From wagi@monom.org Wed Jun 1 00:52:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F0C947CA2 for ; Wed, 1 Jun 2016 00:52:47 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5C6CDAC001 for ; Tue, 31 May 2016 22:52:43 -0700 (PDT) X-ASG-Debug-ID: 1464760357-04cb6c2dbcaba2f0001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id frcIhCz0Wp9y8MDZ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 31 May 2016 22:52:38 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id 984921940648; Wed, 1 Jun 2016 07:52:35 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 5F6B3194043D; Wed, 1 Jun 2016 07:52:35 +0200 (CEST) To: Dave Chinner Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com From: Daniel Wagner Subject: Internal error xfs_trans_cancel Message-ID: X-ASG-Orig-Subj: Internal error xfs_trans_cancel Date: Wed, 1 Jun 2016 07:52:31 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1464760357 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1797 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30074 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Hi, I got the error message below while compiling a kernel on that system. I can't really say if I did something which made the file system unhappy before the crash. [Jun 1 07:41] XFS (sde1): Internal error xfs_trans_cancel at line 984 of file fs/xfs/xfs_trans.c. Caller xfs_rename+0x453/0x960 [xfs] [ +0.000095] CPU: 22 PID: 8640 Comm: gcc Not tainted 4.7.0-rc1 #16 [ +0.000035] Hardware name: Dell Inc. PowerEdge R820/066N7P, BIOS 2.0.20 01/16/2014 [ +0.000048] 0000000000000286 00000000c8be6bc3 ffff885fa9473cb0 ffffffff813d146e [ +0.000056] ffff885fa9ac5ed0 0000000000000001 ffff885fa9473cc8 ffffffffa0213cdc [ +0.000053] ffffffffa02257b3 ffff885fa9473cf0 ffffffffa022eb36 ffff883faa502d00 [ +0.000053] Call Trace: [ +0.000028] [] dump_stack+0x63/0x85 [ +0.000069] [] xfs_error_report+0x3c/0x40 [xfs] [ +0.000065] [] ? xfs_rename+0x453/0x960 [xfs] [ +0.000064] [] xfs_trans_cancel+0xb6/0xe0 [xfs] [ +0.000065] [] xfs_rename+0x453/0x960 [xfs] [ +0.000062] [] xfs_vn_rename+0xb3/0xf0 [xfs] [ +0.000040] [] vfs_rename+0x58c/0x8d0 [ +0.000032] [] SyS_rename+0x371/0x390 [ +0.000036] [] entry_SYSCALL_64_fastpath+0x1a/0xa4 [ +0.000040] XFS (sde1): xfs_do_force_shutdown(0x8) called from line 985 of file fs/xfs/xfs_trans.c. Return address = 0xffffffffa022eb4f [ +0.027680] XFS (sde1): Corruption of in-memory data detected. Shutting down filesystem [ +0.000057] XFS (sde1): Please umount the filesystem and rectify the problem(s) [Jun 1 07:42] XFS (sde1): xfs_log_force: error -5 returned. [ +30.081016] XFS (sde1): xfs_log_force: error -5 returned. cheers, daniel From david@fromorbit.com Wed Jun 1 01:36:00 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BED0E7CA2 for ; Wed, 1 Jun 2016 01:36:00 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7FBA38F8040 for ; Tue, 31 May 2016 23:36:00 -0700 (PDT) X-ASG-Debug-ID: 1464762956-04bdf05ad6ad52b0001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id PYtTr9Z28mPG9Zyp for ; Tue, 31 May 2016 23:35:56 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DWBwDxgE5XLUokLHlbgz2BU4J2g3mebQEBAQEBAQaMJYoPhgsCAgEBAoElTQEBAQEBAQcBAQEBAUFAhEYBAQQ6HCMQCAMOCgklDwUlAwcaE4guwDoBCwEkHoVBhBKBA4oaBYgEhWGKUo4WjyaPTIJoHIFdKjKKNwEBAQ Received: from ppp121-44-36-74.lns20.syd4.internode.on.net (HELO dastard) ([121.44.36.74]) by ipmail07.adl2.internode.on.net with ESMTP; 01 Jun 2016 16:05:54 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b7zkv-0006dl-6o; Wed, 01 Jun 2016 16:35:53 +1000 Date: Wed, 1 Jun 2016 16:35:53 +1000 From: Dave Chinner To: Christoph Hellwig Cc: xfs@oss.sgi.com, rpeterso@redhat.com, vishal.l.verma@intel.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V4 Message-ID: <20160601063553.GI12670@dastard> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V4 References: <1462783638-4968-1-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1462783638-4968-1-git-send-email-hch@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1464762956 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4279 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30074 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Mon, May 09, 2016 at 10:47:03AM +0200, Christoph Hellwig wrote: > This series add a new file system I/O path that uses the iomap structure > introduced for the pNFS support and support multi-page buffered writes. > > This was first started by Dave Chinner a long time ago, then I did beat > it into shape for production runs in a very constrained ARM NAS > enviroment for Tuxera almost as long ago, and now half a dozen rewrites > later it's back. > > The basic idea is to avoid the per-block get_blocks overhead > and make use of extents in the buffered write path by iterating over > them instead. > > Note that patch 1 conflicts with Vishals dax error handling series. > It would be great to have a stable branch with it so that both the > XFS and nvdimm tree could pull it in before the other changes in this > area. I just pulled this forward to 4.7-rc1, and I get an immediate failure in generic/346: [ 70.701300] ------------[ cut here ]------------ [ 70.702029] kernel BUG at fs/xfs/xfs_aops.c:1253! [ 70.702778] invalid opcode: 0000 [#1] PREEMPT SMP [ 70.703484] Modules linked in: [ 70.703952] CPU: 2 PID: 5374 Comm: holetest Not tainted 4.7.0-rc1-dgc+ #812 [ 70.704991] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Debian-1.8.2-1 04/01/2014 [ 70.706285] task: ffff8801365e23c0 ti: ffff8800b0698000 task.ti: ffff8800b0698000 [ 70.707395] RIP: 0010:[] [] __xfs_get_blocks+0x597/0x6b0 [ 70.708768] RSP: 0000:ffff8800b069b990 EFLAGS: 00010246 [ 70.709518] RAX: ffff88013ac283c0 RBX: 000000000005c000 RCX: 000000000000000c [ 70.710527] RDX: 000000000005d000 RSI: 0000000000000008 RDI: ffff8800b3fc1b90 [ 70.711579] RBP: ffff8800b069ba18 R08: 000000000000006b R09: ffff8800b069b914 [ 70.712626] R10: 0000000000000000 R11: 000000000000006b R12: ffff8800b3fc1ce0 [ 70.713656] R13: 0000000000001000 R14: ffff8800b069bb38 R15: ffff8800b9442000 [ 70.714653] FS: 00007ff002a27700(0000) GS:ffff88013fd00000(0000) knlGS:0000000000000000 [ 70.715820] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 70.716669] CR2: 00007ff00436ec00 CR3: 00000000ae8c1000 CR4: 00000000000006e0 [ 70.717656] Stack: [ 70.717940] ffff8800b3fc1b40 ffff8800b3fc1b60 ffff880000000000 000000000000005c [ 70.719062] ffff880100000000 ffff8800b3fc1b00 0000000000000000 00000001b069b9d8 [ 70.720199] 0000000000000000 ffffffffffffffff 000000000000005d 0000000000000000 [ 70.721294] Call Trace: [ 70.721644] [] xfs_get_blocks+0x17/0x20 [ 70.722401] [] do_mpage_readpage+0x3d4/0x710 [ 70.723250] [] ? lru_cache_add+0xe/0x10 [ 70.724013] [] mpage_readpages+0xf8/0x150 [ 70.724828] [] ? __xfs_get_blocks+0x6b0/0x6b0 [ 70.725654] [] ? __xfs_get_blocks+0x6b0/0x6b0 [ 70.726504] [] ? alloc_pages_current+0x8c/0x110 [ 70.727365] [] xfs_vm_readpages+0x38/0xa0 [ 70.728177] [] __do_page_cache_readahead+0x192/0x230 [ 70.729107] [] filemap_fault+0x440/0x4b0 [ 70.729881] [] ? down_read+0x20/0x40 [ 70.730616] [] xfs_filemap_fault+0x5f/0x110 [ 70.731456] [] __do_fault+0x67/0xf0 [ 70.732205] [] handle_mm_fault+0x239/0x1460 [ 70.733015] [] __do_page_fault+0x1c3/0x4f0 [ 70.733821] [] trace_do_page_fault+0x43/0x140 [ 70.734654] [] do_async_page_fault+0x1a/0xa0 [ 70.735493] [] async_page_fault+0x28/0x30 [ 70.736500] Code: 41 ff d2 4d 8b 16 4d 85 d2 75 dd 4c 8b 65 98 4c 8b 75 80 65 ff 0d 82 69 b1 7e 74 11 e9 e6 fb ff ff e8 76 c4 b0 ff e9 e9 fd ff ff <0f> 0b e8 6a c4 [ 70.740283] RIP [] __xfs_get_blocks+0x597/0x6b0 [ 70.741157] RSP [ 70.742097] ---[ end trace aeed47f2452ca28a ]--- Maybe I screwed up the forward merge sorting out all the bits that conflicted with what went into 4.7-rc1. Perhaps it would be best if you rebased and reposted, Christoph? Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Wed Jun 1 02:10:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8D1C47CA2 for ; Wed, 1 Jun 2016 02:10:57 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0402DAC001 for ; Wed, 1 Jun 2016 00:10:53 -0700 (PDT) X-ASG-Debug-ID: 1464765049-04cbb03569ad6a70001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id WFrR1wCa0ggWlDUw for ; Wed, 01 Jun 2016 00:10:50 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DZBwAuiU5XLUokLHlBFAaDPVZ9gnaiZgEBAQEBAQaMJYNZhjYkhWcCAgEBAoElTQEBAQEBAQcBAQEBAUFAhEYBAQQ6HCMQCAMOCgklDwUlAwcaE4guDy3ACQEBAQcCASQehUGFFYQyhWgFjWWKUoYAiBaBc4RPiGRFjweCaByBXSoyAYo2AQEB Received: from ppp121-44-36-74.lns20.syd4.internode.on.net (HELO dastard) ([121.44.36.74]) by ipmail07.adl2.internode.on.net with ESMTP; 01 Jun 2016 16:40:48 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b80Ii-0006jD-0l; Wed, 01 Jun 2016 17:10:48 +1000 Date: Wed, 1 Jun 2016 17:10:47 +1000 From: Dave Chinner To: Daniel Wagner Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com Subject: Re: Internal error xfs_trans_cancel Message-ID: <20160601071047.GJ12670@dastard> X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1464765049 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2389 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-BRTS-Evidence: xfs.org X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA085 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30074 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 BSF_SC0_SA085 Custom Rule SA085 On Wed, Jun 01, 2016 at 07:52:31AM +0200, Daniel Wagner wrote: > Hi, > > I got the error message below while compiling a kernel > on that system. I can't really say if I did something > which made the file system unhappy before the crash. > > > [Jun 1 07:41] XFS (sde1): Internal error xfs_trans_cancel at line 984 of file fs/xfs/xfs_trans.c. Caller xfs_rename+0x453/0x960 [xfs] Anything in the log before this? > [ +0.000095] CPU: 22 PID: 8640 Comm: gcc Not tainted 4.7.0-rc1 #16 > [ +0.000035] Hardware name: Dell Inc. PowerEdge R820/066N7P, BIOS 2.0.20 01/16/2014 > [ +0.000048] 0000000000000286 00000000c8be6bc3 ffff885fa9473cb0 ffffffff813d146e > [ +0.000056] ffff885fa9ac5ed0 0000000000000001 ffff885fa9473cc8 ffffffffa0213cdc > [ +0.000053] ffffffffa02257b3 ffff885fa9473cf0 ffffffffa022eb36 ffff883faa502d00 > [ +0.000053] Call Trace: > [ +0.000028] [] dump_stack+0x63/0x85 > [ +0.000069] [] xfs_error_report+0x3c/0x40 [xfs] > [ +0.000065] [] ? xfs_rename+0x453/0x960 [xfs] > [ +0.000064] [] xfs_trans_cancel+0xb6/0xe0 [xfs] > [ +0.000065] [] xfs_rename+0x453/0x960 [xfs] > [ +0.000062] [] xfs_vn_rename+0xb3/0xf0 [xfs] > [ +0.000040] [] vfs_rename+0x58c/0x8d0 > [ +0.000032] [] SyS_rename+0x371/0x390 > [ +0.000036] [] entry_SYSCALL_64_fastpath+0x1a/0xa4 > [ +0.000040] XFS (sde1): xfs_do_force_shutdown(0x8) called from line 985 of file fs/xfs/xfs_trans.c. Return address = 0xffffffffa022eb4f > [ +0.027680] XFS (sde1): Corruption of in-memory data detected. Shutting down filesystem > [ +0.000057] XFS (sde1): Please umount the filesystem and rectify the problem(s) > [Jun 1 07:42] XFS (sde1): xfs_log_force: error -5 returned. > [ +30.081016] XFS (sde1): xfs_log_force: error -5 returned. Doesn't normally happen, and there's not a lot to go on here. Can you provide the info listed in the link below so we have some idea of what configuration the error occurred on? http://xfs.org/index.php/XFS_FAQ#Q:_What_information_should_I_include_when_reporting_a_problem.3F You didn't run out of space or something unusual like that? Does 'xfs_repair -n ' report any errors? Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Wed Jun 1 03:35:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 1E8147CA2 for ; Wed, 1 Jun 2016 03:35:10 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id CECBF8F8039 for ; Wed, 1 Jun 2016 01:35:06 -0700 (PDT) X-ASG-Debug-ID: 1464770097-04cbb03568ad8d40001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id HCMOTXfqmxIp7H9a for ; Wed, 01 Jun 2016 01:34:58 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CdBwBanU5XLUokLHlbgz0iNH2CdoN5nlUCFgEBAQEBAQaBD4sWhXiEFxcDhXEEgS1NAQEBAQEBBwEBAQEBQUCFIjskNAUlAwctiC6fFKFgDh6FQYohgX0LQIJGBYgEizOFAIYAiBaBc40xAoYziRmCGAsBAQGCOyoyijcBAQE Received: from ppp121-44-36-74.lns20.syd4.internode.on.net (HELO dastard) ([121.44.36.74]) by ipmail07.adl2.internode.on.net with ESMTP; 01 Jun 2016 18:04:58 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b81c7-0006u3-SC for xfs@oss.sgi.com; Wed, 01 Jun 2016 18:34:55 +1000 Date: Wed, 1 Jun 2016 18:34:55 +1000 From: Dave Chinner To: xfs@oss.sgi.com Subject: [ANNOUNCE] xfs: for-next branch update to 26f1fe8 Message-ID: <20160601083455.GK12670@dastard> X-ASG-Orig-Subj: [ANNOUNCE] xfs: for-next branch update to 26f1fe8 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="gj572EiMnwbLXET9" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1464770097 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1630 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.20 X-Barracuda-Spam-Status: No, SCORE=0.20 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=PR0N_SUBJECT X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30076 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.20 PR0N_SUBJECT Subject has letters around special characters (pr0n) --gj572EiMnwbLXET9 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi folks, The for-next branch of the xfs kernel repository at git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git has just been updated. The new head of the for-next branch is commit: 26f1fe8 xfs: reduce lock hold times in buffer writeback New Commits: Brian Foster (2): [a3916e5] xfs: fix broken multi-fsb buffer logging [0c871f9] xfs: remove spurious shutdown type check from xfs_bmap_fini= sh() Christoph Hellwig (1): [4478fb1] xfs: define XFS_IOC_FREEZE even if FIFREEZE is defined Dave Chinner (1): [26f1fe8] xfs: reduce lock hold times in buffer writeback Eric Sandeen (1): [0d5a75e] xfs: make several functions static Code Diffstat: fs/xfs/libxfs/xfs_alloc.c | 2 +- fs/xfs/libxfs/xfs_alloc.h | 7 ------ fs/xfs/libxfs/xfs_attr_leaf.h | 3 --- fs/xfs/libxfs/xfs_fs.h | 8 ++----- fs/xfs/libxfs/xfs_rtbitmap.c | 2 +- fs/xfs/xfs_attr_inactive.c | 2 +- fs/xfs/xfs_attr_list.c | 2 +- fs/xfs/xfs_bmap_util.c | 6 ++--- fs/xfs/xfs_bmap_util.h | 2 -- fs/xfs/xfs_buf.c | 60 +++++++++++++++++++++++++++------------= ------- fs/xfs/xfs_buf_item.c | 18 ++++++++++---- fs/xfs/xfs_inode.c | 16 ++++--------- fs/xfs/xfs_inode.h | 7 ------ fs/xfs/xfs_log.c | 8 +++---- fs/xfs/xfs_log.h | 5 ---- fs/xfs/xfs_rtalloc.h | 2 -- fs/xfs/xfs_super.c | 2 +- fs/xfs/xfs_super.h | 2 -- 18 files changed, 65 insertions(+), 89 deletions(-) --=20 Dave Chinner david@fromorbit.com --gj572EiMnwbLXET9 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJXTp4vAAoJEK3oKUf0dfodEbQQAIwGYmYIbSDfg3S4xU9PGMGE Nq5+YCK+0S7krpw75vfuBGZuJs1K0+A4vs7HtIiZWW8gQcb02NXMQI1H3NMlOs/u dJOGfs/StUAbYZLi2b99h88DdT9ce2h9hFSaKBsftHcxd5eWJXN6k52G9C6QOB1e y+9b7ffFK3ztb5sRnDXUTDc7zwjof9QF8hz/zA7E3wzQ1+3SoB0RIeuALzUeoZIG 68EYDOKHUKdz3VN776JF0xVCACCQ25FU+DGRLZ2XUuHdunlb72eVI1WZjmuk4RTG zY0aHOHVASigip7IkHC87fgIVIu/3fyE0eYMTEJ1jTFBcq15lYXUqe7tcYfHdEXR lB8Jy8Nri0Pz7ISHPMtwXibz6gNl3nUqv9hv+ufiYsOFK39yGz4+JVaFSVZTJXsf SoFusB/R1X3b/fl7lFsnPzUcb0G30zem8F1P6Kv1AXKh8LaipawLBgMCaTHTTqAz ldzxANP6qr8YioqqV85vzfVa17AeHPTxcucBOkk3V7JrVcC5CFrTx8yE3RE1lkNx qvEpTEtl1mr1zEIdQDdOPGgl2f4UsrgJxWMEV0eIbV7rsDsshqQZKUz7PsKvRqTZ aKCH1CZ3zBn06lEl9Vip5r/xabo0y9ZKcskdECYTcPs2JOO3Ilc30W8ED+oy0ut6 fxv4fp86dn4ATyAd8fFd =oh5k -----END PGP SIGNATURE----- --gj572EiMnwbLXET9-- From hch@lst.de Wed Jun 1 07:31:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6C08B7CA6 for ; Wed, 1 Jun 2016 07:31:28 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3DFAF304059 for ; Wed, 1 Jun 2016 05:31:25 -0700 (PDT) X-ASG-Debug-ID: 1464784282-04cbb03569adf810001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id 5DM4eIzlRAuZuiKA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 05:31:23 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 76EB368BC3; Wed, 1 Jun 2016 14:31:21 +0200 (CEST) Date: Wed, 1 Jun 2016 14:31:21 +0200 From: Christoph Hellwig To: Dave Chinner Cc: Christoph Hellwig , xfs@oss.sgi.com, rpeterso@redhat.com, vishal.l.verma@intel.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V4 Message-ID: <20160601123121.GA23101@lst.de> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V4 References: <1462783638-4968-1-git-send-email-hch@lst.de> <20160601063553.GI12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160601063553.GI12670@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1464784282 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 568 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30080 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 01, 2016 at 04:35:53PM +1000, Dave Chinner wrote: > I just pulled this forward to 4.7-rc1, and I get an immediate > failure in generic/346: > Maybe I screwed up the forward merge sorting out all the bits that > conflicted with what went into 4.7-rc1. Perhaps it would be best if > you rebased and reposted, Christoph? No, I screwed up and enabled that BUG_ON for the buffered read case accidentally - it was only supposed to be there for direct I/O. I've rebase three and fixed it up. I'll resend it as soon as the xfstests run completes. From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 07:33:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A6D777CA6 for ; Wed, 1 Jun 2016 07:33:18 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 597558F8040 for ; Wed, 1 Jun 2016 05:33:15 -0700 (PDT) X-ASG-Debug-ID: 1464784393-04bdf05ad5adfb40001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id OS0cqhubKAIJY1FC (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 05:33:13 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1b85Kj-0000Sf-L7; Wed, 01 Jun 2016 12:33:13 +0000 Date: Wed, 1 Jun 2016 05:33:13 -0700 From: Christoph Hellwig To: Dave Chinner Cc: xfs@oss.sgi.com Subject: Re: [ANNOUNCE] xfs: for-next branch update to 26f1fe8 Message-ID: <20160601123313.GA32705@infradead.org> X-ASG-Orig-Subj: Re: [ANNOUNCE] xfs: for-next branch update to 26f1fe8 References: <20160601083455.GK12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160601083455.GK12670@dastard> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464784393 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 178 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.30 X-Barracuda-Spam-Status: No, SCORE=0.30 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, PR0N_SUBJECT, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30080 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.20 PR0N_SUBJECT Subject has letters around special characters (pr0n) 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 01, 2016 at 06:34:55PM +1000, Dave Chinner wrote: > [a3916e5] xfs: fix broken multi-fsb buffer logging Isn't this something we should try to get into 4.7? From cmaiolino@redhat.com Wed Jun 1 07:36:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 368487CA6 for ; Wed, 1 Jun 2016 07:36:56 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id DE411304059 for ; Wed, 1 Jun 2016 05:36:55 -0700 (PDT) X-ASG-Debug-ID: 1464784614-04bdf05ad5ae01f0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id Qke0lanyciLDnkGk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 05:36:54 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 721C23B71B for ; Wed, 1 Jun 2016 12:36:54 +0000 (UTC) Received: from redhat.com (vpn-61-114.rdu2.redhat.com [10.10.61.114]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u51CaoQK011039 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 1 Jun 2016 08:36:53 -0400 Date: Wed, 1 Jun 2016 14:36:50 +0200 From: Carlos Maiolino To: xfs@oss.sgi.com Subject: XFS_IOC_FSEMAP (old XFS_IOC_FIEMAPFS) Message-ID: <20160601123650.GC7967@redhat.com> X-ASG-Orig-Subj: XFS_IOC_FSEMAP (old XFS_IOC_FIEMAPFS) Mail-Followup-To: xfs@oss.sgi.com MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 01 Jun 2016 12:36:54 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1464784614 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 598 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Howdy folks, I've talked to Dave about moving forward XFS_IOC_FIEMAPFS ioctl, and consequently their users, such as xfs_spaceman tool. For now, I'm porting the old stuff to the current code, doing code cleanups, etc. If someone wants to take a look, I've made the patches available here: https://github.com/cmaiolino/linux/tree/fsemap For now, I just did the port forward of the patches, but still need to clean up a few stuff, and also port forward xfs_spaceman. As per Dave suggestion (as you can see in $SUBJ), the ioctl has been renamed to XFS_IOC_FSEMAP. -- Carlos From ming.lei@canonical.com Wed Jun 1 07:38:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 7C4317CA6 for ; Wed, 1 Jun 2016 07:38:50 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id EB23BAC004 for ; Wed, 1 Jun 2016 05:38:46 -0700 (PDT) X-ASG-Debug-ID: 1464784723-04cbb03569adfae0001-NocioJ Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by cuda.sgi.com with ESMTP id wL6rmvARqbuY8eYZ (version=TLSv1 cipher=AES256-SHA bits=256 verify=NO) for ; Wed, 01 Jun 2016 05:38:44 -0700 (PDT) X-Barracuda-Envelope-From: ming.lei@canonical.com X-Barracuda-Effective-Source-IP: youngberry.canonical.com[91.189.89.112] X-Barracuda-Apparent-Source-IP: 91.189.89.112 Received: from mail-yw0-f180.google.com ([209.85.161.180]) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1b85Q2-0003hH-KG for xfs@oss.sgi.com; Wed, 01 Jun 2016 12:38:42 +0000 Received: by mail-yw0-f180.google.com with SMTP id h19so16728260ywc.0 for ; Wed, 01 Jun 2016 05:38:42 -0700 (PDT) X-Gm-Message-State: ALyK8tKQV1OGyfj/ehJnzHYa7rFnyJu8flnOhgh2rsxnd+EmC2jAwhd7qMUV0wJRSDZx6wftf6R2JqT0DDepUg== MIME-Version: 1.0 X-Received: by 10.37.217.143 with SMTP id q137mr57044ybg.12.1464784721693; Wed, 01 Jun 2016 05:38:41 -0700 (PDT) Received: by 10.37.216.78 with HTTP; Wed, 1 Jun 2016 05:38:41 -0700 (PDT) In-Reply-To: <20160531155348.GA24840@redhat.com> References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <20160531155348.GA24840@redhat.com> Date: Wed, 1 Jun 2016 20:38:41 +0800 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs From: Ming Lei X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs To: Mike Snitzer Cc: Jens Axboe , Linux Kernel Mailing List , linux-block@vger.kernel.org, Christoph Hellwig , Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: youngberry.canonical.com[91.189.89.112] X-Barracuda-Start-Time: 1464784723 X-Barracuda-Encrypted: AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1960 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30080 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, May 31, 2016 at 11:53 PM, Mike Snitzer wrote: > On Mon, May 30 2016 at 9:34am -0400, > Ming Lei wrote: > >> >> Hi, >> >> Interests[1] have been shown in multipage bvecs, so this patchset >> try to prepare for the support and do two things: >> >> 1) the 1st 4 patches use bvec iterator to implement iterate_bvec(), >> then we can drop the non-standard way for iterating bvec, which >> can be thought as a good cleanup for lib/iov_iter.c >> >> 2) remove BIO_MAX_SECTORS and makre BIO_MAX_SIZE as obsolete, and >> now there is only one user for each. Once multipage bvecs is introduced, >> one bio may hold lots of sectors, and we should always use sort of >> BIO_MAX_VECS which should be introduced in future and is similiar >> with current BIO_MAX_PAGES. >> >> The only functional change is iterate_bvec():lib/iov_iter.c >> >> xfstests(-a auto) over loop aio is run for ext4/xfs to verify >> the change and no regression found with this patchset. >> >> V6: >> - rebased on v4.7-rc1 >> - add reviewed-by tag >> - mark BIO_MAX_SIZE as obsolete instead of removing because >> dm-tree adds one usage now > > Not sure what you're referring to here with "dm-tree" (since "dm-tree" > doesn't exist). But only direct user of "BIO_MAX_SIZE" in DM appears to Looks it is from crypto tree: git://git.kernel.org/pub/scm/linux/kernel/git/herbert/crypto-2.6 > be dm-crypt.c. Maybe you've identified some indirect use of > BIO_MAX_SIZE? I mean the recently introduced BIO_MAX_SIZE in -next tree: https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/md/dm-crypt.c?id=4ed89c97b0706477b822ea2182827640c0cec486 > -- > To unsubscribe from this list: send the line "unsubscribe linux-block" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html From damien.gombault@recia.fr Wed Jun 1 07:57:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A465B7CA6 for ; Wed, 1 Jun 2016 07:57:16 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6947E8F8035 for ; Wed, 1 Jun 2016 05:57:16 -0700 (PDT) X-ASG-Debug-ID: 1464785830-04cb6c2dbaac94c0001-NocioJ Received: from mx.recia.fr (mx.recia.fr [95.128.41.47]) by cuda.sgi.com with ESMTP id Gy3NPQj5zZ9hsjdH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 05:57:11 -0700 (PDT) X-Barracuda-Envelope-From: damien.gombault@recia.fr X-Barracuda-Effective-Source-IP: mx.recia.fr[95.128.41.47] X-Barracuda-Apparent-Source-IP: 95.128.41.47 Received: from e6530-damien.recia.fr (unknown [37.58.188.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: F12A086p) by mx.recia.fr (Postfix) with ESMTPSA id B5AE122602E for ; Wed, 1 Jun 2016 14:57:09 +0200 (CEST) Subject: Re: Re: Cumulative xfsrestore shows many warnings and files/directories are missing after restoration To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: Re: Cumulative xfsrestore shows many warnings and files/directories are missing after restoration References: <8323ac3a-f9d2-ad31-69e3-1eea5a44dcde@recia.fr> <87a11f69-1a10-89e2-598f-015f0205a55a@sandeen.net> From: Damien Gombault Organization: GIP Recia Message-ID: Date: Wed, 1 Jun 2016 14:57:09 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <87a11f69-1a10-89e2-598f-015f0205a55a@sandeen.net> Content-Type: multipart/mixed; boundary="------------8EA2A3A708D8CFD2D40D45BC" X-Barracuda-Connect: mx.recia.fr[95.128.41.47] X-Barracuda-Start-Time: 1464785831 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3399 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30081 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- This is a multi-part message in MIME format. --------------8EA2A3A708D8CFD2D40D45BC Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Hi. Thank you for your answer. I also open a report on Red Hat Bugzilla : https://bugzilla.redhat.com/show_bug.cgi?id=1341126 Eric answered me also on Bugzilla, I will continue on it. Le 31/05/2016 à 15:57, Eric Sandeen a écrit : > On 5/31/16 5:55 AM, Damien Gombault wrote: >> Hi. >> >> I use xfsdump to backup my systems. >> Recently I had to use xfsrestore to restore a cumulative level 0 + level 1 dumps. >> > ... > >> The level 1 restore shows many warnings : >> xfsrestore: drive 0: examining media file 0 >> xfsrestore: drive 1: searching media for directory dump >> xfsrestore: drive 1: reading directories >> xfsrestore: drive 1: 11013 directories and 96122 entries processed >> xfsrestore: drive 1: directory post-processing >> xfsrestore: drive 1: WARNING: unable to rename dir orphanage/1677721775.4173752252 to dir var/www/html/owncloud/data/F1000buv/files/Dossier personnel et source de partage/E-Administration/08 Sécurité/08c Gestion des mots de passe - Keepass: Aucun fichier ou dossier de ce type >> xfsrestore: drive 1: WARNING: unable to rename dir orphanage/1711276202.4274102453 to dir var/www/html/owncloud/data/F1000buv/files_versions/Dossier personnel et source de partage/E-Administration/02 Mise en oeuvre sOlære: Aucun fichier ou dossier de ce type >> xfsrestore: drive 1: WARNING: unable to rename dir orphanage/1694499004.2655526171 to dir var/www/html/owncloud/data/F1000buv/files_versions/Dossier personnel et source de partage/E-Administration/07 Communication: Aucun fichier ou dossier de ce type >> xfsrestore: drive 1: WARNING: unable to rename dir orphanage/2365644069.2895542759 to dir var/www/html/owncloud/data/F1000buv/files_versions/Dossier personnel et source de partage/E-Administration/08 Sécurité/08c Gestion des mots de passe - Keepass: Aucun fichier ou dossier de ce type >> xfsrestore: drive 1: WARNING: unable to rename nondir orphanage/2902474338.2817943331 to var/www/html/owncloud/data/F1000buv/files/Dossier personnel et source de partage/E-Administration/09 Questionnaires communes solære/Dossiers des collectivités/37003 - Amboise/02-Compte rendu de réunions/Compte rendu réunion 3 mai 2016.odt: Aucun fichier ou dossier de ce type > Restating what I said in the bug you also filed: > > In general, it would helpful to provide the error messages after setting LANG=en_US - because your English is far better than my French. :) > > A couple questions: > >> Some folders are not restored at the right place. > What does that mean? Were they restored to the wrong place, or were they not restored at all? > > Also, the "Aucun fichier ou dossier de ce type" errors indicate that files could not be moved into a directory hierarchy, presumably because some path component did not exist. > > The common portions of those paths which failed are: > >> var/www/html/owncloud/data/F1000buv/files/Dossier personnel et source de partage/E-Administration/ > and > >> var/www/html/owncloud/data/F1000buv/files_versions/Dossier personnel et source de partage/E-Administration > Do those paths still exist on the original filesystem? Is it possible that they were removed while the dump was occurring? > > It seems most likely that the filesystem changed significantly during the dump processes, and this is what led to the errors. > > -Eric > --------------8EA2A3A708D8CFD2D40D45BC Content-Type: text/x-vcard; charset=utf-8; name="damien_gombault.vcf" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="damien_gombault.vcf" begin:vcard fn:Damien Gombault n:Gombault;Damien org;quoted-printable:GIP Recia =E2=88=92 Centre de ressources r=C3=A9gional du num=C3=A9rique adr;quoted-printable;dom:Parc d'Activit=C3=A9s les Aulnaies;;151, Rue de la Juine;Olivet;;45160 email;internet:damien.gombault@recia.fr title;quoted-printable:Responsable des syst=C3=A8mes informatiques tel;work:02 38 42 14 71 tel;cell:06 42 62 78 19 url:http://recia.fr version:2.1 end:vcard --------------8EA2A3A708D8CFD2D40D45BC-- From mstsxfx@gmail.com Wed Jun 1 08:18:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E423F7CA6 for ; Wed, 1 Jun 2016 08:18:06 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id B7AC78F8049 for ; Wed, 1 Jun 2016 06:18:06 -0700 (PDT) X-ASG-Debug-ID: 1464787080-04cb6c2dbaaca6a0001-NocioJ Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by cuda.sgi.com with ESMTP id LrEcJqhzN08rb2gW (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 06:18:01 -0700 (PDT) X-Barracuda-Envelope-From: mstsxfx@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Apparent-Source-IP: 74.125.82.67 Received: by mail-wm0-f67.google.com with SMTP id q62so6718438wmg.3 for ; Wed, 01 Jun 2016 06:18:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=YhMhPUl1fYQMCSC3HjdfsKoT7EsBV29ZIcZOsoHZwJU=; b=M2FeGTwGD8R2iG7ASdzVivohiABQr81zD88hjX67V61cPc4kAwGHDal6uWSxToq+ws t4fmJW7o0F+4loi0N3oZFEWXpbuOfDXbq2HgcxnoGBAwfTrFgKodDQMYZfdcJ6hTYAfT pSAcs13N3atP7sgdPFjzLr62U9/uYLTJJiAsa7RVCu+NyQzmTWKWCTvEBX/dx/eFY/BS yz8Q2NY8WhNUSc0p92IYWY3JmMHSxCkyd7wtdRVV40ccQUCcDB+3pUTOb/d9/yevyblP CEefbF5/xRCvChZqrcLOA4gzKkcUr7iCVv1IH1SN7nrcaWVFy55/CJRSgjXNBdhCzGfS UaTg== X-Gm-Message-State: ALyK8tIdugPIBVVHddtnBdbA1+D0n2+AcNh8vSmD6oEn3kJ5vUeTWNx/WObhgqlXCMKGww== X-Received: by 10.194.102.202 with SMTP id fq10mr3509775wjb.153.1464787080234; Wed, 01 Jun 2016 06:18:00 -0700 (PDT) Received: from localhost (nat1.scz.suse.com. [213.151.88.250]) by smtp.gmail.com with ESMTPSA id h2sm22875495wjv.15.2016.06.01.06.17.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 01 Jun 2016 06:17:59 -0700 (PDT) Date: Wed, 1 Jun 2016 15:17:58 +0200 From: Michal Hocko To: Peter Zijlstra , Dave Chinner Cc: "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160601131758.GO26601@dhcp22.suse.cz> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160512080321.GA18496@dastard> <20160513160341.GW20141@dhcp22.suse.cz> <20160516104130.GK3193@twins.programming.kicks-ass.net> <20160516130519.GJ23146@dhcp22.suse.cz> <20160516132541.GP3193@twins.programming.kicks-ass.net> <20160516231056.GE18496@dastard> <20160517144912.GZ3193@twins.programming.kicks-ass.net> <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160520001714.GC26977@dastard> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Start-Time: 1464787081 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4042 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30081 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Thanks Dave for your detailed explanation again! Peter do you have any other idea how to deal with these situations other than opt out from lockdep reclaim machinery? If not I would rather go with an annotation than a gfp flag to be honest but if you absolutely hate that approach then I will try to check wheter a CONFIG_LOCKDEP GFP_FOO doesn't break something else. Otherwise I would steal the description from Dave's email and repost my patch. I plan to repost my scope gfp patches in few days and it would be good to have some mechanism to drop those GFP_NOFS to paper over lockdep false positives for that. [keeping Dave's explanation for reference] On Fri 20-05-16 10:17:14, Dave Chinner wrote: > On Thu, May 19, 2016 at 10:11:46AM +0200, Peter Zijlstra wrote: > > On Wed, May 18, 2016 at 08:35:49AM +1000, Dave Chinner wrote: [...] > > > There's a maze of dark, grue-filled twisty passages here... > > > > OK; I might need a bit more again. > > > > So now the code does something like: > > > > down_read(&i_lock); -- lockdep marks lock as held > > kmalloc(GFP_KERNEL); -- lockdep marks held locks as ENABLED_RECLAIM_FS > > --> reclaim() > > down_read_trylock(&i_lock); -- lockdep does _NOT_ mark as USED_IN_RECLAIM_FS > > > > Right? > > In the path that can deadlock the log, yes. It's actually way more > complex than the above, because the down_read_trylock(&i_lock) that > matters is run in a completely separate, async kthread that > xfs_trans_reserve() will block waiting for. > > process context xfsaild kthread(*) > --------------- ------------------ > down_read(&i_lock); -- lockdep marks lock as held > kmalloc(GFP_KERNEL); -- lockdep marks held locks as ENABLED_RECLAIM_FS > --> reclaim() > xfs_trans_reserve() > .... > xfs_trans_push_ail() ---- called if no space in the log to kick the xfsaild into action > .... > xlog_grant_head_wait() ---- blocks waiting for log space > ..... > > xfsaild_push() ----- iterates AIL > grabs log item > lock log item > >>>>>>>>>>>>>>>>>>>>> down_read_trylock(&i_lock); > format item into buffer > add to dirty buffer list > .... > submit dirty buffer list for IO > buffer IO started > ..... > > buffer callbacks > mark inode clean > remove inode from AIL > move tail of log forwards > wake grant head waiters > > > transaction reservation granted > ..... > down_write(some other inode ilock) > > xfs_trans_commit > ..... > > (*) xfsaild runs with PF_MEMALLOC context. > > The problem is that if the ilock is held exclusively at GFP_KERNEL > time, the xfsaild cannot lock the inode to flush it, so if that > inode pins the tail of the log then we can't make space available > for xfs_trans_reserve and there is the deadlock. > > Once xfs_trans_reserve completes, however, we'll take the ilock on > *some other inode*, and that's where the "it can't be the inode we > currently hold locked because we have references to it" and > henceit's safe to have a pattern like: > > down_read(&i_lock); -- lockdep marks lock as held > kmalloc(GFP_KERNEL); -- lockdep marks held locks as ENABLED_RECLAIM_FS > --> reclaim() > down_write(&ilock) > > because the lock within reclaim context is completely unrelated to > the lock we already hold. > > Lockdep can't possibly know about this because the deadlock involves > locking contexts that *aren't doing anything wrong within their own > contexts*. It's only when you add the dependency of log space > reservation requirements needed to make forwards progress that > there's then an issue with locking and reclaim. > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com -- Michal Hocko SUSE Labs From jtulak@redhat.com Wed Jun 1 08:19:58 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 55FB27CA6 for ; Wed, 1 Jun 2016 08:19:58 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 293A68F8040 for ; Wed, 1 Jun 2016 06:19:57 -0700 (PDT) X-ASG-Debug-ID: 1464787194-04cb6c2dbcaca760001-NocioJ Received: from mail-it0-f54.google.com (mail-it0-f54.google.com [209.85.214.54]) by cuda.sgi.com with ESMTP id kv6Jeb4tUfrZKkEu (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 06:19:54 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mail-it0-f54.google.com[209.85.214.54] X-Barracuda-Apparent-Source-IP: 209.85.214.54 Received: by mail-it0-f54.google.com with SMTP id e62so89603559ita.1 for ; Wed, 01 Jun 2016 06:19:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=qmdbUzjz28hUUEmGFjz24pJttiokGyMHY+opqdWY6v8=; b=UdTbYa4cD285r2IHchVsxEhRMUJt49SeUATwKkM+Xy/aC8UPA+ugn9l/wRFwUBFmCL +bIuwpnQOoKp2h9y4AAP6wR9Yx8/0MZwf2GfKnEA0tV/0fWLgiQyG+vftjEx33dxcDv1 FLMhqgfiOmBQT5LV/ZVCAWl3oxw1NWxAApC7gAxEVPkaNk00sYkhG/7bOq1RjUn1zQtY 3MMV0VQ5IwULzhtlYRzNnH8fEPm/vAd38qCre6vASDConMWjP4pDRES+sv7tPd7lUN6I awMBSIVTR+kEIl7CI0knn6APtxH2GP8ouRTNEj5x79EJ8fvZVsB/4W2ZXzRhShuClQff 5Lug== X-Gm-Message-State: ALyK8tIVS42IKBTZTGPPNmi82kRFRKcpYzFgPV5PEwDyWB0/QsV8rtfbj8CSCd8F7oNnj025H7WovDG8YmqIAjJH X-Received: by 10.36.104.132 with SMTP id v126mr5207472itb.17.1464787194128; Wed, 01 Jun 2016 06:19:54 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.72.70 with HTTP; Wed, 1 Jun 2016 06:19:34 -0700 (PDT) In-Reply-To: <20160510061054.GI26977@dastard> References: <1461231593-31294-1-git-send-email-jtulak@redhat.com> <20160510061054.GI26977@dastard> From: Jan Tulak Date: Wed, 1 Jun 2016 15:19:34 +0200 Message-ID: Subject: Re: [PATCH 00/19 v2] mkfs cleaning To: Dave Chinner X-ASG-Orig-Subj: Re: [PATCH 00/19 v2] mkfs cleaning Cc: xfs-oss , Eric Sandeen Content-Type: multipart/alternative; boundary=001a11449b2860ead7053437581e X-Barracuda-Connect: mail-it0-f54.google.com[209.85.214.54] X-Barracuda-Start-Time: 1464787194 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6689 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30081 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message --001a11449b2860ead7053437581e Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Tue, May 10, 2016 at 8:10 AM, Dave Chinner wrote: > > Looking at xfstests runs, new failures are: > > generic/054 - > generic/055 - both fail with: > > +*** mkfs failed: -l version=3D2,su=3D4096 *** > > and the .full file has this specific error: > > Illegal value 4096 for -l su option. value is too small > > indicating that we should be allowing (2^N * block size) log > stripe units to be set. This will be a limit configuration issue, > most likely needing fixing in mkfs. > =E2=80=8BI'm looking on it, but this issue was introduced by Eric's fix for patch "mkfs: table based parsing for converted parameters": =E2=80=8B> =E2=80=8B The kernel enforces a max of XLOG_MAX_RECORD_BSIZE, =E2=80=8B> =E2=80=8B and it should match the limits in L_SUNIT after all ... And looking on fs/xfs/xfs_super.c, the MIN value is enforced too. So maybe it is the test what needs fixing? Otherwise, I would put something like XFS_MIN_SECTORSIZE there. See http://lxr.free-electrons.com/source/fs/xfs/xfs_super.c#L435 > > xfs/096 6s ... - output mismatch (see > /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad) > --- tests/xfs/096.out 2016-04-05 11:11:36.814382107 +1000 > +++ /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad > 2016-05-10 12:54:25.956199714 +1000 > @@ -2,18 +2,62 @@ > > # su too big but must be a multiple of fs block size too > --- mkfs=3D-l version=3D2,su=3D262656 --- > -log stripe unit (262656) must be a multiple of the block size (4096) > +Illegal value 262656 for -l su option. value is too large > +Usage: mkfs.xfs > +/* blocksize */ [-b log=3Dn|size=3Dnum] > ... > (Run 'diff -u tests/xfs/096.out > /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad' to see the > entire diff) > > This test is explicitly testing an invalid value, checking that it > falls back to a sane default. This patchset has changed the > behaviour, so the xfstest will need some rework to handle both old > and new mkfs behaviour. > > Can you send patches to fix all these up? > =E2=80=8BSure. Jan =E2=80=8B --=20 Jan Tulak jtulak@redhat.com / jan@tulak.me --001a11449b2860ead7053437581e Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
On Tue, Ma= y 10, 2016 at 8:10 AM, Dave Chinner <david@fromorbit.com> wrote:

Looking at xfstests runs, new failures are:

generic/054 -
generic/055 - both fail with:

+*** mkfs failed: -l version=3D2,su=3D4096 ***

and the .full file has this specific error:

Illegal value 4096 for -l su option. value is too small

indicating that we should be allowing (2^N * block size) log
stripe units to be set. This will be a limit configuration issue,
most likely needing fixing in mkfs.

=E2= =80=8BI'm looking on it, but this issue was introduced by Eric's fi= x for patch=C2=A0"mkfs: table based parsing for converted param= eters":

=E2=80=8B> =E2=80=8B
= The kernel enforces a max of XLOG_MAX_RECORD_BSIZE,
= =E2=80=8B> =E2=80=8B
and it should match the limits in L_SUNIT afte= r all ...

And looking on=C2=A0fs/xfs/xfs_super.c, the MIN value is enforced to= o. So maybe it is the test what needs fixing? Otherwise, I would put someth= ing like=C2=A0XFS_MIN_SECTORSIZE there.


=C2=A0

xfs/096 6s ... - output mismatch (see /home/dave/src/xfstests-dev/results//= xfs/xfs/096.out.bad)
=C2=A0 =C2=A0 --- tests/xfs/096.out=C2=A0 =C2=A0 =C2=A0 =C2=A02016-04-05 11= :11:36.814382107 +1000
=C2=A0 =C2=A0 +++ /home/dave/src/xfstests-dev/results//xfs/xfs/096.out.bad= =C2=A0 =C2=A0 =C2=A0 =C2=A0 2016-05-10 12:54:25.956199714 +1000
=C2=A0 =C2=A0 @@ -2,18 +2,62 @@

=C2=A0 =C2=A0 =C2=A0# su too big but must be a multiple of fs block size to= o
=C2=A0 =C2=A0 =C2=A0--- mkfs=3D-l version=3D2,su=3D262656 ---
=C2=A0 =C2=A0 -log stripe unit (262656) must be a multiple of the block siz= e (4096)
=C2=A0 =C2=A0 +Illegal value 262656 for -l su option. value is too large =C2=A0 =C2=A0 +Usage: mkfs.xfs
=C2=A0 =C2=A0 +/* blocksize */=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 [-b= log=3Dn|size=3Dnum]
=C2=A0 =C2=A0 ...
=C2=A0 =C2=A0 (Run 'diff -u tests/xfs/096.out /home/dave/src/xfstests-d= ev/results//xfs/xfs/096.out.bad'=C2=A0 to see the entire diff)

This test is explicitly testing an invalid value, checking that it
falls back to a sane default. This patchset has changed the
behaviour, so the xfstest will need some rework to handle both old
and new mkfs behaviour.

Can you send patches to fix all these up?

=E2=80=8BSure.

<= /div>
Jan
=E2= =80=8B
=C2=A0


--
--001a11449b2860ead7053437581e-- From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 08:43:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 3AE3E7CA6 for ; Wed, 1 Jun 2016 08:43:23 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id DABAC8F8035 for ; Wed, 1 Jun 2016 06:43:22 -0700 (PDT) X-ASG-Debug-ID: 1464788600-04bdf05ad7ae3090001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id WOTjpkSK5uRuvKj6 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 06:43:20 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1b86QG-00047V-41; Wed, 01 Jun 2016 13:43:00 +0000 Date: Wed, 1 Jun 2016 06:43:00 -0700 From: Christoph Hellwig To: Ming Lei Cc: Jens Axboe , linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, Christoph Hellwig , Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , Mike Snitzer , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs Message-ID: <20160601134300.GA15656@infradead.org> X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464788600 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 94 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30081 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS These patches look good on their own. They might be an easier sell just as bio cleanups :) From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 08:44:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A966E7CA6 for ; Wed, 1 Jun 2016 08:44:43 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1720FAC003 for ; Wed, 1 Jun 2016 06:44:39 -0700 (PDT) X-ASG-Debug-ID: 1464788676-04cb6c2dbbacb160001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id N7PB9t1akNiRs0BW (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 06:44:37 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1b86Rf-0004F3-Ib; Wed, 01 Jun 2016 13:44:27 +0000 Date: Wed, 1 Jun 2016 06:44:27 -0700 From: Christoph Hellwig To: Ming Lei Cc: Mike Snitzer , Jens Axboe , Linux Kernel Mailing List , linux-block@vger.kernel.org, Christoph Hellwig , Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs Message-ID: <20160601134427.GA15888@infradead.org> X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <20160531155348.GA24840@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464788677 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 712 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30081 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 01, 2016 at 08:38:41PM +0800, Ming Lei wrote: > > be dm-crypt.c. Maybe you've identified some indirect use of > > BIO_MAX_SIZE? > > I mean the recently introduced BIO_MAX_SIZE in -next tree: > > https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/md/dm-crypt.c?id=4ed89c97b0706477b822ea2182827640c0cec486 The crazy bcache bios striking back once again. I really think it's harmful having a _MAX value and then having a minor driver reinterpreting it and sending larger ones. Until we can lift the maximum limit in general nad have common code exercise it we really need to stop bcache from sending these instead of littering the tree with workarounds. From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 08:48:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 13BBD7CA6 for ; Wed, 1 Jun 2016 08:48:27 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id CC745304051 for ; Wed, 1 Jun 2016 06:48:23 -0700 (PDT) X-ASG-Debug-ID: 1464788898-04cbb03568ae1e50001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id mGDC2igmpFcENkHz (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 06:48:19 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1b86VM-0005nI-Kj; Wed, 01 Jun 2016 13:48:16 +0000 Date: Wed, 1 Jun 2016 06:48:16 -0700 From: Christoph Hellwig To: Ming Lei Cc: Jens Axboe , linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, Christoph Hellwig , Dave Chinner , "supporter:XFS FILESYSTEM" Subject: Re: [PATCH v6 5/8] fs: xfs: replace BIO_MAX_SECTORS with BIO_MAX_PAGES Message-ID: <20160601134816.GA20963@infradead.org> X-ASG-Orig-Subj: Re: [PATCH v6 5/8] fs: xfs: replace BIO_MAX_SECTORS with BIO_MAX_PAGES References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <1464615294-9946-6-git-send-email-ming.lei@canonical.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1464615294-9946-6-git-send-email-ming.lei@canonical.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464788899 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 708 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30081 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Mon, May 30, 2016 at 09:34:33PM +0800, Ming Lei wrote: > diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c > index e71cfbd..e5d713b 100644 > --- a/fs/xfs/xfs_buf.c > +++ b/fs/xfs/xfs_buf.c > @@ -1157,9 +1157,7 @@ xfs_buf_ioapply_map( > > next_chunk: > atomic_inc(&bp->b_io_remaining); > - nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); > - if (nr_pages > total_nr_pages) > - nr_pages = total_nr_pages; > + nr_pages = min(total_nr_pages, BIO_MAX_PAGES); > > bio = bio_alloc(GFP_NOIO, nr_pages); While I think this is a useful cleanup on it's own I think you'd make everyones life easier if bio_alloc simply clamped down the passed nr_pages value to the maximum allowed. From wagi@monom.org Wed Jun 1 08:50:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id AC4DB7CA6 for ; Wed, 1 Jun 2016 08:50:56 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6FACF304066 for ; Wed, 1 Jun 2016 06:50:56 -0700 (PDT) X-ASG-Debug-ID: 1464789051-04cb6c2db9acb3a0001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id AbzU12jmyz7NptXz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 06:50:52 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id EAB171940648; Wed, 1 Jun 2016 15:50:48 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id B571B194043D; Wed, 1 Jun 2016 15:50:48 +0200 (CEST) Subject: Re: Internal error xfs_trans_cancel To: Dave Chinner X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <20160601071047.GJ12670@dastard> Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com From: Daniel Wagner X-Enigmail-Draft-Status: N1110 Message-ID: Date: Wed, 1 Jun 2016 15:50:45 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <20160601071047.GJ12670@dastard> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1464789051 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14641 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA085 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 BSF_SC0_SA085 Custom Rule SA085 On 06/01/2016 09:10 AM, Dave Chinner wrote: > On Wed, Jun 01, 2016 at 07:52:31AM +0200, Daniel Wagner wrote: >> I got the error message below while compiling a kernel >> on that system. I can't really say if I did something >> which made the file system unhappy before the crash. >> >> >> [Jun 1 07:41] XFS (sde1): Internal error xfs_trans_cancel at line 984 of file fs/xfs/xfs_trans.c. Caller xfs_rename+0x453/0x960 [xfs] > > Anything in the log before this? Just the usual stuff, as I remember. Sorry, I haven't copied the whole log. >> [ +0.000095] CPU: 22 PID: 8640 Comm: gcc Not tainted 4.7.0-rc1 #16 >> [ +0.000035] Hardware name: Dell Inc. PowerEdge R820/066N7P, BIOS 2.0.20 01/16/2014 >> [ +0.000048] 0000000000000286 00000000c8be6bc3 ffff885fa9473cb0 ffffffff813d146e >> [ +0.000056] ffff885fa9ac5ed0 0000000000000001 ffff885fa9473cc8 ffffffffa0213cdc >> [ +0.000053] ffffffffa02257b3 ffff885fa9473cf0 ffffffffa022eb36 ffff883faa502d00 >> [ +0.000053] Call Trace: >> [ +0.000028] [] dump_stack+0x63/0x85 >> [ +0.000069] [] xfs_error_report+0x3c/0x40 [xfs] >> [ +0.000065] [] ? xfs_rename+0x453/0x960 [xfs] >> [ +0.000064] [] xfs_trans_cancel+0xb6/0xe0 [xfs] >> [ +0.000065] [] xfs_rename+0x453/0x960 [xfs] >> [ +0.000062] [] xfs_vn_rename+0xb3/0xf0 [xfs] >> [ +0.000040] [] vfs_rename+0x58c/0x8d0 >> [ +0.000032] [] SyS_rename+0x371/0x390 >> [ +0.000036] [] entry_SYSCALL_64_fastpath+0x1a/0xa4 >> [ +0.000040] XFS (sde1): xfs_do_force_shutdown(0x8) called from line 985 of file fs/xfs/xfs_trans.c. Return address = 0xffffffffa022eb4f >> [ +0.027680] XFS (sde1): Corruption of in-memory data detected. Shutting down filesystem >> [ +0.000057] XFS (sde1): Please umount the filesystem and rectify the problem(s) >> [Jun 1 07:42] XFS (sde1): xfs_log_force: error -5 returned. >> [ +30.081016] XFS (sde1): xfs_log_force: error -5 returned. > > Doesn't normally happen, and there's not a lot to go on here. Restarted the box and did a couple of kernel builds and everything was fine. > Can > you provide the info listed in the link below so we have some idea > of what configuration the error occurred on? Sure, forgot that in the first post. > http://xfs.org/index.php/XFS_FAQ#Q:_What_information_should_I_include_when_reporting_a_problem.3F # uname -r 4.7.0-rc1-00003-g1f55b0d # xfs_repair -V xfs_repair version 4.5.0 # cat /proc/cpuinfo | grep CPU | wc -l 64 # cat /proc/meminfo MemTotal: 528344752 kB MemFree: 526838036 kB MemAvailable: 525265612 kB Buffers: 2716 kB Cached: 216896 kB SwapCached: 0 kB Active: 119924 kB Inactive: 116552 kB Active(anon): 17416 kB Inactive(anon): 1108 kB Active(file): 102508 kB Inactive(file): 115444 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 0 kB SwapFree: 0 kB Dirty: 0 kB Writeback: 0 kB AnonPages: 16972 kB Mapped: 25288 kB Shmem: 1616 kB Slab: 184920 kB SReclaimable: 60028 kB SUnreclaim: 124892 kB KernelStack: 13120 kB PageTables: 2292 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 264172376 kB Committed_AS: 270612 kB VmallocTotal: 34359738367 kB VmallocUsed: 0 kB VmallocChunk: 0 kB HardwareCorrupted: 0 kB AnonHugePages: 0 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 232256 kB DirectMap2M: 7061504 kB DirectMap1G: 531628032 kB # cat /proc/mounts sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 devtmpfs /dev devtmpfs rw,nosuid,size=264153644k,nr_inodes=66038411,mode=755 0 0 securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0 tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0 devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 tmpfs /run tmpfs rw,nosuid,nodev,mode=755 0 0 tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,mode=755 0 0 cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0 pstore /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0 cgroup /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0 cgroup /sys/fs/cgroup/net_cls,net_prio cgroup rw,nosuid,nodev,noexec,relatime,net_cls,net_prio 0 0 cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpu,cpuacct 0 0 cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0 cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0 cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0 cgroup /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0 cgroup /sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatime,perf_event 0 0 cgroup /sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatime,hugetlb 0 0 cgroup /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatime,devices 0 0 configfs /sys/kernel/config configfs rw,relatime 0 0 /dev/sda2 / xfs rw,relatime,attr2,inode64,noquota 0 0 systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=27,pgrp=1,timeout=0,minproto=5,maxproto=5,direct 0 0 debugfs /sys/kernel/debug debugfs rw,relatime 0 0 mqueue /dev/mqueue mqueue rw,relatime 0 0 tmpfs /tmp tmpfs rw 0 0 hugetlbfs /dev/hugepages hugetlbfs rw,relatime 0 0 binfmt_misc /proc/sys/fs/binfmt_misc binfmt_misc rw,relatime 0 0 nfsd /proc/fs/nfsd nfsd rw,relatime 0 0 /dev/sdc1 /mnt/sdc1 xfs rw,relatime,attr2,inode64,noquota 0 0 /dev/sda1 /boot ext4 rw,relatime,data=ordered 0 0 /dev/sde2 /mnt/yocto xfs rw,relatime,attr2,inode64,noquota 0 0 sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime 0 0 tmpfs /run/user/0 tmpfs rw,nosuid,nodev,relatime,size=52834476k,mode=700 0 0 /dev/sde1 /home xfs rw,relatime,attr2,inode64,noquota 0 0 # cat /proc/partitions major minor #blocks name 11 0 1048575 sr0 8 64 249430016 sde 8 65 104857600 sde1 8 66 144571375 sde2 8 48 142737408 sdd 8 16 142737408 sdb 8 32 142737408 sdc 8 33 142736367 sdc1 8 0 142737408 sda 8 1 5120000 sda1 8 2 104857600 sda2 No RAID No LVM HDD (sda, sdb, sdc, sdd): Manufacturer TOSHIBA Product ID MK1401GRRB SSD (sde): Manufacturer Samsung Product ID Samsung SSD 850 Revision 1B6Q # hdparm -I /dev/sde /dev/sde: SG_IO: bad/missing sense data, sb[]: 70 00 05 00 00 00 00 0d 00 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ATA device, with non-removable media Standards: Likely used: 1 Configuration: Logical max current cylinders 0 0 heads 0 0 sectors/track 0 0 -- Logical/Physical Sector size: 512 bytes device size with M = 1024*1024: 0 MBytes device size with M = 1000*1000: 0 MBytes cache/buffer size = unknown Capabilities: IORDY not likely Cannot perform double-word IO R/W multiple sector transfer: not supported DMA: not supported PIO: pio0 # xfs_info /dev/sde1 meta-data=/dev/sde1 isize=256 agcount=4, agsize=6553600 blks = sectsz=512 attr=2, projid32bit=1 = crc=0 finobt=0 spinodes=0 data = bsize=4096 blocks=26214400, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=0 log =internal bsize=4096 blocks=12800, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 > You didn't run out of space or something unusual like that? It should have enough space for building the kernel. I haven't expierenced any problems with that disk or partition in the last half year. It's my test box, so it gets exposed to many -rc kernels and test patches. I've never seen any problems in xfs so far. Filesystem Size Used Avail Use% Mounted on /dev/sde1 100G 72G 29G 72% /home > Does 'xfs_repair -n ' report any errors? # xfs_repair -n /dev/sde1 Phase 1 - find and verify superblock... Phase 2 - using internal log - zero log... - scan filesystem freespace and inode maps... - found root inode chunk Phase 3 - for each AG... - scan (but don't clear) agi unlinked lists... - process known inodes and perform inode discovery... - agno = 0 - agno = 1 - agno = 2 - agno = 3 - process newly discovered inodes... Phase 4 - check for duplicate blocks... - setting up duplicate extent list... - check for inodes claiming duplicate blocks... - agno = 0 - agno = 3 - agno = 2 - agno = 1 No modify flag set, skipping phase 5 Phase 6 - check inode connectivity... - traversing filesystem ... - traversal finished ... - moving disconnected inodes to lost+found ... Phase 7 - verify link counts... No modify flag set, skipping filesystem flush and exiting. cheers, daniel From msnitzer@redhat.com Wed Jun 1 08:51:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B97D47CA6 for ; Wed, 1 Jun 2016 08:51:54 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 798D68F8040 for ; Wed, 1 Jun 2016 06:51:54 -0700 (PDT) X-ASG-Debug-ID: 1464789112-04cbb0356bae1fa0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id FojY5S34nEdNoVcY (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 06:51:53 -0700 (PDT) X-Barracuda-Envelope-From: msnitzer@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 602266333B; Wed, 1 Jun 2016 13:51:52 +0000 (UTC) Received: from localhost (dhcp-25-149.bos.redhat.com [10.18.25.149]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u51Dpp9G010253 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA256 bits=256 verify=NO); Wed, 1 Jun 2016 09:51:51 -0400 Date: Wed, 1 Jun 2016 09:51:51 -0400 From: Mike Snitzer To: Christoph Hellwig Cc: Ming Lei , Jens Axboe , Linux Kernel Mailing List , linux-block@vger.kernel.org, Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs Message-ID: <20160601135150.GA30759@redhat.com> X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <20160531155348.GA24840@redhat.com> <20160601134427.GA15888@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160601134427.GA15888@infradead.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 01 Jun 2016 13:51:52 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1464789113 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1148 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 01 2016 at 9:44am -0400, Christoph Hellwig wrote: > On Wed, Jun 01, 2016 at 08:38:41PM +0800, Ming Lei wrote: > > > be dm-crypt.c. Maybe you've identified some indirect use of > > > BIO_MAX_SIZE? > > > > I mean the recently introduced BIO_MAX_SIZE in -next tree: > > > > https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/md/dm-crypt.c?id=4ed89c97b0706477b822ea2182827640c0cec486 > > The crazy bcache bios striking back once again. I really think it's > harmful having a _MAX value and then having a minor driver > reinterpreting it and sending larger ones. Until we can lift the > maximum limit in general nad have common code exercise it we really need > to stop bcache from sending these instead of littering the tree with > workarounds. So should I not push this type of fix to Linus now? I was going to send the above commit and this one to him this week: https://git.kernel.org/cgit/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.7&id=57b3001b240629ecc5266d28c845e23ca5f11719 Instead, should bcache be made to not do what it is doing? From hare@suse.de Wed Jun 1 08:54:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E88BA7CA6 for ; Wed, 1 Jun 2016 08:54:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id BBE27304066 for ; Wed, 1 Jun 2016 06:54:03 -0700 (PDT) X-ASG-Debug-ID: 1464789240-04cbb0356bae2090001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id qeQyV5Jdo0PI6VC6 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 01 Jun 2016 06:54:02 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id C1485AD89; Wed, 1 Jun 2016 13:53:59 +0000 (UTC) Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs To: Christoph Hellwig , Ming Lei X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <20160601134300.GA15656@infradead.org> Cc: Jens Axboe , linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , Mike Snitzer , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" From: Hannes Reinecke Message-ID: <574EE8F7.4050509@suse.de> Date: Wed, 1 Jun 2016 15:53:59 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <20160601134300.GA15656@infradead.org> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1464789241 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 574 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/01/2016 03:43 PM, Christoph Hellwig wrote: > These patches look good on their own. They might be an easier sell > just as bio cleanups :) Fully agree. I've seen (some) improvements with those patches, so I'd prefer to have them. You can add: Tested-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From msnitzer@redhat.com Wed Jun 1 08:57:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 909A77CA6 for ; Wed, 1 Jun 2016 08:57:28 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 623948F8040 for ; Wed, 1 Jun 2016 06:57:28 -0700 (PDT) X-ASG-Debug-ID: 1464789447-04cbb03568ae21e0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id rzkQ0qctO1HKKNuA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 06:57:27 -0700 (PDT) X-Barracuda-Envelope-From: msnitzer@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A999D7F6A8; Wed, 1 Jun 2016 13:57:26 +0000 (UTC) Received: from localhost (dhcp-25-149.bos.redhat.com [10.18.25.149]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u51DvPpX002683 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA256 bits=256 verify=NO); Wed, 1 Jun 2016 09:57:26 -0400 Date: Wed, 1 Jun 2016 09:57:25 -0400 From: Mike Snitzer To: Hannes Reinecke Cc: Christoph Hellwig , Ming Lei , Jens Axboe , linux-kernel@vger.kernel.org, linux-block@vger.kernel.org, Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs Message-ID: <20160601135725.GB30759@redhat.com> X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <20160601134300.GA15656@infradead.org> <574EE8F7.4050509@suse.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <574EE8F7.4050509@suse.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 01 Jun 2016 13:57:27 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1464789447 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 397 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 01 2016 at 9:53am -0400, Hannes Reinecke wrote: > On 06/01/2016 03:43 PM, Christoph Hellwig wrote: > > These patches look good on their own. They might be an easier sell > > just as bio cleanups :) > > Fully agree. I've seen (some) improvements with those patches, so > I'd prefer to have them. Can you be more specific on what improvements you've seen? From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:05:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BC81C7CA6 for ; Wed, 1 Jun 2016 09:05:38 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7FED78F8039 for ; Wed, 1 Jun 2016 07:05:35 -0700 (PDT) X-ASG-Debug-ID: 1464789933-04cb6c2db9accce0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id oNz6eRaVtpm3jdmx (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:05:33 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1b86lu-0005sx-Et; Wed, 01 Jun 2016 14:05:22 +0000 Date: Wed, 1 Jun 2016 07:05:22 -0700 From: Christoph Hellwig To: Mike Snitzer Cc: Christoph Hellwig , Ming Lei , Jens Axboe , Linux Kernel Mailing List , linux-block@vger.kernel.org, Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs Message-ID: <20160601140522.GA16228@infradead.org> X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <20160531155348.GA24840@redhat.com> <20160601134427.GA15888@infradead.org> <20160601135150.GA30759@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160601135150.GA30759@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464789933 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 556 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 01, 2016 at 09:51:51AM -0400, Mike Snitzer wrote: > So should I not push this type of fix to Linus now? I was going to send > the above commit and this one to him this week: > https://git.kernel.org/cgit/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.7&id=57b3001b240629ecc5266d28c845e23ca5f11719 > > Instead, should bcache be made to not do what it is doing? I think that's much preferably. Otherwise we'll get a constant trickles of patches like that whenever someone tries bcache on top of another stacking driver. From wagi@monom.org Wed Jun 1 09:13:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 56A807CA6 for ; Wed, 1 Jun 2016 09:13:21 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8988FAC001 for ; Wed, 1 Jun 2016 07:13:17 -0700 (PDT) X-ASG-Debug-ID: 1464790391-04cbb0356aae2aa0001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id qpAXqEu0SfcapJp2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 07:13:12 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id 7143D1940648; Wed, 1 Jun 2016 16:13:10 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 32169194043D; Wed, 1 Jun 2016 16:13:10 +0200 (CEST) Subject: Re: Internal error xfs_trans_cancel To: Dave Chinner X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <20160601071047.GJ12670@dastard> Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com From: Daniel Wagner X-Enigmail-Draft-Status: N1110 Message-ID: <0644b434-6cea-4188-9702-469c26d191b8@monom.org> Date: Wed, 1 Jun 2016 16:13:10 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: Content-Type: multipart/mixed; boundary="------------F7168157A7D02CE60331BEA6" X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1464790392 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8412 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header This is a multi-part message in MIME format. --------------F7168157A7D02CE60331BEA6 Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit >> Anything in the log before this? > > Just the usual stuff, as I remember. Sorry, I haven't copied the whole log. Just triggered it again. My steps for it are: - run all lockperf test git://git.samba.org/jlayton/lockperf.git via my test script: #!/bin/sh run_tests () { echo $1 for i in `seq 10`; do rm -rf /tmp/a; $1 /tmp/a > /dev/null sync done for i in `seq 100`; do rm -rf /tmp/a; $1 /tmp/a >> $2 sync done } PATH=~/src/lockperf:$PATH DIR=$1-`uname -r` if [ ! -d "$DIR" ]; then mkdir $DIR fi CPUSET=`cat /sys/devices/system/node/node0/cpulist` taskset -pc $CPUSET $$ sudo sh -c 'for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor ; do echo performance > $i ; done' for c in `seq 8 32 128`; do for l in `seq 100 100 500`; do time run_tests "posix01 -n $c -l $l " $DIR/posix01-$c-$l.data time run_tests "posix02 -n $c -l $l " $DIR/posix02-$c-$l.data time run_tests "posix03 -n $c -l $l " $DIR/posix03-$c-$l.data time run_tests "posix04 -n $c -l $l " $DIR/posix04-$c-$l.data time run_tests "flock01 -n $c -l $l " $DIR/flock01-$c-$l.data time run_tests "flock02 -n $c -l $l " $DIR/flock02-$c-$l.data time run_tests "lease01 -n $c -l $l " $DIR/lease01-$c-$l.data time run_tests "lease02 -n $c -l $l " $DIR/lease02-$c-$l.data done done sudo sh -c 'for i in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor ; do echo powersave > $i ; done' And after that rebuild a new kernel. That was all. This time I saved the logs. xfs_repair was not so happy either. cheers, daniel --------------F7168157A7D02CE60331BEA6 Content-Type: application/x-xz; name="dmesg.log.xz" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="dmesg.log.xz" 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 --------------F7168157A7D02CE60331BEA6 Content-Type: application/x-xz; name="xfs_repair.log.xz" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="xfs_repair.log.xz" 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 --------------F7168157A7D02CE60331BEA6-- From wagi@monom.org Wed Jun 1 09:19:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 596027CA4 for ; Wed, 1 Jun 2016 09:19:36 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id C86AAAC001 for ; Wed, 1 Jun 2016 07:19:35 -0700 (PDT) X-ASG-Debug-ID: 1464790770-04cb6c2dbcacd360001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id NVs56hES6jbjrU5h (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 07:19:31 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id 2BC9B1940648; Wed, 1 Jun 2016 16:19:30 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id F1EA9194043D; Wed, 1 Jun 2016 16:19:29 +0200 (CEST) Subject: Re: Internal error xfs_trans_cancel To: Dave Chinner X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <20160601071047.GJ12670@dastard> <0644b434-6cea-4188-9702-469c26d191b8@monom.org> Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com From: Daniel Wagner Message-ID: <13fe17d7-3a51-f7f9-0c03-67151d27f6b9@monom.org> Date: Wed, 1 Jun 2016 16:19:29 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <0644b434-6cea-4188-9702-469c26d191b8@monom.org> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1464790771 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 153 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header > via my test script: Looks like my email client did not agree with my formatting of the script. https://www.monom.org/data/lglock/run-tests.sh From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0D0977CA4 for ; Wed, 1 Jun 2016 09:45:07 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 783BBAC006 for ; Wed, 1 Jun 2016 07:45:06 -0700 (PDT) X-ASG-Debug-ID: 1464792303-04cbb0356bae3880001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id mqEzU4VaPH6DCvEo (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:04 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OJ-0005Xe-8p; Wed, 01 Jun 2016 14:45:03 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 01/14] fs: move struct iomap from exportfs.h to a separate header Date: Wed, 1 Jun 2016 16:44:44 +0200 X-ASG-Orig-Subj: [PATCH 01/14] fs: move struct iomap from exportfs.h to a separate header Message-Id: <1464792297-13185-2-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792304 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3399 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Signed-off-by: Christoph Hellwig Reviewed-by: Bob Peterson --- fs/nfsd/blocklayout.c | 1 + fs/nfsd/blocklayoutxdr.c | 1 + fs/xfs/xfs_pnfs.c | 1 + include/linux/exportfs.h | 16 +--------------- include/linux/iomap.h | 21 +++++++++++++++++++++ 5 files changed, 25 insertions(+), 15 deletions(-) create mode 100644 include/linux/iomap.h diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c index e55b524..4df16ae 100644 --- a/fs/nfsd/blocklayout.c +++ b/fs/nfsd/blocklayout.c @@ -2,6 +2,7 @@ * Copyright (c) 2014-2016 Christoph Hellwig. */ #include +#include #include #include #include diff --git a/fs/nfsd/blocklayoutxdr.c b/fs/nfsd/blocklayoutxdr.c index 6c3b316..4ebaaf4 100644 --- a/fs/nfsd/blocklayoutxdr.c +++ b/fs/nfsd/blocklayoutxdr.c @@ -3,6 +3,7 @@ */ #include #include +#include #include #include "nfsd.h" diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index d5b7566..db3c7df 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2014 Christoph Hellwig. */ +#include #include "xfs.h" #include "xfs_format.h" #include "xfs_log_format.h" diff --git a/include/linux/exportfs.h b/include/linux/exportfs.h index d841450..b03c062 100644 --- a/include/linux/exportfs.h +++ b/include/linux/exportfs.h @@ -6,6 +6,7 @@ struct dentry; struct iattr; struct inode; +struct iomap; struct super_block; struct vfsmount; @@ -187,21 +188,6 @@ struct fid { * get_name is not (which is possibly inconsistent) */ -/* types of block ranges for multipage write mappings. */ -#define IOMAP_HOLE 0x01 /* no blocks allocated, need allocation */ -#define IOMAP_DELALLOC 0x02 /* delayed allocation blocks */ -#define IOMAP_MAPPED 0x03 /* blocks allocated @blkno */ -#define IOMAP_UNWRITTEN 0x04 /* blocks allocated @blkno in unwritten state */ - -#define IOMAP_NULL_BLOCK -1LL /* blkno is not valid */ - -struct iomap { - sector_t blkno; /* first sector of mapping */ - loff_t offset; /* file offset of mapping, bytes */ - u64 length; /* length of mapping, bytes */ - int type; /* type of mapping */ -}; - struct export_operations { int (*encode_fh)(struct inode *inode, __u32 *fh, int *max_len, struct inode *parent); diff --git a/include/linux/iomap.h b/include/linux/iomap.h new file mode 100644 index 0000000..1b22197 --- /dev/null +++ b/include/linux/iomap.h @@ -0,0 +1,21 @@ +#ifndef LINUX_IOMAP_H +#define LINUX_IOMAP_H 1 + +#include + +/* types of block ranges for multipage write mappings. */ +#define IOMAP_HOLE 0x01 /* no blocks allocated, need allocation */ +#define IOMAP_DELALLOC 0x02 /* delayed allocation blocks */ +#define IOMAP_MAPPED 0x03 /* blocks allocated @blkno */ +#define IOMAP_UNWRITTEN 0x04 /* blocks allocated @blkno in unwritten state */ + +#define IOMAP_NULL_BLOCK -1LL /* blkno is not valid */ + +struct iomap { + sector_t blkno; /* first sector of mapping */ + loff_t offset; /* file offset of mapping, bytes */ + u64 length; /* length of mapping, bytes */ + int type; /* type of mapping */ +}; + +#endif /* LINUX_IOMAP_H */ -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 4ABAF7CA4 for ; Wed, 1 Jun 2016 09:45:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1DA72304053 for ; Wed, 1 Jun 2016 07:45:05 -0700 (PDT) X-ASG-Debug-ID: 1464792301-04cb6c2db9ace0f0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id R4zCivwIgtNe3fo2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:01 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OG-0005WM-M3; Wed, 01 Jun 2016 14:45:01 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: iomap infrastructure and multipage writes V5 Date: Wed, 1 Jun 2016 16:44:43 +0200 X-ASG-Orig-Subj: iomap infrastructure and multipage writes V5 Message-Id: <1464792297-13185-1-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792301 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1190 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 This series add a new file system I/O path that uses the iomap structure introduced for the pNFS support and support multi-page buffered writes. This was first started by Dave Chinner a long time ago, then I did beat it into shape for production runs in a very constrained ARM NAS enviroment for Tuxera almost as long ago, and now half a dozen rewrites later it's back. The basic idea is to avoid the per-block get_blocks overhead and make use of extents in the buffered write path by iterating over them instead. Note that patch 1 conflicts with Vishals dax error handling series. It would be great to have a stable branch with it so that both the XFS and nvdimm tree could pull it in before the other changes in this area. Changes since V4: - rebase to Linux 4.7-rc1 - fixed an incorrect BUG_ON statement Changes since V3: - fix DAX based zeroing - Reviews and trivial fixes from Bob Changes since V2: - fix the range for delalloc punches after failed writes - updated some changelogs Chances since V1: - add support for fiemap - fix a test fail on 1k block sizes - prepare for 64-bit length, this will be used in a follow on patchset From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 457C47CB7 for ; Wed, 1 Jun 2016 09:45:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0B2948F804B for ; Wed, 1 Jun 2016 07:45:10 -0700 (PDT) X-ASG-Debug-ID: 1464792309-04cbb03569ae3880001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id ldrd8vfaVVB9gXL3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:09 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OO-0006NC-Fb; Wed, 01 Jun 2016 14:45:08 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 03/14] fs: support DAX based iomap zeroing Date: Wed, 1 Jun 2016 16:44:46 +0200 X-ASG-Orig-Subj: [PATCH 03/14] fs: support DAX based iomap zeroing Message-Id: <1464792297-13185-4-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792309 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1620 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 This avoid needing a separate inefficient get_block based DAX zero_range implementation in file systems. Signed-off-by: Christoph Hellwig --- fs/iomap.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/fs/iomap.c b/fs/iomap.c index 5cc6d48..e51adb6 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "internal.h" typedef loff_t (*iomap_actor_t)(struct inode *inode, loff_t pos, loff_t len, @@ -268,6 +269,15 @@ static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset, return iomap_write_end(inode, pos, bytes, bytes, page); } +static int iomap_dax_zero(loff_t pos, unsigned offset, unsigned bytes, + struct iomap *iomap) +{ + sector_t sector = iomap->blkno + + (((pos & ~(PAGE_SIZE - 1)) - iomap->offset) >> 9); + + return __dax_zero_page_range(iomap->bdev, sector, offset, bytes); +} + static loff_t iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count, void *data, struct iomap *iomap) @@ -286,7 +296,10 @@ iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count, offset = pos & (PAGE_SIZE - 1); /* Within page */ bytes = min_t(unsigned, PAGE_SIZE - offset, count); - status = iomap_zero(inode, pos, offset, bytes, iomap); + if (IS_DAX(inode)) + status = iomap_dax_zero(pos, offset, bytes, iomap); + else + status = iomap_zero(inode, pos, offset, bytes, iomap); if (status < 0) return status; -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BF65F7CB5 for ; Wed, 1 Jun 2016 09:45:10 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4A3C6AC006 for ; Wed, 1 Jun 2016 07:45:10 -0700 (PDT) X-ASG-Debug-ID: 1464792306-04bdf05ad4ae5f50001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id CL2reS3HSKVTPNf7 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:06 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OL-0005rA-S8; Wed, 01 Jun 2016 14:45:06 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 02/14] fs: introduce iomap infrastructure Date: Wed, 1 Jun 2016 16:44:45 +0200 X-ASG-Orig-Subj: [PATCH 02/14] fs: introduce iomap infrastructure Message-Id: <1464792297-13185-3-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792306 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19578 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Add infrastructure for multipage buffered writes. This is implemented using an main iterator that applies an actor function to a range that can be written. This infrastucture is used to implement a buffered write helper, one to zero file ranges and one to implement the ->page_mkwrite VM operations. All of them borrow a fair amount of code from fs/buffers. for now by using an internal version of __block_write_begin that gets passed an iomap and builds the corresponding buffer head. The file system is gets a set of paired ->iomap_begin and ->iomap_end calls which allow it to map/reserve a range and get a notification once the write code is finished with it. Based on earlier code from Dave Chinner. Signed-off-by: Christoph Hellwig Reviewed-by: Bob Peterson --- fs/Kconfig | 3 + fs/Makefile | 1 + fs/buffer.c | 76 +++++++++- fs/internal.h | 3 + fs/iomap.c | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/iomap.h | 56 ++++++- 6 files changed, 523 insertions(+), 10 deletions(-) create mode 100644 fs/iomap.c diff --git a/fs/Kconfig b/fs/Kconfig index b8fcb41..4524916 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -10,6 +10,9 @@ config DCACHE_WORD_ACCESS if BLOCK +config FS_IOMAP + bool + source "fs/ext2/Kconfig" source "fs/ext4/Kconfig" source "fs/jbd2/Kconfig" diff --git a/fs/Makefile b/fs/Makefile index 85b6e13..ed2b632 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_COREDUMP) += coredump.o obj-$(CONFIG_SYSCTL) += drop_caches.o obj-$(CONFIG_FHANDLE) += fhandle.o +obj-$(CONFIG_FS_IOMAP) += iomap.o obj-y += quota/ diff --git a/fs/buffer.c b/fs/buffer.c index 754813a..228288a 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -1891,8 +1892,62 @@ void page_zero_new_buffers(struct page *page, unsigned from, unsigned to) } EXPORT_SYMBOL(page_zero_new_buffers); -int __block_write_begin(struct page *page, loff_t pos, unsigned len, - get_block_t *get_block) +static void +iomap_to_bh(struct inode *inode, sector_t block, struct buffer_head *bh, + struct iomap *iomap) +{ + loff_t offset = block << inode->i_blkbits; + + bh->b_bdev = iomap->bdev; + + /* + * Block points to offset in file we need to map, iomap contains + * the offset at which the map starts. If the map ends before the + * current block, then do not map the buffer and let the caller + * handle it. + */ + BUG_ON(offset >= iomap->offset + iomap->length); + + switch (iomap->type) { + case IOMAP_HOLE: + /* + * If the buffer is not up to date or beyond the current EOF, + * we need to mark it as new to ensure sub-block zeroing is + * executed if necessary. + */ + if (!buffer_uptodate(bh) || + (offset >= i_size_read(inode))) + set_buffer_new(bh); + break; + case IOMAP_DELALLOC: + if (!buffer_uptodate(bh) || + (offset >= i_size_read(inode))) + set_buffer_new(bh); + set_buffer_uptodate(bh); + set_buffer_mapped(bh); + set_buffer_delay(bh); + break; + case IOMAP_UNWRITTEN: + /* + * For unwritten regions, we always need to ensure that + * sub-block writes cause the regions in the block we are not + * writing to are zeroed. Set the buffer as new to ensure this. + */ + set_buffer_new(bh); + set_buffer_unwritten(bh); + /* FALLTHRU */ + case IOMAP_MAPPED: + if (offset >= i_size_read(inode)) + set_buffer_new(bh); + bh->b_blocknr = (iomap->blkno >> (inode->i_blkbits - 9)) + + ((offset - iomap->offset) >> inode->i_blkbits); + set_buffer_mapped(bh); + break; + } +} + +int __block_write_begin_int(struct page *page, loff_t pos, unsigned len, + get_block_t *get_block, struct iomap *iomap) { unsigned from = pos & (PAGE_SIZE - 1); unsigned to = from + len; @@ -1928,9 +1983,14 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, clear_buffer_new(bh); if (!buffer_mapped(bh)) { WARN_ON(bh->b_size != blocksize); - err = get_block(inode, block, bh, 1); - if (err) - break; + if (get_block) { + err = get_block(inode, block, bh, 1); + if (err) + break; + } else { + iomap_to_bh(inode, block, bh, iomap); + } + if (buffer_new(bh)) { unmap_underlying_metadata(bh->b_bdev, bh->b_blocknr); @@ -1971,6 +2031,12 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, page_zero_new_buffers(page, from, to); return err; } + +int __block_write_begin(struct page *page, loff_t pos, unsigned len, + get_block_t *get_block) +{ + return __block_write_begin_int(page, pos, len, get_block, NULL); +} EXPORT_SYMBOL(__block_write_begin); static int __block_commit_write(struct inode *inode, struct page *page, diff --git a/fs/internal.h b/fs/internal.h index b71deee..c0c6f49 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -11,6 +11,7 @@ struct super_block; struct file_system_type; +struct iomap; struct linux_binprm; struct path; struct mount; @@ -39,6 +40,8 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait) * buffer.c */ extern void guard_bio_eod(int rw, struct bio *bio); +extern int __block_write_begin_int(struct page *page, loff_t pos, unsigned len, + get_block_t *get_block, struct iomap *iomap); /* * char_dev.c diff --git a/fs/iomap.c b/fs/iomap.c new file mode 100644 index 0000000..5cc6d48 --- /dev/null +++ b/fs/iomap.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2010 Red Hat, Inc. + * Copyright (c) 2016 Christoph Hellwig. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "internal.h" + +typedef loff_t (*iomap_actor_t)(struct inode *inode, loff_t pos, loff_t len, + void *data, struct iomap *iomap); + +/* + * Execute a iomap write on a segment of the mapping that spans a + * contiguous range of pages that have identical block mapping state. + * + * This avoids the need to map pages individually, do individual allocations + * for each page and most importantly avoid the need for filesystem specific + * locking per page. Instead, all the operations are amortised over the entire + * range of pages. It is assumed that the filesystems will lock whatever + * resources they require in the iomap_begin call, and release them in the + * iomap_end call. + */ +static loff_t +iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, + struct iomap_ops *ops, void *data, iomap_actor_t actor) +{ + struct iomap iomap = { 0 }; + loff_t written = 0, ret; + + /* + * Need to map a range from start position for count bytes. This can + * span multiple pages - it is only guaranteed to return a range of a + * single type of pages (e.g. all into a hole, all mapped or all + * unwritten). Failure at this point has nothing to undo. + * + * If allocation is required for this range, reserve the space now so + * that the allocation is guaranteed to succeed later on. Once we copy + * the data into the page cache pages, then we cannot fail otherwise we + * expose transient stale data. If the reserve fails, we can safely + * back out at this point as there is nothing to undo. + */ + ret = ops->iomap_begin(inode, pos, length, flags, &iomap); + if (ret) + return ret; + if (WARN_ON(iomap.offset > pos)) + return -EIO; + + /* + * Cut down the length to the one actually provided by the filesystem, + * as it might not be able to give us the whole size that we requested. + */ + if (iomap.offset + iomap.length < pos + length) + length = iomap.offset + iomap.length - pos; + + /* + * Now that we have guaranteed that the space allocation will succeed. + * we can do the copy-in page by page without having to worry about + * failures exposing transient data. + */ + written = actor(inode, pos, length, data, &iomap); + + /* + * Now the data has been copied, commit the range we've copied. This + * should not fail unless the filesystem has had a fatal error. + */ + ret = ops->iomap_end(inode, pos, length, written > 0 ? written : 0, + flags, &iomap); + + return written ? written : ret; +} + +static void +iomap_write_failed(struct inode *inode, loff_t pos, unsigned len) +{ + loff_t i_size = i_size_read(inode); + + /* + * Only truncate newly allocated pages beyoned EOF, even if the + * write started inside the existing inode size. + */ + if (pos + len > i_size) + truncate_pagecache_range(inode, max(pos, i_size), pos + len); +} + +static int +iomap_write_begin(struct inode *inode, loff_t pos, unsigned len, unsigned flags, + struct page **pagep, struct iomap *iomap) +{ + pgoff_t index = pos >> PAGE_SHIFT; + struct page *page; + int status = 0; + + BUG_ON(pos + len > iomap->offset + iomap->length); + + page = grab_cache_page_write_begin(inode->i_mapping, index, flags); + if (!page) + return -ENOMEM; + + status = __block_write_begin_int(page, pos, len, NULL, iomap); + if (unlikely(status)) { + unlock_page(page); + put_page(page); + page = NULL; + + iomap_write_failed(inode, pos, len); + } + + *pagep = page; + return status; +} + +static int +iomap_write_end(struct inode *inode, loff_t pos, unsigned len, + unsigned copied, struct page *page) +{ + int ret; + + ret = generic_write_end(NULL, inode->i_mapping, pos, len, + copied, page, NULL); + if (ret < len) + iomap_write_failed(inode, pos, len); + return ret; +} + +static loff_t +iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data, + struct iomap *iomap) +{ + struct iov_iter *i = data; + long status = 0; + ssize_t written = 0; + unsigned int flags = AOP_FLAG_NOFS; + + /* + * Copies from kernel address space cannot fail (NFSD is a big user). + */ + if (!iter_is_iovec(i)) + flags |= AOP_FLAG_UNINTERRUPTIBLE; + + do { + struct page *page; + unsigned long offset; /* Offset into pagecache page */ + unsigned long bytes; /* Bytes to write to page */ + size_t copied; /* Bytes copied from user */ + + offset = (pos & (PAGE_SIZE - 1)); + bytes = min_t(unsigned long, PAGE_SIZE - offset, + iov_iter_count(i)); +again: + if (bytes > length) + bytes = length; + + /* + * Bring in the user page that we will copy from _first_. + * Otherwise there's a nasty deadlock on copying from the + * same page as we're writing to, without it being marked + * up-to-date. + * + * Not only is this an optimisation, but it is also required + * to check that the address is actually valid, when atomic + * usercopies are used, below. + */ + if (unlikely(iov_iter_fault_in_readable(i, bytes))) { + status = -EFAULT; + break; + } + + status = iomap_write_begin(inode, pos, bytes, flags, &page, + iomap); + if (unlikely(status)) + break; + + if (mapping_writably_mapped(inode->i_mapping)) + flush_dcache_page(page); + + pagefault_disable(); + copied = iov_iter_copy_from_user_atomic(page, i, offset, bytes); + pagefault_enable(); + + flush_dcache_page(page); + mark_page_accessed(page); + + status = iomap_write_end(inode, pos, bytes, copied, page); + if (unlikely(status < 0)) + break; + copied = status; + + cond_resched(); + + iov_iter_advance(i, copied); + if (unlikely(copied == 0)) { + /* + * If we were unable to copy any data at all, we must + * fall back to a single segment length write. + * + * If we didn't fallback here, we could livelock + * because not all segments in the iov can be copied at + * once without a pagefault. + */ + bytes = min_t(unsigned long, PAGE_SIZE - offset, + iov_iter_single_seg_count(i)); + goto again; + } + pos += copied; + written += copied; + length -= copied; + + balance_dirty_pages_ratelimited(inode->i_mapping); + } while (iov_iter_count(i) && length); + + return written ? written : status; +} + +ssize_t +iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *iter, + struct iomap_ops *ops) +{ + struct inode *inode = iocb->ki_filp->f_mapping->host; + loff_t pos = iocb->ki_pos, ret = 0, written = 0; + + while (iov_iter_count(iter)) { + ret = iomap_apply(inode, pos, iov_iter_count(iter), + IOMAP_WRITE, ops, iter, iomap_write_actor); + if (ret <= 0) + break; + pos += ret; + written += ret; + } + + return written ? written : ret; +} +EXPORT_SYMBOL_GPL(iomap_file_buffered_write); + +static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset, + unsigned bytes, struct iomap *iomap) +{ + struct page *page; + int status; + + status = iomap_write_begin(inode, pos, bytes, + AOP_FLAG_UNINTERRUPTIBLE | AOP_FLAG_NOFS, &page, iomap); + if (status) + return status; + + zero_user(page, offset, bytes); + mark_page_accessed(page); + + return iomap_write_end(inode, pos, bytes, bytes, page); +} + +static loff_t +iomap_zero_range_actor(struct inode *inode, loff_t pos, loff_t count, + void *data, struct iomap *iomap) +{ + bool *did_zero = data; + loff_t written = 0; + int status; + + /* already zeroed? we're done. */ + if (iomap->type == IOMAP_HOLE || iomap->type == IOMAP_UNWRITTEN) + return count; + + do { + unsigned offset, bytes; + + offset = pos & (PAGE_SIZE - 1); /* Within page */ + bytes = min_t(unsigned, PAGE_SIZE - offset, count); + + status = iomap_zero(inode, pos, offset, bytes, iomap); + if (status < 0) + return status; + + pos += bytes; + count -= bytes; + written += bytes; + if (did_zero) + *did_zero = true; + } while (count > 0); + + return written; +} + +int +iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero, + struct iomap_ops *ops) +{ + loff_t ret; + + while (len > 0) { + ret = iomap_apply(inode, pos, len, IOMAP_ZERO, + ops, did_zero, iomap_zero_range_actor); + if (ret <= 0) + return ret; + + pos += ret; + len -= ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(iomap_zero_range); + +int +iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero, + struct iomap_ops *ops) +{ + unsigned blocksize = (1 << inode->i_blkbits); + unsigned off = pos & (blocksize - 1); + + /* Block boundary? Nothing to do */ + if (!off) + return 0; + return iomap_zero_range(inode, pos, blocksize - off, did_zero, ops); +} +EXPORT_SYMBOL_GPL(iomap_truncate_page); + +static loff_t +iomap_page_mkwrite_actor(struct inode *inode, loff_t pos, loff_t length, + void *data, struct iomap *iomap) +{ + struct page *page = data; + int ret; + + ret = __block_write_begin_int(page, pos & ~PAGE_MASK, length, + NULL, iomap); + if (ret) + return ret; + + block_commit_write(page, 0, length); + return length; +} + +int iomap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, + struct iomap_ops *ops) +{ + struct page *page = vmf->page; + struct inode *inode = file_inode(vma->vm_file); + unsigned long length; + loff_t offset, size; + ssize_t ret; + + lock_page(page); + size = i_size_read(inode); + if ((page->mapping != inode->i_mapping) || + (page_offset(page) > size)) { + /* We overload EFAULT to mean page got truncated */ + ret = -EFAULT; + goto out_unlock; + } + + /* page is wholly or partially inside EOF */ + if (((page->index + 1) << PAGE_SHIFT) > size) + length = size & ~PAGE_MASK; + else + length = PAGE_SIZE; + + offset = page_offset(page); + while (length > 0) { + ret = iomap_apply(inode, offset, length, IOMAP_WRITE, + ops, page, iomap_page_mkwrite_actor); + if (unlikely(ret <= 0)) + goto out_unlock; + offset += ret; + length -= ret; + } + + set_page_dirty(page); + wait_for_stable_page(page); + return 0; +out_unlock: + unlock_page(page); + return ret; +} +EXPORT_SYMBOL_GPL(iomap_page_mkwrite); diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 1b22197..854766f 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -3,19 +3,65 @@ #include -/* types of block ranges for multipage write mappings. */ +struct inode; +struct iov_iter; +struct kiocb; +struct vm_area_struct; +struct vm_fault; + +/* + * Types of block ranges for iomap mappings: + */ #define IOMAP_HOLE 0x01 /* no blocks allocated, need allocation */ #define IOMAP_DELALLOC 0x02 /* delayed allocation blocks */ #define IOMAP_MAPPED 0x03 /* blocks allocated @blkno */ #define IOMAP_UNWRITTEN 0x04 /* blocks allocated @blkno in unwritten state */ +/* + * Magic value for blkno: + */ #define IOMAP_NULL_BLOCK -1LL /* blkno is not valid */ struct iomap { - sector_t blkno; /* first sector of mapping */ - loff_t offset; /* file offset of mapping, bytes */ - u64 length; /* length of mapping, bytes */ - int type; /* type of mapping */ + sector_t blkno; /* first sector of mapping, fs blocks */ + loff_t offset; /* file offset of mapping, bytes */ + u64 length; /* length of mapping, bytes */ + int type; /* type of mapping */ + struct block_device *bdev; /* block device for I/O */ +}; + +/* + * Flags for iomap_begin / iomap_end. No flag implies a read. + */ +#define IOMAP_WRITE (1 << 0) +#define IOMAP_ZERO (1 << 1) + +struct iomap_ops { + /* + * Return the existing mapping at pos, or reserve space starting at + * pos for up to length, as long as we can do it as a single mapping. + * The actual length is returned in iomap->length. + */ + int (*iomap_begin)(struct inode *inode, loff_t pos, loff_t length, + unsigned flags, struct iomap *iomap); + + /* + * Commit and/or unreserve space previous allocated using iomap_begin. + * Written indicates the length of the successful write operation which + * needs to be commited, while the rest needs to be unreserved. + * Written might be zero if no data was written. + */ + int (*iomap_end)(struct inode *inode, loff_t pos, loff_t length, + ssize_t written, unsigned flags, struct iomap *iomap); }; +ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from, + struct iomap_ops *ops); +int iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, + bool *did_zero, struct iomap_ops *ops); +int iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero, + struct iomap_ops *ops); +int iomap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, + struct iomap_ops *ops); + #endif /* LINUX_IOMAP_H */ -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A05197CC7 for ; Wed, 1 Jun 2016 09:45:14 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1BBF9AC003 for ; Wed, 1 Jun 2016 07:45:14 -0700 (PDT) X-ASG-Debug-ID: 1464792311-04cb6c2db9ace110001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id gd3JmFcKZXJKD09D (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:12 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OR-0006kG-2Z; Wed, 01 Jun 2016 14:45:11 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 04/14] xfs: make xfs_bmbt_to_iomap available outside of xfs_pnfs.c Date: Wed, 1 Jun 2016 16:44:47 +0200 X-ASG-Orig-Subj: [PATCH 04/14] xfs: make xfs_bmbt_to_iomap available outside of xfs_pnfs.c Message-Id: <1464792297-13185-5-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792312 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3310 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 And ensure it works for RT subvolume files an set the block device, both of which will be needed to be able to use the function in the buffered write path. Signed-off-by: Christoph Hellwig Reviewed-by: Bob Peterson --- fs/xfs/xfs_iomap.c | 27 +++++++++++++++++++++++++++ fs/xfs/xfs_iomap.h | 4 ++++ fs/xfs/xfs_pnfs.c | 26 -------------------------- 3 files changed, 31 insertions(+), 26 deletions(-) diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 5839135..2f37194 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -15,6 +15,7 @@ * along with this program; if not, write the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include #include "xfs.h" #include "xfs_fs.h" #include "xfs_shared.h" @@ -940,3 +941,29 @@ error_on_bmapi_transaction: xfs_iunlock(ip, XFS_ILOCK_EXCL); return error; } + +void +xfs_bmbt_to_iomap( + struct xfs_inode *ip, + struct iomap *iomap, + struct xfs_bmbt_irec *imap) +{ + struct xfs_mount *mp = ip->i_mount; + + if (imap->br_startblock == HOLESTARTBLOCK) { + iomap->blkno = IOMAP_NULL_BLOCK; + iomap->type = IOMAP_HOLE; + } else if (imap->br_startblock == DELAYSTARTBLOCK) { + iomap->blkno = IOMAP_NULL_BLOCK; + iomap->type = IOMAP_DELALLOC; + } else { + iomap->blkno = xfs_fsb_to_db(ip, imap->br_startblock); + if (imap->br_state == XFS_EXT_UNWRITTEN) + iomap->type = IOMAP_UNWRITTEN; + else + iomap->type = IOMAP_MAPPED; + } + iomap->offset = XFS_FSB_TO_B(mp, imap->br_startoff); + iomap->length = XFS_FSB_TO_B(mp, imap->br_blockcount); + iomap->bdev = xfs_find_bdev_for_inode(VFS_I(ip)); +} diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 8688e66..718f07c 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -18,6 +18,7 @@ #ifndef __XFS_IOMAP_H__ #define __XFS_IOMAP_H__ +struct iomap; struct xfs_inode; struct xfs_bmbt_irec; @@ -29,4 +30,7 @@ int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, struct xfs_bmbt_irec *); int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t); +void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *, + struct xfs_bmbt_irec *); + #endif /* __XFS_IOMAP_H__*/ diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index db3c7df..0f14b2e 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c @@ -80,32 +80,6 @@ xfs_fs_get_uuid( return 0; } -static void -xfs_bmbt_to_iomap( - struct xfs_inode *ip, - struct iomap *iomap, - struct xfs_bmbt_irec *imap) -{ - struct xfs_mount *mp = ip->i_mount; - - if (imap->br_startblock == HOLESTARTBLOCK) { - iomap->blkno = IOMAP_NULL_BLOCK; - iomap->type = IOMAP_HOLE; - } else if (imap->br_startblock == DELAYSTARTBLOCK) { - iomap->blkno = IOMAP_NULL_BLOCK; - iomap->type = IOMAP_DELALLOC; - } else { - iomap->blkno = - XFS_FSB_TO_DADDR(ip->i_mount, imap->br_startblock); - if (imap->br_state == XFS_EXT_UNWRITTEN) - iomap->type = IOMAP_UNWRITTEN; - else - iomap->type = IOMAP_MAPPED; - } - iomap->offset = XFS_FSB_TO_B(mp, imap->br_startoff); - iomap->length = XFS_FSB_TO_B(mp, imap->br_blockcount); -} - /* * Get a layout for the pNFS client. */ -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 985937CA4 for ; Wed, 1 Jun 2016 09:45:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 54BFD8F804B for ; Wed, 1 Jun 2016 07:45:16 -0700 (PDT) X-ASG-Debug-ID: 1464792314-04cbb0356aae3890001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id BciDnGNdLE01XXGQ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:14 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OT-0006lJ-Li; Wed, 01 Jun 2016 14:45:14 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 05/14] xfs: reorder zeroing and flushing sequence in truncate Date: Wed, 1 Jun 2016 16:44:48 +0200 X-ASG-Orig-Subj: [PATCH 05/14] xfs: reorder zeroing and flushing sequence in truncate Message-Id: <1464792297-13185-6-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792314 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2925 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Currently zeroing out blocks and waiting for writeout is a bit of a mess in truncate. This patch gives it a clear order in preparation for the iomap path: (1) we first wait for any direct I/O to complete to prevent any races for it (2) we then perform the actual zeroing, and only use the truncate_page helpers for truncating down. The truncate up case already is handled by the separate call to xfs_zero_eof. (3) only then we write back dirty data, as zeroing block may cause dirty pages when using either xfs_zero_eof or the new iomap infrastructure. Signed-off-by: Christoph Hellwig Reviewed-by: Bob Peterson --- fs/xfs/xfs_iops.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index c5d4eba..1a5ca4b 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -801,20 +801,35 @@ xfs_setattr_size( return error; /* + * Wait for all direct I/O to complete. + */ + inode_dio_wait(inode); + + /* * File data changes must be complete before we start the transaction to * modify the inode. This needs to be done before joining the inode to * the transaction because the inode cannot be unlocked once it is a * part of the transaction. * - * Start with zeroing any data block beyond EOF that we may expose on - * file extension. + * Start with zeroing any data beyond EOF that we may expose on file + * extension, or zeroing out the rest of the block on a downward + * truncate. */ if (newsize > oldsize) { error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing); - if (error) - return error; + } else { + if (IS_DAX(inode)) { + error = dax_truncate_page(inode, newsize, + xfs_get_blocks_direct); + } else { + error = block_truncate_page(inode->i_mapping, newsize, + xfs_get_blocks); + } } + if (error) + return error; + /* * We are going to log the inode size change in this transaction so * any previous writes that are beyond the on disk EOF and the new @@ -831,9 +846,6 @@ xfs_setattr_size( return error; } - /* Now wait for all direct I/O to complete. */ - inode_dio_wait(inode); - /* * We've already locked out new page faults, so now we can safely remove * pages from the page cache knowing they won't get refaulted until we @@ -851,13 +863,6 @@ xfs_setattr_size( * to hope that the caller sees ENOMEM and retries the truncate * operation. */ - if (IS_DAX(inode)) - error = dax_truncate_page(inode, newsize, xfs_get_blocks_direct); - else - error = block_truncate_page(inode->i_mapping, newsize, - xfs_get_blocks); - if (error) - return error; truncate_setsize(inode, newsize); error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); -- 2.1.4 From ec656c8@yahoo.pl Wed Jun 1 09:45:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 07D237CCF for ; Wed, 1 Jun 2016 09:45:19 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id C2A4D8F804B for ; Wed, 1 Jun 2016 07:45:18 -0700 (PDT) X-ASG-Debug-ID: 1464792313-04cbb0356bae3890001-NocioJ Received: from 67242-vds-kont1k.gmhost.hosting (67242-vds-kont1k.gmhost.hosting [95.46.98.73]) by cuda.sgi.com with ESMTP id vdxuU9CnHztvy8B5 for ; Wed, 01 Jun 2016 07:45:14 -0700 (PDT) X-Barracuda-Envelope-From: ec656c8@yahoo.pl X-Barracuda-Effective-Source-IP: 67242-vds-kont1k.gmhost.hosting[95.46.98.73] X-Barracuda-Apparent-Source-IP: 95.46.98.73 Received: from 67242-vds-kont1k (localhost [127.0.0.1]) by 67242-vds-kont1k.gmhost.hosting (Postfix) with ESMTP id E740920C06 for ; Wed, 1 Jun 2016 17:45:13 +0300 (EEST) From: =?utf-8?B?0JPRgNC40LPQvtGA0LjQuSDQr9GA0L7RgdC70LDQstGG0LXQsg==?= Subject: =?utf-8?B?0JTQvtCy0LXQt9C10Lwg0JLQsNGBINCx0YvRgdGC0YDQviDQuCDRgtGD0LTQsCwg0LrRg9C00LAg0JLQsNC8INC90YPQttC90L4uINCf0YDQvtCx0LrQuCAtINC90LUg0L/QvtC80LXRhdCwLg==?= MIME-Version: 1.0 X-ASG-Orig-Subj: =?utf-8?B?0JTQvtCy0LXQt9C10Lwg0JLQsNGBINCx0YvRgdGC0YDQviDQuCDRgtGD0LTQsCwg0LrRg9C00LAg0JLQsNC8INC90YPQttC90L4uINCf0YDQvtCx0LrQuCAtINC90LUg0L/QvtC80LXRhdCwLg==?= Content-Type: text/plain; charset=UTF-8; Message-Id: <20160601144513.E740920C06@67242-vds-kont1k.gmhost.hosting> Date: Wed, 1 Jun 2016 17:45:13 +0300 (EEST) X-Barracuda-Connect: 67242-vds-kont1k.gmhost.hosting[95.46.98.73] X-Barracuda-Start-Time: 1464792314 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 152 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.21 X-Barracuda-Spam-Status: No, SCORE=1.21 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MISSING_HEADERS, TO_CC_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.21 MISSING_HEADERS Missing To: header 0.00 TO_CC_NONE No To: or Cc: header To: undisclosed-recipients:; Знаете, что такое стоять в пробках? - С нами Вы об этом забудете! - http://такси-ольга.рф From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 61DFD7CCA for ; Wed, 1 Jun 2016 09:45:20 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id E310AAC003 for ; Wed, 1 Jun 2016 07:45:19 -0700 (PDT) X-ASG-Debug-ID: 1464792316-04bdf05ad6ae5f70001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id kuUuazL5oy3qbz4n (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:16 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OW-0006mC-8l; Wed, 01 Jun 2016 14:45:16 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 06/14] xfs: implement iomap based buffered write path Date: Wed, 1 Jun 2016 16:44:49 +0200 X-ASG-Orig-Subj: [PATCH 06/14] xfs: implement iomap based buffered write path Message-Id: <1464792297-13185-7-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792316 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17942 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Convert XFS to use the new iomap based multipage write path. This involves implementing the ->iomap_begin and ->iomap_end methods, and switching the buffered file write, page_mkwrite and xfs_iozero paths to the new iomap helpers. With this change __xfs_get_blocks will never be used for buffered writes, and the code handling them can be removed. Based on earlier code from Dave Chinner. Signed-off-by: Christoph Hellwig Reviewed-by: Bob Peterson --- fs/xfs/Kconfig | 1 + fs/xfs/xfs_aops.c | 212 ----------------------------------------------------- fs/xfs/xfs_file.c | 71 ++++++++---------- fs/xfs/xfs_iomap.c | 144 ++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_iomap.h | 5 +- fs/xfs/xfs_iops.c | 9 ++- fs/xfs/xfs_trace.h | 3 + 7 files changed, 187 insertions(+), 258 deletions(-) diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig index 5d47b4d..35faf12 100644 --- a/fs/xfs/Kconfig +++ b/fs/xfs/Kconfig @@ -4,6 +4,7 @@ config XFS_FS depends on (64BIT || LBDAF) select EXPORTFS select LIBCRC32C + select FS_IOMAP help XFS is a high performance journaling filesystem which originated on the SGI IRIX platform. It is completely multi-threaded, can diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 4c463b9..2ac9f7e 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1427,216 +1427,6 @@ xfs_vm_direct_IO( xfs_get_blocks_direct, endio, NULL, flags); } -/* - * Punch out the delalloc blocks we have already allocated. - * - * Don't bother with xfs_setattr given that nothing can have made it to disk yet - * as the page is still locked at this point. - */ -STATIC void -xfs_vm_kill_delalloc_range( - struct inode *inode, - loff_t start, - loff_t end) -{ - struct xfs_inode *ip = XFS_I(inode); - xfs_fileoff_t start_fsb; - xfs_fileoff_t end_fsb; - int error; - - start_fsb = XFS_B_TO_FSB(ip->i_mount, start); - end_fsb = XFS_B_TO_FSB(ip->i_mount, end); - if (end_fsb <= start_fsb) - return; - - xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_bmap_punch_delalloc_range(ip, start_fsb, - end_fsb - start_fsb); - if (error) { - /* something screwed, just bail */ - if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { - xfs_alert(ip->i_mount, - "xfs_vm_write_failed: unable to clean up ino %lld", - ip->i_ino); - } - } - xfs_iunlock(ip, XFS_ILOCK_EXCL); -} - -STATIC void -xfs_vm_write_failed( - struct inode *inode, - struct page *page, - loff_t pos, - unsigned len) -{ - loff_t block_offset; - loff_t block_start; - loff_t block_end; - loff_t from = pos & (PAGE_SIZE - 1); - loff_t to = from + len; - struct buffer_head *bh, *head; - struct xfs_mount *mp = XFS_I(inode)->i_mount; - - /* - * The request pos offset might be 32 or 64 bit, this is all fine - * on 64-bit platform. However, for 64-bit pos request on 32-bit - * platform, the high 32-bit will be masked off if we evaluate the - * block_offset via (pos & PAGE_MASK) because the PAGE_MASK is - * 0xfffff000 as an unsigned long, hence the result is incorrect - * which could cause the following ASSERT failed in most cases. - * In order to avoid this, we can evaluate the block_offset of the - * start of the page by using shifts rather than masks the mismatch - * problem. - */ - block_offset = (pos >> PAGE_SHIFT) << PAGE_SHIFT; - - ASSERT(block_offset + from == pos); - - head = page_buffers(page); - block_start = 0; - for (bh = head; bh != head || !block_start; - bh = bh->b_this_page, block_start = block_end, - block_offset += bh->b_size) { - block_end = block_start + bh->b_size; - - /* skip buffers before the write */ - if (block_end <= from) - continue; - - /* if the buffer is after the write, we're done */ - if (block_start >= to) - break; - - /* - * Process delalloc and unwritten buffers beyond EOF. We can - * encounter unwritten buffers in the event that a file has - * post-EOF unwritten extents and an extending write happens to - * fail (e.g., an unaligned write that also involves a delalloc - * to the same page). - */ - if (!buffer_delay(bh) && !buffer_unwritten(bh)) - continue; - - if (!xfs_mp_fail_writes(mp) && !buffer_new(bh) && - block_offset < i_size_read(inode)) - continue; - - if (buffer_delay(bh)) - xfs_vm_kill_delalloc_range(inode, block_offset, - block_offset + bh->b_size); - - /* - * This buffer does not contain data anymore. make sure anyone - * who finds it knows that for certain. - */ - clear_buffer_delay(bh); - clear_buffer_uptodate(bh); - clear_buffer_mapped(bh); - clear_buffer_new(bh); - clear_buffer_dirty(bh); - clear_buffer_unwritten(bh); - } - -} - -/* - * This used to call block_write_begin(), but it unlocks and releases the page - * on error, and we need that page to be able to punch stale delalloc blocks out - * on failure. hence we copy-n-waste it here and call xfs_vm_write_failed() at - * the appropriate point. - */ -STATIC int -xfs_vm_write_begin( - struct file *file, - struct address_space *mapping, - loff_t pos, - unsigned len, - unsigned flags, - struct page **pagep, - void **fsdata) -{ - pgoff_t index = pos >> PAGE_SHIFT; - struct page *page; - int status; - struct xfs_mount *mp = XFS_I(mapping->host)->i_mount; - - ASSERT(len <= PAGE_SIZE); - - page = grab_cache_page_write_begin(mapping, index, flags); - if (!page) - return -ENOMEM; - - status = __block_write_begin(page, pos, len, xfs_get_blocks); - if (xfs_mp_fail_writes(mp)) - status = -EIO; - if (unlikely(status)) { - struct inode *inode = mapping->host; - size_t isize = i_size_read(inode); - - xfs_vm_write_failed(inode, page, pos, len); - unlock_page(page); - - /* - * If the write is beyond EOF, we only want to kill blocks - * allocated in this write, not blocks that were previously - * written successfully. - */ - if (xfs_mp_fail_writes(mp)) - isize = 0; - if (pos + len > isize) { - ssize_t start = max_t(ssize_t, pos, isize); - - truncate_pagecache_range(inode, start, pos + len); - } - - put_page(page); - page = NULL; - } - - *pagep = page; - return status; -} - -/* - * On failure, we only need to kill delalloc blocks beyond EOF in the range of - * this specific write because they will never be written. Previous writes - * beyond EOF where block allocation succeeded do not need to be trashed, so - * only new blocks from this write should be trashed. For blocks within - * EOF, generic_write_end() zeros them so they are safe to leave alone and be - * written with all the other valid data. - */ -STATIC int -xfs_vm_write_end( - struct file *file, - struct address_space *mapping, - loff_t pos, - unsigned len, - unsigned copied, - struct page *page, - void *fsdata) -{ - int ret; - - ASSERT(len <= PAGE_SIZE); - - ret = generic_write_end(file, mapping, pos, len, copied, page, fsdata); - if (unlikely(ret < len)) { - struct inode *inode = mapping->host; - size_t isize = i_size_read(inode); - loff_t to = pos + len; - - if (to > isize) { - /* only kill blocks in this write beyond EOF */ - if (pos > isize) - isize = pos; - xfs_vm_kill_delalloc_range(inode, isize, to); - truncate_pagecache_range(inode, isize, to); - } - } - return ret; -} - STATIC sector_t xfs_vm_bmap( struct address_space *mapping, @@ -1747,8 +1537,6 @@ const struct address_space_operations xfs_address_space_operations = { .set_page_dirty = xfs_vm_set_page_dirty, .releasepage = xfs_vm_releasepage, .invalidatepage = xfs_vm_invalidatepage, - .write_begin = xfs_vm_write_begin, - .write_end = xfs_vm_write_end, .bmap = xfs_vm_bmap, .direct_IO = xfs_vm_direct_IO, .migratepage = buffer_migrate_page, diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 47fc632..7316d38 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -37,6 +37,7 @@ #include "xfs_log.h" #include "xfs_icache.h" #include "xfs_pnfs.h" +#include "xfs_iomap.h" #include #include @@ -79,57 +80,27 @@ xfs_rw_ilock_demote( inode_unlock(VFS_I(ip)); } -/* - * xfs_iozero clears the specified range supplied via the page cache (except in - * the DAX case). Writes through the page cache will allocate blocks over holes, - * though the callers usually map the holes first and avoid them. If a block is - * not completely zeroed, then it will be read from disk before being partially - * zeroed. - * - * In the DAX case, we can just directly write to the underlying pages. This - * will not allocate blocks, but will avoid holes and unwritten extents and so - * not do unnecessary work. - */ -int -xfs_iozero( - struct xfs_inode *ip, /* inode */ - loff_t pos, /* offset in file */ - size_t count) /* size of data to zero */ +static int +xfs_dax_zero_range( + struct inode *inode, + loff_t pos, + size_t count) { - struct page *page; - struct address_space *mapping; int status = 0; - - mapping = VFS_I(ip)->i_mapping; do { unsigned offset, bytes; - void *fsdata; offset = (pos & (PAGE_SIZE -1)); /* Within page */ bytes = PAGE_SIZE - offset; if (bytes > count) bytes = count; - if (IS_DAX(VFS_I(ip))) { - status = dax_zero_page_range(VFS_I(ip), pos, bytes, - xfs_get_blocks_direct); - if (status) - break; - } else { - status = pagecache_write_begin(NULL, mapping, pos, bytes, - AOP_FLAG_UNINTERRUPTIBLE, - &page, &fsdata); - if (status) - break; - - zero_user(page, offset, bytes); + status = dax_zero_page_range(inode, pos, bytes, + xfs_get_blocks_direct); + if (status) + break; - status = pagecache_write_end(NULL, mapping, pos, bytes, - bytes, page, fsdata); - WARN_ON(status <= 0); /* can't return less than zero! */ - status = 0; - } pos += bytes; count -= bytes; } while (count); @@ -137,6 +108,24 @@ xfs_iozero( return status; } +/* + * Clear the specified ranges to zero through either the pagecache or DAX. + * Holes and unwritten extents will be left as-is as they already are zeroed. + */ +int +xfs_iozero( + struct xfs_inode *ip, + loff_t pos, + size_t count) +{ + struct inode *inode = VFS_I(ip); + + if (IS_DAX(VFS_I(ip))) + return xfs_dax_zero_range(inode, pos, count); + else + return iomap_zero_range(inode, pos, count, NULL, &xfs_iomap_ops); +} + int xfs_update_prealloc_flags( struct xfs_inode *ip, @@ -841,7 +830,7 @@ xfs_file_buffered_aio_write( write_retry: trace_xfs_file_buffered_write(ip, iov_iter_count(from), iocb->ki_pos, 0); - ret = generic_perform_write(file, from, iocb->ki_pos); + ret = iomap_file_buffered_write(iocb, from, &xfs_iomap_ops); if (likely(ret >= 0)) iocb->ki_pos += ret; @@ -1553,7 +1542,7 @@ xfs_filemap_page_mkwrite( if (IS_DAX(inode)) { ret = __dax_mkwrite(vma, vmf, xfs_get_blocks_dax_fault); } else { - ret = block_page_mkwrite(vma, vmf, xfs_get_blocks); + ret = iomap_page_mkwrite(vma, vmf, &xfs_iomap_ops); ret = block_page_mkwrite_return(ret); } diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 2f37194..620fc91 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -967,3 +967,147 @@ xfs_bmbt_to_iomap( iomap->length = XFS_FSB_TO_B(mp, imap->br_blockcount); iomap->bdev = xfs_find_bdev_for_inode(VFS_I(ip)); } + +static inline bool imap_needs_alloc(struct xfs_bmbt_irec *imap, int nimaps) +{ + return !nimaps || + imap->br_startblock == HOLESTARTBLOCK || + imap->br_startblock == DELAYSTARTBLOCK; +} + +static int +xfs_file_iomap_begin( + struct inode *inode, + loff_t offset, + loff_t length, + unsigned flags, + struct iomap *iomap) +{ + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; + struct xfs_bmbt_irec imap; + xfs_fileoff_t offset_fsb, end_fsb; + int nimaps = 1, error = 0; + + if (XFS_FORCED_SHUTDOWN(mp)) + return -EIO; + + xfs_ilock(ip, XFS_ILOCK_EXCL); + + ASSERT(offset <= mp->m_super->s_maxbytes); + if ((xfs_fsize_t)offset + length > mp->m_super->s_maxbytes) + length = mp->m_super->s_maxbytes - offset; + offset_fsb = XFS_B_TO_FSBT(mp, offset); + end_fsb = XFS_B_TO_FSB(mp, offset + length); + + error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, &imap, + &nimaps, XFS_BMAPI_ENTIRE); + if (error) { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return error; + } + + if ((flags & IOMAP_WRITE) && imap_needs_alloc(&imap, nimaps)) { + /* + * We cap the maximum length we map here to MAX_WRITEBACK_PAGES + * pages to keep the chunks of work done where somewhat symmetric + * with the work writeback does. This is a completely arbitrary + * number pulled out of thin air as a best guess for initial + * testing. + * + * Note that the values needs to be less than 32-bits wide until + * the lower level functions are updated. + */ + length = min_t(loff_t, length, 1024 * PAGE_SIZE); + if (xfs_get_extsz_hint(ip)) { + /* + * xfs_iomap_write_direct() expects the shared lock. It + * is unlocked on return. + */ + xfs_ilock_demote(ip, XFS_ILOCK_EXCL); + error = xfs_iomap_write_direct(ip, offset, length, &imap, + nimaps); + } else { + error = xfs_iomap_write_delay(ip, offset, length, &imap); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + } + + if (error) + return error; + + trace_xfs_iomap_alloc(ip, offset, length, 0, &imap); + xfs_bmbt_to_iomap(ip, iomap, &imap); + } else if (nimaps) { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + trace_xfs_iomap_found(ip, offset, length, 0, &imap); + xfs_bmbt_to_iomap(ip, iomap, &imap); + } else { + xfs_iunlock(ip, XFS_ILOCK_EXCL); + trace_xfs_iomap_not_found(ip, offset, length, 0, &imap); + iomap->blkno = IOMAP_NULL_BLOCK; + iomap->type = IOMAP_HOLE; + iomap->offset = offset; + iomap->length = length; + } + + return 0; +} + +static int +xfs_file_iomap_end_delalloc( + struct xfs_inode *ip, + loff_t offset, + loff_t length, + ssize_t written) +{ + struct xfs_mount *mp = ip->i_mount; + xfs_fileoff_t start_fsb; + xfs_fileoff_t end_fsb; + int error = 0; + + start_fsb = XFS_B_TO_FSB(mp, offset + written); + end_fsb = XFS_B_TO_FSB(mp, offset + length); + + /* + * Trim back delalloc blocks if we didn't manage to write the whole + * range reserved. + * + * We don't need to care about racing delalloc as we hold i_mutex + * across the reserve/allocate/unreserve calls. If there are delalloc + * blocks in the range, they are ours. + */ + if (start_fsb < end_fsb) { + xfs_ilock(ip, XFS_ILOCK_EXCL); + error = xfs_bmap_punch_delalloc_range(ip, start_fsb, + end_fsb - start_fsb); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + if (error && !XFS_FORCED_SHUTDOWN(mp)) { + xfs_alert(mp, "%s: unable to clean up ino %lld", + __func__, ip->i_ino); + return error; + } + } + + return 0; +} + +static int +xfs_file_iomap_end( + struct inode *inode, + loff_t offset, + loff_t length, + ssize_t written, + unsigned flags, + struct iomap *iomap) +{ + if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC) + return xfs_file_iomap_end_delalloc(XFS_I(inode), offset, + length, written); + return 0; +} + +struct iomap_ops xfs_iomap_ops = { + .iomap_begin = xfs_file_iomap_begin, + .iomap_end = xfs_file_iomap_end, +}; diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 718f07c..e066d04 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -18,7 +18,8 @@ #ifndef __XFS_IOMAP_H__ #define __XFS_IOMAP_H__ -struct iomap; +#include + struct xfs_inode; struct xfs_bmbt_irec; @@ -33,4 +34,6 @@ int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t); void xfs_bmbt_to_iomap(struct xfs_inode *, struct iomap *, struct xfs_bmbt_irec *); +extern struct iomap_ops xfs_iomap_ops; + #endif /* __XFS_IOMAP_H__*/ diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 1a5ca4b..5d1fdae 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -38,6 +38,7 @@ #include "xfs_dir2.h" #include "xfs_trans_space.h" #include "xfs_pnfs.h" +#include "xfs_iomap.h" #include #include @@ -822,8 +823,8 @@ xfs_setattr_size( error = dax_truncate_page(inode, newsize, xfs_get_blocks_direct); } else { - error = block_truncate_page(inode->i_mapping, newsize, - xfs_get_blocks); + error = iomap_truncate_page(inode, newsize, + &did_zeroing, &xfs_iomap_ops); } } @@ -838,8 +839,8 @@ xfs_setattr_size( * problem. Note that this includes any block zeroing we did above; * otherwise those blocks may not be zeroed after a crash. */ - if (newsize > ip->i_d.di_size && - (oldsize != ip->i_d.di_size || did_zeroing)) { + if (did_zeroing || + (newsize > ip->i_d.di_size && oldsize != ip->i_d.di_size)) { error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ip->i_d.di_size, newsize); if (error) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index ea94ee0..bb24ce7 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1295,6 +1295,9 @@ DEFINE_IOMAP_EVENT(xfs_map_blocks_alloc); DEFINE_IOMAP_EVENT(xfs_get_blocks_found); DEFINE_IOMAP_EVENT(xfs_get_blocks_alloc); DEFINE_IOMAP_EVENT(xfs_get_blocks_map_direct); +DEFINE_IOMAP_EVENT(xfs_iomap_alloc); +DEFINE_IOMAP_EVENT(xfs_iomap_found); +DEFINE_IOMAP_EVENT(xfs_iomap_not_found); DECLARE_EVENT_CLASS(xfs_simple_io_class, TP_PROTO(struct xfs_inode *ip, xfs_off_t offset, ssize_t count), -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 557ED7CD0 for ; Wed, 1 Jun 2016 09:45:22 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id D35E1AC006 for ; Wed, 1 Jun 2016 07:45:21 -0700 (PDT) X-ASG-Debug-ID: 1464792319-04cbb0356bae38a0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id 4c7OHGFeZjAaHOnq (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:19 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87OY-0006nB-Tk; Wed, 01 Jun 2016 14:45:19 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 07/14] xfs: remove buffered write support from __xfs_get_blocks Date: Wed, 1 Jun 2016 16:44:50 +0200 X-ASG-Orig-Subj: [PATCH 07/14] xfs: remove buffered write support from __xfs_get_blocks Message-Id: <1464792297-13185-8-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792319 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4076 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Signed-off-by: Christoph Hellwig Reviewed-by: Bob Peterson --- fs/xfs/xfs_aops.c | 71 +++++++++++++++---------------------------------------- 1 file changed, 19 insertions(+), 52 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 2ac9f7e..80714eb 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1143,6 +1143,8 @@ __xfs_get_blocks( ssize_t size; int new = 0; + BUG_ON(create && !direct); + if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; @@ -1150,22 +1152,14 @@ __xfs_get_blocks( ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); size = bh_result->b_size; - if (!create && direct && offset >= i_size_read(inode)) + if (!create && offset >= i_size_read(inode)) return 0; /* * Direct I/O is usually done on preallocated files, so try getting - * a block mapping without an exclusive lock first. For buffered - * writes we already have the exclusive iolock anyway, so avoiding - * a lock roundtrip here by taking the ilock exclusive from the - * beginning is a useful micro optimization. + * a block mapping without an exclusive lock first. */ - if (create && !direct) { - lockmode = XFS_ILOCK_EXCL; - xfs_ilock(ip, lockmode); - } else { - lockmode = xfs_ilock_data_map_shared(ip); - } + lockmode = xfs_ilock_data_map_shared(ip); ASSERT(offset <= mp->m_super->s_maxbytes); if (offset + size > mp->m_super->s_maxbytes) @@ -1184,37 +1178,19 @@ __xfs_get_blocks( (imap.br_startblock == HOLESTARTBLOCK || imap.br_startblock == DELAYSTARTBLOCK) || (IS_DAX(inode) && ISUNWRITTEN(&imap)))) { - if (direct || xfs_get_extsz_hint(ip)) { - /* - * xfs_iomap_write_direct() expects the shared lock. It - * is unlocked on return. - */ - if (lockmode == XFS_ILOCK_EXCL) - xfs_ilock_demote(ip, lockmode); - - error = xfs_iomap_write_direct(ip, offset, size, - &imap, nimaps); - if (error) - return error; - new = 1; + /* + * xfs_iomap_write_direct() expects the shared lock. It + * is unlocked on return. + */ + if (lockmode == XFS_ILOCK_EXCL) + xfs_ilock_demote(ip, lockmode); - } else { - /* - * Delalloc reservations do not require a transaction, - * we can go on without dropping the lock here. If we - * are allocating a new delalloc block, make sure that - * we set the new flag so that we mark the buffer new so - * that we know that it is newly allocated if the write - * fails. - */ - if (nimaps && imap.br_startblock == HOLESTARTBLOCK) - new = 1; - error = xfs_iomap_write_delay(ip, offset, size, &imap); - if (error) - goto out_unlock; + error = xfs_iomap_write_direct(ip, offset, size, + &imap, nimaps); + if (error) + return error; + new = 1; - xfs_iunlock(ip, lockmode); - } trace_xfs_get_blocks_alloc(ip, offset, size, ISUNWRITTEN(&imap) ? XFS_IO_UNWRITTEN : XFS_IO_DELALLOC, &imap); @@ -1235,9 +1211,7 @@ __xfs_get_blocks( } /* trim mapping down to size requested */ - if (direct || size > (1 << inode->i_blkbits)) - xfs_map_trim_size(inode, iblock, bh_result, - &imap, offset, size); + xfs_map_trim_size(inode, iblock, bh_result, &imap, offset, size); /* * For unwritten extents do not report a disk address in the buffered @@ -1250,7 +1224,7 @@ __xfs_get_blocks( if (ISUNWRITTEN(&imap)) set_buffer_unwritten(bh_result); /* direct IO needs special help */ - if (create && direct) { + if (create) { if (dax_fault) ASSERT(!ISUNWRITTEN(&imap)); else @@ -1279,14 +1253,7 @@ __xfs_get_blocks( (new || ISUNWRITTEN(&imap)))) set_buffer_new(bh_result); - if (imap.br_startblock == DELAYSTARTBLOCK) { - BUG_ON(direct); - if (create) { - set_buffer_uptodate(bh_result); - set_buffer_mapped(bh_result); - set_buffer_delay(bh_result); - } - } + BUG_ON(direct && imap.br_startblock == DELAYSTARTBLOCK); return 0; -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 965C77CA4 for ; Wed, 1 Jun 2016 09:45:24 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 57828304071 for ; Wed, 1 Jun 2016 07:45:24 -0700 (PDT) X-ASG-Debug-ID: 1464792321-04bdf05ad7ae5f80001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id S0GbjwtCs7pLq1F3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:22 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87Ob-0006o8-Gl; Wed, 01 Jun 2016 14:45:21 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 08/14] fs: iomap based fiemap implementation Date: Wed, 1 Jun 2016 16:44:51 +0200 X-ASG-Orig-Subj: [PATCH 08/14] fs: iomap based fiemap implementation Message-Id: <1464792297-13185-9-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792322 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3176 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Add a simple fiemap implementation based on iomap_ops, partially based on a previous implementation from Bob Peterson . Signed-off-by: Christoph Hellwig --- fs/iomap.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/iomap.h | 3 ++ 2 files changed, 93 insertions(+) diff --git a/fs/iomap.c b/fs/iomap.c index e51adb6..e874c78 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -405,3 +405,93 @@ out_unlock: return ret; } EXPORT_SYMBOL_GPL(iomap_page_mkwrite); + +struct fiemap_ctx { + struct fiemap_extent_info *fi; + struct iomap prev; +}; + +static int iomap_to_fiemap(struct fiemap_extent_info *fi, + struct iomap *iomap, u32 flags) +{ + switch (iomap->type) { + case IOMAP_HOLE: + /* skip holes */ + return 0; + case IOMAP_DELALLOC: + flags |= FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN; + break; + case IOMAP_UNWRITTEN: + flags |= FIEMAP_EXTENT_UNWRITTEN; + break; + case IOMAP_MAPPED: + break; + } + + return fiemap_fill_next_extent(fi, iomap->offset, + iomap->blkno != IOMAP_NULL_BLOCK ? iomap->blkno << 9: 0, + iomap->length, flags | FIEMAP_EXTENT_MERGED); + +} + +static loff_t +iomap_fiemap_actor(struct inode *inode, loff_t pos, loff_t length, void *data, + struct iomap *iomap) +{ + struct fiemap_ctx *ctx = data; + loff_t ret = length; + + if (iomap->type == IOMAP_HOLE) + return length; + + ret = iomap_to_fiemap(ctx->fi, &ctx->prev, 0); + ctx->prev = *iomap; + switch (ret) { + case 0: /* success */ + return length; + case 1: /* extent array full */ + return 0; + default: + return ret; + } +} + +int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fi, + loff_t start, loff_t len, struct iomap_ops *ops) +{ + struct fiemap_ctx ctx; + loff_t ret; + + memset(&ctx, 0, sizeof(ctx)); + ctx.fi = fi; + ctx.prev.type = IOMAP_HOLE; + + ret = fiemap_check_flags(fi, FIEMAP_FLAG_SYNC); + if (ret) + return ret; + + ret = filemap_write_and_wait(inode->i_mapping); + if (ret) + return ret; + + while (len > 0) { + ret = iomap_apply(inode, start, len, 0, ops, &ctx, + iomap_fiemap_actor); + if (ret < 0) + return ret; + if (ret == 0) + break; + + start += ret; + len -= ret; + } + + if (ctx.prev.type != IOMAP_HOLE) { + ret = iomap_to_fiemap(fi, &ctx.prev, FIEMAP_EXTENT_LAST); + if (ret < 0) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(iomap_fiemap); diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 854766f..b3deee1 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -3,6 +3,7 @@ #include +struct fiemap_extent_info; struct inode; struct iov_iter; struct kiocb; @@ -63,5 +64,7 @@ int iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero, struct iomap_ops *ops); int iomap_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf, struct iomap_ops *ops); +int iomap_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + loff_t start, loff_t len, struct iomap_ops *ops); #endif /* LINUX_IOMAP_H */ -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0A5537CDA for ; Wed, 1 Jun 2016 09:45:28 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 79220AC001 for ; Wed, 1 Jun 2016 07:45:27 -0700 (PDT) X-ASG-Debug-ID: 1464792324-04cb6c2dbaace130001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id dRYS5aU5WmguDVbP (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:25 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87Oe-0006pE-35; Wed, 01 Jun 2016 14:45:24 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 09/14] xfs: use iomap fiemap implementation Date: Wed, 1 Jun 2016 16:44:52 +0200 X-ASG-Orig-Subj: [PATCH 09/14] xfs: use iomap fiemap implementation Message-Id: <1464792297-13185-10-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792325 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3301 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Note that this removes support for the untested FIEMAP_FLAG_XATTR. It could be added relatively easily with iomap ops for the attr fork, but without test coverage I don't feel safe doing this. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_iops.c | 80 ++++--------------------------------------------------- 1 file changed, 5 insertions(+), 75 deletions(-) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 5d1fdae..985a263 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #include /* @@ -1004,51 +1004,6 @@ xfs_vn_update_time( return xfs_trans_commit(tp); } -#define XFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR) - -/* - * Call fiemap helper to fill in user data. - * Returns positive errors to xfs_getbmap. - */ -STATIC int -xfs_fiemap_format( - void **arg, - struct getbmapx *bmv, - int *full) -{ - int error; - struct fiemap_extent_info *fieinfo = *arg; - u32 fiemap_flags = 0; - u64 logical, physical, length; - - /* Do nothing for a hole */ - if (bmv->bmv_block == -1LL) - return 0; - - logical = BBTOB(bmv->bmv_offset); - physical = BBTOB(bmv->bmv_block); - length = BBTOB(bmv->bmv_length); - - if (bmv->bmv_oflags & BMV_OF_PREALLOC) - fiemap_flags |= FIEMAP_EXTENT_UNWRITTEN; - else if (bmv->bmv_oflags & BMV_OF_DELALLOC) { - fiemap_flags |= (FIEMAP_EXTENT_DELALLOC | - FIEMAP_EXTENT_UNKNOWN); - physical = 0; /* no block yet */ - } - if (bmv->bmv_oflags & BMV_OF_LAST) - fiemap_flags |= FIEMAP_EXTENT_LAST; - - error = fiemap_fill_next_extent(fieinfo, logical, physical, - length, fiemap_flags); - if (error > 0) { - error = 0; - *full = 1; /* user array now full */ - } - - return error; -} - STATIC int xfs_vn_fiemap( struct inode *inode, @@ -1056,38 +1011,13 @@ xfs_vn_fiemap( u64 start, u64 length) { - xfs_inode_t *ip = XFS_I(inode); - struct getbmapx bm; int error; - error = fiemap_check_flags(fieinfo, XFS_FIEMAP_FLAGS); - if (error) - return error; - - /* Set up bmap header for xfs internal routine */ - bm.bmv_offset = BTOBBT(start); - /* Special case for whole file */ - if (length == FIEMAP_MAX_OFFSET) - bm.bmv_length = -1LL; - else - bm.bmv_length = BTOBB(start + length) - bm.bmv_offset; - - /* We add one because in getbmap world count includes the header */ - bm.bmv_count = !fieinfo->fi_extents_max ? MAXEXTNUM : - fieinfo->fi_extents_max + 1; - bm.bmv_count = min_t(__s32, bm.bmv_count, - (PAGE_SIZE * 16 / sizeof(struct getbmapx))); - bm.bmv_iflags = BMV_IF_PREALLOC | BMV_IF_NO_HOLES; - if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) - bm.bmv_iflags |= BMV_IF_ATTRFORK; - if (!(fieinfo->fi_flags & FIEMAP_FLAG_SYNC)) - bm.bmv_iflags |= BMV_IF_DELALLOC; - - error = xfs_getbmap(ip, &bm, xfs_fiemap_format, fieinfo); - if (error) - return error; + xfs_ilock(XFS_I(inode), XFS_IOLOCK_SHARED); + error = iomap_fiemap(inode, fieinfo, start, length, &xfs_iomap_ops); + xfs_iunlock(XFS_I(inode), XFS_IOLOCK_SHARED); - return 0; + return error; } STATIC int -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 7F2247CDA for ; Wed, 1 Jun 2016 09:45:29 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 13885AC002 for ; Wed, 1 Jun 2016 07:45:28 -0700 (PDT) X-ASG-Debug-ID: 1464792327-04bdf05ad5ae5f80001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id 08GoCCUj0MXOHPAb (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:27 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87Og-0006qY-Kk; Wed, 01 Jun 2016 14:45:27 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 10/14] xfs: use iomap infrastructure for DAX zeroing Date: Wed, 1 Jun 2016 16:44:53 +0200 X-ASG-Orig-Subj: [PATCH 10/14] xfs: use iomap infrastructure for DAX zeroing Message-Id: <1464792297-13185-11-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792327 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2033 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 35 +---------------------------------- fs/xfs/xfs_iops.c | 9 ++------- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 7316d38..090a90f 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -80,34 +80,6 @@ xfs_rw_ilock_demote( inode_unlock(VFS_I(ip)); } -static int -xfs_dax_zero_range( - struct inode *inode, - loff_t pos, - size_t count) -{ - int status = 0; - - do { - unsigned offset, bytes; - - offset = (pos & (PAGE_SIZE -1)); /* Within page */ - bytes = PAGE_SIZE - offset; - if (bytes > count) - bytes = count; - - status = dax_zero_page_range(inode, pos, bytes, - xfs_get_blocks_direct); - if (status) - break; - - pos += bytes; - count -= bytes; - } while (count); - - return status; -} - /* * Clear the specified ranges to zero through either the pagecache or DAX. * Holes and unwritten extents will be left as-is as they already are zeroed. @@ -118,12 +90,7 @@ xfs_iozero( loff_t pos, size_t count) { - struct inode *inode = VFS_I(ip); - - if (IS_DAX(VFS_I(ip))) - return xfs_dax_zero_range(inode, pos, count); - else - return iomap_zero_range(inode, pos, count, NULL, &xfs_iomap_ops); + return iomap_zero_range(VFS_I(ip), pos, count, NULL, &xfs_iomap_ops); } int diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 985a263..ab820f8 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -819,13 +819,8 @@ xfs_setattr_size( if (newsize > oldsize) { error = xfs_zero_eof(ip, newsize, oldsize, &did_zeroing); } else { - if (IS_DAX(inode)) { - error = dax_truncate_page(inode, newsize, - xfs_get_blocks_direct); - } else { - error = iomap_truncate_page(inode, newsize, - &did_zeroing, &xfs_iomap_ops); - } + error = iomap_truncate_page(inode, newsize, &did_zeroing, + &xfs_iomap_ops); } if (error) -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9E0BB7CBB for ; Wed, 1 Jun 2016 09:45:31 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 62398304066 for ; Wed, 1 Jun 2016 07:45:31 -0700 (PDT) X-ASG-Debug-ID: 1464792329-04bdf05ad7ae5f90001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id UvzZWNHhICrPzRaM (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:29 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87Oj-0006rr-6W; Wed, 01 Jun 2016 14:45:29 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 11/14] xfs: handle 64-bit length in xfs_iozero Date: Wed, 1 Jun 2016 16:44:54 +0200 X-ASG-Orig-Subj: [PATCH 11/14] xfs: handle 64-bit length in xfs_iozero Message-Id: <1464792297-13185-12-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792329 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2038 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 We'll want to use this code for large offsets now that we're skipping holes and unwritten extents efficiently. Also rename it to xfs_zero_range to be a bit more descriptive, and tell the caller if we actually did any zeroing. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 11 ++++++----- fs/xfs/xfs_inode.h | 3 ++- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 090a90f..294e5f4 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -85,10 +85,11 @@ xfs_rw_ilock_demote( * Holes and unwritten extents will be left as-is as they already are zeroed. */ int -xfs_iozero( +xfs_zero_range( struct xfs_inode *ip, - loff_t pos, - size_t count) + xfs_off_t pos, + xfs_off_t count, + bool *did_zero) { return iomap_zero_range(VFS_I(ip), pos, count, NULL, &xfs_iomap_ops); } @@ -419,7 +420,7 @@ xfs_zero_last_block( if (isize + zero_len > offset) zero_len = offset - isize; *did_zeroing = true; - return xfs_iozero(ip, isize, zero_len); + return xfs_zero_range(ip, isize, zero_len, NULL); } /* @@ -518,7 +519,7 @@ xfs_zero_eof( if ((zero_off + zero_len) > offset) zero_len = offset - zero_off; - error = xfs_iozero(ip, zero_off, zero_len); + error = xfs_zero_range(ip, zero_off, zero_len, NULL); if (error) return error; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index e52d7c7..dbb0bcf 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -434,7 +434,8 @@ int xfs_update_prealloc_flags(struct xfs_inode *ip, enum xfs_prealloc_flags flags); int xfs_zero_eof(struct xfs_inode *ip, xfs_off_t offset, xfs_fsize_t isize, bool *did_zeroing); -int xfs_iozero(struct xfs_inode *ip, loff_t pos, size_t count); +int xfs_zero_range(struct xfs_inode *ip, xfs_off_t pos, xfs_off_t count, + bool *did_zero); loff_t __xfs_seek_hole_data(struct inode *inode, loff_t start, loff_t eof, int whence); -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C6A157CA7 for ; Wed, 1 Jun 2016 09:45:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 9B186304066 for ; Wed, 1 Jun 2016 07:45:34 -0700 (PDT) X-ASG-Debug-ID: 1464792332-04cb6c2dbbace150001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id GoKAdlD5bY2MJNxR (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:32 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87Ol-0006sv-O6; Wed, 01 Jun 2016 14:45:32 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 12/14] xfs: use xfs_zero_range in xfs_zero_eof Date: Wed, 1 Jun 2016 16:44:55 +0200 X-ASG-Orig-Subj: [PATCH 12/14] xfs: use xfs_zero_range in xfs_zero_eof Message-Id: <1464792297-13185-13-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792332 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4648 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 We now skip holes in it, so no need to have the caller do it as well. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 128 +----------------------------------------------------- 1 file changed, 1 insertion(+), 127 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 294e5f4..713991c 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -381,49 +381,6 @@ out: } /* - * This routine is called to handle zeroing any space in the last block of the - * file that is beyond the EOF. We do this since the size is being increased - * without writing anything to that block and we don't want to read the - * garbage on the disk. - */ -STATIC int /* error (positive) */ -xfs_zero_last_block( - struct xfs_inode *ip, - xfs_fsize_t offset, - xfs_fsize_t isize, - bool *did_zeroing) -{ - struct xfs_mount *mp = ip->i_mount; - xfs_fileoff_t last_fsb = XFS_B_TO_FSBT(mp, isize); - int zero_offset = XFS_B_FSB_OFFSET(mp, isize); - int zero_len; - int nimaps = 1; - int error = 0; - struct xfs_bmbt_irec imap; - - xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_bmapi_read(ip, last_fsb, 1, &imap, &nimaps, 0); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - if (error) - return error; - - ASSERT(nimaps > 0); - - /* - * If the block underlying isize is just a hole, then there - * is nothing to zero. - */ - if (imap.br_startblock == HOLESTARTBLOCK) - return 0; - - zero_len = mp->m_sb.sb_blocksize - zero_offset; - if (isize + zero_len > offset) - zero_len = offset - isize; - *did_zeroing = true; - return xfs_zero_range(ip, isize, zero_len, NULL); -} - -/* * Zero any on disk space between the current EOF and the new, larger EOF. * * This handles the normal case of zeroing the remainder of the last block in @@ -441,94 +398,11 @@ xfs_zero_eof( xfs_fsize_t isize, /* current inode size */ bool *did_zeroing) { - struct xfs_mount *mp = ip->i_mount; - xfs_fileoff_t start_zero_fsb; - xfs_fileoff_t end_zero_fsb; - xfs_fileoff_t zero_count_fsb; - xfs_fileoff_t last_fsb; - xfs_fileoff_t zero_off; - xfs_fsize_t zero_len; - int nimaps; - int error = 0; - struct xfs_bmbt_irec imap; - ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); ASSERT(offset > isize); trace_xfs_zero_eof(ip, isize, offset - isize); - - /* - * First handle zeroing the block on which isize resides. - * - * We only zero a part of that block so it is handled specially. - */ - if (XFS_B_FSB_OFFSET(mp, isize) != 0) { - error = xfs_zero_last_block(ip, offset, isize, did_zeroing); - if (error) - return error; - } - - /* - * Calculate the range between the new size and the old where blocks - * needing to be zeroed may exist. - * - * To get the block where the last byte in the file currently resides, - * we need to subtract one from the size and truncate back to a block - * boundary. We subtract 1 in case the size is exactly on a block - * boundary. - */ - last_fsb = isize ? XFS_B_TO_FSBT(mp, isize - 1) : (xfs_fileoff_t)-1; - start_zero_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)isize); - end_zero_fsb = XFS_B_TO_FSBT(mp, offset - 1); - ASSERT((xfs_sfiloff_t)last_fsb < (xfs_sfiloff_t)start_zero_fsb); - if (last_fsb == end_zero_fsb) { - /* - * The size was only incremented on its last block. - * We took care of that above, so just return. - */ - return 0; - } - - ASSERT(start_zero_fsb <= end_zero_fsb); - while (start_zero_fsb <= end_zero_fsb) { - nimaps = 1; - zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; - - xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_bmapi_read(ip, start_zero_fsb, zero_count_fsb, - &imap, &nimaps, 0); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - if (error) - return error; - - ASSERT(nimaps > 0); - - if (imap.br_state == XFS_EXT_UNWRITTEN || - imap.br_startblock == HOLESTARTBLOCK) { - start_zero_fsb = imap.br_startoff + imap.br_blockcount; - ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); - continue; - } - - /* - * There are blocks we need to zero. - */ - zero_off = XFS_FSB_TO_B(mp, start_zero_fsb); - zero_len = XFS_FSB_TO_B(mp, imap.br_blockcount); - - if ((zero_off + zero_len) > offset) - zero_len = offset - zero_off; - - error = xfs_zero_range(ip, zero_off, zero_len, NULL); - if (error) - return error; - - *did_zeroing = true; - start_zero_fsb = imap.br_startoff + imap.br_blockcount; - ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); - } - - return 0; + return xfs_zero_range(ip, isize, offset - isize, did_zeroing); } /* -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1E53B7CA4 for ; Wed, 1 Jun 2016 09:45:39 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8CE2CAC001 for ; Wed, 1 Jun 2016 07:45:38 -0700 (PDT) X-ASG-Debug-ID: 1464792334-04cb6c2db9ace150001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id xQddjXVyD7rAOCx2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:35 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87Oo-0006u2-AF; Wed, 01 Jun 2016 14:45:34 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 13/14] xfs: split xfs_free_file_space in manageable pieces Date: Wed, 1 Jun 2016 16:44:56 +0200 X-ASG-Orig-Subj: [PATCH 13/14] xfs: split xfs_free_file_space in manageable pieces Message-Id: <1464792297-13185-14-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792335 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8171 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_bmap_util.c | 252 +++++++++++++++++++++++++++---------------------- 1 file changed, 137 insertions(+), 115 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 586bb64..e36664f 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1184,30 +1184,132 @@ xfs_zero_remaining_bytes( return error; } +static int +xfs_unmap_extent( + struct xfs_inode *ip, + xfs_fileoff_t startoffset_fsb, + xfs_filblks_t len_fsb, + int *done) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + struct xfs_bmap_free free_list; + xfs_fsblock_t firstfsb; + uint resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); + int error; + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); + if (error) { + ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp)); + return error; + } + + xfs_ilock(ip, XFS_ILOCK_EXCL); + error = xfs_trans_reserve_quota(tp, mp, ip->i_udquot, ip->i_gdquot, + ip->i_pdquot, resblks, 0, XFS_QMOPT_RES_REGBLKS); + if (error) + goto out_trans_cancel; + + xfs_trans_ijoin(tp, ip, 0); + + xfs_bmap_init(&free_list, &firstfsb); + error = xfs_bunmapi(tp, ip, startoffset_fsb, len_fsb, 0, 2, &firstfsb, + &free_list, done); + if (error) + goto out_bmap_cancel; + + error = xfs_bmap_finish(&tp, &free_list, NULL); + if (error) + goto out_bmap_cancel; + + error = xfs_trans_commit(tp); +out_unlock: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return error; + +out_bmap_cancel: + xfs_bmap_cancel(&free_list); +out_trans_cancel: + xfs_trans_cancel(tp); + goto out_unlock; +} + +static int +xfs_adjust_extent_unmap_boundaries( + struct xfs_inode *ip, + xfs_fileoff_t *startoffset_fsb, + xfs_fileoff_t *endoffset_fsb) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_bmbt_irec imap; + int nimap, error; + xfs_extlen_t mod = 0; + + nimap = 1; + error = xfs_bmapi_read(ip, *startoffset_fsb, 1, &imap, &nimap, 0); + if (error) + return error; + + if (nimap && imap.br_startblock != HOLESTARTBLOCK) { + xfs_daddr_t block; + + ASSERT(imap.br_startblock != DELAYSTARTBLOCK); + block = imap.br_startblock; + mod = do_div(block, mp->m_sb.sb_rextsize); + if (mod) + *startoffset_fsb += mp->m_sb.sb_rextsize - mod; + } + + nimap = 1; + error = xfs_bmapi_read(ip, *endoffset_fsb - 1, 1, &imap, &nimap, 0); + if (error) + return error; + + if (nimap && imap.br_startblock != HOLESTARTBLOCK) { + ASSERT(imap.br_startblock != DELAYSTARTBLOCK); + mod++; + if (mod && mod != mp->m_sb.sb_rextsize) + *endoffset_fsb -= mod; + } + + return 0; +} + +static int +xfs_flush_unmap_range( + struct xfs_inode *ip, + xfs_off_t offset, + xfs_off_t len) +{ + struct xfs_mount *mp = ip->i_mount; + struct inode *inode = VFS_I(ip); + xfs_off_t rounding, start, end; + int error; + + /* wait for the completion of any pending DIOs */ + inode_dio_wait(inode); + + rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_SIZE); + start = round_down(offset, rounding); + end = round_up(offset + len, rounding) - 1; + + error = filemap_write_and_wait_range(inode->i_mapping, start, end); + if (error) + return error; + truncate_pagecache_range(inode, start, end); + return 0; +} + int xfs_free_file_space( struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len) { - int done; - xfs_fileoff_t endoffset_fsb; - int error; - xfs_fsblock_t firstfsb; - xfs_bmap_free_t free_list; - xfs_bmbt_irec_t imap; - xfs_off_t ioffset; - xfs_off_t iendoffset; - xfs_extlen_t mod=0; - xfs_mount_t *mp; - int nimap; - uint resblks; - xfs_off_t rounding; - int rt; + struct xfs_mount *mp = ip->i_mount; xfs_fileoff_t startoffset_fsb; - xfs_trans_t *tp; - - mp = ip->i_mount; + xfs_fileoff_t endoffset_fsb; + int done, error; trace_xfs_free_file_space(ip); @@ -1215,60 +1317,30 @@ xfs_free_file_space( if (error) return error; - error = 0; if (len <= 0) /* if nothing being freed */ - return error; - rt = XFS_IS_REALTIME_INODE(ip); - startoffset_fsb = XFS_B_TO_FSB(mp, offset); - endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len); - - /* wait for the completion of any pending DIOs */ - inode_dio_wait(VFS_I(ip)); + return 0; - rounding = max_t(xfs_off_t, 1 << mp->m_sb.sb_blocklog, PAGE_SIZE); - ioffset = round_down(offset, rounding); - iendoffset = round_up(offset + len, rounding) - 1; - error = filemap_write_and_wait_range(VFS_I(ip)->i_mapping, ioffset, - iendoffset); + error = xfs_flush_unmap_range(ip, offset, len); if (error) - goto out; - truncate_pagecache_range(VFS_I(ip), ioffset, iendoffset); + return error; + + startoffset_fsb = XFS_B_TO_FSB(mp, offset); + endoffset_fsb = XFS_B_TO_FSBT(mp, offset + len); /* - * Need to zero the stuff we're not freeing, on disk. - * If it's a realtime file & can't use unwritten extents then we - * actually need to zero the extent edges. Otherwise xfs_bunmapi - * will take care of it for us. + * Need to zero the stuff we're not freeing, on disk. If it's a RT file + * and we can't use unwritten extents then we actually need to ensure + * to zero the whole extent, otherwise we just need to take of block + * boundaries, and xfs_bunmapi will handle the rest. */ - if (rt && !xfs_sb_version_hasextflgbit(&mp->m_sb)) { - nimap = 1; - error = xfs_bmapi_read(ip, startoffset_fsb, 1, - &imap, &nimap, 0); + if (XFS_IS_REALTIME_INODE(ip) && + !xfs_sb_version_hasextflgbit(&mp->m_sb)) { + error = xfs_adjust_extent_unmap_boundaries(ip, &startoffset_fsb, + &endoffset_fsb); if (error) - goto out; - ASSERT(nimap == 0 || nimap == 1); - if (nimap && imap.br_startblock != HOLESTARTBLOCK) { - xfs_daddr_t block; - - ASSERT(imap.br_startblock != DELAYSTARTBLOCK); - block = imap.br_startblock; - mod = do_div(block, mp->m_sb.sb_rextsize); - if (mod) - startoffset_fsb += mp->m_sb.sb_rextsize - mod; - } - nimap = 1; - error = xfs_bmapi_read(ip, endoffset_fsb - 1, 1, - &imap, &nimap, 0); - if (error) - goto out; - ASSERT(nimap == 0 || nimap == 1); - if (nimap && imap.br_startblock != HOLESTARTBLOCK) { - ASSERT(imap.br_startblock != DELAYSTARTBLOCK); - mod++; - if (mod && (mod != mp->m_sb.sb_rextsize)) - endoffset_fsb -= mod; - } + return error; } + if ((done = (endoffset_fsb <= startoffset_fsb))) /* * One contiguous piece to clear @@ -1288,62 +1360,12 @@ xfs_free_file_space( offset + len - 1); } - /* - * free file space until done or until there is an error - */ - resblks = XFS_DIOSTRAT_SPACE_RES(mp, 0); while (!error && !done) { - - /* - * allocate and setup the transaction. Allow this - * transaction to dip into the reserve blocks to ensure - * the freeing of the space succeeds at ENOSPC. - */ - error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, - &tp); - if (error) { - ASSERT(error == -ENOSPC || XFS_FORCED_SHUTDOWN(mp)); - break; - } - xfs_ilock(ip, XFS_ILOCK_EXCL); - error = xfs_trans_reserve_quota(tp, mp, - ip->i_udquot, ip->i_gdquot, ip->i_pdquot, - resblks, 0, XFS_QMOPT_RES_REGBLKS); - if (error) - goto error1; - - xfs_trans_ijoin(tp, ip, 0); - - /* - * issue the bunmapi() call to free the blocks - */ - xfs_bmap_init(&free_list, &firstfsb); - error = xfs_bunmapi(tp, ip, startoffset_fsb, - endoffset_fsb - startoffset_fsb, - 0, 2, &firstfsb, &free_list, &done); - if (error) - goto error0; - - /* - * complete the transaction - */ - error = xfs_bmap_finish(&tp, &free_list, NULL); - if (error) - goto error0; - - error = xfs_trans_commit(tp); - xfs_iunlock(ip, XFS_ILOCK_EXCL); + error = xfs_unmap_extent(ip, startoffset_fsb, + endoffset_fsb - startoffset_fsb, &done); } - out: return error; - - error0: - xfs_bmap_cancel(&free_list); - error1: - xfs_trans_cancel(tp); - xfs_iunlock(ip, XFS_ILOCK_EXCL); - goto out; } /* -- 2.1.4 From BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 1 09:45:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 761B57CA4 for ; Wed, 1 Jun 2016 09:45:40 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 49E53304067 for ; Wed, 1 Jun 2016 07:45:40 -0700 (PDT) X-ASG-Debug-ID: 1464792337-04cb6c2dbcace160001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id t7B8la3VCzoWOHl8 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 07:45:38 -0700 (PDT) X-Barracuda-Envelope-From: BATV+56f34be8dd15322694df+4665+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b87Or-0006v5-6Z; Wed, 01 Jun 2016 14:45:37 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: [PATCH 14/14] xfs: kill xfs_zero_remaining_bytes Date: Wed, 1 Jun 2016 16:44:57 +0200 X-ASG-Orig-Subj: [PATCH 14/14] xfs: kill xfs_zero_remaining_bytes Message-Id: <1464792297-13185-15-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> References: <1464792297-13185-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464792338 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4826 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Instead punch the whole first, and the use the our zeroing helper to punch out the edge blocks. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_bmap_util.c | 133 ++++++------------------------------------------- 1 file changed, 14 insertions(+), 119 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index e36664f..569f03d 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1089,101 +1089,6 @@ error1: /* Just cancel transaction */ return error; } -/* - * Zero file bytes between startoff and endoff inclusive. - * The iolock is held exclusive and no blocks are buffered. - * - * This function is used by xfs_free_file_space() to zero - * partial blocks when the range to free is not block aligned. - * When unreserving space with boundaries that are not block - * aligned we round up the start and round down the end - * boundaries and then use this function to zero the parts of - * the blocks that got dropped during the rounding. - */ -STATIC int -xfs_zero_remaining_bytes( - xfs_inode_t *ip, - xfs_off_t startoff, - xfs_off_t endoff) -{ - xfs_bmbt_irec_t imap; - xfs_fileoff_t offset_fsb; - xfs_off_t lastoffset; - xfs_off_t offset; - xfs_buf_t *bp; - xfs_mount_t *mp = ip->i_mount; - int nimap; - int error = 0; - - /* - * Avoid doing I/O beyond eof - it's not necessary - * since nothing can read beyond eof. The space will - * be zeroed when the file is extended anyway. - */ - if (startoff >= XFS_ISIZE(ip)) - return 0; - - if (endoff > XFS_ISIZE(ip)) - endoff = XFS_ISIZE(ip); - - for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { - uint lock_mode; - - offset_fsb = XFS_B_TO_FSBT(mp, offset); - nimap = 1; - - lock_mode = xfs_ilock_data_map_shared(ip); - error = xfs_bmapi_read(ip, offset_fsb, 1, &imap, &nimap, 0); - xfs_iunlock(ip, lock_mode); - - if (error || nimap < 1) - break; - ASSERT(imap.br_blockcount >= 1); - ASSERT(imap.br_startoff == offset_fsb); - ASSERT(imap.br_startblock != DELAYSTARTBLOCK); - - if (imap.br_startblock == HOLESTARTBLOCK || - imap.br_state == XFS_EXT_UNWRITTEN) { - /* skip the entire extent */ - lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + - imap.br_blockcount) - 1; - continue; - } - - lastoffset = XFS_FSB_TO_B(mp, imap.br_startoff + 1) - 1; - if (lastoffset > endoff) - lastoffset = endoff; - - /* DAX can just zero the backing device directly */ - if (IS_DAX(VFS_I(ip))) { - error = dax_zero_page_range(VFS_I(ip), offset, - lastoffset - offset + 1, - xfs_get_blocks_direct); - if (error) - return error; - continue; - } - - error = xfs_buf_read_uncached(XFS_IS_REALTIME_INODE(ip) ? - mp->m_rtdev_targp : mp->m_ddev_targp, - xfs_fsb_to_db(ip, imap.br_startblock), - BTOBB(mp->m_sb.sb_blocksize), - 0, &bp, NULL); - if (error) - return error; - - memset(bp->b_addr + - (offset - XFS_FSB_TO_B(mp, imap.br_startoff)), - 0, lastoffset - offset + 1); - - error = xfs_bwrite(bp); - xfs_buf_relse(bp); - if (error) - return error; - } - return error; -} - static int xfs_unmap_extent( struct xfs_inode *ip, @@ -1309,7 +1214,7 @@ xfs_free_file_space( struct xfs_mount *mp = ip->i_mount; xfs_fileoff_t startoffset_fsb; xfs_fileoff_t endoffset_fsb; - int done, error; + int done = 0, error; trace_xfs_free_file_space(ip); @@ -1341,31 +1246,21 @@ xfs_free_file_space( return error; } - if ((done = (endoffset_fsb <= startoffset_fsb))) - /* - * One contiguous piece to clear - */ - error = xfs_zero_remaining_bytes(ip, offset, offset + len - 1); - else { - /* - * Some full blocks, possibly two pieces to clear - */ - if (offset < XFS_FSB_TO_B(mp, startoffset_fsb)) - error = xfs_zero_remaining_bytes(ip, offset, - XFS_FSB_TO_B(mp, startoffset_fsb) - 1); - if (!error && - XFS_FSB_TO_B(mp, endoffset_fsb) < offset + len) - error = xfs_zero_remaining_bytes(ip, - XFS_FSB_TO_B(mp, endoffset_fsb), - offset + len - 1); - } - - while (!error && !done) { - error = xfs_unmap_extent(ip, startoffset_fsb, - endoffset_fsb - startoffset_fsb, &done); + if (endoffset_fsb > startoffset_fsb) { + while (!done) { + error = xfs_unmap_extent(ip, startoffset_fsb, + endoffset_fsb - startoffset_fsb, &done); + if (error) + return error; + } } - return error; + /* + * Now that we've unmap all full blocks we'll have to zero out any + * partial block at the beginning and/or end. xfs_zero_range is + * smart enough to skip any holes, including those we just created. + */ + return xfs_zero_range(ip, offset, len, NULL); } /* -- 2.1.4 From hch@lst.de Wed Jun 1 09:46:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 44EF77CAE for ; Wed, 1 Jun 2016 09:46:47 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id B3E62AC003 for ; Wed, 1 Jun 2016 07:46:46 -0700 (PDT) X-ASG-Debug-ID: 1464792403-04cb6c2dbaace210001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id TevTSMnY6Aqe9gnE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 07:46:44 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 5AFC268C31; Wed, 1 Jun 2016 16:46:43 +0200 (CEST) Date: Wed, 1 Jun 2016 16:46:43 +0200 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V5 Message-ID: <20160601144643.GA25933@lst.de> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V5 References: <1464792297-13185-1-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1464792404 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 369 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30082 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On Wed, Jun 01, 2016 at 04:44:43PM +0200, Christoph Hellwig wrote: > Note that patch 1 conflicts with Vishals dax error handling series. > It would be great to have a stable branch with it so that both the > XFS and nvdimm tree could pull it in before the other changes in this > area. Please ignore this note - that former patch 1 has been merged in 4.7-rc1. From prvs=396015144F=Ann.Martin@tdsb.on.ca Wed Jun 1 11:43:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: *** X-Spam-Status: No, score=3.8 required=5.0 tests=HTML_MESSAGE,LOTS_OF_MONEY, MILLION_USD autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 69C4D7CA7 for ; Wed, 1 Jun 2016 11:43:25 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id E87BCAC004 for ; Wed, 1 Jun 2016 09:43:24 -0700 (PDT) X-ASG-Debug-ID: 1464799389-04bdf05ad5aea120001-NocioJ Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1bon0063.outbound.protection.outlook.com [157.56.111.63]) by cuda.sgi.com with ESMTP id pnFDaUScxOVh7beW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO); Wed, 01 Jun 2016 09:43:09 -0700 (PDT) X-Barracuda-Envelope-From: prvs=396015144F=Ann.Martin@tdsb.on.ca X-Barracuda-Effective-Source-IP: mail-bn1bon0063.outbound.protection.outlook.com[157.56.111.63] X-Barracuda-Apparent-Source-IP: 157.56.111.63 Received: from BLUPR02CA049.namprd02.prod.outlook.com (10.160.23.167) by CY1PR02MB1200.namprd02.prod.outlook.com (10.163.16.142) with Microsoft SMTP Server (TLS) id 15.1.506.9; Wed, 1 Jun 2016 16:43:07 +0000 Received: from BL2FFO11FD025.protection.gbl (2a01:111:f400:7c09::183) by BLUPR02CA049.outlook.office365.com (2a01:111:e400:8ad::39) with Microsoft SMTP Server (TLS) id 15.1.506.9 via Frontend Transport; Wed, 1 Jun 2016 16:43:07 +0000 Authentication-Results: spf=pass (sender IP is 38.116.192.55) smtp.mailfrom=tdsb.on.ca; yahoo.com; dkim=none (message not signed) header.d=none;yahoo.com; dmarc=bestguesspass action=none header.from=tdsb.on.ca; Received-SPF: Pass (protection.outlook.com: domain of tdsb.on.ca designates 38.116.192.55 as permitted sender) receiver=protection.outlook.com; client-ip=38.116.192.55; helo=tls.tdsb.on.ca; Received: from tls.tdsb.on.ca (38.116.192.55) by BL2FFO11FD025.mail.protection.outlook.com (10.173.161.104) with Microsoft SMTP Server (TLS) id 15.1.497.8 via Frontend Transport; Wed, 1 Jun 2016 16:42:51 +0000 Received: from TDSBHUB1.tdsb.on.ca (172.22.19.104) by TLS.tdsb.on.ca (172.22.200.205) with Microsoft SMTP Server (TLS) id 14.3.235.1; Wed, 1 Jun 2016 12:42:22 -0400 Received: from TDSBMBX14.tdsb.on.ca ([172.22.19.135]) by TDSBHUB1.tdsb.on.ca ([172.22.19.104]) with mapi id 14.03.0235.001; Wed, 1 Jun 2016 12:42:21 -0400 From: "Martin, Ann" To: "Martin, Ann" Subject: RE: NEWS Thread-Topic: NEWS X-ASG-Orig-Subj: RE: NEWS Thread-Index: AQHRvCOxc1qJziQ76Ua3cZLhBC1mjp/U0Cj1 Date: Wed, 1 Jun 2016 16:42:21 +0000 Message-ID: <0E924AF669707E4F8D53D7C204C8D1BF6780FD0B@TDSBMBX14.tdsb.on.ca> References: <0E924AF669707E4F8D53D7C204C8D1BF6780E59C@TDSBMBX14.tdsb.on.ca> In-Reply-To: <0E924AF669707E4F8D53D7C204C8D1BF6780E59C@TDSBMBX14.tdsb.on.ca> Accept-Language: en-CA, en-US Content-Language: en-CA X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.22.39.161] Content-Type: multipart/alternative; boundary="_000_0E924AF669707E4F8D53D7C204C8D1BF6780FD0BTDSBMBX14tdsbon_" MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:38.116.192.55;IPV:CAL;SCL:-1;CTRY:CA;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(189002)(199003)(377454003)(16236675004)(5000100001)(2910100002)(107886002)(106116001)(5001970100001)(3900700001)(74482002)(110136002)(189998001)(16796002)(586003)(33656002)(6200100001)(106466001)(11100500001)(221733001)(3480700004)(92566002)(53416004)(55846006)(2950100001)(2900100001)(512934002)(2920100001)(2940100001)(5004730100002)(77096005)(2906002)(5003600100002)(4001450100002)(19580405001)(19580395003)(6806005)(6116002)(8676002)(87936001)(50986999)(8936002)(84326002)(76176999)(102836003)(3846002)(54356999)(5008740100001)(7099028)(563594002)(571714004)(585564001);DIR:OUT;SFP:1101;SCL:1;SRVR:CY1PR02MB1200;H:tls.tdsb.on.ca;FPR:;SPF:Pass;MLV:nov;MX:1;A:1;PTR:tls.tdsb.on.ca;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;BL2FFO11FD025;1:iUNyZzRgObUwiCXGfX0AzrvW6Lu8MeMlAUUbudB1DAz4imApoRWP83Nt4Ncv0lVoM5zw51uT+XQ7THsXNcBPLMDoT+NjHNWeW3N0ggdkVkjkAQvjSDvURQ+wW2VYwAS4qDRqWdJ6OFiQzh6++5X/N5+D86SUfVqwOG9w1t0i3NB5BbWmuaZuLSDlHGdBR+FI3w+KL9a7iMuftdydpNiQfDo1py78/TySnyv4han0xlYgy+DSSVYmdX2hHdj26vwDlRyyhCcNvuGKBvPks+XldL2hSB9PQAlo8Jx0XuxrFJmE+kUjDa+1Xng7XY8Aw+pkIGZxZ4oMKx6Nudz26myyOxd4Cjcq3j9VSzxGj7G7rsLlbw8FyIaEggTuqJoSz2zCoPVZKjfuhaNHyUCvxczv5n/MG/no9KoHd68k4E9fVxYaAbYBxSPpSjvaUc6ByO9BlgtnGPEZMmt2fk82cLtfglX2qo8FVjz24kZCpub7joStNnK9TA5bd+e+xQtJeuqca68TxYkMoDizZO/UtFU+FUiZK/0h70mQcaYzw6+xYvW92TyX5uxMd/rgfj9z1dfP X-MS-Office365-Filtering-Correlation-Id: 7e1b83ac-60c6-4620-895d-08d38a3bcf37 X-Microsoft-Exchange-Diagnostics: 1;CY1PR02MB1200;2:7Qrbknrdl69/tLrTCp8XcMU4P6WGtv+JX6jwWZ7iYZLA09+jjFHAOUYkZR2IZlDKc8P3TgBF8eQLXL3mN+YQ0+XSGS5L7HYBzaF/Mn02Y2Mr7zGo4pU7UIS7PlgGRaVjc3tILJtg3wZEA/yxNiuewTzaYJ7/R0pR6Q9EHJe/tjRUe0VHl/sLC3Txl91ugpEU;3:04q9urhRT4stnGbjPBhq8wgmoEVfnAwnUn7rv0IvUKxPEkL/rHXgttNy5ENjvHcxM4YucSCS2Q5A4ukn8BJbKZ45LmSW0u4PoxhFUdhs9n/I3Oij7hdNb4oLFY68W/G8XVw7QpE4ladtVxqLT4MQaZ0AoznQoPGLgJ+IUc72rAAQ6wcvuAWKw+Cb6Sf7HGlq4IvNA/cqdkYFB2K3LRSSDo5bubPYJVYmdjL1Aze5YUNG0DyLC+meIWemimz3KNP15XNOKTa2aheN+mdKQ/IOyg==;25:2UvV0hyQBF4qgMy6OEFPKOHi8oDaKzkhyDirxoRQGMuNv0zp/q+taABg5Xme5+Bv2TkksaCvoWyi9U9NwoAsixSE3PSo28hjgHDHCRFieVCPcsMpxFU5JmbefjBRNBSZlgs7+abib0JtXRAwkG3gYI6/TydcbFgmdpAC/pQUVyKDd1tID6ZU/tUd6wFFVLIOhgv+4MDQOQxT9NG2tTNSCnEd/yjyQ8eLrJeTSbnvh5WUOgXaYwiqOxp1qm2yXf3MR7LE3U4uEBw15y2xQAovndE14epSUSBVaDcdcrHG7JXU7W5NW/m34bpzE0WQU3KAInbHA4TpAxx/X1rr361wdyvUCdvEz4KlFiCxSCt9DCCLgVcm5ICbrszcdr3Ml/6qV+wgUxj7B7UoapoGMEPk6G8a4nT/c7SzI3eGPJ05Ye4= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(8251501002);SRVR:CY1PR02MB1200; X-Microsoft-Exchange-Diagnostics: 1;CY1PR02MB1200;20:dF+CZ9iIjEP3piXf2jdQnq46/VuAgHox0zlXeRlKFB2QSMezswggW6689f5pIDQVHuCk+TV8ZxBw/f0813baOJRQ8Kza/FpOXRM5gEjtOM2gdwROaCC5jtk83XbiIHYJuwIcnFBc3WjtzhVl4rJFXynIDVfqzua1b4QfE904hlM=;4:7o5u6GgV7Yg7erFepZPTiXDCaKTSNDmHyvP5AQrqqgFMUAO6Z4m8hyC8oEPR4grB405fWJlPnI+YEobUrz4S3xN/WZHMi4bA88If9YTTzf1fdTgPJiC5WufrPavwoUGzyc3UMNQSUX58km1OBmowcaR4VQDmwdKHRnMhxZ6vuisOeK95kwH6Z8GUQXoddjj4tHSJfEuGm7u9ANJhpddcVOmNHjzJBhsM5F+UG3TJw1zkIGMAMhnCsI3CppZ6AExPaN7VQJJm+4RjNQyT65wBlwnQZaUFkV99dU2tK9mwkUdhIFpxxHh2T1ujqcPJy0Gy9JzsLrdcxY8tXYKRxJmu4qtDULOdV5n/XhXcdelSFaYx1NRx/un8GQQLnZlnx3LmMw/wPf2bkd1Zp4wt5++U2g9lqEvEYLyjlzV0rPY6sVoMiOdArpp3lxz0+cnvKfA+v9oLEcooU1KiX9JT03hhJwQENVxm7d8CpLxNtlFDgjo= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(130843839470238); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(8121501046)(13023025)(5005006)(13024025)(13013025)(13020025)(3002001)(10201501046);SRVR:CY1PR02MB1200;BCL:0;PCL:0;RULEID:;SRVR:CY1PR02MB1200; X-Forefront-PRVS: 096029FF66 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;CY1PR02MB1200;23:hi9q45GwNvaBAi1PXFSKeR5Iil7BYp9JNRNgnv2D0?= =?us-ascii?Q?IoUpFQh26d7k8+2sJKXmK6qDIblo/NcNG4qlp7ybYjkwJ/kDmyU7/XNDDic0?= =?us-ascii?Q?9tLIL5mKfmKNWcVOozVjaq9ofTIrpvbTR4o8WQU0grf78ClyhHsQ0NirxG2e?= =?us-ascii?Q?b/rMl3N7KnTZMQRjTxxZPS6QLN9qyY7HV4/t/XCsFbfm+FEZKPvChSTkJyg3?= =?us-ascii?Q?e+g+lhQcZ8g5MudasPKUARZCNMbqT3V09bKg76RVdB9sYevj8Rq1E4ixE4/2?= =?us-ascii?Q?yT1A/22eZyiBKyQ08IqlOVljQRoXACjoebOmSXlnxSKxnx6aKelmjA6kMrnz?= =?us-ascii?Q?jdD7r7+ExfnG6mKkfV1eN+4xPJg1K/jPd5r0dBW6cTb6MqN+N8wiLIAj+XY/?= =?us-ascii?Q?0kk5sRuUuRecJrTxPKaAtrxH8iNKSglDjR/EMWu0xisu48LvGE54QYG5k4P5?= =?us-ascii?Q?cCBDhVe0wLL70+37MHZesQgMVTxLnZcnkqs0Ln+INr3EZWWaF3132o5zUSiA?= =?us-ascii?Q?VioVMGY007RrM30ZzEYoBCc2rGKlx2F1QPLdqSOjFUbG96K+1wKMFR1vt7IW?= =?us-ascii?Q?VkTRJzGfkHxgho7v7e4TOapw+O20lDyUZFZn+C9VlobuqkpJDJei5OXZdfB7?= =?us-ascii?Q?CuKe/DP0wmiTEYfdAPgklB4fKtjZ+c2uuqAkcnD3NlzDpPCvnlm+jRKA0Uep?= =?us-ascii?Q?4RqPCvNi/dpVhRRpwrsmAe5pL/Y2c90MGJbB9ua9bx4va71YPjUtAmCLxKh6?= =?us-ascii?Q?H4YtfW5YduXSCRZPBDxiC4bI8DJzINeMlTIjjrDHNmjr3He7zZFFpptkHLgm?= =?us-ascii?Q?leLVoo+ufgxlncKTRlGKhglO1joN89y3PD6ZZR7/ZTxJtnxSoXs0KVCBObY7?= =?us-ascii?Q?B3N4qjKl88VjytRRckJuNCE89Vsb7Bh4nm8QJCkQwfveFuZRy1wpDDyE1IkX?= =?us-ascii?Q?YNDITet5Wl7Z1tPvk5cGLwi49lHjUMfZMohvnuQarO+WlPddeMRd9q5HxKFR?= =?us-ascii?Q?YjZTnSH7Yx6Bn2tcBz8dY5FgHWaM9UUPIDtZyNdUc6Ti4CccwMAhm9lzFwHM?= =?us-ascii?Q?kasxScE7osGLrhdxujrgwRp0HGLedsJ0rUIUG+v9n2gB62V1NhlZSOu10jYb?= =?us-ascii?Q?O8X+jMM/yq+6mviIOcY8YjS1cHCvaNPReULu0A01jZMrF/gOlBd5UGHCLOwL?= =?us-ascii?Q?XRbzjjgPShMjgFB0SOqzHY9IidOKS9iV/pkmHRVo3nSS3M1Jd9rxIIBXPZ0A?= =?us-ascii?Q?F9rVSsr3lE4pdNe2PmBdgHvEvwkD6NPkedKQm29AHp7jGVpiMios7np2sbgA?= =?us-ascii?Q?2BC8AuiTwj338OZ8lnrbfsak3UAgeMg3cBX7znHZ/ssMN2EIQliTVZi/a7Ym?= =?us-ascii?Q?1BlnSqPTakXaTlhyTIJD8vP4eC6eOExbeJyE+WA0RLCidXauTcQmjEQrAcql?= =?us-ascii?Q?XjgH8+jOEaBya/XgS0EtM84pqAnCUE=3D?= X-Microsoft-Exchange-Diagnostics: 1;CY1PR02MB1200;5:fmQC1VcNBYUuyVKKQ8y+PJVz+2PhgWz5KJIh5x1wsyPcZMAseY5/ClTp5cpfRU7nIedzAaiI5hSr0LKIfOsHh2lJQfSJK3cI5WxLrIfk2MGUQMPoWlKBpzbv6CaeynE0mKppJ9OtIr57SsUoFxczPA==;24:p+Ts0+dreZ1lfnA6N9ffJkYxyA08v3CJ5clJyV+XFfc8/TVcZ6A8LvQVH40tDIzVacVk605dCe+p6R7vOKVJtssh2kn4npu1LulB2oxzBuM=;7:SFRpGsExbnRBqPa8s7cttK/SCQMb1jo1Il4jUQK7q707iRDXEKi0zDNvptO2xPam3VAm93hkkUVSfGkJL9HQhTWE+OUIcsRlWVKOtlR6q++cdg7dflcHEHvhnSB4FMAiQoHp6ssoyv6/2xFfurDtGjkpc3bv9ZaMxpZfLfO3n13rlk/v2AoNaG6ZjEVkb3rA SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: tdsb.on.ca X-MS-Exchange-CrossTenant-OriginalArrivalTime: 01 Jun 2016 16:42:51.1046 (UTC) X-MS-Exchange-CrossTenant-Id: c4d72b4d-8155-4a90-9155-7705148c41ca X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=c4d72b4d-8155-4a90-9155-7705148c41ca;Ip=[38.116.192.55];Helo=[tls.tdsb.on.ca] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR02MB1200 X-Barracuda-Connect: mail-bn1bon0063.outbound.protection.outlook.com[157.56.111.63] X-Barracuda-Start-Time: 1464799389 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2507 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.31 X-Barracuda-Spam-Status: No, SCORE=2.31 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=ADVANCE_FEE_1, BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_ADDR_MATCH, HTML_MESSAGE, MILLION_USD, MILLION_USD_2, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30084 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 MILLION_USD BODY: Talks about millions of dollars 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message 0.00 ADVANCE_FEE_1 Appears to be advance fee fraud (Nigerian 419) 0.50 BSF_SC0_SA_TO_FROM_ADDR_MATCH Sender Address Matches Recipient Address 1.78 MILLION_USD_2 Talks about millions of dollars --_000_0E924AF669707E4F8D53D7C204C8D1BF6780FD0BTDSBMBX14tdsbon_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable ________________________________ From: Martin, Ann Sent: June 1, 2016 12:36 PM To: Martin, Ann Subject: NEWS Three Million USD donated to you from Mrs Julie, send email to julialeach@= 163.com For More Information. --_000_0E924AF669707E4F8D53D7C204C8D1BF6780FD0BTDSBMBX14tdsbon_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable

 

From: Martin, Ann
Sent: June 1, 2016 12:36 PM
To: Martin, Ann
Subject: NEWS

Three Million USD donated to you from Mrs Julie, send email to  julialeach@163.com  For More Information.
--_000_0E924AF669707E4F8D53D7C204C8D1BF6780FD0BTDSBMBX14tdsbon_-- From peterz@infradead.org Wed Jun 1 13:16:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 28BBE7CAE for ; Wed, 1 Jun 2016 13:16:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id EEC808F8049 for ; Wed, 1 Jun 2016 11:16:30 -0700 (PDT) X-ASG-Debug-ID: 1464804986-04cb6c2dbbad3ad0001-NocioJ Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by cuda.sgi.com with ESMTP id tdNdbZodHMQE3eof (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 01 Jun 2016 11:16:28 -0700 (PDT) X-Barracuda-Envelope-From: peterz@infradead.org X-Barracuda-Effective-Source-IP: merlin.infradead.org[205.233.59.134] X-Barracuda-Apparent-Source-IP: 205.233.59.134 Received: from j217100.upc-j.chello.nl ([24.132.217.100] helo=twins) by merlin.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1b8Agl-0004sm-13; Wed, 01 Jun 2016 18:16:19 +0000 Received: by twins (Postfix, from userid 1000) id 6BC49101F82E5; Wed, 1 Jun 2016 20:16:17 +0200 (CEST) Date: Wed, 1 Jun 2016 20:16:17 +0200 From: Peter Zijlstra To: Michal Hocko Cc: Dave Chinner , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160601181617.GV3190@twins.programming.kicks-ass.net> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160513160341.GW20141@dhcp22.suse.cz> <20160516104130.GK3193@twins.programming.kicks-ass.net> <20160516130519.GJ23146@dhcp22.suse.cz> <20160516132541.GP3193@twins.programming.kicks-ass.net> <20160516231056.GE18496@dastard> <20160517144912.GZ3193@twins.programming.kicks-ass.net> <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160601131758.GO26601@dhcp22.suse.cz> User-Agent: Mutt/1.5.21 (2012-12-30) X-Barracuda-Connect: merlin.infradead.org[205.233.59.134] X-Barracuda-Start-Time: 1464804988 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4464 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30087 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 01, 2016 at 03:17:58PM +0200, Michal Hocko wrote: > Thanks Dave for your detailed explanation again! Peter do you have any > other idea how to deal with these situations other than opt out from > lockdep reclaim machinery? > > If not I would rather go with an annotation than a gfp flag to be honest > but if you absolutely hate that approach then I will try to check wheter > a CONFIG_LOCKDEP GFP_FOO doesn't break something else. Otherwise I would > steal the description from Dave's email and repost my patch. > > I plan to repost my scope gfp patches in few days and it would be good > to have some mechanism to drop those GFP_NOFS to paper over lockdep > false positives for that. Right; sorry I got side-tracked in other things again. So my favourite is the dedicated GFP flag, but if that's unpalatable for the mm folks then something like the below might work. It should be similar in effect to your proposal, except its more limited in scope. --- include/linux/gfp.h | 5 ++++- include/linux/lockdep.h | 2 ++ kernel/locking/lockdep.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 570383a41853..d6be35643ee7 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -187,7 +187,10 @@ struct vm_area_struct; #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK) #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) -/* Room for N __GFP_FOO bits */ +/* + * Room for N __GFP_FOO bits. + * Fix lockdep's __GFP_SKIP_ALLOC if this ever hits 32. + */ #define __GFP_BITS_SHIFT 26 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h index eabe0138eb06..08a021b1e275 100644 --- a/include/linux/lockdep.h +++ b/include/linux/lockdep.h @@ -354,6 +354,7 @@ static inline void lock_set_subclass(struct lockdep_map *lock, extern void lockdep_set_current_reclaim_state(gfp_t gfp_mask); extern void lockdep_clear_current_reclaim_state(void); +extern void lockdep_skip_alloc(void); extern void lockdep_trace_alloc(gfp_t mask); struct pin_cookie { unsigned int val; }; @@ -398,6 +399,7 @@ static inline void lockdep_on(void) # define lock_set_subclass(l, s, i) do { } while (0) # define lockdep_set_current_reclaim_state(g) do { } while (0) # define lockdep_clear_current_reclaim_state() do { } while (0) +# define lockdep_skip_alloc() do { } while (0) # define lockdep_trace_alloc(g) do { } while (0) # define lockdep_info() do { } while (0) # define lockdep_init_map(lock, name, key, sub) \ diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 589d763a49b3..aa3ccbadc74e 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -2851,6 +2851,13 @@ void trace_softirqs_off(unsigned long ip) debug_atomic_inc(redundant_softirqs_off); } +#define __GFP_SKIP_ALLOC (1UL << __GFP_BITS_SHIFT) + +static void __lockdep_skip_alloc(void) +{ + current->lockdep_reclaim_gfp |= __GFP_SKIP_ALLOC; +} + static void __lockdep_trace_alloc(gfp_t gfp_mask, unsigned long flags) { struct task_struct *curr = current; @@ -2876,11 +2883,36 @@ static void __lockdep_trace_alloc(gfp_t gfp_mask, unsigned long flags) if (DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags))) return; + /* + * Skip _one_ allocation as per the lockdep_skip_alloc() request. + * Must be done last so that we don't loose the annotation for + * GFP_ATOMIC like things from IRQ or other nesting contexts. + */ + if (current->lockdep_reclaim_gfp & __GFP_SKIP_ALLOC) { + current->lockdep_reclaim_gfp &= ~__GFP_SKIP_ALLOC; + return; + } + mark_held_locks(curr, RECLAIM_FS); } static void check_flags(unsigned long flags); +void lockdep_skip_alloc(void) +{ + unsigned long flags; + + if (unlikely(current->lockdep_recursion)) + return; + + raw_local_irq_save(flags); + check_flags(flags); + current->lockdep_recursion = 1; + __lockdep_skip_alloc(); + current->lockdep_recursion = 0; + raw_local_irq_restore(flags); +} + void lockdep_trace_alloc(gfp_t gfp_mask) { unsigned long flags; @@ -3015,6 +3047,10 @@ static inline int separate_irq_context(struct task_struct *curr, return 0; } +void lockdep_skip_alloc(void) +{ +} + void lockdep_trace_alloc(gfp_t gfp_mask) { } From david@fromorbit.com Wed Jun 1 19:27:17 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BEEE07CAE for ; Wed, 1 Jun 2016 19:27:17 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 83C038F8039 for ; Wed, 1 Jun 2016 17:27:14 -0700 (PDT) X-ASG-Debug-ID: 1464827229-04cb6c2dbcadf470001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id ZTo72DUYMpcdgzzm for ; Wed, 01 Jun 2016 17:27:10 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CTDAA3fE9XPGSyLXlegzpWfYJ2g3meegwBAQEBAQEGjCWDWYY2HoVtAgIBAQKBMz0QAQEBAQEBAQYBAQEBQkCERgEBBDocIxAIAw4KCSUPBSUDBxoTiC7BTQEBCAIBJB6FQYUVihoFmDeGAIgWjyZFjwc3gjEcgV0qMop8AQEB Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail05.adl6.internode.on.net with ESMTP; 02 Jun 2016 09:56:54 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8GTN-0000Yj-Bo; Thu, 02 Jun 2016 10:26:53 +1000 Date: Thu, 2 Jun 2016 10:26:53 +1000 From: Dave Chinner To: Daniel Wagner Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com Subject: Re: Internal error xfs_trans_cancel Message-ID: <20160602002653.GL12670@dastard> X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <20160601071047.GJ12670@dastard> <0644b434-6cea-4188-9702-469c26d191b8@monom.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <0644b434-6cea-4188-9702-469c26d191b8@monom.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1464827229 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1804 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30097 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 01, 2016 at 04:13:10PM +0200, Daniel Wagner wrote: > >> Anything in the log before this? > > > > Just the usual stuff, as I remember. Sorry, I haven't copied the whole log. > > Just triggered it again. My steps for it are: > > - run all lockperf test > > git://git.samba.org/jlayton/lockperf.git > > via my test script: > > #!/bin/sh > > run_tests () { ..... > for c in `seq 8 32 128`; do > for l in `seq 100 100 500`; do > time run_tests "posix01 -n $c -l $l " $DIR/posix01-$c-$l.data > time run_tests "posix02 -n $c -l $l " $DIR/posix02-$c-$l.data > time run_tests "posix03 -n $c -l $l " $DIR/posix03-$c-$l.data > time run_tests "posix04 -n $c -l $l " $DIR/posix04-$c-$l.data posix03 and posix04 just emit error messages: posix04 -n 40 -l 100 posix04: invalid option -- 'l' posix04: Usage: posix04 [-i iterations] [-n nr_children] [-s] ..... So I changed them to run "-i $l" instead, and that has a somewhat undesired effect: static void kill_children() { siginfo_t infop; signal(SIGINT, SIG_IGN); >>>>> kill(0, SIGINT); while (waitid(P_ALL, 0, &infop, WEXITED) != -1); } Yeah, it sends a SIGINT to everything with a process group id. It kills the parent shell: $ ./run-lockperf-tests.sh /mnt/scratch/ pid 9597's current affinity list: 0-15 pid 9597's new affinity list: 0,4,8,12 sh: 1: cannot create /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor: Directory nonexistent posix01 -n 8 -l 100 posix02 -n 8 -l 100 posix03 -n 8 -i 100 $ So, I've just removed those tests from your script. I'll see if I have any luck with reproducing the problem now. Cheers, Dave. -- Dave Chinner david@fromorbit.com From ming.lei@canonical.com Wed Jun 1 21:13:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 1D7527CAE for ; Wed, 1 Jun 2016 21:13:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id E2E318F8049 for ; Wed, 1 Jun 2016 19:13:23 -0700 (PDT) X-ASG-Debug-ID: 1464833599-04cb6c2db9ae1350001-NocioJ Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by cuda.sgi.com with ESMTP id wiOfBPfb8mr5uVeK (version=TLSv1 cipher=AES256-SHA bits=256 verify=NO) for ; Wed, 01 Jun 2016 19:13:20 -0700 (PDT) X-Barracuda-Envelope-From: ming.lei@canonical.com X-Barracuda-Effective-Source-IP: youngberry.canonical.com[91.189.89.112] X-Barracuda-Apparent-Source-IP: 91.189.89.112 Received: from mail-yw0-f181.google.com ([209.85.161.181]) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1b8I8N-0005BV-8D for xfs@oss.sgi.com; Thu, 02 Jun 2016 02:13:19 +0000 Received: by mail-yw0-f181.google.com with SMTP id x189so36793542ywe.3 for ; Wed, 01 Jun 2016 19:13:19 -0700 (PDT) X-Gm-Message-State: ALyK8tLpK0YcqOYcPJmLwlv7pW8WOODyLdb3xC/R+kUqIR+8fd2jjNDPf1D8oSE6+NZn/DbltjULP6kuB87mug== MIME-Version: 1.0 X-Received: by 10.129.114.85 with SMTP id n82mr4427422ywc.321.1464833598349; Wed, 01 Jun 2016 19:13:18 -0700 (PDT) Received: by 10.37.216.78 with HTTP; Wed, 1 Jun 2016 19:13:18 -0700 (PDT) In-Reply-To: <20160601135150.GA30759@redhat.com> References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <20160531155348.GA24840@redhat.com> <20160601134427.GA15888@infradead.org> <20160601135150.GA30759@redhat.com> Date: Thu, 2 Jun 2016 10:13:18 +0800 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs From: Ming Lei X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs To: Mike Snitzer Cc: Christoph Hellwig , Jens Axboe , Linux Kernel Mailing List , linux-block@vger.kernel.org, Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: youngberry.canonical.com[91.189.89.112] X-Barracuda-Start-Time: 1464833600 X-Barracuda-Encrypted: AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1800 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30099 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 1, 2016 at 9:51 PM, Mike Snitzer wrote: > On Wed, Jun 01 2016 at 9:44am -0400, > Christoph Hellwig wrote: > >> On Wed, Jun 01, 2016 at 08:38:41PM +0800, Ming Lei wrote: >> > > be dm-crypt.c. Maybe you've identified some indirect use of >> > > BIO_MAX_SIZE? >> > >> > I mean the recently introduced BIO_MAX_SIZE in -next tree: >> > >> > https://git.kernel.org/cgit/linux/kernel/git/next/linux-next.git/commit/drivers/md/dm-crypt.c?id=4ed89c97b0706477b822ea2182827640c0cec486 >> >> The crazy bcache bios striking back once again. I really think it's >> harmful having a _MAX value and then having a minor driver >> reinterpreting it and sending larger ones. Until we can lift the >> maximum limit in general nad have common code exercise it we really need >> to stop bcache from sending these instead of littering the tree with >> workarounds. > > So should I not push this type of fix to Linus now? I was going to send > the above commit and this one to him this week: > https://git.kernel.org/cgit/linux/kernel/git/device-mapper/linux-dm.git/commit/?h=dm-4.7&id=57b3001b240629ecc5266d28c845e23ca5f11719 I don't suggest this kind of fix. That fix should be in bcache or blk-core instead of other places. Last time, I sent out the following fix([PATCH v1] block: make sure big bio is splitted into at most 256 bvecs): https://lkml.org/lkml/2016/4/5/1046 But forget to clear the flag of REQ_NOMERGE for this case. If Jens doesn't mind doing such thing in block-core, I can post v2 for this issue. > > Instead, should bcache be made to not do what it is doing? It depends on if bcache is the only user of this kind of usage. In theory, any driver can use external bvec table. Thanks, Ming From ming.lei@canonical.com Wed Jun 1 22:33:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B949D7CAE for ; Wed, 1 Jun 2016 22:33:01 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2C778AC002 for ; Wed, 1 Jun 2016 20:32:58 -0700 (PDT) X-ASG-Debug-ID: 1464838372-04cb6c2dbcae2980001-NocioJ Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by cuda.sgi.com with ESMTP id 5Gu63uzkpsask7AF (version=TLSv1 cipher=AES256-SHA bits=256 verify=NO) for ; Wed, 01 Jun 2016 20:32:53 -0700 (PDT) X-Barracuda-Envelope-From: ming.lei@canonical.com X-Barracuda-Effective-Source-IP: youngberry.canonical.com[91.189.89.112] X-Barracuda-Apparent-Source-IP: 91.189.89.112 Received: from mail-yw0-f173.google.com ([209.85.161.173]) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1b8JNM-0000LQ-4l for xfs@oss.sgi.com; Thu, 02 Jun 2016 03:32:52 +0000 Received: by mail-yw0-f173.google.com with SMTP id c127so38087532ywb.1 for ; Wed, 01 Jun 2016 20:32:52 -0700 (PDT) X-Gm-Message-State: ALyK8tIJcOcX1lLQ67ZVQJxhw8CPuDQLzd/2nN7uo1iHoyhdEt1rt9jJNngt+Gqf4wzAOfkHcB0Bu495z1UajA== MIME-Version: 1.0 X-Received: by 10.37.195.133 with SMTP id t127mr4149367ybf.149.1464838371243; Wed, 01 Jun 2016 20:32:51 -0700 (PDT) Received: by 10.37.216.78 with HTTP; Wed, 1 Jun 2016 20:32:51 -0700 (PDT) In-Reply-To: <20160601134816.GA20963@infradead.org> References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <1464615294-9946-6-git-send-email-ming.lei@canonical.com> <20160601134816.GA20963@infradead.org> Date: Thu, 2 Jun 2016 11:32:51 +0800 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v6 5/8] fs: xfs: replace BIO_MAX_SECTORS with BIO_MAX_PAGES From: Ming Lei X-ASG-Orig-Subj: Re: [PATCH v6 5/8] fs: xfs: replace BIO_MAX_SECTORS with BIO_MAX_PAGES To: Christoph Hellwig Cc: Jens Axboe , Linux Kernel Mailing List , linux-block@vger.kernel.org, Dave Chinner , "supporter:XFS FILESYSTEM" Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: youngberry.canonical.com[91.189.89.112] X-Barracuda-Start-Time: 1464838373 X-Barracuda-Encrypted: AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1309 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30100 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 1, 2016 at 9:48 PM, Christoph Hellwig wrote: > On Mon, May 30, 2016 at 09:34:33PM +0800, Ming Lei wrote: >> diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c >> index e71cfbd..e5d713b 100644 >> --- a/fs/xfs/xfs_buf.c >> +++ b/fs/xfs/xfs_buf.c >> @@ -1157,9 +1157,7 @@ xfs_buf_ioapply_map( >> >> next_chunk: >> atomic_inc(&bp->b_io_remaining); >> - nr_pages = BIO_MAX_SECTORS >> (PAGE_SHIFT - BBSHIFT); >> - if (nr_pages > total_nr_pages) >> - nr_pages = total_nr_pages; >> + nr_pages = min(total_nr_pages, BIO_MAX_PAGES); >> >> bio = bio_alloc(GFP_NOIO, nr_pages); > > While I think this is a useful cleanup on it's own I think > you'd make everyones life easier if bio_alloc simply clamped down > the passed nr_pages value to the maximum allowed. Yes, that looks a good cleanup, but need be careful because the passed 'nr_pages' can be used after returning from bio_alloc() in the current function, and it is easy to see this usage. So we can do that in another patchset instead of this one. Thanks, > -- > To unsubscribe from this list: send the line "unsubscribe linux-block" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html From bounce-452-13530548-248-248@china.com Wed Jun 1 23:48:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,T_DKIM_INVALID,T_OBFU_JPG_ATTACH autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 91D447CAE for ; Wed, 1 Jun 2016 23:48:18 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 521E08F8039 for ; Wed, 1 Jun 2016 21:48:15 -0700 (PDT) X-ASG-Debug-ID: 1464842890-04cb6c2dbbae41a0002-NocioJ Received: from eoe006.eoesell.mom ([192.200.210.71]) by cuda.sgi.com with ESMTP id XN1EKgadtiaNlfHl for ; Wed, 01 Jun 2016 21:48:12 -0700 (PDT) X-Barracuda-Envelope-From: bounce-452-13530548-248-248@china.com X-Barracuda-Effective-Source-IP: UNKNOWN[192.200.210.71] X-Barracuda-Apparent-Source-IP: 192.200.210.71 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; s=eoesell; d=188.com; h=Date:To:From:Reply-to:Subject:Message-ID:List-Unsubscribe:MIME-Version:Content-Type; i=allwaygroup@188.com; bh=9OsUAkiz/snHLBW6wKlVf1xEAn4=; b=MbufBhjSgtruH4cyTsUwyyZ4NBaLXvJrVEkICpnOIq+aZ18JaVdhV1txlmWJ5BUlg5CzU4/bc67M TpNQ9geuMl1FryZzLG3xR75oH/YcQhtWw9igktBaAvEVY+l5b2IVHE3/wVSbozTJQRCPtAyti1Hp OopjUca/NJeEtKJK+1g= DomainKey-Signature: a=rsa-sha1; c=nofws; q=dns; s=eoesell; d=188.com; b=fjXroke8f2rgtPgjGrS4Tbr9xAMElt6evldbeWaoM5PFn6tmjDpdsfoyvTSAEHTEh8IQq5FtWJ01 cJ3yhGnH9OU5m16L/iBZ5n6bdF3EO/KJxdvP9esA+q4pLqhuGVHFe/iSee5rgxvlCoXDyKauuQ77 DHeoF0cobPB+030JDu0=; Received: by eoe001.eoesell.mom id h9um3g0e97cf for ; Wed, 1 Jun 2016 20:47:01 -0700 (envelope-from ) Date: Wed, 1 Jun 2016 20:46:59 -0700 To: "xfs@oss.sgi.com" From: SK1 Reply-to: SK1 Subject: cigar humidor,cigar accessories-sk01... Message-ID: <2d89beb3af4ba377ae7a13851abee0b2@192.200.210.66> X-ASG-Orig-Subj: cigar humidor,cigar accessories-sk01... X-Priority: 3 X-Mailer: Email Sending System X-Complaints-To: admin@qq.com List-Unsubscribe: X-MessageID: Mnx8fHw2NjMyNnx8fHx4ZnNAb3NzLnNnaS5jb218fHx8MXx8fHwxfHx8fDA%3D X-Report-Abuse: MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="b1_2d89beb3af4ba377ae7a13851abee0b2" X-Barracuda-Connect: UNKNOWN[192.200.210.71] X-Barracuda-Start-Time: 1464842892 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 702 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30101 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS --b1_2d89beb3af4ba377ae7a13851abee0b2 Content-Type: text/plain; charset = "utf-8" Content-Transfer-Encoding: quoted-printable one of the biggest cigar accessories exporter in china above 300 items have stock goods,can ship out within 7 days after order con= firm =20 professional and quick service for distributor do OEM or ODM for big importer top quality humidor :with 3mm thickness hinge,piano super thick lacquer, so= lid wood frame middle quality humidor: service many big importer, above 100000pcs 1 year Additional product and details, please contact us. =20 Regards, ALLWAY GROUP LIMITED=20 3/F Block E, ShaLuo Industrial District, Cuiyuan Road 123#,Liwan District,Guangzhou ,Guangdong ,China. TEL:86-20-84042816 FAX:86-20-84041636 MOBILE:13922457369 allwaygroup@188.com =2E.. 1 66326 --b1_2d89beb3af4ba377ae7a13851abee0b2 Content-Type: application/octet-stream; name="2016-NEW.jpg" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="2016-NEW.jpg" /9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/b AIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxsc Hx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f Hx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgCwwPtAwERAAIRAQMRAf/EAM0AAQABBQEBAQAAAAAAAAAA AAAGAQQFBwgDAgkBAQADAQEBAQAAAAAAAAAAAAABAgMEBQYHEAABAwMDAQUEBAcJCQ0HAQkBAAID EQQFIRIGMUFRIhMHYXEyFIGRQgihsVJiIzMVwdFygrLSUyQW4ZKiQ3OT0zQY8PFjo7NEVJTUJVVW F8KDZIS0Njd0dSbiNWUn8sNFEQEBAAIBBAAFAwEHAwUAAgMAARECAyExEgRBUSIyBWFxE4HwkbEj MxQGQlJyocHR4RViwvGCJP/aAAwDAQACEQMRAD8A6oQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBB8OAL2uqRt7Ow1QWN3yHCWd0LS6voIbkt3eS54D6d5HYPelGQa4OaHA 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 0jK7HkAubXrQ9QmB97Qopk261+pTIKoCAgICAgICAgICAgICChH1oPg28JlEpY0ytFGyEAuA9/VR gzX3t6exLBTapH1T60FNqD4bBE2R0jWtEr6b5ABuNO8qMJy+tmg9namEK7QpFUBAQEBAQEBAQEBA QEBAQEBBQiqD4it4YW7YWNjaTXa0ACvfooxgfe0KQ2hMBRRgfLomPaWPAcwgtc0ioIIpQ94U4COJ kbGsYA1jRRrWigAHYKIPraOxB8eRF5glLG+aGlokp4qHs3dVGB6AUFFIICAgICAgICAgICAgICAg oRVB8RW8MLdsLGxtJrtaABXv0UYwPvaFIbQmAoowPl0THtLHgOYQWuaRUEEUoe8KcBHEyNjWMAax oo1rRQADsFEH1RIPg28JkEpY0yAUD6DcAewHqowZegFBRSCAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICChcB+8gimV9VfT/FX5sL7NQRXTX+W+Mbn7Xdzi1rgFS7yNJxbYzhJ rS8tby3jubWVs9vKN0UsZDmuB7QQr5ZvZAQEBAQEBAQEBAQEAIK0QUQPrQEFRRAogUQKIFEFEBAQ EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEFK/76DHchyLcdhMhfk0+Vt5 Zev5LCQq7XEq2kztI4mbkYpMleCc+Z5rj8XaXGrna968rk2r1tfk6M+7XkpJuI5DHucXR46+c23q a0jlY1+0dw3Err9Te2dXD7euNujb46LscogICAgICAgICAgIAQRf1C55Y8PxDbuVnzF5cOMdlaA7 d7gKuc53Yxo6lZc3LNJmt/X4LybYjRGW9Wee5KR8hyMlrCa7YbRohYAezdQvd9JXk8nvbW9K93i/ Hcc7zLC/215aZK/ti/r7bmT99Y/7zb5t/wDZcfyi/svUPnUO0xZu80PwveJB9Tw5TPd3nxU29Djv wjY/B/Wa9feQ2HJg10cz2xx5BrRGWOcaN81o8O0nTcOi7/X96bXFeZ7X4/xmdW42moXovKVQEFhk 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 TrVTrpiYMnE+J2PGMa7F4+4uJceJXy2tvcPbILdjzu8mF21rvLb9kOLiO9TrrgtZS9s4ryzntJSR HcRvieW03APaWmlajtU2GUcv/TzF3PHcPhobu7s5MAyFuJykD2tu4nQQ+QHF23Y7fHUPaW0dVVun Qy8rb0ywX7Hy2Oyk9zmJc7s/auQu5B8xL5X6kAxtjYxsR1YGt0Kiccxc/Ey+sN6eRWWWt8pks1kc 7c2LXtxoyD43Nt/MG1z2iKOLdIWeHe6pok065LWYyXHbPIZbEZSeSRtxhZZZrVkZaGOdPA+3d5gI cSAyQ0oRqrWdZSVlQrIEBAQEBAQEBAQEBAQEBAQUc1rmlrgC0ihB1BBQYKw4FwnH5H9pWOBsLW/r ubcxW0TJGuPUtIb4SfYqzTWXOE5rLR4+wjvZb6O2iZe3DWxz3TWNEr2R12Ne8Dc4NqaAnRThD5GL xjci7Ji0hGSfGIH3ojZ55iB3CMyU37a67a0TE7i6Ui2ixuOhjuIobWGOO7e+W6YyNrWyvkFHvkAH ic77RPVRgWWE4nxjBPmfhcTaY59wazvtoWROf20JaAaezoomsnaJtfDOGcRZmTm2Yayblydxvxbx ibcer9+2u787qnhM5wZrLTwQ3EMkE8bZYJWlksTwHMcxwo5rmnQgjqFZBBBDbwxwQRtigiaGRRMA axrGijWtaNAAOgQfaAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIKVQK ojKqJEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEHnNPDBGZZntjjb8TnGgCCOZHnePhJZaN89403uO1v0d6jIxX9tstI6rBGG/mt3U/DVMi6teaX2 6kscc4HVgrG/6AahMiRYzOWOQBbE4smHxQSaPH0dqkZAICAg8bm7t7aF89xI2KGMVfI87Wge0lV2 2mszUyZ7Ne571ixscht8Kw3TydouSKR1/Nr1XBzfkJr9sy6uP1Nr3Qmbn+Yv5H+fJNo8t8LiBpT4 QKd65v8AcbbTOf8A1W24ZrcUg5rk4rhrbfISQEfFuL2nvoA4lhVtOfb41fj4ZZ2Tfj/qVci4FtmW CSF/6u+iFKD/AIRvf7l1cftztWG/DLOjYcE0U0TJYnB8TxuY8aggrtlzOjmeikEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBj83mbXE2LrmfxHpFEOr 3dwQaxy2ayGVufMuZSI9fLgbowU9nb9KpaPKC0dIK7Wgd5BJSC+bjpQ3wCumopSh9qnA+JI5oiBI 2or0P76gXUMzmljg8tcDWKYaOae4oJvgM187E6KajbqL4wOjm9jgrSjLqR8TTRwxOllcGxxgue46 AAaklRbjqNEc45hc8guns3mPGsfS1hNQCAaCR3eXHoF4ns+zd707PQ4eOa9Uft7KV7W7T4YyA6TS je+q4Ofk11mJHTeXWd69obWFtwXSzxsaHkxt3DcQKa69AVxfybWYjPn9rj11iwzeO+YEl/FuuLOA tEj4neY2h1d07qhdHFmTG0xl2cHJiSf9yR4dvk2cexxfHtBjcNSBoaVPYtfX9nabWb9dY8/n72Tu nPAuQy20gsbl/wCie8REHoyQjwOH5r+32r2fW5sbY+F7OTeNjA1C9JiqgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgINZczyT7zOPiDv0Np+ijHZu+0ff 2KtGFigZ53iGoFC4dygYe75V8jdyQXsr4nnzDC2NwDSAaRBjB4jUfETqOwFWguMPzLN3eakxkFtJ Nbtt47mO5vHC3e0SO2OYAA5z2upVm5rTRTRLGXRkjAumCtPGAQaH3hQLaeLyXlgNY36g9lP31Wi8 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 AQfJFe1Bb3eNx95t+btorjYdzPNY1+0ju3AqMJls7LhrQ1oa0AAaADQAe5ShRsbGCjGhoJrQCmv0 IPpAQEBAQEBAQEBAQEBAQEBAQEBBUICCiAgICAgICAgICAgICBUoGqBqgIKUQfEsEMzCyZjZWHq1 4Dh9RCDB3Xp5wG7fvuuNYqeQ9Xy2Ns8/W5hUYTmvD/0u9M//AClhfZ/3da/6NMGaz1hjMdjrdttj 7WGztmfDBbxtiYPc1gaFKFyNEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQVCAgogICAgICAgICAgICAgt7+7faWVxcst5bp0EbpG20AaZZNorsjDyxpceyrgooi9x6 pcYi4jZ8nj8+5tr+SO2s7GFjXXkl1I/Z8sIi4DzWuBDhu7DqqXkmMpw9OReoVvhcvY4gYbJZLJX1 s+7ZbWDLeRzI43Br95fNGKhzqeElTd8XGE4e/GueY7OZO5xDrK9xWXtImXEmOyMTYpTBI7a2VhY+ Vj2btDtdodCmu+UYZTPZ/FYHE3OWys3y9jat3SyEEmpIa1rWgVc5xIAA6q12kREYh9VLWO9s4szg spg7LIytgsclfxRtgdI/RjJdkj3Ql/2fMaFn/LPithf5/wBQsfico/FQY3I5m+t4mz3sWLtxP8vH JXY6UudGKu2ktY2riOxWvJIjCuS9RuPWeBxWbhbcZG1zUrIMbDZRebPK+RjpKCMlhG1sbt1eh06p eSYyYZDj3JP21DNL+y7/ABnkuDdmRg+Xc6orVg3OqB2qdbb8DDMKyBAQEBAQEBAQEBAQEBAQEBB8 ueGgucaAaknQAIIHL6u2Jimv8fgctk8DbF4nzVrDGYKRuLXvia+RksrGkGrmN7Csv5YthnMnz3jd hx6zz3nuurPI+U3GMtWOlmunzisccMY1LndxpTtorXeYyjCwxPqTb3OZtcPl8PkOP3uQDjjf2gyI RXGwbixskMkrWyBupY6hUTk+ZhJsnfPscfNdstJ718LdwtLYNdM/81ge5jSfe5XtREJj9YGSZWXE s4jyA5KGFlxNa+RZ72xSEta8/wBa6EtIWf8AL1xhbxZPKepNhj8jFjBiMre5F9nFfzWlnbCZ8EUz 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 QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQVCAgICAgICAEFCgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg qEBAQEBAQEAIKFAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQEBAQEBBUICAgICAgIAQUKAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICCoQEBAQEBAQAgoUBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEFQgICAgICAg//9k= --b1_2d89beb3af4ba377ae7a13851abee0b2 Content-Type: application/octet-stream; name="sikarlan2015-new.jpg" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="sikarlan2015-new.jpg" /9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+4ADkFkb2JlAGTAAAAAAf/b AIQABgQEBAUEBgUFBgkGBQYJCwgGBggLDAoKCwoKDBAMDAwMDAwQDA4PEA8ODBMTFBQTExwbGxsc Hx8fHx8fHx8fHwEHBwcNDA0YEBAYGhURFRofHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8f Hx8fHx8fHx8fHx8fHx8fHx8f/8AAEQgDIAaNAwERAAIRAQMRAf/EANIAAQABBQEBAQAAAAAAAAAA AAAFAgMEBgcIAQkBAQADAQEBAQAAAAAAAAAAAAABAgMEBQYHEAABBAECAgQGCwsKAwUFAw0BAAID BAUREiEGMUETB1FhIjIUVnGBkdOk1BWVFwgYobFCUiO05HWlZjfB0WJygpIzJIS1okMW4bJTkzTC 0mNzJfDxg6NUNVXis0RkwyZ0RTYRAQACAgEDAwMDAgUDAwQBBQABAhEDBCExEkFRBWEiE3EyFIFC kaFSIxWxMwbwwdHh8WJyJIKiQ1Ml/9oADAMBAAIRAxEAPwDzryVyFzZzvlZcVyxR+UL8EDrUsPaw w6QseyNzt074m+dK0aa68VCzdfsud+vqz8Ox/wAYUoyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn 2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCM IZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Ds f8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z +HY/4whk+y536+rPw7H/ABhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+ vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn 2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCM IZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Ds f8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z +HY/4whk+y536+rPw7H/ABhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+ vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn 2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCM IZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Ds f8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z +HY/4whk+y536+rPw7H/ABhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+ vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn 2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCM IZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Ds f8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z +HY/4whk+y536+rPw7H/ABhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+ vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn 2XO/X1Z+HY/4whlytQlunJXcz3k874qXK8sYf5QoQTuqyzek1YdJmMZI5u2eWJ3mytOumnFShsH2 XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCMIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MI ZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf 8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/ABhDJ9lzv19W fh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnf r6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2 XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCMIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MI ZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf 8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/ABhDJ9lzv19W fh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnf r6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2 XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCMIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MI ZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf 8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/ABhDJ9lzv19W fh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnf r6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2 XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCMIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MI ZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf 8YQyfZc79fVn4dj/AIwhk+y536+rPw7H/GEMn2XO/X1Z+HY/4whk+y536+rPw7H/ABhDJ9lzv19W fh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P8AjCGT7Lnf r6s/Dsf8YQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8AGEMn2XO/X1Z+HY/4whk+y536+rPw7H/GEMn2 XO/X1Z+HY/4whk+y536+rPw7H/GEMn2XO/X1Z+HY/wCMIZPsud+vqz8Ox/xhDJ9lzv19Wfh2P+MI ZPsud+vqz8Ox/wAYQyfZc79fVn4dj/jCGT7Lnfr6s/Dsf8YQyfZc79fVn4dj/jCGWgc08rZ3lXO2 sDnqvoeWp7PSa2+OXb2sbZWeXE57Dqx7TwcoSikHf/qVfxTyv6jsfndRSiXtNECAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPytULPaf1Kv4WZX9eWPzSopRLv6IEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBB4B+tH/HXmb/AEP+310T DlahLv8A9Sr+KeV/Udj87qKUS9pogQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBB+VqhZ7T+pV/CzK/ryx+aVFKJd/RAgIPhcAg1JnelyI/JfJzcrGbBf2Qfo/sjJrpt7XT Zrr41z/ytecZevPwPMjX+T8c+OM/XH6d0vFzNhpcjexzbDRbxzGyXGOBaI2PGoJcfJ6PGtI21mZj PZw24e2uuuyY+284r9ZfMBzRhs/WfaxM/pNaN5jMwa5rC4dO0uA3e0mvbF+xy+Ht49vHZHjb2VZT mLD4qenXv2WwT35RBUjOpdI89QA++mzbWmM+qvH4m3dFppXMUjM/SGJm+euVMJeioZPIxVrcwBbE 7UkBx0BdoDtBPWVW++lZxM9XRxfi+TvpN9dJtWFOc5+5TwU8dfKZGOCeVoeI/KeQw9DjsDtG+NL7 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 lX8LMr+vLH5pUUol39ECAgaILcMEMMYjhY2ONvmsYA1o1OvABBXtCD7oEDQIPm0IPugQNAgaBA0C BoEDQIGgQNAgaBA0CD5tCCl8bJGlj2hzHAhzSNQQekEFB8gggghbDBG2KJg2sjYA1rQOoAcAguaB A0CBoEDQeBA0CBoEFpkELHvexjWvkIMjgAC4gaAuPXwCC7oEDQIGg8CBoEDQIGgQNAgtRwQse97G Na+QgyOAALiBoC4jp4ILugQNB4EDQIGgQNB4EDQIGgQNAgaBA0CD5tCD7oEDQIPm0eBB90CBoEDQ eBA0HgQNAgaIGgQNAgaBA0CBoEDQeBA0CBoEDQeBA0CD5tCD7oPAgaBA0CBoEDQIGgQNAgaBA0CB oEDQIGgQfNoQfdAgaBA0CBoEHzaEH3QIGgQNAg+bQg+6BA0HgQNAgaBA0CBoEDQIGgQEBAQEBAQE HgH60f8AHXmb/Q/7fXRMOVqEiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI Ov8A1X+QuU+d+fr+K5no/KFCDFTWooe1mh0mZZrxtdugfE7zZXDTXTipRL0/9lzuK9Wfh2Q+MIjJ 9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MI ZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHx hDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q +MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8O yHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wf h2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXq z8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK 9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsud xXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9l zuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZP sudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhD J9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+M IZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyH xhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2 Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8 OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9W fh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxX qz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzu K9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsu dxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9lzuK9Wfh2Q+MIZPsudxXqz8OyHxhDJ9 lzuK9Wfh2Q+MIZeAVCz099V/uZ7tud+Qb+V5nw/yhfgys1WKb0m1DpCytXka3bBLE3zpXHXTXipR LsH2XO4r1Z+HZD4wiMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7I fGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+H ZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerP w7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1 Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53F erPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO 4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y 53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn 2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4wh k+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfG EMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD 4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7 IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+ HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53Fer Pw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r 1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53 FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2X O4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+ y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEM n2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4w hk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMn2XO4r1Z+HZD4whk+y53FerPw7If GEMn2XO4r1Z+HZD4whk+y53FerPw7IfGEMvIHf1ytguVe9jO4HA1fQ8TT9F9Grb5Jdva04ZX+XK5 7zq97jxciWgKEu//AFKv4p5X9R2PzuopRL2miBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQEBAQEH5WqFntP6lX8LMr+vLH5pUUol39ECAgIGo8KBqEDUeFA1HhQNQgajwoGo8K BqPCgahAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEDUIGo8KD5wPQUMvuoQNR4UDUIGo8KBqEDUICAgICAgICAgICAgICAg IPAP1o/468zf6H/b66JhytQl3/6lX8U8r+o7H53UUol7TRAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICD8rVCz2n9Sr+FmV/Xlj80qKUS7+iBAQWp3PbG8xgOkDSWNPDUg cAokjGerhmN535rmvxi3zI3HZ70rZNgMjW9HqGPeRsZMGuOunRqvKrvvnrbFvaez73d8Vx4pPjp/ Jp8f+5S2bZ+tUtzN3qXuXOaOYqc0npBjjrNw1NwAY2SRusj5Hga7W668Vps5dqXtHf2cfB/8fpye PpvHT903n1xHaI+st95VZk6OFhkz+WZevWAJXzeRHENw1DItNNWjw9a69Wa1+6c5fPc6dezbMaae NK9MdZn9ZazzXzRzXBzfgqdaD0LBT5CKu63ua51rezcQ1uh2xjw9ZWG7deLxGMVz/i9P4/4/jW42 29p890Um2P8ARj/3RvOPNXN4y/MsuLyLaVLlWCCX0YxNkFl8g3PEjncQNOA0VN2682t4zjwdfxvx 3G/FpjbTztyLWjOceOO2GJnee+Y7NvIS1MtFhIsXjqmQq1JI2O9MfYjEjmkv8otBO3yVXbyLzmYn GIj+rbh/E8elaxfXO2dmy1JmJn7IrOM/r69X3mbvCzll+Bko3Z8XUuYz5QvS1qhtlrnO0A29TRtO p14Ju5FpmuJx0zJwPhtNfy+da7LV2+FYtbx7PuZ5tyseQ5bqR82MqY69jpLNnNOhj2SPY47XFj9N pPm6JbbMzWPPETHdHF+O1TTdadE2vTZERTM9P6w2Tup5nzOahy0V623J1qFrsaOWZH2TbEZGpO0c OC34ey1onM+WJ7vM+f4OrROuaV/HN65tTOfH+roS7Hz4gICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICC1OXiF5YNzwCWt6NT1BEx 9XC6HO3NcuQa23zGMbnha2TYLI1uwpmLfptZMGuOpb0a9K8mu+8z1ti2e3o+93fFcetM10+enwz+ Sls3zj/Tn3bLzl3kT8rc6Sx2pTLjvksS16DGg9pbc8hvlaagaDiVtu5M02de3i8v4z4SOXxImsYv +TE2n0rhsfIE+dmwozWdyUdp2RaLEUUQY2vXidxaxruGp48SSujR5Y8rTnLy/lq6a7vxaaTXw6Tn 91p/R958z+bo4CWxy7WZbmcyXtLZkaI6zI2FzpHdO49TWjrTkbLRTNeqvxXE1bN0V3zNIzHTHW2f Rr2Q5wztTuqw2UhnDsxlHVawuSNDtr7DiDIW9BIAWNt9o0xaP3S9PV8Zpv8AI7NUx/ta/K2P/wBY WGc38z4ahzjQt2hlchy/FFNSuujDC5szQfyjGcDs6VX816xeM5mrSfjePvvx71r+Om6Zia5z29pn 3OUecMxBzM3E38zHn6trGfKTZ4mMa6GUDc6L8mdNNvRqmnfaLYmfKPHKPkvjdduP+WmudNq7PDHX rHv19UdyVz7m8zn8fPYzbIm5CeVkmHkqubAI2k7I4LIGjptNCeKpo5FrWiZt3ns6vlfiNOjTesas +ER98W+7Pvav+n2Y2W51zzMpzR2vNseI+S7MkeNx8kMUhmDWlwaNfK6RtVb7beVvvxhto+L1Tr04 0Ts/JWPK0TMeP1dT5Kyd/K8q4vIZGLsbtqBsk7NNvlHr06t3Su/RabUiZfJfJcemnkXpSc1rbon1 s4hAQEBAQEBAQEBAQEBB4B+tH/HXmb/Q/wC310TDlahLv/1Kv4p5X9R2PzuopRL2miBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEH5WqFntP6lX8LMr+vLH5pUUol39ECA gx7MPbQSRbnMEjSze06OG4aag9RCiYyms4mJ9nLsh3b895LFN5fyeWpWsQyUOGQljkfkezD9wbvP k7urVcFuPstHjOMZ/q+r0/NcPVs/PTXeu2Y/bEx4ZxjsnIu7mvLzJn8hkhFZpZarFVhZoTMxrGBr 9XEcC7QHULWOLHlaZ7S8+/zVo4+rXrzFtdpt9Jn0W8F3bh3LseA5rMWYqUZnOxcgMjXtiIIDX6Ec WjoUU432+N+uOy/K+a/3538bOu1o+7tPX3j9UlzDyhLdm5aFB8cFbBW45zG/cdYo2bGsYfDp4Vpt 0Z8cf2uThfIxrjd55m26kx/WeqC5q7uc/fyuYlxN6CGjzHFFDlG2GvdJH2XDdDt4Hc3wrHbx7Taf Htbu9H4/5rTr1642VtN9EzNMdpz/AKjmnu6zuRfFVx89B2NbTjoxG7XD7FUMAa6SCRo1LnNHQ48C o28a1pxGMYx+iPj/AJrVqza8bPPzm322+230tDOvcq85UYK1PlrJV246GgKMlO6wlocBp27Cwa7j 4DwV7aLxERWemMOfVz+Lsm1uRS3nN/PyrP8A/bOWHje6qOnlOXXSvgvY7DUZqtiGePe6WWVxfvDX At0DncNU18XxmuesRDff/wCQTfXtxE12bbxaJie0R0dDrVa1aJsVeJkMTfNjY0NaNfAAuqtYiMQ+ dtebTm05lfVkGqAgICBqgICAgahAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEDUICBqEBAQEBAQEBBZsxdrXki1c3tGlu5p0cNRpqD4VExmMJrOJiXK8j3bc+ZL GDl/I5elbxDJdzchNE9+Q7IP37d5JaHdWq4LcfZaPGZjGf6vqtPzfE1bPz69dq7fH9sT9mcYzhsk /IcdjniLO2exnx8OO9BZXkaXP36kb+I2+aSFtPHzs8p/bjDza/LTXiTprmLzs88x/wBP8WPyx3ey 43HZTlzJTR3+WLMpkx9cl4liY524xPPDydeI0KjXx5iJrbrVfnfLxt2U30ia76x90+kz7pp3J+Op 8q3sDhYm04bMUzY2kuc0STNILiSSelafhiKTWvTLi/5HZfk137Z8rVmJ/wAEHe7vrlvu7xvLnpMb MljOwkgs6ExdvXOo1HnbSCQsp48/iinrDv1fM1pzrcjxnw2eUTHriyrCcl8xQM5gyN+9XZn841rG y14y+CBsbNrBsl136/hapr0WiLTOPKyvK+T02/DSlbfh1ekz90579YYvKHdzfoZl2WzBoMkZUdSi q42IxRkSHWWaTXTV71GnizFvK3thv8j81TZq/Fq88eXlM3nM9O0R9IYeI7sOYKdrFULN+tJy/hLr 71HYxwtvJJc1khPkaAu4kKtOLaJiJn7azltyfndN67L1paN26kUt1+2Pr7p/l3kGGlm89k8nDVuu ydz0qm50TXviZt0LdXg6HXwLbXpxMzOJzLz+Z8vbZp1a9c2p+OnjPXv/AINzaxoAAGgHQF0vGVIC AgICAgICAgICAgICDwD9aP8AjrzN/of9vromHK1CXf8A6lX8U8r+o7H53UUol7TRAgICAgICAgIC AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICD8rVCz2n9Sr+FmV/Xlj80qKUS7+iBAQf COKDn2D5x5qdl+ahnKUVGviqUF2hQjcJpmseJyTNI3yS9/YjyW8G9GqDWMJ3pZyHly9lcnkjZy8W I+UYMDYxkmPDnv2gPimedZo43vDX7R4+sKRsDOcczynlbNLnDIMyVc4xuTr2a1YQyiVsza8lZkTS e03PlZ2fXx0KgMz3oZOu/HwQcu5GtcmydSnbrWYotewste8OikbN2TnO2EcHeSQd2nBBtPMvNtTB Po1zUsZDI5OR0WPx9RrXTSFjN8jvLcxjWMbxc5zkGnZbvQknmoyYx8tCua2bGWrWIGPtV7WMrtkD Swu27mF27Tdo4EcUwJyHvJwsOJv2LDbMljFGlFYiETGy2JMgyN1d0DA/ae2MugG4aHUdSD43vTwz siyD0O2MZJf+SmZstj9EN3f2XZef2una/k9+zbu4IJnmLmf5HNWFmNuZO3dc9sFeoxpAEbdz3Syy OjijaB+M7j1aoNcb3wYSerjZKGPv3beSjsysx8bYWzsbSl7GcHtJWMc9snBrWOcXewgw7verPjuY cuJsZfuYani6GU214GCSrFOJnTPsCV8btQ2MeQNSNCgmu8Tm25huTGZ3FayOdPT2NbGJHvhsTMa5 rGO01c5j9B40Cr3l4t05qXKF7H5Fl2pQlo2GR9o11/d6PLqyR7DE7s3alriQQRog+5rvLxOLktV/ Qbt23WyEWJbWqxse+W1PWFpgZue3ydh0LjpofFxQV93/ADHlM7HnJL7DEaeUmq1672tZJFC1kb2x ybC4F7S8gnVBrnd73s2cnicM3P0bcdvJm3HDlOyiZUnmquleY4w1+8fkouBLQCQUGzO7wsN8nYi9 2VgQ5qpPeqDazc2KvB6Q8SDfwds6NNeKCEi75aMwj7Dl3MyOsUxk6UfYQtdPS4F041lAaG6jyXEO Oo0CC59KGLjt2rYls26ctTGTYzGxVmiWSXJb+xZG4vBe+Tbxa7QM06UGFjO9a23I59uVx1xj4L9T HYfCCKL01809btXM1a/s3A7XP3l+gagkbPe5i4K7GnEZOTLuunGOwzIojaZZEPbtDvygj2Pj8prw 4hBvFaZ80EUro3QukY15ik03sLhqWu0JGo6DoUF5AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAPQg0Xmjmfmqhzpy7jK9SKHA5C36PauyPD5ZnGCSTs44x5jWFnlPJ49A QQPNvP2Yp85ZPHjKPwmHxcVQSXfkuS9D2lkOc9804LWRMaCwffQZnMnNPOMmR5nmwVuvWpco1YbD 4JYRML0r4DbkY6TcDGwRaNBbx1OqCVud5tGs5rK+KyGTdFSgyORFGJsgqwWG7mb9z2F7yATsYHO0 GqC5gOcshk+ec5hDSkZjcdWqT1bRa1of6Q0uO7yy7y/wBtHQddEGPmu9nE4jI36smKydmHF2IamR u14WPhjmstY6Fo1kD37+1aPJbw60GTW7x6cuPyliTE5KC9irEVWziDCJLRlsBjoNgjc+MtkbIDu3 6D8LRBbh70MM3H5izdp3KFnByQw3MfI2OSd0lnTsGxdi+RjzKXaDyunpQX2d4UYx92exg8rXu0ZI IXYwwNfPI6ydITE6N7oXNP4Tt+jfwtEGKe9fCw4nKXbtK3UsYizDSuY+QRGXt7O0whj2yOhLX9oP KLwB1oLtrvKo08H8qXsXeqSm7HjY6EzYmSPsTAGPZKZOwdG4HXtO02+2gyDz2wYaK/8AImT9KmtG izGdg3t+2brq4u39iItBr2vabSOtBgy97GHjwHys7HX3zDJNwxxcccT7IuuOjYxpJ2ZaeHlB+nFB f5z5tyOJ5Wx2arVJ4ZrFyjHPj3xsksiOxM1kkOwOLe00O0aO6etB8i7zcV6BcsXKF2hYoXq2OuUJ 2R9syW45ggf5L3MdG7tQdQ7woL2Y7yMDiDnhZhtPPLvofpwija8v+UOEPYjcC/T8Lo8WqCIn75cd WkvMt4HL1ziXQ/K4fDDpVisadjNIWyuBDwddrCXDQ6hBm2+f6WKyfM/p809iDESY+KCjDXb2hlvR js4oXB2szpXuHnBu32OKDAx/efsu802c1UtY+hg20GMx80LDaE1sOGxnZOe2XtXbAzR2iDNm71cR To5ezlsdfxdnCVo71yhPHGZ3VpXFjJIuzkfHINwLSN2oKDZsBmJcvjmXZMfaxm9zg2tdaxs20ea8 hj5AA4cRx1QSiAgICAgICAgICAgICAg8A/Wj/jrzN/of9vromHK1CXf/AKlX8U8r+o7H53UUol7T RAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICD8rVCz2n9Sr+FmV/Xlj 80qKUS7+iBAQEGsy8rWX5zPZGO86t8sUYKUL4BpNXfAJfyrXHUE/lgRw6kGuW+7PPcwiRvN+Yht9 jjbGMoPpQOhcHWdgktyl736y/km6Nbo3pQU3e7DO56O3PzJmIJcq6pXqYyepXdHFAathlts7mSPe XvfNEwuGoGg0QZGR5L56ysTLV/OVflWrdp3cfBHWf6BF6Jv3AsMnaudN2h3Hfw4aIJnmzlnK5O9h 8xiLkVTL4V8zoPSI3S15YrMfZzRyNa5rxroC1zTw0Qay/ujyMrXzWMrHJkbjcxJkJhCWxusZesys OyZvO2OFsTeBJJQSM/di2Xmfl3Mm7tgw9aGHIUmsIZbmptIpynjw7F8j3AcerwIIqn3NmnmQ+F+O OLbknZQTyUWyZI75TOa3bucWbO0PB+3cBwHhQT3PvI9/mO9irME9V8OPMvbYvIxST05u1DQ2R8cb 49XxbfJ3ajig1kdzWVj5epYf0vF5CCq64XQXqBMANuczMmh7N7ZIZItdujX7SPdQTtDu2uVMXmqL sq607KYSrhmWp2l0ofWhmiM8rt3lbjPrp4ulBJcz8n38rybVwVO+yldqOpPivOjMjQ+m9j9ez1b0 9n4UEHd7t+ZL7rmWuZas3maa1j7NOWGu8U4m4t7nxROjdIZHCR0ry87tePDoQXsV3d55mSOUyuVg s3ZM3HmphDA6KMNjo+h9hGHPcdB0hxQbHyty5NhJM1JJO2f5VyU2RYGtLezbK1g7M6k6kbOlBruJ 7sbNLB8p4yTIMk/6ctWLE8jYyO2bYZOza0Fx2FvpHSdehBgUe6/mpjMZUvZurPjsJRu47HxxVXxy PZbg7BkszjI4b2N01DQAeKDYKXI9itZxsrrjXijgjhHtDD5bz2f5YceA/J+b4+lBr7e5+9HFDJFl ImZChWxDcdOYC5jLWIEg3yMLvKjlEpaWg6gdaC59GvNU161nLOaqnmF2RrZKlJHWeKsfo9Z1V1d8 ZkL3MfG8+UHB3WgyaHdrlm5ypn8jk4p8p8qHKZARQuZCWtqOqRQQNLnOaGNOpc4nVB0TQICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg1/mTlqXL5TAXY52wtw103JG OaXGQGF8W1p1G0/lNdUEJzTyZzflpMrRrZ2OPl/OMZFbrTwGWeqzaGStpvDmsAlb+O07TxQY2c7u MvNaykeCysVDF8wVIKWYhmhdNK1leM1+0rPD2hr3weQdwI4aoL+Q5D5hq5K3Z5Uy8OLhydOvRuie B08kXojTHFPWcHsAkEbtujwRqAUEniOVcljeb72ZbebYo5GnWr2IZYz6R21QFjZO1Dtuj2uJcNvS mRhZHu/tW4s4wXWM+WMpTyTCYz+TbU7DWM+VxLvR+nxoMfmbu6yGWHMD4MiyE5m3QtNhex5icylG xj61jY9jnxTbPK2kcEEXS7n7cNHPQm7Tpy5aSjbpNx9XsYKlnHu3x6Rue7tGFwaXakOPHxIM7Mcj c6Z3EXIctnK77U9mrMyjFDKzHdjVJL4JIxJ2z22C7WTy/AOpBi4vuqytDF5+rDex0Ds1PWssqwUG iiwV2hj67673u3xSBo1Ood0nVApd1OSp8tZDGxXKEbr16O78l+iGXEsjjYGOrNryve9rJNN7nNcD u4hBYPdBkmcsVsVHeqkQ5R+Tfi5I5zi3RviMYpiHte07GMntGgu8/qQZmE7rchj6MVSS9V2x8wRZ 1rK1YwRMYxgDq7Iw923yvNdr0dPFBt3NWAlzVWlBFM2B1S/UvFzml24VZhIWcCNC7TTVBAcw93lr KDmF8WQZBPlrWPvUXmMvbBLjhGWCQbhva90XHTTgUEdL3Z8xX4eZpcrlaz7/ADFJjJC6vXeyGAY2 QO2BrpHOduA4HVBnZ/u4t5Q85ll6OIc1R0Y4d0bndgabNji7R3l7+rTTRB8zHdrZyF/mG8zItgtZ SxjLuMkERd6NYxbAGGQF35Rr3DiBpwKDGl7tuYMnDzDLnMvXdkcw/HzU5addzIqk2Mf2kBDJHvMj e0AcdT4UFrMd2fMGfocwSZvLVnZnMY+PF1n1a746teCOTtidjpHve57zqfK8AQdNA4BAQEBAQEBA QEBAQEBAQEHgH60f8deZv9D/ALfXRMOVqEu//Uq/inlf1HY/O6ilEvaaIEBAPBBhX8rjsfXNi/Zj qwA6GSZ4Y3X2XaKtrxWMzLTVpvst40ibT9FFXNYi3TN2rdhnptBLrEb2vYAOnVwOiReJjMSbNGyl vG1Zi3thj1+bOWLMzYYMtTmmcdGxsnjc4nxAFVjbWfWGt+FvrGbUtEfpKX3t011WjmYEucw0NxtG W7BHcf5lZ0jBIfYaTqqTsrE4y2rxtk18orPj746Ll3JUKNc2LtiOtA0gOllcGNBJ0A1dp0qbWiIz LPXrtecVjM/Qu5THUYPSLlmKvBw/KSvDG8eji4gKbWiO6dWq+ycUibT9Fypcq24Gz1pmTwv4sljc HNPsEJWYmMwi9LVnFoxLIUqiAgICAgICAgICAgICAgICAgICAgICAgaoPm9uumqD52jPCgdozwoK kHze3woPnaM8PQgdozwoPoc09B1QfUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEH5WqFntP6lX8LMr+vLH5pUUol39ECAgsWjP2Eno+3t9h7LtNdm /Q7d2nHTXpQcZuc1c1cn5swX8vcylpuHvXsmy/C2KhJcrQtljbjXiOMuDSXbmgnyBqeKDJ5LynMO TuV8be5hzNO5m8Y60w3qleLtJWujcZ8c9gc2JjA/R0UrdSCHIMjBXuc6ljmLOUcnc5nw+F3U6lC0 6CN1uxA8G5JE+KNv+EAY4wfOcHIM2TnHJ834P5XxF5vLnJ7bbRPzBM9sdmanHGTK6BsrHMi3T6Rh zuPA6dSDXmcw8928FTioT5q/j7GZsMoZapWhF+fFxVt0bn9s2OENdO4tbI/buAQZFzmLmG9i+X4M Db5iux9vkGZqxBWrDIxzVyA2vYEoZWjLXP8ADxAGmqCRHetBhsBiLjo7maxt+OarVvyhrbr8tFI5 jKNiFjWtjfI4FoI4At9tBI81ZjnepnuSt0taljsnkYquTpQ73zmV1WeV8ZldowxNdH1N1JQatn+e M8/mTmK18o5TF47l67FShnq1YrGMhaAwySXw4iaXtC/T8n/hjQoM2fmPOwc43beauZ/GYKPMR06c sVeuMW6LWNkYke8ekbJpCQZGt28fOQZ7+9Xmx80Bq8twyU7uUsYShI+5se+1A6QCV7ezO2HSJ2pB LtR0ILkHenzJdmx+Lx+Ahlz1qxlKVyGS0WVoJsS6Nsj+1EbnOY/tht8nVBf5R70Mvmr2EF7CMoY/ mFlkY6ZtntpRLTH5USx7GgNdtdsIcejjog6QEBAQEBAQEBAQEBAQEDVAQNUDUICBqgahRkNVIahA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBB8d0IOW969rmvD18jn4cxeq1asDRh aWMriaITsaXSS5LdG/8AIk6DzgGt1PSgiea+ds7e5it0qd3J1qeIxNa8+fAwQ2IzNaY6T0id02m+ BjWjbGzyn8fAgludZsy/l3H57Fc03RcysVSriaVBkLK1q5ZHkSASxySMY7dvf5XktBQZub53y3I8 GKxmXrTZua5UbXoZKLTtLmXGgFZ8YaGx9trua7o0B8CDB7wchzFSEl+/zC/BEU4m4LE4rZYs28oW udK10T43vmja7YxrW6DTUu0QYfNWa56N7Giw3OU60OEit5Z+Cr15Gtuuce2a91nyT2bWnyIyXceh BVzXzFnrtjBy4K1nLHL8mHN6XI4WvA+SZznNDHSushjA4Ma52xvlanoQSuS7062Cw+CyIhnzODy1 MR4/Ks/9RPkNo7GvNEGtDHWNCA7oDtQQEFzvAy/PNLBYa9XkrYwS3MfHmIGb5Zw6e1Gx8UMvks2+ VtcS3iNdEEd3icy513O8HLOOky0NeHFnJz/IcMMtl73zOhZvdP5LY4+zLi0cXk6BBhZfmXmnJ0+V ZMTcy9+haxs1u/lMBTha6aZromM3ttns4z55Me7dr0BBMQ94WTdV5ao8sV/+opczRsWor2Ql9EcB UcxrzOGxnR2r9pDW8HeJA5Y71cpl5cRPcwraON5gp2beKlbZ7WXdTYHyNmYGNDQ4ElhaT40GFiO9 jnTKNw7a/LFeOXmKpJdxXa3tA1kABlNjSIlocHDZt18eiDfeTuY28y8s47ONgdVF+ISGu4hxY4Et c3cOB0cOlBNoCAgICAgICAgICAgICDwD9aP+OvM3+h/2+uiYcrUJd/8AqVfxTyv6jsfndRSiXtNE CAgHoKDmvM8NO53p4enmg2TGClLJThn07F1nXjqD5JcG9C4NuJ3RFu2H0fCtanx+y2qcbPOInHfx ZEdbkytHzXDgdsdwVnHIwRE9g13ZnbtaPIBPXokxrit/H26svPlXtond1r5R45793NWUbTe73HXp 6GMjxsBhmkvQO0yZY2X8EHQb+rp6Fx4/246Vx/m+nturPNvWL7JvOY8Zj/b7erslnmx9eXHxQYi/ dguxxyNtQxh0cbZNNO1OvAgcXL0p24xEVmXxVOBFovNr0rNZmMTPfHs0bm3EYDJZq5gcNFGcxasR 3Mxl5ng+hhhBDWPdxDyBoGBcu2tJt41j7p7zL3fj9+7Xqru2zP461mtKRH7v6e31lmd8mCa7lo5K S3PI2oa0UFXdpDuMoDpXAec4tKtztf25z2Zf+M8mY5HhERHl5TM+vaejJ7y2ekX+V6kDIpcg6d8l aC3/AOjcGReV23j/ABdFflRmaRGM/Vj8LPhTfeZmKRGJmv7u/TDO7piyPEZCpoG2a2QsMtMj/wDT tkcddtfT/lgdCtwp+2f1Y/P5nbW39tqVxn92P/y+rfl2PDEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB B8d0IOb2ZczzPztl8RFlLGJxmFZENtQtZLNLKN25zyD5I8C4p8tmya5xEPoq11cTi02zSuy+3P7u 0RCvNN5owfd9mnWsx6bdqhzqV+MbZms3DQSdRcFF/Omucz2U4scfkc3X46/Gtu8T2/o1SlzLmK1j BSxZbLh1qeFl12WiDKLmPHl7ZNvX+Cueu2Yms5t39ez2dvC1XrtiderFYnx8J+/+sOtT8zYGvkWY ue/BFkJdOyqOkAldu83RvTxXpTtrE4z1fH04e62udkVmaR646Of8y2ObMbmoGVs7Jbz164DUwsDW +jMpbvKMzSNw0b+FquLb51t0n7pns+i4VePt1T5a4rqrXref3eX0SPeBJk6Pa5KxzBLjKLYRHjaF IAzTXD1O3B28E9QWnImY6zbEekR7uT4itL4111Re2futbtFf/Zfsxc12uVcRZyeXGD7KETZ6doDZ SNvmscQWsPhVpi80iZnx91KW49eRsrSn5czjXHp/Vl92V7M3sJYsZCaWzVNmQYu1Ybsnlqg+Q+QD Tp6ip4lrTXr/AEZ/N6dWvbFaREW8Y84jrEW9oboup44gICAgICAgICAgICAgICAgICAgICDAyeXx mMg7fIWoakGunazvbG3XwauVbXivecNdOi+2fGlZtPtEZUwZzE2KTr9e3DNSYC59lkjXRtDRqSXA 6Dgoi8TGYnoX4+yl/C1Zi3tjqx63NnLVqVsFfK05pXHRscc8b3E+IAqsbqTOImGuzgb6Rm2u8R9a ymC7Ruq1cqOk5gw0d5tCS9XZddptqulYJTr4Ga6rOdtc4zDavH2TTzitvH3x0L+ew9B7GXrkFV8p 0ibNKxhcfEHEK1r1jvOEatGzZ+ys2x7RlXczGMo1xZu2oa1Y6aTSyNYw69GhJ4pa8RGZlGvRe9vG sTNvaIZFWzXtQtnryNlheNWSMIc0jxEKa2iYzClqTWcTGJhfUoEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQflaoWe0/qVfwsyv68sfmlRSiXf0QICDHu1IrdWarMCYbEbopQCQdr2lrtCOI4FBpFbuorP NOHN5i5m8fjK09TG1LIiYIo7EJrvc98TGvlf2LiwOceHT0oMvBd3rsZkat+7m7mWmxtR9HEektha K0Um0Od+TYztJC1jQXv6ggvx931OHkWPk+res1qYj7Ge5EWixKx7982r9ODptXBzhx4oIS53L4ws bWxeTsYzFw325OrjGRQT14bAj7PyI52SN2k+XtcCA7iEExLyTnJmVZ5Oar7srSlkfWvCKsxvZStD XQy12Rthlb5O5pc3cD0FBjQd2hx7K82Izt+llGPsyXL+sc3pb7j2vmfPBI0w7tzBsIaNvR0IMWbu U5YsUq+Puz2bdGrBZbDFI8Bwu3JDLNkC9oBNjcfJPQ3qCDYLvKLL8PLov3prFnl61HdZZIYHWJY4 JINZQBp5QmJOnWgic13X18jcyRjy1qnic3LHPmsTEIjFYkjDWktkc0yRdo1jQ/aeKD7Y7so7Mzq8 +avScvvutyDsI8xuj7VjxK2MTOaZhAJGh3Z7tOroQZcXd7j44cZELUxbi8rNmIiQ3V0s7pXFjuHm jtzp1oPmJ7u8fjM58rxWpnzelZO52btu3dlnROkbw46MMA2oPmI7usdjG8uNjtTPHLRtGruDfynp gcH9poPwd3DRBt4KAgIGqAgICAgIGoQEEbzDlTicPZyIiM/o7d3ZAgE8QOkqJnCYjMuZSd/8Ubi0 4hw0Oh1lb/IFjO50xxpXmd+naNBZiunwyf8AYpjafxvq+t77pCTrjGtA6PyvH7yflP431Q3Mn1kB hIo3y4p0vanRoi1kI9nTRTGxW2iK90Ha+tVPDBBMMPIWWASxrWEubodPLGvkqI2K/jhsNDvuzl6p DZjrwRNmbuDXtdqPZ4qs7Zb14sTC+O9vmdwIayqD1Haej2yo/NK38SD6VuZ9pJNYHq8gn+VV/NKf 4tV+HvS5hLdXugJ8AZ0KY3SfxasPmrvF5/qcuvyeKnqMlbKyICxEdDv8ACt+acZlnfjxno2XuQ50 5j5t5Ws5DmDsvToLktb8gzY3awNI4f2ltS2Yy5b1xOHRVZUQEBAQEBAQEBAQEBAQEBAQEBAQEFsS sLi0EFzeDgCCQfGg+skY8ascHDo1B1GvtIK9UDVA1CBqEHwnRBb7eLTXe3TXQHUdOumiCoSsLi0O G4dLdeI9lBXqgoe9rRq4gAdJJ0CB2jd23UbtNduvHTwoDZGO12uB2nQ6HXQ+AoK9Qg+HiEGmZ/u9 kyl7JT1c5dxlbNxNhzFSARPZK1jDFrG6Vr3QvdGdriz76CjJd2leSQnDZW1g2T0YcVejrCKQTVIG ubEPyrXlkjGvc0SN48UEl/0Pim3OW5YnPZW5YjkZj6Y0MZc+EQNe8ka7o4wQ3+sUGHzZ3a4jmu8b OXnnkZFVdXx0DCGNqTPcHG3CQNe3G1oa49AHjKCHZylFkOYhmsXzq75XmoxVxLBHQsvMFZxifJH2 jJSwPmLu02aDdwPQglMnyjNeyMrKvNFunkJKMVbLww9g8zReW1s/Yva5sEjtXjewDX2kCTu5bVjq Q8v5m7g4atBmLMUJZNG+vHrtdsma8NmGp/KN4+FBjXu57lm9RoYyy+d+JxdF9LHUi7hFNLwN3f5x sD8F34PHTpQSuT5dp5XDVOWr+VfYuUnU7kkxMfpMgqzNeySRg6pHxaF2mhOqBzDyXJksxFmsdlrG FyraxozWazYpBLXL+0DHMma8aseSWOHEalBhRd3DcdUx9flzM3cKMfTNBvZ9nOyWIu7Te+OZr2dr vJPaAA8SOhBk4Xu6w+Hs4SanNNtwdSzTgZI4PMnpj2SSyyuI1Ly9mvDwoLGK7s8XjafLlWK3O9vL da1UrOds1kbbZ2bnP0HSB0aIL+H7vcfi38vPitSvPLtKbH1twb+UZOGAufoOkdmOhBncl4vGYbl+ thMbbFyviy+s+XcxzhIHFzmP2cGuaXcQgn0BAQEBAQEBAQEBAQEBB4B+tH/HXmb/AEP+310TDlah Lv8A9Sr+KeV/Udj87qKUS9pogQEBBE5vlvCZyu2DK1GW42HdHv13Nd4WuGhHtFZ7NVbxizo43L26 LeWu01lbxnKfL2MoS4+jSjgqWAROxuusm4aHc4nceHjSuqsRiI6Lbudu23i97TNo7fRHQd2PIkEj JI8PDujIczcXuAI4g7XOIWccTXE5w6r/ADfLtGJ2WbQ2JrW7RwA4ADqC6HltYtd2nJFqxLZsYqOS xO8yTSl0mrnk6knRy554tJ9HpU+Z5VaxWLz4x6dP/hL5LA4rJY4Y69AJ6XkfkXE6fkzq3oI6NFrf XFoxPZyaeTs1X86Ti3v+qjM8t4XM146+TqtsxRHdFu1DmOHDVrmkOHtKL6q3jEp43M26bTbXaazK 7iMLjMPSbTxtdtau0l2xuvEnpJJ1JPjKmmuKxiFN/Ivtt5XnyskVdkICAgICAgICAgICAgICAgIC AgICAgICARqg07M8jPtZl+ZxOUnw2SmYIrUkLWyMma3zd7H8NR1Fc2zj5t5RMxL1eL8p4avxbKV2 UjrGekwoh7uqEXKuQwLbk73ZNxfbvy6PldI4gl2h8nqUfxY8Jrnutb5i88iu7xj7O1Y7YYR7srFm CpUyfMNu/jKjo3MomOKNjux8wOLRu0Cr/E7RNpmPZtPzcVta+vVSmy0T1656/q29+ExEliO5JThf bjAEdh0bXSN28G6OI14LpnXXOcPIrydkV8YtPjPpno06DuxyNfMXMrW5ltxXL0m+eTsYnHbrqIw5 2pDR0aBc38WYtNot1l7M/N0tqrqtprNaR06z/iyM/wB3NvLcwR5xucsVLFeMR1YmxRyNi0GjnN36 +U7rKnZxvO3lmWXE+Yrp0Tq/HW0T36zGX3mHu8t57GY+hdztgiiS+WXs2H0iTXVrpW+b5PgU7eN5 xETM9Dg/L142y9666/d6Zn7f0T/LOFyGKrSQ3MpLlC52sb5Y2R7GgabWhgA0WurXNYxnLzuXyKbb eVaRT9Jmf+qbWrmEBAQEBAQEBAQEBAQEBAQEBAQEBAPQg5rma9K93t1amYYyWlFjXSY6GbQxGbf5 btruBcAuC+J3Yt2w+j497a/jbW1TMXnZi0x3iMPs1bk6th+c4uXnAWBVn+Ua8ZPZMk7F2mxvmDx7 VMxSK38VaX5NtvHnd28q+M+uM+vr/i0Oajfr8j4XIXMbjYcVB6JNJeqHTJFgcND5QA3O/C0K5JrP hEzFcfTu+hrupflbKVvstsnyjxt+x1+/zYauRp0WYu7ajtNjcLkUe6Fgf0do7Xhp0lelbd4zEYmX xurgedLXm9K+Oekz1n9Gjcw4bBZHmF+BwVdj8m67HfzWXlcC6sGuDtjJDx3u00DR0Lj20rNvCvfO Zl7vD5G7Xp/NtmfDwmlKR/d9Zj2+rP7w62A+UHVoKTMnzXma/otaKdwdHDCOmZ27hGB08OlX5MV7 R1taMfo5/hr7vDym004+q3lOO8z/AKfqkX8uYuDCYPE2n1b+bo1izFx3nEwyyBoa9xYNdwC0mkRW sdJtEdM9nLXm7J27NlfKmq1vu8e8R6dVfdA6JnLE1JuvbUbtiG0OBjEofq4QkcOz4+Sp4f7Me0rf +QxM8iL+lqVmPfGPX6+7fF1vCEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQflaoWe0/qVfwsyv68sf mlRSiXf0QICD452mp6gNSg5RUzHeBleS7PPdXNsreRPep4E14HVfRK7n6RTSlvb9o9jOL2vGh6uC C5F3k5N+Slla2aes6yTSx0TIg6SIYUZDsXvcNQd+pBHHXh0KRK5Tvdw1SISV6z7TZYaD67+0jijd Pk9zoIHSSENZpFGZHuPANUCa5R5xqcxYy3cdGKklCd9a9H2sczGujaH72TRnY9jmODg4fyINI5H7 3Jr9nmCxkrEV2q2k7O4arS2PnjosfJG6vI1hJMo2Mf5X46DIs96mXv0MZbxGPb2k2XqVHQwWq1qO zFZhleY2zNO2J7XMG/cAW+NBM5XnfIzd3fMWcq1nYzLYhluF8EpZN2dmrwJDm6tkb0EcOKDWMR3m ZOnk5XXrl3I42PDWMnJFfx/ybKZ62xxZVcWQiYFjnbuB28Dqg27N95FbFvsxjHT2p4IMdMyKJzA6 R2UnfXijbuIALXs46+FBH0+8c46pzPe5lkjquxlrZUxpkiEm1tSGZ8MbtWiVwfIeIQfecO9eHES0 G4ttG5Bdimmbfs3BXpl0BaDWZYayWPt3buAcQB1oKMp3n5aD5UtUsI2ziuXoIbGfmfZayWMywNsv jgY1r2SGGF4e4lwB6kEZW55nr527Pet2JcazOWGVwx4DGVIsMLmxzNpL26gkN1HlIM3E84c4ZLnT leLIY/5KxmVx967DDHYE4la1sBibONjNksYk18kkeV4kEoees/ZzlyHE4L07CYu8zHZC6JwyftXb e1fDAW6OZB2g36uBPHToQQmH78KeQykO+tA3D3JLMdaSG02W6wVmPeJbFUNHZslETtujiRw16UFD O8Dm2znOW7lrFmliMjSv5GvBDZZK6xDHWbLDFOHNjbHLo4O84t49PBSFPvrlfQz1iWhUszYfGNyz Y8dc9JY5rnFvoz5DGxolaRxLdzfGoG1XObcti8Bjspl8Y2vJZu16t2Bk/aCtDal7JkpeG6OLS9m4 ePpQa5R77KNqs+d2OkibDZvtmYXgvFGhB6Q221unETtLAweF3SpF6XvVyeJgfLzNgxRNjHvyWKir WBO6ba5jPRZNWR7JtZmdGrenjwUCu73m5rEGzQzeDZDniyq/GVK1ntYLJuz+jMYZnMZ2ZjlP5TyS NOI1QZvIua5nvc1c0U87CKr6AoNhqRS9vA3tYXuc+J5bG7R/DXcNdQg3lBDc3w9tyzkYwNSYXEe1 x/kVbdlqT1h52ytCk4PkdG0SbQ4vA4rht0etWIlERxQDzSA32CFWLL+MKXdmDowj+1r/ADqfJHi+ btXaFjHOHtqPKVvFdY+LoMcfH+inmTEMuJ8f4rB4NAkWIrDLZPMBwZG4Dxa8EynxXGzcR5DR7SGF 5s+n4LdCQDpw4E6FTBKe7w955Bia0gFjq7mjw6DVW2T9rl9U99Wkl3I1+Q9L8rZJ/usXXp/bDg2/ udbWjMQEBAQEBAQEBAQEBAQEBAQEBAQCg4Rezd3lnnfnPI1Nz3cw2vkarGOIGVbVgNE/2xNID/VU iK5ezWT5W5QiwGGykteag7M2JTGKYMgq2jE2WWe6dm3tNdWMYXnXpCDa6vPOfykhtP5jrYRtGtiJ Y6ToY5I7r8gxr5XP1a+ba57jEwRabSOOqgY9HvJzz88yUZdr8Zejy7oG3GVIoG+hNeYXRwwmS41r CzR5lOrupoUjHrc+85jGz1H5jXMTHHPYZjj9pjsueJjStwh1UmXZ+SbYYCNOvVB9vd4+flw1eOlm LQyFWDJTW3Ogx1aQmnN2TO3lmfJXcGHyXejg7zxG1BtXJHMPMnMXMfbS5NseLrYnF3ZMfDDHtlny EMjpCZSC9rWuj4NBUDR+YMTeuZzN8jUN8b8Pct83VCzUD8pE2WozUeG7JLw8SDOwXMtzISQcwVL/ AMi1OecvMDl3sic+Kpj6nZ1oGdsHRh0skb9C4dGunFBfo898yZONlSzzHFhoalXI2Is4Ya+mSNO2 +vG9rZQ6MMEbA94j6d3AgKRGcxc5Z7P8s5abJZaLECGpitMEY4gLXpzYpZX7pB23lOcWx7Do3Tjr xQb53kWq3LWWwvPc2rKmMMtDNPaNT6Dbbq1x/wDl2I4z7agaXXyHNOBpYLHRzS427zJDf5izN6H0 ISutSvY9sG6+6OHSOKQbvwtrOriUGTZ5058tYu7k2ZiOi7E8vUsw+tBDBNFYsSyWA8ue8OPZPbAO DCOngUGS7nvnGbmyyYrPY1K+agxUeKeaTYZK7xHudq93ppme2QyMLG7eGnRqVIjsZ3kc6zV3ZOS6 Ntuplpn0JfQQys6lFI+LsGROda3ROjDZBONDr1cEGxWebOdMHy/y7LLHZztvLWKL7WQjjpwxbbZG 6pHGXxuB/FcR18XKBDc484cwVOZpr0mQtUMfSbjzJjqtip21N07m9oy5SlGtrtN+gdDKdB0cQguR 805g34cseYZvleTmQYiTlbWLsW0zZ7Ex9gGdrvEH5btdfuINWwHMuYw/KMRxlgV+zxF2TtxGx7oR JzE6CWwCQT+Sie52h4cNT0IOgd38daLvH5lr185Jn4osdjQLU8kU0rNz7DjG6WJrGu6dw4ajVBAY /m7Msw45l/6mkn5hsMyjpOVHRslhDqjJjHCyFgEkDoOyaXPefK6PwggjKnO/O1HG3Z4cq+322FF6 aWxap3pIJTLEw3IYqrB2cTWSyHY/h5I6eKkX8jl48LzBnzj+Z7OWkOKxNWvkg+rNZidbvyDsu2PZ wt3hxIe/zA7XjoEFdbm7meejcxMOamrzR8x43HR2fSK96xDBdjBljM7WCOQ7tdPJOnRqdFA3DvJz Wa5PxWHyFa7PPVhEuNtdsWufNPYruZTlkIaPK9JY0EjTzkGmw87c9Mw+RjtZR0dnlsVsLncjsbsb ZtZAMmu6EafkqYa8dTd+pUjMv8z5fHZC9gKXMk9vAm/i603Msj4ZZqTLrJTPF6Q1oj1Jij2uc3yO 09hQPv8A1LmXZSPls8yWP+nflp9L/qoPgbYcwUBZbU9I29nu9I1YX7deGiDZ+5VzHYTOll35Sb8v 5ADIeTrPo5o3nYA3U6cdAg6KgICAgICAgICAgICAgIPAP1o/468zf6H/AG+uiYcrUJd/+pV/FPK/ qOx+d1FKJe00QICAehBr+X5sZj8szFQ4+3kbjoRYkZUaxwjiL9jS8vfH0kHoQWMtz3isZekqy17M rarYn5OzEwOiqCwdIu2OoPHp8kHQcUE4/KY+O3HTkswstzDdDXdI0SPHhawncUGNiOYsRl47clCw 2ZtKeSrZII0bJEdH6+LxoIOHvFoTPjnZj7rsNNMK8OaEYNZ0hd2YIAd2vZl/kh+zRBPDNU2xW5rT hUgqTGF8072NYSAPKB3cAd3XoUFyTM4qOr6XJcgZU109IMrBHr4N+uiBLmcXFDHPLbgjgmAMMrpW BjwSANridD09SCxNnakOdp4VzXm1drzWYnAeQGV3Ma/U+HWUaIPlHmGhbtZCsNYpMdZbTmMmjWul fG2RoZx46h4QZc2ToQRvkmsxRxxktke97Wta4DUhxJ4HTigtwZrE2JWw17kE0z4xMyKOVjnujP4Y AOpb40GOeZMbFiYslbeKccrHOZFM9jXktBOweUWl2g6AUCnzLiJ8ZRyElhlWHIsa+q2w9sbnbxqG gOPF3HoCDNfkaEdhlWSxEyzIdI4HPaHu4a+S0nU8AgykBAQEBAQEBAQEBAQEBAQEBAQY1m9BBNBA 935ay7ZEwcSdBq4+wB0oI5/OHLbMwcMb8fyoHtjNUBxcHuG5rSQNASOPEoK2818vvy5w7b0RyYJa aoJ3bgNxbr5u4N47ddUFWb5mwWEbE7KW2Vu3JELSHOe8tGp2sYHOOnXwQV0uYMLep1rlS7FNWtv7 KtK13B8nHyBrx3eSeHSgyal+tbbI6u/tGxSOikIBGj2HRzePgQUuydFmRjxrpmi9LG6eOv8AhGJj g1zx4gXAIMrcEGJdyuPpTVYbU7YZb0vYVGO6ZJNpdtb49rSUCLJ0Zb8+Pjma67WYySxXHnMbJrsJ /raFBmahA1QY1a9VtSTx1373VpOymGhG14AO3iPAepBTSyVK6ZhVmbN6PK+vPt/Alj85h8Y1QZWo QYtbI07M9ivDK189RwZYjGocwuG5uoPhHQgy0BAQEBAQEBAQEBAQEBBC5/lXBZ+NkeVqNstjO6Jx LmPYfC17C1wWd9Vb/uh08Xm7uPMzrt45/wA1FHk7l6hipsVTpRwUbLXNnibuJeHja7c4ncdR40rq rEYiE7udu27I2XtM3r2n2RtXus5FryxyxYmPfEQ6MPkmkaCOjyXvc37ip/F1+zr2fOcu0TE3nr9K x/0htuzRm0cABoFu8pqMndZyLJafbfjA61I8yvk7acEvJ13ECTTpXP8Axdfs9SvznLisV8/tjp2r /wDC/lO7jk/K3XX8ljxYuPaGOmMszTtaNGjyXtGgCtfj0tPWFOP8vytNPCl8V/Sv/wAL1vkblq3i quMnpNdTpDSowPkD4/6sgdv+6luPSYiJjpDPX8lyKXnZW33W79I6/rHZJYfDY7D0mUsdA2tVj12R M101PSSTqSfZWlKRWMQ59/I2breeyfK0pFWZCAgICAgICAgICAgICAgICAgICAgICAgIPytULPaf 1Kv4WZX9eWPzSopRLv6IEBA04oNEn7qcXJBZxkeUyFfly5K+azgYpI21ndo4vkja7YZmRPcTuY14 HSgk4+QcRFnmZmN8rZ47hvNhBaIg80vQdgbp5oi46eFBH1u6blurhJcVWksRh2QGVr29zXTQWGH8 kI97XM2RM8hrHNI28EEjHyPXby1k8G6/akGW7U3Lxcxs2szQx3ZhjWxxjYNoDW6BBYyPdpyzakpP qwnFvpRT12SY/bXe+GxF2TmOewbuGgc09IcAUGPS7rsTBkGZKe7ZtZBtqrbdYeIYy802SMia5sMc bD/jOLnabj4UEnY5JxtjA5zCullFbPS2ZrTwRvY615+zUaDTq1QRI7q8fY1+WcrkMwW07GPqmy+J grw2oxFMYxDHGN7mDTc7VAh7rMeLE1m3k7161OcdulmdENG4mc2K7WtjYxoG5x3cOKCRud3+DuVM 7Xsh0gz8jprD3BjnROfCyAmEkHb5MYQU5zkOrk9or37OKj7B9SevTEPYSwyHVwfDLHLHu8Dw0OQR tnuiwUjJalW7eoYu3Wr08nj68rOytw1WCKMSl7HSNcYwGPcxw3N4FBm/RrgDffbeZXtkvS5B9clv Zl01L0B0WmmuzsurwoLeD7taeKzONyfyrkLpw9aWjjKtp8booa8wYCwbWMc4gRtG5xJ0CC5Y7usf JlrF1l+7BTu2o8hfxMUjW1p7MW3a93k9qAezaXNa8NdpxCC3jO7TGULMTWX7smJrOmfUwj3s9FjN gOD2nYxssjB2jtrHvIbqg1DO8ud2WGkqYvmTmux6NFTs4zH42zYj0gq2Y+zfGDGwP1a0ANe8k6AB RlOF+ry73fZNlsHnN+QN3HHET7rFRrfRg4PjDGRxxtY5h14gcdeOqZMS3zOUcBzLgLuCmuRvrXoT BI6CVhkaD0OaQTo5pGo8alCLo91nK1S7NaEb5hYxMWDlheQWOrRN2F2gA/KPYGtc7xILEXdRhX15 YMrevZeI0XYyr6XIzdWquLXFsRiZGd+sbD2jtXeSOKCqTutxdqG4crkr+SyFuOvFHk7D42z121Je 2g7Ds2MY1zZfLJLSXHpQSvLHJ8eDv5TIPyNrJ38uYXW7Fwx6/kGFjAxsTI2NbtPQAg2NBh5hodib rTx1gk4f2Sot2TXu835N2xr+vyD9xcF3r0a414Op6ljlqpndvDuGhAOhU5RhtFHJ8iw8tVqs+Nnk yjIWR2bLInSazOYHcNDx1Xo01VmHk7ORaJVY/PcgVajflPFWpXs4yyOgewDXo61b8NJZ/wAm3uyT z53L7APkiyXeExPH/tKY0Vj0Wjk392DkMhgMi6G5go3xY+Rrg2N42uDmu0PTquHdXxs9PjX8qZla DjoNPcWcOhkF29m3TTiNPdVoUsmO8szDkqqIh+U31w3Ua/gqdvZzR3bR9Wlgb3e2COh2TtHX+6F2 av2w4Nv7pdZWjMQEBAQEBAQEBAQEBAQEBAQEBAQEGI7GY8uL3VYXPMosbjG0ntmja2TUjzwOAd0o LE3L2Cm2dtjqshie6WIvgjdskedXvbq3g5x6Sg+jl/BtkrStx1USUxpTeIY90I110iOmrOP4qD4z l7AsnNluNqtsOk7Z0wgjDzLoRvLg3XdxPFB8i5b5eirTVYsXUjrWSDYgbBEI5COgvaG6O9tB9dy7 gHR14zjKhjqf+kYYIy2LXiezG3yfaQX6mNx9PX0StFWBa1hELGs8lmu1vkgcG7jp7KCsU6osOsiG MWZGCN8waN7mNOoaXaakAnoQWZMLh5aAx8lGu+gOim6JjoRodeEZG3pOvQgpsYHC2YIK9jH1poK2 no8UkMb2R6cBsaQQ3TxIPtvB4a5NHPboV7E8TdkUssTHva3XXa1zgSB7CDJtVKtuu+vahZYryDSS GVoexw6dHNdqCgs38Ti8jE2HIU4LkLDubHYjZK0EdYDwQCg+vxmOf2gfWhcJo2wygsad8TddrHcO LRqdAgodhcQ683IGjXOQYNrLhiZ2zWgaACTTcOHDpQUtwOFZPPYbj6zbFppZZmEMYfK13S2RwGrg evVBkOp1XRxxmFhjhLXQsLRtYWeYWjTht6tEFmzhMPZtxXLNGvPch07GzLEx8jNOI2vcC4e6g+jD YkX/AJRFKuMiRtN3smdtpppp2mm7o8aD5Hh8VCCIqkMbdjoiGxsA7N7i97OA81zjqR4UGFR/6Sxh eKDaFLfoHiuIotdCeB2Aa6ElRmE4l9ik5SiuSXovQY7s/Ca0wRNleP6TwNx9sp5QeMqKZ5OpCb0J uPrekf8AqOxbFH2nh37QN3T1p5Qnxli7u7ypBLWDMZBBM3ZNC2OFrHt13aOaBo4a8eKeR4ytQ5Xu 4gIbBJjYy0sLRGyIEGLXsyNo/A47fAq+cJikr9rm7kq0zsbV2tPHq14ZIA9u5h3NOhB4tcNQn5IP x2WRzZyGW2GizVLbRJttDARKSNp7Th5ereHFPyQn8VvZTWzXd6yg+jXFNlCTXtajIWNidr07ow3a fbCflg/Db2YOV517rMXiRTyL6kGJ10bWfXHo+vT/AIe3Z9xTFolE0mGy8tWsBdxMN3AiH5Ns/lIn V2CNjtQBu0AHgVlEsgICAgICAgICAgICAgIPAP1o/wCOvM3+h/2+uiYcrUJd/wDqVfxTyv6jsfnd RSiXtNECAgHoQc6575UvZTI2pauEhuT2qba9PLCwYJqsrXEh7wXDyWa7mlnHqQWc5ypzS/5ax9WF l2HmOCnFPkjI2P0d9dgime9h8p25rdzdvWgyZ+WsrFzHdeMRXykN+1Us18rYeGmrHXYxpYW69pqw sLmbOBLuKCV5YwFqpX5gx1uq2tDeu2pobMRZ+VhtakHRvEOZu08pBGYCrz1h8Vj+WoMbB2dFza4z ckzXQuqsdrvEA0k7VzOG3o146oIvP4ubEzDJZFteSq7mGW7FSsyNZDPHNV7JjnSOBjY9jgXND+H3 EGBgcRm73LdGfGYyFtQ5jJWXxRCF744pXvET63pA7EtJPF208PNQSfLPIOVi/wCl25mlDLFhzlDP G9zJmtNqQOrkAANdw8DeCnIneZuTvlzm/EXLUTn4unTtxSujmfC8TSviMY/JlriNGO61AhjyLlcf VyYxlYSxszlXK0Kz5y58sMDI2vb2khcQ4lrtNxQfYOUc5eLZslQijbNzIMvLUdIyQNqiuI27tPJc 4OHFqCvB8h3MffxFmOlBA+rl8lasyRlgcKtpkzYQCOkeWzyepBGQ8i8w06ON7bGQ5csw82KkoPlY G15pJHPE4L/JLXNcGuLfKCC5LyVn69Ou1+KhzDpcFFiRXklja2nOwEOkaX8CxxdqXN8rggn+WuTb NHmU5LIxxWpIMVRo17ztHPM0DXCZzdeLd2o4oN4HQgICAgICAgICAgICAgICAgICCCvQyRc00Lr2 l1Z9eWqHAaiOV72vaT/XDS1BpQx+ZqczSvxMGVgyVnLCe4J9r8bJTdoJJN4aG6bG6NGu8FBTTxGV ZZp4Q46wLVbmOTLS5F0ekBqmR8naCboLnNeGbenw8EExz7Wl+V8ZeZWyMRrxTMjzOJAmmgc8t1il rFj98cgHTpwIQQPyVmbmNwN3K4yYmnnnWP8ALwmvYfVka5rbNitCfJe55G/3UGTZpZ/sIflOHITY YZm/JkIK3adu6u7X0V2kZEhhB6Q3xII/LYHm6zLjbGEgu1Y6+Ltsmitu3W5YTZY9tX0j/kyyxjyS dXNHBBf5pgzr8nWu4ynkn/5Wp6FjpGzsa0g6va2eJ+kMjf8Amdu0goNh7wcNlcrc5VbS7eB1fJia zbrhrn12ejyNLyXBzdNTt4hBBZDlnmqtZ5yNSe7fs2sbUbj70mxkj5Ii8uiidG2NuoH30DJyc1Ze LmaelWydWCelj4sdva+GUytk/wAwYmHi1wB4lBbyHKOYqTZyXHfKRNO3j5cG0WJnt0eWG0WhzjvB 47w7VBl5anzI45Dt470mJOf7W5BXLxNJjxA0Dsdh3mMS6bgziQgwKGHy1fCta6lkmYN+et2L9Qdp 6bJSkb+Rc4MPauZv0LgDu0QX6eB5myEGKp3RkI8O7MWXxxukeywzG9i4wssvad4HadAJ100QbRSj I7y7Yra+jxYiGO4ddR2pmJh1/pdmHe0g28ICAgICAgICAgICAgICDByORbVfXia0yWLUgigiB01O hc52vgY0ElBB5vnkYa6yvYw2Qlilniq17cTYnRySzcGhgMgefH5KC+/m5pz0+HrY63bfVfFHbtxC PsInStDxuLntdwY4E6NKC9n+aIsRLTqx058jkL5f6JSrbN7mxAOkcXSOYxrWgjpKDGh59whp1J7g lx0lu4cc2tab2cjbQ11Y7jt04ecCQgk2Zui2tYs23tpQV5nwPlsPYxpLDpru3aaO6teKCy/mfFty rMf2g/KU3Xxa1b2PYteGE79dOkoMx2XxjLEVZ9uBtmdu6GEyND3tPQWt11PtILNzOVquZx+Lka8z 5ITOruaPJArtDn7vZDuCC3U5kx9i/kqW7spMZNFXnfJo1rnzMEjAwk8dQ7T2UGZLkaMTXvlsRRsi dskc57QGuI12u1PA6dSC3XzeIsyshrXq800rO1ijjlY5z2fjNAJJHjQWI+YKAxsd+1K2kyUuaxli SNpLmkjaDuLSTt6igox3NWGt4ahln2GVKuRY19b0l7Y3Hf0N4np9hBmzZSjDOyvLYiZZl0EMLnta 95Ouga0nU66ILeGy9bLUW3K+5o3PjlifwfHLG4skjeOpzXDRBIICAgICAgICAgICAgICAgICD8rV Cz2n9Sr+FmV/Xlj80qKUS7+iBAQEBAQEBAQEBAQEBAQEBA1Qa/zXzzytypVFjOX46ocCYoidZH6d TWjiVEzEJiJl537wfrH53NMdQ5XjfiKLho+24g2X8Trt01axp91c9t/s3po93Gp47NuxJYtSunnk JdJLKS5xJ6ySsJvMuiKRD6yloAd2h9k/yKvlKfFkVm3q+klaxLC7wxyOb94qY2SjwhKQ83c81R+Q zl1jW9DRM4j7uqtG2UfihMU+97vVrObs5hnAH4MjWPGnttVvzSrOmGy0PrId5dYaTuqXNv8A4kW0 n2dpCvHI94Vnjw2XD/Wi5heScngYHxtGpNeV7T/xByn+TCk8eU7B9abA7dbOCuRnrDHxv/8AdVo5 FZROiySr/WP5AyNeWCaO5TdLG5ussWrQXAjiWkq07a47qxqtns55kZd8Ye0+TIwkHxFcluz0qIB3 ma9Kxavh4nwg9QQbVQ5OyE2Hiv18xFXinhZMazo9z2PYwN+6vSreMPG2abeU9CLkTKZqi5suagjj k1EgkjLSNuhHWrxePdnOqY9GP9B8+3d/1DUGgBdrG/r4eFWjbB+OVGQ5Z/6crUsbJbjtvaJHumhB DfKfrpx48Fw8i2bZerxIxTC3Hs4dPsrF1MtnBoPUOPBWhFuyU7y5Hu5OrbHhu18B1PT5vBTt7OeG 7fVxaB3btOuu+9aOvh8sBdur9sPN2ful1JXUEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQUSjdE8eFpH3FEkPMPMGKlF2xJFKWflJNWHwhxXHa0vU1ViYRsD7LW7C7d4OJVfNf 8av0qdg27tNevpCfkIohrmBqXsj6dLcnEgPBjHeRw/op+RE8eMsjEct0qF192CzNJI/UOZI7c3j4 Boo80104nLYmPaAN7ujrGijyaeMr7JYiNWP0HiATKcL8UjGgAP01Pg6ykSlR3u068fJFUM4l0u57 naH8FaZw5LRnLr3c1D2PdpgmdH+XafdXZWejzrd27KUCAgICAgICAgICAgICDwD9aP8AjrzN/of9 vromHK1CXf8A6lX8U8r+o7H53UUol7TRAgIB6EGlZLncYvnifEX+0dj/AJPhswiCvLO8Svmex+4x NeQNrRpqgj+VufrORr4yxemEUdy9lYtBDsHYUS8s37iHRlrG6nhxQZUXePHbi2Q423TdcoWr+Kt2 Ws7OWOuzcHENcXN13AhrupBc5F57mzkGNq5GlNUyNvHMvslkaxsU7fJbI6MNc4t0c4cHdRQSeAzN 27zDzHQsFpr4uxBFV2jRwbLA2R249flFBh5LnvG1s3FhrtCYRWLMdJliTstjpZfMIhc7tXM14b9u iDIp85QWb769fHWvkyGaWqcs1jTWElcHtNQDvaxpaW7y3bqgxMf3i0rliu35OtwwXq9i7j7UjWdn PBWaHOc3a4uaXAgtDhqgzI+eMQ6GpPKJIYLeLdmRK8DbHWYGOIdp+FpIOAQRtLvSw1mrendXmhNG kcl2JdFI+SsOtvZvcA7o1Y7QoMjP81ZGHu9yXMdWpJjrkNZ81WG21r3DTzHuYxxB1B1266oNaxPP +cdkMlS+UI8lHXw82RZPLSfj5GWIxq1jY5D+WZ1uI6EE3a7x48VgsddyVKaczY+C9csxdlFEO0YC 8R9q9m9w4nYzU6IM+xz1X+UZKNDHXMn6MyCS9NVY0iFtkB0erXEOe7b5RDASAgw+XOexe5gyOBkH pORr3rMfZwAAVqcW0RyTknhuJ0b1lBhc6c25THc3VsTHlhiqT8e62ZW0JL73yiXZpow6tG1BI2ec PkhzzftPvR1MP8pzmKuIjKBLt3tBdq1xHDZp7aCzd7xGjF5SSSraxVyhBXtNbOyOVz4LMgYyRrWv 2njqCCQQgkG88U5OaZeX4qs8k8EjYZ5g6MBjnsDw7si8SmPT8MN26oIzlnvBtW7MVPKU5m+l5C5R qZBrWNgc+u95ZHoHF+vZx+dt0JQSPMveFiOXflAX4py6hHWl2RgOdMy1IYgYhrx2Ob5fgQDznXs5 KnXpvk7J999Fzwxr2TubUNkhjtw2gcBu8PBBr1LvH5jsQcuznFyPlytvI1pqEPZmR7ajXmNzHuft YAWeUSUGxXebnT9397mXGtdBNFUsTRRWGgujmg3NLXtB0O17NOlBrvJ/PeVt56KjayTcnWlxz70p dSfQkjkZt8iMSH8sCHHXb0cPCg2SPn7Fvjx8gim2ZHHT5WHUDyYawYXtdx849oNEEfj+echk81yy 2CnJRxuajtymO01vbPjhiY+GRu1ztodv6DxQbygICAgIPjuhBocvMvPNrL5+LEV8dLUwczYRBYMz Z5tYGzHR7dWNPlaDUIMql3h4q1Vq5EvEOOmxUmWlicx5mYyF4a/iPI0bxBHSUFLu9XllofviutEU TLUhNWUbasvmWncOER8KDPynP3LmNtPgnle4QsjkuWI2OfDXZNxjdM8eaHDj7CC3kO8TlyhesVJn Tn0R0LblqOB768PpABiMkoG0B+4cUGSedcOc27DxieWzFKyCaaOJz4Y5ZG72se8dGrT09CDEZz1j 4YAbJdatTXLNSpUpRSSSyGs4h+jDx8gec7zUFcveHy+2vRli9Isy5F00dWpBC985krf40bowNWOZ 1hyCmXvE5cZUx9mLt7HyoySSrXhhc6YtgOku6PgRsPAjp1QZ+c5lq43lmXONaZI+ya+vE4FjnySk NiYQ7Qguc4Digjcl3g4nCSGllRMchXqx3MiK0MkscMTztdK5w6GBwKCsd43LYp37cxnrx4wRPsxz QvZJ2dg7YpGMI1cx/UQgss7zOW3WHVpY7kEsE8da32taRgrvn0EPbEjRjZN3klBmR80uhzuXxV2u 7tKEEd2r2DXSPmrSEtOjBxL2PG06IM/M28yzHsfh6rLF2Z8bGtsOMbI2vPlSSaeVowfgjig1fCZ/ NXcbmrNCLHV7tG66K5kndqaVlkUYL5WOb5erB5J6gQUGI3vB5ni5Or5m5TqxWcleZWxe1s7o3Vnk 6WJIwDKA5rS5rRx00QbRytzBLlMI+/NPWuSRukDzjxJtBj6YyyXSQSDraQgqwXOeCzk5hxkr5pGw tmn8hzRDucWiOXXzJNQfIPFBE53mnmbFZaIyU6wxk92KlVgMjnXLIkA3zRNb5IDNSS09QJQMpzdn sdzRRx9mvVFTI2/RaldsjjcfFt1Nr/wwxp/BPFBHu7y7kWSEk8dVmIdlThWwb3eniQEtEzmHydhc PN6dvHVBtOd5uweCmjiyk5rCaOSWGVzT2bjFxdG13QZDr5LOk9SDLsZOVuJ+UK1Sey90bZIqbQGT OL9NGkPIDTx469CDVa/PWbl7vP8AqZmJM+TLbBdQhkHZxmB72kySOI8lvZ8SPaQU8xc/5DH4jlue tHCLmdY2R7pmTyRRM7ESv8mEOkPToEG0ct5N2Tw1W86xXtOnbudNTLjAeJHkb/KGnWDx1QSqAgII bM1LHyjjMhEwyipJI2aJvF3Zzs2Fzf6h0PsaoMO3ibtznelenj3YvGU5HViXDT02d4Y523p1ZCCA f6SDWs1ynkbXMcstTCsr3pchXtxcywz6bYIgwSCRhdv3ljDHsa3aQdUEzz3iLmQ9BPyMzM4+JzzY gjk9HuxSEDs5a0xfHppxDxuGqCBrcr80jC4t9upJbNDNtu1sfanjsWYaO0sDHTvO17ml27zujhqU FyXlXNV7MV+THDIw181krr8aHR6yQ3BpFM0SERlzPA49aCPzXd/zHkZcdcq0YMf8n0pHsw7Xh1OW b0vtmVJx1tczjw8kO8SDK5g5Z5ks8zR5LG4oRT2XUpJXTurzVAIQN4la7SaKSLiGGE6OQbDzdyn8 v8ycvy2IHS4yiLhtuZK6JzXSxtbFxY5rzqR1INducgZSnXzzMXT3wuyuPyWPrvm3PmZUEbpWh8jn EOJYdNxQVu5Tz2Vbamv4sQMt8xU8mackkbz6LAxgcX7S5uvkcWoLlDkK7UvUbMOPhhkg5htX3yM2 Nc2nM14boR1eUPIQYkHJufox4axYxLMtHWo3qM2NMkf5KW1YMsc47Q7CCzyXacQCgoo8nZzG1sPL ZwkeYEWCbiZaAkiIr2N5cXDtSGljgdrnN48EEryryPfx/M9S9lYorIo4KnQjvOIeRZhke6TZu1cN GkeUgmuQY3uhzN0AirkcpZs09fwovJjEg8T3MLgg2rUICBqEDUeFA1HhQNQgIGoQNQgahAQEBAQE BAQflaoWe0/qVfwsyv68sfmlRSiXf0QICAgICAgICAgICAgICAgwMvm8Th6brmUtxU6zBqZJnBg9 ga9J8QUZIjLgXPn1mrD3y0eToAyPzflSwOJ8JjjP3ysL74js6NenPdw7LZHLZm7Jfyl2W9blJc6W ZxcdT+KOho9hc9rzPd01pEMU1pG6A9fFU8mmF2KE6E6nxBRlC9FDu8I8GvD76jIvNrE9JIUZFBqu L9A72NVGRUac7ekag+D/ALE8ln1lJxPmnXqTyMM5lYthDACHHzvAqzJhZdA/tDo17gFORdiryvjk Dm9m7QaF3D3FGYG+vk30Krj1x6aHw6aLonstREHzT4AOj21k0R9y5bjtY6pVja+a/YbXZvJABd0E rTXTylnu2eMZb1N3Yd4lW2yrJPRbLJ/ht9Jc32gD9xbfxp93N/M+is92neY2UwtkpPm10MYtncPE R0p/Hn3T/Mj2VR8gd5zg4NbSl2g7w22CQB4ePQn4J90fy49ll3J3eC6pJcko1p61VrnSuZYa5wDe Ljp7STplavLj2YUL2Pjje3UB7QQD4xr9xYzDsjsymjyDx08k/cSET2SHeGQeWqmp1j3Ruf4wI+Cb Z6Od0P6vcAi7sKOnRJNO8f2pCu/X+2Hm37ulK6ogICAgICAgICAgICAgICAgICAgICAgICAgahBQ 6WNo1c5rR4SQEGHYz2ErNLp79eMDpLpWD+VMiGtd5nIlZ7Y5c1W3OO0bXh3E+woynDYKl6nbiE1W dk8TuLXxuDgdfYUoZGqAgICAgICAgIB6EHnfmpjY8rcjPQJpOHskriu9TT2hpTZOnQkN14Lnl0qS Q6aNrXFrHva15HSGk6OKtSMzhS9sRls2Sx/JUMkDKeUMzXECd7g4bW9ZGjV2xxavPnmyz46Xdexo 7bmF0J8BDvd02qP4se5/Ot7LeQg5JFR78HmfT7LND2JBB268TxAWe3TFYzDo4/Jm9sSi2kbOgA69 Kwdq+S0sbtHHUaHx6qYUsr76pCeTsfGCQ0uG7Tr8gLVyz6u3d17Azu/wTQNP8rH95dcPPt3bUpVE BAQEBAQEBAQEBAQEHgH60f8AHXmb/Q/7fXRMOVqEu/8A1Kv4p5X9R2PzuopRL2miBAQD0IIeLCVo +ZJ84JXm3PUjpvh4bAyKRz2uA87Ul560ETT5AxVMViJ5ZW1LF+01kpbse7Ih3asfoPNG/gg1vlzk XmM5OqzKGevjaGOt4+KOWxDYA9K2tHYGNjXFrGN86XyugINvxfJtLHWsVZimle/E484yAO26OiJY d79APK/Jjo4IMaTkq6zOX8tj87bx/wApSRS2qsUdd8ZdEwRjQyxucNWjjxQYFvu2xL8ub8mRljdL kI8oyItg3mxGQQ3tXN7Ux8PM10CCRrcmQ1rz5IslaZjnWJbhxAcxsPaz69pucAJHRlzi7YXaaoIi lyRJS5gxPYZB93B0ql2o2tK+IGCOcMDGM2AOf0Ebj0AIMjGd3eMgeI7WWnyUDMfJh4Ksxha1lSTb 5H5NrXFwDQNx4oLlbu5pVsbfpT5KaaG5TNDeWV4uzhPDd+TjYHSf0naoJvOYKnleWbODmnfBWs1x XfYYWh7W6ABwLgW68EEMOQo5J3W8tmreSnbUno1pJxBG2GO03ZI5jYmMBeQBxdqgw8l3VYm55Lr0 8bX4+LFSDbA95hgYWtdG6RjjG8ji7Z0oM5/I0AvPmp5a3RdZhrw5GOu6NrrDKoDY3btu+NxaNHOZ pqEFVfkTE1syMrWsSRZEXJrskjdm57LLQ2SvJw8qLyQRrxB60EuMJU/6l+Xe2cbbafoJhBGwRmTt NxGm7dr40GDneUcdmLF2zPYljNzHuxcvZlm1sTpO0LgXA+UDw48EFjMcjYrKC6+a1Kxt6nXoyOYW aCOtL2zXN1B8ou4FB8vciVchn4MvPfmlbXsR24a+2E7JYhoGsn29s2M6auYHaFBfg5HoQCgGzzEY 7ITZOLXZ5UtjtNzHcPNHanTTigu5zkvGZnMY/KXC8yY+OeIQjb2crbDNh7QEHXZ5zfAUGLiO7/G4 ujhakE8724SeS1FLIWl80krHxkynTj5MnDTToCCrF8iVcdLjnstzzNxdm3ZpxybNGi6CHxktA1a0 vJb1oMmPk+ozla1y4J5TUtsssfN5PagWnue/Tht4F504IMTGciGtkKl3I5W3lpMfBJXox2BDGyJs zQx5AhZHucWt01KDDo92NWpLE6TJ27MVahYxdOKTsg2KtZ01GrWguc3aNHH20EtW5OpQWcBO2aUu 5ervq1QS3R7ZI2xEycOnRnUg2JAQEBAQCNUGk2+Rs8cpmbGP5gNGnnJGy2oW1WSTMIibCeymc7hq 1vW3ggrtd22NfW9EqWH1KrcPLhIow0PLWSuDu1JJGrtR7aCq9yBBaF8G89vp+KixDtGNO1sRd+VH HpO7oQYOT7rK1vITW4rMTPTY4I7vb1YrEn+XYIw6BzzpGXtGjgQ4IM/I938F2nnaouPiZnHVnEhj T2IqtY0ADhru7NBayfd6+9zHDlzkOxEM0U7XRQtZbAiAHYiw0tJifpxa5pQfXcgTwS17mPyRr5Kp buW4J5ImyRll926WF8erdRwGhB1QXcRyDHQv4y++8+ezRlu2LL3MaBPNkNDI7QeYGkeSAgwLvdp2 2FqYxl+KSKs+y5wtVY5mONl5fvbxa+OSPXyXNd7KCRzXKUs/IgwNa1Jas1IoXVbVh258k1V7ZIzI 7+k5mhQUXuTflh+SvzzvqT5rGRUJq+xruwLSXF2uvlHV2miCnI93kN5+Rc68+P5Qr0qzgGNOz0F+ 8OHHjv6CgqyfIEV5+ac66+P5Zs07TgGNPZmkWkNGp479iCpmEzFrmzL5reKLvRGY3FyuaJDtD+1k mczUajfoGjVBn818v5TN4N2MqZR2NllLO3tRx7y+Nvnx6bmaCToOh6EGE3k7Iy8pXOXLWQibDYj7 CCSnWbWbDCdA5jYw54Oo146oJLKYW7NSqQ4u8cbNScx0LgwSRuaxpZ2ckZI1YQeoghBZ5e5Ynw9H INFwz5LJzyW7N10bWjt5GhoLYxwDWho0GqDD5U5Gby3dnsQZCWyL7e0ybJWt/L3d2rreo8xzh5Ja OHQgsO5Lz/8A1bLzAM3G/e5rYK81QSGvXGgdDA8yDZv6XO26lBdyXJV7JZBvpmXfLiGXGZBlJ0TT KySIhzYmT66ti3DXTbr1aoLVvu8jvcwNyV2zHLWjstuMjFaNtgvZ/hxPsjynRMPEDTXwlBlc3cjw c0S123rckdOmDLWrxAAtua/krO/rMX4LejwoJ+hDZhpwxWpvSbMbGtmn27O0eBoX7Rrpu8CCGxnK EdHlGflwWXSMnZZjNktAI9Kc9xO3XTye0QW5uWstDQxFfF5d1ObEwtr6vibLDO0RiP8AKxktOvk6 t2uQZ/K/L8OBxDMfHK6ch8k007wGmSWZ5kkftHBurncAOhBMICAg0m/f5wvc6X8PichWoVaFKtZa 2eqbBkkndI0guEkZaB2fUgtYbnua5Vw9i2BXntNyLbleJm9jpcaSyTZI4gtbq0lvA6oKD3s44RiV uHyTo30vlSE9nEN9Jv8AiTcZOAZr5rvKPUEGbl+8zA42UMcyWdsdaK7blj2AQV5uLHuD3Mc4kDXa wE6IKsr3j4vH3rFd9S1PXpNrSXr0LGmCGO5oInkuc1zuJ47QdBxQZLed6B5ml5fjrTyTwSMhsTtD NjHyR9o0lpd2hZt6Xhu0HggxIOeY2RxwsgnymRs27kFatXjZG8spybZHHe8MDWcBuLvKKD67vHx7 46HoNC5fsZCOeWKrCxjZGeiuDJ2y9o5jWuY46dPFBTP3m4ZrMc6tWs2jkapvRRsEbHiEO2nyZXs3 vDvwGauQSHNnME2NxdQ1G65DKWYKNBrxwElg+c9p6mMDnEeJBG5TvLx2Lv26b6F2yzGzwVL1uGNh jZLZa0wgAuDnby8DyRw60Fx3eLQZSbK/H3Bcdf8Ako47bGZxaLd7Wkh+za5uh3btEHzE941DJXad X5Pu1G3Zpqkc87GCMWq4cZYDo9x1bsPlabT1FBl4LmK5Yr2YbNd9i7RyL8dZMDRoBqHsnLSeDOze 0nRBRzvkc7jqDrtGxDVp145JLcr4JLcjnNH5OKOFhHB5853UEGsZTvDyccOJrUzFRsWcSMrZdHXk vMbro1sbGQkaRg7i9+vAdHFBJ80Z3mmHC47JYbI0+3yTa8FOkK7p2T2rHEFkpkjIjDdXHVvBoQbH ls63AYeK9lN0jIzGy9ZhZ5EW7yXzuaTq2JruLj1BBRj87NmMC/J4que0lbIce2z+SbNt1Ech01c2 OTTUdeiCBxuc5vflcpiI5aeWuVKTJvSGRuggguyO09FkcHP3Db5f42nT0oMKxzpzJja3MDXS1sr8 ksraZKKF0UMU879kscoa5+4QNPaO2nUDgUEvydzRPkMxlcPPdrZR2NZXmZkajQyN7bLSdpAdI3cw t6ndCDMxXPGOyeblwkEE7chWMovwvZp6OIyAx0h100m11j06RxQWeZc/n8fzBgqlatEMXfttrW7c jtZCXRvcGRxjo8zi4lBG838zcyYPL1H763yfbuV6lWmYpC58cjg2aaWzqGQlm7yAelBj2edMzHzd aqWbPybhoLsNKCSXHyyRTOexpINve1jC97trfJIQdEb0eBB9QEBAQEBB+VqhZ7T+pV/CzK/ryx+a VFKJd/RAgICAgICAgICAgICAgIMe++ZlKw+DTtmxvdFrxG4NJGvtoPB/Mue595iuHIZSwMkZHudH EZCGx8fNY08BouK+yJnEy7aa5iMxCLNjIQsBsYyVo04ubo77yp4xPq0i0x3hTDmKD+Dt0LvA8EFR OuVotEpCC5SkcA2w0nqBKp4z7LRLOZG0t10BPWdepZylfhhZte89I8arMittdhABOijKV1tVjTpq D91MmFbaw6RodfuKDC6ysWuI4HQ6knqQwvw13NJ8kPa7oHWpiSV0QRuJ2jZoDu1A118SkiEJzBmW 4mJrWMEl2caV4idePRuOg6lpr1+XX0U2Wx0brQMr8FjXTHWZ0be0P9LTit5wtrYGnSD0H7+qybsY Qk80csjpHynCtdH7nLy/2PQfM2PtWOa6M7YHva1zDvDSQNp48Rr0Lty8y2MrcONvN52dYNaTsnSP Pa7Tt0LfxtqmCGBgcZdiv5bfWkY2WtMGktOhJdwA8gJKWXy3Vmi5ezzHxOjD4COII6GO/oMUTHRN e7ktHV1Gs46O/JMP/CFwT3e1TtCQjGsMviYfvJCZVd4upweOa3ym72atPiiUbXPLrXcZGGd1+FI/ 5jHv/vPK9CnaHm37t+VlBAQEBAQEBAQEBAQEBAQEBAQEFme5VrjWeaOIeF7g376CHuc9cmUgTazd KLb07p2fzqMpxLXbvft3XU9Q/NxSkfgwgyH/AIQo8oW8JQVz6zndvBr2BtWSPxYtv31HnCfxygL3 1scIwkUsNPL4DI8NH3AnmfjlruQ+tdzFIT6DiYIB1GRxef5FHmn8bXLv1ke820T2dmGqD0COJnD2 yCnmn8aCt98feZc1bLzBZAPVGQwf8ICjzT+NBXebuZ7ZJt5i3Nr+NM/+dMo8UY+5PJxfK97j1ucT 99Mo8VJmJHEe6mTCc5c575r5cnEuGyU1Ya6mIO1jd7LTqEixNXbOSvrQgtZX5rpEOHA3q41BPjYF fzhH45l2vlznPlrmKu2fEX4rLSNTGHASDxOYeIUxMSrNZjundVKogICAgICAUHnjnp4+X7+nQJ3h cWzu9PT2aK7o9tczpV1+NiLXoL2gn21fXMZU2RmstotctXaYg2ZOnJG/8m0NjLiGn8Y+Jej51eNO i2WPd7qZshP6RJnaTSW7QACOA8StGyIR+GfZQzu2dgYLOQdlq1vSPZ2MJ8o6keFY8i8TV18Skxdi wgaakk+ALih6bNadI2nwOB+6rQiynvrlLuVsa1vQHeV/cC1iXLZ3vu4BHImDB/8AzWP7y7Iefbu2 VFRAQEBAQEBAQEBAQEBB4B+tH/HXmb/Q/wC310TDlahLv/1Kv4p5X9R2PzuopRL2miBAQEHNObMt dxXN/MF6m8NsVOWGzwB/lMEjbMmhLdUEbzFleYo8Pm8Xksh6e2XEVMlHN2bIXxSS2BHJG3s9PI4a jXigyOa+e8zjsxOaFpzq2PuUKc9cxwMgHpJjEjHukd28ryJdQY2ho91BMP5nzzecv+lt7TZfcbbj n2DT5J7Le4eDcJR2e7xoN8HmoOTc64+hb5oy9lz8dkJK9aBtjHZaWSpJAwNcRJSsDVoD9fKO3zh0 oM3F5fHz57F5CwZa+LfytJNO264l7IhKzcZSdNTt6T1oMPkzCcs2r1rmmnFVoCStNFgsbBI0Sis5 hLrEzA4kySjiB+C3xoMbuvxFEQYG9LUwQlMLHixHO92QLyzgdh8neT5wQbhzFFh7NGtVy+QhtzT2 5hjmzOMdV87Q4sgn7I6OEY4aOPEjwoNKwxht1uUMXmXiTCssZWvc3vJqTWK5d2O15I3Qgbuy3Hq8 SC5iDWyA5aqZ6TtOXnRZU1PSZCI5RDOW1nPcS3UtrcWanxoNh5T5dmznL3K2YuXrcdjHsMkbA9wE zNzmxmUHp1j++gwWQ4LIc8xtwsrW2cfkHT5fLyzjtJJNCPQIAXavbx8oabWgadKBiIcFe53gkwUr Y2Y21Zdk8pLODPcneHNdVjaXavjjcfKOmg0Aago5YrYHIc2QWeXphHj6HpUdrIPn3WMlPLq1zA3d ufFEfK3kdIG3gEGTn+UWYTlplWK9JehmykNixWv2OzbZa9xLqol81oe87hu4E8CUEBXrTZHEXcZJ YqYrFu5giZTrTPfYq9nHCJH1WvjLGn8r0gODd2o1Qbz3a2WS4W1XZXrQso3Z6olo7vRpthBMsYeX kA66HyjxCDcEDRA0QNEBA0QEBAQEBAQEAnRBzl3Oebg56NK1aYMVJeFGsyuyOZmro9QyYhwnim3c dS0s0QYuH555gszYq7NbryDKZGbHzYBkYE1aOMvHab9d5czsw5+4aaHggwsBzBdo47DyxxC5Kypn LIDy50jnV5tWMadeg9CDM5Vy+SyPOeDsW8vDkPTcJPadBXaIxC6SSI7NrSdQ3XaN3lcCgr5p7wOY MJnLeNAiIpzR5KaRzToMIGtEx/rtkJGviQXK/NvMeRfiIHXocNBmI7d+HIPia78hHIBXgaJCGbnR u7RxPV0ILdHnTmDLsw1c362G9MqWrMuTdG17J3VpuxaIWyna1r2/lDx106EFuPnXP5epQY+7Xwgs Yqe/LZfGHMsSRyGINj7QjawtHaHTytCEHy9Lfl7hIpobj4bD8dAX2W+U5wc5odoXHXygelBn4/IZ fHZXK0WXoa2B5Wo15OxFfc6UyV3SOLyDua1pbro3igg8f3j8zNsXIpp22GPwM+ZqPmihic2WLzdr InvIicD0SeUguWeaufIH3Yzlq7jWwkWe3iq3i9x0dW87/COnnecgu53vE5pbl78VFkdeDG1KlqNk hgEdg2WB7u0fNIx4jGuwGME6oOo1nulrxyPbse9jXOaDroSASNfEgvICAgICAgICAgICAgICAgIN UyvJVm3nrGZp5y5i5rcEVWxHWbAWuZCXuaQZY5HNP5Q8QUFbOQsRFDjIKz5YosXBaghGocX+mt2y vkcRqXk+Vr4UFs8iYowRwG1KWsxEuC11ZqYZNu5/R/iDb7HiQYmS7scRbsRTstyV5PRYadkiOCR0 sdYaMcDKx5jfpwLmacEGfk+Rsdfiy8T55Y2ZmOtFNs2/k21NNmzUdenHVBZyXIFPI8x181YuzONe eK1DX2xeRJE3QNZNt7ZsbulzA7QoD+QoIzDPQyNilfr2LdiG4xsTyBefvmicx7SxzNdNOHDRBexP I+OxctKaCeZz6cFmEukLSZXXJBLNLIQB5Ze3XhwQRmQ7scbawlLFHIzMoU4HVyJI4JQ5jnF3aAyM PZyDXg9miCT5k5dkt4XHRY1265hp61vHdo/UPdW8nY9518+MuGqD5a5Ix9s5F8k80bsnbq352gs8 iSoGbGt4eaezGqCo8lUXXjcM8u85NuW2+Tp2zYhDs6PM0GvhQfa3JdCs+lI2eZxpX7OSjHk+VJa3 72O0HmjtDogpwWAyMMFqxYndUuXsk+/YZFsfrHqGMruLg7gY2N3ae0gzc3gbWRlhnq5Szi7ELXxu fX2Oa9kmmodHI17SRp5LukIImXu6ox16MWKvWcXJRpuxonh7N75KryHFj+0a4a7vKDgOBQSUXKWO hlwboHPZDy/G+OlX1Bae0iEO5+o13Nbrp7JQZHMOBgzlFtCzLIyk6Rr7UDCALEbeJgkOhPZv/C06 RwQY1Dlg0cBPhauRsxxPErKdkFhlqxyeayJxbxEXQwu1KCJxHd3YxeGt4evzDebWswuiY9rK0csT 3nV87XsjDnSO63O1QX8LyHJisNYw0eZtvpyx9nAAyvE6A67i9jo427nOPnb9dUGdy3yrBhH2p+3d auXNgnsOjjiGyMEMYyOFrI2gak8BxJQWMTyNUx2ZOZiuWH5Gcy/KEzi3S2JDqxsrQAAIeiPbpoEE nl8JBkp8dLLI9hxtoXIgzTyntY5m12oPk6PPQgic1yQ3LWpzYylwYu3JDLbxYLDC90BBAa5zS9jX Fo3NaeKD7kuSflC851rKXJMVJYjuSYglhhMsRDmtDy3tGx7mhxYDpqg2odHj60BAQEBAQEH5WqFn tP6lX8LMr+vLH5pUUol39ECAgICAgICAgICAgICAg+OAI0PEHgUHibmLGR4vmvKYqODWOtdmjZrw 8lryRr7RXl764tL1NE5rDEitF1gsYwasGpGmg4LHDZkAtk17elHJvfqCWgj2OhRmYPGGNYw2Iezf Jj44nl3lBvkHQdY0V/yW9zwh9bybjpq01qtLLAIi1ugdqCXnhpx6lP5ZROuFTuV8xCx5qXnSBgLj 2jR0D2dUi0T6HgNw3NscJlfUisx9HaNIB4DXgAQrYrKPFYZZyUZHbY97G/jjUD7oUfjr7mLey63K 1mP2SB7HdOrm6t90Ks65M/SUnBYimj8mRrmn8XrPUqYThmQxz8CxpcDw4dSYPFkTxSNrvfBW7axt JbG7yQ53UNVpWqJiWqVOUeYJrcuUyMLX3Hk7Iy5pDG9GjePgWl56YhSuuc5nu3SlFebUhqmLyIQ3 a4npOvlD2laMRVeInPVV8j3Q4kRnaehZ4arMmJtl7JOyIdE4PikB0c1w6HA9RUxOETWJ7s45DnAy MkOTub2a7ZPSH6jXwHVWjZZn+CvszY81zmBxy94gAaD0h/8AOp/LY/jU9lfy/wA5sYXnNX9jekmd ztPuq0bLI/BT2WouYOaWRPhbmLfYzbu1j7XVrt3BxIPhT81kfxq+yivGyKFkUeoaxoaNTrroOCpl vEM2OLSpM52o1aQpgnsxe8KbSjjm7dG+Xp4TpHoq7PRz4dp7lm7e6/l8aaf5YH3XFejTs8y3du6s qICAgICAgICAgICAgICAgICAg83fWYZK7mXH1hO+IW6jzBtcQO0iOumg8IK5t+a9XpcKldlZr/d6 POsm9riZXkuB0OpJ0I4KkWz1R446PgmLjwBPsBMowr2yEagEeElMwjwXGRSHq1TyhaNUq2V5Tw2n 2gnmtGm3svR4+w7gGE6+JR+SFo4tvZebirJPEBg8LlH5V/4tlbsdGz/EmYfY6kjb7InjRHeVBixz OHaF58DR/Op8rSr+PXC2+ak3i2Il3jKvFbKzanpC2+6wcI2AeBT4qTuiPRQ27ZcdsYLj1aD+ZROE Re89o/yZuNk5sgsssY0WYJmnVske5qr+atfVp/F3bP7Zdm5K78+8TECOLmSGLI029MkkjYpwPZ00 Ptp/Mr+raPhds98V/V6E5U5nx3M2Fhy+PJNeYloDtNQ5p0cOHgXVW2Yy8rbrmlprKaVmYgICAgFB 537xGGPmPJDo/Lk6ezquLZ3eno7NGe3QPHh6QuaXU+4DHZDO83UuX6kzK3pcUkhneC7b2enUD41t p1xaOrn37ZphuUfdXke1uMHMFdppH8qTE/oB016Vt/Hj3c/8yfYf3a5KGsy0eZajYJCWMeYpOJHT 1p/Hj3R/MX2922dbeio/L1IyztBY0sfx3cR7qfx4W/mShJqdqjas0bJa6epK6KSRnBpI8GvsrC1f GXZqv5RlWB+S19s+0kd1pWO+B/aYHFNael33S0LSO7lt6vRfJUPYcqYmI/gVox/whdkPOt3TalAg ICAgICAgICAgICAg8A/Wj/jrzN/of9vromHK1CXf/qVfxTyv6jsfndRSiXtNECAgHoQRV6bl6O4y C9JUZcuM7Fkc5jEksYOuwB3FzdepAsP5dN5tCw6ob88YY2s8x9q+Jp3BoYfKLQeOiCJit8uZLJPm OLiltsuSYuWzLHDvDoG79dXeU5ng04oLENzAVuemn005DMZVslSNrXRObTiqs7d0RDfKaHk6+VqS UG0PyNBm9r7MTTG9sTwXtG2R+m1h48HO14BBG5mLk6UNt5plCRtZ/ZNsXBC7s5OnZuk6D4kF3JWe Woq7bOSlpsr2Gdgyaw6MMfG/j2Yc7g5p6dOhBgWafImAYMl6JjcfLsea8rI4IZJBsJc2N2jd25vg QRdy5yHheWa/ORw9Oux8UNmoWQQRWN9gNMbWvIaA/wAvw+FBNQycs3ajcfZiptdZb6TNi5DA8guA ke9zGktd524uHsoLsb+UcjinwMdQt4mto2SIdlJXj2+aCOLG6dSC3Lc5KyEEFKWfHW68knZ1aznQ yMMkXDZGw6jc3wBBInKYiK4zGG3BHdLQY6faMbLtA4bY9d2ntIMdvK3LbLYusxNNt1r+1babBEJR JrruD9u7d40CDlfluC0LcGJpxW2kubYZBE2QOPSd4aHanVB9qcr8t07TbdTE061pmu2xFBEyQa8D o5rQeKDOt06tuu+tahZPXkGkkMrQ9jh4C12oKCw7DYp2PGOdSgOPADRTMbOx0B107PTb0oL9SpXq Qsr1omQQRjSOKNoYxo8Aa3QBBfQEBAQEBAQEBAQEBAQCEGF8kYo3vlA04Df009K7Nva6dHn6bkBm Ixkd196OpCy7INJLLY2iRwPhdpqUFUeOpRFhigjjMQcIy1jRtDzq/bw4bj0oLdTCYmnK6apSgrzP 1L5Io2McS7i7UtA6UF2bH0p3vfNXjle+Mwvc9jSXRO4lhJHmnwILdvD4q5WZVt04bFWPTs4JY2vY 3aNBtaRoNB4EHy3hcVcrsrW6UFivFoY4ZY2uY3TgNrSNBw8CD7bw+LuRxRW6cFiOAgwsljY9rCBo NoI8n2kFx1CqavohgjNXQN7DaOz2joG3o0QfW0qzXySCJgkmAbM4NGrw0aAO8OgQY0HL+FrtLa+P rQtcHNcGRMaC1/ntOg6HdYQXzjKJLia8RLo+xfqxp1iHRGf6PiQW7GExNmWGWxSgmkraejvkjY50 enRsJHDRBngaICAgICAgICAgICAgICAgICDnXNPNmcxnNL2elMiwld1VkxhZFO5jrD9rhZjL2TtD 9QGOjBHhQWHc5Z/06a4LtdsNfOswowXZtMronSti7QyE7+0Id2o0G3agj8LlJqmQrBkTbJfn+YCA 7UyfkWSPa2M68NS3RBk8t5XJ5PmvlW9dy0F05DHXbPocLGxiAuEWrPJJLg3Xb5XHUIL/ADfz3zBg 87Zx0fZyNgkhyb3FnEYZjdLnX5zHjgfGg+1ubOYMtJh42ZCLEQZqO7kILz4mPPo8MgFeFrXkNJMT u0eT1ILOO505gzTcZXGQgwpmx1i9LkHRteyd9ewYB2bZCGtjLW9qevQ+2gxrnOOdzWHeDer4Zn/T 7slMZIw8WHydpG7aXlu2MBmvk8fKCDJ5xgsWe6rl+uyyYGWX4iGx5IeJI5Xxtc1wd0g68fCgyWcw 5ijFzXckyENXE8vu9Co1m1tzWuEURbI7aQ46OfoGDQIItnPnNsNLmavJKDfxTMfLVlsxwb2+mSbH NkZXe9mnWBrqOtBk2OYuc8ffvMnysVuvictQoOjNZjDPFf7LdvcCdpj7Xydvg4oKoOdObJuZJNjG jHx5l2KNV5rMZ2TXbNwcZO37bTywNmhHBB1BumnBB9QEBAQEBAQEBAQEBAQEBAQEBAQflaoWe0/q Vfwsyv68sfmlRSiXf0QICAgICAgICAgICAgICAUHk/vwxjcf3mZJ8LtptxRXD4NXDa77y4OVHV6H FnphpUc80bWPa1r9WuLnda5ejpiFyrdkm8yMA6bj5WmmvDgomErxitvfIC9r9rOJ06Q3j/Kqrs7t 2R1BVbEW79HyPJ1Gg6NAgzXW4Y4C1hJdKza5unh6UkZNWBliBmjnCNuvaHXo1/7FECQeyEiLsoy6 Fmoe86AceOvFXEHn8pQuOdDTrMbE0AGUgFx04dIVlYlHxkmHTQAtPD2Eythn17UDIC6WXYAeGqho zWW4ISN8urXcADrrxVolXDMitwSktjmGoGpaR0K/kqustwBrn9uzs2a7newmRkDI1QxrnTtDXaaa Hp1U5GQ21XGkZlYHScBx6UGLO+pE/aZ2l3gJVcrQwr2TDGxx19stmy/soGNPX1u/sjirVjKL2xCT jgZWpCvu3nTQk9J4dfsrSYc9ZnPVENkrajXVpHTqs8N0hHZg28ZBp7PQmRlG7WNUxiVriepTEkw1 /nLKG6zsyfydWSxGCOloZGOCjZHZzzL0L3PDTux5cH/8mz75Xo1eXbu3JWQICAgICAgICAgICAgI CAgICAg89/W1pFuO5dy0QLbFS08NkHgLAdD7iz2RmMN+PsmlvKO8OOz4bF3aseXD2shsgOLdQNJP wgvLi9onxfS7ePS0Rsielv8AqjH08dGeD2uHhJKvmWHhrh9a7ERnjx0HQ0BJ8jz1wqkymJiA7OAP I/GOv3lHhaU230jtCz8vcSIomgnoAGv86t+P6sv5M+kKWvz9whsEE8oPVGx38gVoiserO19k+7Pg 5I50teUMdOxp/CkBYPuqZ2Vgjj7be7KPdvl2AOv3KlNvgkmbu9zVV/PHsvHAtPeYhafyryvW/wDW 59kp62VxuPtKJ229IWjg64/ddald3eVOIis23D8d20FPLZb1wn8fFr7yxpObsHBwo4WEEea6Tc8p +K095THL1U/bSP6sO1zxmiP8vDHWaT0RxNH3SFMcevr1LfI7fSIj9IRtnmLPzA9tec0EeaHaf91a Rqr7Oe/L3W72RxdNOfKkkmPi3O/nV8Q5ZmZ7zL3H3BUTT7qsIwtLTIx0uhGh8pxXXXs4Nk/c6IpU EBA1CBqgHoQcE71ImwcyWv8A4m159skLk3d3oceejnjh+UePH0Fcvq7GfyHdp4vvHxuUuv7ClFXn Y+U8QHO02j21vovHVycqs27Onwcx8qus5R3ytEDb1EZIPW7dxXT5w4vw29luxkOXZcRBSZlqhkjl c9znA7dHaePpUxeE/ht7Mv5b5f8Al6hZGTp7Imxh7jrqOzGh0KnzhWdNvZovMM1azzJlbFeQSwSW C6ORp1a4bW9C5Ns9Xp8aMVY8TQYZDp0MP3lnDeUf3qlrsfhWkaEyDyfaatI7ua/Z6ewrAzEUmtGg bBGNP7IXbDzJZqlAgICAgICAgICAgICAg8A/Wj/jrzN/of8Ab66JhytQl3/6lX8U8r+o7H53UUol 7TRAgIB6EHN+dOWM/b5idfw9LfNPHXj9Je+GSq7sZN221BM3eAzXVj4TuQWsnyjnZchlKkVCOb5T ylfJQ50yMBrxxGMlhafyu5nZuawN4HX2UGdHypmxk4pzG1kYztzIGQPbubXnrOijeB4dx6EEbyry jnaOY5ZZYxUUTMA29HczDZIy616Qwhj2tb5Z3u8p27oKC5z33f5nM56eSgWNx9uAW5SXbXDJ02ub TOngO/Un+ig+1eVc/RZg8tax7MrehF2bL45r4xpavlrjLGZNI3dmG9n0+b0ILeP5Qz2IbiLcuKjy 4r17teTFNlj21jbn7ZnZmXRjmtZ+Td4ujggsRck8wY6jSjkxsWbd8jS4p8HaMa2tLJK6UFpl01j2 vDHEcfJCDYL/ACxkp+7TH4EQMkyNatj4nxOLSwPrGLtNHHhwDHILdvlW+2TnK5Uo1n3sq2NmMfOG ua9jKrYix3W1u4EbetBrY5G5ps0OZopKj2jL4yrVrxzyVmudLC929pZXDY2N2u8nxIJbJ8g2JJeY paePgbJenxcmPc3Y07afZdroR5mhYfZQYk3I2fPMdkyRzz17GXZk47zZq7IWxBwcGvBjdZ3xhuwN adpHgQdTCD6gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgahA1QfNT4EGHPmMVXcGT3IIn uOjWvlY0k+AAlBltka4atII8KCpAQEBAQEBAQEBAQEBBgWsHh7VyK9ZpV5rkH+DZkiY6RnX5LyNQ g+OweIdkBknUoDkWja24YmdsB0cH6bkFbMTjo3tkjrQseyR8zHtY0ESSee8HTg5/4R60Fury/hal p9urQrwWpC4yTxRMY9xd52rgNePWgvTYuhYldLPXilkfE6u972Nc4wvOroySOLHdbehBauYHDXKk dO3Rr2KkWnZV5YmPjZtGg2sI0HDwIPlzl/C3oIq92hWs14NOwiliY9jNBoNrSNB7SD7dwWHvCEXa VeyK/wDgCaJjwzhp5O4HTggvSY6lJXjrPgjdXiLDDEWNLGmPiwtbpoNunBBS7F0Hx2I3V4nR2yTb YWNIlJG09oOh3AacUFiDlzBV4nQwY6rFE4Na+NkLGtIYdzQQBx2niEF6TFY+R0hfWieZZGSylzGk ukj02PdqOLm7RtPUgt/IOHOR+UzSr/KOmgudkzttNNPP03IJEDQaICAgICAgICAgICAgICAgICAg ICD8rVCz2n9Sr+FmV/Xlj80qKUS7+iBAQEBAQEBAQEBAQEBAQCg84fWZwsjeZ8RljqyrYqyVZHj8 dpDm6+0uXlR9uXVxbfdhyrHxOjkAeO1ZtOjwdRx6OC4Jd75NUmbLH2Y3NLTo9vuqF4Z1NpIZqRvf E4E6jpPDRVMqJ5ZGhz3uDYj5LRrqNG/zolNY/sLEz4ZdGWxEyVsbSHDsBwDnEcGuJ6ulWmmIyrW2 ZTddlQPMewOZC3eIwfO4j+dFl6THR36RryT+jwl5eY2EDdqNNDr4FpSuWcsNnJdLbwsnX2Wq81Il dZybSaNPSydT1lvBRFU5ByJRLzI+8S4nyQS06ewE8Tyl9ZyHT3Euvvc9/AE7eCeMJzLKbyPUMYiF tzB+ERpqfDxTCMSqfyBDIWt9PLYmdEY00J6tVKOq5F3fR9s2R1/cWjRjSBo3Xr6VEQnqvw8gvbM6 T04PeToDpwaOrrUoys/RjafuLso0vedXOLfvcVGE+S6/k+PD2obcsrLAZGY4to81x6XE+NaVlnaZ YGWuejRgtA7Vx0jCtecI19Z+jAiyzwNXQgn8bTVY+Tp8WRXyNDcTNXY954kOACnyR4se7KzR1ihQ jmFdvaSt1eHHjw2AEaqMo6eqmny/f5znp43AxNjvvbNYyT5zsZGyUhrpNDxceoBa69c2j9HJv2RX s9Mcp4JuA5cx+FbIZhQhbCJSNN23rXe86UugICAgICAgICAgICAgICAgICAg5F9ZrHGz3diwBr6H ajf7TgWql2mvu818r63YrGAd/wDxGr6p8EnSOlcPIpMT5Q9743bF6zot+sJqLulzAaH5DI06TCOJ fJud7gKznZ7LRxveVxnIvJdZ3/1LmQzEecytEXfdKjzlP4aR3nKsxd1GP1LKt3IPb1vLWN19gaqM 2kxrr6DO8DCVRsxXLVaMDofOdzvZPBT+NH54jsxrfezzK5pZXdBTaeAbWiAIHsqY1wj+RZr9vmnm K+SbN2zK3qDnlo4eIKfCIUnbafVGSstWZGt36uefCXH21bpDK2ZWziLhOzspXnxDQe6reSPCe76c NbjaXvjjiZ+NK9pPuAp5QjxWJIqrGavujUdLYmk/fUxmUTLDfapHhskfp0bnaD7ithla8SpF1jR5 FeNp6nEFx+6rYVmy2/IWuOkr2nQ6Bvkj3Apwzmz9AO7Oqavd/wAvwu13ClC4k8Tq9u7+VdMOO09W 0KUBOiDn3O/fDgOW5jThBv5DrijI2MP9Jy578iKujXx5t1cvyffPzpfsFsU7KUWvksiHHTxlc1uR aZdlOJX1fI+8fnNp0dlpT7IBCr+W3u0njVZEfPvOQcZDlpXB3VpwC0/NZWePRGZO5dzVttrJ2XTz NbtDyNDp7SrN5leuqsdlv5Kov1dx3eHVVaKX4Wrs3al3HiFWYIWGYuo08GkHxpK2H1tembTa7Wlz yNTp0AeNXpXKlpw+WqjIZnMa0Ob1HwKJjCYnMMis1pY0DgPBpwSBnwsAqykdJHQrQiYa/wB5k0Up wjWSbiyXbJp1HyRorx+5z37PVOMGmOqjwRMH/CF3PLllICAgICAgICAgICAgICDwD9aP+OvM3+h/ 2+uiYcrUJd/+pV/FPK/qOx+d1FKJe00QICAgaBA0HQgaBB82hB90CD5tHgQfdAgaBA0QNAgaBA0C BoEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBZntVq7d9iVkLOt8jgwe6SEGvX+8zkCg4ttc wUWvHSxkzZHf3WbimBgfSxgJyW4yjlMr4HVaUuw+w+QRt+6pwKhzjzZZbrS5VmhB4h9+1DAAPG1n av8AuKlr1jvKYiZUOvd4k5HaT4rHMI8oMZNZePbcY2n3Fjbla49WkabStPp5yYD03may/wDGZTii rtPthr3j3VjbmR6RlpXjTLHfgMKWjt/Tb+h11s2ppBr7G4BV/lbJ7VaRxo9ZXq2Ow1bc+rh60buk u7Npd7OpCznbuz7NI49F2i6vPdY5nkOa7UmCUgAtPQ4NOntFbadl5nEypt01rXLeG9C7nC+oCAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg/K1Qs9p/Uq/hZlf15Y/NK ilEu/ogQEBAQEBAQEBAQEBAQEBByX6x9Nz+TaVxjA41r8bZNR+BM1zCPdIWW+M1lrpn7nA6rK7mR uc3ZM07dW+SR1cfCvLmsvUjuyXU3l4ljJ7JoadzejU8DwHR0KuFslihFLclLPyZaBsHRpw4/fUEM VuLsTmRnZ6hpOkJOuoHH3Ez7JltNi0yOzUtOY2OO7UiLQxu0CRmsbm6f2elbbY6xPvDLT0iY9l2v E4ZWZx8iKNrg5/TqQNwHt6LKO7XtC/I1u/eQW7vK0PjXRrnorL6Wnb5Dz4dFeUKoGh3TI4+FJSzI q401LnH21WZWZcVeIDdx4KEqowSVWRmQxa6dftKMmV87Q7b1Dp9lTAuN2/g8EwK5HEaNB0J6SpwM fKM1xExc7gNp+6r6+7LZ2c0ylp9m6541MUfkxdY0HDVVvOZW1VxCmKR7QHF20+Pgs2uUhUqS2uJ8 hn42nFaVqpayjP5GHGVGwUx2kztGk9Q160vfDOG0/VyFiTnPLyzjy20mjU+AyLo4k5y4+XGMPRa6 3GICAgICAgICAgICAgICAgICAgINI758f6d3bZqPTUxw9qB42HVRK1ZxLxpHFNG9k8RLZB0ObwOh Cwt2deu0xeLQrdNO/wAqUukd1bjw+6uXD0ZvZQ2OSTTjofxWguP3FHRXrLNhweRmALIJjr0Ejsx/ xaKPJbC9/wBOsjf/AJqeCAnp3P3uHtDVPJMVh9fT5egZo66+cj8GFgYD/acFXMpxVhSZLBw6iPH9 v1B00jj9xuivESznZWGVgeY4xlYGvhgqUwSX7IxroOgbnanipmqk7vZtDKeG5kklfLfkp2nbuyoV ydoaNdp3ePxqkROVZ2TMd3Lp6MomkZK5xLHFpJ49B0XR5KYyx5KbNeJ4Dp4qcqdIWZBWa46HXwaB T1RmFp7266NZqPCUiFJldquDpoY9oJke1vDp4kBTEEy/Rblyv6Ny/jK+mnZVYWaexGAupxykiiHK e9PnnOwvdh+X26SDhatAjVuvU1cu3bPaHZo0R3lw+Tl/PSOdLJC6SWQ7nOc4Ek+HiVxTV3xOF5/L +aaARVcXgDTQjp91T4ymLLgxXNbQf8o58j+gAt2tHuqPFM3ZNbFc0N03wv0H4PA7laIlSbMh9Hmr aS2k4yP6ANNGjwqZyRZcipc172M9Gk2NGr3EDU+IJB5MiOLmdvaSGjJoAQyMAanxpMJ8mMMfzdLK N9GVgd5Tjt4N8SeK3mycVjp6sMs9lu25ZeTID0tA4NatsdMOe1urEsy05Z9psFj2+S4g8Cs7TGW1 I6L0LGkhkdsbB0ueP5kjC3VTcsyUw3tbrDC46btDpp49AVGcdUxmUNnMbfvXMLFTY67PatPkjZEN x2lzdNQOjo61rrnynMOTd9sdXrilG6OpCxw0c1jQ4eAgLueYvoCAgICAgICAgICAgICDwD9aP+Ov M3+h/wBvromHK1CXf/qVfxTyv6jsfndRSiXtNECAgIIrmHmXDcvYuXJ5ey2tUhGrnu6XH8Vjelzj 4AhMuQM+tfygLL2S4i82uHEMmaYnEt8JZqNPY1VvFXybly7348h5yMy15bNdgOm+xA5g18ALS8Fc +7fTXOLS31ab3jMR0bPX5y5Vna0x5Wt5fBofK1hJ8Gjy1W17a3/bOUX1Wr+6MJaKzDM0Oie2Rp6H McHD3QtGa5qEH0HVAQEBAQEBAQEBAQEDUICAgICAgICAgICAgICAgICAgICAgINO72LNityHk5q1 iSrK1sek8MjontBkbro9pDm6jwKaxmUS5V3f43kXmP0t2Qwklm7RDDadkLU9xru04gs7V2uvshZb 9sVjo006pvLo1Gvy5j//ANGYepUDeAdHDGw6eyBquD8+2fo7a8WsMt2XsFhIIYweaAs5rae9msaa x6LD8k467nvd18FXwpHfMrxr+i2bjnjVkbtOvX+RTFa+kLeP1UOmskcG7PD0qczHomKwth9t3nSk KIvafVbFfZq/PNeaxXpxCaUazeWGPc3UBuuh0Ky23mJdGmtcJju9ghgrTNiYGAWZNQPDwXRxp6uT nz0dXXqvFEBAQEBAQEBAQEBAQEBAQNQgaoGoQfC5o6SgpM0QOheB7YQWp71WCIyyyBrG+c7p09xR MwnCqrbrW4WzVpWzQv8ANkYQ5p9sKULyAgICAgICAgICAgICAgICAgICAgICAg/K1Qs9p/Uq/hZl f15Y/NKilEu/ogQEBAQEBAQEBAQEBAQEBBCc4ctQ8y8v2sPNIYW2A0tmADixzHhwcAfYUTGYTWcT lx/K9wmcjL3U5ILbdzXN49m86ez5K4rca0dnfXlR6tUyHIHNWJLe2x8+1u5z37S5uh/pN1CytrtH eG9dlbdpYZZVmc2KUOhe9oDiQNCSNNTr7Czw1Di3wmW1BIJez0bqw6kdXEKsVgzln27JlxuPnsgy xxQ+jvY4DQEEu1BHR0q222WWjvKzDGGHtomuJl8qaB/W3wt9hZx1bSyLbo3BhaXCQNcA/TUN49Dh 4Qp6kQ5/e9Lr5W/H6U92yQOZ5RA2PGoPT0LS09mUd145PI12aiVzm6N0IJPsqsXnKfHKQo53IyD/ ABTs1003EEEK/wCbHoeHtKYqZ+bRm+SQ7jt6d3FR+as+iY8kpT5lqeW2RmnAkEkh3k9Kzm8Nq/Vk R5j0mDayxJXcfNkYBuHugqa3TNcx0Yxqc0PfrW5hka3q7SGF3/shbRaPZhNMdrLJZ3nRPPYZWtNH r50tYffbwU+dfZP47e6zPlO9eHifQJQfBASfuOTyp7f5qzr2R6rbuaecJKc9XMRQMjl0DTFC+MjQ 8dSSUzHoeE+qLbJ5UbYm9pNJ5kY6duum4+AKJWiU7SwrnObLYGrtOAHEBTWMlpwt5PKQxQvjpkFz XbDK3iAddNGqmzZjopETKAsOcd25uumo3dOjnLn6r9nS/q4s/wD7izJ04tqxjXr4yFd/D9XDy/R3 9dziEBAQEBAQEBAQEBAQEBAQEBAQEERzZQfkOWcpSYNXz1pWNHjLTog8URUpo5pIZRoY3OY9mvW0 6afcWNodeuVUeUqwu/JU4S8cNZtXn7q4pq9KLqJeYMkXkMnEDepsLQ0BTGtE7erFnyFqfg58kvhL yVPgidssPs5/CG6jxkq2IZ5kFKZ/TqR4DwUTJ45DjtBqS0AJlHipNatxBeCFJ0XKlr0CQuquLJJB sdoNNQepTETMq2msImxM6R790mhJ6OOqthlNmJIGEdblMKzLGf4hoVZGVt2rulEJDlaq6xzLiq4G oktRN08OrwrV7qzPR+jlZmyvEz8VjR7gW7mXSg8780i/T5myEL5NPyxd18Q7iFwW/c9bVMTWEd6d caBo8eyVGF4XYrd88RINVCcMqOW64gGXj1quUxDIE87XAb9SB0osyorFlwGr/dUZRjLKFiUeTv49 PiUnjC4y1YDj5eup6dFHU8V0ZG2H7WP1A6VGUeMNU5ruOp2Jn6gueBtHgc7XUrWJ+1jav3NLileR 5WhcenXwrHLqjszIB2rwyJpD/F0KYhE2wv5W3Tw2NmlyDxJ2zCwxdJcDx0AK0wy8stq+rRbiyOdz E7WaMhrQiFh47NXu10K6OP6vP5MRno9DjoXS5hAQEBAQEBAQEBAQEBAQeAfrR/x15m/0P+310TDl ahLv/wBSr+KeV/Udj87qKUS9pogQCdEGi94/exy5yTU/zcnpOUkaTWxsR/KO8BefwG+MqYhEzh5K 567w+ZOcsp6Zlp9zGk+i0maiGFp6mN8PhJ4rSMRDOZyzOU+7+zeLLuVa6KnwdFW08uTwaj8Fq8rm fIxSPGnWXqcP46b/AHW7Nuz+Xw3L1Noe1rZNulajHoCdPDp5rfGV5fH0bN1v/d627ka9FcOU5zOX sxbNiy/g3/CiHmxjwN/nX0PH41dVcRD53fyLbZzaTH8wZ/FuDsdkbNRw6Oxlez/ulbsXVe73vG74 LDmzvzcr8XGdpfbYyYvI/BYSA4+zquDmc2mqMR1s7uJwrbes9Kuv0O9zKs0bapR2PC5hdGf/AGgv Mr8taP3Q77/FR6SqsfWI5HoXBTybbEFgDV4iaJmt8Ti0g/cXrcbb+WvljDy+Rp/HOM5bFhe+Du5z O0U87XZI7oisEwO//KbV04lhEw2yvcrWYxJXlZMw9D43B491pKhK8DqmR9QEBAQEBBhZe+2hjLd1 3m1ony8f6LdR91VtOIWrXM4cWqd+XMhl7F8VWWbTcWFj2nTxEFcccmfZ6E8Ovuloe/DKDTtsRE49 e2V7fvtcpjl/RWeD9UhX77qp/wDUYqRnh2StP3wFf+VHsrPBn0lIV++Xlt/+NXtRHxNa/wC85T/K qpPDuzou9fk9/AzTR6/jxO/k1Vv5FPdT+Lf2ZsHeJydNwbkmNP8ATa9v3wrRur7qzov7M+vzVy5P /hZOs72ZGt/7xCtF6z6qTrtHozY8hTlGsU8cgPQWPa77xVolWYlkB4PR7qlD6gICAgICAgICAgIC Ag0rvljD+7XNA/8AhMPuSNUwQ1TlWONtNkzI2NmnrwCWTQAuDWcNx69F8b8Xst+W8TPu+k2Vj8dU 52Z1JLiSekdWi9uerBayNyHH423kJWF8dSJ0zmN6SGDXQap45RK6+Gx8lw5N0kEMFiJk0bHEbw2Q ajUvLG8AeK644meritzMMOxzHyHRb/ns92r2jy4qzg/U+AdkD99b14kOW3P69GPjud+TspeOMw1e x2743PZamjLW6R8T5TnE/cUbtEVpMp4/Jm2yIyleLm9Htrg9Hq+qD5p0bDUJ6O10PuLm2w6dDM5L O2Kwf/5qT7pC24/eHLzY6f0dTXrvFEBAQEBAQEBAQEFi5bhqVJrUx2wwMdJK7TXRrBqTp7CCMrcz 1bUMc9atZlhlaHxyCMNaWuGoPlOas421n1W8ZVPzk4OjaTx4DJJG0fcJUTuqmNcyoOctdcMMY6y6 Un/utVZ5NYW/FZZdnbG7jLA0eBrXvPuktWc8qPRaOPaVMmblDdTO4jp1bGB/Oo/kT6Qn+PLGdzGx zgA6yeOhOmwdHsBX/JaY9k/glZk5iG3c54jHhkkP8hWNtt49Ya14/wBGFLzTWaSO3jOv4oLlh+Wf WzavFj2YsvNg0PZuldpx8mMjh7arOz/8paxxfowsLzbJmZ5I6/pMYh4mSTRoPHTQBTW2fVOzjxRu vI7dMAwkaF09gnTh0zOXp6v2w8rdH3S2FaMhAQEBAQEBAQEBAQEBAQfNwQfUBAQEBAQEH5WqFntP 6lX8LMr+vLH5pUUol39ECAgICAgICAgICAgICAgICBogpcwOaWkAtPSD0IIjIcp8u34yyzj4XajT c1jWuHsELO2qs94aV3WjtLTcx3L4U0LLcPNNWsSDVjHODmEg66cRrxWVuPHo2jl29Wu1O7rmIY6W CSjvLAW9m5wAd1cNVyzptM9m1d9YRVvlnM0t7LNSaFob+TIYXtGg04OCz8Jj0dMbK27ShpqszRI/ Ts5RoAT5sgI46hF4aJzfW2cyOYD2Xb1mPGvmlzTpwPgUz2ypP7litC4sfFK3Q6ANk1BGvWsZWhT2 UrJ3aDQNeNdOA0PAosz2tcIZC0gFrnaDXrI0CpKVzHuLrM8Palj4Y90khjfKxrHecTt8SvWmVbXw 2Sj6L6BHchD2MkaCxjxtcNOHEdWuijOJWicxlIiQvbCWODYiwOPskcR7Kt5SeMeo+4WxODXHeJCw 8dNG9RKtOycEUhlC3NA2PU7jJqdAd2mnsqfOPWCsT6L8d1thhjcwajRxD26cCkTWU5sxrjsVWdFJ LFHXc52jX8AX69Q61rriJ7SzvfEdny/G6aqDE5zG6gnbwJU26s4lERYBgZpuI1cZC0jXiVSNUH5G HZ5fl2GCKXr0DiOP9InxqPwyTsdG+r/g5sdlMxK8giWGNoOup1DyV2cWmIlx8m8Th21dTkEBAQEB AQEBAQEBAQEBAQEBAQEA9CDyX3qctjBc+XomtLa9t3pMPg0k4nT+0s5hprnq0CXHQmZxc4hziSQF xzOHqRXMZVsoMbppHqPC4/8A3KPI8VZggZw3anr2BOqVmaSOPygzTTrcePuK0VUm+GJNac/odw8L QrxWGXnMscyPd1F3sklMJ/oBsx6g0HrA0TEHVIcq4uxf5krVo3QPkIcSbI3RtAaTqQCFfX3Z3xPe cNeyUcsd+zE7a57JHtc5nm6gnoUzHVWPp1Yzasjm6nydOnXgq5hOJWnRRNPF/Hr0GqZMQtOEDDwB PjPBEYhtHdVTlvd4mAijiL2emRueWgnQN4nUq1O6t5jD9AgABwXQ5QhBBZTkvlrKWXWr1JsthwDT Jq4HQdHQVS1IlpXbaIxEvHmQzfMeMyt6oZX7a9mWMNc0O0DXkDpHgXHanV6erZOMyux8/ZGI6PaH eEgaKvivNoSNTvKj3D0guiHW7RrvuDimEZhsWJ5yxd+w2KCYWJSCXMaCHADpOizvOGtcfRIV+Zak 5kZWsta4HRrvJOntFUiy/jEqJJObHkvq5KBw8MkQ0+4tYtHtLGa291r07vFhdwbSnZ+Nsc3+VT51 PG/0WZOaOfq79r8XVd/TAf8AyFM1Vxs+jAy2XtZWyyW3EIJWMAfG0ENGnEnik9SIx1nupx1CW83c 2Ps4T0PPS4JhfPRkZnJ43l+oSdrrRGrIus+Mq3ZnM57uY5O7dyth1q48ubrqG9QGvQERPV3b6rDW elZtzG7W9jAPcc5b6PVw8mcvQ66XMICAgICAgICAgICAgICDwD9aP+OvM3+h/wBvromHK1CXf/qV fxTyv6jsfndRSiXtNEPhcNOPAeFBw7vZ+sLSw4nw3KkjbmVGrJ7+m6GuR07OqR/3ArRVS1nmq1ay eWyLpp5JLt+2/Vz3Evke4+Mq1piIzKK1m04jrLofJ/d3HVcy9kw2e550dfpZGfC78Zy8Dm/Jzb7a dnvcP46KRFr9ZZnOPO9PAxupUy2xlSOI/Ai163nw+JYcP4+22c26V/6teZzo1xiOtnI7121dtvs2 5XTTyec951K+k164pGI7Pn9mybzmZY50V1MN35I7v5sr2eQybHMxmv5OLofN/M3768rn/Ixr+2v7 np8LgTs+637XVRDDAxkEEQYyNoZHEwaBoHAaL52bzMzMvoa1iIxHZpfO3OseK3Y7HPD8ieE8murY fEPC77y9TgcCbz5X/a8znfIeH207uZmWSV7pJHF8jyXOe46kk9JJX0MRERiHz9pmZzKoAHgeKtlV u/d/ic/JPHehu2aOPjdq3sZXxmQt6m6EcPCvN53OjXGK/vn/ACejweDOyfK37Xaoe8zPYqo6zdth 1WEauMwDuA8fSSV5Wjm7pt4xOZepv4WmIzPRE4z61UBsujyGEd6NuIZPBLq/b1EseOn219HWk469 3ztr1z07Oi8t99nd7npYq8GS9GtykNZWtMdE4uJ0ADjqw+6p8TyhvwIKqsICAg0vvayXofJlpjTp Jbcyu32HHV33AseRbFJdHFrm8PPuLrl9uWcDo0aCfH0rznsTPVPtjB8B8ZUYRNn1zI3NGrVEwmJU 9jFp0fcQ6KTXi118PtIdHx1dunAHh0aFTCMrMkPk8deHhGqnCMrIkmY9oYdviHA/cKnsrjLdvq75 POZPMc2S2bs02JqTRV6VaRxcxr9CXubrrp0BerSuKQ8fdOby7ipZiAgICAgICAgICAgINM749B3a Z4n8GuD/AMbVMDT+VJSMPTe0edXg9wtAXxXB6cq/9X0uz/t1bADr0Hgvdhzo/mMa8uZUaag1JvF+ CVaJwiO7QHYTOXdJhhZbcTdjordhwEAjMbQ3Z2jtNPYC9vXb7YfOba/fKTPdFzTkRDLLJTxsLW6a M/KnaeOoEYa37qt+aI6KxpynMB3b4/l22Mg/KSXLkcbmCEMbHH5Y0PQXOXNyd0TSYdXF48xsiU+1 5DNB0eNeRl7kwgebD+RqDXQOm0BWO2XRx47szlJ+kU3Dpsv4/wBsBbaJ6x+rn5sdJdWXsPCEBAQE BAQEBAQEEdzCwPwOSaRruqzDT/8ADKi0dEw5zyncm/6YxZDjtFWMbQdNTtXzPCvM2vE+kvbtSMR0 7r5zOQl0Dae0A6Avf/Mu+u2IjpBGmI9X11vLE8BEzXo4E6KZ2T7J8KqHuypaSbe3QF2jGgdA161n N7eiYrVjRWBYxLMjLkOzDyQIZZQx3A6f0V3auNNozlw7uZXXOMKZb/JsDN97Oxg/hMD3Sfe1W3/H z7ywn5OPZRRv8q5ES/Ik/pXYODZnOYWgbujTUBc/K40aoy6uJyvypA04gNWsAPiC4bR6u3ylSYQG v9g/eVJnC8SjOWYOymmkHAua3TTq8rVb6J7o5Lo3JLdOXYOOur5jqfHK5eppnNYeFu/fKfWrIQEB AQEDUIGoQfNzejVB9QY1vJY6m3dbtQ12+GWRrB/xEIIC53lcjVXFsmYge8fgRF0p9oRhynAjJu97 l46ijWvXndWyu6Jp/tTbPvLO1617ytWk27MOXvO5klOlDliTQ9D7M4aP/wAm1/31hbmao9W1eNaW PJzP3nWjqxmPx8Z6AGumcPZLnD/urC/ymqv1XrwrzKOuy94zozMzPPfO07hBEyONvDj+Jx9grKny 9JnGGluBb0TnKfehDZkZjeYmihkh5DZ9C2CU9HX/AIbvEeHgK9PXsi8ZhxX12rOJdDDgdFdV9QEB AQEH5WqFntP6lX8LMr+vLH5pUUol39ECAgICAgICAgICAgICAgICAgICAgIPjmgjQjUeAoI27y9h LvGzSikPhLQD9xUtrrK9dlo7S4R368j4fl4YzK1BI8WpZaz4pDuYwOZvbt6xxauXdpitZw69W+b3 jLnVaKs/ZK3RpcNHt4lnDTpHtrgmHZ1ZUNXs7RD9eycXANPEEDo0RaZ6MZuPPYuki4kBxcNevqUZ SmuVKd5uRZVYXuiykb6tgRgEkOYXN6fA4arXRmZx7sd+IjLJqSdpVmru17euw72nhxa7bwWUx6N4 92fBC9lJkeuswaXPbw0btP8AMkdiZ6lmNzqw2u1c9rJTp0Hjoplassmet2cUBMoDg7ceP30mCO6l 8zvSTI13asc0DQnjuH8izlevZC8/sIjxMp03C5EAPBwIXTxf3Md37WyNbZe0BrBoOorWHMrZFJGD I8AyE7Rppp4leESpjqbdXaEud09fT1BXVl1ru75amxVJ9ux5M9wNPZfitHEa+PiujXXDj22zLcFo yEBAQEBAQEBAQEBAQEBAQEBAQEA9CDkv1geWRcwEGbhjBsY922Vw6eyef5FEwmHnKxJDFYJkBLnA abVyXr1enr2x4sZ9mV2uxh06nPOqrFI9SdixJ2ztd79B4BwCv0Uz9VhwYAdTuPuplHRR5bh5EZPt KUZ9n0w2gCXFsYPh0CLYspdXZqC5zpB/R6FUw+4y96HallrtMTvNaSePHpXRq93Put1YklLI2MtN WpwPsyyntAyFpc7U8DwHjKjbHVOqW24TuI7z800OixPo0biPytuRsQA9gklUimV5vWO7oXL/ANUb IyAP5gy0UYPTDVBcf7zgFeNbOd0ezo+B+rZ3X4sMdPQdkpm9L7Ltw/ujRXirKdsuhYnljl7EMazG Y6vTDeDexja0+6ApwpM5SilAgIPH3epWiod4eche0gPn7VvDh5Y1XJtp16PR0bPt6tPkfUfrw4+H /wC9Z+MtvOGDNBVcdNSNevpTEozCzXE1Kbt6kgDyNp0OmoPSOCYyjxyzc++tdxtS1VY2pfY8ssRx Fw1bpwcfHqorEQicoKLN8w0RpBelb4BvcVeMSibSlKXedzdU0bJMJg3qkGv3QVPjCPyTDZsd342W Bgu0NwA0LonaH3HKk6oafnlslPvc5OvEelMMEjxppNHqPdaqTpXjeqyvPmLr4zXGN7WSUEQyAAMb pw14q81x0Itlz6Z9i7M6xZe53WXOOuuqiKotZiTnedG+YOgeFaRGGVrZeifqvY98VDJ3S4Fs4YwA dW0lbaYcnInM4d4WznEBAQEBAQEBAQEBAQEBB4B+tH/HXmb/AEP+310TDlahLv8A9Sr+KeV/Udj8 7qKUS9j5LJ0sdSmu3Z2VqkDS6aeQ6NaB4yiHmPvZ7/b2fZPhuWnPp4c6smuebNZb4tOLGfdK0irK 1nJMVh8hl7rKdCIyyu849DWj8Zx6gs9+6uuvlaWmjTbZOKur8scoUcFG5zWizeI0mtOHBo62sHUP GvmOXzb7px/b7PpOJwq6q5nugOc+8NsHaUMJIHTHyZrjfNb1ER+E/wBJdvB+Nz92yOns5Ob8hj7a d/dzKRxkc57yXPcdXOJ1JPhOq96OnR4mZWyPB7ilEujcjd3EkgiyuZrkx+dWou1Bf4HyD8XwBeJz /ksRNaPY4PBz913TmAMaI426eBo6B1ABeDPf6vciOmPRoPPPP5pGTGYiXW5xbZtN4iPqLGf0vCep exwPjs/fd5XO5/j9tXMCXOcXOcS5xJcSdSSV9BEYh4MzlWwdSDb+SuRrGad6bbBjxcbunrlcPwWe Lwledz+fGqMR+538LhTt6z+112aKlQodrJsrU6zOJ81rWj2F8zE22WxHW0voZ8aV9qw41zlzhPnr fZwkx4yE/kIejcfx3+M9XgX1PA4Uaa5n98vmubzJ22xH7YQcLN5DW6ue46NA6yvQjq8/DpvIXKDI 7VG5cHF00RjaekntG6H2B91TMpir1yABwCwbvqAgIOSd+9/SPGUAeB7Sw8exo1v8q4+XbtDv4Ne8 uY4NulYPPS5xK45l6SXZ5WgJB/kVcqyvGFmnEalWiVXwsb0NGishTozTweA9KCkxsOnEa+xogpkY 1up3BBF3J2xskmceEMbnuPsDh95TEZ6EziMumfVnxTqvduzISDSbL257bj4W7tjPuNXr2jHR4Wc9 fd1tVSICAgICAgICAgICAg0/vdbu7ts+Or0Un3HNUwNH5Ic12CpEnXWrFofYGmq+K4kf/wAu/wDV 9Lsn/aq2MaBvBe654Wr4rvoWK9p4ignjdHI97gzyXjQ8SpRlD2eeuVKWNr4qXKwSQVWMhjhjHbSE RjRo8gFbTt2TGKuedGuOtltvOeSvNEeI5fy2SHQx7o/R4dB1bpNAArfi2T3Zzs1QuGv3l2GdoaOO wsRGpNqbtnjxFrPJ19tWrw/eVJ5sR2hjZCpzXjcdBlJuY47rXW68Lq0FaNsJbNIGOaXEudw8SnZx axGYV18q1rKecLIZPjYm+Y+yWu9peTfu97T2lI8pyA1nkO8k2njXq/xF0au8fq5ebHSf0dcXsvAE BAQEBAQEBAQEGJlm78XcZ+NBIPdYUkco5RcDypjndYhaPc4L5bg/97b+r37dqpBrdHcdV2rR2ZTC NArQpK4dNjhp+CePtK/jlDnc3JuQyO7LmetDTlfqztNXvGnkkbOGi9fj3iKvE5mq1rzhkjulxhLH 286zQDhHXhGunT17uK2nl1icZc1eFeYynMDypi8BHKMbPYtutuaZzKAANnRt0AXnc7f5vX4PHmkJ klwAOnDoH8y870d8R1Y0+7R3EAAHh7Sys1qw+VC17ntJ1dtAPuldHH7Kcl0LksEct1NevtD7sjl6 ej9kPC2/ulOrZmIBOiC1NZghYXzSMiYOlz3Bo906IIO7z/yXSJbazdKNw6W9s1x9xupTAhbXfJyX FqKz7V9w4aVq0hB9hzxG37qdDEsCXvetyt1xvLF6fdwaZ3xwt19rtCstm6lO8rxrtPaFl/O3eZbO lbF0cew/hTOkmI9wxj7iwnn6o9WteNefRjyy95VtpbZz8NRh6RUgjafacQ5wXPs+X1R2jLavBtPd Yk5XvWv/ANIZ6/c6y0zPa33Glq5rfMT6Q2rwI9XyLkflhsvaPqds8fhSuL9T492q5dny22Z6No4d ISdfDYquQYKkbCOjyQVzX5W23WZbRprHoy2sawaNa1v9UABYWtM95XisR2h8cXEdJ9jVY2haHwNS sZMm0aeNT4zBlH5bB4/KMLLLNsnmtmaPKHs+ELq4nNvqt9GW3RW0MTC8z8x8oyMq32uyWEB2xPB1 fGP6Dj1f0Xe0V9Px+dTbH1eRu400dOw2bxuYptuY+Zs0LvO04OafxXtPFpHgK63MkQQUBAQEH5Wq FntP6lX8LMr+vLH5pUUol39ECAgICAgICAgICAgICAgICAgICAgICAg0zvS5Ln5s5dZRrOaLVexH ZiD+DXbD5TSfGFW9cxhfXbE5cPy3dfzTitr5aErGDcA+HSVvEf0V51tNo9HpU21n1Rbat2lKILMb tgDWvJB69AfJKymGsSyWUqszXiN/lN1LGnhtA4Eaqs1XZnLva43NUC5rjFuLpNriNRtI4OHsq2rN erHkdYwv3YKnp00LuL3PduIdo/Y7jx8PSsbW6uin7VdPdE/Y9wdG/UxyeFoBG1ysq+VIQ+zGGPMe 1ujYpOjTjw9tV7LSrdDtc6KdhayIO4+MgkBWlMQrq9mcZPPMzY5oY2LXjqCSDooglFc/QxkUYoW6 R1rMO8668St9H7mWz9raWtDImdsS9zgDtZwABHS4rVjldjgL/L27WjzW/fVlJb3yXye3czKXo+Df KqQn/vuH3l0a6e7k3bM9G/6LdgICAgICAgICAgICAgICAgICAgICAgwM5i4criLeOmGsdqJ8Z9lw 0B91B4yzeFuV8i6k6Mmeu90Umo62nRc+yYiXbx4taOjH+RrDRrPMyLwAkE+4Fl+SHR+GfWcLT6VF umrnzO8Q2j7qZmUTSpsYODIGhvhedT/IoxPrK0dO0PrYppndkzVxP4EY/mUZWmsyn8R3Zc2ZghtP GyEHokk1DfdKtWLT2Vt417y3fE/Vp5htMacnkIqTT5zGDe77i1jVM93NbkVjs2E/VX5W9A7OPJ2h d3bzZdsLT4tmnQtq1w5r7PKcto7r+5upyRet3nXPT7NlvZte5gbtbu3cFZTLpOiIEBAQEBAQeZvr CYljOforDmObHcqNIkb+E+MkO+5osN04dnG69HKrGP0817Xa9ThtKxi2W868dkfPXkZruicB+MOI VswoxjwOgcCfA5RhaJW31pH0bMzn+VA5v5MBxBDuGu7qVor0UmZRL3EcASCenXiqo8mM+STXiQT1 6q2EZlbcWk+U0jxg6oTL61rS4APAHgPBEN6o0xJh6DnHg0vAb1ed0qlnVSHyzI5/5NnFvRw6ykR6 q2tnokuV+UMpnspDQoxOkmkI3uaPJY3wn2FPdHSIzL113f8AJFDlHBRY6t5Uums8v4zz0rprXDz7 38py2hXUEBAQEBAQEBAQEBAQEBB4B+tH/HXmb/Q/7fXRMOVqEu6/U+usod4WdvSAujq8vW5ntbxJ bHZquIHuKUSm+8TnXmPnecmXJ1osWw61sYwyRMGnQ5+8eU/xkraKsJs1rl3kDP5u46JkZZUh0Niz GWyAA9AbtJ1JXHy+ZGmPe09nRxeLO22O1XTaOHxvLmNcWhtOpCNbE79A53je49J8QXzOzbffbr1l 9Lrpr016enq5zzf3hWcmH0cYTXxx4PkHCSUePTob4l7fC+Oin3W62eNy/kJ2fbXpVpbiNOA0K9V5 ymKGSWVscbS+R5DWMaNSSegABRNojrPZNYzOIdZ5F7tY8cYsnmmB90eXDVdoWxeBzx1u+8vn+d8j 5TNdfb3e5wvj/D7r92+utNLiwaMJBJJ6NB169S8eIeo5lz33hambFYWQEHybV9vTr1tiPg8JXu8D 4/8Avv8A4PH5vP8A7Kf4uaOHEnXU9a9uIeNMjCVMjduQ+Q5c9KLlwOixcZ01HB0rh+C0nq8JXmc7 nxqjxr+56HC4U7Put+12VjaVDH6eTWpVWHXgGsY1q+aza9ve0voMVpGO0OMc9c9WM7ZNWoXR4mIn s2dBkI/Df/IF9PwOBGqMz+6f8nzvN5k7JxHSIakwFztANSToAvSec6JyPye0gXrw/JN6G+E/i+x4 Sp7JiHScWBJmMe0DRvpEIa3wDeFXK2XoRZriAg+OOiDzx315U2OaLETTr6O1ldg6tdNXfdcvO3zm 71uLHjT9UTQgEdZjXO7ONjfLdproB08B0nxLnnu6ZviE7/0/fnoW5KkckNmtF2wEujmuA4hrmgAt JCtOu0RlyxyszjDXMDnDkq7nvGx7DteB4UtXDak+SvO5+LEY91x7O20c1jY9QNxcfCVfVrm84hXd sikZlr/0l493D0V8Zbru1IOnsaaLp/hzHq5I59PaWRDz7h5NNzyzXpLh/wDeqzxbtK8zXPqz6uax 9xu+CYPDvNLTqFhakx3dFbxPZEc5WvReWr8jT+Ul2wx+y86LTjVzshTk28dcvT3d5hhhuSMHjNND WpwtcP6Rbud91y9GZ6vHjs2NQkQEBAQEBAQEBAQEBBqXew3d3c8wN/8A5R/3wpiMyieznXd1L2nL dB3hqs19o6L43X9vO2frL6T/APwVT2Vnlixtl8LiJGxvLXDqOi9jyZVhyv6v+Mpc15TmRnMzX5UU pGyVmWJHuY3e7QjTXiF6lNdcQ8jbe0Wnq7ZhaWLpWZY6eMqVIWRveww19HAt4D8o8MHtfdW0ViGE 2me65Fk7VypdLpnO0iBYWuBDT/REQGn94q+FWBHIDiJy4guEzQS7QknTrBNg/wAqkYHNDJByhT7Q OH/1KpruaW8DYH4wB+4sd37ZX4/7oQnOwBuYnh0WHkH2l8/Z9PonukeU2n5PEnEt9IcRp0eVMB/K t9Mda/q5+bPSf0dgXtPnxAQEBAQEBAQEBBasjdXlb4WOHugoOOcoEt5XqD8Rpaf7LiF8xxYxu2/q 9+vWtUmyV5dx6CumJy0wyW9HTx0OmqspMIGPme5d5oPLmKoia42EzPmnk2RAA6HgOK6NWqbsN26u vul4uXeaZu0YbGLqRx8XBkMkrhp06anTpXZ/H6d3H/MjOcPp5YtGA2JM/O5u7a5tSvFFqfEXcVMc WucypblzMdIwrfydii+ubFrI2myn/mWdo/utatP49I9Gf8myPs4ynh+ZrtSg10cHo0D+zc9z/KJO p8olcHLpWvZ6PD2zeMSvudrC4nidpXDMO31YfKDgLcrf6IOvi4ro0QryezpPJo//ALZx/ji3f3nE r1NX7YeBs/dKbWiggFB5Y5yzMMHeFm/lisJsfPdlZXtSgv7Mxhrdo1JG3xKK7Im3hE9S1LY8vRvn LOO5XtwsEdKNlnQEEabJAegs06l5HPtvpb6PR4sUvXMtlhpUo+EVdkZHgaF41t1p7u+tIhkFhHVt 9jgs/KZ9VugWk9KTlOQM6eKjBk2DXinigI04acEwlTtKYMm1RMJy+acVEQZNmvHik1ky+dn41Scm Xxw01U1hOVBaHtMcjQ+N40c1w1BHjCmt/Gekq2rE90N8h5HFWzkeXZnxTt4yVD5jx+Lx4Eeyvd4n ymZis9Xn7uJ6tt5X7waWTe2jkGCjlBwMTv8ADe4dOxx6D/RK93HTMPMmMThuSgEBB+VqhZ7T+pV/ CzK/ryx+aVFKJd/RAgICAgICAgICAgICAgICAgICAgICAgICD5tCCPyWBxGSZsvVY52/0hx90Ktq RPdauy0dpallu53lW4JHVe1ozSDTdG7c33HArG3GrLeOVeGvHulzVFwfHYZbiiGkYGrX9PWDwWN+ NMR0XnkxPohuYOVcnFcEhxk+9kWostbqDw0LeHSuS2i0dZh2ad9ZjCAuQPawOLdxDNZIwCDq3Ti0 Hwdao3wx3NLWytc4uhDGua/8JhJ46pMDNjs23F+rmzRSlhLgOI08KnB6s2rNWsVzG6LyY3u2geEd Z9oKME2Q3OUMMeJlna8lwsRPaD1s3AarbTH3M9lujZaVftYYn6alzGkNHQOC3npLnz0bzynyq205 l203/LsOrGH8Mj+Rbateesufdtx0hv7WgNAA0A6AulyPqAgICAgICAgICAgICAgICAgICAgICAg8 79+3Kk9XmaDJ1InGDJAh4jDj+VaBrrp4Vhuh28PvMNRxHdrzVkw30bGSBp6ZJRt6fZ0WERZ1WtSO 8tzxf1e87YaDkLUVZv4o8p3/AAhaV1W9WFuTrjtEt1w/cHyXTDXXGyXZRxJe4hp9oFaxphh/Kt6N 1xnKPLWMaBSxsEO3ocGNLvdOpV4pEMrbbT3lLtY1o0aNB4BwVmarRAQEBAQEBAQEBBr3NHI/L3Mp iflIO0lgDmwyA6Fod0qlqRZfXsmk5hzzOfV1xllznY686uOlrXt3cfdWX4XTHK94c7zncZztj2vd DCLUDT50Z4kf1VSdcw2jdS3q57luXcpRc5tyo+Ij8dh4e2FCfCPRG0si6HG5ShGwBt0NBHTxYdwI W+vEw5tk4lrhrl+m14OvtLJbDGlryNcS4dHtoYYrhoeB0UxCDc72fZSUS6PU3f8ATOPazpc5zSev Xp0VHTE+jPw2Au5G/FSpxmW5MQNANdoKfu6HjjrL1P3c93eO5TxzdGiTIytHpE56ePS0Lo168OLd um0/Ruq0YiAgICAgICAgICAgICAgIPAP1o/468zf6H/b66JhytQl3f6nVZtrvFztZ41bPy9ajI8T rNUKUSjJGMZK+LQtLHOYR06bToujLml0TuYnAnytXdqHsik0GuvSQvnfnqdK2j6vY+Jt+6E33uxv HK8UjDq1tholYQHAgggagjwrl+Gv/vY+jo+Rj/b/AKuKur05fPrM8Zj1YfucPuL6h4jHnxdQgmN7 4z1B2jh9zRSiXVuQ+72DE0K+XmaLN6zGJGSfgxNcNRtB69Okr5j5Hnze00jpWH0HA4ta18p/dLaZ myGN0riBCwEvk10AaOkleZHWcQ9GZiO7lHPfeCL+/FYh2yk3yZrI4Om/og9Oz76+g4Hx/jHlb9zx OZzvL7admhHhx14L2HlPmgKkblyByHNnZxdutdFiYj5R6DMR0sb4vCV5nyHPjVGK/ud/C4U7JzP7 XaA+rRrMZE1lenWZwA0DGMA+4vmc2vbPeZfQxitfaIce5/5+mzlh1GgTHiYT0dBmcPwnafg+AL6X 4/gRrjyt+54HN5s7J8Y/a0hx0ceC9R5zeOR+T5LcouW27YW8Xa9I8Q/pHw9St2Vw6W0sbG2OMbIW DRjB0aBVWZ/L2r+Y8XGOJNmM6ew7VJHoNZriAgtzSNjjc93msBcfYA1USYy8r8y2HZPmIzOOpnsP ld7G7Ufc0XlzOcy92K4iITdB8ccze14sO3jproWuD2kjwbm8fEs4nGJRspmMNg5o5zjjp37VBjX5 XIQiDsoA4t4AgOe4gcG68Ota7N3nHi49XGms5lofK+Gnx1IiY7ppjuk8SzvaJ7OzXXEILvItboal QEDVxkcBw6OAXbwa9Zlw/IXxEQt4rlfk6zyPPn8jbnht1pZK8teIsJmkc0OrhgcPJA47/EFpfdsj bFY9fV59aVmmWiWnCKrLJ0BrdrB43cCV2xLGG2939J0dKJxH4O8/2uK83kT1ezxo+1NZio7K8w8r cvsG70/IxPmaOPkMeCdfa1VuFXrNkfIWxWK+72A1rWtDWjRoGgHiC6nnqkBAQEBAQEBAQEBAQEGr d57N3d/nm+Go/wDkVqd4RPZy3uwk28q48knUVy33HlfG7OnyF/1fR6uvHr+jab7Y34SfjoXRv18f SvWwz7Wcv+rbJDQ5j5wbblZWj2sfvme2Nu3fw4uIC9bVP2w8jkVnzl1avzHyxVllezIi/I4PZ2dC F9g+V/8AFG/o/raK9ttYZV02nsx4s7LskZj8FalbK0NfLlJ2xRloP/htMrvcAWVuVV0V4dp7qTa5 qeC30ihi6x6GU4C9+n9eUhvt7VhPN9odFeDHqtfJMdt8Ul65dyj4XtkjZNKTEJGHVjuyYGM4Hwrn vyLW6NqcWlZWs7hb+QkrTNLIxVe6TbIdC7UdQGq551TPWHZTdFZwjcK/I18tise9xiifXsTTVHg7 3u9KiDHgeAaldPGpmIz3iXFzr9ZxPR3IEFeo8gQEBAQEBAQEBAQfHjVpHh4e6g4xyq4DAFn/AIc0 rP7srgvm9EY3bf1e/SP9uv6JKMauC2qvbsydPIOnSOjVWVaZyUXM78pg7okoScPYIXfw56OHn56O pV3xQT3O2lihBaQHPkjHSevQgrvmYebFZRM/MPLNem6pazVKObtN4DZRLw006FW26sH4rT6I+Xn7 lgGCKE3LjoeG6tXftOnHXceGiytyaNq8W8+jAsZC1k83bybqb6sEsUMUDZSN7thJJIHR0rzOXt8p erxNM1jqvydoK8mjdDsJ06dPAFz+jrrMZYHLVutVsF1h+0ybYm8NNXu10HFb6J6SrzOtXUeTRpyv jB19g1etT9sPnb900rqiAUHnfIY2jmZ+YKl1gfGcvc2P/CY7cNHNK+P+V5NtPLm1Z/th9DwdVdmn EtOx1/LcmZNtDIl8mM3/AOUts1/J8ddzT4Pxmr6Tg87XydWM/c8ffxr6Z6dnaMDnYcnFGC5psFu5 j2kbJW/jNK8fncC2ufKOzs4/Ji3RLMHh149C8+MOuVRb41MRlHk+bQVOCZfdinB5PjmaHVR4piXz hroOKjxTk2E8dFE1PJ8eGtGrtGjwuICtGq0+iJvEMWXJY2LXtLLAP6J3cfaW1eHtn0lnbkVj1RV3 nXlypqJLGrh0DVo1906/cXTT4u9u/RlPNrHZr93vawsOrYGB8ng1Lj7nBdev4SJ7yynne0Neud8d x0hjqQcNOkNA+/qVr/xunVP3M55Oye0ImTnfnTJO2xQzGJ/Fr2B50Ptq1r8bXOYwiK7r9MLAo94F 1w3HsNT5W9wAcD7HFZX+c016L/8AFbJ65eqMBHJFhqEUri+VlaISPJJJdsGpJPjXq1nMZcExicJF SgQflaoWe0/qVfwsyv68sfmlRSiXf0QICAgICAgICAgICAgICAgICAgICAgICAgICAgIPhCDBvYT E3m6WqkU3Xq5o191UtrrPeF67LR2lrWX7q+W70T+wa+nK/gZIzrw8GhWFuJWezopzLx9WrXO53L1 2l1G8yyGPD2RyAxu4f0hwWF+JMdnVXn1nvGEBb5P5vxzoRLTe8/lXOLDvaOH4zVhbVeveG1d+u3a Wqc42JTy3akswui7JkbW7uBBa9o4q2m33RlG6sePR1XkLl/5TqVJ3tIpsiY5zzw3u012jxLtjVme rgvsxH1dPjjZGwMY0NY0aNaOgBdOHJKtAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEFqWvDLp2sbX7T q3cAdD4RqhE4VtaGjQAAeAIKtEBAQEBAQEBAQEBAQEBAQEAjVBiW8Zj7bC2zWimaeBD2B33womIl aLTDm/PncRyvm8e9+HqxY3LsJfDMwbWPdp0PAURXHYm0y5tV+qlkbGDbJNkG1M1udvjcd8RGvDQg a8VW1Mta7sQ0bmL6u3efhy6SOk2/CNfylR+46f1ToVnOuWkbKy5vlMTlsbK6DJUJasrTo7to3M4+ zpooxMJywAInDc0HUdWuqGMuocpU7WSw9OCrH2k75drQOkbgq3jo31T7vT3dj3dU+W8dHZniDslM A57yNXN1HRqVrq147uXfuz0js37RbOYQEBAQEBAQEBAQEBAQEBAQeAfrR/x15m/0P+310TDlahLv 31K/4p5T9Rz/AJ3VUolic2U/QuacvVHDsbk7QPF2hIXTVz27ti7obGzmaeLXb2tV3HxtcCvE+cr/ ALMT7Wen8VP+5MfR0HvNiMvI19xHlR9k8eIh41K8b4q2N9Xo82M6pcG3+HQr7B89D47QgjiNUJh3 PlW4+flLFPB6YGs0PhYdq+H59Mb7fq+p4k51x+i1zdCTynlXa6Ewuc5jeHEEcU4H/er+qeX/ANu3 6OEyVoXjVwB8BIX3M93ykSx3Yxh80lp6uOo9wqqyc5K5I+Wcg82pNtGsAZQ3g55PQ0eyvO+R5k6a Rj90u3gcb8tpz+2HaazKlWoyKMNgrQs0AGjWNa373Qvk5tNrZnrMvpYiK16dIhyDvC58OXsPxuNe Ri4zo944GZw6z/RHUvpvjuB+OPO37peBz+b5z417NJ3+PoXrvMbdybyjPkbLJZm7WNIcS78EdR4/ hHqVoHU2xwQQtrwDZBGNAB1qotyTNaCg6j3a8lGs2POZKPS1INakDv8AltP4Z/pEdCraVoh0gBVS ICCC52yHyfyrk7WujmwOaz+s/wAkffWe6cVmWuiubxDzdSDZswSeLY2/dK8v0e5PdPxNbx1GvjUR Csy+iMOJOnAqMIyPDOrXVIhKPyWGx18A3K7ZXAaNeekDxELWmy1e0stmqtu8IWxyThZY+yY+SFhO 7a12o18OhXRXlWjq5r8KkxhC5buz9Kr9nVvBgB1cJG66+2FpHM94ZfwK+kp7F4b5Mr9jvDnABure A4DRct75l3a6eMYS3djjTmO/KtJpurYCi+d/gEkg2N+69d3FjGvPu87nWzsx7PTy1cwgICAgICAg ICAgICAg1vvGaHci5wHo9Dk+8rU7wi3Zx/uvmA5RqPe4MYyCUue7oaGOJ4r4/fH/AP0Z/V9HpmP4 9W5MmrSU4272yRvbqSOhwPHgvVn2VnvljtwWEkkE4xEUkgGxsrom+brroS7pHsq9ZsztFZSMdd7W BkQjgZ0dmziP7rOCTEyiLRHZX6C4ny3yHT8EERj+UqPxp85fHQ0IPKlfE09QcdzvdcVE2pX1RHlK k362mkQln8DYwQPvAK0b646dV/xSxLjs5MA2j2NAHzpZR2rvaa3+dTS+f3dGd647T1RtjHzRXILF nKSy5QNcIbccbGOiYXBxY3Xd5BLRqCp/NETCkcWbRMtuw/OWUgYW5aJt2s3T/wCoU2ne0f8Axq+p cP6zNQvQptrbs87ZotVttDI071ZtipOyxC7okjOo9g+ArRiywUBAQEBAQEBAQCg4ngAW0L8Q85l+ 00jo6JXcF87EY5F493vabf7cJGN+jgGg69fsqeuW8TGGY3tC3QcdOkLXPRlPdET8pY6e/wDKMjZG 2yC3tY5DG7aekatI4JS9o7Si2J7woHKOG7Tc+syQnpdO50hPsk6qZvefUrFY9GWzEYyu0BsUDAOg sYPvqJrPqtEx6Lh9FYPJfoD+INPuKv2rxaV6JzHHVgLwenVRmpNl9jZnAua1x8LQOJ91axMMZthi XMI2zXFkxipOyVk2spDt5YfNIHQujXSO7HdsmYw2nkbmGjNRgwsm6vlKMYZJWlG0vaP+ZEeh7D4l 30tGHk3iYltzTqNVdV9QCg88Y6QnKcwgnUDM3NP76+K+ej/f/o+k+K/7f9WVlMVRytF9O40OicDt d1td1OavL0b7ar+VXbu1VvGJaPj7mU5OyYoXt0mIe4+jWAeLD+Mw/favvOFzdfKp93fD5fl8W2m2 aw7JgOYIb8cUUz2mZwHYyg+TKNPvrz+dwfCcxHR08bf5R1TQY7XQA8OledSkx6OrMKZZIYuL5WMH WSQr11bJ9FJ2Vj1YUudw8Ou+yNR07f8At4Lo18HbbvCluRWOyFu943LtY6CRr3joa94H3Bqt/wDi rT6sZ5sQ1+/3yY6NpNdm5x1Aa1h13ey4tXTr+NpH7pZ25lvSEDa72sxZ8ipA4k/hg6lv9loC2jVx tcYUjbvv2hHS5fn7Ju1ZBJGND2UobwJ/pbuIWV+fxNfrDSOFuv3WhylzfdYHXLYjc7z43yF7dfCN vQuTZ/5DqrH25a0+IvnqzIe7aJ20XL0kgAG4NboQfE48V5+3/wAi2T+2HXT4qsd0pDyNy9CQXxOn c3g10ryeHtaLz9ny2+/rh3U4VKx2ScOHxMGnYVIYyOsN4+6uW3J2W72mW9dNY9GUNrB0DTq6vvLC eq+MdlMr2jyug9JKtrj7oj6qz0iXcqrNleJv4rGt9wAL9KpHSHxs95X1ZAg/K1Qs9p/Uq/hZlf15 Y/NKilEu/ogQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQNEHzaowI7Kcv4TKwPgyNKG1D INHskYDqNdeKjxhaLzHqyqdKrSrR1qsTYa8QDY42DQADqCsiZZCIEBAQEBAQEBAQEBAQEBAQEBAQ EBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQNEDRBg5HDYvJRGLIVIbUZ6WysDvvhE5c45l+rh3a 5p7pY6jsdO78OsQB/dKiawtGyYSHd73L4PkuxLNXty3g8gxMna0dmQNOGirFITOyZdFA4K7MQEBA QEBAQEBAQEBAQEBAQEHgH60f8deZv9D/ALfXRMOVqEu/fUr/AIp5X9Rz/ndRSiW2d73d3zgznTL5 WpiprOKty9vFYgb2g8poLgWt1cNDr1LatujG1erW+7KSanzxVjlaYpXsljcyQFrtS3raV5ny9c6J +js+PnG2HVud3MscpZdnEaQOIb42kFfNcC2N9Z+r2+VX/as89a8OlfcYfMRIHH2lCcu2d3D2S8m0 QRxjMjXHw6POi+O+Wj/+RZ9HwJ/2oSnMrBJgMgNdQasvi6GlcvEnG2v6w6ORH+3b9Hn5nmt9gL7t 8pHZVx16eChLofdVLsbky4f+Hx8HSvnvnv7HsfE/3Ng51c08r3wCNdrQXDgSC4eBeZ8bH/8AIq7+ bafxThxiXFVnjUaA9Wo/lGi+19XzDO5a5ZFzLCNw1DBvGp1bwPTp08ERDqcMVenXbWrjSNnnO63H r1KhK3JYPuKcDfe7TkZ+SmZmsmzWjG7WrA4f4rx+ER+KPuqsymIdjAGg4Kiz6gIGoQaN3p3GjDw0 QwzSWJC/sG6alsTSQSPBu0XDztnjTGcZl18Ov3Z9nCKLLNCxOL0boZnkbWvBB0HsrlzE9nrQmIbs Tmja8DxKCashlgngSCD4FGUeL72hGuoGimAL3O6ANfHqpiVZhS1rePWetWVUva0DqJ6kGA57nzBp 049I8SWWhtX1ZaItWubeY3DX0u42nE7+jCNxH/EF61YxSIeJtt5XmXeEUEBAQEBAQEBAQEBAQEEP zZjbOU5byOOraekW68kURdwbucOGpUxOJRMdHnbk6xkaUl/kLK0JK2Qjq2xGeB3NLdTqHaAjwEcC vE5nxs/yPzxPR6/H5Ufiins33AZmOLE0akVK1PaghjjljgiDGxuaAAHPdw49K7LafVSN2Zwm23bD 2jTHS9r+F2727B7B1OvuLnm+PRvEfVW12Ue3TWGu3wMBefdO0Ks2vP0W8Yj6qPQmvP5WWSQ9Yc7Q e43RZ/jzPWVovMKInYptp9ZnZekxaF8Wg3AOHDiVMRWJTPlLKc+MDifaWkzCmJY884aNQNB4FnMr 1hr9uyZMmNx0DWkg+2s89cumsdH3t3xuDmOLHjzXNOh+4tK39lZpE92dRzE0MzpgXxykgutQEMkO n47T5Eg/rBdFORMd3Ju4dbdu7c8Nza2eMCdzZtOmeEEOHjkhOrm+yNQu7Vui7y9vHtTu2SGeKaNs kTw+N3muB1BWrBcQEBAQEBAQD0IOElrJZ87jYn6WocxZcYxrv29qXDQDjxBXg/imeXP1e3p2xGuE /DFdbr2deU6Dc5zmkAe6BquidE1I3xZcZ8pTDyGuDT07tG/fWExLTMLjcfccCXyhob0h3/YkUmUe cL7cRw8uRxPXtVvxyidkei43F1AdXMc7TqcVeNH1UnbK6yrVZ5sLG/8A28av+GsI8pWBkIhamgY1 oEO3c5o8PsLOfGJxC/hMxldfaHW7Q9C0iYU8EXkLbXWImF2vEkg+wq32dcQ1pXDCfO12kduIWYWH dEQdk0Tup0TxxaQrV3TVXZxa2bThOa7NWBovSuv44dGRa38tEPxbMY4/22+2vQ17Yt2eVt0TSW6Q zwzRMlie2SN4DmPYQWkHrBHStWC4SDog83YSXfkM/oeJy9skf/iFfG/PR/vx+j6P4mf9v+qejIGn urwpenbqtZPGUsnVfWtx74nDh4QeotK00brareVWezXFoxLRorGW5LsOqTNfdxs+opkE+S8cQdR5 pC+44Hydd9MT3fOcviW12zDMn7xObL7nMrRPcNNGlge92unDUFdE7uPT90sq6t0x0Y/Zc+33xue6 SMFupeXNY3Xxt6Vy7fmePXs2p8dst+59ZyJmLDNLuQA1dudtJfw9teft/wDIv9MOqnxMeqRq93uJ jJdNLLOdNCODRp7XFcGz53dbt0dNPjdcJStyngIGtDKbHAcQZNXOB8OpXBs+Q3W72dlONSPRIRVK 8GnYxMiI6drQ3X3FzW2Wt3lt4VhdL2ne7QuEY1eR0NHRqUjVa3WFLWrXuB7XAEDh1FVws+E6cQFG F4Ul3HTRTAo61I+EaonKkN1PZnr0HtnoWuiM7K/qx3T9ku9RjRoHiC/R4fGqlIIPytULPaf1Kv4W ZX9eWPzSopRLv6IEBAQafmO8zA4nLXMbZhuP+Tewdk7cVdz69WOyNY5JZAeDfDoDp09CC0O8SvXi svmr2MlJHeuVo4sdXc4tipkb3SGRzWeSHDyt3lfghBTf72uWKmx4iu2oPQoMnLYr1nPjhp2N2yaU 8NoGw6jp8SDLn7xsBBmHY57bJijsx0Jsm2EmlHbmA2QPm14PO5o6NASATqUEXzlz/lMNn7dCCJsN Kjh5spYuTQSSsL2vDI2gxub5I47uBJPAIJCPvLwDs6cT2NwOZeOKkvGu4VBd27hD2pPS4dBA08JQ YWN708ZLWosnisXLU8LLFqajWeYoIpp3wRSSMc7tAC6M9AdppqeCD5y53oQX77sbkKk8E78pbxde 6yF3obpa73mOLtSf8R0Ue7o014INuzeYgxGNmyFhkssUOn5KvGZZXuc4Na1jG8SSSg1Gz3p1xLi4 6mMuPkt5b5IvVpYts1Z/YOm1Ia5zSSNpGh026+BBmZnn6LC8xZCnkWf5CrSpzw9ix0liWzcsSQNh YwHyi4sG0IK4+8XGS0zNDQyMtxlk0p8UyvraimbH2pErS4Ma3syHBxfodRogx396/LLoqUlWK7eb cq+nuFauZHQ1u0MJkmZqHcJGlpDQ48DwQZfLvOs2Xl5kY3GzsOBtSVoWlpHpIZEHjYXfhu16PAW+ FBqtrvU5lw3pUGbxlR9/5OZfr0qckjpK8088deGrc3A7XPfO3y29OjuCDZ8BzJnpLeaxOdgrMy2J hhtNkpmQ15YbDHlhAk8sOa+JzXe0UEfR716UWCxV/LU7TXW6VW5kLVaBzqlYWjtbvkc4cN3U3cQO JQTL+f8Al2MDtJJGPGQmxTmOjIcyeux0srnjqibEztN/Rt0KCLZ3ucrGhZyE8d2nVr1PlGJ9iu5n pFMPEZnrtBJe0F7dRwdoRw4oL0Hehhpr7KQoZJsoMDbZdVI9FNo/kPSG7t7O0HHg06DztEGdzHz3 icDc9DsQW7lhkDrtmOlCZzBVa7aZ5tCNrdQdNNSdDoOCDB5Y50t53nPOY2GLTDYyvUkqWeyd+Xda Z2vaCXdt2FumxobxHHVBgY/vZqRct0cnmKVndNA61fmpwl9atEJnxB73vcPxNdG6u69EErP3j8vw Zh+NeyyY4p2U7OTbCTShsyMD2wyTa8HbSNeGg1AJQYUPe/yw+N0skF+tAakuRrTT1XMZPUgLQ6WL jxHljQHQ6cdEEpl+fsDi5rdewZn2qbah9Giic+SV99z2144Rr5b3GJ3Dq60GCe9PAdlVDat9963b loNxjKznWo7MDQ+RkjAdG6Mdv3a7dvWgr7xM1zZgsU/L4eWj6LXMMc1e3DLI9757DIQ5sjJIw0Dt NdNpQRuQ7wsxy7nziM9XOS2Yx2TmnxNWUljW2HRuc5j5H7WMjAJ8rUnoQSdzvQ5aq3fRyLM1eM1h cyMUJdVrG4GmATyEjbvD2ngDt1GuiC9mucXYnmR1GeIvx8WKlyMhhjfLYMjJ2QtYxjfO139GnSgx /pPwgrSudVvMyEVuOgcSYAbjrE0fbRtaxriwgx6u3btABxQZOD7w8BmLENes2zHYmNxvYzwuicx+ OcxllrwegtdK0eNBg2O9vleKvBaYy5ZryVI8jalggL21Kkri1k1niNgO0nQanQE6aIJjE84Y3KZ2 /hqUViSXGENt2zERWD3MZI1jZSdHOcyQO0CCNb3n8vixPFYgu1GRV7VqGaxXMbLEVH/HdCCd529I 3NGo6EFmHvZ5bfVs2Za9+t2MNexBBPWcyazFck7Ku6szUl/aSeSBwPhQfcBz/ZyjuaZXY+eGLAOj bDTkjLLbiarZntezUgnedG7ToQghcd3y7nQWchirUePmwtbLzGvC6V9ftZZWTPlJcPyLRGHNOmpG p0QbHY7yuXYcucbtsyRsnhqT5KOEmnDYsgGGGSXUaOdvb0DQajUhBm5fnfBYizkoL8kkMmLpNyM+ rDo+B7nMHZH8N29m3aOsjwoMFneVgHZYY7s7QYbIouyBhIqMuubu9FdLrwk/BPDQO8nXVBj43vb5 VvDtXMuU6T6ti7XvWoHRQTQ0/wD1BidqSTHr0acerVBXF3qcuGnas2obtGSsyvIylarllidlt5jr mCMF2/tHjaB0g9OiD4/vUwEcEJfUvi9PddjBihWLrbbTYjPsfG0kAGIbw7Xbp1oJDmbnjHcvEel0 7thogfbsSVYO0ZBBGQHvleS1vDXzRq7xIIMd6tOvzBlqV+tOcZSmpNiyleFz68cd2Fj432ZNfJ1e /Tg3gOlBIfSdy8L8lXsrjoWzT1Yb4gcas9qs1zpK8MmvlSeQ4N4aOI0BJQVWe87lWvUhtGaWWOeh DkoRFE57nRWZBFAwNH/NlkdtazxHwIJLl/mqlm69t1eGevaoSmC5RtMEdiOTYHta5upb5bXAtIOh QQOL7yT8j8xZjP0JcVXwN8U3VhpPPsMULmucIi9pc50/Qw9CC5T718DYyTKElLI1JvSo6Fh9msY4 4LM41hjlfuIBlBBbpr0jXRBix99HLczYnQY/KztssmlpmOm7SdlYkWHR6uHCL8InTxaoJLPc/QUa XLd+hVkyFTmG5XrxSRNJLYrEbpGv0/G4dB8aCEwXe3BexRddrTU8i+PImtZdA/0GSTHmRz2Mfu3P LY49zujXiGlBnw97OBEjK80VuZ8LaIyV6Cs70SB+RijkgL3uOrWv7ZvhI60FGY72MXBTyxoV7Mk1 OC96DdlgeKNi3QifJJCyYHjoYyNdADodCgy4+8/AnGemATWndrBTjbUiMgs3ZmbnV6p10kdHod51 0b1ngUFEnety+Ia7oa16zbnNkSY2GDdah9Cc1tntYy4admXt4NJJ14aoMmPvFwk2aGKrwW5niSGC e3HA414ZbMYmijlOu9hcxwJO3RuvEoMznnmaXlnlW/nI6rrj6bGubXZrq4ueG8dOrig1/Hd6cLs9 ksbkaFqGGvka1CvbZXcY4jbrwyRNtP3HbI6SYt4DQcNelBKYvvGwGSy8WNrsstZZlnr0chJCW1LM 1XXto4ZNfKLdjuoA6HToQa9zF3j3qPOGVwhzWHwtfHxVXwfKUUsssxsRue4jZNENG7dOhBlRcy8+ 5LmXNYnCyYstwtbHza2YpyLMl2F8h2vZIOybrHw8l3AoMel3kZjmNtJmCFTEtGN+U81eyQdLHV1l fAIWtY+IOPaQyFzy8ANGvWgsX+87LV8FiLL7uFgluZKbH2ssyU3MeGRRPlZKzspGuaZNrfIc7Vuq DZcFzaHcsX89eydTL1KPaySWMTDI1ojhYHPbsfJKXPHTwKD6zvL5VkvWqUM8ktirNRruayMu3PyQ Br9n+MNHav8AxUGo2e+a3Di7E8dL0h8GKq5QX2RStrv7e26B7QwneAGt8nrLtQg3bF851crUyrq1 WzVu4pp9Ip3ojDI0uiMsRI1ILXt8BQaizvl7Xkl2UZSmr5o4sZKsy1C+OrZ2ljZjXfrq5rDIOnQ6 EHoQbVJz/iIc83DzV7kQks+gxZCSEtqutCMydk2QncfJHnbduvDVBA5jvgx7cPauYmtP2jY2z46z dhdFUtQtsxwSyQya6uDRLuGumo49CDZI+eMNJgsjn4e3lxGO7QvttjO2ZkP+JJX/APEY3Q+UOB0O iDHZ3j8rvyFrHxzySWqdurQlY2MnWa7H2kRYfwm7dS4jo0KCJyfevTGHy0+Pp2YchTx8mSpMyEJh jsQxvEZkbo7dt3OHB208ehBnw95mDkzAxXo90OFwYyW76O70RlwtDmwmTX8IHgdNPCgZDvMwsPL8 OWpxz2jeqXLeOgEZDpBRaTIHfi/zIL7ufqNbljDZq7VsNnzQgZUx0TA6d887N/ZtDi0dAJ1cRwQY 9rvRwVeGvIKmQnllrPuz1oqrjNWrRPMb5bDCWlgD2uGg1J0OmqDFj7xmyZ+Sv29duJ9Kgjr2tr3d pXmxpvF+4Ha3QDXceG3xqRfwPeLDneZ6eMp07Felax82QjmuQuhdLG2SNkUsOpIMbw8njoejhxUC +7vQ5SZar1ZLEkU9n5Q2xvjcC35LLha3/i6bDt/G6kFpveny46xCxsVz0V5rMsZD0d3o1aW61roI rD9fIe4Ss14aN3DdoguQ95vLcl81nekQ1XSWIYMtLCWUppaYc6dkcuvEsEb+Omh2nTXRBi4DvIGd 5uqYipRsVqNnFzZJktyF0MkjWzQxxPi1JBje2Unjx6EFF/vQpfLGPx2NrTvis5T5NlyU0Lm03GKO R1hsM2vF8Zi04jTgdNdEF6r3tcqSwS2ZRap021ZL9WzZgcxlqtC4NfJW01c/i9ujSA46jggrHehh dmx9DJRZMzsrRYaSsW3JHyRmVrmM3bSzs2ucXbtBpx0KCuDvQ5dszYyvWiuz2MqJTHCys8vh9GlE Nj0kf8rsXnytfa1QR2U73sbXw2Ut1sbe9Oo0flKvTtQmIz194jEzRuLmsDiN24Bw8CCQm7zsFBcb Vmgtt2GtFftiHWvTnuNa6KGw/d5Dz2jddAdNRqg3IdCAgICAgICAg8A/Wj/jrzN/of8Ab66JhytQ l3/6lX8U8r+o7H53UUol7S2jqGiIR93A4e7K2W1SgmlZxZK5jd4PRwdpqq3rFoxPZNbTWcwgs53c YbJ4+zUjdJU9JY5jnsO7TcNNdHLg/wCL0+UWiMTDr/nbMYnrDiWd+rHzZU1fiMhWyLOqOQGCT7u5 p91ep5PP8HPM73e88YLccnhbUMQ/5zWGSP8Avx7grZiUYl0HuntB3LAi1BfHNINvQRx16Cvk/mq4 35+j6H42c64bJlnMmwl9o1GteUaeLYV53H6bK/rDs3ftn9Hnhsh2j2F98+Ufd/FQrLo3dJNEDkw/ oLYzp7ZXz/zsdKPZ+Jnu2LnQQf8AS18sB4Nb7HnBeZ8Z/wB+rv5v/as5C0+A6L7OHzLY+S9flCV2 4D8mRrpx4kJKrbZXknTqULNm5A5Ln5jviWZpbia7v8xJ0F7uns2n76iZwRDvVeCGvCyGFgjijaGx sbwAaOAAVF10kBBYt3alSIzWpmQRDpfI4NH3VEzEd0xEz2aZmu9zlbHhzKrn5CYdUI0Z7b3LC3Jr Hbq6qcO9vTDnnMHfbzBYa9lJ0WPiPAGP8pJ/eOv3AsZ3Xt26OiONrp+7q5vk+ZsrayDLM1qSaeJx LnSvL3EHpHiWU0mf3NY2V7QzHc00JyHZCJ7to0a8nefYHWsfxY7No2M6GTCTt3Q2Aw6Alu/aQD4Q 5JiV4tEr8dHdoYLfA8R0H7oKonK56PlY/NkD+rzv5wpyl8NnJRnyonHwkNB+8pB2SP4Y2Hr4EffU 5Umr6bIl4gud4AP+xW8oVmHw+jMw2ayM0vZfJ9R0sTegukcQ1o0PsqY6zEMtl5rDqf1dsOcd3U4p z27Zr7pbsnhPayHTX+yAvZv3eLV05USICAgICAgICAgICAgIBQcy78qFaDlZnMEMbW5nF2IDSu6e WwPkDXMJ/CaQeIKreM1n9F9dsWhhennIFu+c1JHOZIWM0bG9wbpuGnR7BXzGr5qm37dn2veng/jn yr1ZbL88B7K4zyDwbMOjTxr0fT6e6k1iezMFiPaHN469GnEKMIYt2/2MbndHg9pVtbC9a5aTjrMd jKZJ0jtZHyNc0nUHg3TpWWXXjENhx96fR0Esm948qFzhxcB0s18KtFmOysMa/mB5TA7yxw0AJ4qJ lalUCMjMLpllY9semm92mnT4lWWuEoycvaCCNerXrCVmVbQuwOkkkDI2l7z+C0E6+4tMTLOZhJ1s XlnSCQQejub5krnbCNfY4rWlJYXvXtls+KmyVb/EnbJIdBujbp/f6nLspaax7uDZppPbo2OrmIDJ FXsPZHYl4Rx7hq4+JvSuml/JxXp4pMK6ggICAgIBGoQaHzpDTocwYzKQ14xdkZOyWYNG94aG6Anx aleL8xyZ0RW9Y65d/B1+czViNlMsQlbO+aM8TqfKaT1KujmV5FYnPV2/h8JwutftGvnA/hcVvnHe FZQXNmeFWk5jHbXOAGo6vKCi94hrq157pbHZD0iuPK1mYBw8I0UxdS+vqyDY18SrN5lTxWbFrRmg Oh01Senq0rXKDxExkyOQ1dqdY9PurOnjM5y2vExEJKzC6Vr3xE9vpps14O/mWl69Ms62iO7WMpW5 jhylZjKM0weNwewatA8ZXN4WmezX8lE1Hg8rI0OfGISenc4fyLaum092U76wzavL1+vI2WK22F/4 W0FzSPARwWtNc19YZW2Vt6Jmk6xjX9pRlY1ruM1R/kwvd1ln/huPi4LaebSn7rQ4r8fPaG043Ix3 6rbEbXMBJa5jxo5rmnRw8B9ldmvZF65js5LVmJxLzdlje5N56v4fNRhlXKzy3aV1vBju1eSOPt6H wLxPmOBOyPOveHp/HcqK/bLZmO6OOuo6R0L4+X0VezIa46BQiYVOhgl0D2B4ALtrgDx9tItMdlZx PeFoNa1vkgNPsfzK85T4waN11VcJfdT1AJgwF3DoTCJGu48VEwh8+74kWQOQwmUs5AzNsbYCWlrd zhpo0tc0gHRwOuvFe3w/k66dM08erg5HFnZeJz0TUETYYmRjUhgDRr06AaLx7Tmcu+IxGFwkKEqe GqhCg9KlL45zm6HqRMRCuuN96uNODpY+H9sarp4dc7ax9Yc/Jnx12h3gBfoj48QEH5WqFntP6lX8 LMr+vLH5pUUol39ECAgIOaZLkfmHNc182xOt+gcvZqLHwTawtkfPHFE4TdjJvBjPHYS5p6dQgqyH dIbc/aDIxujNm/YNW1WFiAfKDmOD2xl7W9tCI9rHu1GhPBBkUO7CevhchjZsmJXXsNBg2yth27GV xK1kpbvOpLZuI8SCux3bWpbliBuXLOXruRhytvG9gDKbELo5NjLG7yY3yQteRt16gUEhzbyN/wBQ vyTjc9G+UMU/FEdnv2b5e07TpGvg0QUfR/xefTfP5gHMH+H4AB2HneLzvuINfn7mXS0qVM5WPSpG 2Jls1R6XAWzumdJTsNe18Tnh+jg7cOvRSJ+Du/EUNCP00u9Bzc+c17MDeZjMex87hp2/neJQKspy 1nOYeS48TmLrYMpI+Oa1LAwmF/ZTdoIZIw5pdG9gDJAHceKCIxvdVax+x1bJ14nxZeLNQxxUxHCx 7a5rSQiNsnmOY7yTrqD06oM7m7u1g5jyNm9JcEUj46IrxuiErGS0J5Jmue0kdo1/alrm8OHWgjZe 6KSSOBxu1O1ZbltzVPQQKDxJC2FjTXbI0vdCGasdI93ElBiS9yksmEpYh2VhkjpQSVoLMlJvbwB8 zpRPVkZIx0MwD9vSW8B5PhkbdiuVchi3cwCvkuGYk9IqSPiBkrTmBsLnudu0k4xtcBoOtQNbxfdR kocBdwF/LVZaN2Npls1qRhuPtxyNlitTTvmmMr2vYHEOHHxBBsmD5Tu07eWyOUvtv5XLxxQSTRw9 jFHDAxzY2Mj3SHzpHOcS7iSg07Idx77VFlP5Xjc1tCpRZNPUE0kLqY0D626QNiEx0MgAJ8BQZ1bk abKc+53JZCvNXxclIU2h+xrZ7s8Po9q5A1rnlrTWayMF3HpQW63c12eLsY+TIVg00GY6tNBSZFJt Ekb3SzO3uc97hC0ENLW9eiCS5j7tHZnmMZf0+OAiWtKyZtcemwejEEx17TXMc1ku3y2vDuk6IM3m TkvJ5DK2cliMsMXPkKHyZkN8AsB0LXPdHJFq9myRnbP0J1B14jggyuVuTK/Lty/LWndJBaho14Yn Dyo2UK/o7dXa+UXDj0BBpl7uNNrHii/LRviNH0EST1BM6AiWSXtaoMgbG5/a6PJBPAaEIJ6Du+yc Ni1E3NGPEZK16dk6McAbJLK+Jsc8TJi87YZXNDi3aT1a6IIC53Z8xT3sdhrmSdcwcWGv4qG6yBkb 67ZOxbCZfLPavLWacAB5PjQSV3upvZSS3cy2XitZGZ1CSBwqBtdjsd2m1r4TI7eyTtnbhuHiQZ+D 7ufky/jcg63CZqVm3aljrVm14nmzAIGsY1rnFoja3pcXEoMzIcu5rmDlGxic1Yjgu2LAeJomAtbD DcE0ILQdNxjjaHcelBkZTlH0/N3sp6T2fpuIfiOy2a7d8jpO11146b+hBrL+52D0+SZlyv2Fz0N1 7tqbJp99OKOE9hI922NsrIW6hzHacdEEzzjyC/mG1PYZkX0XzY848bGE/wD8THZ1cQ5pLXdlse3h q0nighsf3SWcfZlu08nXq3fTIMjT9HpNirwzRQOrPj7ISeVHJE8g+Vu146oMfl3kDmntpchNkhTy 1fI5YCxJXa+OxVyLo3GRkbZBs4xAs4nx6oPo7lWRV4IoMhA95oV8dcntU2WHEVtwbNAHPDY3ua8g hwc3o4KRuvLnLLcLPl3xzdozJ3BcazbtEQFeKuGDQ8eEGvV0qBo1fuTmhIIysJkFa9Sks+if5meO /GWOkszGQuklbw48G+JBO5ru0+UpYLDMi6vZqUadWnK2MO7OejYFiOYgu8oOLdrmeDrQZ3L3J+Rx 8+etZPJNv28/Ix8r4oBA2IR1xXa1jd0mujW9ZQRNPuunhw9zHz5MSutYKLl8Sth2BrIHTbJi3e7U 7Z9CNerxoLf0SxNzL7bLcBrWLcF6yJajJbHaQsja5kUznENjkMQPFhLeOhQTPN3IdbmPLYe/JZdX GOl1twNaHC3XD2TCvJqRo3toWP8AaI60EXF3UwxZ6W+yzAaU2RdlXMkqMktiV53mJtlzjpH2nlDy Nw6NUFNnumq28Dh8LavudXxlC9j5HsYGukF6MM7Qakhpj26gcdUGM7udjsUJ4bduqLWtR1SStRZF E19KTtWumYXvdL2jvPbvA06NDxQSOH7tvQLuPvOtQixUyEuQkjq1m14nB9R1RsTWhznaND925znE nxIKeeu7I81ZF1l92OOGWi+g6CxXFoQ73OcZ64c9rWSkO2lxaegIMU912Wkju1Js435MynoPyjXZ V0eRRijj0ikMh2dqIRu1B06kGVT7trMF+pG7Kl/L+OyUmXo40QhsrZ5HPe2N8+47oo3yuc0bQeol BhM7m6LMPlse2+97rtyG1j5JI2vZVhqSGWtV7PXSSJjnv11I1DkGycocpfIEd0vkgfPemEsgq121 oWNY0MYxrAXuOgGu5zifaQYlrkLt6efqm5oM5kockXdnr2fYiuOz6fK19F6fGgou934sz5CT00t9 PzFPMadnrsNNsQ7Lp47ux87q1QUYbu5+TY8GwXzJ8jUblEHs9vaemOa7f5x027OhBddyHM3lnlzD 174jn5bmqzwWnRbmyGqx0ZDo9zdA5rz0O4IMN/dhuwmLxfygQMZ8paS9l5/yjHNH0buHZ+ka+PRB 9j7sizDZXGjIf/pN2NcJey8z5NhrxdG7j2no2vi1QUO7tct8l3sFFnnxYCwzICvTbAO0DsiJNWzS 7vykcT5nOa3QE8NTwQYT+5mpHWZTo244cdVtQZDHY6WuJa0NtkLoLHkb26xWGvLiwEbX+UCg+3e6 D0nGxVDcpucHWnzMkx8fYNkslpEtZrHskhkiDA1ru0Oo87XggvfRRIczj77sr2poSVJG3JK7flIt qsa10JtscwuimLNXh7XdJCCZt8v5zmDka1hs5YZBk7zZWPswsBawds50B2btDpGGBw3dOqCyzkSy 6HI+kZAPsZLKU8tK9kW1rX0xXBja0udwea3h4aoMDlzuqgweWpzxWYH0sdNPPUjFRjbTjPv0bNYL nbmx9odu1rSeGp8IZeR5M5nHM+TzWFzNSmzKMrNnr2qJtEGsxzGlrxNFpru6NEGNJyHzhHncll8d zJBSnzNanBknegCRwkpxOj7WAumDY9xkLgHB2njQVw92j8T6A/lrINpS1KDcVaZch9LitQMe6Rrp Wb4j2gke924HjuI0QYUPdVladSH0HNxDJw5abM+lTUmuiL7Ff0d0fo7JI2hrR5uh4cEG3YXE5qOj Zq5+5WyXbktHo1X0Vgjc3a5jmGSbdr4dUGoct9zVXC38JdOSktS4o2HWN7APSnyFwrOk0PD0Zr9r UHxvdDOzGxY+PLAQ/JlfF2C6DVz/AES263HI07/J4yOaRxQbdFy0WZLPXTPr8txwx9nt/wALsYXR a66+Vru1Qab9EWRs4SDE5XOC23H4yTFYyVlURdm2Yxh8sg3u3v2QtaNNB09aC7a7opJ+ZPlg5KJz m5Q5Rrpau+y5rwWmq6wZNRExrzsDGjThrqguS91mTsctHlm1njNg4KzaVKp6M1o7Jk0cjTZ8v8q5 scXZjTaOJOmqCe5e5Lgw+NyeEE3b4G3JKaNBzNBVgsNPaVmnXyow5ziwaeSDog1zA9zUGKuYm27L TTz46vaink2Brp5pzJ2Nhx1Oj4GTPa1Bh0+5GWvXnhGVgBsYuXETyx09ksrZHseLE0hlc6SYuZ5R PA9QCkbTByH2UT4/Tdd+bZm9ez002Fp7Hp/oed9xQIWh3T3YI6dSbNCTHY6rkaVKBtYMkEeRaQXy Sb3bnx68NAAUEtkeR7V/lLFYKxcrzuxoibL6RUbNVsthjMYbLXc7UcNHAtfqHBBEU+6nJYysxuJz 7q1manLj78stft2GCSZ80fYMdJrEYO2c2PVzht6ddEF6Luhx8U0TI7jxj4nxaVtvlmKLGOxuztNe lzX792nSgzuWeRcxisxj7t7MtvwYrHOxVGBtcQu7JzoyJJXh79z9IWg6ADxIIrO9zNLK5DN3BkHw Oy9mtPEGsB9HbHwtxsOvEWg5wd4NUEhku7ezZt5CCDK+jcvZe3BeyWMEDXSOkgEYcyKfcNjJRXYH DYT06EaoMf6KnTRwYq7lDPyxTntWaONbC1kzX22Ss2vsbjubELMmzRoPRrrogzeXORc1jc/RyuRz TcjHjcY/E1IG1hAezdJE/tZHB79z9IADoAPEgwn919w2qlf5XH/T9TJz5WPGmuO1L7Ql7SJ0+/zA 6w9zfJ16kEfT7lIY8a/GzZCIQR0jRpz1qccVgHex7JppC5+9zeyaNG7Wu46oJm1yTzLatV8rPzCH ZyjY7alIKo9DjjdCYJIvRzJuPaB25zu011004IPmI7s3ULJtuysj7k9XIQ3LLWCN7rGSmbNJPHoS GbCzRrePsoISl3JPrxXIzk4GemYiXDSur0xG5we5r22ZHGR7pJd7dX7joerRBnT903a5aa5JdrOZ enrW8jvpMkmM0DI2SCCR73COOXsQdHNcW8dCg3PBNzYjtnMPidIblg0+yG3SpvPYB+hOrwzpKCUQ EBAQEBAQeAfrR/x15m/0P+310TDlahLv/wBSr+KeV/Udj87qKUS9pogQEHzQIBY0jQjUeBBF3OV+ X7gPb0YS48S9rAx2vh1bosdvHps/dGWmvdan7Zw1vK92GMswzMpWZajpWOZofyjPKBHQdCuC3xOr MTXpMOuPkL4xPVwrPfVs5+xwfLj318vENSGxOMUun9V/D3CvZizzZhz3M8pc14V7m5TEW6m3pfJC /Zw/pgFv3UU6tr7oJwbOTbwd+TYCPBxK8L539tP6vX+K72bfzg7dypkWaDVsXSPCHBeT8f8A9+v6 vS5n/at+jjLH69C+0h8vls/Jbv8AOy/1FI6Dyzy1f5kyzKVQFsI0dasaeTGzw+z4AomVsPQuGxFL E46HH02dnXgbtaOsnrcT1krJdEc8894bk3GR5HLdoIZpRBEIm7iXkEjXwDgo6pju0J/fJ8vRmLEX YqbiCSIwJpQ3w8ej3Fwb9+yvpiHoaOPrt65lquYxfMGRLpWZOO/M7/8AOJHa8fA08AuT8k26zLui sV6Vhq2R5Z5rj1M1aWUadMWjmcPE1aRavozt5eqCnrWq4ImgkiJ6QWOb99aRb6spr7saSBsrHNHA O0O1nkkkdZIVvOVPCFPoUzj5Ly3hoAADpr4k/ImNc+kqfR7MW13B4PDZrq4nwk9Q9hR5VT42iCKe 7E0PfC6OTXaSzXa32XH+RT4RPqjztDOocxW60bibErI4tTsk0JcdegB3lKJ0zPZb+RjukqvNeQle yIMbI+Ub2tDTuDfHt14rOdMwvXfE9m3YXD8x5H8pZqCjUPRPYdtJ9hhGqz6Q1i7MuZbkrlB7bd3I sN2IHboWg8eB2xjVxURS1/2wi+ysR90obBc2Uu9vMzclOMlSnbglnlyUccTJnGA6saG6ebo7jqV6 HH4lqz5XnMvL3bqz0q9IYLFVsRh6eLqgivRhZXi101LY2hup06zouvOXMz0BAQEBAQEBAQEBAQEB AQc77+f4a5A+CWuf/wAq1T6T+k/9CveP1hp0Ti6Nh/ot4+0F+YW6TMPt6z0SdXKSxAMkHbQ/iO4n 2tV18XnbNU4z9rC/Hi3WOkpOvFHIwyUZQ7XUvqu6P+xfScXla90dJxZ522tqz1hE5etamhcKg2zc d9eU6O4fiHrV71aUtDSI4clRvSyysJL9A9h8kt09lZ4mO7s6Jepk/SpDFCDLJ1MYC52vsAKseXsz tiO7YamJzVloElQtaR/iTHs3A/yreNNpc9t1I9WdByYJWgWZWB3W2AEjT+11ravG92c8v2hn0+T8 LTcXmPUni4zvJHtN6EvOvX+6YhhO+1kj2+Lrt2tcCB+DE3Qe6uHb81xtfafL9ERp2WY8mZjBIggG h/CfxP3F5e7/AMkt/ZWP6uinC95YsuRuSdL9oHQG8F5G/wCU37Ok26S6K8elfRqbZde+Llwu4uER YXdJ8przpqvqf/GPKdNpmc9XkfJ9LREO6DoX0rzxAQEBAQEGh95h/wA1ifYsfeYvn/8AyH/tR+r1 viZ++f0avRvPrSgs6D5w6iF8po3Tqt5Q93bpi0NhhfBYiMkPFhGkkXWPGvreHy68iOneHkbaTWer n3eBhOZHOEeMqS5KGXjG6IDc3Q66PW9tU5a03REJ7lvD8z+iwSWazaszWgESP1d7bQo/HLO+6rah jJHs0lftmdxDowdBp7KvbX9WP5ViXA1nt0sTPcD0+WGH7iwma17zH+LSNs+kKKmOwONMhrwsfJJx ke5xe7h7Kxvz+NTrnqnx2WVjOUw/s4poHHo7JhHaAjp1Gqjb8pWlPLGYVrp8pxlU/Oga7IePhcf5 l5mz/wAhn+2raODjvLGkzVk+aGt9gLi2fM8i3acN68OsMaTI2pBoZXcekdC478zdeetpa101j0Y7 pXkjVxOvhKxtMz3nLaKw3/lHjgoHfjOeT/fI/kX6J8TH/wDGp+j5Xl/92zD5+5Fw/OGBmxl9u2TX fUtNGskMo81zevT8YdYXoudwLFXsxy7mX8o8zt7G3W4VbDvMlj18lzXnzmnq9wr5X5b4vH+5T+sP oOBzox4z3bizXQanVfNPWyuAjU/1SoVWdSFq0xD5u16lVGH3UeBEG4FB818CCrq161VEy+Et9seB TELQcANTwUk4CD0/g+FDLGnv0IOM9iKIf03tCvTTe3aJUtesd5hE2+c+XK+v+a7Zw/BiBcf5l2av jN9/TDnvzddfVC3e87Gwsc6Gs9wHXM5sY+7qu/V8DsnvMOTZ8vSvaFnlTvCyGa5txFKpAx8Ni5A1 7oWvk2t3guLnAaDQL0+P8NXXaJz2cG35Gb1mPd61XuPNEBB+VqhZ7T+pV/CzK/ryx+aVFKJd/RAg ICDjfPuU5wh5jz0VS+11WCXl/wBAp6SMaySxdc07nNf0O2ntNG+UNB1IMzI94vNtCw7AvbBPmflV 2Pbka1SeaPsW0m3TJ6EyQyOf5ezQSafhKRXzDzJzFl+5nK5DUYzLtMlWaRrZY9RFaELnsZubLF2j OOhdq3XRQKrPOPNeLGXrxyUI6WFnqYamDDZmnmszxVzvaxr3vftD37Y9SXcNXDQlSLdHn7nfJHG4 ymKlfJW8pdxs1u5WljDYqlUWRKaol3Nk46bDJ7igYcPexzbQwbc3l69KzXt4u7eq1arJWOjmozxw APe5z97JTLuOjRt6OKkbRyNzRzPk7+UxWXjb6TUghsV7noc9FrjPvaY3QTue87HR8Hg6OCgatB3z Z+d8ddlGD0iatFSj13EfL3bMZNW018xsb9/h4KRhXc5zI903o130XG+ic1GxVYZnPe+pLtbL2jpD o4FwLOGjeOnSNA3HkDPcyuu1cJmn1rAkwtPJVp67JGOYJD2TopO0fJ2h8ndv4dfBQICTvY5kx3yl YytaGMMr3ZsdQdDLGJDWkDInQ3WukgssLHB02m1zPApF/Ocxc0xZKrgcxZrSW4sjgrkdzHNkha6G 1f7GSGRjnyHpZwOvlNPQoERBzfzXf5MyFTDPq0GY7C2chcfaM8ssvbTWo2MgkMgczY2AkvO7RxA0 0Qblcz+fio8oYXDSQR5LN1tzshdY+Zkcdas2SQ9m10ZkkeXDTyh1lBreV70ucoJbENatWlnw1KG1 kfRK892C1LK6T8nHYic1ldm2Hz37vKOn4JQVZ3mvmnLPr3opa1HA1+ZaeMNTSRl0iOZm975d4Zo8 n/D2eZx1Uiqn3q8wSW5XPjhsU7GPyd6jIytPDCHY8bouznld/mWPafKc1jQD0INhk5p5oxvIdHmT LehyTyS1LGRbXZIyKGjZewSbS9xJdEyTcXHhw6FA1eDvozjqNud9Cv6Rj4bl+eAlzQaTuy+THl3H b2wstc8/0XaKRJ3+e+c8VlXcs3HULOatSY9tHJRRSsqxtvvlY7toi9zi6M13bAHjfqOhQKqvO/Od 3OM5Vgfj481Bbtw2sm+OR9aSKpDDM3s4BI1zZH+ktDm9odu0nigmu6W5ctch4+xel7W5JJaMzt5k GotSDyXHUlo6G+JBrM8eal5zdLhMjfyuSp5GSXMWGvfFiq1JrSRjuyc4xyTbdvmDcHeU4joQQ2P5 gzGCwuB5oiyM+Rv53D5LI5SrbmfLXdPWrizG6OPXSERv/JeRpwOnSgmLfPneLj3ZOW07FzV8MzHX LTI4JmuliyL9pgYTK7aYgCRIQd34oUi9/wBad4VvMw1aT8ZDVv5fIYeqZYJpJIm0Q9wsPIlaHucI tuwaDr3KBdzPNPM+U7p6mcpWIsbl5bVeGzJE17mksvitII9HNcGvLddCT5OoQWcfzFzbjcjPJLJX mw9vmSxiuwe2Q2PygcRKyXftY1jm6Nj29HWpGPyzzpzdfxdePD/J1WtiMbRt5BuQfK4zm4Xns2Tv k/JNayM/lH7tXKBj43vHzNSTmmlXYGHCfLeT7W8HuNvsbMoZFUOoBjg0aJHdWoAHWgkMn3i854Or YjycdK3fs1sbYxxqwzBkT8jO+uWSR73vlEezcNpBd0cEFsd4fPJqOqNpF1yC+6vPfZj5zIa3o4mZ I3GOlbYLt7tj9HHQeV1qRTL3ocx60LrTTZhnVqktnIRwWbFSSWeUxztkmYRJSDNPI7WI6u4E8FA6 43oQfUBAQEBAQEBAQEBAQEBAQEBAQNEBAQEBAQEBA0CAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAg8A/Wj/jrzN/of8Ab66JhytQl3/6lX8U8r+o7H53UUol7TRAgICAgIGg QNAgofFG9hY9oe09LXAEH2iggrPJHKs00k5xkEViYBss0LBE9wHhLNNVju0V2Ri0Zaa9tqT9rU+Z u5mnkqFuvjr8tV1mMx6SgSsBPHX8Fy5KfG663i1emHTfnXtWaz6uL5z6u3eRi3OfUigysA6HVn7X /wDlybT7hXq+UPN8ZYPJvJfN3/UQxc2KtVrkw2jt4nsYBrxcXkbdB7KnMJiHqXlPlaly7iY6NYbp POsTng6R56SfF4As5nLROqByH6z8WvdxFJ/4d+Dj7LXhWp3Vt2cB7pZCObQG9L68o6OvVpXm/Nx/ sf1h2/F/93+ic727V2lnKElWaSAvg1PZuLQSHdei5/g4i2u0T16tvk72raMS1/H94fNlNzdt0ytb 0NkGvD2eC9S/FpPo46czZHSZy7JDbuSwtc94kDmNdtlYHDyhrw1XzM8vxtMY7PfjVmMtRt838nPu TVMhjmRywvMbpGs2gkHTUFq9avH2WrFo9XDbk64tMT3hdjq8iZDQU7roZD0Rh4cCT/ROhWd6bK94 a1vS3aX2fk1pINS5E4jgBIC0rONkS08GGeVs4JGxtiExeQ1hY4EEn2dNFbyhXxlO1O7ulXb2+euR wt859eIhzv7T3cB7iTfrjqjwRmZ71+7nlLfDhq7Ld4cHOiDZHkjh5Uh8ke0uimnZf6Q577tdPrP0 cs5p77ucM25zK83yfXPS2I6vI8bz/IuvXw6V79Zce3m2t26Q0V9meeR0k73Syv4ue8lzifZPFdcd Ozkmc93YvqsOP0r1f/8ADtD/AIWqbdiO72iOhZLiAgICAgICAgICAgICAgINc595VZzVyxcwjpjX 9JDSyYDdtew7mkjrGo4qYnBDhE97mPk+8zEc31Xdjrtq5aIExSNHRx/C++F8xz/gs/dq7+z3ON8p H7bNlr2YZ4WTV5GywvGrZGHUHXxhfL2pNZxMYl7NbeUZhkMkexwcxxa4dDugqKzMTmCcW7pivmIJ 2CLJR7hr5M4HEeMr2+N8xP7dvWPdxbeLMdaSzY8ZjrLGWpH1b9F/+BK9zSd3g3A8fYXvYiseUz9v 1ed+XPSOks9ktGoCIhHEOgthYG/dC4tnzGinacrRx7W7rUmXYOEcWv8ASedV5u7/AMht/ZX/ABb1 4fvLFnydx40a/Y38VvBePv8AlORsnrb/AAbV49I9GKXPJ1c4n2eK8+17W7zltERBqSNehUwkPhBV x8c4NbueQ1o01c4gD3SkdeyJmGoU7cFnvjwfYvbNG1zWslYdzNWwvLmhw6x1r9B/8c0zTi/dGJmX gfI3idkYegh0L3HEICAgICAg439Y61nsXiMRzFjIHz1sTYeciWanZDK1rdzmj8HUcT1Ln5XGrupN bNdO6ddswgeW+ZMbnscy7ScOIBljBBLT/MvgeZxLabeNn1Wjk12V6J+nckrTCVh0IPEHrCx0brar eUL31xaMSnhmw1oMcIDnDyjqvWn5++MRVwfwoz1lZfmrjgQ3Rg6tFybPlt1u04a14lIWX37b+Ekr j4tVxbeXtvPWZaxorHox3Oc48ST7awm0z3axWDVzSCCqzESTGWDSwuNp25rsUWlmc6ySHifaW+3k 7L0ikz0hl+KsTmGbroNTwXPLZ81CQBDjqdDp4Spg8mLPkKNdu6e1FG0dO57eC2rqvbtWVJ2xDo/J T45OWaEsbg+OWMvY8cQQ5xIK/ROBWa6aRPSfGHy3JmJ2TMJ5drBpveR3d43nPCGrN+QyNfWTH3gN XRyadB6yx34QVZiJ7rRaY7OI8v5rI4/Jycq8xsNfMUz2THP4CQDzdHHztw4tPWvkvlvivxzOyn7X u/Hc+LfZbu25nST4jr7i+fevaYWes8VYyAjVET1N4Gnh8CsYfQSR5vBVRPRi2crjauvb2Y4/CC8a +4OK218bZftEqTsrHeUVa555fr66TOmDeJ7Jpd99dev4jkW9MMdnN11Q2Q70K0MTnQ0w0fgmxIGN Pj4cV6Wv/wAdv/dLiv8AK1jshT3k5/JPEOMhfPI4aCKjWksv19lgcF36vgdNY6zMuTZ8ree0M+ty d30Z/b2WFvsa7iJbkjKcZ1/GY47vuLv1/H6adquW/M229Ww0Pq294VvY/I5bHY4Hz442y3Hj23dk 3VdcVrHasOeb2nvLbcZ9VvlhrWnM5rJZFw0IZE9lSPX2I2l//ErZV8W44fuR7rcU9skHL9eedvET 291l+o8JlLlCcNxqY3H02BlStFWYOhsMbYx7jQEGUgICD8rVCz2n9Sr+FmV/Xlj80qKUS7+iBAQE ENd5T5cvZE5K3QjmvObE107tdSK8naw66HQ7H+UEFN/k3lm+ZjboRyusTstyyeU15njYI2yh7SHN cGDbq0jggux8r4BmD+QWUIhiNu00gNIyN2/j1nV3EnwoKLvKXLl2K3FaoxysvTMtWtdQXzxBrY5d wILXtDG6FunQgs4vkblPFWI7FDGRV5opXTxvZu1EskZhfJxJ8p8Z2uPX1oLreUOWRBFX+TYDBBBN Viic3c0QWSHTR6HUFryOKCvCcrYDBCb5Kpsqmxs7d4LnPf2Y2sDnvLnaNHBo10CC23kzlZk7J24y ATMvOyrH7eIuvZsdOP6ZbwQUz8j8qT9n2uNid2TrLo/OGhva+k9B/wCbr5SDOrYTF1rUdqCsyOzF WbSjlGura8Z3NiH9EFBHV+QuT68888OJrtfYZNHKC0uZssHWZrWOJY0SfhbQNUHyhyFyjj4jHUxc MbTNBZJ8pzjLVIdXcXOJd+SI8ga6BBaud3HJF2vDVtYevLBXY+GOIhwHZSvMj43aEbmOeS7a7Uao M/J8q4DJ0q1K9SjmrUy01GHVpiLW7B2b2kPb5Pk8D0IMKz3eclWG1my4euWVYmV4Iw0taIY3bmRu a0gPa13HR2qCuzyHyfbyzcvYxUEmRZMyy2cg/wCPEAGSloO0vaABu01QWYu7bkaGbtosPAyTbKwO G7yWTtLZWNG7RrHBx1aOHiQTU+GxdjEvxE9ZkmNkh9GfVcNWGHbs2EeDbwQYcfKXLUb7LmY2AG5V jo2gWAiSrC0tjhcDqCxrSRogxYO77k2DG2cbHiYBTuOY6zGdzi90OnZEvcS/8np5Gh8nqQfX8gcn OxsOOdiofQ68r7ELBuDmzSAh8naAh+54d5RLuPWgrxXJmCxN6rYxkAqR06j6VapF5MLIpJRM7Rvh 3jh4EFiHu35JgygysOLZHkBObXbtfKD2znbi/bu26lx16EFyHkDk2F918WKgachHJDaADtHRzO3S sa0nRjXu4uDNNSgzLHKvL9hltk9GORt5kMVsO1/KMrHWFruP4HUg+xcs4GKeGeOlG2WCxNdheAdW 2LAImkHHznh51QUS8q8vS4N+BfRjOIeSXUuOzUydsSNDqD2h3a69KC5/0zguyZEaUZjjs+nMadTp Z4/lenzuKDAk7vuS5TUMmJru9CjZDWGh0EUTt7GOGuj2tdxAdrogvXOS+VrrBHaxsMrGvsyAEHzr wcLR1B1/LbzuHQUF67yry/ejljt0IpmTV46kgeNdYInF8bP7DnEtPSCgwvo95N9DbU+S4hCyZ1lr gXiUTPbsdJ2od2m5zfJPldHBAf3eckvfXccPXBrRxwxNa0tb2cLt0bXtaQ14Y7iNwOhQbIBogICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgIPAP1o/468zf6H/AG+uiYcrUJd/+pV/FPK/qOx+d1FKJe00QICAgICAgICAgIBGqCnZ x1J1RGFSJEHO+/jlrL8w93drH4is63fbNBNHXaQHOEb/ACtNdBwaVavdFuzzj3f4PmPBc6QDJ4yz Sd2UrS6aJzW+br52mi4fmYzx5x7ur4zpt/ozO+GUPvYyQN4mKQHTxOXF8BP2X/V0fLR1q0IEHpX0 Dx8vQeMeZMdVdrxfCz/uhfC74++36vrtc5rH6ON8yRgcxZEdBFh6+w4X/Zp+j5rlf9236rOF2NzF J3gnZr7q05MZ1W/SVNE/fX9XSudZn18DbmqzPjlY5hY9pII8oda+X+O67YiesPoubaY1zMNArc+c zUiHMtdqW8W9o0OOo8a+ktw9c+jw6c7bHq0TmTnzmbN2JflG7I6IOO2Bh2xjQ/ijp9tTr0Vp2hXZ yL37y1zXUdK1YYVNAIUpSWFweWzFxtPF05rtp58mGBjnu+50KYgenu4HuK5r5Wz8PM+ffFUe2CWO LHN/KS/lQBrI4eS3TwcVW1kxD0U3oVFn1AQEBAQEBAQEBAQEBAQEBBH5jCYvMY+WhlK0dunKNHxS t1HsjrB8YQcO5n7q+aOT7EuU5Se/I4Xi+fFyEukY3r2tHngeFvFcXM+P1ciPuj7vd18fm7NU9+jF wHNWNzMbWQu7G40flaknB2o6dp618bzfjNvHn7o+33fRcXmU2x0nqndw6PE7Ue0vOju6pc77vQH5 Dbx2NyI2M1cWgganhrovvvlMRwrTjr4w+P497TviPrLsz/OPg8C/NvR9JC3pxISZWNnWOlZTKMsO 7l8XRGtu3FD4GucNx9ho1K31cXbsnFKzKl9ta90Hc7wsNGdtSKW5IXbBoDG0npB4+UR7AXtaP/Gu TfvisOO/yOuOyiCXvKzjiMVijTgLtGzOYGDTwmSbT7gXu8b/AMY0U67LTb/o49nyN/7YS9PuXz2Q e6XmDMkB48qGIumcPYL9GD+6vZ08LRqj7KxDi2br3nrLdOXO67lXBWoLsMT7F+uD2Nqd25zCRoS1 o0aCR16Lqyyw3AKEiAgICAgILFqrBahkgnY2WGVpZLE8BzHNdwLXNPSCg8v94Xdzle6rNnmjloPn 5PsSaXqQ1JpF56NB0wnqP4K4+bw676TWe/o342+dVvKG14TPY7N0WXKL9zHAb2a6lhI10K+D5XGt ptNbQ+s0bY2ViYbBHr2bevgFyEqtRokRkfdBw6yUQP2sBLyGgdJcQB91RFZt2hWbwjbXMeAr69re j3t6WMO93uNXRr4W+/aks7cikd5RFzvG5crsJYZJdOnQBg/4l6FPgOTPWcQ5b/Ia6+rBZ3g5W/oM PgbFwO4NfHFLL91jdv3V3U/8Znvazmn5WJ7QkK+G76Ms93Y4tuOgPmvnkjh6f6Plv+4vQ0/+P6a/ uzLC3yV/SEjW7l+fr+12W5ihra+eyBskx/4jG37i9CnxnHr2pDmtzNtvVL0fq78sscH5HJ377tdX De2Bp8WkY1+6uylK0/bGGE3tPeXTMVi6eKx9fH0mdnUqxthgj1J2saNANTxKsqzEHxw1GiDQO9Xu xrc4YsS1NtfmCmC6hb003aceykcOO09R6iomImMT2kjpOYcf5b5skimmwvMH+RytLWKXtvJ1c3gQ 7+l99fIfIfD3rby1xmJfQcLmVtGLdMMm1zng4nODJXzPaNSyNp46eAlc+r4ndb0w6rc3XHqjLfeJ HC0OZV2Md0SzPDQP6zV6Ov8A8dt/dLh3fK1r+2MoUc+57IzPixrHTSg6NZRgksag9e5ocAu3X8Fp r+7q5L/LbJ7JSryR3v58NMWJuthPEvvTMpt9wku/4V6GvgaKR0q5r8zbbvKcxn1b+ebUhkyeVoY1 pHRCyS3KPbeY2LprWK9oYWta3eW3Yv6sfLEQ/wDquYyORLh5bGuZVjJ/qxDX7qvN5U8W4YjuX7r8 TtNbl2pJK3/nWWmxIf7UxeVXMrNuqUKdOLsqkEdePqZExrG+40BBkAICAgICAgICD8rVCz2n9Sr+ FmV/Xlj80qKUS7+iBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQeAfrR/wAdeZv9D/t9dEw5WoS7/wDUq/inlf1HY/O6ilEvaaIEBAQEBAQEBAQEBAQEBAIB6UFt 8bHjRzQ5vgIBH3UmMkNb5j7tuSuYmgZbFQ2HtBDJBrG9uvgcwtKrSIr2jGU3tNu8ue5n6sHKVgud i71rHuOu1jiJ4x7TtHfdW0XZ+CRZ3W8wUKkMFazBbFdoY13lROIA04g7gvnuR8Xa1pms93tavkKx ERMOM8793XPNPOXrcuGsOrSyF7ZYB2zdCBx8jU/cXt8Sk111rPeHk8m3lsmY7S1Kl2kGUqtmjdE9 szAWSNLDruHU4Ba7v2W/SVNX74/V0rnTaeXL7NBroHAf2gvl/jY/3qvoOb11S5JIPJI8RX1b5qGh 2WO9Jl/ru++qS0T3KHd/zbzbbFbAY2a67odK0bYW/wBaV2jAkIh3/kP6osbTHa5yyG/jqcbRJ09h 856f7ITyj0WiHoDlrkzljlmkKeBx0OPg0G7smjc7Tre86ud7ZVZlMQnNAoSICAgICAgICAgICAgI CAgICAg+ObqOHA9RQc25/wC5rDcxPdkMa4YrOAh4sxAiOVw/8VrdOP8ASbxS0RavjMZhNbTWcx0c wfluYuV7wxHONR0b9pEORjG5jxoeO4DR4+74l81zvgM/fp/wezxvlv7dn+KE7vJoo7pllkEUIyBc 6R50bt2ag8V6vysWniWpEfd4w83TePzxPpmXTLnOWCrl22V9hwOm2NvDU8fOdoF8Xx/geVtj9vjH vL1787XT1YEXMvMOVAjwOGklcWkiRwdINddBqQGsHur1tP8A4r//ALL/AODmt8nntDPb3dd5OX1G Rvx0IHBp2h/EadPkRAf95e1o+G4urrFfKfq5NnN2W+ibxHcXy5XPaZKzNkJN2/b/AITNfBwJeR/a Xp0iK/tjH6OWbWnvLdsTyny5iQPk/HwV3D8MMBf/AHnau+6pQl9AgaICAgICAgICAgILFurWtVpa 9iJs0EzHMmieA5rmuGha4HpBCDzNzv3e5Xury7+YeXw+1yZYePSqnFzqZcfNd0kw/iu/B6CuDncG u+uP7m+jk21T9EtF3j4+xWhdQqy2JJWgtjGrjqeoBgcV89r/APG9s95iIerf5akfVm1rXeFkRpjc DOwO6Hvj7MD+1MWru1f+OUj99v8ABhs+Vmf2wzB3f97eQ0bYmrUmnpcZ+gexC0/fXdq+F41PSZc9 vkNk/Rnw9w121tdl+YXyH8JsEOh/vSOf95d9OPpr+2sOa+69u8p2j3GciwAG0yzkH8NXWJ3tbw/o xdmPdW8WmIxDLDZsZyHybjCHUsNTheP+Z2TXO/vOBKqlOtY1rQGgNA6AOAQVaBA0QEBAQEHwgFBz vvI7nsXzlNWvRzjHZWu4B9xsfaCWIfgyN1buLfwSpicJzKHx31cOV4/KymUv5DXzo2vbWjPh4RDf p/aTKuG14nug7tcW4Pqcv1TK3oknabDuH9KYvKTOTDa61StViEVeJkMQ82ONoY0e00BQle2hB90C AgICAgICAgICAgIPytULPaf1Kv4WZX9eWPzSopRLv6IEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBB4B+tH/AB15m/0P+310TDlahLv/ANSr+KeV/Udj87qKUS9p ogQEBAQEBAQEBAQEBAQEBAQEBAQUuYD0hBG5HlzC5ID0+jBZ2nVplja4gjo4nig13mHum5TzVWWC SJ9XtW7XPrvLfuHULnrxddbRaI6w2tyLzXxmXMcx9Vl+jjiM90+bFbi1/wCOM/yLs83L+NnckfVT 5Sxkou8zTnOWyd3ooBjqtOv4oO5/tlVmy0Q7VjMTj8XUjp4+tFUqRDSOCFgYwD2AqrMxAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQRmd5fxOdxz8dlarLVSTpjeOg+FpHFpHUQg53jO4TGUrNsOycslCeXt IoRGwStbppsMh119nRTmURDccb3d8o49zXx4+OaZuh7WxrM7Udfl6ge0EzJENjjjZGwNY1rGjoa0 aAe0FCVaAgICAgICAgICAgICAgILNmtBZgfBYjbLDK0slieA5rmuGha4HgQUFqji8bQjEVGrDVjA ADIY2sGg6PNAQZaAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPytULPaf1Kv4WZX9eWPzSo pRLv6IEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBB4B+tH/H Xmb/AEP+310TDlahLv8A9Sr+KeV/Udj87qKUS9pogQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBB+VqhZ7T+pV/CzK/ryx+aVFKJd/RAgICAgICAgICAgICAgICAgICAgIC AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC AgICAgICAgICAgICAgICAgICAgICAgICAgIPAP1o/wCOvM3+h/2+uiYcrUJd/wDqVfxTyv6jsfnd RSiXtNECAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPytULPaf1Kv4W ZX9eWPzSopRLv6IEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BB4B+tH/AB15m/0P+310TDlahLdO7nLZXEYvnbIYq5Pj78GDi7G5VlfDMzfmsax22SMtcNWuLToe gqUMX6WO9P1yznzlb98UJPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XL OfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P 1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+lj vT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QP pY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/f ED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOV v3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yzn zlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9c s585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70 /XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6W O9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA +ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb9 8QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585 W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLO fOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1 yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljv T9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPp Y70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fE D6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv 3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznz lb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QaqgmsJzvzpgar6eDz+SxVSSQ zPr0rc9eN0hAaXlkT2tLi1oGviCCQ+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA +ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb9 8QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585 W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLO fOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1 yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljv T9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPp Y70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fE D6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv 3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznz lb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs 585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/ XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO 9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98 QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W /fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOf OVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1y znzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT 9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY 70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED 6WO9P1yznzlb98QPpY70/XLOfOVv3xA+ljvT9cs585W/fED6WO9P1yznzlb98QPpY70/XLOfOVv3 xBr+Uy2Vy9+XIZW5PkL8+3trlqV80z9jQxu6SQucdGtDRqegIMVB1T6vnIv/AF3mOaOVPTfk75Rw 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 77fsv9LQyfYZ/fb9l/paGT7DP77fsv8AS0Mn2Gf32/Zf6Whk+wz++37L/S0Mn2Gf32/Zf6Whk+wz ++37L/S0Mn2Gf32/Zf6Whk+wz++37L/S0Mn2Gf32/Zf6Whk+wz++37L/AEtDJ9hn99v2X+loZPsM /vt+y/0tDJ9hn99v2X+loZPsM/vt+y/0tDJ9hn99v2X+loZPsM/vt+y/0tDJ9hn99v2X+loZPsM/ vt+y/wBLQyfYZ/fb9l/paGT7DP77fsv9LQyfYZ/fb9l/paGXAO9HkX/oTnvJ8qem/KPyd2H+c7Ls N/b145/8PfLt29rt849GqhLVUHf/AKlX8U8r+o7H53UUol7TRAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICD8rVCz2n9Sr+FmV/Xlj80qKUS7+iBAQEBAQEBAQEBAQEBAQ EBAQEBA0CBoEDQIGgQNEDRA0CAgaBA0CBoEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAJAGp4BBgXs7haEZlu369aMcC+WRjB7pKjIwq3O/J1pzG1s1SmdJwYI52O3exoU8oTiU pFkKMshjisRvkHTG17S7j4tdVKGQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDwD9a P+OvM3+h/wBvromHK1CXf/qVfxTyv6jsfndRSiXtNECAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgIPytULPaf1Kv4WZX9eWPzSopRLv6IEBAQEBAQEBBYmu14jtc7V/4jeJ QYz8lKf8OMNHhef5Agtm5bP/ADAPYb/Og+el2/8AxfdaEFQyFtvSGPHttP8AKgvsycR/xWmPx9I9 0IMpr2PaHNIc09BHEIKkBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBRJNFGNXuDfBqgtelbv8ONzvGfJ H3UFXaWT0MYPZcT94IG62PwGH+0R/Ig+dvIPPhcPG3RyCtk8Tzo13lfingfcKC4gICAgICAgICAg ICAgICAgICAgICDGyGSo46nLdv2I6tSBpfNPM4MY1o6y48EHDOYfrX8tRZ+visBVfcpOlEdrMS6x xNBOm6GM+U8a9Z0Ct4qzZulrI2r0bJX2XSse0ObodG6HiNAFy2mW0QiM1g6mYxVjHWGtcyw0hriA S1481w9gpCXAMfBawebsYicdlLFIXVz0bXtOpA9npCXr0ymlvR0jmqkeauU4OYqW5mbw7dlwxEte 6EdJ1aQSWHyh4tVXvC0dJ6vndf3m8x1MlDj7uSlsU5/ycYsHtQx/4PF3laHo6VFdkwvfXEx0dXw3 ezi5eYZuW85GcVlmaOrued1exG7zXsf+CfC1y6PyQ5/CfRv4cCAQdQeIIV1H1AQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEHgH60f8AHXmb/Q/7fXRMOVqEu/8A1Kv4p5X9R2PzuopRL2miBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEH5WqFntP6lX8LMr+vLH5pUUo l39ECAgICAgIKJZY4mF8h2tHWgjZrk02oBMcfgHBx9k9XtILLQGjQAAIPqAgICAgMc+N26J2x3Xp 0H2Qgz6t1sh2SDZL1Dqd/VP8iDLQEBAQEBAQEBAQEBAQEBAQEBAQEFuWaKGN0sr2xxsBc97iA0Ad ZJQQuK5nx2erSWcPZbNSjlfA6w3rfHwcG69XjQZbdjTqOLj0vPEn2ygr7Q+FB9EvjQViZw6CgrFk oDnxSDSRgKCkPkj8wmRvWx3ne07r9tBfimZK3c069RHQQfAQguICAgICAgICAgICAgICAgICAgxM lkq9CuZpTqehjB0uPgCDivfZjchzZytO3e4zVD6RXrMJDCW9Rb+Fw8KitsSi0dHkqwzY89WmvD+R bM4ejO4rnY5vAuxFuTdfxgDQXdL4Twafa6Fz7q+rXXPo6a8bCQerRZRLVzXvh5X7erHzBTbtsREN sOaOjTzH/wAhV8qTGEZ3bc2eiXYpJADXtHsLkTugO6Dqsv2y17xli898tHl3P9pUBGNt/l6Mg/BG urma+FjvuKl6+rbXbMJTmaCTmbkyvzLUP/1/A+TbA858PSTw8Hne6rV6xiWdo8Z6Oh91PeS/IYaJ 0j+1bFoyxETq5vVub/KFal5rOJRspE9Ydcr2IrELZonB8bxq1wXS511AQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQeAfrR/x15m/0P8At9dEw5WoS7/9Sr+KeV/Udj87qKUS9pogQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBB+VqhZ7T+pV/CzK/ryx+aVFKJd/RAgICA gIKJpWRRmR50aEETJK+eTtJOrzGdTR/Og+ICAg+aoBKBqg+aoG5BSdDwPteJBIUbhf8AkZT+UHmu /GA/lQZyAgICAgICAgICAgICAgICAgIKZZGRsL3nRo6Sg8+d5fexcy0+S5ahoSV4Y5xC1278q8Rk 7w5vQNztNPEoRllfV+ys1e1lsBaBje9rLsDHDTj5j9B7GhUyirsyLCAgalB9Dig+7yg+iRALnB3a RnbIPccPA5Bm17DZmajg4cHtPSCguoCAgICAgICAgICAgICAgILNqzFWryWJTtjiaXPPiCDSMhdd kXNtl2sUjdYW9QaegKkzlLBdGHMLSNQeDvYQeW+9zk48v8yzdm3bTv62KpA4Ak+Wz2ittc5hjMYl rnIfNM3K/NNPKsJ7Brgy0zqdE7g73OlTMZ6ETh7Crz171OK3XcJIZmh8bh0FrhqFxTExOHVE5Wp6 sNqtLTnaHQytLXtPgKkcCy+Km5Z5inpzf+nldoH9Wh/w3j7xVrRmEVnEum4ljOc+Tp8JYIOVp/lK bz072jyT7Dx5LlSIzGF/LE5adyXmPkbOGreG2rY1rXYn/gnXb5Q8R4FYx3b2jMJ/l/kazyrzFeyQ ykNXA790Ub+Lnsdx2nXQDToW1oziWNbY6Ny5W748GzmKDCxtlko2n9mbhH5OOQ8GnTp2k8CVelvR S9PV2UHVbMhAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBB4B+tH/HXmb/Q/wC310TDlahLv/1K v4p5X9R2PzuopRL2miBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEH5 WqFntP6lX8LMr+vLH5pUUol39ECAgICAgibdjtptBxijOjfG7oJ/kCC2gp1QEFSCgnig+ElBRLPB Cxz5ZGsawbnFxA0HhUTJhhzZ3Hx9oGF074w1zmQtLztd0OGnDRR5Qt4o6/zfXqB75ewrwx6SdpZn YzfCfw42glxOvABR5SnENYu95TWte6jbdftQlzWw1a7jE7eNWue9+gAj4alR1OjauVstnMnTZLfp sqPjA1kEm5zpANQ4NA26EePxK0TKLRDdKlgTwh54OHkvb4HBWVX0BAQEBAQEBAQEBAQEBAQEBBF2 J+2l1B/JMOkY8J63fzIOP80U8RgO96jmsnGz5JycThM941YyUt7Nz3D2wSognu1WhzVWq96VfL1p CMc6f0djXEEMqyHsg0AdDW+cAkInu9D7tCR4+lSs+6goh9QEBAQEBAbI6KQSt46cHjwt/wCzqQSb XNc0OadQRqD4kFSAgICAgICAgICAgICAgIOc89c9Ua3M9LlcP/LOi9Kt6dTXHbG32ToSststddfV Yxrwx8tP8Afla/8AUcfKH9l331WkotC/INp1A0WijRO+DlI8w8qSugZrfoa2K/hIA8pnthWrbEq2 jMPKFkBp109rxraWT0P9XPnf07FS8s3H62KPl1CTxdC7pb/ZKy2Vz1a67ejrs8Ox+vV1FY+LXLTO 9DlRmWwpuws3WqbSTp0ui/CHtdKt2VlzrkzmK3jbcNprj6RTcGzN/wDEiPh9kKloxK1esYbd3m4C K06tzRiWb6+SLWWWM46TkeS7h+P0HxrO9fVtrt6IGjypnMs5nyvakkjiaA2AO1DGjoBcfJCRCZmE /A3BYOB/YtjdKBsDG+UddOlx6/dVsq93Yu6/m9nMWAO8/wCcoP7CceEaasd7bVvScwwtGJbmrKiA gICAgICAgICAgICAgICAgICAgICAgICAgIPAP1o/468zf6H/AG+uiYcrUJd/+pV/FPK/qOx+d1FK Je00QICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg/K1Qs9p/Uq/hZlf 15Y/NKilEu/ogQEBAQY16YxQOLfPd5LPZPX7SCMA0Gg6AgqQUoMPL2X18fLJHI2KXzYnP027z5re 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 UtLbbwNlIz3dAimZNG2SNwfG8ase06tIPQQQulxLiAgICAgICAgxb1+CnA6aU+SBwA6SfAFS+yKx mV6Um04hqE+Ygyln/NWGRRMPkVS7T23a9JXlbeR5z17PVpx51x9sZn3TNaxV2BkLmlo/FIOq1pau OjkvS2esSuiTiTp1q+YlSaqt48fFMowt2GsljMYeWOPQ9vSFHRMZhD3MBNYkbIZmTPj1MZmYHbT4 R52iiato249ErXhMcYY9+7To4BoHDoACRDKbdV8RNBBBKtFUZfXRM4nUg+EJ4mWC+5M2RxjaBFHq XO46uI4BvHwkrC2yYtiGv44x+qJ5qzEGD5du5GwA91eMuAPQ6Zw8gcf6RTxz36rUiZnoku7HtTyD hJJnF80tcSyuPSXSuL3H3XL1Kx0hw7etpbUrqCAgICAgICAgICAgICAgICAgICAgICBogICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPytULPaf1Kv4WZX9eWPzSopRLv6IEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBB4B+tH/HXmb/AEP+310T DlahLv8A9Sr+KeV/Udj87qKUS9pogQEBAQEDUIGqChz2tBc47WjiSeA90oYQ2Q505Vx523MrWheO lnaBzuHibqVS2ysd5aV1WntDW73fTyVXLWwSzXHP1MZijLWHTwOftCwtzKR65dNPj9tvogL3fw53 DH4nTQne6xJ5TW/jFjB0e2ue/wAhHpDpp8XPrLWMj3w8+WHbYpoKTXHVhhjDtwPQwOdv0efGqfzb W7dFv4NK92r3uZObsjK83cnasbXflIe0c1zD+L2bSA5o6yAsbcm0+rppxqRPSIYT6pOm5okZMSWE +Y934TmuOhGngKw85me7piIx2YZwdmNws1Y3mLiZG7T5IB/D4ae2FrHJrP22ljOiY61fJ6onLddQ esf/AG6VPnMJ/H5d2y8p8+c1cp7YaU3pmMadX0ZidoHXtPSw+wurVysS5N/B6Zjq7hyb3n8sczhs ME3ouTI1fjpyBJw6dnU8ewu+t4s8i+uatzBV1BAQEBAQD0IOBfWA5r5r5b5pxcmJyD61azUcex0a 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 kIs4C9jvR5qOgeN44ObH52rfOBQV1+/HEyUMnddjpezqVRkMfFHIySS3UdOK+8Nb/hu3keS7joUH QcLduXcXXtXKbsfZmbukpyODnRk/gkt4a6IM9BiZPF4/KUpqGQrstU7Dds0EoDmuHsFInBMOTZTu +n5O9Ou4qI3MNI0yS1ms3SsDGODWEAeUC5+mvg11XR+TyxDGKeOZceoNAqRscdGN3N48eAPk6jxL rcZo8yjXRw29Q1Gg8SJW2RnV41GzXXQjyf8AsUYQoL9ehurm666EADwJKVddr3atboQ7TTwgeyhK 65hY8aEODeOvSNenq6ldDMhexjSdwPDUHzQHeyVKrduSu7nLZ98diZrqeJHE2HjR8g6xE09P9YrL ZvivbrLammbfo7nh8PQxFGOjQiENePoA6Setzj1krz7WmZzLtisRGIZ6hIgICAgICAgICAgICAgI CAgICAgICAgICAg8A/Wj/jrzN/of9vromHK1CXf/AKlX8U8r+o7H53UUol7TRAgICAgICAgICAgI CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICD45uqDFixlCKZ88deJk 8h3SStY0PcT1lwGqjEGWUB41I+oCAgICAgICAgICAgICAgICAgICAgpLdeGvBBDZXkzlTLAjI4mp Z16XPibu/vDQqPGFovMerTcp9Xvu6tlz6tebHPd11pXBv9124LO2msta8m8erUcn9W7KxanD58SN 6WQ3Iv8A2mk/eWNuLDeObb1apk+57vQx+5wxkOQib+HUlbqf7B2uWU8WXRTm1lMd0vI+WyPNTZ81 j56lbE6TPistID5eiNrdekA8U08aYtmeyOTy4mmI9Xo1nmr0HlPqAgICAgICAgICAgICAg/K1Qs9 p/Uq/hZlf15Y/NKilEu/ogQEBAQEBAQEBAQEBAQEBAQEFuevDYjMczA9h6ig55mu6x/pD7WJsF29 xe+tOdTqePkyfzrmvo9YWizW6vKeUs5yOpk6r69CtpNY3jRspB8iNp6HDUauVNeuY7otOejoYDQ3 aOgDpWyFmTso2OmkOjGjUqJTCCv3CA8yu0a8ayvJ8xoHALKbZadmlS258rffJGx0jfMrxtBcQ0eI dZWPeVu0JnG92vMWVma+wwY+oPw5eMhHijH8ui0rx7T36J/JEOj8t8l4TAt31ou0tkaPty6GQ+If ijxBdVNVa9mVrzLYFooICAgICAgICAgIKJImSN2vAcPGgtdnYj/w3CRv4j+n2nD+VB99JDeEjHMP hI1HuhBWLMB6JG+6g+9tD+O33QgoNqAdD9x8DeP3kFJlmf8A4cZA/Gk4D3BxQfRWBIdK7tCOgHg0 ew1BfQUuaHNLTxBGhHsoOXy92XNp5XucqMylQ4SCRs2GDo5BI5rbHb+j29p0dFp5B28SEF3Hd0+R gxvo81+u2Z78rI5teExwsOUhETWRs6mxae2gs3e6vmd4lo1cxXZhslUx9HMRPicZezoxhj3wOB0D pQNPK6Agkc33b5G3hL9KrchMljMNy8UNhrzXfG3b/lpw0hzmaM6kGJjO67M4+tg4mX60hpTZH5Ta InRskrZMkvbAG/4bo/wepBI93Xd/b5W7SGyzHSQxQirUtVIDFalia4kGy8nQnbpwbw14oIrH91/M 8FqhWnzFd+Cwsl44uBsThO5l6J7GiZxO3WHtTpt6Qg1XnHB5Ll7HP5exuWbLbvYyhj7mOFWV808k DuzjkrPaNjQ9pIk3HyRxQb3e5AzBkkuULkEd35YrZeFkzHOjDYoWwSQu28eLddHBBDVu57LsymRn myFUwWY8nFDYbE70uU5JugdYkJ49j0NDeGiDcZOUpnv5VcLLR/07/i+T/i/5bsPJ8HHig0a/ycYs 7yXy3HO6xao2LV3KSRxuETseZTOI5HHhxnEe0a9RQYbqeRh58xuDx+Sbfx0fMMuTfRFaVs9cOje6 btpiBH2bHv8AII4u10QbU7u+5hx+MwD8Hkq7M1gfSWB9mNzq88NtxL2PDfKaW+SQR4EHyj3XWatG SD5REks+JtY+eZzNN1m5MZ5JtB0N3O0DUGPnu6e1kY7T2XIH2HRYv0SOxGXw9rjA4ETNHEslD9Dp xCDI+j3L68vTRvx9STHOuR5OrVifHXfWvN2SdgPOEjQBo53Sgj8P3R5KlgbuFfJjYmGOGCnkKtdz LL44JxKDZcToSWtA0bw14oOpt6EH1AQNEGmcy91XK+ce+wIjQvP4us1gG7j/AE2ea5aU2zVnbVEu Z5nuT5spbjQkiyMA1MYYeyeB0cWu4e4V0V5ET3YTon0afd5R5ooBzbWKtsAGmpicRw4DzdQtIvX3 UnXMIs0MjuaPQ59QQx/kPBPDq4Kcwr4ykKXK/Md2Qx1MVblJPSIX7ePUXOACedY9UxS0+jbcL3L8 53SHWWx4yE6D8s4PcB4mM1+6VnPIrC8aLOlctdz/AC1iHNnuA5S20hwfOAImuHW2IcPd1WF99pb0 1RDemta0ANGgHAAdACxaqkBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQeAfrR/x15m/0P8At9dE w5WoS7/9Sr+KeV/Udj87qKUS9pogQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBB+VqhZ7T+pV/CzK/ryx+aVFKJd/RAgICAgICAgICAgICAgICAgICAgpcxrho4Bw8B4oMa TGUX9MQB/o6j7yjECxNgcdKAJGuLQddNx01CiaRKYlYPKXL7g4SVGyh/niQucD7IJUfjr7HlKQqY 7H0mBlStFXaOGkbGt+8FaIiEMlSCAgICAgICAgcUBAQEBAQEFJjjPS0H2QEHzsofxG+4EFQa0dAA 9hB9QEBAQEBAQEBAQEDQa69aAgICAgaBAQEBAQEBAQEBAQEDRB82t8AQfUBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEHgH60f8deZv9D/ALfXRMOVqEu//Uq/inlf1HY/O6ilEvaaIEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQflaoWe0/qVfwsyv68sfmlRSiXf0 QICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDwD9aP+OvM3+h /wBvromHK1CXb/qi8w4DA95OSuZzJ1MVUkw08LLF2eOvG6Q2qzgwPlc1pcWtJ08RUol65+ljus9c sH85VPfEQfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHd Z65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfS x3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+I H0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqn viB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/n Kp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65Y P5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3We uWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd 1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9 LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74 gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yq e+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+ cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrl g/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ 65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx 3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH 0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnv iB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nK p74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP 5yqe+IH0sd1nrlg/nKp74gfSx3WeuWD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74gfSx3Weu WD+cqnviB9LHdZ65YP5yqe+IH0sd1nrlg/nKp74g/NdQs9c/VF535LwPdtkqecz+NxVuTMzzMr3b cFeR0Zq1mh4ZK9ri0uaRr4ipRLt/0sd1nrlg/nKp74iD6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98 QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85V PfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/ OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1y wfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus 9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY 7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED 6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3 xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzl U98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH 85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPX LB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6 z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+l jus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98Q PpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VP fED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/O VT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1yw fzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9 csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7 rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6 WO6z1ywfzlU98QPpY7rPXLB/OVT3xA+ljus9csH85VPfED6WO6z1ywfzlU98QPpY7rPXLB/OVT3x B4h+sdlsVl++fmHIYq5BkKE/ofY3KsrJoX7KMDHbZIy5p0c0tOh6QiXNVCRAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBA QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEH/2Q== --b1_2d89beb3af4ba377ae7a13851abee0b2-- From wagi@monom.org Thu Jun 2 00:23:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 896887CA7 for ; Thu, 2 Jun 2016 00:23:30 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0E2EEAC001 for ; Wed, 1 Jun 2016 22:23:29 -0700 (PDT) X-ASG-Debug-ID: 1464845005-04cbb03568b02dd0001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id opuXSBUBPokupGw6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 22:23:26 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id 81D6219414C0; Thu, 2 Jun 2016 07:23:24 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 53BBF194030D; Thu, 2 Jun 2016 07:23:24 +0200 (CEST) Subject: Re: Internal error xfs_trans_cancel To: Dave Chinner X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <20160601071047.GJ12670@dastard> <0644b434-6cea-4188-9702-469c26d191b8@monom.org> <20160602002653.GL12670@dastard> Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com From: Daniel Wagner X-Enigmail-Draft-Status: N1110 Message-ID: Date: Thu, 2 Jun 2016 07:23:24 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <20160602002653.GL12670@dastard> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1464845006 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1444 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30102 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header > posix03 and posix04 just emit error messages: > > posix04 -n 40 -l 100 > posix04: invalid option -- 'l' > posix04: Usage: posix04 [-i iterations] [-n nr_children] [-s] > ..... I screwed that this up. I have patched my version of lockperf to make all test using the same options names. Though forgot to send those patches. Will do now. In this case you can use use '-i' instead of '-l'. > So I changed them to run "-i $l" instead, and that has a somewhat > undesired effect: > > static void > kill_children() > { > siginfo_t infop; > > signal(SIGINT, SIG_IGN); >>>>>> kill(0, SIGINT); > while (waitid(P_ALL, 0, &infop, WEXITED) != -1); > } > > Yeah, it sends a SIGINT to everything with a process group id. It > kills the parent shell: Ah that rings a bell. I tuned the parameters so that I did not run into this problem. I'll do patch for this one. It's pretty annoying. > $ ./run-lockperf-tests.sh /mnt/scratch/ > pid 9597's current affinity list: 0-15 > pid 9597's new affinity list: 0,4,8,12 > sh: 1: cannot create /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor: Directory nonexistent > posix01 -n 8 -l 100 > posix02 -n 8 -l 100 > posix03 -n 8 -i 100 > > $ > > So, I've just removed those tests from your script. I'll see if I > have any luck with reproducing the problem now. I was able to reproduce it again with the same steps. From darrick.wong@oracle.com Thu Jun 2 00:42:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 26DB77CAE for ; Thu, 2 Jun 2016 00:42:07 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id ED5B58F8039 for ; Wed, 1 Jun 2016 22:42:03 -0700 (PDT) X-ASG-Debug-ID: 1464846120-04cbb03568b03470001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 6t64fbettUzq4cmr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 01 Jun 2016 22:42:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u525fus9006255 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Thu, 2 Jun 2016 05:41:57 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u525ftOn015780 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 2 Jun 2016 05:41:56 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u525fqd8000895; Thu, 2 Jun 2016 05:41:54 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 01 Jun 2016 22:41:52 -0700 Date: Wed, 1 Jun 2016 22:41:51 -0700 From: "Darrick J. Wong" To: xfs@oss.sgi.com, cmaiolino@redhat.com, Dave Chinner Subject: Re: XFS_IOC_FSEMAP (old XFS_IOC_FIEMAPFS) Message-ID: <20160602054151.GE5053@birch.djwong.org> X-ASG-Orig-Subj: Re: XFS_IOC_FSEMAP (old XFS_IOC_FIEMAPFS) References: <20160601123650.GC7967@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160601123650.GC7967@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1464846121 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1994 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30102 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Wed, Jun 01, 2016 at 02:36:50PM +0200, Carlos Maiolino wrote: > Howdy folks, > > I've talked to Dave about moving forward XFS_IOC_FIEMAPFS ioctl, and > consequently their users, such as xfs_spaceman tool. > > For now, I'm porting the old stuff to the current code, doing code cleanups, > etc. > > If someone wants to take a look, I've made the patches available here: > > https://github.com/cmaiolino/linux/tree/fsemap > > For now, I just did the port forward of the patches, but still need to clean up > a few stuff, and also port forward xfs_spaceman. > > As per Dave suggestion (as you can see in $SUBJ), the ioctl has been renamed to > XFS_IOC_FSEMAP. I was planning to push the GETFSMAPX ioctl that we talked about at LSF as part of the reverse mapping patchset: https://lwn.net/Articles/685978/ Patches here: https://github.com/djwong/linux/commit/fa063533cffa4627f423ba952422796da9364cfc https://github.com/djwong/xfsprogs/commit/21502ebb972f03319940fe8bb1a1e6fcb181ed3f https://github.com/djwong/xfsprogs/commit/8347e762e3b94dc14f40754a4db952acdadfb080 https://github.com/djwong/man-pages/commit/822729ce87cb389f5d980d88187d86745e41ecd5 GETFSMAPX reports device id and owner id, which (AFAICT) FSEMAP doesn't. I think the btrfs folks are interested in using the (possibly obsolete) mappings for duperemove enhancements, and from the brief look I took at spaceman, it could use this interface for its reporting. xfs_scrub could (possibly) use it to figure out which parts of the disk to scrub. I think it'd be pretty simple to bring spaceman up to date with current xfsprogs and teach it to use GETFSMAPX. I also think there could be a (stupider) GETFSMAPX implementation for non-rmapbt filesystems that only reports free space extents that are in the bnobt. --D > > -- > Carlos > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From david@fromorbit.com Thu Jun 2 01:35:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8D9E67CA7 for ; Thu, 2 Jun 2016 01:35:48 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4FF948F8049 for ; Wed, 1 Jun 2016 23:35:45 -0700 (PDT) X-ASG-Debug-ID: 1464849341-04cb6c2dbbae6340001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id p8G17fzPcg8Zw681 for ; Wed, 01 Jun 2016 23:35:42 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AsIXALLST1d5LbJkLWdsb2JhbABegzpWfYJ2g3mefAwBAQEBAQEGjCWDWYY1HoVtAgIBAQKBM00BAQEBAQEHAQEBAQFAAUCERgEBBDocIxAIAw4KCSUPBSUDBxoTiC7BNAEBCAIBJB6FQYUVihoFmDeGAIgWjyZFjweCaByBXSoyinwBAQE Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail06.adl2.internode.on.net with ESMTP; 02 Jun 2016 16:05:41 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8MEF-0001Bt-7t; Thu, 02 Jun 2016 16:35:39 +1000 Date: Thu, 2 Jun 2016 16:35:39 +1000 From: Dave Chinner To: Daniel Wagner Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com Subject: Re: Internal error xfs_trans_cancel Message-ID: <20160602063539.GM12670@dastard> X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <20160601071047.GJ12670@dastard> <0644b434-6cea-4188-9702-469c26d191b8@monom.org> <20160602002653.GL12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1464849341 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1964 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30103 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 02, 2016 at 07:23:24AM +0200, Daniel Wagner wrote: > > posix03 and posix04 just emit error messages: > > > > posix04 -n 40 -l 100 > > posix04: invalid option -- 'l' > > posix04: Usage: posix04 [-i iterations] [-n nr_children] [-s] > > ..... > > I screwed that this up. I have patched my version of lockperf to make > all test using the same options names. Though forgot to send those > patches. Will do now. > > In this case you can use use '-i' instead of '-l'. > > > So I changed them to run "-i $l" instead, and that has a somewhat > > undesired effect: > > > > static void > > kill_children() > > { > > siginfo_t infop; > > > > signal(SIGINT, SIG_IGN); > >>>>>> kill(0, SIGINT); > > while (waitid(P_ALL, 0, &infop, WEXITED) != -1); > > } > > > > Yeah, it sends a SIGINT to everything with a process group id. It > > kills the parent shell: > > Ah that rings a bell. I tuned the parameters so that I did not run into > this problem. I'll do patch for this one. It's pretty annoying. > > > $ ./run-lockperf-tests.sh /mnt/scratch/ > > pid 9597's current affinity list: 0-15 > > pid 9597's new affinity list: 0,4,8,12 > > sh: 1: cannot create /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor: Directory nonexistent > > posix01 -n 8 -l 100 > > posix02 -n 8 -l 100 > > posix03 -n 8 -i 100 > > > > $ > > > > So, I've just removed those tests from your script. I'll see if I > > have any luck with reproducing the problem now. > > I was able to reproduce it again with the same steps. Hmmm, Ok. I've been running the lockperf test and kernel builds all day on a filesystem that is identical in shape and size to yours (i.e. xfs_info output is the same) but I haven't reproduced it yet. Is it possible to get a metadump image of your filesystem to see if I can reproduce it on that? Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 2 02:04:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 123557CAE for ; Thu, 2 Jun 2016 02:04:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id C9FA430404E for ; Thu, 2 Jun 2016 00:04:49 -0700 (PDT) X-ASG-Debug-ID: 1464851082-04cbb0356ab05460001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id 1G1v9oVPERuMHKPe for ; Thu, 02 Jun 2016 00:04:43 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: ApAWALzZT1d5LbJkLWdsb2JhbABUCoM6Vn2CdqMBAQEBAQEBBowlg1mGNSSFIxA0BAICgTNNAQEBAQEBBwEBAQEBQAFAhEUBAQEDATocIwULCAMYCSUPBSUDBxoTiCcHD8ElAQEBBwIBHwUehUGFFYQYhgIFmDeGAIgWjyZFjweCaByBXSoyBYp3AQEB Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail06.adl2.internode.on.net with ESMTP; 02 Jun 2016 16:34:24 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8Mg3-0001Hg-JW; Thu, 02 Jun 2016 17:04:23 +1000 Date: Thu, 2 Jun 2016 17:04:23 +1000 From: Dave Chinner To: "Darrick J. Wong" Cc: xfs@oss.sgi.com, cmaiolino@redhat.com Subject: Re: XFS_IOC_FSEMAP (old XFS_IOC_FIEMAPFS) Message-ID: <20160602070423.GN12670@dastard> X-ASG-Orig-Subj: Re: XFS_IOC_FSEMAP (old XFS_IOC_FIEMAPFS) References: <20160601123650.GC7967@redhat.com> <20160602054151.GE5053@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160602054151.GE5053@birch.djwong.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1464851082 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3229 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30104 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 01, 2016 at 10:41:51PM -0700, Darrick J. Wong wrote: > On Wed, Jun 01, 2016 at 02:36:50PM +0200, Carlos Maiolino wrote: > > Howdy folks, > > > > I've talked to Dave about moving forward XFS_IOC_FIEMAPFS ioctl, and > > consequently their users, such as xfs_spaceman tool. > > > > For now, I'm porting the old stuff to the current code, doing code cleanups, > > etc. > > > > If someone wants to take a look, I've made the patches available here: > > > > https://github.com/cmaiolino/linux/tree/fsemap > > > > For now, I just did the port forward of the patches, but still need to clean up > > a few stuff, and also port forward xfs_spaceman. > > > > As per Dave suggestion (as you can see in $SUBJ), the ioctl has been renamed to > > XFS_IOC_FSEMAP. > > I was planning to push the GETFSMAPX ioctl that we talked about at LSF > as part of the reverse mapping patchset: > > https://lwn.net/Articles/685978/ > > Patches here: > > https://github.com/djwong/linux/commit/fa063533cffa4627f423ba952422796da9364cfc > https://github.com/djwong/xfsprogs/commit/21502ebb972f03319940fe8bb1a1e6fcb181ed3f > https://github.com/djwong/xfsprogs/commit/8347e762e3b94dc14f40754a4db952acdadfb080 > https://github.com/djwong/man-pages/commit/822729ce87cb389f5d980d88187d86745e41ecd5 > > GETFSMAPX reports device id and owner id, which (AFAICT) FSEMAP > doesn't. I think the btrfs folks are interested in using the > (possibly obsolete) mappings for duperemove enhancements, and from the > brief look I took at spaceman, it could use this interface for its > reporting. xfs_scrub could (possibly) use it to figure out which > parts of the disk to scrub. GETFSMAP is a bit different to FSEMAP. fsemap is for iterating things like free space extents for generating histograms or determining if free space is fragmented in a quick, concise manner. I can see how you could do this with GETFSMAP, but it seems a lot less efficient to get this infomration from the rmap tree rather than directly from the free space trees. Indeed, I see that FSEMAP is similar to XFS_IOC_FSINUMBERS in that it returns a specific set of information that could then be used to quickly target ranges of the filesystem with GETFSMAP. e.g. freespace defragmentation requires us to first identify an area of fragmented space to address, GETFSMAP() on the used space in that range then tells us the owners of the objects we need to move to defragment that free space... Hence I see them as complementary rather than competing interfaces, and it not being a problem to introduce two separate interfaces to extract all this info... > I think it'd be pretty simple to bring spaceman up to date with > current xfsprogs and teach it to use GETFSMAPX. Should be no harder than adding ti to xfs_io - spaceman is structured almost identically to xfs_io. > I also think there > could be a (stupider) GETFSMAPX implementation for non-rmapbt > filesystems that only reports free space extents that are in the > bnobt. Which is what FSEMAP already does. No need to implement GETFSMAPX twice for different filesystem formats... :P Cheers, Dave. -- Dave Chinner david@fromorbit.com From s.priebe@profihost.ag Thu Jun 2 07:13:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EB3F97CA1 for ; Thu, 2 Jun 2016 07:13:14 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8004DAC003 for ; Thu, 2 Jun 2016 05:13:11 -0700 (PDT) X-ASG-Debug-ID: 1464869587-04bdf05ad5b07750001-NocioJ Received: from mail-ph.de-nserver.de (mail-ph.de-nserver.de [85.158.179.214]) by cuda.sgi.com with ESMTP id 7Ee5BKXtZeQkFZHu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 05:13:08 -0700 (PDT) X-Barracuda-Envelope-From: s.priebe@profihost.ag X-Barracuda-Effective-Source-IP: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Apparent-Source-IP: 85.158.179.214 Received: (qmail 18996 invoked from network); 2 Jun 2016 14:13:06 +0200 X-Fcrdns: No Received: from phoffice.de-nserver.de (HELO [10.11.11.93]) (185.39.223.5) (smtp-auth username hostmaster@profihost.com, mechanism plain) by mail-ph.de-nserver.de (qpsmtpd/0.92) with (ECDHE-RSA-AES256-SHA encrypted) ESMTPSA; Thu, 02 Jun 2016 14:13:06 +0200 Subject: Re: shrink_active_list/try_to_release_page bug? (was Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage) To: Dave Chinner X-ASG-Orig-Subj: Re: shrink_active_list/try_to_release_page bug? (was Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage) References: <20160516010602.GA24980@bfoster.bfoster> <57420A47.2000700@profihost.ag> <20160522213850.GE26977@dastard> <574BEA84.3010206@profihost.ag> <20160530223657.GP26977@dastard> <20160531010724.GA9616@bbox> <20160531025509.GA12670@dastard> <20160531035904.GA17371@bbox> <20160531060712.GC12670@dastard> <574D2B1E.2040002@profihost.ag> <20160531073119.GD12670@dastard> Cc: Minchan Kim , Brian Foster , "xfs@oss.sgi.com" , linux-mm@kvack.org, linux-kernel@vger.kernel.org From: Stefan Priebe - Profihost AG Message-ID: <575022D2.7030502@profihost.ag> Date: Thu, 2 Jun 2016 14:13:06 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <20160531073119.GD12670@dastard> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-User-Auth: Auth by hostmaster@profihost.com through 185.39.223.5 X-Barracuda-Connect: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Start-Time: 1464869588 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 932 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30109 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Am 31.05.2016 um 09:31 schrieb Dave Chinner: > On Tue, May 31, 2016 at 08:11:42AM +0200, Stefan Priebe - Profihost AG wrote: >>> I'm half tempted at this point to mostly ignore this mm/ behavour >>> because we are moving down the path of removing buffer heads from >>> XFS. That will require us to do different things in ->releasepage >>> and so just skipping dirty pages in the XFS code is the best thing >>> to do.... >> >> does this change anything i should test? Or is 4.6 still the way to go? > > Doesn't matter now - the warning will still be there on 4.6. I think > you can simply ignore it as the XFS code appears to be handling the > dirty page that is being passed to it correctly. We'll work out what > needs to be done to get rid of the warning for this case, wether it > be a mm/ change or an XFS change. Any idea what i could do with 4.4.X? Can i safely remove the WARN_ONCE statement? Stefan From holger@applied-asynchrony.com Thu Jun 2 07:44:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1EFC07CA2 for ; Thu, 2 Jun 2016 07:44:41 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 96C74304059 for ; Thu, 2 Jun 2016 05:44:35 -0700 (PDT) X-ASG-Debug-ID: 1464871471-04cbb0356bb11540001-NocioJ Received: from mail02.iobjects.de (mail02.iobjects.de [188.40.134.68]) by cuda.sgi.com with ESMTP id uvVU4lTU4ZRDEHyH (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 05:44:32 -0700 (PDT) X-Barracuda-Envelope-From: holger@applied-asynchrony.com X-Barracuda-Effective-Source-IP: mail02.iobjects.de[188.40.134.68] X-Barracuda-Apparent-Source-IP: 188.40.134.68 Received: from tux.wizards.de (p4FF5801B.dip0.t-ipconnect.de [79.245.128.27]) by mail02.iobjects.de (Postfix) with ESMTPSA id 5BB3C416017A; Thu, 2 Jun 2016 14:44:31 +0200 (CEST) Received: from [192.168.100.223] (ragnarok [192.168.100.223]) by tux.wizards.de (Postfix) with ESMTP id CE94D11C01CF; Thu, 2 Jun 2016 14:44:30 +0200 (CEST) Subject: Re: shrink_active_list/try_to_release_page bug? (was Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage) To: Stefan Priebe - Profihost AG , Dave Chinner X-ASG-Orig-Subj: Re: shrink_active_list/try_to_release_page bug? (was Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage) References: <20160516010602.GA24980@bfoster.bfoster> <57420A47.2000700@profihost.ag> <20160522213850.GE26977@dastard> <574BEA84.3010206@profihost.ag> <20160530223657.GP26977@dastard> <20160531010724.GA9616@bbox> <20160531025509.GA12670@dastard> <20160531035904.GA17371@bbox> <20160531060712.GC12670@dastard> <574D2B1E.2040002@profihost.ag> <20160531073119.GD12670@dastard> <575022D2.7030502@profihost.ag> Cc: linux-mm@kvack.org, Minchan Kim , Brian Foster , linux-kernel@vger.kernel.org, "xfs@oss.sgi.com" From: =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= Organization: Applied Asynchrony, Inc. Message-ID: <57502A2E.60702@applied-asynchrony.com> Date: Thu, 2 Jun 2016 14:44:30 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <575022D2.7030502@profihost.ag> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail02.iobjects.de[188.40.134.68] X-Barracuda-Start-Time: 1464871472 X-Barracuda-Encrypted: DHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1542 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30109 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/02/16 14:13, Stefan Priebe - Profihost AG wrote: > > Am 31.05.2016 um 09:31 schrieb Dave Chinner: >> On Tue, May 31, 2016 at 08:11:42AM +0200, Stefan Priebe - Profihost AG wrote: >>>> I'm half tempted at this point to mostly ignore this mm/ behavour >>>> because we are moving down the path of removing buffer heads from >>>> XFS. That will require us to do different things in ->releasepage >>>> and so just skipping dirty pages in the XFS code is the best thing >>>> to do.... >>> >>> does this change anything i should test? Or is 4.6 still the way to go? >> >> Doesn't matter now - the warning will still be there on 4.6. I think >> you can simply ignore it as the XFS code appears to be handling the >> dirty page that is being passed to it correctly. We'll work out what >> needs to be done to get rid of the warning for this case, wether it >> be a mm/ change or an XFS change. > > Any idea what i could do with 4.4.X? Can i safely remove the WARN_ONCE > statement? By definition it won't break anything since it's just a heads-up message, so yes, it should be "safe". However if my understanding of the situation is correct, mainline commit f0281a00fe "mm: workingset: only do workingset activations on reads" (+ friends) in 4.7 should effectively prevent this from happenning. Can someone confirm or deny this? -h PS: Stefan: I backported that commit (and friends) to my 4.4.x patch queue, so if you want to try that for today's 4.4.12 the warning should be gone. No guarantees though :) From s.priebe@profihost.ag Thu Jun 2 08:23:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1FBD97CA6 for ; Thu, 2 Jun 2016 08:23:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id E6BB8304066 for ; Thu, 2 Jun 2016 06:23:38 -0700 (PDT) X-ASG-Debug-ID: 1464873812-04cb6c2dbbaefe50001-NocioJ Received: from mail-ph.de-nserver.de (mail-ph.de-nserver.de [85.158.179.214]) by cuda.sgi.com with ESMTP id yugvCOP0DGLA1JGp (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 06:23:33 -0700 (PDT) X-Barracuda-Envelope-From: s.priebe@profihost.ag X-Barracuda-Effective-Source-IP: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Apparent-Source-IP: 85.158.179.214 Received: (qmail 21998 invoked from network); 2 Jun 2016 15:23:31 +0200 X-Fcrdns: No Received: from phoffice.de-nserver.de (HELO [10.11.11.93]) (185.39.223.5) (smtp-auth username hostmaster@profihost.com, mechanism plain) by mail-ph.de-nserver.de (qpsmtpd/0.92) with (ECDHE-RSA-AES256-SHA encrypted) ESMTPSA; Thu, 02 Jun 2016 15:23:31 +0200 To: "xfs-masters@oss.sgi.com" Cc: "xfs@oss.sgi.com" , Dave Chinner , holger@applied-asynchrony.com From: Stefan Priebe - Profihost AG Subject: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 Message-ID: <57503353.2050402@profihost.ag> X-ASG-Orig-Subj: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 Date: Thu, 2 Jun 2016 15:23:31 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-User-Auth: Auth by hostmaster@profihost.com through 185.39.223.5 X-Barracuda-Connect: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Start-Time: 1464873813 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2380 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30110 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Hi, another issue i'm having with 4.4.11 is the following trace after a reboot: [ 541.661121] XFS (dm-0): _xfs_buf_ioapply: no ops on block 0x188e78/0x8 [ 541.662423] ffff88013a3b3000: 44 51 01 01 00 00 00 00 00 00 00 00 00 00 00 00 DQ.............. [ 541.663258] ffff88013a3b3010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ [ 541.664156] ffff88013a3b3020: 00 00 00 00 00 00 00 00 00 00 00 00 00 0b db fd ................ [ 541.664930] ffff88013a3b3030: 00 00 00 00 00 01 9e 82 00 00 00 00 00 00 00 00 ................ [ 541.665704] CPU: 0 PID: 489 Comm: xfsaild/dm-0 Not tainted 4.4.11 #1 [ 541.666486] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 [ 541.667276] 0000000000000000 ffff880037a57c70 ffffffffbe3b3c33 0000000000000001 [ 541.668094] ffff880139d16900 ffff880037a57d18 ffffffffbe31c681 0000000000000000 [ 541.668896] ffff880139d16980 0000000000000000 0000000000000000 0000000000000000 [ 541.669705] Call Trace: [ 541.670491] [] dump_stack+0x63/0x90 [ 541.671286] [] _xfs_buf_ioapply+0x3e1/0x440 [ 541.672113] [] ? wake_up_q+0x70/0x70 [ 541.672901] [] ? __xfs_buf_delwri_submit+0x179/0x270 [ 541.673704] [] xfs_buf_submit+0x64/0x1c0 [ 541.674506] [] __xfs_buf_delwri_submit+0x179/0x270 [ 541.675321] [] ? xfs_buf_delwri_submit_nowait+0x20/0x30 [ 541.676129] [] xfs_buf_delwri_submit_nowait+0x20/0x30 [ 541.676930] [] xfsaild+0x2a6/0x710 [ 541.677738] [] ? xfs_trans_ail_cursor_first+0x90/0x90 [ 541.678557] [] ? xfs_trans_ail_cursor_first+0x90/0x90 [ 541.679357] [] kthread+0xdb/0x100 [ 541.680136] [] ? kthread_park+0x60/0x60 [ 541.680912] [] ret_from_fork+0x3f/0x70 [ 541.681708] [] ? kthread_park+0x60/0x60 I found a bug report from redhat here https://bugzilla.redhat.com/show_bug.cgi?id=1234586 pointing to this commit: xfs: handle dquot buffer readahead in log recovery correctly which isn't part of 4.4. Is it missing from linux-stable? i'm using XFS V5 with root quotas on in this case. Greets, Stefan From wagi@monom.org Thu Jun 2 08:29:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 455937CA3 for ; Thu, 2 Jun 2016 08:29:38 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id A5A89AC001 for ; Thu, 2 Jun 2016 06:29:34 -0700 (PDT) X-ASG-Debug-ID: 1464874170-04bdf05ad7b09830001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id 3qSXBs4Z9c2jXGuG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 06:29:31 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id AF5A21940307; Thu, 2 Jun 2016 15:29:29 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 76EC019400BD; Thu, 2 Jun 2016 15:29:29 +0200 (CEST) Subject: Re: Internal error xfs_trans_cancel To: Dave Chinner X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <20160601071047.GJ12670@dastard> <0644b434-6cea-4188-9702-469c26d191b8@monom.org> <20160602002653.GL12670@dastard> <20160602063539.GM12670@dastard> Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com From: Daniel Wagner Message-ID: Date: Thu, 2 Jun 2016 15:29:29 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <20160602063539.GM12670@dastard> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1464874171 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 454 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30110 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header > Hmmm, Ok. I've been running the lockperf test and kernel builds all > day on a filesystem that is identical in shape and size to yours > (i.e. xfs_info output is the same) but I haven't reproduced it yet. I don't know if that is important: I run the lockperf test and after they have finished I do a kernel build. > Is it possible to get a metadump image of your filesystem to see if > I can reproduce it on that? Sure, see private mail. From holger@applied-asynchrony.com Thu Jun 2 09:05:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A32B37CA2 for ; Thu, 2 Jun 2016 09:05:47 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 583B7304059 for ; Thu, 2 Jun 2016 07:05:44 -0700 (PDT) X-ASG-Debug-ID: 1464876340-04bdf05ad4b0a7b0001-NocioJ Received: from mail02.iobjects.de (mail02.iobjects.de [188.40.134.68]) by cuda.sgi.com with ESMTP id l4p5oSzfMiZN8sqO (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 07:05:41 -0700 (PDT) X-Barracuda-Envelope-From: holger@applied-asynchrony.com X-Barracuda-Effective-Source-IP: mail02.iobjects.de[188.40.134.68] X-Barracuda-Apparent-Source-IP: 188.40.134.68 Received: from tux.wizards.de (p4FF5801B.dip0.t-ipconnect.de [79.245.128.27]) by mail02.iobjects.de (Postfix) with ESMTPSA id EDFAE416014D; Thu, 2 Jun 2016 16:05:39 +0200 (CEST) Received: from [192.168.100.223] (ragnarok [192.168.100.223]) by tux.wizards.de (Postfix) with ESMTP id 7DEB011C01CF; Thu, 2 Jun 2016 16:05:39 +0200 (CEST) Subject: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 To: Stefan Priebe - Profihost AG X-ASG-Orig-Subj: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 References: <57503353.2050402@profihost.ag> Cc: "xfs@oss.sgi.com" , Dave Chinner From: =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= Organization: Applied Asynchrony, Inc. Message-ID: <57503D33.6010000@applied-asynchrony.com> Date: Thu, 2 Jun 2016 16:05:39 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <57503353.2050402@profihost.ag> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail02.iobjects.de[188.40.134.68] X-Barracuda-Start-Time: 1464876341 X-Barracuda-Encrypted: DHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2586 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30111 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/02/16 15:23, Stefan Priebe - Profihost AG wrote: > Hi, > > another issue i'm having with 4.4.11 is the following trace after a reboot: > [ 541.661121] XFS (dm-0): _xfs_buf_ioapply: no ops on block 0x188e78/0x8 > [ 541.662423] ffff88013a3b3000: 44 51 01 01 00 00 00 00 00 00 00 00 00 > 00 00 00 DQ.............. > [ 541.663258] ffff88013a3b3010: 00 00 00 00 00 00 00 00 00 00 00 00 00 > 00 00 00 ................ > [ 541.664156] ffff88013a3b3020: 00 00 00 00 00 00 00 00 00 00 00 00 00 > 0b db fd ................ > [ 541.664930] ffff88013a3b3030: 00 00 00 00 00 01 9e 82 00 00 00 00 00 > 00 00 00 ................ > [ 541.665704] CPU: 0 PID: 489 Comm: xfsaild/dm-0 Not tainted 4.4.11 #1 > [ 541.666486] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014 > [ 541.667276] 0000000000000000 ffff880037a57c70 ffffffffbe3b3c33 > 0000000000000001 > [ 541.668094] ffff880139d16900 ffff880037a57d18 ffffffffbe31c681 > 0000000000000000 > [ 541.668896] ffff880139d16980 0000000000000000 0000000000000000 > 0000000000000000 > [ 541.669705] Call Trace: > [ 541.670491] [] dump_stack+0x63/0x90 > [ 541.671286] [] _xfs_buf_ioapply+0x3e1/0x440 > [ 541.672113] [] ? wake_up_q+0x70/0x70 > [ 541.672901] [] ? __xfs_buf_delwri_submit+0x179/0x270 > [ 541.673704] [] xfs_buf_submit+0x64/0x1c0 > [ 541.674506] [] __xfs_buf_delwri_submit+0x179/0x270 > [ 541.675321] [] ? > xfs_buf_delwri_submit_nowait+0x20/0x30 > [ 541.676129] [] xfs_buf_delwri_submit_nowait+0x20/0x30 > [ 541.676930] [] xfsaild+0x2a6/0x710 > [ 541.677738] [] ? xfs_trans_ail_cursor_first+0x90/0x90 > [ 541.678557] [] ? xfs_trans_ail_cursor_first+0x90/0x90 > [ 541.679357] [] kthread+0xdb/0x100 > [ 541.680136] [] ? kthread_park+0x60/0x60 > [ 541.680912] [] ret_from_fork+0x3f/0x70 > [ 541.681708] [] ? kthread_park+0x60/0x60 > > I found a bug report from redhat here > https://bugzilla.redhat.com/show_bug.cgi?id=1234586 pointing to this commit: > xfs: handle dquot buffer readahead in log recovery correctly > > which isn't part of 4.4. Is it missing from linux-stable? Yes, mainline 7d6a13f02356 is missing from 4.4-stable because it applies, but doesn't compile. :) I'll look into a fix. -h From BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org Thu Jun 2 09:19:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3AA427CA3 for ; Thu, 2 Jun 2016 09:19:19 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0C32B304067 for ; Thu, 2 Jun 2016 07:19:19 -0700 (PDT) X-ASG-Debug-ID: 1464877155-04cb6c2dbcaf13d0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id 2UPRWUQXzVrL1K2C (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 02 Jun 2016 07:19:16 -0700 (PDT) X-Barracuda-Envelope-From: BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b8TSs-0001SQ-Rd; Thu, 02 Jun 2016 14:19:15 +0000 From: Christoph Hellwig To: darrick.wong@oracle.com Cc: xfs@oss.sgi.com Subject: [RFC] allow enabling reflinks at runtime Date: Thu, 2 Jun 2016 16:19:07 +0200 X-ASG-Orig-Subj: [RFC] allow enabling reflinks at runtime Message-Id: <1464877150-20457-1-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464877155 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 276 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30111 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 I've had some vocal user requests to allow enabling reflinks at run time, which happens to be a mostly trivial feature. The only caveat is that we need a large enough log size to support the reflink requirements, but for typical large file systems that's not an issue. From BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org Thu Jun 2 09:19:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1C4027CAE for ; Thu, 2 Jun 2016 09:19:24 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id CC0B5304067 for ; Thu, 2 Jun 2016 07:19:23 -0700 (PDT) X-ASG-Debug-ID: 1464877161-04cb6c2db9af13d0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id hKwiPmDWn1ptymqp (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 02 Jun 2016 07:19:21 -0700 (PDT) X-Barracuda-Envelope-From: BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b8TSy-0001Wb-QZ; Thu, 02 Jun 2016 14:19:21 +0000 From: Christoph Hellwig To: darrick.wong@oracle.com Cc: xfs@oss.sgi.com Subject: [PATCH 2/3] xfs: refactor xfs_refcountbt_alloc_block Date: Thu, 2 Jun 2016 16:19:09 +0200 X-ASG-Orig-Subj: [PATCH 2/3] xfs: refactor xfs_refcountbt_alloc_block Message-Id: <1464877150-20457-3-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464877150-20457-1-git-send-email-hch@lst.de> References: <1464877150-20457-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464877161 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2684 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30111 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Split out a low level helper that we can use for enabling the reflink btree at mount time. Signed-off-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_refcount_btree.c | 54 +++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c index f83cb4b..7ae3ad7 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.c +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -66,49 +66,61 @@ xfs_refcountbt_set_root( } STATIC int -xfs_refcountbt_alloc_block( - struct xfs_btree_cur *cur, - union xfs_btree_ptr *start, - union xfs_btree_ptr *new, +__xfs_refcountbt_alloc_block( + struct xfs_trans *tp, + xfs_agnumber_t agno, + enum xfs_ag_resv_type resv, + __be32 *agbno, int *stat) { + struct xfs_mount *mp = tp->t_mountp; struct xfs_alloc_arg args; /* block allocation args */ int error; /* error return value */ - XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); - memset(&args, 0, sizeof(args)); - args.tp = cur->bc_tp; - args.mp = cur->bc_mp; + args.tp = tp; + args.mp = mp; args.type = XFS_ALLOCTYPE_NEAR_BNO; - args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, - xfs_refc_block(args.mp)); + args.fsbno = XFS_AGB_TO_FSB(mp, agno, xfs_refc_block(mp)); args.firstblock = args.fsbno; xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); args.minlen = args.maxlen = args.prod = 1; - args.resv = XFS_AG_RESV_METADATA; + args.resv = resv; error = xfs_alloc_vextent(&args); if (error) - goto out_error; - trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, - args.agbno, 1); + return error; + trace_xfs_refcountbt_alloc_block(mp, agno, args.agbno, 1); if (args.fsbno == NULLFSBLOCK) { - XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); *stat = 0; return 0; } - ASSERT(args.agno == cur->bc_private.a.agno); + ASSERT(args.agno == agno); ASSERT(args.len == 1); - new->s = cpu_to_be32(args.agbno); - - XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *agbno = cpu_to_be32(args.agbno); *stat = 1; return 0; +} + +STATIC int +xfs_refcountbt_alloc_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *start, + union xfs_btree_ptr *new, + int *stat) +{ + int error; + + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); + + error = __xfs_refcountbt_alloc_block(cur->bc_tp, cur->bc_private.a.agno, + XFS_AG_RESV_METADATA, &new->s, stat); + if (error) + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); + else + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); -out_error: - XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); return error; } -- 2.1.4 From BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org Thu Jun 2 09:19:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B83257CA3 for ; Thu, 2 Jun 2016 09:19:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 221DDAC003 for ; Thu, 2 Jun 2016 07:19:22 -0700 (PDT) X-ASG-Debug-ID: 1464877158-04cbb0356ab13f40001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id BcJd0bJA4FKEqD5b (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 02 Jun 2016 07:19:19 -0700 (PDT) X-Barracuda-Envelope-From: BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b8TSv-0001Uy-HJ; Thu, 02 Jun 2016 14:19:18 +0000 From: Christoph Hellwig To: darrick.wong@oracle.com Cc: xfs@oss.sgi.com Subject: [PATCH 1/3] xfs: add xfs_mp_hasreflink Date: Thu, 2 Jun 2016 16:19:08 +0200 X-ASG-Orig-Subj: [PATCH 1/3] xfs: add xfs_mp_hasreflink Message-Id: <1464877150-20457-2-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464877150-20457-1-git-send-email-hch@lst.de> References: <1464877150-20457-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464877158 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12749 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30111 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Add a per-mount check for reflink capability. We'll add a mount flag to enable reflink post-mkfs soon and it'll need this to hook in. Signed-off-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 4 ++-- fs/xfs/libxfs/xfs_bmap.c | 4 ++-- fs/xfs/libxfs/xfs_bmap_btree.c | 2 +- fs/xfs/libxfs/xfs_format.h | 2 +- fs/xfs/libxfs/xfs_refcount_btree.c | 4 ++-- fs/xfs/libxfs/xfs_rmap.c | 6 +++--- fs/xfs/libxfs/xfs_rmap_btree.c | 4 ++-- fs/xfs/libxfs/xfs_trans_resv.c | 8 ++++---- fs/xfs/xfs_aops.c | 2 +- fs/xfs/xfs_fsops.c | 10 +++++----- fs/xfs/xfs_ioctl.c | 3 +-- fs/xfs/xfs_mount.h | 5 +++++ fs/xfs/xfs_reflink.c | 6 +++--- fs/xfs/xfs_super.c | 4 ++-- 14 files changed, 34 insertions(+), 30 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index e6e32c2..b3cfa34 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -68,7 +68,7 @@ xfs_extlen_t xfs_prealloc_blocks( struct xfs_mount *mp) { - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) return xfs_refc_block(mp) + 1; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) return XFS_RMAP_BLOCK(mp) + 1; @@ -2466,7 +2466,7 @@ xfs_agf_verify( be32_to_cpu(agf->agf_btreeblks) > be32_to_cpu(agf->agf_length)) return false; - if (xfs_sb_version_hasreflink(&mp->m_sb) && + if (xfs_mp_hasreflink(mp) && be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS) return false; diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 7e51f5c..effa8cc 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -810,7 +810,7 @@ try_another_ag: * has a block reservation. That isn't the case here, so if we run out * of space we'll try again with another AG. */ - if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && + if (xfs_mp_hasreflink(cur->bc_mp) && args.fsbno == NULLFSBLOCK && args.type == XFS_ALLOCTYPE_NEAR_BNO) { flist->xbf_low = 1; @@ -972,7 +972,7 @@ try_another_ag: * has a block reservation. That isn't the case here, so if we run out * of space we'll try again with another AG. */ - if (xfs_sb_version_hasreflink(&ip->i_mount->m_sb) && + if (xfs_mp_hasreflink(ip->i_mount) && args.fsbno == NULLFSBLOCK && args.type == XFS_ALLOCTYPE_NEAR_BNO) { goto try_another_ag; diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index b742bd8..d07718d 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -489,7 +489,7 @@ try_another_ag: * has a block reservation. That isn't the case here, so if we run out * of space we'll try again with another AG. */ - if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && + if (xfs_mp_hasreflink(cur->bc_mp) && args.fsbno == NULLFSBLOCK && args.type == XFS_ALLOCTYPE_NEAR_BNO) { cur->bc_private.b.flist->xbf_low = 1; diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 5cc0b8c..dcfc1ee 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -550,7 +550,7 @@ static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp) static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp) { - return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && + return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK); } diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c index 303f959..f83cb4b 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.c +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -218,7 +218,7 @@ xfs_refcountbt_verify( if (block->bb_magic != cpu_to_be32(XFS_REFC_CRC_MAGIC)) return false; - if (!xfs_sb_version_hasreflink(&mp->m_sb)) + if (!xfs_mp_hasreflink(mp)) return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; @@ -463,7 +463,7 @@ xfs_refcountbt_calc_reserves( xfs_extlen_t tree_len = 0; int error; - if (!xfs_sb_version_hasreflink(&mp->m_sb)) + if (!xfs_mp_hasreflink(mp)) return 0; *ask += xfs_refcountbt_max_size(mp); diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index d2bf531..e1ff7d7 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -874,7 +874,7 @@ xfs_rmap_unmap( * Only data fork extents on a reflink filesystem can overlap. * Everything else can use the regular free function. */ - if (!xfs_sb_version_hasreflink(&mp->m_sb) || + if (!xfs_mp_hasreflink(mp) || XFS_RMAP_NON_INODE_OWNER(owner) || (flags & XFS_RMAP_BMBT_BLOCK) || (flags & XFS_RMAP_ATTR_FORK)) @@ -1047,7 +1047,7 @@ xfs_rmap_map( * Only data fork extents on a reflink filesystem can overlap. * Everything else can use the regular alloc function. */ - if (!xfs_sb_version_hasreflink(&mp->m_sb) || + if (!xfs_mp_hasreflink(mp) || XFS_RMAP_NON_INODE_OWNER(owner) || (flags & XFS_RMAP_BMBT_BLOCK) || (flags & XFS_RMAP_ATTR_FORK)) @@ -1646,7 +1646,7 @@ xfs_rmap_convert( * Only data fork extents on a reflink filesystem can overlap. * Everything else can use the regular convert function. */ - if (!xfs_sb_version_hasreflink(&mp->m_sb)) + if (!xfs_mp_hasreflink(mp)) return __xfs_rmap_convert(cur, bno, len, unwritten, oinfo); oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; new_endoff = offset + len; diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c index 3d6f12f..8969722 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.c +++ b/fs/xfs/libxfs/xfs_rmap_btree.c @@ -65,7 +65,7 @@ xfs_rmapbt_need_reserve( struct xfs_mount *mp) { return xfs_sb_version_hasrmapbt(&mp->m_sb) && - xfs_sb_version_hasreflink(&mp->m_sb); + xfs_mp_hasreflink(mp); } static struct xfs_btree_cur * @@ -479,7 +479,7 @@ void xfs_rmapbt_compute_maxlevels( struct xfs_mount *mp) { - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) mp->m_rmap_maxlevels = XFS_BTREE_MAXLEVELS; else mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index c88395b..d53fe89 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -84,7 +84,7 @@ xfs_allocfree_log_count( blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1); - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) blocks += 2 * num_ops * (2 * mp->m_refc_maxlevels - 1); return blocks; @@ -812,14 +812,14 @@ xfs_trans_resv_calc( * require a permanent reservation on space. */ resp->tr_write.tr_logres = xfs_calc_write_reservation(mp); - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; else resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp); - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT_REFLINK; else resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; @@ -879,7 +879,7 @@ xfs_trans_resv_calc( resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp); - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; else resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index d053a9e..a030f3e 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -698,7 +698,7 @@ xfs_is_cow_io( { bool is_cow; - if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb)) + if (!xfs_mp_hasreflink(ip->i_mount)) return false; xfs_ilock(ip, XFS_ILOCK_SHARED); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 5b908dc..c2c939e 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -111,7 +111,7 @@ xfs_fs_geometry( XFS_FSOP_GEOM_FLAGS_SPINODES : 0) | (xfs_sb_version_hasrmapbt(&mp->m_sb) ? XFS_FSOP_GEOM_FLAGS_RMAPBT : 0) | - (xfs_sb_version_hasreflink(&mp->m_sb) ? + (xfs_mp_hasreflink(mp) ? XFS_FSOP_GEOM_FLAGS_REFLINK : 0); geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? mp->m_sb.sb_logsectsize : BBSIZE; @@ -266,7 +266,7 @@ xfs_growfs_data_private( agf->agf_longest = cpu_to_be32(tmpsize); if (xfs_sb_version_hascrc(&mp->m_sb)) uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid); - if (xfs_sb_version_hasreflink(&mp->m_sb)) { + if (xfs_mp_hasreflink(mp)) { agf->agf_refcount_root = cpu_to_be32( xfs_refc_block(mp)); agf->agf_refcount_level = cpu_to_be32(1); @@ -463,7 +463,7 @@ xfs_growfs_data_private( be16_add_cpu(&block->bb_numrecs, 1); /* account for refc btree root */ - if (xfs_sb_version_hasreflink(&mp->m_sb)) { + if (xfs_mp_hasreflink(mp)) { rrec = XFS_RMAP_REC_ADDR(block, 5); rrec->rm_startblock = cpu_to_be32( xfs_refc_block(mp)); @@ -533,7 +533,7 @@ xfs_growfs_data_private( /* * refcount btree root block */ - if (xfs_sb_version_hasreflink(&mp->m_sb)) { + if (xfs_mp_hasreflink(mp)) { bp = xfs_growfs_get_hdr_buf(mp, XFS_AGB_TO_DADDR(mp, agno, xfs_refc_block(mp)), BTOBB(mp->m_sb.sb_blocksize), 0, @@ -1075,7 +1075,7 @@ xfs_getfsmap_is_shared( xfs_extlen_t flen; int error; - if (!xfs_sb_version_hasreflink(&cur->bc_mp->m_sb)) + if (!xfs_mp_hasreflink(cur->bc_mp)) return false; /* Are there any shared blocks here? */ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 4668ae6..cfc05ce 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1267,8 +1267,7 @@ xfs_ioctl_setattr_check_cowextsize( if (!(fa->fsx_xflags & FS_XFLAG_COWEXTSIZE)) return 0; - if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb) || - ip->i_d.di_version != 3) + if (!xfs_mp_hasreflink(mp) || ip->i_d.di_version != 3) return -EINVAL; if (!S_ISREG(VFS_I(ip)->i_mode) && !S_ISDIR(VFS_I(ip)->i_mode)) diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index d06b192..c2e1294 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -227,6 +227,11 @@ typedef struct xfs_mount { #define XFS_WSYNC_READIO_LOG 15 /* 32k */ #define XFS_WSYNC_WRITEIO_LOG 14 /* 16k */ +static inline bool xfs_mp_hasreflink(struct xfs_mount *mp) +{ + return xfs_sb_version_hasreflink(&mp->m_sb); +} + /* * Allow large block sizes to be reported to userspace programs if the * "largeio" mount option is used. diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 1e17d2e..e2664ea 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -852,7 +852,7 @@ xfs_reflink_recover_cow( xfs_agnumber_t agno; int error = 0; - if (!xfs_sb_version_hasreflink(&mp->m_sb)) + if (!xfs_mp_hasreflink(mp)) return 0; for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { @@ -1416,7 +1416,7 @@ xfs_reflink_remap_range( xfs_extlen_t cowextsize; bool is_same; - if (!xfs_sb_version_hasreflink(&mp->m_sb)) + if (!xfs_mp_hasreflink(mp)) return -EOPNOTSUPP; if (XFS_FORCED_SHUTDOWN(mp)) @@ -1880,7 +1880,7 @@ xfs_reflink_check_flag_adjust( if (!chg) return 0; - if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb)) + if (!xfs_mp_hasreflink(ip->i_mount)) return -EOPNOTSUPP; if (i_size_read(VFS_I(ip)) != 0) return -EINVAL; diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 58068fc..84348af 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1589,7 +1589,7 @@ xfs_fs_fill_super( "Block device does not support DAX Turning DAX off."); mp->m_flags &= ~XFS_MOUNT_DAX; } - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) xfs_alert(mp, "DAX and reflink have not been tested together!"); } @@ -1602,7 +1602,7 @@ xfs_fs_fill_super( xfs_alert(mp, "EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!"); - if (xfs_sb_version_hasreflink(&mp->m_sb)) + if (xfs_mp_hasreflink(mp)) xfs_alert(mp, "EXPERIMENTAL reflink feature enabled. Use at your own risk!"); -- 2.1.4 From BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org Thu Jun 2 09:19:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E0F847CA3 for ; Thu, 2 Jun 2016 09:19:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5CBB1AC001 for ; Thu, 2 Jun 2016 07:19:27 -0700 (PDT) X-ASG-Debug-ID: 1464877164-04cb6c2dbcaf13e0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id mjRFfqmN0CRFBP0V (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 02 Jun 2016 07:19:24 -0700 (PDT) X-Barracuda-Envelope-From: BATV+679c1c940bff3faafe47+4666+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b8TT1-0001Xw-Jp; Thu, 02 Jun 2016 14:19:23 +0000 From: Christoph Hellwig To: darrick.wong@oracle.com Cc: xfs@oss.sgi.com Subject: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Date: Thu, 2 Jun 2016 16:19:10 +0200 X-ASG-Orig-Subj: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-Id: <1464877150-20457-4-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1464877150-20457-1-git-send-email-hch@lst.de> References: <1464877150-20457-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464877164 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8732 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30111 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 If the reflink mount option is specified we'll add the reflink btree root block to each AG late in the mount process and can then use the reflink tree. Signed-off-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_refcount_btree.c | 83 ++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount_btree.h | 2 + fs/xfs/libxfs/xfs_trans_resv.c | 23 +++++++++++ fs/xfs/libxfs/xfs_trans_resv.h | 1 + fs/xfs/xfs_mount.c | 24 +++++++++-- fs/xfs/xfs_mount.h | 5 ++- fs/xfs/xfs_super.c | 7 +++- 7 files changed, 139 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c index 7ae3ad7..aaea8da 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.c +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -484,3 +484,86 @@ xfs_refcountbt_calc_reserves( return error; } + +static int +xfs_reflink_ag_add( + struct xfs_trans *tp, + xfs_agnumber_t agno) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_perag *pag; + struct xfs_buf *bp, *agbp; + struct xfs_agf *agf; + __be32 bno; + int stat, error; + + error = __xfs_refcountbt_alloc_block(tp, agno, XFS_AG_RESV_NONE, + &bno, &stat); + if (error) + return error; + + bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(bno)), + mp->m_bsize, 0); + if (!bp) + return -ENOMEM; + + bp->b_ops = &xfs_refcountbt_buf_ops; + xfs_btree_init_block(mp, bp, XFS_REFC_CRC_MAGIC, 0, 0, agno, + XFS_BTREE_CRC_BLOCKS); + xfs_trans_buf_set_type(tp, bp, XFS_BLFT_BTREE_BUF); + xfs_trans_log_buf(tp, bp, 0, XFS_BTREE_SBLOCK_CRC_LEN - 1); + + error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp); + if (error) + return error; + + agf = XFS_BUF_TO_AGF(agbp); + agf->agf_refcount_root = bno; + agf->agf_refcount_level = cpu_to_be32(1); + + pag = xfs_perag_get(mp, agno); + pag->pagf_refcount_level = 1; + xfs_perag_put(pag); + + xfs_alloc_log_agf(tp, agbp, + XFS_AGF_REFCOUNT_ROOT | XFS_AGF_REFCOUNT_LEVEL); + return 0; +} + +int +xfs_reflink_add( + struct xfs_mount *mp) +{ + struct xfs_trans *tp = NULL; + int error, i; + + tp = xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE); + tp->t_flags |= XFS_TRANS_RESERVE; + error = xfs_trans_reserve(tp, &M_RES(mp)->tr_add_reflink, + mp->m_sb.sb_agcount, 0); + if (error) + goto out_trans_cancel; + + for (i = 0; i < mp->m_sb.sb_agcount; i++) { + xfs_log_sb(tp); + + error = xfs_reflink_ag_add(tp, i); + if (error) + goto out_trans_cancel; + + error = xfs_trans_roll(&tp, NULL); + if (error) + goto out_trans_cancel; + } + + mp->m_sb.sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK; + xfs_log_sb(tp); + + return xfs_trans_commit(tp); + +out_trans_cancel: + if (tp) + xfs_trans_cancel(tp); + return error; +} diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h index 6f4bf70..481e0d0 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.h +++ b/fs/xfs/libxfs/xfs_refcount_btree.h @@ -70,4 +70,6 @@ extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); +extern int xfs_reflink_add(struct xfs_mount *mp); + #endif /* __XFS_REFCOUNT_BTREE_H__ */ diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index d53fe89..346c0c1 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -802,6 +802,25 @@ xfs_calc_sb_reservation( return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize); } +/* + * For adding the reflinking we need to allocate the new root block + * and modify the AGF and SB, giving: + * the AGF: sectorsize + * the superblock for the reflink flag: sector size + * the reflink root block itself: sector size + * the allocation btrees: 2 trees * (max depth - 1) * block size + */ +STATIC uint +xfs_calc_add_reflink_resv_alloc( + struct xfs_mount *mp) +{ + return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize) + + mp->m_sb.sb_sectsize + + mp->m_sb.sb_sectsize + + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), + XFS_FSB_TO_B(mp, 1)); +} + void xfs_trans_resv_calc( struct xfs_mount *mp, @@ -885,6 +904,10 @@ xfs_trans_resv_calc( resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; + resp->tr_add_reflink.tr_logres = xfs_calc_add_reflink_resv_alloc(mp); + resp->tr_add_reflink.tr_logcount = XFS_DEFAULT_LOG_COUNT; + resp->tr_add_reflink.tr_logflags = XFS_TRANS_PERM_LOG_RES; + /* * The following transactions are logged in logical format with * a default log count. diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h index cf734cf..1c007da 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.h +++ b/fs/xfs/libxfs/xfs_trans_resv.h @@ -60,6 +60,7 @@ struct xfs_trans_resv { struct xfs_trans_res tr_qm_dqalloc; /* allocate quota on disk */ struct xfs_trans_res tr_qm_quotaoff; /* turn quota off */ struct xfs_trans_res tr_qm_equotaoff;/* end of turn quota off */ + struct xfs_trans_res tr_add_reflink; /* add reflink */ struct xfs_trans_res tr_sb; /* modify superblock */ struct xfs_trans_res tr_fsyncts; /* update timestamps on fsync */ }; diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 792f547..6e4cebf 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -962,11 +962,27 @@ xfs_mountfs( xfs_fs_reserve_ag_blocks(mp); - /* Recover any CoW blocks that never got remapped. */ - error = xfs_reflink_recover_cow(mp); - if (error && !XFS_FORCED_SHUTDOWN(mp)) - xfs_err(mp, + if (!xfs_sb_version_hasreflink(&mp->m_sb) && + (mp->m_flags & XFS_MOUNT_REFLINK)) { + if (XFS_SB_VERSION_NUM(&mp->m_sb) < XFS_SB_VERSION_5) { + xfs_warn(mp, + "Can't enable reflinks on version %d superblock.", + XFS_SB_VERSION_NUM(&mp->m_sb)); + return -EINVAL; + } + + error = xfs_reflink_add(mp); + if (error) { + xfs_err(mp, + "Failed to enable reflinks: %d\n", error); + } + } else { + /* Recover any CoW blocks that never got remapped. */ + error = xfs_reflink_recover_cow(mp); + if (error && !XFS_FORCED_SHUTDOWN(mp)) + xfs_err(mp, "Error %d recovering leftover CoW allocations.", error); + } } return 0; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index c2e1294..e3002cb 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -178,6 +178,8 @@ typedef struct xfs_mount { #define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops must be synchronous except for space allocations */ +#define XFS_MOUNT_REFLINK (1ULL << 1) /* allow use of reflinks (will + be permanent once used) */ #define XFS_MOUNT_WAS_CLEAN (1ULL << 3) #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem operations, typically for @@ -229,7 +231,8 @@ typedef struct xfs_mount { static inline bool xfs_mp_hasreflink(struct xfs_mount *mp) { - return xfs_sb_version_hasreflink(&mp->m_sb); + return xfs_sb_version_hasreflink(&mp->m_sb) || + (mp->m_flags & XFS_MOUNT_REFLINK); } /* diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 84348af..dfa5077 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -82,7 +82,7 @@ enum { Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota, Opt_prjquota, Opt_uquota, Opt_gquota, Opt_pquota, Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce, - Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, + Opt_discard, Opt_nodiscard, Opt_reflink, Opt_dax, Opt_err, }; static const match_table_t tokens = { @@ -132,6 +132,7 @@ static const match_table_t tokens = { {Opt_qnoenforce, "qnoenforce"}, /* same as uqnoenforce */ {Opt_discard, "discard"}, /* Discard unused blocks */ {Opt_nodiscard, "nodiscard"}, /* Do not discard unused blocks */ + {Opt_reflink, "reflink"}, /* Do not discard unused blocks */ {Opt_dax, "dax"}, /* Enable direct access to bdev pages */ {Opt_err, NULL}, @@ -219,6 +220,7 @@ xfs_parseargs( */ mp->m_flags |= XFS_MOUNT_BARRIER; mp->m_flags |= XFS_MOUNT_COMPAT_IOSIZE; + mp->m_flags |= XFS_MOUNT_REFLINK; /* * These can be overridden by the mount option parsing. @@ -368,6 +370,9 @@ xfs_parseargs( case Opt_nodiscard: mp->m_flags &= ~XFS_MOUNT_DISCARD; break; + case Opt_reflink: + mp->m_flags |= XFS_MOUNT_REFLINK; + break; #ifdef CONFIG_FS_DAX case Opt_dax: mp->m_flags |= XFS_MOUNT_DAX; -- 2.1.4 From holger@applied-asynchrony.com Thu Jun 2 09:21:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id BB4687CA3 for ; Thu, 2 Jun 2016 09:21:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8D8EC304039 for ; Thu, 2 Jun 2016 07:21:16 -0700 (PDT) X-ASG-Debug-ID: 1464877273-04cbb03569b13fd0001-NocioJ Received: from mail02.iobjects.de (mail02.iobjects.de [188.40.134.68]) by cuda.sgi.com with ESMTP id n6fTgcmY0IHuRNkG (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 07:21:14 -0700 (PDT) X-Barracuda-Envelope-From: holger@applied-asynchrony.com X-Barracuda-Effective-Source-IP: mail02.iobjects.de[188.40.134.68] X-Barracuda-Apparent-Source-IP: 188.40.134.68 Received: from tux.wizards.de (p4FF5801B.dip0.t-ipconnect.de [79.245.128.27]) by mail02.iobjects.de (Postfix) with ESMTPSA id EB304416014D; Thu, 2 Jun 2016 16:21:12 +0200 (CEST) Received: from [192.168.100.223] (ragnarok [192.168.100.223]) by tux.wizards.de (Postfix) with ESMTP id 7AF1411C01CF; Thu, 2 Jun 2016 16:21:12 +0200 (CEST) Subject: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 To: Stefan Priebe - Profihost AG X-ASG-Orig-Subj: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 References: <57503353.2050402@profihost.ag> <57503D33.6010000@applied-asynchrony.com> Cc: "xfs@oss.sgi.com" , Dave Chinner From: =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= Organization: Applied Asynchrony, Inc. Message-ID: <575040D8.8070903@applied-asynchrony.com> Date: Thu, 2 Jun 2016 16:21:12 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <57503D33.6010000@applied-asynchrony.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mail02.iobjects.de[188.40.134.68] X-Barracuda-Start-Time: 1464877274 X-Barracuda-Encrypted: DHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 712 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30111 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/02/16 16:05, Holger Hoffstätte wrote: > On 06/02/16 15:23, Stefan Priebe - Profihost AG wrote: >> I found a bug report from redhat here >> https://bugzilla.redhat.com/show_bug.cgi?id=1234586 pointing to this commit: >> xfs: handle dquot buffer readahead in log recovery correctly >> >> which isn't part of 4.4. Is it missing from linux-stable? > > Yes, mainline 7d6a13f02356 is missing from 4.4-stable because it applies, > but doesn't compile. :) > > I'll look into a fix. Well, that was easy. It also needs 233135b763 ("xfs: print name of verifier if it fails") which added a .name to the various xfs_buf_ops types. Can someone confirm that these can both go into 4.4-stable? -h From mstsxfx@gmail.com Thu Jun 2 09:50:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 88C2D7CA3 for ; Thu, 2 Jun 2016 09:50:53 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 4A9A6304062 for ; Thu, 2 Jun 2016 07:50:53 -0700 (PDT) X-ASG-Debug-ID: 1464879050-04cb6c2dbaaf1f30001-NocioJ Received: from mail-wm0-f48.google.com (mail-wm0-f48.google.com [74.125.82.48]) by cuda.sgi.com with ESMTP id 9Rvim8EJDedoXNhq (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 02 Jun 2016 07:50:51 -0700 (PDT) X-Barracuda-Envelope-From: mstsxfx@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f48.google.com[74.125.82.48] X-Barracuda-Apparent-Source-IP: 74.125.82.48 Received: by mail-wm0-f48.google.com with SMTP id a136so234159450wme.0 for ; Thu, 02 Jun 2016 07:50:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=IGzxEafujw1cBpR+3k6bB8wmhNVrNJnueUB72rEvwH8=; b=cJ36XO13jJQwwakTQn8Sy8omT/PhBOEFsQQ20eFubGW8bUgfSjmZmWQiU9NnNg62dx 3NUFSU/BsTrllVOwRlcmVoXw315P4aI3QHwxrmmMrfH9oykkQqxvaYAo+u9ekkIxdrDR aARiEeePHfq1CMD4Uz0laN64tcu40kvRMPFW/dm35kgHKf47lBxeEyP9iMs9IIcs7kmp 0yU6McDFHBbBAqyek5KpXDPvi09YQJbBDuirFnYgt295RcXsR3KI6X3/3TxiHXCHz3zP D+8ml59yQxLF9HLRxcjKeFvlOc+zeqU86ggOFlJLQJY98wh/uruCEASkK0P86nZdJF28 NqRA== X-Gm-Message-State: ALyK8tKUMvxA+ZGWcbCFfH/7QmW9eYSfzE3INnaq6Cr6AY+/p9bG6j+iW7O2veyRCDDOew== X-Received: by 10.28.169.2 with SMTP id s2mr9343325wme.78.1464879050305; Thu, 02 Jun 2016 07:50:50 -0700 (PDT) Received: from localhost (nat1.scz.suse.com. [213.151.88.250]) by smtp.gmail.com with ESMTPSA id d5sm964505wje.20.2016.06.02.07.50.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jun 2016 07:50:49 -0700 (PDT) Date: Thu, 2 Jun 2016 16:50:49 +0200 From: Michal Hocko To: Peter Zijlstra Cc: Dave Chinner , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160602145048.GS1995@dhcp22.suse.cz> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160516104130.GK3193@twins.programming.kicks-ass.net> <20160516130519.GJ23146@dhcp22.suse.cz> <20160516132541.GP3193@twins.programming.kicks-ass.net> <20160516231056.GE18496@dastard> <20160517144912.GZ3193@twins.programming.kicks-ass.net> <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160601181617.GV3190@twins.programming.kicks-ass.net> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: mail-wm0-f48.google.com[74.125.82.48] X-Barracuda-Start-Time: 1464879051 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2188 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30112 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed 01-06-16 20:16:17, Peter Zijlstra wrote: > On Wed, Jun 01, 2016 at 03:17:58PM +0200, Michal Hocko wrote: > > Thanks Dave for your detailed explanation again! Peter do you have any > > other idea how to deal with these situations other than opt out from > > lockdep reclaim machinery? > > > > If not I would rather go with an annotation than a gfp flag to be honest > > but if you absolutely hate that approach then I will try to check wheter > > a CONFIG_LOCKDEP GFP_FOO doesn't break something else. Otherwise I would > > steal the description from Dave's email and repost my patch. > > > > I plan to repost my scope gfp patches in few days and it would be good > > to have some mechanism to drop those GFP_NOFS to paper over lockdep > > false positives for that. > > Right; sorry I got side-tracked in other things again. > > So my favourite is the dedicated GFP flag, but if that's unpalatable for > the mm folks then something like the below might work. It should be > similar in effect to your proposal, except its more limited in scope. [...] > @@ -2876,11 +2883,36 @@ static void __lockdep_trace_alloc(gfp_t gfp_mask, unsigned long flags) > if (DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags))) > return; > > + /* > + * Skip _one_ allocation as per the lockdep_skip_alloc() request. > + * Must be done last so that we don't loose the annotation for > + * GFP_ATOMIC like things from IRQ or other nesting contexts. > + */ > + if (current->lockdep_reclaim_gfp & __GFP_SKIP_ALLOC) { > + current->lockdep_reclaim_gfp &= ~__GFP_SKIP_ALLOC; > + return; > + } > + > mark_held_locks(curr, RECLAIM_FS); > } I might be missing something but does this work actually? Say you would want a kmalloc(size), it would call slab_alloc_node slab_pre_alloc_hook lockdep_trace_alloc [...] ____cache_alloc_node cache_grow_begin kmem_getpages __alloc_pages_node __alloc_pages_nodemask lockdep_trace_alloc I understand your concerns about the scope but usually all allocations have to be __GFP_NOFS or none in the same scope so I would see it as a huge deal. -- Michal Hocko SUSE Labs From peterz@infradead.org Thu Jun 2 10:11:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 92CB57CA3 for ; Thu, 2 Jun 2016 10:11:29 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 53844304062 for ; Thu, 2 Jun 2016 08:11:26 -0700 (PDT) X-ASG-Debug-ID: 1464880280-04bdf05ad6b0c260001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id 3aEehPxLDhXVC6pc (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 02 Jun 2016 08:11:20 -0700 (PDT) X-Barracuda-Envelope-From: peterz@infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from j217100.upc-j.chello.nl ([24.132.217.100] helo=twins) by bombadil.infradead.org with esmtpsa (Exim 4.80.1 #2 (Red Hat Linux)) id 1b8UHF-0001Bq-2v; Thu, 02 Jun 2016 15:11:17 +0000 Received: by twins (Postfix, from userid 1000) id 1DD1D119CC208; Thu, 2 Jun 2016 17:11:16 +0200 (CEST) Date: Thu, 2 Jun 2016 17:11:16 +0200 From: Peter Zijlstra To: Michal Hocko Cc: Dave Chinner , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160602151116.GD3190@twins.programming.kicks-ass.net> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160516130519.GJ23146@dhcp22.suse.cz> <20160516132541.GP3193@twins.programming.kicks-ass.net> <20160516231056.GE18496@dastard> <20160517144912.GZ3193@twins.programming.kicks-ass.net> <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160602145048.GS1995@dhcp22.suse.cz> User-Agent: Mutt/1.5.21 (2012-12-30) X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1464880280 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2073 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30112 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Thu, Jun 02, 2016 at 04:50:49PM +0200, Michal Hocko wrote: > On Wed 01-06-16 20:16:17, Peter Zijlstra wrote: > > So my favourite is the dedicated GFP flag, but if that's unpalatable for > > the mm folks then something like the below might work. It should be > > similar in effect to your proposal, except its more limited in scope. > [...] > > @@ -2876,11 +2883,36 @@ static void __lockdep_trace_alloc(gfp_t gfp_mask, unsigned long flags) > > if (DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags))) > > return; > > > > + /* > > + * Skip _one_ allocation as per the lockdep_skip_alloc() request. > > + * Must be done last so that we don't loose the annotation for > > + * GFP_ATOMIC like things from IRQ or other nesting contexts. > > + */ > > + if (current->lockdep_reclaim_gfp & __GFP_SKIP_ALLOC) { > > + current->lockdep_reclaim_gfp &= ~__GFP_SKIP_ALLOC; > > + return; > > + } > > + > > mark_held_locks(curr, RECLAIM_FS); > > } > > I might be missing something but does this work actually? Say you would > want a kmalloc(size), it would call > slab_alloc_node > slab_pre_alloc_hook > lockdep_trace_alloc > [...] > ____cache_alloc_node > cache_grow_begin > kmem_getpages > __alloc_pages_node > __alloc_pages_nodemask > lockdep_trace_alloc Bugger :/ You're right, that would fail. So how about doing: #define __GFP_NOLOCKDEP (1u << __GFP_BITS_SHIFT) this means it cannot be part of address_space::flags or radix_tree_root::gfp_mask, but that might not be a bad thing. And this solves the scarcity thing, because per pagemap we need to have 5 'spare' bits anyway. > I understand your concerns about the scope but usually all allocations > have to be __GFP_NOFS or none in the same scope so I would see it as a > huge deal. With scope I mostly meant the fact that you have two calls that you need to pair up. That's not really nice as you can 'annotate' a _lot_ of code in between. I prefer the narrower annotations where you annotate a single specific site. From mstsxfx@gmail.com Thu Jun 2 10:46:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4DDF67CA3 for ; Thu, 2 Jun 2016 10:46:28 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9DA71AC003 for ; Thu, 2 Jun 2016 08:46:24 -0700 (PDT) X-ASG-Debug-ID: 1464882381-04cb6c2dbaaf35f0001-NocioJ Received: from mail-wm0-f44.google.com (mail-wm0-f44.google.com [74.125.82.44]) by cuda.sgi.com with ESMTP id tA5KMtcZQZvdzcGq (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 02 Jun 2016 08:46:22 -0700 (PDT) X-Barracuda-Envelope-From: mstsxfx@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f44.google.com[74.125.82.44] X-Barracuda-Apparent-Source-IP: 74.125.82.44 Received: by mail-wm0-f44.google.com with SMTP id a20so72687972wma.1 for ; Thu, 02 Jun 2016 08:46:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=tC+afMeO/TSrsvuZ1uigmgNY6YGFTsMzqWgHg/+3GYQ=; b=cW+o55OPSK4NvNr+gXfkmfJkw43qDmspRJM5Y/NJqKI4XQ9Ypt+phuC3WX1jlhCd0O cByIJi5f0iuCqitPa8wds0b9Wd5/lLUbkwr/Tg2ZXU6HKF9s4Ju15aQPDTa0l2UYXmT2 eI2vxJ6DkQuCnciNtFEMvm4zT/3uii3CBPQvH+DkTFB0UXXRpuZAjbFqpZWqMQySr47T S2KTj0r5W58bsyv1CX6+wgpUoyj68vwkaA2WczkGW8kYOYTy6jwhKY7RofLJVTn1J3d0 mabY8Rh82bld4E4CZp9GIsqt5zLUFnUD5NY6kG6oPweblYrM/9ChyIhCYX3wRjMdbxzu sS3A== X-Gm-Message-State: ALyK8tLgP/MRUP8kNlNw0n7L5jPgbxs9x7BbjsBi7V+lYya19SfbI/Bqj7HlrkNga7vsAA== X-Received: by 10.195.17.138 with SMTP id ge10mr10295812wjd.94.1464882380795; Thu, 02 Jun 2016 08:46:20 -0700 (PDT) Received: from localhost (nat1.scz.suse.com. [213.151.88.250]) by smtp.gmail.com with ESMTPSA id az2sm1217645wjc.6.2016.06.02.08.46.19 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 02 Jun 2016 08:46:19 -0700 (PDT) Date: Thu, 2 Jun 2016 17:46:19 +0200 From: Michal Hocko To: Peter Zijlstra Cc: Dave Chinner , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160602154619.GU1995@dhcp22.suse.cz> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160516132541.GP3193@twins.programming.kicks-ass.net> <20160516231056.GE18496@dastard> <20160517144912.GZ3193@twins.programming.kicks-ass.net> <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160602151116.GD3190@twins.programming.kicks-ass.net> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: mail-wm0-f44.google.com[74.125.82.44] X-Barracuda-Start-Time: 1464882381 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3778 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30112 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu 02-06-16 17:11:16, Peter Zijlstra wrote: > On Thu, Jun 02, 2016 at 04:50:49PM +0200, Michal Hocko wrote: > > On Wed 01-06-16 20:16:17, Peter Zijlstra wrote: > > > > So my favourite is the dedicated GFP flag, but if that's unpalatable for > > > the mm folks then something like the below might work. It should be > > > similar in effect to your proposal, except its more limited in scope. > > [...] > > > @@ -2876,11 +2883,36 @@ static void __lockdep_trace_alloc(gfp_t gfp_mask, unsigned long flags) > > > if (DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags))) > > > return; > > > > > > + /* > > > + * Skip _one_ allocation as per the lockdep_skip_alloc() request. > > > + * Must be done last so that we don't loose the annotation for > > > + * GFP_ATOMIC like things from IRQ or other nesting contexts. > > > + */ > > > + if (current->lockdep_reclaim_gfp & __GFP_SKIP_ALLOC) { > > > + current->lockdep_reclaim_gfp &= ~__GFP_SKIP_ALLOC; > > > + return; > > > + } > > > + > > > mark_held_locks(curr, RECLAIM_FS); > > > } > > > > I might be missing something but does this work actually? Say you would > > want a kmalloc(size), it would call > > slab_alloc_node > > slab_pre_alloc_hook > > lockdep_trace_alloc > > [...] > > ____cache_alloc_node > > cache_grow_begin > > kmem_getpages > > __alloc_pages_node > > __alloc_pages_nodemask > > lockdep_trace_alloc > > Bugger :/ You're right, that would fail. > > So how about doing: > > #define __GFP_NOLOCKDEP (1u << __GFP_BITS_SHIFT) Hmm, now that I looked closer this would break GFP_SLAB_BUG_MASK :/ The whole thing is a bit hysterical because I really do not see any reason to blow up just because somebody has used incorrect gfp mask (we have users who give us combinations without any sense in the tree...) We can fix that either by dropping the whole GFP_SLAB_BUG_MASK thingy or to update it with __GFP_NOLOCKDEP. It just shows how this might get really tricky and subtle. > this means it cannot be part of address_space::flags or > radix_tree_root::gfp_mask, but that might not be a bad thing. True, those shouldn't really care. > And this solves the scarcity thing, because per pagemap we need to have > 5 'spare' bits anyway. > > > I understand your concerns about the scope but usually all allocations > > have to be __GFP_NOFS or none in the same scope so I would see it as a > > huge deal. > > With scope I mostly meant the fact that you have two calls that you need > to pair up. That's not really nice as you can 'annotate' a _lot_ of code > in between. I prefer the narrower annotations where you annotate a > single specific site. Yes, I can see you point. What I meant to say is that we would most probably end up with the following pattern lockdep_trace_alloc_enable() some_foo_with_alloc(gfp_mask); lockdep_trace_alloc_disable() and some_foo_with_alloc might be a lot of code. But at the same time we know that _any_ allocation done from that context is safe from the reclaim recursiveness POV. If not then annotation is buggy and needs to be done at a different level but that would be exactly same if we did some_foo_with_alloc(gfp_mask|__GFP_NOLOCKDEP) because all the allocations down that road would reuse the same gfp mask anyway. That being said I completely agree that a single entry point is much less error prone but it also is tricky as we can see. So I would rather go with something less tricky. It's not like people are not used to enable/disable pattern. Anyway I will leave the decision to you. If you really insist on __GFP_NOLOCKDEP which doesn't consume new flag then I can review the resulting patch. -- Michal Hocko SUSE Labs From david@fromorbit.com Thu Jun 2 17:25:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8D1257CA3 for ; Thu, 2 Jun 2016 17:25:54 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 072A0AC001 for ; Thu, 2 Jun 2016 15:25:50 -0700 (PDT) X-ASG-Debug-ID: 1464906347-04cb6c2dbaafc970001-NocioJ Received: from ipmail04.adl6.internode.on.net (ipmail04.adl6.internode.on.net [150.101.137.141]) by cuda.sgi.com with ESMTP id D1TiPpQhxz1sC5Z8 for ; Thu, 02 Jun 2016 15:25:48 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Apparent-Source-IP: 150.101.137.141 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AkIRACaxUFd5LbJkKGdsb2JhbABegzpWfaYQAQEBAQEBBowlg1mGJyKFagQCAoE1TQEBAQEBAQcBAQEBAQE/AUCERgEBBDIBIyMQCAMYCSUPBSUDBxoTG4gTD8JfAQEBAQYBAQEBAR0FHoVBhRWKGgWNZYpShgCIFo8mRY8HhFQqMgGKewEBAQ Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail04.adl6.internode.on.net with ESMTP; 03 Jun 2016 07:55:46 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8b3h-0003Ag-Ej; Fri, 03 Jun 2016 08:25:45 +1000 Date: Fri, 3 Jun 2016 08:25:45 +1000 From: Dave Chinner To: Holger =?iso-8859-1?Q?Hoffst=E4tte?= Cc: Stefan Priebe - Profihost AG , "xfs@oss.sgi.com" Subject: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 Message-ID: <20160602222545.GO12670@dastard> X-ASG-Orig-Subj: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 References: <57503353.2050402@profihost.ag> <57503D33.6010000@applied-asynchrony.com> <575040D8.8070903@applied-asynchrony.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <575040D8.8070903@applied-asynchrony.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Start-Time: 1464906347 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1078 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30125 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 02, 2016 at 04:21:12PM +0200, Holger Hoffsttte wrote: > On 06/02/16 16:05, Holger Hoffsttte wrote: > > On 06/02/16 15:23, Stefan Priebe - Profihost AG wrote: > >> I found a bug report from redhat here > >> https://bugzilla.redhat.com/show_bug.cgi?id=1234586 pointing to this commit: > >> xfs: handle dquot buffer readahead in log recovery correctly > >> > >> which isn't part of 4.4. Is it missing from linux-stable? > > > > Yes, mainline 7d6a13f02356 is missing from 4.4-stable because it applies, > > but doesn't compile. :) > > > > I'll look into a fix. > > Well, that was easy. It also needs 233135b763 ("xfs: print name of verifier > if it fails") which added a .name to the various xfs_buf_ops types. > Can someone confirm that these can both go into 4.4-stable? You could just remove the line: + .name = "xfs_dquot_ra", from 7d6a13f02356 and that will fix the backport problem and not require any other commits to be backported. I'm fine with either solution. Cheers, Dave. -- Dave Chinner david@fromorbit.com From holger@applied-asynchrony.com Thu Jun 2 17:44:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0245D7CA3 for ; Thu, 2 Jun 2016 17:44:02 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id C8A528F8066 for ; Thu, 2 Jun 2016 15:44:01 -0700 (PDT) X-ASG-Debug-ID: 1464907437-04cbb0356ab1fe50001-NocioJ Received: from mail02.iobjects.de (mail02.iobjects.de [188.40.134.68]) by cuda.sgi.com with ESMTP id Ns3zqlB0BmNWMFGC (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 15:43:58 -0700 (PDT) X-Barracuda-Envelope-From: holger@applied-asynchrony.com X-Barracuda-Effective-Source-IP: mail02.iobjects.de[188.40.134.68] X-Barracuda-Apparent-Source-IP: 188.40.134.68 Received: from tux.wizards.de (p4FF5801B.dip0.t-ipconnect.de [79.245.128.27]) by mail02.iobjects.de (Postfix) with ESMTPSA id 97D55416014D for ; Fri, 3 Jun 2016 00:43:57 +0200 (CEST) Received: from [192.168.100.223] (ragnarok [192.168.100.223]) by tux.wizards.de (Postfix) with ESMTP id 2715211C01CF for ; Fri, 3 Jun 2016 00:43:57 +0200 (CEST) Subject: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 References: <57503353.2050402@profihost.ag> <57503D33.6010000@applied-asynchrony.com> <575040D8.8070903@applied-asynchrony.com> <20160602222545.GO12670@dastard> X-ASG-Orig-Subj: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 To: "xfs@oss.sgi.com" From: =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= Organization: Applied Asynchrony, Inc. Message-ID: <5750B6AD.2050308@applied-asynchrony.com> Date: Fri, 3 Jun 2016 00:43:57 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <20160602222545.GO12670@dastard> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mail02.iobjects.de[188.40.134.68] X-Barracuda-Start-Time: 1464907438 X-Barracuda-Encrypted: DHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1278 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30125 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 06/03/16 00:25, Dave Chinner wrote: > On Thu, Jun 02, 2016 at 04:21:12PM +0200, Holger Hoffstätte wrote: >> On 06/02/16 16:05, Holger Hoffstätte wrote: >>> On 06/02/16 15:23, Stefan Priebe - Profihost AG wrote: >>>> I found a bug report from redhat here >>>> https://bugzilla.redhat.com/show_bug.cgi?id=1234586 pointing to this commit: >>>> xfs: handle dquot buffer readahead in log recovery correctly >>>> >>>> which isn't part of 4.4. Is it missing from linux-stable? >>> >>> Yes, mainline 7d6a13f02356 is missing from 4.4-stable because it applies, >>> but doesn't compile. :) >>> >>> I'll look into a fix. >> >> Well, that was easy. It also needs 233135b763 ("xfs: print name of verifier >> if it fails") which added a .name to the various xfs_buf_ops types. >> Can someone confirm that these can both go into 4.4-stable? > > You could just remove the line: > > + .name = "xfs_dquot_ra", > > from 7d6a13f02356 and that will fix the backport problem and not > require any other commits to be backported. I'm fine with either > solution. Ha..that totally didn't occur to me..too simple. :} The .name patch applies cleanly and can't hurt either, so I think sending both commits to Greg is easiest for everyone. thanks! Holger From david@fromorbit.com Thu Jun 2 17:54:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 291DD7CA3 for ; Thu, 2 Jun 2016 17:54:21 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id A9C4CAC003 for ; Thu, 2 Jun 2016 15:54:20 -0700 (PDT) X-ASG-Debug-ID: 1464908057-04bdf05ad7b176a0001-NocioJ Received: from ipmail04.adl6.internode.on.net (ipmail04.adl6.internode.on.net [150.101.137.141]) by cuda.sgi.com with ESMTP id Nm4Cg8XCqBCJ9lhi for ; Thu, 02 Jun 2016 15:54:17 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Apparent-Source-IP: 150.101.137.141 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AhkQAEe4UFd5LbJkKGdsb2JhbABegzqBU4ZvnyABAQEBAQEGjCWKAIYMBAICgTRNAQEBAQEBBwEBAQEBAT8BQIRGAQEEOhwjEAgDDgoJJQ8FJQMHGhOILsJyAQEIAiUehUGFFYoaAQSYOI4WjyaPTIRUKjKJOiuBFwEBAQ Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail04.adl6.internode.on.net with ESMTP; 03 Jun 2016 08:24:16 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8bVI-0003DY-0Z; Fri, 03 Jun 2016 08:54:16 +1000 Date: Fri, 3 Jun 2016 08:54:15 +1000 From: Dave Chinner To: Christoph Hellwig Cc: darrick.wong@oracle.com, xfs@oss.sgi.com Subject: Re: [RFC] allow enabling reflinks at runtime Message-ID: <20160602225415.GP12670@dastard> X-ASG-Orig-Subj: Re: [RFC] allow enabling reflinks at runtime References: <1464877150-20457-1-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1464877150-20457-1-git-send-email-hch@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Start-Time: 1464908057 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 783 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30126 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 02, 2016 at 04:19:07PM +0200, Christoph Hellwig wrote: > I've had some vocal user requests to allow enabling reflinks at run time, > which happens to be a mostly trivial feature. The only caveat is that we > need a large enough log size to support the reflink requirements, but for > typical large file systems that's not an issue. Hmmm - how does this interact with all the rmap code? I was not planning on enabling reflink without rmap and vice versa simply because it makes the validation and testing matrix vastly more complex. Indeed, having reflink turned on after a filesystem has aged for some time (i.e. from unknown initial conditions) makes validation especially tricky.... Darrick? Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 2 18:08:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C3B207CA3 for ; Thu, 2 Jun 2016 18:08:30 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 84279304032 for ; Thu, 2 Jun 2016 16:08:27 -0700 (PDT) X-ASG-Debug-ID: 1464908904-04bdf05ad4b17a70001-NocioJ Received: from ipmail04.adl6.internode.on.net (ipmail04.adl6.internode.on.net [150.101.137.141]) by cuda.sgi.com with ESMTP id uzex0dmIMRie33UA for ; Thu, 02 Jun 2016 16:08:25 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Apparent-Source-IP: 150.101.137.141 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AiMQALK7UFd5LbJkKGdsb2JhbABegzqBU4ZvnyMBAQEBAQEGjCWDWYIfhAiEaoEiBAICgTBNAQEBAQEBBwEBAQEBAT8BQIRGAQEEJwsBIyMQCAMYCRoLDwUlAwcaE4guwnUBAQgCJR6FQYUVihoFmDiOFoFzh3uFOEWPB4JbHBaBRyoyinwBAQE Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail04.adl6.internode.on.net with ESMTP; 03 Jun 2016 08:38:13 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8bin-0003FV-7J; Fri, 03 Jun 2016 09:08:13 +1000 Date: Fri, 3 Jun 2016 09:08:13 +1000 From: Dave Chinner To: Holger =?iso-8859-1?Q?Hoffst=E4tte?= Cc: Stefan Priebe - Profihost AG , linux-mm@kvack.org, Minchan Kim , Brian Foster , linux-kernel@vger.kernel.org, "xfs@oss.sgi.com" Subject: Re: shrink_active_list/try_to_release_page bug? (was Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage) Message-ID: <20160602230813.GQ12670@dastard> X-ASG-Orig-Subj: Re: shrink_active_list/try_to_release_page bug? (was Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage) References: <574BEA84.3010206@profihost.ag> <20160530223657.GP26977@dastard> <20160531010724.GA9616@bbox> <20160531025509.GA12670@dastard> <20160531035904.GA17371@bbox> <20160531060712.GC12670@dastard> <574D2B1E.2040002@profihost.ag> <20160531073119.GD12670@dastard> <575022D2.7030502@profihost.ag> <57502A2E.60702@applied-asynchrony.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <57502A2E.60702@applied-asynchrony.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Start-Time: 1464908904 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1973 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30126 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 02, 2016 at 02:44:30PM +0200, Holger Hoffsttte wrote: > On 06/02/16 14:13, Stefan Priebe - Profihost AG wrote: > > > > Am 31.05.2016 um 09:31 schrieb Dave Chinner: > >> On Tue, May 31, 2016 at 08:11:42AM +0200, Stefan Priebe - Profihost AG wrote: > >>>> I'm half tempted at this point to mostly ignore this mm/ behavour > >>>> because we are moving down the path of removing buffer heads from > >>>> XFS. That will require us to do different things in ->releasepage > >>>> and so just skipping dirty pages in the XFS code is the best thing > >>>> to do.... > >>> > >>> does this change anything i should test? Or is 4.6 still the way to go? > >> > >> Doesn't matter now - the warning will still be there on 4.6. I think > >> you can simply ignore it as the XFS code appears to be handling the > >> dirty page that is being passed to it correctly. We'll work out what > >> needs to be done to get rid of the warning for this case, wether it > >> be a mm/ change or an XFS change. > > > > Any idea what i could do with 4.4.X? Can i safely remove the WARN_ONCE > > statement? > > By definition it won't break anything since it's just a heads-up message, > so yes, it should be "safe". However if my understanding of the situation > is correct, mainline commit f0281a00fe "mm: workingset: only do workingset > activations on reads" (+ friends) in 4.7 should effectively prevent this > from happenning. Can someone confirm or deny this? I don't think it will. The above commits will avoid putting /write-only/ dirty pages on the active list from the write() syscall vector, but it won't prevent pages that are read first then dirtied from ending up on the active list. e.g. a mmap write will first read the page from disk to populate the page (hence it ends up on the active list), then the page gets dirtied and ->page_mkwrite is called to tell the filesystem.... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 2 18:23:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 47E767CA3 for ; Thu, 2 Jun 2016 18:23:43 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 190D330404E for ; Thu, 2 Jun 2016 16:23:42 -0700 (PDT) X-ASG-Debug-ID: 1464909817-04cb6c2db9afdc20001-NocioJ Received: from ipmail04.adl6.internode.on.net (ipmail04.adl6.internode.on.net [150.101.137.141]) by cuda.sgi.com with ESMTP id CE17isx9eKHRKX6P for ; Thu, 02 Jun 2016 16:23:37 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Apparent-Source-IP: 150.101.137.141 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AhkQAHK/UFd5LbJkKGdsb2JhbABegzqBU4ZvnyMBAQEBAQEGjCWKAIYMBAICgTFNAQEBAQEBBwEBAQEBAT8BQIRGAQEEOhwjEAgDDgoJJQ8FJQMHGhOILsJqAQEBBwIlHoVBhRWKGgWYOI4WjyaPTIRUKjKKfAEBAQ Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail04.adl6.internode.on.net with ESMTP; 03 Jun 2016 08:52:55 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8bx0-0003Gq-C0; Fri, 03 Jun 2016 09:22:54 +1000 Date: Fri, 3 Jun 2016 09:22:54 +1000 From: Dave Chinner To: Michal Hocko Cc: Peter Zijlstra , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160602232254.GR12670@dastard> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160516231056.GE18496@dastard> <20160517144912.GZ3193@twins.programming.kicks-ass.net> <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160602154619.GU1995@dhcp22.suse.cz> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Start-Time: 1464909817 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1789 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30126 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 02, 2016 at 05:46:19PM +0200, Michal Hocko wrote: > On Thu 02-06-16 17:11:16, Peter Zijlstra wrote: > > With scope I mostly meant the fact that you have two calls that you need > > to pair up. That's not really nice as you can 'annotate' a _lot_ of code > > in between. I prefer the narrower annotations where you annotate a > > single specific site. > > Yes, I can see you point. What I meant to say is that we would most > probably end up with the following pattern > lockdep_trace_alloc_enable() > some_foo_with_alloc(gfp_mask); > lockdep_trace_alloc_disable() > > and some_foo_with_alloc might be a lot of code. That's the problem I see with this - the only way to make it maintainable is to precede each enable/disable() pair with a comment explaining *exactly* what those calls are protecting. And that, in itself, becomes a maintenance problem, because then code several layers deep has no idea what context it is being called from and we are likely to disable warnings in contexts where we probably shouldn't be. I think such an annotation approach really requires per-alloc site annotation, the reason for it should be more obvious from the context. e.g. any function that does memory alloc and takes an optional transaction context needs annotation. Hence, from an XFS perspective, I think it makes more sense to add a new KM_ flag to indicate this call site requirement, then jump through whatever lockdep hoop is required within the kmem_* allocation wrappers. e.g, we can ignore the new KM_* flag if we are in a transaction context and so the flag is only activated in the situations were we currently enforce an external GFP_NOFS context from the call site..... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 2 19:53:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 53BD77CA3 for ; Thu, 2 Jun 2016 19:53:49 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 25387304089 for ; Thu, 2 Jun 2016 17:53:46 -0700 (PDT) X-ASG-Debug-ID: 1464915219-04cbb03569b22980001-NocioJ Received: from ipmail04.adl6.internode.on.net (ipmail04.adl6.internode.on.net [150.101.137.141]) by cuda.sgi.com with ESMTP id uutb37VeykgeBLbH for ; Thu, 02 Jun 2016 17:53:40 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Apparent-Source-IP: 150.101.137.141 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Ah0QAIjUUFd5LbJkKGdsb2JhbABUCoM6Vn2mBgwBAQEBAQEGjCWFeIQIIoVqAgIBAQKBNE0BAQEBAQEHAQEBAQEBPwFAhEUBAQEDASMECwEjFwwFCwgDDgoCAgUhAgIPBSUDBxoTiCcHD7EkkTcBAQgCASQeY4RehRWCYIE4BYMkglkFiAGHFokhhgCIFo8mj0yEVCoyAYk4gUMBAQE Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail04.adl6.internode.on.net with ESMTP; 03 Jun 2016 10:23:27 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8dMa-0003QC-KI; Fri, 03 Jun 2016 10:53:24 +1000 Date: Fri, 3 Jun 2016 10:53:24 +1000 From: Dave Chinner To: Jan Tulak Cc: xfs-oss , Eric Sandeen Subject: Re: [PATCH 00/19 v2] mkfs cleaning Message-ID: <20160603005324.GS12670@dastard> X-ASG-Orig-Subj: Re: [PATCH 00/19 v2] mkfs cleaning References: <1461231593-31294-1-git-send-email-jtulak@redhat.com> <20160510061054.GI26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail04.adl6.internode.on.net[150.101.137.141] X-Barracuda-Start-Time: 1464915219 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2491 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30129 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 01, 2016 at 03:19:34PM +0200, Jan Tulak wrote: > On Tue, May 10, 2016 at 8:10 AM, Dave Chinner wrote: > > > > > Looking at xfstests runs, new failures are: > > > > generic/054 - > > generic/055 - both fail with: > > > > +*** mkfs failed: -l version=2,su=4096 *** > > > > and the .full file has this specific error: > > > > Illegal value 4096 for -l su option. value is too small > > > > indicating that we should be allowing (2^N * block size) log > > stripe units to be set. This will be a limit configuration issue, > > most likely needing fixing in mkfs. > > > > ​I'm looking on it, but this issue was introduced by Eric's fix for > patch "mkfs: > table based parsing for converted parameters": > > ​> ​ > The kernel enforces a max of XLOG_MAX_RECORD_BSIZE, > ​> ​ > and it should match the limits in L_SUNIT after all ... So nobody got it right, then. i.e. Eric's changes made it the same as what was in my original patchset, which means *I got it wrong*, too. Really, it's not at all important who made the incorrect change or why it was wrong - it's easy very make mistakes or get complex things wrong. What matters is that we identify the problem code, we fix the problem, and we try not to make the same error again. Mistakes are a learning opportunity for everyone, not just the person who wrote or reviewed the code. > And looking on fs/xfs/xfs_super.c, the MIN value is enforced too. So maybe > it is the test what needs fixing? Otherwise, I would put something > like XFS_MIN_SECTORSIZE there. > > See http://lxr.free-electrons.com/source/fs/xfs/xfs_super.c#L435 mp->m_logbsize is the incore log buffer size and this is checking that the iclogsize passed in as a mount option is within the valid range (16k->256k). It is not checking stripe unit alignment limits. We can write an iclogbuf at any sector offset in the log; the log stripe unit is simply an alignment guide. i.e. a lsunit = 4096 is 8 sector alignment, so the iclogbuf when written is padded out to 8 sector boundaries so that log writes are always aligned and sized to the log stripe unit. The only actual limit on iclogbuf size vs lsunit is that the iclogbuf size must be >= than the lsunit, which limits the lsunit to XLOG_MAX_RECORD_BSIZE. i.e valid range for specifying lsunit on the command line is 1 <= lsunit <= XLOG_MAX_RECORD_BSIZE. Cheers, Dave. -- Dave Chinner david@fromorbit.com From darrick.wong@oracle.com Thu Jun 2 20:58:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 293F87CA3 for ; Thu, 2 Jun 2016 20:58:49 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id DCB888F80C4 for ; Thu, 2 Jun 2016 18:58:48 -0700 (PDT) X-ASG-Debug-ID: 1464919126-04bdf05ad6b1af20001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id f5jTz73qC4CiOCm5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 02 Jun 2016 18:58:46 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u531wbS6009550 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 3 Jun 2016 01:58:37 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u531waOW007481 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 3 Jun 2016 01:58:37 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u531wYU8032184; Fri, 3 Jun 2016 01:58:35 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 02 Jun 2016 18:58:33 -0700 Date: Thu, 2 Jun 2016 18:58:33 -0700 From: "Darrick J. Wong" To: Dave Chinner Cc: Christoph Hellwig , xfs@oss.sgi.com Subject: Re: [RFC] allow enabling reflinks at runtime Message-ID: <20160603015832.GA5758@birch.djwong.org> X-ASG-Orig-Subj: Re: [RFC] allow enabling reflinks at runtime References: <1464877150-20457-1-git-send-email-hch@lst.de> <20160602225415.GP12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160602225415.GP12670@dastard> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1464919126 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1941 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30130 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 03, 2016 at 08:54:15AM +1000, Dave Chinner wrote: > On Thu, Jun 02, 2016 at 04:19:07PM +0200, Christoph Hellwig wrote: > > I've had some vocal user requests to allow enabling reflinks at run time, > > which happens to be a mostly trivial feature. The only caveat is that we > > need a large enough log size to support the reflink requirements, but for > > typical large file systems that's not an issue. > > Hmmm - how does this interact with all the rmap code? I was not > planning on enabling reflink without rmap and vice versa simply > because it makes the validation and testing matrix vastly more > complex. Indeed, having reflink turned on after a filesystem has > aged for some time (i.e. from unknown initial conditions) makes > validation especially tricky.... Well... It's not strictly impossible, but there will be some problems running repair and remounting. The patchset doesn't actually check that we satisfy the minimum log space requirement, which will result in xfs refusing to mount. As Christoph says, this is only an issue on small FSes, but nevertheless, we shouldn't trap the user like that. Second, mkfs lays out all the AG btree roots at the start of the AG before finding an aligned inode block for the root inode. xfs_repair feeds the same algorithm from the on-disk feature fields to check that s_rootino is sane, and gets very unhappy if it doesn't find the root inode at the computed location. Adding the two btree root blocks is enough to shift the root inode from 96 to 128. This all can be fixed, but it /was/ convenient not to have to support weirdo upgraded XFSes like ext4. :) Furthermore, if you turn on reflink, you should enable the per-AG reservations so we don't crash the FS by running out of space when it needs a block for the refcountbt. --D > > Darrick? > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com From jtulak@redhat.com Fri Jun 3 04:20:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A3BC17CA3 for ; Fri, 3 Jun 2016 04:20:52 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 688778F80A1 for ; Fri, 3 Jun 2016 02:20:49 -0700 (PDT) X-ASG-Debug-ID: 1464945646-04cbb03569b2e0e0001-NocioJ Received: from mail-io0-f181.google.com (mail-io0-f181.google.com [209.85.223.181]) by cuda.sgi.com with ESMTP id a5XWmBiLoHRhFbWX (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 03 Jun 2016 02:20:47 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-RBL-Trusted-Forwarder: 209.85.223.181 Received: by mail-io0-f181.google.com with SMTP id p194so69910745iod.1 for ; Fri, 03 Jun 2016 02:20:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=nl0w1d0T1s/RudD/J42HZsvB9HuPUTBbJ9zZAd1TexI=; b=CfOgLEzd/tVt6mqrXi2IpGcu6BFZudt5E8gzHU0IPOYYL0J+XSK0wXV6WNAq4o/9NM nRtH9PjDSaVwfr7wXep+vDOLRFOXDJokYvrJU/NOys8Nq1axGV5rM1wkDCuyQUotKgVD tZHpqEE9ZhPlMyJPpc1pVSz20jx3cP10QwIwlKXWyY1GE2vvt1wNoOmr3s/UNkTg8AVo mk2RFAbwEnP97vCwq14BMl4/q+ZYEV3ghLGbao0AvVacT5bAi70Y6ka7b6ZRrGg8k3GL j03FQxWaqtuzPceuHz0uT8mGGJzc+P/V/rah7Gjc3XY1qMJVL5scTIHN1oBRl7oamlLW KjWQ== X-Gm-Message-State: ALyK8tK0h2Y9JXWG+7dQZTJNble/9YCkPHy1Yf8aa/1NtSod4PmIOuFjR2vWI5GfFoVm+GUWZUHQQeAR2V+c3xai X-Received: by 10.107.4.71 with SMTP id 68mr3927834ioe.52.1464945646667; Fri, 03 Jun 2016 02:20:46 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.72.70 with HTTP; Fri, 3 Jun 2016 02:20:27 -0700 (PDT) In-Reply-To: <20160603005324.GS12670@dastard> References: <1461231593-31294-1-git-send-email-jtulak@redhat.com> <20160510061054.GI26977@dastard> <20160603005324.GS12670@dastard> From: Jan Tulak Date: Fri, 3 Jun 2016 11:20:27 +0200 Message-ID: Subject: Re: [PATCH 00/19 v2] mkfs cleaning To: Dave Chinner X-ASG-Orig-Subj: Re: [PATCH 00/19 v2] mkfs cleaning Cc: xfs-oss , Eric Sandeen Content-Type: multipart/alternative; boundary=001a113ee27ee2b06205345c3c7d X-Barracuda-Connect: mail-io0-f181.google.com[209.85.223.181] X-Barracuda-Start-Time: 1464945647 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9036 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30137 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message --001a113ee27ee2b06205345c3c7d Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Fri, Jun 3, 2016 at 2:53 AM, Dave Chinner wrote: > On Wed, Jun 01, 2016 at 03:19:34PM +0200, Jan Tulak wrote: > > On Tue, May 10, 2016 at 8:10 AM, Dave Chinner > wrote: > > > > > > > > Looking at xfstests runs, new failures are: > > > > > > generic/054 - > > > generic/055 - both fail with: > > > > > > +*** mkfs failed: -l version=3D2,su=3D4096 *** > > > > > > and the .full file has this specific error: > > > > > > Illegal value 4096 for -l su option. value is too small > > > > > > indicating that we should be allowing (2^N * block size) log > > > stripe units to be set. This will be a limit configuration issue, > > > most likely needing fixing in mkfs. > > > > > > > =E2=80=8BI'm looking on it, but this issue was introduced by Eric's fix= for > > patch "mkfs: > > table based parsing for converted parameters": > > > > =E2=80=8B> =E2=80=8B > > The kernel enforces a max of XLOG_MAX_RECORD_BSIZE, > > =E2=80=8B> =E2=80=8B > > and it should match the limits in L_SUNIT after all ... > > So nobody got it right, then. i.e. Eric's changes made it the same > as what was in my original patchset, which means *I got it wrong*, > too. > > Really, it's not at all important who made the incorrect change or > why it was wrong - it's easy very make mistakes or get complex > things wrong. What matters is that we identify the problem code, we > fix the problem, and we try not to make the same error again. > Mistakes are a learning opportunity for everyone, not just the > person who wrote or reviewed the code. > > =E2=80=8BYeah, I was just trying to get together all the info. =E2=80=8B > > And looking on fs/xfs/xfs_super.c, the MIN value is enforced too. So > maybe > > it is the test what needs fixing? Otherwise, I would put something > > like XFS_MIN_SECTORSIZE there. > > > > See http://lxr.free-electrons.com/source/fs/xfs/xfs_super.c#L435 > > mp->m_logbsize is the incore log buffer size and this is checking > that the iclogsize passed in as a mount option is within the valid > range (16k->256k). It is not checking stripe unit alignment limits. > We can write an iclogbuf at any sector offset in the log; the log > stripe unit is simply an alignment guide. i.e. a lsunit =3D 4096 is 8 > sector alignment, so the iclogbuf when written is padded out to 8 > sector boundaries so that log writes are always aligned and sized to > the log stripe unit. > > The only actual limit on iclogbuf size vs lsunit is that the > iclogbuf size must be >=3D than the lsunit, which limits the lsunit > to XLOG_MAX_RECORD_BSIZE. i.e valid range for specifying lsunit on > the command line is 1 <=3D lsunit <=3D XLOG_MAX_RECORD_BSIZE. > OK. Only, it seems we mixed lsu and lsunit. From manpage: lsunit is specified in 512-bytes block units. So the correct ranges for both lsunit and lsu should be: 1 <=3D lsunit <=3D BTOBB(XLOG_MAX_RECORD_BSIZE) BBTOB(1) <=3D lsu <=3D XLOG_MAX_RECORD_BSIZE Which will be further limited from the bottom by the physical block size, but that check is already in place and working. If this sounds ok, I will send the patch. Cheers, Jan --=20 Jan Tulak jtulak@redhat.com / jan@tulak.me --001a113ee27ee2b06205345c3c7d Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable


On Fri, Jun 3, 2016 at 2:53 AM, Dave Chinner <david@fromorb= it.com> wrote:
On Wed, J= un 01, 2016 at 03:19:34PM +0200, Jan Tulak wrote:
> On Tue, May 10, 2016 at 8:10 AM, Dave Chinner <david@fromorbit.com> wrote:
>
> >
> > Looking at xfstests runs, new failures are:
> >
> > generic/054 -
> > generic/055 - both fail with:
> >
> > +*** mkfs failed: -l version=3D2,su=3D4096 ***
> >
> > and the .full file has this specific error:
> >
> > Illegal value 4096 for -l su option. value is too small
> >
> > indicating that we should be allowing (2^N * block size) log
> > stripe units to be set. This will be a limit configuration issue,=
> > most likely needing fixing in mkfs.
> >
>
> =E2=80=8BI'm looking on it, but this issue was introduced by Eric&= #39;s fix for
> patch "mkfs:
> table based parsing for converted parameters":
>
> =E2=80=8B> =E2=80=8B
> The kernel enforces a max of XLOG_MAX_RECORD_BSIZE,
> =E2=80=8B> =E2=80=8B
> and it should match the limits in L_SUNIT after all ...

So nobody got it right, then.=C2=A0 i.e. Eric's changes made it = the same
as what was in my original patchset, which means *I got it wrong*,
too.

Really, it's not at all important who made the incorrect change or
why it was wrong - it's easy very make mistakes or get complex
things wrong. What matters is that we identify the problem code, we
fix the problem, and we try not to make the same error again.
Mistakes are a learning opportunity for everyone, not just the
person who wrote or reviewed the code.

=E2=80=8BYe= ah, I was just trying to get together all the info. =E2=80=8B
=C2=A0
> And looking on fs/xfs/xfs_super.c, the MIN value is enforced too. So m= aybe
> it is the test what needs fixing? Otherwise, I would put something
> like XFS_MIN_SECTORSIZE there.
>
> See http://lxr.free-electrons.com/s= ource/fs/xfs/xfs_super.c#L435

mp->m_logbsize is the incore log buffer size and this is checking=
that the iclogsize passed in as a mount option is within the valid
range (16k->256k). It is not checking stripe unit alignment limits.
We can write an iclogbuf at any sector offset in the log; the log
stripe unit is simply an alignment guide. i.e. a lsunit =3D 4096 is 8
sector alignment, so the iclogbuf when written is padded out to 8
sector boundaries so that log writes are always aligned and sized to
the log stripe unit.

The only actual limit on iclogbuf size vs lsunit is that the
iclogbuf size must be >=3D than the lsunit, which limits the lsunit
to XLOG_MAX_RECORD_BSIZE. i.e valid range for specifying lsunit on
the command line is 1 <=3D lsunit <=3D XLOG_MAX_RECORD_BSIZE.

OK. Only, it seems we mixed lsu and lsunit. F= rom manpage: lsunit is specified in 512-bytes block units.=C2=A0
So the correct ranges for both lsunit and lsu should be:
1 <=3D lsunit <=3D BTOB= B(XLOG_MAX_RECORD_BSIZE)
BBTOB(1) <=3D lsu <=3D=C2=A0XLOG_MAX_RECORD_BSIZE

W= hich will be further limited from the bottom by the=C2=A0physical block siz= e, but that check is already in place and working.

If this sounds ok, I will send the patch.

=
Cheers,
Jan


--
<= div class=3D"gmail_signature" data-smartmail=3D"gmail_signature">
--001a113ee27ee2b06205345c3c7d-- From jtulak@redhat.com Fri Jun 3 07:09:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id DF0927CA0 for ; Fri, 3 Jun 2016 07:09:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4B106AC021 for ; Fri, 3 Jun 2016 05:09:41 -0700 (PDT) X-ASG-Debug-ID: 1464955779-04cb6c2db9b0e5a0001-NocioJ Received: from mail-io0-f176.google.com (mail-io0-f176.google.com [209.85.223.176]) by cuda.sgi.com with ESMTP id fzEINqgTHCHyr0mD (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 03 Jun 2016 05:09:39 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-RBL-Trusted-Forwarder: 209.85.223.176 Received: by mail-io0-f176.google.com with SMTP id p194so72973508iod.1 for ; Fri, 03 Jun 2016 05:09:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=4TOR1ADMEaIANpwTifrTqyHfT56yEgeJ19w5u3ptcAM=; b=T02XzuhmFJ9o15NaQHgEpd0oaYsbcGggjNPpHzt+U4OruoYAtjTioqEyCVdFfvDL7e NukGzZBjt3Z9mhUUB/fSkm82y09Qpm4InxzUsb61oPBHE6D9+5gzXHXhYvSczx97WuAL Q0KAv0qNISkO/BhDTof7qXqM7VzbtedT4UIMb3SWhFV0hO4KlHy74N660QHxM0KgnWPm bdlm1zBv/MwYXt/LL+CF1gUE9yfx6+jOfMtWdUM8DHm+PIttqYVMkkCYQG53/tPDbdCA lryTQIAEoMsTy7K0byYhM3P8TVilOvrD0uilntGg9YzPh3d759EJhxZFaFGEOcFv1Wsy SwMw== X-Gm-Message-State: ALyK8tJ8mDnluunoPzMblnETKlp3L0uZueMFY9X5jCMnOdLF8quS8BD+Ap+bL5mf7A6xQAZYwV1msRgyYABZ7Qfk X-Received: by 10.107.133.141 with SMTP id p13mr5134544ioi.71.1464955779015; Fri, 03 Jun 2016 05:09:39 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.72.70 with HTTP; Fri, 3 Jun 2016 05:09:19 -0700 (PDT) In-Reply-To: References: <1461231593-31294-1-git-send-email-jtulak@redhat.com> <20160510061054.GI26977@dastard> <20160603005324.GS12670@dastard> From: Jan Tulak Date: Fri, 3 Jun 2016 14:09:19 +0200 Message-ID: Subject: Re: [PATCH 00/19 v2] mkfs cleaning To: Dave Chinner X-ASG-Orig-Subj: Re: [PATCH 00/19 v2] mkfs cleaning Cc: xfs-oss , Eric Sandeen Content-Type: multipart/alternative; boundary=001a113ecd9cd208e005345e980a X-Barracuda-Connect: mail-io0-f176.google.com[209.85.223.176] X-Barracuda-Start-Time: 1464955779 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5240 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30140 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message --001a113ecd9cd208e005345e980a Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable [ =E2=80=8Bsnip all, another issue, unrelated to the lsunit one]=E2=80=8B > =E2=80=8BI realised one small glitch with conflicts watching in the code in combination with flags. It is not regression, I think, because b=E2=80=8Bef= ore now, it was not possible to do something like -l internal=3D0,logdev=3Dsomething= , but now it should be possible. The code checks only whether an option was seen, not its value, so it does't know that we are in fact disabling something. I see two ways how to do solve it. One is a custom conflict solving for these cases, putting some if (flag1 && option2) somewhere once every argument and option is parsed. But this goes against what the patchset did and moves it again out of the option table... The other way is to make a special case for flags in the conflicts-handling code. Basically, I would extend the structure with something like: { .index =3D L_INTERNAL, .conflicts =3D { L_FILE, L_DEV, LAST_CONFLICT }, .conflicts_ignore_on_false=3Dtrue, // new item, shorter name to be found .minval =3D 0, .maxval =3D 1, .defaultval =3D 1, }, And then, if a conflict is found, it checks the value and if the value is false/zero, then ignore the conflict. A more generic code would allow for any given value, but I think that this would be useful only for flags, so "on_false" and possibly "on_true" would be enough. =E2=80=8BAny comments? Thanks, Jan=E2=80=8B --=20 Jan Tulak jtulak@redhat.com / jan@tulak.me --001a113ecd9cd208e005345e980a Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

[
=E2=80=8Bsnip all, another issue, unrelated to = the lsunit one]=E2=80=8B
<= div dir=3D"ltr">

<= /div>
=E2=80=8BI realised one small glitch wit= h conflicts watching in the code in combination with flags. It is not regre= ssion, I think, because b=E2=80=8Before now, it was not possible to do some= thing like -l internal=3D0,logdev=3Dsomething, but now it should be possibl= e.

The code checks only whether an option was seen, no= t its value, so it does't know that we are in fact disabling something.= I see two ways how to do solve it. One is a custom conflict solving for th= ese cases, putting some if (flag1 && option2) somewhere once every = argument and option is parsed. But this goes against what the patchset did = and moves it again out of the option table...

The oth= er way is to make a special case for flags in the conflicts-handling code. = Basically, I would extend the structure with something like:

{ .index =3D L_INTERNAL,
=C2=A0 .conflicts =3D { L_FILE,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 L_DEV,
=C2=A0 =C2=A0 =C2=A0 =C2=A0 LAST_CONFLICT },
=C2=A0 .conflicts_ignore_on_false=3Dtrue, // new item, shorter nam= e to be found
=C2=A0 .minval =3D 0,
=C2=A0 .maxval =3D 1,
=C2=A0 .defaultval =3D 1,
}= ,

= And then, if a conflict is found, it checks the value and if the value is f= alse/zero, then ignore the conflict. A more generic code would allow for an= y given value, but I think that this would be useful only for flags, so &qu= ot;on_false" and possibly "on_true" would be enough.

=E2=80=8BAny comments?
=
Thanks,
Jan=E2=80=8B




--
Jan Tulak
<= /div>jtulak@redhat.c= om=C2=A0/ jan@tulak.m= e
--001a113ecd9cd208e005345e980a-- From fspu@mail.ua Fri Jun 3 09:48:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_MESSAGE,MIME_HTML_ONLY, SPOOFED_URL_HOST,T_REMOTE_IMAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BEE537CA0 for ; Fri, 3 Jun 2016 09:48:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7F5B78F80CB for ; Fri, 3 Jun 2016 07:48:52 -0700 (PDT) X-ASG-Debug-ID: 1464965327-04cbb03569b3a270001-NocioJ Received: from infobiz.in.ua (infobiz.ua [89.184.82.114]) by cuda.sgi.com with ESMTP id Hy89VV1X9CAYLwnz for ; Fri, 03 Jun 2016 07:48:47 -0700 (PDT) X-Barracuda-Envelope-From: fspu@mail.ua X-Barracuda-Effective-Source-IP: infobiz.ua[89.184.82.114] X-Barracuda-Apparent-Source-IP: 89.184.82.114 Received: from [127.0.0.1] (localhost [127.0.0.1]) by infobiz.in.ua (Postfix) with ESMTP id C84B02D5C1C for ; Fri, 3 Jun 2016 17:48:44 +0300 (EEST) Message-ID: <1464965283.575198a30cd96@swift.generated> Date: Fri, 03 Jun 2016 17:48:03 +0300 Subject: =?utf-8?Q?=D0=9E=D1=82=D0=BA=D1=80=D1=8B=D1=82=D1=8B=D0=B9?= =?utf-8?Q?_=D0=A7=D0=B5=D0=BC=D0=BF=D0=B8=D0=BE=D0=BD=D0=B0=D1=82_=D0=A3?= =?utf-8?Q?=D0=BA=D1=80=D0=B0=D0=B8=D0=BD=D1=8B_=D0=BF=D0=BE_=D1=81=D0=BF?= =?utf-8?Q?=D0=BE=D1=80=D1=82=D0=B8=D0=B2=D0=BD=D0=BE=D0=BC?= =?utf-8?Q?=D1=83_=D0=BF=D0=B0=D1=80=D0=B5=D0=BD=D0=B8=D1=8E?= From: =?utf-8?Q?=D0=9D=D0=B0=D1=82=D0=B0=D0=BB=D1=8C=D1=8F?= X-ASG-Orig-Subj: =?utf-8?Q?=D0=9E=D1=82=D0=BA=D1=80=D1=8B=D1=82=D1=8B=D0=B9?= =?utf-8?Q?_=D0=A7=D0=B5=D0=BC=D0=BF=D0=B8=D0=BE=D0=BD=D0=B0=D1=82_=D0=A3?= =?utf-8?Q?=D0=BA=D1=80=D0=B0=D0=B8=D0=BD=D1=8B_=D0=BF=D0=BE_=D1=81=D0=BF?= =?utf-8?Q?=D0=BE=D1=80=D1=82=D0=B8=D0=B2=D0=BD=D0=BE=D0=BC?= =?utf-8?Q?=D1=83_=D0=BF=D0=B0=D1=80=D0=B5=D0=BD=D0=B8=D1=8E?= To: xfs@oss.sgi.com MIME-Version: 1.0 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: infobiz.ua[89.184.82.114] X-Barracuda-Start-Time: 1464965327 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5051 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-BRTS-Evidence: mfsportpar.com X-Barracuda-Spam-Score: 0.80 X-Barracuda-Spam-Status: No, SCORE=0.80 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC7_SA_HREF_HTTP_MISMATCH, HTML_MESSAGE, MIME_HTML_ONLY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30143 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.80 BSF_SC7_SA_HREF_HTTP_MISMATCH BODY: Custom Phishing Mismatch 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message

=D0=A4=D0=B5=D0=B4=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F= =D1=81=D0=BF=D0=BE=D1=80=D1=82=D0=B8=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE= =D0=BF=D0=B0=D1=80=D0=B5=D0=BD=D0=B8=D1=8F =D0=A3=D0=BA=D1=80= =D0=B0=D0=B8=D0=BD=D1=8B


=D0=BF=D1=80=D0=B8 =D0=BF= =D0=BE=D0=B4=D0=B4=D0=B5=D1=80=D0=B6=D0=BA=D0=B5

=D0=9A= =D0=B8=D0=B5=D0=B2=D1=81=D0=BA=D0=BE=D0=B9 =D0=9E=D0=B1=D0=BB=D0=B0= =D1=81=D1=82=D0=BD=D0=BE=D0=B9 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0= =D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9 =D0=B0=D0=B4= =D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=86=D0=B8=D0=B8,<= /p>

=D0=9C= =D0=B5=D0=B6=D0=B4=D1=83=D0=BD=D0=B0=D1=80=D0=BE=D0=B4=D0=BD=D0=BE=D0=B9= =D0=A4=D0=B5=D0=B4=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8 =D1=81= =D0=BF=D0=BE=D1=80=D1=82=D0=B8=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE =D0=BF= =D0=B0=D1=80=D0=B5=D0=BD=D0=B8=D1=8F (=D0=9C=D0=A4=D0=A1=D0=9F),

=D0=90=D1=81=D1=81=D0=BE=D1=86=D0=B8=D0=B0=D1=86=D0=B8=D0=B8 = =D0=B1=D0=B0=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE =D0=B1=D0=B8=D0=B7=D0=BD= =D0=B5=D1=81=D0=B0 =D0=A3=D0=BA=D1=80=D0=B0=D0=B8=D0=BD=D1=8B,

<= p style=3D"text-align: center;">=D0=9C= =D0=B5=D0=B6=D0=B4=D1=83=D0=BD=D0=B0=D1=80=D0=BE=D0=B4=D0=BD=D0=BE=D0=B9= =D0=90=D0=BA=D0=B0=D0=B4=D0=B5=D0=BC=D0=B8=D0=B8 =D0=B1=D0=B0= =D0=BD=D0=BD=D0=BE=D0=B3=D0=BE =D0=B8=D1=81=D0=BA=D1=83=D1=81=D1=81= =D1=82=D0=B2=D0=B0

=D0=BF=D0=BE=D0=B4 =D0=BF=D0=B0=D1=82=D1=80=D0=BE=D0=BD= =D0=B0=D1=82=D0=BE=D0=BC =D0=BC=D1=8D=D1=80=D0=B8=D0=B8 =D0=B3= . =D0=91=D1=83=D1=87=D0=B0


16-18 =D1=81=D0=B5= =D0=BD=D1=82=D1=8F=D0=B1=D1=80=D1=8F 2016 =D0=B3=D0=BE=D0=B4=D0=B0&nbs= p; =D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B4=D0=B8=D1=82

<= p style=3D"text-align: center;">

=D0=9E=D1=82=D0=BA=D1=80=D1=8B=D1=82=D1=8B=D0=B9 =D1=87= =D0=B5=D0=BC=D0=BF=D0=B8=D0=BE=D0=BD=D0=B0=D1=82 =D0=A3=D0=BA=D1=80= =D0=B0=D0=B8=D0=BD=D1=8B =D0=BF=D0=BE =D1=81=D0=BF=D0=BE=D1=80= =D1=82=D0=B8=D0=B2=D0=BD=D0=BE=D0=BC=D1=83 =D0=BF=D0=B0=D1=80=D0=B5= =D0=BD=D0=B8=D1=8E

=D1=81=D1=80=D0=B5=D0=B4=D0=B8= =D0=BC=D0=B0=D1=81=D1=82=D0=B5=D1=80=D0=BE=D0=B2 =D0=B1=D0=B0= =D0=BD=D0=BD=D0=BE-=D0=BE=D0=B7=D0=B4=D0=BE=D1=80=D0=BE=D0=B2=D0=B8= =D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D1=85 =D0=BF=D1=80=D0=BE=D1=86= =D0=B5=D0=B4=D1=83=D1=80

 (=D0=B3. =D0=91=D1=83= =D1=87=D0=B0, =D0=9A=D0=B8=D0=B5=D0=B2=D1=81=D0=BA=D0=B0=D1=8F= =D0=BE=D0=B1=D0=BB=D0=B0=D1=81=D1=82=D1=8C)

http://mfsportpar.com/


2016 =C2=A9 =D0=A4=D0=B5= =D0=B4=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F =D1=81=D0=BF=D0=BE=D1=80= =D1=82=D0=B8=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE =D0=BF=D0=B0=D1=80=D0=B5= =D0=BD=D0=B8=D1=8F =D0=A3=D0=BA=D1=80=D0=B0=D0=B8=D0=BD=D1=8B | http://mfsportpar.com/
= =D0=AD=D1=82=D0=BE =D0=BF=D0=B8=D1=81=D1=8C=D0=BC=D0=BE = =D0=B1=D1=8B=D0=BB=D0=BE =D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BB= =D0=B5=D0=BD=D0=BE =D0=BD=D0=B0 xfs@oss.= sgi.com | =D0=9E=D1=82=D0=BF=D0=B8=D1=81=D0=B0=D1=82=D1=8C= =D1=81=D1=8F

=D0=9F=D0=BE= =D0=B6=D0=B0=D0=BB=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=D1=81=D1=8F =D0=BD= =D0=B0 =D1=81=D0=BF=D0=B0=D0=BC

= =D0=A1=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=BE c =D0=BF= =D0=BE=D0=BC=D0=BE=D1=89=D1=8C=D1=8E I= nfoBiz

From s.priebe@profihost.ag Fri Jun 3 12:43:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 80A1D7CA0 for ; Fri, 3 Jun 2016 12:43:30 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 52F8E3040D4 for ; Fri, 3 Jun 2016 10:43:27 -0700 (PDT) X-ASG-Debug-ID: 1464975803-04cbb03568b3e500001-NocioJ Received: from mail-ph.de-nserver.de (mail-ph.de-nserver.de [85.158.179.214]) by cuda.sgi.com with ESMTP id WSmg7yU0gJ5Eu30O (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 03 Jun 2016 10:43:24 -0700 (PDT) X-Barracuda-Envelope-From: s.priebe@profihost.ag X-Barracuda-Effective-Source-IP: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Apparent-Source-IP: 85.158.179.214 Received: (qmail 728 invoked from network); 3 Jun 2016 19:43:23 +0200 X-Fcrdns: No Received: from phoffice.de-nserver.de (HELO [10.242.2.3]) (185.39.223.5) (smtp-auth username hostmaster@profihost.com, mechanism plain) by mail-ph.de-nserver.de (qpsmtpd/0.92) with (ECDHE-RSA-AES256-SHA encrypted) ESMTPSA; Fri, 03 Jun 2016 19:43:23 +0200 Subject: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 To: Dave Chinner , =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= X-ASG-Orig-Subj: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 References: <57503353.2050402@profihost.ag> <57503D33.6010000@applied-asynchrony.com> <575040D8.8070903@applied-asynchrony.com> <20160602222545.GO12670@dastard> Cc: "xfs@oss.sgi.com" From: Stefan Priebe - Profihost AG Message-ID: <5751C1B9.90709@profihost.ag> Date: Fri, 3 Jun 2016 19:43:21 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <20160602222545.GO12670@dastard> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-User-Auth: Auth by hostmaster@profihost.com through 185.39.223.5 X-Barracuda-Connect: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Start-Time: 1464975804 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1150 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30145 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Am 03.06.2016 um 00:25 schrieb Dave Chinner: > On Thu, Jun 02, 2016 at 04:21:12PM +0200, Holger Hoffsttte wrote: >> On 06/02/16 16:05, Holger Hoffsttte wrote: >>> On 06/02/16 15:23, Stefan Priebe - Profihost AG wrote: >>>> I found a bug report from redhat here >>>> https://bugzilla.redhat.com/show_bug.cgi?id=1234586 pointing to this commit: >>>> xfs: handle dquot buffer readahead in log recovery correctly >>>> >>>> which isn't part of 4.4. Is it missing from linux-stable? >>> >>> Yes, mainline 7d6a13f02356 is missing from 4.4-stable because it applies, >>> but doesn't compile. :) >>> >>> I'll look into a fix. >> >> Well, that was easy. It also needs 233135b763 ("xfs: print name of verifier >> if it fails") which added a .name to the various xfs_buf_ops types. >> Can someone confirm that these can both go into 4.4-stable? > > You could just remove the line: > > + .name = "xfs_dquot_ra", > > from 7d6a13f02356 and that will fix the backport problem and not > require any other commits to be backported. I'm fine with either > solution. > Great. Should be push that one to greg? Greets, Stefan From s.priebe@profihost.ag Fri Jun 3 12:56:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 7843A7CA0 for ; Fri, 3 Jun 2016 12:56:14 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2DE7E3040D6 for ; Fri, 3 Jun 2016 10:56:14 -0700 (PDT) X-ASG-Debug-ID: 1464976570-04bdf05ad5b327f0001-NocioJ Received: from mail-ph.de-nserver.de (mail-ph.de-nserver.de [85.158.179.214]) by cuda.sgi.com with ESMTP id 51SA7LEFYbHhfrBd (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 03 Jun 2016 10:56:11 -0700 (PDT) X-Barracuda-Envelope-From: s.priebe@profihost.ag X-Barracuda-Effective-Source-IP: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Apparent-Source-IP: 85.158.179.214 Received: (qmail 1320 invoked from network); 3 Jun 2016 19:56:10 +0200 X-Fcrdns: No Received: from phoffice.de-nserver.de (HELO [10.242.2.3]) (185.39.223.5) (smtp-auth username hostmaster@profihost.com, mechanism plain) by mail-ph.de-nserver.de (qpsmtpd/0.92) with (ECDHE-RSA-AES256-SHA encrypted) ESMTPSA; Fri, 03 Jun 2016 19:56:10 +0200 Subject: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage To: Dave Chinner X-ASG-Orig-Subj: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage References: <20160324122417.GB4068@bfoster.bfoster> <57332508.307@profihost.ag> <20160511133417.GA42410@bfoster.bfoster> <57333BA4.4040402@profihost.ag> <20160511155951.GF42410@bfoster.bfoster> <5738576B.4010208@profihost.ag> <20160515115017.GA6433@laptop.bfoster> <57386E84.3090606@profihost.ag> <20160516010602.GA24980@bfoster.bfoster> <57420A47.2000700@profihost.ag> <20160522213850.GE26977@dastard> Cc: Brian Foster , "xfs-masters@oss.sgi.com" , "xfs@oss.sgi.com" From: Stefan Priebe - Profihost AG Message-ID: <5751C4B8.2080301@profihost.ag> Date: Fri, 3 Jun 2016 19:56:08 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <20160522213850.GE26977@dastard> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-User-Auth: Auth by hostmaster@profihost.com through 185.39.223.5 X-Barracuda-Connect: mail-ph.de-nserver.de[85.158.179.214] X-Barracuda-Start-Time: 1464976571 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3398 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30145 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Hi, should i remove the complete if conditions incl. the return 0 or should id convert it to if without WARN_ONCE? like below? if (WARN_ON_ONCE(delalloc)) return 0; if (WARN_ON_ONCE(unwritten)) return 0; => if (delalloc) return 0; if (unwritten) return 0; Am 22.05.2016 um 23:38 schrieb Dave Chinner: > On Sun, May 22, 2016 at 09:36:39PM +0200, Stefan Priebe - Profihost AG wrote: >> Am 16.05.2016 um 03:06 schrieb Brian Foster: >>>> sd_mod ehci_pci ehci_hcd usbcore usb_common igb ahci i2c_algo_bit libahci >>>> i2c_core ptp mpt3sas pps_core raid_class scsi_transport_sas >>>> [Sun May 15 07:00:44 2016] CPU: 2 PID: 108 Comm: kswapd0 Tainted: G O >>>> 4.4.10+25-ph #1 >>> >>> How close is this to an upstream kernel? Upstream XFS? Have you tried to >>> reproduce this on an upstream kernel? >> >> It's a vanilla 4.4.10 + a new adaptec driver and some sched and wq >> patches from 4.5 and 4.6 but i can try to replace the kernel on one >> machine with a 100% vanilla one if this helps. > > Please do. > >>>> [295086.353473] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>> 0x52000 size 0x13d1c8 >>>> [295086.353476] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>> 0x53000 size 0x13d1c8 >>>> [295086.353478] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>> 0x54000 size 0x13d1c8 >>> ... >>>> [295086.567508] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>> 0xab000 size 0x13d1c8 >>>> [295086.567510] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>> 0xac000 size 0x13d1c8 >>>> [295086.567515] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>> 0xad000 size 0x13d1c8 >>>> >>>> The file to the inode number is: >>>> /var/lib/apt/lists/security.debian.org_dists_wheezy_updates_main_i18n_Translation-en >>>> >>> >>> xfs_bmap -v might be interesting here as well. >> >> # xfs_bmap -v >> /var/lib/apt/lists/security.debian.org_dists_wheezy_updates_main_i18n_Translation-en >> /var/lib/apt/lists/security.debian.org_dists_wheezy_updates_main_i18n_Translation-en: >> EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL >> 0: [0..2567]: 41268928..41271495 3 (374464..377031) 2568 > > So the last file offset with a block is 0x140e00. This means the > file is fully allocated. However, the pages inside the file range > are still marked delayed allocation. That implies that we've failed > to write the pages over a delayed allocation region after we've > allocated the space. > > That, in turn, tends to indicate a problem in page writeback - the > first page to be written has triggered delayed allocation of the > entire range, but then the subsequent pages have not been written > (for some as yet unknown reason). When a page is written, we map it > to the current block via xfs_map_at_offset(), and that clears both > the buffer delay and unwritten flags. > > This clearly isn't happening which means either the VFS doesn't > think the inode is dirty anymore, writeback is never asking for > these pages to be written, or XFs is screwing something up in > ->writepage. The XFS writepage code changed significantly in 4.6, so > it might be worth seeing if a 4.6 kernel reproduces this same > problem.... > > Cheers, > > Dave. > From holger@applied-asynchrony.com Fri Jun 3 14:30:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 1642B7CA0 for ; Fri, 3 Jun 2016 14:30:05 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id CF31B8F80B9 for ; Fri, 3 Jun 2016 12:30:01 -0700 (PDT) X-ASG-Debug-ID: 1464982197-04cb6c2db9b19ab0001-NocioJ Received: from mail02.iobjects.de (mail02.iobjects.de [188.40.134.68]) by cuda.sgi.com with ESMTP id yWKBWgA6LeqkAEhm (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 03 Jun 2016 12:29:58 -0700 (PDT) X-Barracuda-Envelope-From: holger@applied-asynchrony.com X-Barracuda-Effective-Source-IP: mail02.iobjects.de[188.40.134.68] X-Barracuda-Apparent-Source-IP: 188.40.134.68 Received: from tux.wizards.de (p4FF5801B.dip0.t-ipconnect.de [79.245.128.27]) by mail02.iobjects.de (Postfix) with ESMTPSA id 44E2A416014D for ; Fri, 3 Jun 2016 21:29:57 +0200 (CEST) Received: from [192.168.100.223] (ragnarok [192.168.100.223]) by tux.wizards.de (Postfix) with ESMTP id 65EEA11C01CF for ; Fri, 3 Jun 2016 21:29:56 +0200 (CEST) Subject: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 References: <57503353.2050402@profihost.ag> <57503D33.6010000@applied-asynchrony.com> <575040D8.8070903@applied-asynchrony.com> <20160602222545.GO12670@dastard> <5751C1B9.90709@profihost.ag> X-ASG-Orig-Subj: Re: _xfs_buf_ioapply: no ops on block 0x188e78/0x8 on vanilla 4.4.11 To: "xfs@oss.sgi.com" From: =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= Organization: Applied Asynchrony, Inc. Message-ID: <5751DAB4.40406@applied-asynchrony.com> Date: Fri, 3 Jun 2016 21:29:56 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <5751C1B9.90709@profihost.ag> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mail02.iobjects.de[188.40.134.68] X-Barracuda-Start-Time: 1464982198 X-Barracuda-Encrypted: DHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1342 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30147 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 06/03/16 19:43, Stefan Priebe - Profihost AG wrote: > Am 03.06.2016 um 00:25 schrieb Dave Chinner: >> On Thu, Jun 02, 2016 at 04:21:12PM +0200, Holger Hoffstätte wrote: >>> On 06/02/16 16:05, Holger Hoffstätte wrote: >>>> On 06/02/16 15:23, Stefan Priebe - Profihost AG wrote: >>>>> I found a bug report from redhat here >>>>> https://bugzilla.redhat.com/show_bug.cgi?id=1234586 pointing to this commit: >>>>> xfs: handle dquot buffer readahead in log recovery correctly >>>>> >>>>> which isn't part of 4.4. Is it missing from linux-stable? >>>> >>>> Yes, mainline 7d6a13f02356 is missing from 4.4-stable because it applies, >>>> but doesn't compile. :) >>>> >>>> I'll look into a fix. >>> >>> Well, that was easy. It also needs 233135b763 ("xfs: print name of verifier >>> if it fails") which added a .name to the various xfs_buf_ops types. >>> Can someone confirm that these can both go into 4.4-stable? >> >> You could just remove the line: >> >> + .name = "xfs_dquot_ra", >> >> from 7d6a13f02356 and that will fix the backport problem and not >> require any other commits to be backported. I'm fine with either >> solution. >> > > Great. Should be push that one to greg? You're too slow ;-) http://www.spinics.net/lists/stable/msg134549.html ..or steal them from my patch queue. -h From holger@applied-asynchrony.com Fri Jun 3 14:36:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 565077CA0 for ; Fri, 3 Jun 2016 14:36:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1717A304090 for ; Fri, 3 Jun 2016 12:36:01 -0700 (PDT) X-ASG-Debug-ID: 1464982558-04bdf05ad5b35440001-NocioJ Received: from mail02.iobjects.de (mail02.iobjects.de [188.40.134.68]) by cuda.sgi.com with ESMTP id FACOcj0yvCPKOnLB (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 03 Jun 2016 12:35:59 -0700 (PDT) X-Barracuda-Envelope-From: holger@applied-asynchrony.com X-Barracuda-Effective-Source-IP: mail02.iobjects.de[188.40.134.68] X-Barracuda-Apparent-Source-IP: 188.40.134.68 Received: from tux.wizards.de (p4FF5801B.dip0.t-ipconnect.de [79.245.128.27]) by mail02.iobjects.de (Postfix) with ESMTPSA id 469E6416014D for ; Fri, 3 Jun 2016 21:35:57 +0200 (CEST) Received: from [192.168.100.223] (ragnarok [192.168.100.223]) by tux.wizards.de (Postfix) with ESMTP id D188211C01CF for ; Fri, 3 Jun 2016 21:35:56 +0200 (CEST) Subject: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage References: <20160324122417.GB4068@bfoster.bfoster> <57332508.307@profihost.ag> <20160511133417.GA42410@bfoster.bfoster> <57333BA4.4040402@profihost.ag> <20160511155951.GF42410@bfoster.bfoster> <5738576B.4010208@profihost.ag> <20160515115017.GA6433@laptop.bfoster> <57386E84.3090606@profihost.ag> <20160516010602.GA24980@bfoster.bfoster> <57420A47.2000700@profihost.ag> <20160522213850.GE26977@dastard> <5751C4B8.2080301@profihost.ag> X-ASG-Orig-Subj: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage To: "xfs@oss.sgi.com" From: =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= Organization: Applied Asynchrony, Inc. Message-ID: <5751DC1C.5010909@applied-asynchrony.com> Date: Fri, 3 Jun 2016 21:35:56 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <5751C4B8.2080301@profihost.ag> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail02.iobjects.de[188.40.134.68] X-Barracuda-Start-Time: 1464982558 X-Barracuda-Encrypted: DHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 574 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30148 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 06/03/16 19:56, Stefan Priebe - Profihost AG wrote: > Hi, > > should i remove the complete if conditions incl. the return 0 or should > id convert it to if without WARN_ONCE? like below? > > if (WARN_ON_ONCE(delalloc)) > return 0; > if (WARN_ON_ONCE(unwritten)) > return 0; > > => > > if (delalloc) > return 0; > if (unwritten) > return 0; Good thing you ask, I forgot about the returns.. Until the bigger picture has been figured out with -mm I'd probably keep the returns. -h From david@fromorbit.com Fri Jun 3 19:05:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=unavailable version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9B8F67CA2 for ; Fri, 3 Jun 2016 19:05:48 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 33EF5AC019 for ; Fri, 3 Jun 2016 17:05:44 -0700 (PDT) X-ASG-Debug-ID: 1464998738-04bdf05ad4b3bd50001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id lwDB1Q6Hno5ro4nD; Fri, 03 Jun 2016 17:05:39 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CpCwB2GlJXKGSyLXlegzqBU4J2g3mfMwEBAQECBowrg1qCI4IPgXqGDAQCAoEzOxIBAQEBAQEBBgEBAQEBAUBAhEYBAQQ6HCMQCAMYCSUPBSUDBxoTiC7CYQEBCAIlHoVBhRWKGgEEmEWOGo8mRY8NJQ6CKBwWgUcqMooSAQEB Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail05.adl6.internode.on.net with ESMTP; 04 Jun 2016 09:34:49 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8z57-00067I-3H; Sat, 04 Jun 2016 10:04:49 +1000 Date: Sat, 4 Jun 2016 10:04:49 +1000 From: Dave Chinner To: Stefan Priebe - Profihost AG Cc: Brian Foster , "xfs-masters@oss.sgi.com" , "xfs@oss.sgi.com" Subject: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage Message-ID: <20160604000449.GU26977@dastard> X-ASG-Orig-Subj: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage References: <20160511133417.GA42410@bfoster.bfoster> <57333BA4.4040402@profihost.ag> <20160511155951.GF42410@bfoster.bfoster> <5738576B.4010208@profihost.ag> <20160515115017.GA6433@laptop.bfoster> <57386E84.3090606@profihost.ag> <20160516010602.GA24980@bfoster.bfoster> <57420A47.2000700@profihost.ag> <20160522213850.GE26977@dastard> <5751C4B8.2080301@profihost.ag> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <5751C4B8.2080301@profihost.ag> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1464998738 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 789 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30153 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 03, 2016 at 07:56:08PM +0200, Stefan Priebe - Profihost AG wrote: > Hi, > > should i remove the complete if conditions incl. the return 0 or should > id convert it to if without WARN_ONCE? like below? > > if (WARN_ON_ONCE(delalloc)) > return 0; > if (WARN_ON_ONCE(unwritten)) > return 0; > > => > > if (delalloc) > return 0; > if (unwritten) > return 0; Yes, you need to keep the checks and returns. That's what I meant when I said that "XFS handles the dirty page case correctly in this case". If the page is dirty, we should not be attempting to release the buffers, and that is what the code does. It's just noisy about it... Cheers, Dave. -- Dave Chinner david@fromorbit.com From gwendal@google.com Fri Jun 3 19:31:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0A4AC7CA0 for ; Fri, 3 Jun 2016 19:31:33 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 79707AC022 for ; Fri, 3 Jun 2016 17:31:32 -0700 (PDT) X-ASG-Debug-ID: 1465000287-04bdf05ad7b3c4c0001-NocioJ Received: from mail-pa0-f46.google.com (mail-pa0-f46.google.com [209.85.220.46]) by cuda.sgi.com with ESMTP id AOAnBBuWwFPvgUfV (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 03 Jun 2016 17:31:28 -0700 (PDT) X-Barracuda-Envelope-From: gwendal@google.com X-Barracuda-Effective-Source-IP: mail-pa0-f46.google.com[209.85.220.46] X-Barracuda-Apparent-Source-IP: 209.85.220.46 Received: by mail-pa0-f46.google.com with SMTP id ec8so12730850pac.0 for ; Fri, 03 Jun 2016 17:31:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=fjqSpHuuYs0o1fiLBm2tUa0AtvsLUMGvVaJArdnZ3u0=; b=FgQC1WkNuqme98Z0DxOa/4AARoAQVCSIpzQvZyfc7fxZkHolXrm4Tj7AFqQnmaTw73 ieuNYl239Joe9bfhPZUb2rhnivvkDOM0LxwH3itQq7BbhaOu9qcuhwv6FLf66+takKuC aqXZaT1rimLNPpv0L6NNCZGN0g/4ecJFYUQdbQP8QQXVWQLKDIIcLJV/Li5PoKjhe0zf dGh59GNN+/K7MtQEDnCO6/MpjNL0faZ8Ij4sLCeIaGSli8woBXtbhkR7fRJZ41xHE7uY qXqlbaMV5AD7Xu9Q6hLMfKlyfbvwXlLIQ6F7qOOE3/uT7uD6Coe8fhqhZOXQSh0hiVyQ ZJxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=fjqSpHuuYs0o1fiLBm2tUa0AtvsLUMGvVaJArdnZ3u0=; b=PX0hK9QCB3O5L8wIsZ4RbstOha+IfUNnrqFkCOTgbyDJ3m+sWeYU7CaZB0TufESxAv ylOdHDc0mdEPMBHWBuB5ekjKDqPGpzkmK2VlfOCwiF0eChysjaTuw5fO2A39pvMbioH/ YbphM2dXNvM7icnqCIiTBjdfWKWS2OpxD57dojytXOIrLkyH04RpouJDmQH13d1xwqOF p1KX0FUUt0BfTD+EsL1hSLvX69AZzwoT4cNW8H/EbSQw73o4HjEjiCFk8KC64Kg0YTZz BsQcpm+JdU1uZByKYZGjn79vWytu8Nqq7+jWvx2Zqq+dJJR6w85rY3etlvU0x2kI3Km7 KQUg== X-Gm-Message-State: ALyK8tLungq3oRiyO+h/MpCfns2DeN8W1FTu0v0zfZWCdxFF774JIvypEzyX7quhmixOK6fp X-Received: by 10.66.73.138 with SMTP id l10mr1155416pav.92.1465000287130; Fri, 03 Jun 2016 17:31:27 -0700 (PDT) Received: from gwendal.mtv.corp.google.com ([172.22.64.242]) by smtp.gmail.com with ESMTPSA id fn3sm8502842pab.20.2016.06.03.17.31.25 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 03 Jun 2016 17:31:25 -0700 (PDT) Sender: Gwendal Grignou From: Gwendal Grignou To: hch@infradead.org Cc: tytso@mit.edu, fstests@vger.kernel.org, xfs@oss.sgi.com, vapier@gentoo.org Subject: [PATCH] Allow compiling xfsprogs in a cross compile environment. Date: Fri, 3 Jun 2016 17:31:16 -0700 X-ASG-Orig-Subj: [PATCH] Allow compiling xfsprogs in a cross compile environment. Message-Id: <1465000276-16554-1-git-send-email-gwendal@chromium.org> X-Mailer: git-send-email 2.1.2 In-Reply-To: References: X-Barracuda-Connect: mail-pa0-f46.google.com[209.85.220.46] X-Barracuda-Start-Time: 1465000287 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5216 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30154 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature Without this patch, we are using the same compiler and options for the host compiler (BUILD_CC) and the target compiler (CC), and we would get error messages at compilation: x86_64-pc-linux-gnu-gcc -O2 -O2 -pipe -march=armv7-a -mtune=cortex-a15 ... x86_64-pc-linux-gnu-gcc.real: error: unrecognized command line option '-mfpu=neon' '-mfloat-abi=hard' '-clang-syntax' '-mfpu=neon' '-mfloat-abi=hard' '-clang-syntax' Add BUILD_CC and BUILD_CFLAGS as precious variables to allow setting it up from the ebuild. Signed-off-by: Gwendal Grignou --- This patch issue has been pushed into gentoo as well: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=8806f22bf65d99348770bbb6207d199c74fd96c5 configure | 26 +++++++++++++++++++++----- configure.ac | 20 +++++++++++++++----- include/builddefs.in | 6 ++++-- libxfs/Makefile | 4 ++-- 4 files changed, 42 insertions(+), 14 deletions(-) diff --git a/configure b/configure index 325081f..863a447 100755 --- a/configure +++ b/configure @@ -700,6 +700,7 @@ libreadline enable_blkid enable_gettext enable_shared +BUILD_CFLAGS BUILD_CC CPP LT_SYS_LIBRARY_PATH @@ -806,7 +807,9 @@ LDFLAGS LIBS CPPFLAGS LT_SYS_LIBRARY_PATH -CPP' +CPP +BUILD_CC +BUILD_CFLAGS' # Initialize some variables set by options. @@ -1456,6 +1459,9 @@ Some influential environment variables: LT_SYS_LIBRARY_PATH User-defined run-time library search path. CPP C preprocessor + BUILD_CC C compiler for build tools + BUILD_CFLAGS + C compiler flags for build tools Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -11957,11 +11963,12 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test $cross_compiling = no; then - BUILD_CC="$CC" -else - for ac_prog in gcc cc +if test "${BUILD_CC+set}" != "set"; then + if test $cross_compiling = no; then + BUILD_CC="$CC" + else + for ac_prog in gcc cc do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -12003,6 +12010,15 @@ fi test -n "$BUILD_CC" && break done + fi +fi + +if test "${BUILD_CFLAGS+set}" != "set"; then + if test $cross_compiling = no; then + BUILD_CFLAGS="$CFLAGS" + else + BUILD_CFLAGS="-g -O2" + fi fi # Check whether --enable-shared was given. diff --git a/configure.ac b/configure.ac index d44438f..fc286b3 100644 --- a/configure.ac +++ b/configure.ac @@ -9,11 +9,21 @@ AC_PREFIX_DEFAULT(/usr) AC_PROG_LIBTOOL AC_PROG_CC -if test $cross_compiling = no; then - BUILD_CC="$CC" - AC_SUBST(BUILD_CC) -else - AC_CHECK_PROGS(BUILD_CC, gcc cc) +AC_ARG_VAR(BUILD_CC, [C compiler for build tools]) +if test "${BUILD_CC+set}" != "set"; then + if test $cross_compiling = no; then + BUILD_CC="$CC" + else + AC_CHECK_PROGS(BUILD_CC, gcc cc) + fi +fi +AC_ARG_VAR(BUILD_CFLAGS, [C compiler flags for build tools]) +if test "${BUILD_CFLAGS+set}" != "set"; then + if test $cross_compiling = no; then + BUILD_CFLAGS="$CFLAGS" + else + BUILD_CFLAGS="-g -O2" + fi fi AC_ARG_ENABLE(shared, diff --git a/include/builddefs.in b/include/builddefs.in index c2ca4cb..9ca57a6 100644 --- a/include/builddefs.in +++ b/include/builddefs.in @@ -27,6 +27,7 @@ MALLOCLIB = @malloc_lib@ LOADERFLAGS = @LDFLAGS@ LTLDFLAGS = @LDFLAGS@ CFLAGS = @CFLAGS@ +BUILD_CFLAGS = @BUILD_CFLAGS@ LIBRT = @librt@ LIBUUID = @libuuid@ @@ -150,7 +151,7 @@ PCFLAGS+= -DENABLE_BLKID endif -GCFLAGS = $(OPTIMIZER) $(DEBUG) \ +GCFLAGS = $(DEBUG) \ -DVERSION=\"$(PKG_VERSION)\" -DLOCALEDIR=\"$(PKG_LOCALE_DIR)\" \ -DPACKAGE=\"$(PKG_NAME)\" -I$(TOPDIR)/include -I$(TOPDIR)/libxfs @@ -158,8 +159,9 @@ ifeq ($(ENABLE_GETTEXT),yes) GCFLAGS += -DENABLE_GETTEXT endif +BUILD_CFLAGS += $(GCFLAGS) $(PCFLAGS) # First, Global, Platform, Local CFLAGS -CFLAGS += $(FCFLAGS) $(GCFLAGS) $(PCFLAGS) $(LCFLAGS) +CFLAGS += $(FCFLAGS) $(OPTIMIZER) $(GCFLAGS) $(PCFLAGS) $(LCFLAGS) include $(TOPDIR)/include/buildmacros diff --git a/libxfs/Makefile b/libxfs/Makefile index 873d4ec..8d728c0 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -111,7 +111,7 @@ default: crc32selftest ltdepend $(LTLIBRARY) crc32table.h: gen_crc32table.c @echo " [CC] gen_crc32table" - $(Q) $(BUILD_CC) $(CFLAGS) -o gen_crc32table $< + $(Q) $(BUILD_CC) $(BUILD_CFLAGS) -o gen_crc32table $< @echo " [GENERATE] $@" $(Q) ./gen_crc32table > crc32table.h @@ -122,7 +122,7 @@ crc32table.h: gen_crc32table.c # disk. crc32selftest: gen_crc32table.c crc32table.h crc32.c @echo " [TEST] CRC32" - $(Q) $(BUILD_CC) $(CFLAGS) -D CRC32_SELFTEST=1 crc32.c -o $@ + $(Q) $(BUILD_CC) $(BUILD_CFLAGS) -D CRC32_SELFTEST=1 crc32.c -o $@ $(Q) ./$@ # set up include/xfs header directory -- 2.8.0.rc3.226.g39d4020 From david@fromorbit.com Fri Jun 3 19:33:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id CE6567CA0 for ; Fri, 3 Jun 2016 19:33:22 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 902FE3040CB for ; Fri, 3 Jun 2016 17:33:19 -0700 (PDT) X-ASG-Debug-ID: 1465000396-04bdf05ad7b3c530001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id EAObp43X319BIR8j for ; Fri, 03 Jun 2016 17:33:16 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2ANEwBSIVJXKGSyLXlegzqBU4J2g3mfMwEBAQECBowrhX2CD4F6hgwCAgEBAoEzOxIBAQEBAQEBBgEBAQEBAUBAQRABg3MBAQEDASMPASMjBQsIAw4KAgIFIQICDwUlAwcaE4gnB7FPkRkBAQgCASQeY4RehRWEEYMwglkFjWaKX44ajyaPUiUCgjQcgV0qMoNohioBAQE Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail05.adl6.internode.on.net with ESMTP; 04 Jun 2016 10:03:00 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b8zWN-0006AH-Qf; Sat, 04 Jun 2016 10:32:59 +1000 Date: Sat, 4 Jun 2016 10:32:59 +1000 From: Dave Chinner To: Jan Tulak Cc: xfs-oss , Eric Sandeen Subject: Re: [PATCH 00/19 v2] mkfs cleaning Message-ID: <20160604003259.GV26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 00/19 v2] mkfs cleaning References: <1461231593-31294-1-git-send-email-jtulak@redhat.com> <20160510061054.GI26977@dastard> <20160603005324.GS12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1465000396 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1998 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30154 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 03, 2016 at 02:09:19PM +0200, Jan Tulak wrote: > [ > ​snip all, another issue, unrelated to the lsunit one]​ > > > > ​I realised one small glitch with conflicts watching in the code in > combination with flags. It is not regression, I think, because b​efore now, > it was not possible to do something like -l internal=0,logdev=something, > but now it should be possible. I think that overly complicates things. My original intent for this work was to simplify the interface and code, not make it more elaborate to support configurations that are theoretically possible but completely redundant. i.e. '-l internal=0,logdev=something' is identical in function to '-l logdev=something', so there is no need to specify internal=0. AFAICT, therxp eis never a need to specify '-l internal=[0|1]' because if '-l logdev=' is specified, it implies an external log is being configured, and in every other case the log is internal. > The code checks only whether an option was seen, not its value, so it > does't know that we are in fact disabling something. I see two ways how to > do solve it. One is a custom conflict solving for these cases, putting some > if (flag1 && option2) somewhere once every argument and option is parsed. > But this goes against what the patchset did and moves it again out of the > option table... > > The other way is to make a special case for flags in the conflicts-handling > code. Basically, I would extend the structure with something like: > > { .index = L_INTERNAL, > .conflicts = { L_FILE, > L_DEV, > LAST_CONFLICT }, > .conflicts_ignore_on_false=true, // new item, shorter name to be found What happens when you have two conflicts, on which you want to ignore on false, the other you want to ignore on true? And where do you draw the line? L_SU vs L_SUNIT conflict and throw an error only when the values differ? Cheers, Dave. -- Dave Chinner david@fromorbit.com From vapier@gentoo.org Fri Jun 3 19:43:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D18957CA0 for ; Fri, 3 Jun 2016 19:43:28 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5D124AC01F for ; Fri, 3 Jun 2016 17:43:28 -0700 (PDT) X-ASG-Debug-ID: 1465001006-04bdf05ad5b3c920001-NocioJ Received: from smtp.gentoo.org (smtp.gentoo.org [140.211.166.183]) by cuda.sgi.com with ESMTP id kz7TwkVy5J4qRb42 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 03 Jun 2016 17:43:26 -0700 (PDT) X-Barracuda-Envelope-From: vapier@gentoo.org X-Barracuda-Effective-Source-IP: smtp.gentoo.org[140.211.166.183] X-Barracuda-Apparent-Source-IP: 140.211.166.183 Received: from vapier.lan (localhost [127.0.0.1]) by smtp.gentoo.org (Postfix) with SMTP id 7F2AF340B0B; Sat, 4 Jun 2016 00:43:25 +0000 (UTC) Date: Fri, 3 Jun 2016 20:43:25 -0400 From: Mike Frysinger To: Gwendal Grignou Cc: hch@infradead.org, tytso@mit.edu, fstests@vger.kernel.org, xfs@oss.sgi.com Subject: Re: [PATCH] Allow compiling xfsprogs in a cross compile environment. Message-ID: <20160604004325.GZ7717@vapier.lan> X-ASG-Orig-Subj: Re: [PATCH] Allow compiling xfsprogs in a cross compile environment. Mail-Followup-To: Gwendal Grignou , hch@infradead.org, tytso@mit.edu, fstests@vger.kernel.org, xfs@oss.sgi.com References: <1465000276-16554-1-git-send-email-gwendal@chromium.org> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="9+ohdFDUqiMJzwPo" Content-Disposition: inline In-Reply-To: <1465000276-16554-1-git-send-email-gwendal@chromium.org> X-Barracuda-Connect: smtp.gentoo.org[140.211.166.183] X-Barracuda-Start-Time: 1465001006 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 58 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30154 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header --9+ohdFDUqiMJzwPo Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Reviewed-by: Mike Frysinger -mike --9+ohdFDUqiMJzwPo Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAEBCAAGBQJXUiQsAAoJEEFjO5/oN/WBv2IP/Az8W7bMSzhiVcH/yT6UC98J dGZrsP7meey44BCojV1TVfgaKEF2nzYAv9396wchEkKqOD4hb93dd4IZ2Ir75kX/ 2ob4DQoBv/PmVRhvHvLfUVhTWUm7ax4L8dwmqQ5XEhHc0GApnSlZjFpVFuvUied/ GyorBn3CvQ9v7NhIoF0esDc+4k2YeflHhyVNZ8YSMbTqW7Sj70Dk5qXEx/IKn2fU gHys/cdQKq15vD9v5JNXwalap+UAtwJAEAmj3K1OnJVL9/nAUxtOUQkwe7+JEj8C /Kd4TwXZC6Kj7YXqqBWkfW9DTTOUY1ovkeYx6B+xw6Tcfnu+HsBCNrDc8enFweeN +bwYQFnNGumtojGRSwckiqPZvHR4zaFSH2v8Xx7K4GWEWNQqbFD4y5pL8DSQHd6r 6mGomYv6yPxoJRI8LqF+eBGQTfduno0ZV5tgneCOpeoET1uSJZdpzMA8gy/0731X mr2tmZgdjX1ri11Et+eopv6RdhoWB6jADDjbYUbQ9aS+F7AC1klZ0OuexbO4zxUI b/AYkRu396a+wtMlXbM+/sd6LV7NR9/4HgtkeZ1dwJ/1TwDOrJekuAaRTOjidih5 OW1ONx+DojASxKizPZGNj9DrvS+p21+hcnGMDiGuI9vYddS2cnzswxF0PO/NGGXW GF5mrtgCjhqi+hGa3p+M =bRrJ -----END PGP SIGNATURE----- --9+ohdFDUqiMJzwPo-- From darrick.wong@oracle.com Fri Jun 3 19:48:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A412C7CA0 for ; Fri, 3 Jun 2016 19:48:10 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5C497304081 for ; Fri, 3 Jun 2016 17:48:10 -0700 (PDT) X-ASG-Debug-ID: 1465001287-04cb6c2dbcb20f50001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id gzfEN47xppd0tzAi (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 03 Jun 2016 17:48:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u540lYxZ009998 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 4 Jun 2016 00:47:35 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u540lYri029287 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 4 Jun 2016 00:47:34 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u540lVA1006846; Sat, 4 Jun 2016 00:47:32 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 03 Jun 2016 17:47:31 -0700 Date: Fri, 3 Jun 2016 17:47:30 -0700 From: "Darrick J. Wong" To: david@fromorbit.com Cc: Christoph Hellwig , xfs@oss.sgi.com, bfoster@redhat.com Subject: June 2016 XFS reverse-mapping, reflink, and online fs scrub Message-ID: <20160604004730.GA5737@birch.djwong.org> X-ASG-Orig-Subj: June 2016 XFS reverse-mapping, reflink, and online fs scrub References: <20160505202502.GA7297@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160505202502.GA7297@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1465001287 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1554 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30154 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Hi all, Time for my monthly rmap+reflink code dump to github! Kernel patches are against 4.6.0, and xfsprogs patches are against ... 4.5. xfs/128 still fails when rmap is enabled. On the plus side, CoW and reflink remapping is now atomic! For rmap, I also moved the 'unwritten' bit out of the rm_blockcount field so that we can use all 32 bits. I've fixed numerous silly bugs in xfs_repair dealing with incorrect key handling, and worked in some large(ish) performance improvements. I also put in some tests that inject errors into the deferred op finishing code so that we can crash the FS at various points during a remapping multi-transaction to check that the redo items actually work. I plan to rebase the whole mess against 4.7-rc and for-next when I get a chance; and properly integrate the new patches into the start of the patchbomb. (342 patches is a bit much). The remaining work items are to make sure that quota accounting works acceptably, fix swapext when rmap is enabled, investigate caching the "is shared?" information in core to speed up reflink, and fixing performance problems. Maybe more scrub work too some day. Christoph: I've put in all your patches that you've sent me. --D Code-bomb: https://github.com/djwong/linux/commits/djwong-devel https://github.com/djwong/xfsprogs/commits/djwong-devel https://github.com/djwong/xfstests/commits/djwong-devel https://github.com/djwong/xfs-documentation/commits/djwong-devel https://github.com/djwong/man-pages/commits/djwong-devel From tireman@shaw.ca Fri Jun 3 21:28:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 857F97CA0 for ; Fri, 3 Jun 2016 21:28:55 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 44FB73040A4 for ; Fri, 3 Jun 2016 19:28:52 -0700 (PDT) X-ASG-Debug-ID: 1465007329-04bdf05ad7b3f1d0001-NocioJ Received: from smtp-out-so.shaw.ca (smtp-out-so.shaw.ca [64.59.136.139]) by cuda.sgi.com with ESMTP id m3eeovh3GD2tGqjI (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 03 Jun 2016 19:28:50 -0700 (PDT) X-Barracuda-Envelope-From: tireman@shaw.ca X-Barracuda-Effective-Source-IP: smtp-out-so.shaw.ca[64.59.136.139] X-Barracuda-Apparent-Source-IP: 64.59.136.139 Received: from [192.168.0.3] ([174.5.120.103]) by shaw.ca with SMTP id 91KRbDstcBLFm91KSbEzCN; Fri, 03 Jun 2016 20:28:49 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shaw.ca; s=s20150330; t=1465007329; bh=wzJHA4TFdpmsxLeBXmNwpPJQDg+5exBTuzasiE+rKpE=; h=From:Subject:To:References:Cc:Date:In-Reply-To; b=VDjFwSglD4ablUAGWH0077HskMjgb+APcTg+De+MAZLYwlJcxcI8BgUCAgh46HhSs VTehGSPrHiBWjjal51qoD8TflhnX1u5Pd1GFKjFZCmxaY3LjTzF+SRA2wwe+a2yLU8 gZTe61UQAd+kPYHL9zakvaDH9Azxvt9eDozJrIbOsttV1KM+DcLBxI/SKouUtL2lUa C/nifbqA4v8Atf9eJjCN/TbQgUxnpbUJRxw/JxA//deGiKOB1B9m2hhpHRmV8ZJFiW +fbmkWhyrIqtpiC4uQn19j9yAjrSI49oJM3qRHslfVCPrMOB6SSo9ez/iIxYA889Fd Rqr9rMuuylHsA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shaw.ca; s=s20150330; t=1465007329; bh=wzJHA4TFdpmsxLeBXmNwpPJQDg+5exBTuzasiE+rKpE=; h=From:Subject:To:References:Cc:Date:In-Reply-To; b=VDjFwSglD4ablUAGWH0077HskMjgb+APcTg+De+MAZLYwlJcxcI8BgUCAgh46HhSs VTehGSPrHiBWjjal51qoD8TflhnX1u5Pd1GFKjFZCmxaY3LjTzF+SRA2wwe+a2yLU8 gZTe61UQAd+kPYHL9zakvaDH9Azxvt9eDozJrIbOsttV1KM+DcLBxI/SKouUtL2lUa C/nifbqA4v8Atf9eJjCN/TbQgUxnpbUJRxw/JxA//deGiKOB1B9m2hhpHRmV8ZJFiW +fbmkWhyrIqtpiC4uQn19j9yAjrSI49oJM3qRHslfVCPrMOB6SSo9ez/iIxYA889Fd Rqr9rMuuylHsA== X-Authority-Analysis: v=2.2 cv=W5d6blek c=1 sm=1 tr=0 a=p2XoxBGfiVgixJHHDgKfSQ==:117 a=p2XoxBGfiVgixJHHDgKfSQ==:17 a=IkcTkHD0fZMA:10 a=9wYxZL4EAAAA:20 a=Sqk-MOYxAAAA:20 a=xBWF7wlVAAAA:20 a=uD6-8160AAAA:20 a=0RGs6xqVecw1MUq6YiUA:9 a=E6LPTDj9DoQ12ICq:21 a=5NnF_LXB8V_ur5m3:21 From: Andrew Ryder Subject: Re: xfs_repair fails after trying to format log cycle? To: Dave Chinner X-ASG-Orig-Subj: Re: xfs_repair fails after trying to format log cycle? References: <56F6DE67.60403@shaw.ca> <20160328085541.GA27040@bfoster.bfoster> <570C8D4D.3060304@shaw.ca> <20160412140512.GA59690@bfoster.bfoster> <570D578D.5010706@shaw.ca> <570DB6CD.1000007@shaw.ca> <20160413045129.GO567@dastard> Cc: Brian Foster , xfs@oss.sgi.com Message-ID: <57523CE6.7020906@shaw.ca> Date: Fri, 3 Jun 2016 22:28:54 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <20160413045129.GO567@dastard> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-CMAE-Envelope: MS4wfIqF/G5nWvMpgH58oG4rXc6D02v9leArNX0HC7O7UvzrbpG36vMQC2jUzUsp8y/AAQMnLfIkbNHQ+mOWMXTIQcn31fsJ6vngcxrR+mWFBoj2okZcPOk7 /1ZQRKedTfezqNeOOAdi3Ua7Rj69en2AsyDqEoFawkIODhuVM0h9VRcs990kkzhKMX7LHa1swsegUWh6BnzGR+vfG6mmDOWozAY1Hk0lQrbT0Ay4oCatHZ23 X-Barracuda-Connect: smtp-out-so.shaw.ca[64.59.136.139] X-Barracuda-Start-Time: 1465007329 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2766 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30156 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature Sorry to dig up old stuff here but after replacing hardware and pulling my hair out to no end, I traced the source of the problem out. On every drive in the array, the points on the PCB which the contacts for the drives motors and head/actuators make contact with were oxidized enough to cause the issue. I ended up pulling the PCB off each drive and cleaning them as well as cleaning out all other cable and drive connectors from the HBA outward and everything is happy again. http://s33.postimg.org/uhjmvw4dr/Not_Cleaned.jpg http://s33.postimg.org/xo94ieii7/Partial_Cleaned_1.jpg http://s33.postimg.org/hoqgyumgf/Partial_Cleaned_2.jpg http://s33.postimg.org/68k20t8a7/Partial_Cleaned_3.jpg On 04/13/2016 12:51 AM, Dave Chinner wrote: > On Tue, Apr 12, 2016 at 11:02:37PM -0400, Andrew Ryder wrote: >> Is it possible the location its searching for at block >> >> 02:34:43.887528 pread64(4, 0x7fb8f53e0200, 2097152, 3001552175104) = >> -1 EIO (Input/output error) > > so offset is 3001552175104, or roughly around the 3TB mark. Given > the log i always placed int eh middle of the filesystem and you have > a 6TB device, then the above definitely looks like a valid place to > be reading from the log. > >> xfs_logprint: >> data device: 0x902 >> log device: 0x902 daddr: 5860130880 length: 4173824 > > daddr converted to offset is 5860130880 * 512 = 3001552175104, which > tells us that the above pread64 failure was definitely coming from > an attempt to read the log. > > That this is coming from the block device from userspace indicates a > problem below XFS. There is something going wrong with your > underlying block device and/or hardware here; AFAICT it's not > related to XFS at all. > >>> GNU Parted 3.2 >>> Using /dev/sdk >>> Welcome to GNU Parted! Type 'help' to view a list of commands. >>> (parted) p >>> Model: ATA ST2000DL001-9VT1 (scsi) >>> Disk /dev/sdk: 2000GB >>> Sector size (logical/physical): 512B/512B >>> Partition Table: msdos >>> Disk Flags: >>> >>> Number Start End Size Type File system Flags >>> 1 512B 2000GB 2000GB primary raid >>> Number Start End Size Type File system Flags >>> 1 1s 3907029167s 3907029167s primary raid > > Compared to the other devices, it has a different start sector, a > different size, and an msdos partition table rather than gpt. > Definitely a red flag... > >>>>> This all began when the RR2722 driver running under 3.18.15 >>>>> complained and > > Reported physical IO errors to a write command. Really, this looks > like a hardware issue, not something that can be fixed by running > xfs_repair... > > Cheers, > > Dave. > From ben@decadent.org.uk Sat Jun 4 12:11:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 15ECB7CA0 for ; Sat, 4 Jun 2016 12:11:26 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 76F28AC023 for ; Sat, 4 Jun 2016 10:11:22 -0700 (PDT) X-ASG-Debug-ID: 1465060278-04cbb0356bb62dd0001-NocioJ Received: from shadbolt.e.decadent.org.uk (shadbolt.e.decadent.org.uk [88.96.1.126]) by cuda.sgi.com with ESMTP id FLTq5BgPUHsqROoP (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Sat, 04 Jun 2016 10:11:19 -0700 (PDT) X-Barracuda-Envelope-From: ben@decadent.org.uk X-Barracuda-Effective-Source-IP: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Apparent-Source-IP: 88.96.1.126 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1b9F6R-0000iY-Lk; Sat, 04 Jun 2016 18:11:15 +0100 Received: from ben by deadeye with local (Exim 4.87) (envelope-from ) id 1b9F6R-0003Tt-Hb; Sat, 04 Jun 2016 18:11:15 +0100 Message-ID: <1465060270.2847.149.camel@decadent.org.uk> Subject: Re: XFS hole punch races From: Ben Hutchings X-ASG-Orig-Subj: Re: XFS hole punch races To: Jan Kara , stable@vger.kernel.org Cc: xfs@oss.sgi.com, Dave Chinner Date: Sat, 04 Jun 2016 18:11:10 +0100 In-Reply-To: <20160322155740.GB28772@quack.suse.cz> References: <20160322155740.GB28772@quack.suse.cz> Content-Type: multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature"; boundary="=-DkW9dkZvWpfg5goUO7kh" X-Mailer: Evolution 3.20.2-2 Mime-Version: 1.0 X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false X-Barracuda-Connect: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Start-Time: 1465060278 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1327 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30168 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header --=-DkW9dkZvWpfg5goUO7kh Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, 2016-03-22 at 16:57 +0100, Jan Kara wrote: Hi, similarly to ext4 also XFS had races between hole punching and page faults which could result in data corruption. The fixes were merged in 4.1-rc1 but it might make sense to backport them to older stable releases given the nature of the issue. Relevant fixes are: de0e8c20ba3a65b0f15040aabbefdc1999876e6b 075a924d45cc69c75a35f20b4912b85aa98b180a e8e9ad42c1f1e1bfbe0e8c32c8cac02e9ebfb7ef 0f9160b444e4de33b65dfcd3b901358a3129461a 723cac48473358939759885a18e8df113ea96138 ec56b1f1fdc69599963574ce94cc5693d535dd64 You missed the first in that sequence: 653c60b633a9 xfs: introduce mmap/truncate lock For 3.16, I've queued up all=C2=A0those fixes with one further=C2=A0prerequ= isite: 812176832169 xfs: fix swapext ilock deadlock For 3.2, I've queued up all but 723cac484733, with these additional prerequisites: f38996f57687 xfs: reduce ilock hold times in xfs_setattr_size bc4010ecb8f4 xfs: use iolock on XFS_IOC_ALLOCSP calls 76ca4c238cf5 xfs: always take the iolock around xfs_setattr_size 5f8aca8b43f4 xfs: always hold the iolock when calling xfs_change_file_space I realise I'll need to check for regressions with xfstests. Ben. --=20 Ben Hutchings The most exhausting thing in life is being insincere. - Anne Morrow Lindberg --=-DkW9dkZvWpfg5goUO7kh Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCgAGBQJXUwuuAAoJEOe/yOyVhhEJYTMP/1d8PwM5Xw+FrAnZd7znk5ZY HLa3GV5PBB1joWQsk4mttnzKnaHdKQNmVIDlN1f0Z5vg7BDnBqLj98R0idNkBLOo 1ZXQ7IEj4BHMtGPqyIj3cZk+E+hfkenI72LXrNaRmELCRsTX2mNwzJ+O2vvDYY6t EuYxZymHujVaGyU55sjszMN9XkfZKlyF6ZV1Duq0qA7Wwuv57Meb+6oCoevZusIG s+UX0L9uOrA136kiW9XROIdeTzlWcwd0I0Y0atqQ2rsPnzzBJip40KW+SsJjzJWN LYSBIOHGYPHsuw7U+GfEzffxmjPi9MN6qlI7/E8jc/M7rCgQOnJDlRMzXT3L+MwV UsQFzJfcAECVoxB9Xikksa8YF+NYOEtha+zuyMdhJKnpZOtWmdl8AAL8IuXSCyPi kTIMe4X25aFjcfEcMVfgAaJOw1Zhxw63oq2/lLmFgU4/PYOcQ9VApYf6VA6c1uCT D1GIqxBWo/QW3Yk4e/Z05KFOumRqP3nfCULDpAEHDStkaG44JHKcAyWJBKSEmlVH KfrUQZ/KIPjyuEWOWcK2RN26MwXNKbrUitRG390yY+LrsvXyil8Ezinj07xAbm2C R/Ra81nvYB3OhcxBJPp/FY+pLJP2KQ17RPGUFxLZNXwZkcdTP9JhXmNTT5GOUwNG 5zXfEUaTCBaKj+Oin/CZ =VpAB -----END PGP SIGNATURE----- --=-DkW9dkZvWpfg5goUO7kh-- From david@fromorbit.com Sat Jun 4 18:28:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A5BDA7CA0 for ; Sat, 4 Jun 2016 18:28:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6707F304039 for ; Sat, 4 Jun 2016 16:28:10 -0700 (PDT) X-ASG-Debug-ID: 1465082882-04bdf05ad6b5e9b0001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id A1kXLYSTPoqev1rl for ; Sat, 04 Jun 2016 16:28:03 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DaBgCoYlNXKGSyLXlegzqBU4J2g3mfMAECAQEBBowriA2BeoYMBAICgRs5FAEBAQEBAQEGAQEBAQFBQIRGAQEEMgEjIxAIAxgJJQ8FJQMHGhOILrpyAQEIJx6FQYUVihoFmEiOHI8oj1oehDYqMoljAQEB Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail05.adl6.internode.on.net with ESMTP; 05 Jun 2016 08:58:01 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b9Kz2-0007ta-6P; Sun, 05 Jun 2016 09:28:00 +1000 Date: Sun, 5 Jun 2016 09:28:00 +1000 From: Dave Chinner To: Ben Hutchings Cc: Jan Kara , stable@vger.kernel.org, xfs@oss.sgi.com Subject: Re: XFS hole punch races Message-ID: <20160604232800.GW26977@dastard> X-ASG-Orig-Subj: Re: XFS hole punch races References: <20160322155740.GB28772@quack.suse.cz> <1465060270.2847.149.camel@decadent.org.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <1465060270.2847.149.camel@decadent.org.uk> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1465082882 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2461 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30173 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Sat, Jun 04, 2016 at 06:11:10PM +0100, Ben Hutchings wrote: > On Tue, 2016-03-22 at 16:57 +0100, Jan Kara wrote: > > Hi, > > similarly to ext4 also XFS had races between hole punching and page faults > which could result in data corruption. The fixes were merged in 4.1-rc1 but > it might make sense to backport them to older stable releases given the > nature of the issue. > > Relevant fixes are: > > de0e8c20ba3a65b0f15040aabbefdc1999876e6b > 075a924d45cc69c75a35f20b4912b85aa98b180a > e8e9ad42c1f1e1bfbe0e8c32c8cac02e9ebfb7ef > 0f9160b444e4de33b65dfcd3b901358a3129461a > 723cac48473358939759885a18e8df113ea96138 > ec56b1f1fdc69599963574ce94cc5693d535dd64 > > > You missed the first in that sequence: > > 653c60b633a9 xfs: introduce mmap/truncate lock > > For 3.16, I've queued up allthose fixes with one furtherprerequisite: > > 812176832169 xfs: fix swapext ilock deadlock > > For 3.2, I've queued up all but 723cac484733, with these additional > prerequisites: > > f38996f57687 xfs: reduce ilock hold times in xfs_setattr_size > bc4010ecb8f4 xfs: use iolock on XFS_IOC_ALLOCSP calls > 76ca4c238cf5 xfs: always take the iolock around xfs_setattr_size > 5f8aca8b43f4 xfs: always hold the iolock when calling xfs_change_file_space > I realise I'll need to check for regressions with xfstests. Hi Ben, You do realise that this sort of backport effectively makes the stable kernels unsupportable by the upstream XFS developers? You're taking random changes from the upstream kernel until the kernel compiles, and then mostly hoping that it works. It's trivially easy to break truncate by screwing up the locking and IO barriers that it depends on, and this set of patches make quite a lot of different changes that have an unknown set of dependencies for correct behaviour. xfstests won't find all those problems; at best it will tell us that there won't be obvious problems. Stable kernels are supposed to be stable, and backports like this are riskier than the original changes in the upstream kernels. if a user is hitting a mmap/hole-punch race on an XFS filesytem (I can't remember any reports to the upstream list for any kernel) on a 3.2 kernel, then correct answer is "upgrade to a newer upstream kernel", not "do a risky backport that exposes the entire user base to the potential of new data corruption bugs".... Cheers, Dave. -- Dave Chinner david@fromorbit.com From ben@decadent.org.uk Sat Jun 4 20:19:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D45647CA0 for ; Sat, 4 Jun 2016 20:19:46 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4C621AC005 for ; Sat, 4 Jun 2016 18:19:45 -0700 (PDT) X-ASG-Debug-ID: 1465089579-04cbb0356bb706c0001-NocioJ Received: from shadbolt.e.decadent.org.uk (shadbolt.e.decadent.org.uk [88.96.1.126]) by cuda.sgi.com with ESMTP id k3by0pdl7VhyqhV3 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Sat, 04 Jun 2016 18:19:40 -0700 (PDT) X-Barracuda-Envelope-From: ben@decadent.org.uk X-Barracuda-Effective-Source-IP: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Apparent-Source-IP: 88.96.1.126 Received: from [2a02:8011:400e:1:221:ccff:fe6d:2443] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1b9Mj2-0004c2-P1; Sun, 05 Jun 2016 02:19:36 +0100 Received: from ben by deadeye with local (Exim 4.87) (envelope-from ) id 1b9Mj2-0007N5-EH; Sun, 05 Jun 2016 02:19:36 +0100 Message-ID: <1465089572.2847.180.camel@decadent.org.uk> Subject: Re: XFS hole punch races From: Ben Hutchings X-ASG-Orig-Subj: Re: XFS hole punch races To: Dave Chinner Cc: Jan Kara , stable@vger.kernel.org, xfs@oss.sgi.com Date: Sun, 05 Jun 2016 02:19:32 +0100 In-Reply-To: <20160604232800.GW26977@dastard> References: <20160322155740.GB28772@quack.suse.cz> <1465060270.2847.149.camel@decadent.org.uk> <20160604232800.GW26977@dastard> Content-Type: multipart/signed; micalg="pgp-sha512"; protocol="application/pgp-signature"; boundary="=-GGgF4nOcNdE0iJ56Ay5F" X-Mailer: Evolution 3.20.2-2 Mime-Version: 1.0 X-SA-Exim-Connect-IP: 2a02:8011:400e:1:221:ccff:fe6d:2443 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false X-Barracuda-Connect: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Start-Time: 1465089579 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2939 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30174 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header --=-GGgF4nOcNdE0iJ56Ay5F Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Sun, 2016-06-05 at 09:28 +1000, Dave Chinner wrote: > On Sat, Jun 04, 2016 at 06:11:10PM +0100, Ben Hutchings wrote: > > On Tue, 2016-03-22 at 16:57 +0100, Jan Kara wrote: > >=20 > > Hi, > >=20 > > similarly to ext4 also XFS had races between hole punching and page fau= lts > > which could result in data corruption. The fixes were merged in 4.1-rc1= but > > it might make sense to backport them to older stable releases given the > > nature of the issue. > >=20 > > Relevant fixes are: > >=20 > > de0e8c20ba3a65b0f15040aabbefdc1999876e6b > > 075a924d45cc69c75a35f20b4912b85aa98b180a > > e8e9ad42c1f1e1bfbe0e8c32c8cac02e9ebfb7ef > > 0f9160b444e4de33b65dfcd3b901358a3129461a > > 723cac48473358939759885a18e8df113ea96138 > > ec56b1f1fdc69599963574ce94cc5693d535dd64 > >=20 > >=20 > > You missed the first in that sequence: > >=20 > > 653c60b633a9 xfs: introduce mmap/truncate lock > >=20 > > For 3.16, I've queued up all=C2=A0those fixes with one further=C2=A0pre= requisite: > >=20 > > 812176832169 xfs: fix swapext ilock deadlock > >=20 > > For 3.2, I've queued up all but 723cac484733, with these additional > > prerequisites: > >=20 > > f38996f57687 xfs: reduce ilock hold times in xfs_setattr_size > > bc4010ecb8f4 xfs: use iolock on XFS_IOC_ALLOCSP calls > > 76ca4c238cf5 xfs: always take the iolock around xfs_setattr_size > > 5f8aca8b43f4 xfs: always hold the iolock when calling xfs_change_file_s= pace > > I realise I'll need to check for regressions with xfstests. >=20 > Hi Ben, >=20 > You do realise that this sort of backport effectively makes the > stable kernels unsupportable by the upstream XFS developers? You're > taking random changes from the upstream kernel until the kernel > compiles, and then mostly hoping that it works. I'm applying slightly more intelligence than that, but of course I'm not an XFS developer. > It's trivially easy to break truncate by screwing up the locking and > IO barriers that it depends on, and this set of patches make quite a > lot of different changes that have an unknown set of dependencies > for correct behaviour. xfstests won't find all those problems; at > best it will tell us that there won't be obvious problems. >=20 > Stable kernels are supposed to be stable, and backports like this > are riskier than the original changes in the upstream kernels. if a > user is hitting a mmap/hole-punch race on an XFS filesytem (I can't > remember any reports to the upstream list for any kernel) on a 3.2 > kernel, then correct answer is "upgrade to a newer upstream kernel", > not "do a risky backport that exposes the entire user base to the > potential of new data corruption bugs".... OK, then I'll drop them for 3.2. Ben. --=20 Ben Hutchings Everything should be made as simple as possible, but not simpler. =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2= =A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0= =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0- Albert Einstein --=-GGgF4nOcNdE0iJ56Ay5F Content-Type: application/pgp-signature; name="signature.asc" Content-Description: This is a digitally signed message part -----BEGIN PGP SIGNATURE----- Version: GnuPG v2 iQIcBAABCgAGBQJXU34kAAoJEOe/yOyVhhEJ9IYP/iaZuRDEahJ6CCIBHzbOwiYw xb23RFpa0bk0uXLgIZaiRkMQ+LAAf/n8mLFcqGkZP6DhaaSh5qdzi8yguz5izd+F gK/qmugvOUANA5gQ8IQaW0t4GfvkgdSBE/I7uXBbKB1Q9VHqaClm6xdzbCWN6RbE QAOXWhl1Uf8M4hVWV57BxJTllycRX8buvm+cgJLPN1TzL5r6kHMIo6qs7PJVlKGH lAHQ6mvgz9sTtF3c7z8wpF+jr74xNYSaU7XrPq5jGXm2HGLQboQkHnzYGzIMkxKY GEbZ+VkDHhg4vaN9wYOyIGMz7F3MHhOuc7Ev+Ctni1Aa7HJxE5w5pZwNQ5mS/o3p zacjRB7AsAqsLHlUJat1+ZmxCJywdsyNGD5zU7yLLvUl09yxrY49JyeoCNgzf1Hu TRvadINWcmgNdFSSRvfECGqqLtcQW0e890sLC3/6D8rrU50uDBxyrHwoXpRkVsrQ M0oDpwu5uq8NV7pxGY9LcJsXPRKZC41ePvEozO0/+0DiALLUvPFArt3nHlOD9U81 MMpNNN7NPDjeFUaBSG2vxhqjfBCcPj3UXq+oKNoVXgdjaWOr5meTqu84FDvyKvie yCmBMk/xQd6hhfnDonVNroXMe2+iecwfeECS379OLpQi/hEZpq31WEcUjyhR60BO qRCTxL5RJCYUaUw0o/NR =yS2t -----END PGP SIGNATURE----- --=-GGgF4nOcNdE0iJ56Ay5F-- From david@fromorbit.com Sat Jun 4 21:17:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 476277CA0 for ; Sat, 4 Jun 2016 21:17:19 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 01D25304048 for ; Sat, 4 Jun 2016 19:17:15 -0700 (PDT) X-ASG-Debug-ID: 1465093032-04cbb03569b71af0001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id ZgBEcOKdJttX0cqB for ; Sat, 04 Jun 2016 19:17:13 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CnBADEilNXN2SyLXlegzqBU4J2g3mfLwECAQEBBowriA2BeoYMBAICgRs5FAEBAQEBAQEGAQEBAUJAhEUBAQEDATIBIyMQCAMYCSUPBSUDBxoTiCcHuwcBAQgnHoVBhRWKGgWYSI4cjyiPWh6ENioyiWMBAQE Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail05.adl6.internode.on.net with ESMTP; 05 Jun 2016 11:47:12 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1b9NcU-00085k-Kw; Sun, 05 Jun 2016 12:16:54 +1000 Date: Sun, 5 Jun 2016 12:16:54 +1000 From: Dave Chinner To: Ben Hutchings Cc: Jan Kara , stable@vger.kernel.org, xfs@oss.sgi.com Subject: Re: XFS hole punch races Message-ID: <20160605021654.GX26977@dastard> X-ASG-Orig-Subj: Re: XFS hole punch races References: <20160322155740.GB28772@quack.suse.cz> <1465060270.2847.149.camel@decadent.org.uk> <20160604232800.GW26977@dastard> <1465089572.2847.180.camel@decadent.org.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <1465089572.2847.180.camel@decadent.org.uk> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1465093032 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3325 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30175 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Sun, Jun 05, 2016 at 02:19:32AM +0100, Ben Hutchings wrote: > On Sun, 2016-06-05 at 09:28 +1000, Dave Chinner wrote: > > On Sat, Jun 04, 2016 at 06:11:10PM +0100, Ben Hutchings wrote: > > > On Tue, 2016-03-22 at 16:57 +0100, Jan Kara wrote: > > > > > > Hi, > > > > > > similarly to ext4 also XFS had races between hole punching and page faults > > > which could result in data corruption. The fixes were merged in 4.1-rc1 but > > > it might make sense to backport them to older stable releases given the > > > nature of the issue. > > > > > > Relevant fixes are: > > > > > > de0e8c20ba3a65b0f15040aabbefdc1999876e6b > > > 075a924d45cc69c75a35f20b4912b85aa98b180a > > > e8e9ad42c1f1e1bfbe0e8c32c8cac02e9ebfb7ef > > > 0f9160b444e4de33b65dfcd3b901358a3129461a > > > 723cac48473358939759885a18e8df113ea96138 > > > ec56b1f1fdc69599963574ce94cc5693d535dd64 > > > > > > > > > You missed the first in that sequence: > > > > > > 653c60b633a9 xfs: introduce mmap/truncate lock > > > > > > For 3.16, I've queued up allthose fixes with one furtherprerequisite: > > > > > > 812176832169 xfs: fix swapext ilock deadlock > > > > > > For 3.2, I've queued up all but 723cac484733, with these additional > > > prerequisites: > > > > > > f38996f57687 xfs: reduce ilock hold times in xfs_setattr_size > > > bc4010ecb8f4 xfs: use iolock on XFS_IOC_ALLOCSP calls > > > 76ca4c238cf5 xfs: always take the iolock around xfs_setattr_size > > > 5f8aca8b43f4 xfs: always hold the iolock when calling xfs_change_file_space > > > I realise I'll need to check for regressions with xfstests. > > > > Hi Ben, > > > > You do realise that this sort of backport effectively makes the > > stable kernels unsupportable by the upstream XFS developers? You're > > taking random changes from the upstream kernel until the kernel > > compiles, and then mostly hoping that it works. > > I'm applying slightly more intelligence than that, but of course I'm > not an XFS developer. Sorry, Ben, I didn't mean to imply you hadn't done your due diligence properly. It's more a case of lots of things around these patches also changed, and from that perspective the changes are effective a random selection of changes spread across several years of development. It's subtle things, like changes to how IO completion is processed (especially for AIO), etc that the backported code might depend on for correct behaviour but aren't in the older kernels. These sorts of subtle problems are typically only discovered by users with uncommon applications and/or load.... > > Stable kernels are supposed to be stable, and backports like this > > are riskier than the original changes in the upstream kernels. if a > > user is hitting a mmap/hole-punch race on an XFS filesytem (I can't > > remember any reports to the upstream list for any kernel) on a 3.2 > > kernel, then correct answer is "upgrade to a newer upstream kernel", > > not "do a risky backport that exposes the entire user base to the > > potential of new data corruption bugs".... > > OK, then I'll drop them for 3.2. Probably for the best - these mmap/holepunch races had been in the code since XFS was first ported, so it's not like it's a new problem. :/ Cheers, Dave. -- Dave Chinner david@fromorbit.com From w@1wt.eu Sun Jun 5 00:17:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3E6027CA0 for ; Sun, 5 Jun 2016 00:17:08 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C72E7AC004 for ; Sat, 4 Jun 2016 22:17:04 -0700 (PDT) X-ASG-Debug-ID: 1465103820-04bdf05ad4b65130001-NocioJ Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by cuda.sgi.com with ESMTP id wlPbwhlMC4POCPfm for ; Sat, 04 Jun 2016 22:17:01 -0700 (PDT) X-Barracuda-Envelope-From: w@1wt.eu X-Barracuda-Effective-Source-IP: wtarreau.pck.nerim.net[62.212.114.60] X-Barracuda-Apparent-Source-IP: 62.212.114.60 Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id u555GsJ7020747; Sun, 5 Jun 2016 07:16:54 +0200 Date: Sun, 5 Jun 2016 07:16:54 +0200 From: Willy Tarreau To: Dave Chinner Cc: Ben Hutchings , Jan Kara , stable@vger.kernel.org, xfs@oss.sgi.com Subject: Re: XFS hole punch races Message-ID: <20160605051654.GA20713@1wt.eu> X-ASG-Orig-Subj: Re: XFS hole punch races References: <20160322155740.GB28772@quack.suse.cz> <1465060270.2847.149.camel@decadent.org.uk> <20160604232800.GW26977@dastard> <1465089572.2847.180.camel@decadent.org.uk> <20160605021654.GX26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160605021654.GX26977@dastard> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: wtarreau.pck.nerim.net[62.212.114.60] X-Barracuda-Start-Time: 1465103821 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1342 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30178 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Dave, On Sun, Jun 05, 2016 at 12:16:54PM +1000, Dave Chinner wrote: > On Sun, Jun 05, 2016 at 02:19:32AM +0100, Ben Hutchings wrote: > > On Sun, 2016-06-05 at 09:28 +1000, Dave Chinner wrote: > > > You do realise that this sort of backport effectively makes the > > > stable kernels unsupportable by the upstream XFS developers? You're > > > taking random changes from the upstream kernel until the kernel > > > compiles, and then mostly hoping that it works. > > > > I'm applying slightly more intelligence than that, but of course I'm > > not an XFS developer. > > Sorry, Ben, I didn't mean to imply you hadn't done your due diligence > properly. It's more a case of lots of things around these patches > also changed, and from that perspective the changes are effective a > random selection of changes spread across several years of > development. > > It's subtle things, like changes to how IO completion is processed > (especially for AIO), etc that the backported code might depend on > for correct behaviour but aren't in the older kernels. These sorts > of subtle problems are typically only discovered by users with > uncommon applications and/or load.... Does this mean that as a rule of thumb we'd rather avoid backporting XFS fixes unless they seem really obvious (or at all) ? Thanks, Willy From mchristi@redhat.com Sun Jun 5 14:32:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6ADF17CA0 for ; Sun, 5 Jun 2016 14:32:40 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id A6EE9AC007 for ; Sun, 5 Jun 2016 12:32:39 -0700 (PDT) X-ASG-Debug-ID: 1465155153-04cb6c2dbab58d80001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id bwPNfDpVbQ2OSPYq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:34 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C009B8E39A; Sun, 5 Jun 2016 19:32:32 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR97003130; Sun, 5 Jun 2016 15:32:27 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Subject: [PATCH 00/45] v8: separate operations from flags in the bio/request structs Date: Sun, 5 Jun 2016 14:31:40 -0500 X-ASG-Orig-Subj: [PATCH 00/45] v8: separate operations from flags in the bio/request structs Message-Id: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:32:33 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155154 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13668 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 The following patches begin to cleanup the request->cmd_flags and bio->bi_rw mess. We currently use cmd_flags to specify the operation, attributes and state of the request. For bi_rw we use it for similar info and also the priority but then also have another bi_flags field for state. At some point, we abused them so much we just made cmd_flags 64 bits, so we could add more. The following patches seperate the operation (read, write discard, flush, etc) from cmd_flags/bi_rw. They were made against Linus's tree. I put a git tree here: https://github.com/mikechristie/linux-kernel/tree/op The patches are in the op branch. Note that I made it against linus's tree, but right now the only major conflicts with -next are in the dm tree from the dm-rq related changes. I have patches for that and can submit them. I was just not sure how to coordinate everything. v8: 1. Handle Jens's review comments from LSF. Instead of adding a op field, store the value in bi_rw/cmd_flags and access via accessors. v7: 1. Fix broken feature_flush/fua use. v6 and maybe hopfully the last version: 1. Adapt patch 41 to Jens's QUEUE_FLAG_WC/FUA patchset. v5: 1. Missed crypto fs submit_bio_wait call. 2. Change nfs bi_rw check to bi_op. 3. btrfs. Convert finish_parity_scrub. 4. Reworked against Jens's QUEUE_FLAG patches so I could drop my similar code. 5. Separated the core block layer change into multiple patches for merging, elevator, stats, mq and non mq request allocation to try and make it easier to read. v4: 1. Rebased to current linux-next tree. v3: 1. Used "=" instead of "|=" to setup bio bi_rw. 2. Removed __get_request cmd_flags compat code. 3. Merged initial dm related changes requested by Mike Snitzer. 4. Fixed ubd kbuild errors in flush related patches. 5. Fix 80 char col issues in several patches. 6. Fix issue with one of the btrfs patches where it looks like I reverted a patch when trying to fix a merge error. v2 1. Dropped arguments from submit_bio, and had callers setup bio. 2. Add REQ_OP_FLUSH for request_fn users and renamed REQ_FLUSH to REQ_PREFLUSH for make_request_fn users. 3. Dropped bio/rq_data_dir functions, and added a op_is_write function instead. Diffstat for the set: Documentation/block/writeback_cache_control.txt | 28 +++--- Documentation/device-mapper/log-writes.txt | 10 +- arch/um/drivers/ubd_kern.c | 2 block/bio.c | 20 ++-- block/blk-core.c | 105 +++++++++++------------ block/blk-flush.c | 25 ++--- block/blk-lib.c | 37 ++++---- block/blk-map.c | 2 block/blk-merge.c | 24 ++--- block/blk-mq.c | 42 ++++----- block/cfq-iosched.c | 55 +++++++----- block/elevator.c | 7 - drivers/ata/libata-scsi.c | 2 drivers/block/brd.c | 2 drivers/block/drbd/drbd_actlog.c | 34 ++++--- drivers/block/drbd/drbd_bitmap.c | 10 +- drivers/block/drbd/drbd_int.h | 4 drivers/block/drbd/drbd_main.c | 22 ++-- drivers/block/drbd/drbd_protocol.h | 2 drivers/block/drbd/drbd_receiver.c | 38 +++++--- drivers/block/drbd/drbd_req.c | 2 drivers/block/drbd/drbd_worker.c | 7 - drivers/block/floppy.c | 5 - drivers/block/loop.c | 16 +-- drivers/block/mtip32xx/mtip32xx.c | 2 drivers/block/nbd.c | 4 drivers/block/osdblk.c | 2 drivers/block/pktcdvd.c | 4 drivers/block/ps3disk.c | 4 drivers/block/rbd.c | 4 drivers/block/rsxx/dma.c | 2 drivers/block/skd_main.c | 2 drivers/block/umem.c | 2 drivers/block/virtio_blk.c | 2 drivers/block/xen-blkback/blkback.c | 31 ++++-- drivers/block/xen-blkfront.c | 67 +++++++-------- drivers/block/zram/zram_drv.c | 2 drivers/ide/ide-cd_ioctl.c | 3 drivers/ide/ide-disk.c | 2 drivers/ide/ide-floppy.c | 2 drivers/lightnvm/rrpc.c | 6 - drivers/md/bcache/btree.c | 4 drivers/md/bcache/debug.c | 10 +- drivers/md/bcache/io.c | 2 drivers/md/bcache/journal.c | 11 +- drivers/md/bcache/movinggc.c | 2 drivers/md/bcache/request.c | 28 +++--- drivers/md/bcache/super.c | 28 +++--- drivers/md/bcache/writeback.c | 4 drivers/md/bitmap.c | 6 - drivers/md/dm-bufio.c | 11 +- drivers/md/dm-cache-target.c | 22 ++-- drivers/md/dm-crypt.c | 15 +-- drivers/md/dm-era-target.c | 4 drivers/md/dm-flakey.c | 2 drivers/md/dm-io.c | 65 +++++++------- drivers/md/dm-kcopyd.c | 11 +- drivers/md/dm-log-writes.c | 19 ++-- drivers/md/dm-log.c | 5 - drivers/md/dm-raid.c | 5 - drivers/md/dm-raid1.c | 24 +++-- drivers/md/dm-region-hash.c | 8 - drivers/md/dm-snap-persistent.c | 24 ++--- drivers/md/dm-snap.c | 6 - drivers/md/dm-stats.c | 9 -- drivers/md/dm-stripe.c | 6 - drivers/md/dm-thin.c | 30 +++--- drivers/md/dm.c | 45 +++++----- drivers/md/linear.c | 4 drivers/md/md.c | 24 +++-- drivers/md/md.h | 5 - drivers/md/multipath.c | 2 drivers/md/raid0.c | 4 drivers/md/raid1.c | 38 ++++---- drivers/md/raid10.c | 54 ++++++------ drivers/md/raid5-cache.c | 35 ++++--- drivers/md/raid5.c | 48 +++++----- drivers/mmc/card/block.c | 13 +- drivers/mmc/card/queue.c | 6 - drivers/mmc/card/queue.h | 8 + drivers/mtd/mtd_blkdevs.c | 4 drivers/nvme/host/core.c | 4 drivers/nvme/host/nvme.h | 4 drivers/scsi/osd/osd_initiator.c | 12 +- drivers/scsi/sd.c | 34 ++++--- drivers/staging/lustre/lustre/llite/lloop.c | 6 - drivers/target/target_core_iblock.c | 53 ++++++----- drivers/target/target_core_pscsi.c | 2 fs/btrfs/check-integrity.c | 73 ++++++++-------- fs/btrfs/check-integrity.h | 6 - fs/btrfs/compression.c | 17 ++- fs/btrfs/ctree.h | 2 fs/btrfs/disk-io.c | 45 ++++------ fs/btrfs/disk-io.h | 2 fs/btrfs/extent-tree.c | 2 fs/btrfs/extent_io.c | 107 +++++++++++------------- fs/btrfs/extent_io.h | 8 - fs/btrfs/inode.c | 74 ++++++++-------- fs/btrfs/raid56.c | 27 +++--- fs/btrfs/scrub.c | 25 +++-- fs/btrfs/volumes.c | 95 +++++++++++---------- fs/btrfs/volumes.h | 6 - fs/buffer.c | 75 ++++++++-------- fs/crypto/crypto.c | 5 - fs/direct-io.c | 37 ++++---- fs/exofs/ore.c | 2 fs/ext4/balloc.c | 2 fs/ext4/ialloc.c | 2 fs/ext4/inode.c | 8 - fs/ext4/mmp.c | 4 fs/ext4/namei.c | 3 fs/ext4/page-io.c | 9 +- fs/ext4/readpage.c | 11 +- fs/ext4/super.c | 2 fs/f2fs/checkpoint.c | 10 +- fs/f2fs/data.c | 51 ++++++----- fs/f2fs/f2fs.h | 5 - fs/f2fs/gc.c | 9 +- fs/f2fs/inline.c | 3 fs/f2fs/node.c | 8 + fs/f2fs/segment.c | 18 ++-- fs/f2fs/trace.c | 7 - fs/fat/misc.c | 2 fs/gfs2/bmap.c | 4 fs/gfs2/dir.c | 2 fs/gfs2/log.c | 8 - fs/gfs2/lops.c | 14 +-- fs/gfs2/lops.h | 2 fs/gfs2/meta_io.c | 20 ++-- fs/gfs2/ops_fstype.c | 5 - fs/gfs2/quota.c | 2 fs/hfsplus/hfsplus_fs.h | 2 fs/hfsplus/part_tbl.c | 5 - fs/hfsplus/super.c | 6 - fs/hfsplus/wrapper.c | 17 ++- fs/isofs/compress.c | 2 fs/jbd2/commit.c | 6 - fs/jbd2/journal.c | 12 +- fs/jbd2/recovery.c | 4 fs/jfs/jfs_logmgr.c | 10 +- fs/jfs/jfs_metapage.c | 14 +-- fs/logfs/dev_bdev.c | 27 +++--- fs/mpage.c | 43 ++++----- fs/nfs/blocklayout/blocklayout.c | 26 +++-- fs/nilfs2/btnode.c | 6 - fs/nilfs2/btnode.h | 2 fs/nilfs2/btree.c | 6 - fs/nilfs2/gcinode.c | 5 - fs/nilfs2/mdt.c | 11 +- fs/nilfs2/segbuf.c | 20 ++-- fs/ntfs/aops.c | 6 - fs/ntfs/compress.c | 2 fs/ntfs/file.c | 2 fs/ntfs/logfile.c | 2 fs/ntfs/mft.c | 4 fs/ocfs2/aops.c | 2 fs/ocfs2/buffer_head_io.c | 8 - fs/ocfs2/cluster/heartbeat.c | 22 ++-- fs/ocfs2/super.c | 2 fs/reiserfs/inode.c | 4 fs/reiserfs/journal.c | 14 +-- fs/reiserfs/stree.c | 4 fs/reiserfs/super.c | 2 fs/squashfs/block.c | 4 fs/udf/dir.c | 2 fs/udf/directory.c | 2 fs/udf/inode.c | 2 fs/ufs/balloc.c | 2 fs/ufs/util.c | 2 fs/xfs/xfs_aops.c | 27 +++--- fs/xfs/xfs_buf.c | 32 +++---- include/linux/bio.h | 37 +++----- include/linux/blk-cgroup.h | 15 +-- include/linux/blk_types.h | 94 +++++++++++---------- include/linux/blkdev.h | 56 ++++++++---- include/linux/blktrace_api.h | 2 include/linux/buffer_head.h | 11 +- include/linux/dm-io.h | 3 include/linux/elevator.h | 4 include/linux/fs.h | 71 +++++++++------ include/trace/events/bcache.h | 12 +- include/trace/events/block.h | 31 ++++-- include/trace/events/f2fs.h | 37 ++++---- kernel/power/swap.c | 35 ++++--- kernel/trace/blktrace.c | 72 +++++++++------- mm/page_io.c | 14 +-- 186 files changed, 1679 insertions(+), 1413 deletions(-) From mchristi@redhat.com Sun Jun 5 14:32:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AC6D77CA2 for ; Sun, 5 Jun 2016 14:32:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 71E808F8039 for ; Sun, 5 Jun 2016 12:32:39 -0700 (PDT) X-ASG-Debug-ID: 1465155157-04cb6c2dbcb58d90001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id l596yVqit5FiSdXz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:38 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 86F677AEBD; Sun, 5 Jun 2016 19:32:37 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR99003130; Sun, 5 Jun 2016 15:32:35 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 02/45] block: add REQ_OP definitions and helpers Date: Sun, 5 Jun 2016 14:31:42 -0500 X-ASG-Orig-Subj: [PATCH 02/45] block: add REQ_OP definitions and helpers Message-Id: <1465155145-10812-3-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Sun, 05 Jun 2016 19:32:37 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155158 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4479 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie The following patches separate the operation (WRITE, READ, DISCARD, etc) from the rq_flag_bits flags. This patch adds definitions for request/bio operations (REQ_OPs) and adds request/bio accessors to get/set the op. In this patch the REQ_OPs match the REQ rq_flag_bits ones for compat reasons while all the code is converted to use the op accessors in the set. In the last patches the op will become a number and the accessors and helpers in this patch will be dropped or updated. Signed-off-by: Mike Christie --- include/linux/bio.h | 3 +++ include/linux/blk_types.h | 24 ++++++++++++++++++++++++ include/linux/blkdev.h | 10 +++++++++- include/linux/fs.h | 26 ++++++++++++++++++++++++-- 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/include/linux/bio.h b/include/linux/bio.h index 3bde942..09c5308 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -44,6 +44,9 @@ #define BIO_MAX_SIZE (BIO_MAX_PAGES << PAGE_SHIFT) #define BIO_MAX_SECTORS (BIO_MAX_SIZE >> 9) +#define bio_op(bio) (op_from_rq_bits((bio)->bi_rw)) +#define bio_set_op_attrs(bio, op, flags) ((bio)->bi_rw |= (op | flags)) + /* * upper 16 bits of bi_rw define the io priority of this bio */ diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 77e5d81..6e60baa 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -242,6 +242,30 @@ enum rq_flag_bits { #define REQ_HASHED (1ULL << __REQ_HASHED) #define REQ_MQ_INFLIGHT (1ULL << __REQ_MQ_INFLIGHT) +enum req_op { + REQ_OP_READ, + REQ_OP_WRITE = REQ_WRITE, + REQ_OP_DISCARD = REQ_DISCARD, + REQ_OP_WRITE_SAME = REQ_WRITE_SAME, +}; + +/* + * tmp cpmpat. Users used to set the write bit for all non reads, but + * we will be dropping the bitmap use for ops. Support both until + * the end of the patchset. + */ +static inline int op_from_rq_bits(u64 flags) +{ + if (flags & REQ_OP_DISCARD) + return REQ_OP_DISCARD; + else if (flags & REQ_OP_WRITE_SAME) + return REQ_OP_WRITE_SAME; + else if (flags & REQ_OP_WRITE) + return REQ_OP_WRITE; + else + return REQ_OP_READ; +} + typedef unsigned int blk_qc_t; #define BLK_QC_T_NONE -1U #define BLK_QC_T_SHIFT 16 diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 3d9cf32..49c2dbc 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -200,6 +200,13 @@ struct request { struct request *next_rq; }; +#define req_op(req) (op_from_rq_bits((req)->cmd_flags)) +#define req_set_op(req, op) ((req)->cmd_flags |= op) +#define req_set_op_attrs(req, op, flags) do { \ + req_set_op(req, op); \ + (req)->cmd_flags |= flags; \ +} while (0) + static inline unsigned short req_get_ioprio(struct request *req) { return req->ioprio; @@ -597,7 +604,8 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) -#define rq_data_dir(rq) ((int)((rq)->cmd_flags & 1)) +#define rq_data_dir(rq) \ + (op_is_write(op_from_rq_bits(rq->cmd_flags)) ? WRITE : READ) /* * Driver can handle struct request, if it either has an old style diff --git a/include/linux/fs.h b/include/linux/fs.h index 65e4c51..62ca2f9 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2465,14 +2465,36 @@ extern bool is_bad_inode(struct inode *); #ifdef CONFIG_BLOCK /* + * tmp cpmpat. Users used to set the write bit for all non reads, but + * we will be dropping the bitmap use for ops. Support both until + * the end of the patchset. + */ +static inline bool op_is_write(unsigned long flags) +{ + if (flags & (REQ_OP_WRITE | REQ_OP_WRITE_SAME | REQ_OP_DISCARD)) + return true; + else + return false; +} + +/* * return READ, READA, or WRITE */ -#define bio_rw(bio) ((bio)->bi_rw & (RW_MASK | RWA_MASK)) +static inline int bio_rw(struct bio *bio) +{ + if (op_is_write(op_from_rq_bits(bio->bi_rw))) + return WRITE; + + return bio->bi_rw & RWA_MASK; +} /* * return data direction, READ or WRITE */ -#define bio_data_dir(bio) ((bio)->bi_rw & 1) +static inline int bio_data_dir(struct bio *bio) +{ + return op_is_write(op_from_rq_bits(bio->bi_rw)) ? WRITE : READ; +} extern void check_disk_size_change(struct gendisk *disk, struct block_device *bdev); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 690437CA1 for ; Sun, 5 Jun 2016 14:32:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 37F4B8F8039 for ; Sun, 5 Jun 2016 12:32:42 -0700 (PDT) X-ASG-Debug-ID: 1465155155-04cb6c2db9b58d80001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id UMq5t2HxNamuu8fH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:36 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 801C38E938; Sun, 5 Jun 2016 19:32:35 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR98003130; Sun, 5 Jun 2016 15:32:32 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio Date: Sun, 5 Jun 2016 14:31:41 -0500 X-ASG-Orig-Subj: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio Message-Id: <1465155145-10812-2-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:32:35 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155156 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 57655 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This has callers of submit_bio/submit_bio_wait set the bio->bi_rw instead of passing it in. This makes that use the same as generic_make_request and how we set the other bio fields. Signed-off-by: Mike Christie --- v8: 1. Fix bug in xfs code introduced in v6 due to ioend changes. 2. Dropped signed-offs due to so many upstream changes since last review. v5: 1. Missed crypto fs submit_bio_wait call. v2: 1. Set bi_rw instead of ORing it. For cloned bios, I still OR it to keep the old behavior incase there bits we wanted to keep. block/bio.c | 7 +++---- block/blk-core.c | 11 ++++------- block/blk-flush.c | 3 ++- block/blk-lib.c | 20 +++++++++++--------- drivers/block/drbd/drbd_actlog.c | 2 +- drivers/block/drbd/drbd_bitmap.c | 4 ++-- drivers/block/floppy.c | 3 ++- drivers/block/xen-blkback/blkback.c | 4 +++- drivers/block/xen-blkfront.c | 4 ++-- drivers/md/bcache/debug.c | 6 ++++-- drivers/md/bcache/journal.c | 2 +- drivers/md/bcache/super.c | 4 ++-- drivers/md/dm-bufio.c | 3 ++- drivers/md/dm-io.c | 3 ++- drivers/md/dm-log-writes.c | 9 ++++++--- drivers/md/dm-thin.c | 3 ++- drivers/md/md.c | 10 +++++++--- drivers/md/raid1.c | 3 ++- drivers/md/raid10.c | 4 +++- drivers/md/raid5-cache.c | 7 ++++--- drivers/target/target_core_iblock.c | 24 +++++++++++++----------- fs/btrfs/check-integrity.c | 18 ++++++++++-------- fs/btrfs/check-integrity.h | 4 ++-- fs/btrfs/disk-io.c | 3 ++- fs/btrfs/extent_io.c | 7 ++++--- fs/btrfs/raid56.c | 17 ++++++++++++----- fs/btrfs/scrub.c | 15 ++++++++++----- fs/btrfs/volumes.c | 14 +++++++------- fs/buffer.c | 3 ++- fs/crypto/crypto.c | 3 ++- fs/direct-io.c | 3 ++- fs/ext4/page-io.c | 3 ++- fs/ext4/readpage.c | 9 +++++---- fs/f2fs/data.c | 4 +++- fs/f2fs/segment.c | 6 ++++-- fs/gfs2/lops.c | 3 ++- fs/gfs2/meta_io.c | 3 ++- fs/gfs2/ops_fstype.c | 3 ++- fs/hfsplus/wrapper.c | 3 ++- fs/jfs/jfs_logmgr.c | 6 ++++-- fs/jfs/jfs_metapage.c | 10 ++++++---- fs/logfs/dev_bdev.c | 15 ++++++++++----- fs/mpage.c | 3 ++- fs/nfs/blocklayout/blocklayout.c | 22 ++++++++++++---------- fs/nilfs2/segbuf.c | 3 ++- fs/ocfs2/cluster/heartbeat.c | 12 +++++++----- fs/xfs/xfs_aops.c | 15 ++++++++++----- fs/xfs/xfs_buf.c | 4 ++-- include/linux/bio.h | 2 +- include/linux/fs.h | 2 +- kernel/power/swap.c | 5 +++-- mm/page_io.c | 10 ++++++---- 52 files changed, 219 insertions(+), 147 deletions(-) diff --git a/block/bio.c b/block/bio.c index 0e4aa42..fc779eb 100644 --- a/block/bio.c +++ b/block/bio.c @@ -854,21 +854,20 @@ static void submit_bio_wait_endio(struct bio *bio) /** * submit_bio_wait - submit a bio, and wait until it completes - * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) * @bio: The &struct bio which describes the I/O * * Simple wrapper around submit_bio(). Returns 0 on success, or the error from * bio_endio() on failure. */ -int submit_bio_wait(int rw, struct bio *bio) +int submit_bio_wait(struct bio *bio) { struct submit_bio_ret ret; - rw |= REQ_SYNC; init_completion(&ret.event); bio->bi_private = &ret; bio->bi_end_io = submit_bio_wait_endio; - submit_bio(rw, bio); + bio->bi_rw |= REQ_SYNC; + submit_bio(bio); wait_for_completion_io(&ret.event); return ret.error; diff --git a/block/blk-core.c b/block/blk-core.c index 2475b1c7..e953407 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2094,7 +2094,6 @@ EXPORT_SYMBOL(generic_make_request); /** * submit_bio - submit a bio to the block device layer for I/O - * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) * @bio: The &struct bio which describes the I/O * * submit_bio() is very similar in purpose to generic_make_request(), and @@ -2102,10 +2101,8 @@ EXPORT_SYMBOL(generic_make_request); * interfaces; @bio must be presetup and ready for I/O. * */ -blk_qc_t submit_bio(int rw, struct bio *bio) +blk_qc_t submit_bio(struct bio *bio) { - bio->bi_rw |= rw; - /* * If it's a regular read/write or a barrier with data attached, * go through the normal accounting stuff before submission. @@ -2113,12 +2110,12 @@ blk_qc_t submit_bio(int rw, struct bio *bio) if (bio_has_data(bio)) { unsigned int count; - if (unlikely(rw & REQ_WRITE_SAME)) + if (unlikely(bio->bi_rw & REQ_WRITE_SAME)) count = bdev_logical_block_size(bio->bi_bdev) >> 9; else count = bio_sectors(bio); - if (rw & WRITE) { + if (bio->bi_rw & WRITE) { count_vm_events(PGPGOUT, count); } else { task_io_account_read(bio->bi_iter.bi_size); @@ -2129,7 +2126,7 @@ blk_qc_t submit_bio(int rw, struct bio *bio) char b[BDEVNAME_SIZE]; printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n", current->comm, task_pid_nr(current), - (rw & WRITE) ? "WRITE" : "READ", + (bio->bi_rw & WRITE) ? "WRITE" : "READ", (unsigned long long)bio->bi_iter.bi_sector, bdevname(bio->bi_bdev, b), count); diff --git a/block/blk-flush.c b/block/blk-flush.c index b1c91d2..3af4a5a 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -485,8 +485,9 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, bio = bio_alloc(gfp_mask, 0); bio->bi_bdev = bdev; + bio->bi_rw = WRITE_FLUSH; - ret = submit_bio_wait(WRITE_FLUSH, bio); + ret = submit_bio_wait(bio); /* * The driver must store the error location in ->bi_sector, if diff --git a/block/blk-lib.c b/block/blk-lib.c index 23d7f30..1f6dec5 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -9,14 +9,14 @@ #include "blk.h" -static struct bio *next_bio(struct bio *bio, int rw, unsigned int nr_pages, +static struct bio *next_bio(struct bio *bio, unsigned int nr_pages, gfp_t gfp) { struct bio *new = bio_alloc(gfp, nr_pages); if (bio) { bio_chain(bio, new); - submit_bio(rw, bio); + submit_bio(bio); } return new; @@ -62,9 +62,10 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, req_sects = end_sect - sector; } - bio = next_bio(bio, type, 1, gfp_mask); + bio = next_bio(bio, 1, gfp_mask); bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; + bio->bi_rw = type; bio->bi_iter.bi_size = req_sects << 9; nr_sects -= req_sects; @@ -110,7 +111,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, type, &bio); if (!ret && bio) { - ret = submit_bio_wait(type, bio); + ret = submit_bio_wait(bio); if (ret == -EOPNOTSUPP) ret = 0; } @@ -147,13 +148,14 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, max_write_same_sectors = UINT_MAX >> 9; while (nr_sects) { - bio = next_bio(bio, REQ_WRITE | REQ_WRITE_SAME, 1, gfp_mask); + bio = next_bio(bio, 1, gfp_mask); bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; bio->bi_vcnt = 1; bio->bi_io_vec->bv_page = page; bio->bi_io_vec->bv_offset = 0; bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev); + bio->bi_rw = REQ_WRITE | REQ_WRITE_SAME; if (nr_sects > max_write_same_sectors) { bio->bi_iter.bi_size = max_write_same_sectors << 9; @@ -166,7 +168,7 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, } if (bio) - ret = submit_bio_wait(REQ_WRITE | REQ_WRITE_SAME, bio); + ret = submit_bio_wait(bio); return ret != -EOPNOTSUPP ? ret : 0; } EXPORT_SYMBOL(blkdev_issue_write_same); @@ -190,11 +192,11 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, unsigned int sz; while (nr_sects != 0) { - bio = next_bio(bio, WRITE, - min(nr_sects, (sector_t)BIO_MAX_PAGES), + bio = next_bio(bio, min(nr_sects, (sector_t)BIO_MAX_PAGES), gfp_mask); bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; + bio->bi_rw = REQ_WRITE; while (nr_sects != 0) { sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects); @@ -207,7 +209,7 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, } if (bio) - return submit_bio_wait(WRITE, bio); + return submit_bio_wait(bio); return 0; } diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 10459a1..6069e15 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -177,7 +177,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) bio_io_error(bio); else - submit_bio(rw, bio); + submit_bio(bio); wait_until_done_or_force_detached(device, bdev, &device->md_io.done); if (!bio->bi_error) err = device->md_io.error; diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index 92d6fc0..e8959fe 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -1011,12 +1011,12 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho bio_add_page(bio, page, len, 0); bio->bi_private = ctx; bio->bi_end_io = drbd_bm_endio; + bio->bi_rw = rw; if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) { - bio->bi_rw |= rw; bio_io_error(bio); } else { - submit_bio(rw, bio); + submit_bio(bio); /* this should not count as user activity and cause the * resync to throttle -- see drbd_rs_should_slow_down(). */ atomic_add(len >> 9, &device->rs_sect_ev); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 84708a5..73ded25 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3822,8 +3822,9 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive) bio.bi_flags |= (1 << BIO_QUIET); bio.bi_private = &cbdata; bio.bi_end_io = floppy_rb0_cb; + bio.bi_rw = READ; - submit_bio(READ, &bio); + submit_bio(&bio); process_fd_request(); init_completion(&cbdata.complete); diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 4809c15..79fe493 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -1369,6 +1369,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; bio->bi_iter.bi_sector = preq.sector_number; + bio->bi_rw = operation; } preq.sector_number += seg[i].nsec; @@ -1386,13 +1387,14 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, bio->bi_bdev = preq.bdev; bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; + bio->bi_rw = operation; } atomic_set(&pending_req->pendcnt, nbio); blk_start_plug(&plug); for (i = 0; i < nbio; i++) - submit_bio(operation, biolist[i]); + submit_bio(biolist[i]); /* Let the I/Os go.. */ blk_finish_plug(&plug); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index ca13df8..52963a2 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -2114,7 +2114,7 @@ static int blkif_recover(struct blkfront_info *info) bio_trim(cloned_bio, offset, size); cloned_bio->bi_private = split_bio; cloned_bio->bi_end_io = split_bio_end; - submit_bio(cloned_bio->bi_rw, cloned_bio); + submit_bio(cloned_bio); } /* * Now we have to wait for all those smaller bios to @@ -2123,7 +2123,7 @@ static int blkif_recover(struct blkfront_info *info) continue; } /* We don't need to split this bio */ - submit_bio(bio->bi_rw, bio); + submit_bio(bio); } return 0; diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c index 8b1f1d5..52b6bcf 100644 --- a/drivers/md/bcache/debug.c +++ b/drivers/md/bcache/debug.c @@ -52,9 +52,10 @@ void bch_btree_verify(struct btree *b) bio->bi_bdev = PTR_CACHE(b->c, &b->key, 0)->bdev; bio->bi_iter.bi_sector = PTR_OFFSET(&b->key, 0); bio->bi_iter.bi_size = KEY_SIZE(&v->key) << 9; + bio->bi_rw = REQ_META|READ_SYNC; bch_bio_map(bio, sorted); - submit_bio_wait(REQ_META|READ_SYNC, bio); + submit_bio_wait(bio); bch_bbio_free(bio, b->c); memcpy(ondisk, sorted, KEY_SIZE(&v->key) << 9); @@ -113,11 +114,12 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio) check = bio_clone(bio, GFP_NOIO); if (!check) return; + check->bi_rw |= READ_SYNC; if (bio_alloc_pages(check, GFP_NOIO)) goto out_put; - submit_bio_wait(READ_SYNC, check); + submit_bio_wait(check); bio_for_each_segment(bv, bio, iter) { void *p1 = kmap_atomic(bv.bv_page); diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index 29eba72..af3f9f7 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -418,7 +418,7 @@ static void journal_discard_work(struct work_struct *work) struct journal_device *ja = container_of(work, struct journal_device, discard_work); - submit_bio(0, &ja->discard_bio); + submit_bio(&ja->discard_bio); } static void do_journal_discard(struct cache *ca) diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index f5dbb4e..1eb526a7 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -212,7 +212,7 @@ static void __write_super(struct cache_sb *sb, struct bio *bio) unsigned i; bio->bi_iter.bi_sector = SB_SECTOR; - bio->bi_rw = REQ_SYNC|REQ_META; + bio->bi_rw = REQ_WRITE|REQ_SYNC|REQ_META; bio->bi_iter.bi_size = SB_SIZE; bch_bio_map(bio, NULL); @@ -238,7 +238,7 @@ static void __write_super(struct cache_sb *sb, struct bio *bio) pr_debug("ver %llu, flags %llu, seq %llu", sb->version, sb->flags, sb->seq); - submit_bio(REQ_WRITE, bio); + submit_bio(bio); } static void bch_write_bdev_super_unlock(struct closure *cl) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index cd77216..9d3ee7f 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -634,6 +634,7 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, * the dm_buffer's inline bio is local to bufio. */ b->bio.bi_private = end_io; + b->bio.bi_rw = rw; /* * We assume that if len >= PAGE_SIZE ptr is page-aligned. @@ -660,7 +661,7 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, ptr += PAGE_SIZE; } while (len > 0); - submit_bio(rw, &b->bio); + submit_bio(&b->bio); } static void submit_io(struct dm_buffer *b, int rw, sector_t block, diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 06d426e..50f17e3 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -322,6 +322,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, bio->bi_iter.bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; + bio->bi_rw = rw; store_io_and_region_in_bio(bio, io, region); if (rw & REQ_DISCARD) { @@ -355,7 +356,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, } atomic_inc(&io->count); - submit_bio(rw, bio); + submit_bio(bio); } while (remaining); } diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index 608302e..addcc4b 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c @@ -205,6 +205,7 @@ static int write_metadata(struct log_writes_c *lc, void *entry, bio->bi_bdev = lc->logdev->bdev; bio->bi_end_io = log_end_io; bio->bi_private = lc; + bio->bi_rw = WRITE; page = alloc_page(GFP_KERNEL); if (!page) { @@ -226,7 +227,7 @@ static int write_metadata(struct log_writes_c *lc, void *entry, DMERR("Couldn't add page to the log block"); goto error_bio; } - submit_bio(WRITE, bio); + submit_bio(bio); return 0; error_bio: bio_put(bio); @@ -269,6 +270,7 @@ static int log_one_block(struct log_writes_c *lc, bio->bi_bdev = lc->logdev->bdev; bio->bi_end_io = log_end_io; bio->bi_private = lc; + bio->bi_rw = WRITE; for (i = 0; i < block->vec_cnt; i++) { /* @@ -279,7 +281,7 @@ static int log_one_block(struct log_writes_c *lc, block->vecs[i].bv_len, 0); if (ret != block->vecs[i].bv_len) { atomic_inc(&lc->io_blocks); - submit_bio(WRITE, bio); + submit_bio(bio); bio = bio_alloc(GFP_KERNEL, block->vec_cnt - i); if (!bio) { DMERR("Couldn't alloc log bio"); @@ -290,6 +292,7 @@ static int log_one_block(struct log_writes_c *lc, bio->bi_bdev = lc->logdev->bdev; bio->bi_end_io = log_end_io; bio->bi_private = lc; + bio->bi_rw = WRITE; ret = bio_add_page(bio, block->vecs[i].bv_page, block->vecs[i].bv_len, 0); @@ -301,7 +304,7 @@ static int log_one_block(struct log_writes_c *lc, } sector += block->vecs[i].bv_len >> SECTOR_SHIFT; } - submit_bio(WRITE, bio); + submit_bio(bio); out: kfree(block->data); kfree(block); diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index fc803d5..8c070ee 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -371,7 +371,8 @@ static void end_discard(struct discard_op *op, int r) * need to wait for the chain to complete. */ bio_chain(op->bio, op->parent_bio); - submit_bio(REQ_WRITE | REQ_DISCARD, op->bio); + op->bio->bi_rw = REQ_WRITE | REQ_DISCARD; + submit_bio(op->bio); } blk_finish_plug(&op->plug); diff --git a/drivers/md/md.c b/drivers/md/md.c index 866825f..fb3950b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -394,8 +394,9 @@ static void submit_flushes(struct work_struct *ws) bi->bi_end_io = md_end_flush; bi->bi_private = rdev; bi->bi_bdev = rdev->bdev; + bi->bi_rw = WRITE_FLUSH; atomic_inc(&mddev->flush_pending); - submit_bio(WRITE_FLUSH, bi); + submit_bio(bi); rcu_read_lock(); rdev_dec_pending(rdev, mddev); } @@ -742,9 +743,10 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; + bio->bi_rw = WRITE_FLUSH_FUA; atomic_inc(&mddev->pending_writes); - submit_bio(WRITE_FLUSH_FUA, bio); + submit_bio(bio); } void md_super_wait(struct mddev *mddev) @@ -761,6 +763,7 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, bio->bi_bdev = (metadata_op && rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; + bio->bi_rw = rw; if (metadata_op) bio->bi_iter.bi_sector = sector + rdev->sb_start; else if (rdev->mddev->reshape_position != MaxSector && @@ -770,7 +773,8 @@ int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, else bio->bi_iter.bi_sector = sector + rdev->data_offset; bio_add_page(bio, page, size, 0); - submit_bio_wait(rw, bio); + + submit_bio_wait(bio); ret = !bio->bi_error; bio_put(bio); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index c7c8cde..bc95d4d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2208,7 +2208,8 @@ static int narrow_write_error(struct r1bio *r1_bio, int i) bio_trim(wbio, sector - r1_bio->sector, sectors); wbio->bi_iter.bi_sector += rdev->data_offset; wbio->bi_bdev = rdev->bdev; - if (submit_bio_wait(WRITE, wbio) < 0) + + if (submit_bio_wait(wbio) < 0) /* failure! */ ok = rdev_set_badblocks(rdev, sector, sectors, 0) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c7de2a5..0be6497 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2474,7 +2474,9 @@ static int narrow_write_error(struct r10bio *r10_bio, int i) choose_data_offset(r10_bio, rdev) + (sector - r10_bio->sector)); wbio->bi_bdev = rdev->bdev; - if (submit_bio_wait(WRITE, wbio) < 0) + wbio->bi_rw = WRITE; + + if (submit_bio_wait(wbio) < 0) /* Failure! */ ok = rdev_set_badblocks(rdev, sector, sectors, 0) diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index e889e2d..0b01453 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -254,7 +254,7 @@ static void r5l_submit_current_io(struct r5l_log *log) __r5l_set_io_unit_state(io, IO_UNIT_IO_START); spin_unlock_irqrestore(&log->io_list_lock, flags); - submit_bio(WRITE, io->current_bio); + submit_bio(io->current_bio); } static struct bio *r5l_bio_alloc(struct r5l_log *log) @@ -373,7 +373,7 @@ static void r5l_append_payload_page(struct r5l_log *log, struct page *page) io->current_bio = r5l_bio_alloc(log); bio_chain(io->current_bio, prev); - submit_bio(WRITE, prev); + submit_bio(prev); } if (!bio_add_page(io->current_bio, page, PAGE_SIZE, 0)) @@ -686,7 +686,8 @@ void r5l_flush_stripe_to_raid(struct r5l_log *log) bio_reset(&log->flush_bio); log->flush_bio.bi_bdev = log->rdev->bdev; log->flush_bio.bi_end_io = r5l_log_flush_endio; - submit_bio(WRITE_FLUSH, &log->flush_bio); + log->flush_bio.bi_rw = WRITE_FLUSH; + submit_bio(&log->flush_bio); } static void r5l_write_super(struct r5l_log *log, sector_t cp); diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 7c4efb4..c25109c 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -312,7 +312,7 @@ static void iblock_bio_done(struct bio *bio) } static struct bio * -iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) +iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num, int rw) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); struct bio *bio; @@ -334,18 +334,19 @@ iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num) bio->bi_private = cmd; bio->bi_end_io = &iblock_bio_done; bio->bi_iter.bi_sector = lba; + bio->bi_rw = rw; return bio; } -static void iblock_submit_bios(struct bio_list *list, int rw) +static void iblock_submit_bios(struct bio_list *list) { struct blk_plug plug; struct bio *bio; blk_start_plug(&plug); while ((bio = bio_list_pop(list))) - submit_bio(rw, bio); + submit_bio(bio); blk_finish_plug(&plug); } @@ -387,9 +388,10 @@ iblock_execute_sync_cache(struct se_cmd *cmd) bio = bio_alloc(GFP_KERNEL, 0); bio->bi_end_io = iblock_end_io_flush; bio->bi_bdev = ib_dev->ibd_bd; + bio->bi_rw = WRITE_FLUSH; if (!immed) bio->bi_private = cmd; - submit_bio(WRITE_FLUSH, bio); + submit_bio(bio); return 0; } @@ -478,7 +480,7 @@ iblock_execute_write_same(struct se_cmd *cmd) goto fail; cmd->priv = ibr; - bio = iblock_get_bio(cmd, block_lba, 1); + bio = iblock_get_bio(cmd, block_lba, 1, WRITE); if (!bio) goto fail_free_ibr; @@ -491,7 +493,7 @@ iblock_execute_write_same(struct se_cmd *cmd) while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) != sg->length) { - bio = iblock_get_bio(cmd, block_lba, 1); + bio = iblock_get_bio(cmd, block_lba, 1, WRITE); if (!bio) goto fail_put_bios; @@ -504,7 +506,7 @@ iblock_execute_write_same(struct se_cmd *cmd) sectors -= 1; } - iblock_submit_bios(&list, WRITE); + iblock_submit_bios(&list); return 0; fail_put_bios: @@ -712,7 +714,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, return 0; } - bio = iblock_get_bio(cmd, block_lba, sgl_nents); + bio = iblock_get_bio(cmd, block_lba, sgl_nents, rw); if (!bio) goto fail_free_ibr; @@ -732,11 +734,11 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) != sg->length) { if (bio_cnt >= IBLOCK_MAX_BIO_PER_TASK) { - iblock_submit_bios(&list, rw); + iblock_submit_bios(&list); bio_cnt = 0; } - bio = iblock_get_bio(cmd, block_lba, sg_num); + bio = iblock_get_bio(cmd, block_lba, sg_num, rw); if (!bio) goto fail_put_bios; @@ -756,7 +758,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, goto fail_put_bios; } - iblock_submit_bios(&list, rw); + iblock_submit_bios(&list); iblock_complete_cmd(cmd); return 0; diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index b677a6e..50f8191 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -1673,6 +1673,7 @@ static int btrfsic_read_block(struct btrfsic_state *state, } bio->bi_bdev = block_ctx->dev->bdev; bio->bi_iter.bi_sector = dev_bytenr >> 9; + bio->bi_rw = READ; for (j = i; j < num_pages; j++) { ret = bio_add_page(bio, block_ctx->pagev[j], @@ -1685,7 +1686,7 @@ static int btrfsic_read_block(struct btrfsic_state *state, "btrfsic: error, failed to add a single page!\n"); return -1; } - if (submit_bio_wait(READ, bio)) { + if (submit_bio_wait(bio)) { printk(KERN_INFO "btrfsic: read error at logical %llu dev %s!\n", block_ctx->start, block_ctx->dev->name); @@ -2918,9 +2919,10 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh) return submit_bh(rw, bh); } -static void __btrfsic_submit_bio(int rw, struct bio *bio) +static void __btrfsic_submit_bio(struct bio *bio) { struct btrfsic_dev_state *dev_state; + int rw = bio->bi_rw; if (!btrfsic_is_initialized) return; @@ -3016,16 +3018,16 @@ leave: mutex_unlock(&btrfsic_mutex); } -void btrfsic_submit_bio(int rw, struct bio *bio) +void btrfsic_submit_bio(struct bio *bio) { - __btrfsic_submit_bio(rw, bio); - submit_bio(rw, bio); + __btrfsic_submit_bio(bio); + submit_bio(bio); } -int btrfsic_submit_bio_wait(int rw, struct bio *bio) +int btrfsic_submit_bio_wait(struct bio *bio) { - __btrfsic_submit_bio(rw, bio); - return submit_bio_wait(rw, bio); + __btrfsic_submit_bio(bio); + return submit_bio_wait(bio); } int btrfsic_mount(struct btrfs_root *root, diff --git a/fs/btrfs/check-integrity.h b/fs/btrfs/check-integrity.h index 13b8566..c04e249 100644 --- a/fs/btrfs/check-integrity.h +++ b/fs/btrfs/check-integrity.h @@ -21,8 +21,8 @@ #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY int btrfsic_submit_bh(int rw, struct buffer_head *bh); -void btrfsic_submit_bio(int rw, struct bio *bio); -int btrfsic_submit_bio_wait(int rw, struct bio *bio); +void btrfsic_submit_bio(struct bio *bio); +int btrfsic_submit_bio_wait(struct bio *bio); #else #define btrfsic_submit_bh submit_bh #define btrfsic_submit_bio submit_bio diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 6628fca..3666558 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3486,12 +3486,13 @@ static int write_dev_flush(struct btrfs_device *device, int wait) bio->bi_end_io = btrfs_end_empty_barrier; bio->bi_bdev = device->bdev; + bio->bi_rw = WRITE_FLUSH; init_completion(&device->flush_wait); bio->bi_private = &device->flush_wait; device->flush_bio = bio; bio_get(bio); - btrfsic_submit_bio(WRITE_FLUSH, bio); + btrfsic_submit_bio(bio); return 0; } diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 3cd5782..c1e6f20 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2041,9 +2041,10 @@ int repair_io_failure(struct inode *inode, u64 start, u64 length, u64 logical, return -EIO; } bio->bi_bdev = dev->bdev; + bio->bi_rw = WRITE_SYNC; bio_add_page(bio, page, length, pg_offset); - if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) { + if (btrfsic_submit_bio_wait(bio)) { /* try to remap that extent elsewhere? */ bio_put(bio); btrfs_dev_stat_inc_and_print(dev, BTRFS_DEV_STAT_WRITE_ERRS); @@ -2725,14 +2726,14 @@ static int __must_check submit_one_bio(int rw, struct bio *bio, start = page_offset(page) + bvec->bv_offset; bio->bi_private = NULL; - + bio->bi_rw = rw; bio_get(bio); if (tree->ops && tree->ops->submit_bio_hook) ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio, mirror_num, bio_flags, start); else - btrfsic_submit_bio(rw, bio); + btrfsic_submit_bio(bio); bio_put(bio); return ret; diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index f8b6d41..36d5bf7 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -1320,7 +1320,9 @@ write_data: bio->bi_private = rbio; bio->bi_end_io = raid_write_end_io; - submit_bio(WRITE, bio); + bio->bi_rw = WRITE; + + submit_bio(bio); } return; @@ -1573,11 +1575,12 @@ static int raid56_rmw_stripe(struct btrfs_raid_bio *rbio) bio->bi_private = rbio; bio->bi_end_io = raid_rmw_end_io; + bio->bi_rw = READ; btrfs_bio_wq_end_io(rbio->fs_info, bio, BTRFS_WQ_ENDIO_RAID56); - submit_bio(READ, bio); + submit_bio(bio); } /* the actual write will happen once the reads are done */ return 0; @@ -2097,11 +2100,12 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio) bio->bi_private = rbio; bio->bi_end_io = raid_recover_end_io; + bio->bi_rw = READ; btrfs_bio_wq_end_io(rbio->fs_info, bio, BTRFS_WQ_ENDIO_RAID56); - submit_bio(READ, bio); + submit_bio(bio); } out: return 0; @@ -2433,7 +2437,9 @@ submit_write: bio->bi_private = rbio; bio->bi_end_io = raid_write_end_io; - submit_bio(WRITE, bio); + bio->bi_rw = WRITE; + + submit_bio(bio); } return; @@ -2610,11 +2616,12 @@ static void raid56_parity_scrub_stripe(struct btrfs_raid_bio *rbio) bio->bi_private = rbio; bio->bi_end_io = raid56_parity_scrub_end_io; + bio->bi_rw = READ; btrfs_bio_wq_end_io(rbio->fs_info, bio, BTRFS_WQ_ENDIO_RAID56); - submit_bio(READ, bio); + submit_bio(bio); } /* the actual write will happen once the reads are done */ return; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 46d847f..44da605 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1504,8 +1504,9 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info, sblock->no_io_error_seen = 0; } else { bio->bi_iter.bi_sector = page->physical >> 9; + bio->bi_rw = READ; - if (btrfsic_submit_bio_wait(READ, bio)) + if (btrfsic_submit_bio_wait(bio)) sblock->no_io_error_seen = 0; } @@ -1583,6 +1584,7 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, return -EIO; bio->bi_bdev = page_bad->dev->bdev; bio->bi_iter.bi_sector = page_bad->physical >> 9; + bio->bi_rw = WRITE; ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0); if (PAGE_SIZE != ret) { @@ -1590,7 +1592,7 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, return -EIO; } - if (btrfsic_submit_bio_wait(WRITE, bio)) { + if (btrfsic_submit_bio_wait(bio)) { btrfs_dev_stat_inc_and_print(page_bad->dev, BTRFS_DEV_STAT_WRITE_ERRS); btrfs_dev_replace_stats_inc( @@ -1684,6 +1686,7 @@ again: bio->bi_end_io = scrub_wr_bio_end_io; bio->bi_bdev = sbio->dev->bdev; bio->bi_iter.bi_sector = sbio->physical >> 9; + bio->bi_rw = WRITE; sbio->err = 0; } else if (sbio->physical + sbio->page_count * PAGE_SIZE != spage->physical_for_dev_replace || @@ -1731,7 +1734,7 @@ static void scrub_wr_submit(struct scrub_ctx *sctx) * orders the requests before sending them to the driver which * doubled the write performance on spinning disks when measured * with Linux 3.5 */ - btrfsic_submit_bio(WRITE, sbio->bio); + btrfsic_submit_bio(sbio->bio); } static void scrub_wr_bio_end_io(struct bio *bio) @@ -2041,7 +2044,7 @@ static void scrub_submit(struct scrub_ctx *sctx) sbio = sctx->bios[sctx->curr]; sctx->curr = -1; scrub_pending_bio_inc(sctx); - btrfsic_submit_bio(READ, sbio->bio); + btrfsic_submit_bio(sbio->bio); } static int scrub_add_page_to_rd_bio(struct scrub_ctx *sctx, @@ -2088,6 +2091,7 @@ again: bio->bi_end_io = scrub_bio_end_io; bio->bi_bdev = sbio->dev->bdev; bio->bi_iter.bi_sector = sbio->physical >> 9; + bio->bi_rw = READ; sbio->err = 0; } else if (sbio->physical + sbio->page_count * PAGE_SIZE != spage->physical || @@ -4392,6 +4396,7 @@ static int write_page_nocow(struct scrub_ctx *sctx, bio->bi_iter.bi_size = 0; bio->bi_iter.bi_sector = physical_for_dev_replace >> 9; bio->bi_bdev = dev->bdev; + bio->bi_rw = WRITE_SYNC; ret = bio_add_page(bio, page, PAGE_SIZE, 0); if (ret != PAGE_SIZE) { leave_with_eio: @@ -4400,7 +4405,7 @@ leave_with_eio: return -EIO; } - if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) + if (btrfsic_submit_bio_wait(bio)) goto leave_with_eio; bio_put(bio); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index bdc6256..d549f23 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -462,7 +462,7 @@ loop_lock: sync_pending = 0; } - btrfsic_submit_bio(cur->bi_rw, cur); + btrfsic_submit_bio(cur); num_run++; batch_run++; @@ -5988,7 +5988,7 @@ static void btrfs_end_bio(struct bio *bio) */ static noinline void btrfs_schedule_bio(struct btrfs_root *root, struct btrfs_device *device, - int rw, struct bio *bio) + struct bio *bio) { int should_queue = 1; struct btrfs_pending_bios *pending_bios; @@ -5999,9 +5999,9 @@ static noinline void btrfs_schedule_bio(struct btrfs_root *root, } /* don't bother with additional async steps for reads, right now */ - if (!(rw & REQ_WRITE)) { + if (!(bio->bi_rw & REQ_WRITE)) { bio_get(bio); - btrfsic_submit_bio(rw, bio); + btrfsic_submit_bio(bio); bio_put(bio); return; } @@ -6015,7 +6015,6 @@ static noinline void btrfs_schedule_bio(struct btrfs_root *root, atomic_inc(&root->fs_info->nr_async_bios); WARN_ON(bio->bi_next); bio->bi_next = NULL; - bio->bi_rw |= rw; spin_lock(&device->io_lock); if (bio->bi_rw & REQ_SYNC) @@ -6049,6 +6048,7 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio, btrfs_io_bio(bio)->stripe_index = dev_nr; bio->bi_end_io = btrfs_end_bio; bio->bi_iter.bi_sector = physical >> 9; + bio->bi_rw |= rw; #ifdef DEBUG { struct rcu_string *name; @@ -6067,9 +6067,9 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio, btrfs_bio_counter_inc_noblocked(root->fs_info); if (async) - btrfs_schedule_bio(root, dev, rw, bio); + btrfs_schedule_bio(root, dev, bio); else - btrfsic_submit_bio(rw, bio); + btrfsic_submit_bio(bio); } static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical) diff --git a/fs/buffer.c b/fs/buffer.c index 754813a..9a55e7f 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -3030,8 +3030,9 @@ static int submit_bh_wbc(int rw, struct buffer_head *bh, rw |= REQ_META; if (buffer_prio(bh)) rw |= REQ_PRIO; + bio->bi_rw = rw; - submit_bio(rw, bio); + submit_bio(bio); return 0; } diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 2fc8c43..5b75856 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -318,6 +318,7 @@ int fscrypt_zeroout_range(struct inode *inode, pgoff_t lblk, bio->bi_bdev = inode->i_sb->s_bdev; bio->bi_iter.bi_sector = pblk << (inode->i_sb->s_blocksize_bits - 9); + bio->bi_rw = WRITE; ret = bio_add_page(bio, ciphertext_page, inode->i_sb->s_blocksize, 0); if (ret != inode->i_sb->s_blocksize) { @@ -327,7 +328,7 @@ int fscrypt_zeroout_range(struct inode *inode, pgoff_t lblk, err = -EIO; goto errout; } - err = submit_bio_wait(WRITE, bio); + err = submit_bio_wait(bio); if ((err == 0) && bio->bi_error) err = -EIO; bio_put(bio); diff --git a/fs/direct-io.c b/fs/direct-io.c index f3b4408..1bcdd5d 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -375,6 +375,7 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, bio->bi_bdev = bdev; bio->bi_iter.bi_sector = first_sector; + bio->bi_rw = dio->rw; if (dio->is_async) bio->bi_end_io = dio_bio_end_aio; else @@ -412,7 +413,7 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio) sdio->logical_offset_in_bio); dio->bio_cookie = BLK_QC_T_NONE; } else - dio->bio_cookie = submit_bio(dio->rw, bio); + dio->bio_cookie = submit_bio(bio); sdio->bio = NULL; sdio->boundary = 0; diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 2a01df9..a72dbcc 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -342,7 +342,8 @@ void ext4_io_submit(struct ext4_io_submit *io) if (bio) { int io_op = io->io_wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE; - submit_bio(io_op, io->io_bio); + io->io_bio->bi_rw = io_op; + submit_bio(io->io_bio); } io->io_bio = NULL; } diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index dc54a4b..130bd45 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -271,7 +271,7 @@ int ext4_mpage_readpages(struct address_space *mapping, */ if (bio && (last_block_in_bio != blocks[0] - 1)) { submit_and_realloc: - submit_bio(READ, bio); + submit_bio(bio); bio = NULL; } if (bio == NULL) { @@ -294,6 +294,7 @@ int ext4_mpage_readpages(struct address_space *mapping, bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9); bio->bi_end_io = mpage_end_io; bio->bi_private = ctx; + bio->bi_rw = READ; } length = first_hole << blkbits; @@ -303,14 +304,14 @@ int ext4_mpage_readpages(struct address_space *mapping, if (((map.m_flags & EXT4_MAP_BOUNDARY) && (relative_block == map.m_len)) || (first_hole != blocks_per_page)) { - submit_bio(READ, bio); + submit_bio(bio); bio = NULL; } else last_block_in_bio = blocks[blocks_per_page - 1]; goto next_page; confused: if (bio) { - submit_bio(READ, bio); + submit_bio(bio); bio = NULL; } if (!PageUptodate(page)) @@ -323,6 +324,6 @@ int ext4_mpage_readpages(struct address_space *mapping, } BUG_ON(pages && !list_empty(pages)); if (bio) - submit_bio(READ, bio); + submit_bio(bio); return 0; } diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 9a8bbc1..c595c8f 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -102,7 +102,8 @@ static inline void __submit_bio(struct f2fs_sb_info *sbi, int rw, { if (!is_read_io(rw)) atomic_inc(&sbi->nr_wb_bios); - submit_bio(rw, bio); + bio->bi_rw = rw; + submit_bio(bio); } static void __submit_merged_bio(struct f2fs_bio_info *io) @@ -1080,6 +1081,7 @@ submit_and_realloc: bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(block_nr); bio->bi_end_io = f2fs_read_end_io; bio->bi_private = ctx; + bio->bi_rw = READ; } if (bio_add_page(bio, page, blocksize, 0) < blocksize) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 2e6f537..3fe2fab 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -406,7 +406,8 @@ repeat: fcc->dispatch_list = llist_reverse_order(fcc->dispatch_list); bio->bi_bdev = sbi->sb->s_bdev; - ret = submit_bio_wait(WRITE_FLUSH, bio); + bio->bi_rw = WRITE_FLUSH; + ret = submit_bio_wait(bio); llist_for_each_entry_safe(cmd, next, fcc->dispatch_list, llnode) { @@ -438,7 +439,8 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi) int ret; bio->bi_bdev = sbi->sb->s_bdev; - ret = submit_bio_wait(WRITE_FLUSH, bio); + bio->bi_rw = WRITE_FLUSH; + ret = submit_bio_wait(bio); bio_put(bio); return ret; } diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index d5369a1..ce28242 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -240,7 +240,8 @@ void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int rw) { if (sdp->sd_log_bio) { atomic_inc(&sdp->sd_log_in_flight); - submit_bio(rw, sdp->sd_log_bio); + sdp->sd_log_bio->bi_rw = rw; + submit_bio(sdp->sd_log_bio); sdp->sd_log_bio = NULL; } } diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 8eaadab..66670e1 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -230,7 +230,8 @@ static void gfs2_submit_bhs(int rw, struct buffer_head *bhs[], int num) bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); } bio->bi_end_io = gfs2_meta_read_endio; - submit_bio(rw, bio); + bio->bi_rw = rw; + submit_bio(bio); } /** diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 4546360..d9e19f6 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -246,7 +246,8 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) bio->bi_end_io = end_bio_io_page; bio->bi_private = page; - submit_bio(READ_SYNC | REQ_META, bio); + bio->bi_rw = READ_SYNC | REQ_META; + submit_bio(bio); wait_on_page_locked(page); bio_put(bio); if (!PageUptodate(page)) { diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index cc62356..d026bb3 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -65,6 +65,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, bio = bio_alloc(GFP_NOIO, 1); bio->bi_iter.bi_sector = sector; bio->bi_bdev = sb->s_bdev; + bio->bi_rw = rw; if (!(rw & WRITE) && data) *data = (u8 *)buf + offset; @@ -83,7 +84,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, buf = (u8 *)buf + len; } - ret = submit_bio_wait(rw, bio); + ret = submit_bio_wait(bio); out: bio_put(bio); return ret < 0 ? ret : 0; diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 63759d7..3ee3f32 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -2002,12 +2002,13 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) bio->bi_end_io = lbmIODone; bio->bi_private = bp; + bio->bi_rw = READ_SYNC; /*check if journaling to disk has been disabled*/ if (log->no_integrity) { bio->bi_iter.bi_size = 0; lbmIODone(bio); } else { - submit_bio(READ_SYNC, bio); + submit_bio(bio); } wait_event(bp->l_ioevent, (bp->l_flag != lbmREAD)); @@ -2145,13 +2146,14 @@ static void lbmStartIO(struct lbuf * bp) bio->bi_end_io = lbmIODone; bio->bi_private = bp; + bio->bi_rw = WRITE_SYNC; /* check if journaling to disk has been disabled */ if (log->no_integrity) { bio->bi_iter.bi_size = 0; lbmIODone(bio); } else { - submit_bio(WRITE_SYNC, bio); + submit_bio(bio); INCREMENT(lmStat.submitted); } } diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index b60e015..9725443 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -411,7 +411,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) inc_io(page); if (!bio->bi_iter.bi_size) goto dump_bio; - submit_bio(WRITE, bio); + submit_bio(bio); nr_underway++; bio = NULL; } else @@ -434,6 +434,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) bio->bi_iter.bi_sector = pblock << (inode->i_blkbits - 9); bio->bi_end_io = metapage_write_end_io; bio->bi_private = page; + bio->bi_rw = WRITE; /* Don't call bio_add_page yet, we may add to this vec */ bio_offset = offset; @@ -448,7 +449,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) if (!bio->bi_iter.bi_size) goto dump_bio; - submit_bio(WRITE, bio); + submit_bio(bio); nr_underway++; } if (redirty) @@ -506,7 +507,7 @@ static int metapage_readpage(struct file *fp, struct page *page) insert_metapage(page, NULL); inc_io(page); if (bio) - submit_bio(READ, bio); + submit_bio(bio); bio = bio_alloc(GFP_NOFS, 1); bio->bi_bdev = inode->i_sb->s_bdev; @@ -514,6 +515,7 @@ static int metapage_readpage(struct file *fp, struct page *page) pblock << (inode->i_blkbits - 9); bio->bi_end_io = metapage_read_end_io; bio->bi_private = page; + bio->bi_rw = READ; len = xlen << inode->i_blkbits; offset = block_offset << inode->i_blkbits; if (bio_add_page(bio, page, len, offset) < len) @@ -523,7 +525,7 @@ static int metapage_readpage(struct file *fp, struct page *page) block_offset++; } if (bio) - submit_bio(READ, bio); + submit_bio(bio); else unlock_page(page); diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index cc26f8f..29704bd 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -29,8 +29,9 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw) bio.bi_bdev = bdev; bio.bi_iter.bi_sector = page->index * (PAGE_SIZE >> 9); bio.bi_iter.bi_size = PAGE_SIZE; + bio.bi_rw = rw; - return submit_bio_wait(rw, &bio); + return submit_bio_wait(&bio); } static int bdev_readpage(void *_sb, struct page *page) @@ -95,8 +96,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = writeseg_end_io; + bio->bi_rw = WRITE; atomic_inc(&super->s_pending_writes); - submit_bio(WRITE, bio); + submit_bio(bio); ofs += i * PAGE_SIZE; index += i; @@ -122,8 +124,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = writeseg_end_io; + bio->bi_rw = WRITE; atomic_inc(&super->s_pending_writes); - submit_bio(WRITE, bio); + submit_bio(bio); return 0; } @@ -185,8 +188,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = erase_end_io; + bio->bi_rw = WRITE; atomic_inc(&super->s_pending_writes); - submit_bio(WRITE, bio); + submit_bio(bio); ofs += i * PAGE_SIZE; index += i; @@ -206,8 +210,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = erase_end_io; + bio->bi_rw = WRITE; atomic_inc(&super->s_pending_writes); - submit_bio(WRITE, bio); + submit_bio(bio); return 0; } diff --git a/fs/mpage.c b/fs/mpage.c index eedc644..2c251ec 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -59,8 +59,9 @@ static void mpage_end_io(struct bio *bio) static struct bio *mpage_bio_submit(int rw, struct bio *bio) { bio->bi_end_io = mpage_end_io; + bio->bi_rw = rw; guard_bio_eod(rw, bio); - submit_bio(rw, bio); + submit_bio(bio); return NULL; } diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 17a42e4..4c79f4d 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -102,14 +102,15 @@ static inline void put_parallel(struct parallel_io *p) } static struct bio * -bl_submit_bio(int rw, struct bio *bio) +bl_submit_bio(struct bio *bio) { if (bio) { get_parallel(bio->bi_private); dprintk("%s submitting %s bio %u@%llu\n", __func__, - rw == READ ? "read" : "write", bio->bi_iter.bi_size, + bio->bi_rw == READ ? "read" : "write", + bio->bi_iter.bi_size, (unsigned long long)bio->bi_iter.bi_sector); - submit_bio(rw, bio); + submit_bio(bio); } return NULL; } @@ -158,7 +159,7 @@ do_add_page_to_bio(struct bio *bio, int npg, int rw, sector_t isect, if (disk_addr < map->start || disk_addr >= map->start + map->len) { if (!dev->map(dev, disk_addr, map)) return ERR_PTR(-EIO); - bio = bl_submit_bio(rw, bio); + bio = bl_submit_bio(bio); } disk_addr += map->disk_offset; disk_addr -= map->start; @@ -174,9 +175,10 @@ retry: disk_addr >> SECTOR_SHIFT, end_io, par); if (!bio) return ERR_PTR(-ENOMEM); + bio->bi_rw = rw; } if (bio_add_page(bio, page, *len, offset) < *len) { - bio = bl_submit_bio(rw, bio); + bio = bl_submit_bio(bio); goto retry; } return bio; @@ -252,7 +254,7 @@ bl_read_pagelist(struct nfs_pgio_header *header) for (i = pg_index; i < header->page_array.npages; i++) { if (extent_length <= 0) { /* We've used up the previous extent */ - bio = bl_submit_bio(READ, bio); + bio = bl_submit_bio(bio); /* Get the next one */ if (!ext_tree_lookup(bl, isect, &be, false)) { @@ -273,7 +275,7 @@ bl_read_pagelist(struct nfs_pgio_header *header) } if (is_hole(&be)) { - bio = bl_submit_bio(READ, bio); + bio = bl_submit_bio(bio); /* Fill hole w/ zeroes w/o accessing device */ dprintk("%s Zeroing page for hole\n", __func__); zero_user_segment(pages[i], pg_offset, pg_len); @@ -306,7 +308,7 @@ bl_read_pagelist(struct nfs_pgio_header *header) header->res.count = (isect << SECTOR_SHIFT) - header->args.offset; } out: - bl_submit_bio(READ, bio); + bl_submit_bio(bio); blk_finish_plug(&plug); put_parallel(par); return PNFS_ATTEMPTED; @@ -398,7 +400,7 @@ bl_write_pagelist(struct nfs_pgio_header *header, int sync) for (i = pg_index; i < header->page_array.npages; i++) { if (extent_length <= 0) { /* We've used up the previous extent */ - bio = bl_submit_bio(WRITE, bio); + bio = bl_submit_bio(bio); /* Get the next one */ if (!ext_tree_lookup(bl, isect, &be, true)) { header->pnfs_error = -EINVAL; @@ -427,7 +429,7 @@ bl_write_pagelist(struct nfs_pgio_header *header, int sync) header->res.count = header->args.count; out: - bl_submit_bio(WRITE, bio); + bl_submit_bio(bio); blk_finish_plug(&plug); put_parallel(par); return PNFS_ATTEMPTED; diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index bf36df1..0f62909 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -364,7 +364,8 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, bio->bi_end_io = nilfs_end_bio_write; bio->bi_private = segbuf; - submit_bio(mode, bio); + bio->bi_rw = mode; + submit_bio(bio); segbuf->sb_nbio++; wi->bio = NULL; diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 6aaf3e3..8b1d86e 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -530,7 +530,7 @@ static void o2hb_bio_end_io(struct bio *bio) static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, struct o2hb_bio_wait_ctxt *wc, unsigned int *current_slot, - unsigned int max_slots) + unsigned int max_slots, int rw) { int len, current_page; unsigned int vec_len, vec_start; @@ -556,6 +556,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, bio->bi_bdev = reg->hr_bdev; bio->bi_private = wc; bio->bi_end_io = o2hb_bio_end_io; + bio->bi_rw = rw; vec_start = (cs << bits) % PAGE_SIZE; while(cs < max_slots) { @@ -591,7 +592,8 @@ static int o2hb_read_slots(struct o2hb_region *reg, o2hb_bio_wait_init(&wc); while(current_slot < max_slots) { - bio = o2hb_setup_one_bio(reg, &wc, ¤t_slot, max_slots); + bio = o2hb_setup_one_bio(reg, &wc, ¤t_slot, max_slots, + READ); if (IS_ERR(bio)) { status = PTR_ERR(bio); mlog_errno(status); @@ -599,7 +601,7 @@ static int o2hb_read_slots(struct o2hb_region *reg, } atomic_inc(&wc.wc_num_reqs); - submit_bio(READ, bio); + submit_bio(bio); } status = 0; @@ -623,7 +625,7 @@ static int o2hb_issue_node_write(struct o2hb_region *reg, slot = o2nm_this_node(); - bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1); + bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1, WRITE_SYNC); if (IS_ERR(bio)) { status = PTR_ERR(bio); mlog_errno(status); @@ -631,7 +633,7 @@ static int o2hb_issue_node_write(struct o2hb_region *reg, } atomic_inc(&write_wc->wc_num_reqs); - submit_bio(WRITE_SYNC, bio); + submit_bio(bio); status = 0; bail: diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 4c463b9..0cd1603 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -438,7 +438,10 @@ xfs_submit_ioend( ioend->io_bio->bi_private = ioend; ioend->io_bio->bi_end_io = xfs_end_bio; - + if (wbc->sync_mode == WB_SYNC_ALL) + ioend->io_bio->bi_rw = WRITE_SYNC; + else + ioend->io_bio->bi_rw = WRITE; /* * If we are failing the IO now, just mark the ioend with an * error and finish it. This will run IO completion immediately @@ -451,8 +454,7 @@ xfs_submit_ioend( return status; } - submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, - ioend->io_bio); + submit_bio(ioend->io_bio); return 0; } @@ -510,8 +512,11 @@ xfs_chain_bio( bio_chain(ioend->io_bio, new); bio_get(ioend->io_bio); /* for xfs_destroy_ioend */ - submit_bio(wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE, - ioend->io_bio); + if (wbc->sync_mode == WB_SYNC_ALL) + ioend->io_bio->bi_rw = WRITE_SYNC; + else + ioend->io_bio->bi_rw = WRITE; + submit_bio(ioend->io_bio); ioend->io_bio = new; } diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index e71cfbd..0777c67 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1166,7 +1166,7 @@ next_chunk: bio->bi_iter.bi_sector = sector; bio->bi_end_io = xfs_buf_bio_end_io; bio->bi_private = bp; - + bio->bi_rw = rw; for (; size && nr_pages; nr_pages--, page_index++) { int rbytes, nbytes = PAGE_SIZE - offset; @@ -1190,7 +1190,7 @@ next_chunk: flush_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); } - submit_bio(rw, bio); + submit_bio(bio); if (size) goto next_chunk; } else { diff --git a/include/linux/bio.h b/include/linux/bio.h index 9faebf7..3bde942 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -473,7 +473,7 @@ static inline void bio_io_error(struct bio *bio) struct request_queue; extern int bio_phys_segments(struct request_queue *, struct bio *); -extern int submit_bio_wait(int rw, struct bio *bio); +extern int submit_bio_wait(struct bio *bio); extern void bio_advance(struct bio *, unsigned); extern void bio_init(struct bio *); diff --git a/include/linux/fs.h b/include/linux/fs.h index dd28814..65e4c51 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2747,7 +2747,7 @@ static inline void remove_inode_hash(struct inode *inode) extern void inode_sb_list_add(struct inode *inode); #ifdef CONFIG_BLOCK -extern blk_qc_t submit_bio(int, struct bio *); +extern blk_qc_t submit_bio(struct bio *); extern int bdev_read_only(struct block_device *); #endif extern int set_blocksize(struct block_device *, int); diff --git a/kernel/power/swap.c b/kernel/power/swap.c index 160e100..be227f5 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -271,6 +271,7 @@ static int hib_submit_io(int rw, pgoff_t page_off, void *addr, bio = bio_alloc(__GFP_RECLAIM | __GFP_HIGH, 1); bio->bi_iter.bi_sector = page_off * (PAGE_SIZE >> 9); bio->bi_bdev = hib_resume_bdev; + bio->bi_rw = rw; if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { printk(KERN_ERR "PM: Adding page to bio failed at %llu\n", @@ -283,9 +284,9 @@ static int hib_submit_io(int rw, pgoff_t page_off, void *addr, bio->bi_end_io = hib_end_io; bio->bi_private = hb; atomic_inc(&hb->count); - submit_bio(rw, bio); + submit_bio(bio); } else { - error = submit_bio_wait(rw, bio); + error = submit_bio_wait(bio); bio_put(bio); } diff --git a/mm/page_io.c b/mm/page_io.c index 242dba0..5a5fd66 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -259,7 +259,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, bio_end_io_t end_write_func) { struct bio *bio; - int ret, rw = WRITE; + int ret; struct swap_info_struct *sis = page_swap_info(page); if (sis->flags & SWP_FILE) { @@ -317,12 +317,13 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, ret = -ENOMEM; goto out; } + bio->bi_rw = WRITE; if (wbc->sync_mode == WB_SYNC_ALL) - rw |= REQ_SYNC; + bio->bi_rw |= REQ_SYNC; count_vm_event(PSWPOUT); set_page_writeback(page); unlock_page(page); - submit_bio(rw, bio); + submit_bio(bio); out: return ret; } @@ -369,8 +370,9 @@ int swap_readpage(struct page *page) ret = -ENOMEM; goto out; } + bio->bi_rw = READ; count_vm_event(PSWPIN); - submit_bio(READ, bio); + submit_bio(bio); out: return ret; } -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5A7657CA1 for ; Sun, 5 Jun 2016 14:32:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2F0D8304043 for ; Sun, 5 Jun 2016 12:32:46 -0700 (PDT) X-ASG-Debug-ID: 1465155164-04cb6c2dbcb58da0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 67tLHsEWnioan9yg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:45 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6501FC06C9CB; Sun, 5 Jun 2016 19:32:44 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9C003130; Sun, 5 Jun 2016 15:32:42 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 05/45] block, drivers, cgroup: use op_is_write helper instead of checking for REQ_WRITE Date: Sun, 5 Jun 2016 14:31:45 -0500 X-ASG-Orig-Subj: [PATCH 05/45] block, drivers, cgroup: use op_is_write helper instead of checking for REQ_WRITE Message-Id: <1465155145-10812-6-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sun, 05 Jun 2016 19:32:44 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155165 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5573 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie We currently set REQ_WRITE/WRITE for all non READ IOs like discard, flush, writesame, etc. In the next patches where we no longer set up the op as a bitmap, we will not be able to detect a operation direction like writesame by testing if REQ_WRITE is set. This patch converts the drivers and cgroup to use the op_is_write helper. This should just cover the simple cases. I did dm, md and bcache in their own patches because they were more involved. Signed-off-by: Mike Christie --- block/blk-core.c | 4 ++-- block/blk-merge.c | 2 +- drivers/ata/libata-scsi.c | 2 +- drivers/block/loop.c | 6 +++--- drivers/block/umem.c | 2 +- drivers/scsi/osd/osd_initiator.c | 4 ++-- include/linux/blk-cgroup.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index e953407..e8e5865 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2115,7 +2115,7 @@ blk_qc_t submit_bio(struct bio *bio) else count = bio_sectors(bio); - if (bio->bi_rw & WRITE) { + if (op_is_write(bio_op(bio))) { count_vm_events(PGPGOUT, count); } else { task_io_account_read(bio->bi_iter.bi_size); @@ -2126,7 +2126,7 @@ blk_qc_t submit_bio(struct bio *bio) char b[BDEVNAME_SIZE]; printk(KERN_DEBUG "%s(%d): %s block %Lu on %s (%u sectors)\n", current->comm, task_pid_nr(current), - (bio->bi_rw & WRITE) ? "WRITE" : "READ", + op_is_write(bio_op(bio)) ? "WRITE" : "READ", (unsigned long long)bio->bi_iter.bi_sector, bdevname(bio->bi_bdev, b), count); diff --git a/block/blk-merge.c b/block/blk-merge.c index 2613531..b198070 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -439,7 +439,7 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq, } if (q->dma_drain_size && q->dma_drain_needed(rq)) { - if (rq->cmd_flags & REQ_WRITE) + if (op_is_write(req_op(rq))) memset(q->dma_drain_buffer, 0, q->dma_drain_size); sg_unmark_end(sg); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index bfec66f..4c6eb22 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1190,7 +1190,7 @@ static int atapi_drain_needed(struct request *rq) if (likely(rq->cmd_type != REQ_TYPE_BLOCK_PC)) return 0; - if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_WRITE)) + if (!blk_rq_bytes(rq) || op_is_write(req_op(rq))) return 0; return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 1fa8cc2..e9f1701 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -447,7 +447,7 @@ static int lo_req_flush(struct loop_device *lo, struct request *rq) static inline void handle_partial_read(struct loop_cmd *cmd, long bytes) { - if (bytes < 0 || (cmd->rq->cmd_flags & REQ_WRITE)) + if (bytes < 0 || op_is_write(req_op(cmd->rq))) return; if (unlikely(bytes < blk_rq_bytes(cmd->rq))) { @@ -541,7 +541,7 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset; - if (rq->cmd_flags & REQ_WRITE) { + if (op_is_write(req_op(rq))) { if (rq->cmd_flags & REQ_FLUSH) ret = lo_req_flush(lo, rq); else if (rq->cmd_flags & REQ_DISCARD) @@ -1672,7 +1672,7 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx, static void loop_handle_cmd(struct loop_cmd *cmd) { - const bool write = cmd->rq->cmd_flags & REQ_WRITE; + const bool write = op_is_write(req_op(cmd->rq)); struct loop_device *lo = cmd->rq->q->queuedata; int ret = 0; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index 7939b9f..4b3ba74 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -462,7 +462,7 @@ static void process_page(unsigned long data) le32_to_cpu(desc->local_addr)>>9, le32_to_cpu(desc->transfer_size)); dump_dmastat(card, control); - } else if ((bio->bi_rw & REQ_WRITE) && + } else if (op_is_write(bio_op(bio)) && le32_to_cpu(desc->local_addr) >> 9 == card->init_size) { card->init_size += le32_to_cpu(desc->transfer_size) >> 9; diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 3b11aad..14ed39b 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -824,7 +824,7 @@ void osd_req_write(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, len); WARN_ON(or->out.bio || or->out.total_bytes); - WARN_ON(0 == (bio->bi_rw & REQ_WRITE)); + WARN_ON(!op_is_write(bio_op(bio))); or->out.bio = bio; or->out.total_bytes = len; } @@ -875,7 +875,7 @@ void osd_req_read(struct osd_request *or, { _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, len); WARN_ON(or->in.bio || or->in.total_bytes); - WARN_ON(bio->bi_rw & REQ_WRITE); + WARN_ON(op_is_write(bio_op(bio))); or->in.bio = bio; or->in.total_bytes = len; } diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index c02e669..04f9c8d 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -601,7 +601,7 @@ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, { struct percpu_counter *cnt; - if (rw & REQ_WRITE) + if (op_is_write(rw)) cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_WRITE]; else cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_READ]; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id AC2D87CA0 for ; Sun, 5 Jun 2016 14:32:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 158ECAC007 for ; Sun, 5 Jun 2016 12:32:43 -0700 (PDT) X-ASG-Debug-ID: 1465155160-04cb6c2dbbb58d90001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 6Dyl0hdelUzPVusN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:40 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D1F9F78234; Sun, 5 Jun 2016 19:32:39 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9A003130; Sun, 5 Jun 2016 15:32:37 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 03/45] fs: have submit_bh users pass in op and flags separately Date: Sun, 5 Jun 2016 14:31:43 -0500 X-ASG-Orig-Subj: [PATCH 03/45] fs: have submit_bh users pass in op and flags separately Message-Id: <1465155145-10812-4-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sun, 05 Jun 2016 19:32:39 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155160 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 31782 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This has submit_bh users pass in the operation and flags separately, so submit_bh_wbc can setup the bio op and bi_rw flags on the bio that is submitted. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- drivers/md/bitmap.c | 4 ++-- fs/btrfs/check-integrity.c | 24 ++++++++++---------- fs/btrfs/check-integrity.h | 2 +- fs/btrfs/disk-io.c | 4 ++-- fs/buffer.c | 53 +++++++++++++++++++++++---------------------- fs/ext4/balloc.c | 2 +- fs/ext4/ialloc.c | 2 +- fs/ext4/inode.c | 2 +- fs/ext4/mmp.c | 4 ++-- fs/fat/misc.c | 2 +- fs/gfs2/bmap.c | 2 +- fs/gfs2/dir.c | 2 +- fs/gfs2/meta_io.c | 6 ++--- fs/jbd2/commit.c | 6 ++--- fs/jbd2/journal.c | 8 +++---- fs/nilfs2/btnode.c | 6 ++--- fs/nilfs2/btnode.h | 2 +- fs/nilfs2/btree.c | 6 +++-- fs/nilfs2/gcinode.c | 5 +++-- fs/nilfs2/mdt.c | 11 +++++----- fs/ntfs/aops.c | 6 ++--- fs/ntfs/compress.c | 2 +- fs/ntfs/file.c | 2 +- fs/ntfs/logfile.c | 2 +- fs/ntfs/mft.c | 4 ++-- fs/ocfs2/buffer_head_io.c | 8 +++---- fs/reiserfs/inode.c | 4 ++-- fs/reiserfs/journal.c | 6 ++--- fs/ufs/util.c | 2 +- include/linux/buffer_head.h | 9 ++++---- 30 files changed, 102 insertions(+), 96 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index d8129ec..bc6dced 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -297,7 +297,7 @@ static void write_page(struct bitmap *bitmap, struct page *page, int wait) atomic_inc(&bitmap->pending_writes); set_buffer_locked(bh); set_buffer_mapped(bh); - submit_bh(WRITE | REQ_SYNC, bh); + submit_bh(REQ_OP_WRITE, REQ_SYNC, bh); bh = bh->b_this_page; } @@ -392,7 +392,7 @@ static int read_page(struct file *file, unsigned long index, atomic_inc(&bitmap->pending_writes); set_buffer_locked(bh); set_buffer_mapped(bh); - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); } block++; bh = bh->b_this_page; diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 50f8191..0d3748b 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -2856,12 +2856,12 @@ static struct btrfsic_dev_state *btrfsic_dev_state_lookup( return ds; } -int btrfsic_submit_bh(int rw, struct buffer_head *bh) +int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh) { struct btrfsic_dev_state *dev_state; if (!btrfsic_is_initialized) - return submit_bh(rw, bh); + return submit_bh(op, op_flags, bh); mutex_lock(&btrfsic_mutex); /* since btrfsic_submit_bh() might also be called before @@ -2870,26 +2870,26 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh) /* Only called to write the superblock (incl. FLUSH/FUA) */ if (NULL != dev_state && - (rw & WRITE) && bh->b_size > 0) { + (op == REQ_OP_WRITE) && bh->b_size > 0) { u64 dev_bytenr; dev_bytenr = 4096 * bh->b_blocknr; if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO - "submit_bh(rw=0x%x, blocknr=%llu (bytenr %llu)," - " size=%zu, data=%p, bdev=%p)\n", - rw, (unsigned long long)bh->b_blocknr, + "submit_bh(op=0x%x,0x%x, blocknr=%llu " + "(bytenr %llu), size=%zu, data=%p, bdev=%p)\n", + op, op_flags, (unsigned long long)bh->b_blocknr, dev_bytenr, bh->b_size, bh->b_data, bh->b_bdev); btrfsic_process_written_block(dev_state, dev_bytenr, &bh->b_data, 1, NULL, - NULL, bh, rw); - } else if (NULL != dev_state && (rw & REQ_FLUSH)) { + NULL, bh, op_flags); + } else if (NULL != dev_state && (op_flags & REQ_FLUSH)) { if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO - "submit_bh(rw=0x%x FLUSH, bdev=%p)\n", - rw, bh->b_bdev); + "submit_bh(op=0x%x,0x%x FLUSH, bdev=%p)\n", + op, op_flags, bh->b_bdev); if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) { if ((dev_state->state->print_mask & (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH | @@ -2907,7 +2907,7 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh) block->never_written = 0; block->iodone_w_error = 0; block->flush_gen = dev_state->last_flush_gen + 1; - block->submit_bio_bh_rw = rw; + block->submit_bio_bh_rw = op_flags; block->orig_bio_bh_private = bh->b_private; block->orig_bio_bh_end_io.bh = bh->b_end_io; block->next_in_same_bio = NULL; @@ -2916,7 +2916,7 @@ int btrfsic_submit_bh(int rw, struct buffer_head *bh) } } mutex_unlock(&btrfsic_mutex); - return submit_bh(rw, bh); + return submit_bh(op, op_flags, bh); } static void __btrfsic_submit_bio(struct bio *bio) diff --git a/fs/btrfs/check-integrity.h b/fs/btrfs/check-integrity.h index c04e249..f78dff1 100644 --- a/fs/btrfs/check-integrity.h +++ b/fs/btrfs/check-integrity.h @@ -20,7 +20,7 @@ #define __BTRFS_CHECK_INTEGRITY__ #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY -int btrfsic_submit_bh(int rw, struct buffer_head *bh); +int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh); void btrfsic_submit_bio(struct bio *bio); int btrfsic_submit_bio_wait(struct bio *bio); #else diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3666558..11033ce 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3420,9 +3420,9 @@ static int write_dev_supers(struct btrfs_device *device, * to go down lazy. */ if (i == 0) - ret = btrfsic_submit_bh(WRITE_FUA, bh); + ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_FUA, bh); else - ret = btrfsic_submit_bh(WRITE_SYNC, bh); + ret = btrfsic_submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); if (ret) errors++; } diff --git a/fs/buffer.c b/fs/buffer.c index 9a55e7f..881d336 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -45,7 +45,7 @@ #include static int fsync_buffers_list(spinlock_t *lock, struct list_head *list); -static int submit_bh_wbc(int rw, struct buffer_head *bh, +static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, unsigned long bio_flags, struct writeback_control *wbc); @@ -1225,7 +1225,7 @@ static struct buffer_head *__bread_slow(struct buffer_head *bh) } else { get_bh(bh); bh->b_end_io = end_buffer_read_sync; - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) return bh; @@ -1697,7 +1697,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, struct buffer_head *bh, *head; unsigned int blocksize, bbits; int nr_underway = 0; - int write_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); + int write_flags = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0); head = create_page_buffers(page, inode, (1 << BH_Dirty)|(1 << BH_Uptodate)); @@ -1786,7 +1786,7 @@ static int __block_write_full_page(struct inode *inode, struct page *page, do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { - submit_bh_wbc(write_op, bh, 0, wbc); + submit_bh_wbc(REQ_OP_WRITE, write_flags, bh, 0, wbc); nr_underway++; } bh = next; @@ -1840,7 +1840,7 @@ recover: struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { clear_buffer_dirty(bh); - submit_bh_wbc(write_op, bh, 0, wbc); + submit_bh_wbc(REQ_OP_WRITE, write_flags, bh, 0, wbc); nr_underway++; } bh = next; @@ -2248,7 +2248,7 @@ int block_read_full_page(struct page *page, get_block_t *get_block) if (buffer_uptodate(bh)) end_buffer_async_read(bh, 1); else - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); } return 0; } @@ -2582,7 +2582,7 @@ int nobh_write_begin(struct address_space *mapping, if (block_start < from || block_end > to) { lock_buffer(bh); bh->b_end_io = end_buffer_read_nobh; - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); nr_reads++; } } @@ -2949,7 +2949,7 @@ static void end_bio_bh_io_sync(struct bio *bio) * errors, this only handles the "we need to be able to * do IO at the final sector" case. */ -void guard_bio_eod(int rw, struct bio *bio) +void guard_bio_eod(int op, struct bio *bio) { sector_t maxsector; struct bio_vec *bvec = &bio->bi_io_vec[bio->bi_vcnt - 1]; @@ -2979,13 +2979,13 @@ void guard_bio_eod(int rw, struct bio *bio) bvec->bv_len -= truncated_bytes; /* ..and clear the end of the buffer for reads */ - if ((rw & RW_MASK) == READ) { + if (op == REQ_OP_READ) { zero_user(bvec->bv_page, bvec->bv_offset + bvec->bv_len, truncated_bytes); } } -static int submit_bh_wbc(int rw, struct buffer_head *bh, +static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh, unsigned long bio_flags, struct writeback_control *wbc) { struct bio *bio; @@ -2999,7 +2999,7 @@ static int submit_bh_wbc(int rw, struct buffer_head *bh, /* * Only clear out a write error when rewriting */ - if (test_set_buffer_req(bh) && (rw & WRITE)) + if (test_set_buffer_req(bh) && (op == REQ_OP_WRITE)) clear_buffer_write_io_error(bh); /* @@ -3024,27 +3024,28 @@ static int submit_bh_wbc(int rw, struct buffer_head *bh, bio->bi_flags |= bio_flags; /* Take care of bh's that straddle the end of the device */ - guard_bio_eod(rw, bio); + guard_bio_eod(op, bio); if (buffer_meta(bh)) - rw |= REQ_META; + op_flags |= REQ_META; if (buffer_prio(bh)) - rw |= REQ_PRIO; - bio->bi_rw = rw; + op_flags |= REQ_PRIO; + bio_set_op_attrs(bio, op, op_flags); submit_bio(bio); return 0; } -int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags) +int _submit_bh(int op, int op_flags, struct buffer_head *bh, + unsigned long bio_flags) { - return submit_bh_wbc(rw, bh, bio_flags, NULL); + return submit_bh_wbc(op, op_flags, bh, bio_flags, NULL); } EXPORT_SYMBOL_GPL(_submit_bh); -int submit_bh(int rw, struct buffer_head *bh) +int submit_bh(int op, int op_flags, struct buffer_head *bh) { - return submit_bh_wbc(rw, bh, 0, NULL); + return submit_bh_wbc(op, op_flags, bh, 0, NULL); } EXPORT_SYMBOL(submit_bh); @@ -3086,14 +3087,14 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) if (test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; get_bh(bh); - submit_bh(WRITE, bh); + submit_bh(rw, 0, bh); continue; } } else { if (!buffer_uptodate(bh)) { bh->b_end_io = end_buffer_read_sync; get_bh(bh); - submit_bh(rw, bh); + submit_bh(rw, 0, bh); continue; } } @@ -3102,7 +3103,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) } EXPORT_SYMBOL(ll_rw_block); -void write_dirty_buffer(struct buffer_head *bh, int rw) +void write_dirty_buffer(struct buffer_head *bh, int op_flags) { lock_buffer(bh); if (!test_clear_buffer_dirty(bh)) { @@ -3111,7 +3112,7 @@ void write_dirty_buffer(struct buffer_head *bh, int rw) } bh->b_end_io = end_buffer_write_sync; get_bh(bh); - submit_bh(rw, bh); + submit_bh(REQ_OP_WRITE, op_flags, bh); } EXPORT_SYMBOL(write_dirty_buffer); @@ -3120,7 +3121,7 @@ EXPORT_SYMBOL(write_dirty_buffer); * and then start new I/O and then wait upon it. The caller must have a ref on * the buffer_head. */ -int __sync_dirty_buffer(struct buffer_head *bh, int rw) +int __sync_dirty_buffer(struct buffer_head *bh, int op_flags) { int ret = 0; @@ -3129,7 +3130,7 @@ int __sync_dirty_buffer(struct buffer_head *bh, int rw) if (test_clear_buffer_dirty(bh)) { get_bh(bh); bh->b_end_io = end_buffer_write_sync; - ret = submit_bh(rw, bh); + ret = submit_bh(REQ_OP_WRITE, op_flags, bh); wait_on_buffer(bh); if (!ret && !buffer_uptodate(bh)) ret = -EIO; @@ -3392,7 +3393,7 @@ int bh_submit_read(struct buffer_head *bh) get_bh(bh); bh->b_end_io = end_buffer_read_sync; - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) return 0; diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 3020fd7..a806b58 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -470,7 +470,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group) trace_ext4_read_block_bitmap_load(sb, block_group); bh->b_end_io = ext4_end_bitmap_read; get_bh(bh); - submit_bh(READ | REQ_META | REQ_PRIO, bh); + submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh); return bh; verify: err = ext4_validate_block_bitmap(sb, desc, block_group, bh); diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 3da4cf8..1e4b0b7 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -214,7 +214,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group) trace_ext4_load_inode_bitmap(sb, block_group); bh->b_end_io = ext4_end_bitmap_read; get_bh(bh); - submit_bh(READ | REQ_META | REQ_PRIO, bh); + submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) { put_bh(bh); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f7140ca..ee3c7d8 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -4281,7 +4281,7 @@ make_io: trace_ext4_load_inode(inode); get_bh(bh); bh->b_end_io = end_buffer_read_sync; - submit_bh(READ | REQ_META | REQ_PRIO, bh); + submit_bh(REQ_OP_READ, REQ_META | REQ_PRIO, bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) { EXT4_ERROR_INODE_BLOCK(inode, block, diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index 23d436d..d89754e 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -52,7 +52,7 @@ static int write_mmp_block(struct super_block *sb, struct buffer_head *bh) lock_buffer(bh); bh->b_end_io = end_buffer_write_sync; get_bh(bh); - submit_bh(WRITE_SYNC | REQ_META | REQ_PRIO, bh); + submit_bh(REQ_OP_WRITE, WRITE_SYNC | REQ_META | REQ_PRIO, bh); wait_on_buffer(bh); sb_end_write(sb); if (unlikely(!buffer_uptodate(bh))) @@ -88,7 +88,7 @@ static int read_mmp_block(struct super_block *sb, struct buffer_head **bh, get_bh(*bh); lock_buffer(*bh); (*bh)->b_end_io = end_buffer_read_sync; - submit_bh(READ_SYNC | REQ_META | REQ_PRIO, *bh); + submit_bh(REQ_OP_READ, READ_SYNC | REQ_META | REQ_PRIO, *bh); wait_on_buffer(*bh); if (!buffer_uptodate(*bh)) { ret = -EIO; diff --git a/fs/fat/misc.c b/fs/fat/misc.c index c4589e9..8a86981 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c @@ -267,7 +267,7 @@ int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) int i, err = 0; for (i = 0; i < nr_bhs; i++) - write_dirty_buffer(bhs[i], WRITE); + write_dirty_buffer(bhs[i], 0); for (i = 0; i < nr_bhs; i++) { wait_on_buffer(bhs[i]); diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 24ce1cd..06d79aa 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -285,7 +285,7 @@ static void gfs2_metapath_ra(struct gfs2_glock *gl, if (trylock_buffer(rabh)) { if (!buffer_uptodate(rabh)) { rabh->b_end_io = end_buffer_read_sync; - submit_bh(READA | REQ_META, rabh); + submit_bh(REQ_OP_READ, READA | REQ_META, rabh); continue; } unlock_buffer(rabh); diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 271d939..0fbb426 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -1513,7 +1513,7 @@ static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index, continue; } bh->b_end_io = end_buffer_read_sync; - submit_bh(READA | REQ_META, bh); + submit_bh(REQ_OP_READ, READA | REQ_META, bh); continue; } brelse(bh); diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 66670e1..091483e 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -37,8 +37,8 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb { struct buffer_head *bh, *head; int nr_underway = 0; - int write_op = REQ_META | REQ_PRIO | - (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); + int write_flags = REQ_META | REQ_PRIO | + (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0); BUG_ON(!PageLocked(page)); BUG_ON(!page_has_buffers(page)); @@ -79,7 +79,7 @@ static int gfs2_aspace_writepage(struct page *page, struct writeback_control *wb do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { - submit_bh(write_op, bh); + submit_bh(REQ_OP_WRITE, write_flags, bh); nr_underway++; } bh = next; diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 7007809..8f7d133 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -155,9 +155,9 @@ static int journal_submit_commit_record(journal_t *journal, if (journal->j_flags & JBD2_BARRIER && !jbd2_has_feature_async_commit(journal)) - ret = submit_bh(WRITE_SYNC | WRITE_FLUSH_FUA, bh); + ret = submit_bh(REQ_OP_WRITE, WRITE_SYNC | WRITE_FLUSH_FUA, bh); else - ret = submit_bh(WRITE_SYNC, bh); + ret = submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); *cbh = bh; return ret; @@ -718,7 +718,7 @@ start_journal_io: clear_buffer_dirty(bh); set_buffer_uptodate(bh); bh->b_end_io = journal_end_buffer_io_sync; - submit_bh(WRITE_SYNC, bh); + submit_bh(REQ_OP_WRITE, WRITE_SYNC, bh); } cond_resched(); stats.run.rs_blocks_logged += bufs; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index b31852f..2606de4 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1346,15 +1346,15 @@ static int journal_reset(journal_t *journal) return jbd2_journal_start_thread(journal); } -static int jbd2_write_superblock(journal_t *journal, int write_op) +static int jbd2_write_superblock(journal_t *journal, int write_flags) { struct buffer_head *bh = journal->j_sb_buffer; journal_superblock_t *sb = journal->j_superblock; int ret; - trace_jbd2_write_superblock(journal, write_op); + trace_jbd2_write_superblock(journal, write_flags); if (!(journal->j_flags & JBD2_BARRIER)) - write_op &= ~(REQ_FUA | REQ_FLUSH); + write_flags &= ~(REQ_FUA | REQ_FLUSH); lock_buffer(bh); if (buffer_write_io_error(bh)) { /* @@ -1374,7 +1374,7 @@ static int jbd2_write_superblock(journal_t *journal, int write_op) jbd2_superblock_csum_set(journal, sb); get_bh(bh); bh->b_end_io = end_buffer_write_sync; - ret = submit_bh(write_op, bh); + ret = submit_bh(REQ_OP_WRITE, write_flags, bh); wait_on_buffer(bh); if (buffer_write_io_error(bh)) { clear_buffer_write_io_error(bh); diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c index 0576033..4cca998 100644 --- a/fs/nilfs2/btnode.c +++ b/fs/nilfs2/btnode.c @@ -62,7 +62,7 @@ nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr) } int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, - sector_t pblocknr, int mode, + sector_t pblocknr, int mode, int mode_flags, struct buffer_head **pbh, sector_t *submit_ptr) { struct buffer_head *bh; @@ -95,7 +95,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, } } - if (mode == READA) { + if (mode_flags & REQ_RAHEAD) { if (pblocknr != *submit_ptr + 1 || !trylock_buffer(bh)) { err = -EBUSY; /* internal code */ brelse(bh); @@ -114,7 +114,7 @@ int nilfs_btnode_submit_block(struct address_space *btnc, __u64 blocknr, bh->b_blocknr = pblocknr; /* set block address for read */ bh->b_end_io = end_buffer_read_sync; get_bh(bh); - submit_bh(mode, bh); + submit_bh(mode, mode_flags, bh); bh->b_blocknr = blocknr; /* set back to the given block address */ *submit_ptr = pblocknr; err = 0; diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h index 2cc1b80..4e8aaa1 100644 --- a/fs/nilfs2/btnode.h +++ b/fs/nilfs2/btnode.h @@ -43,7 +43,7 @@ void nilfs_btnode_cache_clear(struct address_space *); struct buffer_head *nilfs_btnode_create_block(struct address_space *btnc, __u64 blocknr); int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t, int, - struct buffer_head **, sector_t *); + int, struct buffer_head **, sector_t *); void nilfs_btnode_delete(struct buffer_head *); int nilfs_btnode_prepare_change_key(struct address_space *, struct nilfs_btnode_chkey_ctxt *); diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c index eccb1c8..982d1e3 100644 --- a/fs/nilfs2/btree.c +++ b/fs/nilfs2/btree.c @@ -476,7 +476,8 @@ static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, sector_t submit_ptr = 0; int ret; - ret = nilfs_btnode_submit_block(btnc, ptr, 0, READ, &bh, &submit_ptr); + ret = nilfs_btnode_submit_block(btnc, ptr, 0, REQ_OP_READ, 0, &bh, + &submit_ptr); if (ret) { if (ret != -EEXIST) return ret; @@ -492,7 +493,8 @@ static int __nilfs_btree_get_block(const struct nilfs_bmap *btree, __u64 ptr, n > 0 && i < ra->ncmax; n--, i++) { ptr2 = nilfs_btree_node_get_ptr(ra->node, i, ra->ncmax); - ret = nilfs_btnode_submit_block(btnc, ptr2, 0, READA, + ret = nilfs_btnode_submit_block(btnc, ptr2, 0, + REQ_OP_READ, REQ_RAHEAD, &ra_bh, &submit_ptr); if (likely(!ret || ret == -EEXIST)) brelse(ra_bh); diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index 693aded..e9148f9 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -101,7 +101,7 @@ int nilfs_gccache_submit_read_data(struct inode *inode, sector_t blkoff, bh->b_blocknr = pbn; bh->b_end_io = end_buffer_read_sync; get_bh(bh); - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); if (vbn) bh->b_blocknr = vbn; out: @@ -138,7 +138,8 @@ int nilfs_gccache_submit_read_node(struct inode *inode, sector_t pbn, int ret; ret = nilfs_btnode_submit_block(&NILFS_I(inode)->i_btnode_cache, - vbn ? : pbn, pbn, READ, out_bh, &pbn); + vbn ? : pbn, pbn, REQ_OP_READ, 0, + out_bh, &pbn); if (ret == -EEXIST) /* internal code (cache hit) */ ret = 0; return ret; diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c index 3417d85..0d7b71f 100644 --- a/fs/nilfs2/mdt.c +++ b/fs/nilfs2/mdt.c @@ -121,7 +121,7 @@ static int nilfs_mdt_create_block(struct inode *inode, unsigned long block, static int nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, - int mode, struct buffer_head **out_bh) + int mode, int mode_flags, struct buffer_head **out_bh) { struct buffer_head *bh; __u64 blknum = 0; @@ -135,7 +135,7 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, if (buffer_uptodate(bh)) goto out; - if (mode == READA) { + if (mode_flags & REQ_RAHEAD) { if (!trylock_buffer(bh)) { ret = -EBUSY; goto failed_bh; @@ -157,7 +157,7 @@ nilfs_mdt_submit_block(struct inode *inode, unsigned long blkoff, bh->b_end_io = end_buffer_read_sync; get_bh(bh); - submit_bh(mode, bh); + submit_bh(mode, mode_flags, bh); ret = 0; trace_nilfs2_mdt_submit_block(inode, inode->i_ino, blkoff, mode); @@ -181,7 +181,7 @@ static int nilfs_mdt_read_block(struct inode *inode, unsigned long block, int i, nr_ra_blocks = NILFS_MDT_MAX_RA_BLOCKS; int err; - err = nilfs_mdt_submit_block(inode, block, READ, &first_bh); + err = nilfs_mdt_submit_block(inode, block, REQ_OP_READ, 0, &first_bh); if (err == -EEXIST) /* internal code */ goto out; @@ -191,7 +191,8 @@ static int nilfs_mdt_read_block(struct inode *inode, unsigned long block, if (readahead) { blkoff = block + 1; for (i = 0; i < nr_ra_blocks; i++, blkoff++) { - err = nilfs_mdt_submit_block(inode, blkoff, READA, &bh); + err = nilfs_mdt_submit_block(inode, blkoff, REQ_OP_READ, + REQ_RAHEAD, &bh); if (likely(!err || err == -EEXIST)) brelse(bh); else if (err != -EBUSY) diff --git a/fs/ntfs/aops.c b/fs/ntfs/aops.c index 97768a1..fe251f1 100644 --- a/fs/ntfs/aops.c +++ b/fs/ntfs/aops.c @@ -362,7 +362,7 @@ handle_zblock: for (i = 0; i < nr; i++) { tbh = arr[i]; if (likely(!buffer_uptodate(tbh))) - submit_bh(READ, tbh); + submit_bh(REQ_OP_READ, 0, tbh); else ntfs_end_buffer_async_read(tbh, 1); } @@ -877,7 +877,7 @@ lock_retry_remap: do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); need_end_writeback = false; } bh = next; @@ -1202,7 +1202,7 @@ lock_retry_remap: BUG_ON(!buffer_mapped(tbh)); get_bh(tbh); tbh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE, tbh); + submit_bh(REQ_OP_WRITE, 0, tbh); } /* Synchronize the mft mirror now if not @sync. */ if (is_mft && !sync) diff --git a/fs/ntfs/compress.c b/fs/ntfs/compress.c index f2b5e74..f8eb043 100644 --- a/fs/ntfs/compress.c +++ b/fs/ntfs/compress.c @@ -670,7 +670,7 @@ lock_retry_remap: } get_bh(tbh); tbh->b_end_io = end_buffer_read_sync; - submit_bh(READ, tbh); + submit_bh(REQ_OP_READ, 0, tbh); } /* Wait for io completion on all buffer heads. */ diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index 5622ed5..f548629 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c @@ -553,7 +553,7 @@ static inline int ntfs_submit_bh_for_read(struct buffer_head *bh) lock_buffer(bh); get_bh(bh); bh->b_end_io = end_buffer_read_sync; - return submit_bh(READ, bh); + return submit_bh(REQ_OP_READ, 0, bh); } /** diff --git a/fs/ntfs/logfile.c b/fs/ntfs/logfile.c index 9d71213..761f12f 100644 --- a/fs/ntfs/logfile.c +++ b/fs/ntfs/logfile.c @@ -821,7 +821,7 @@ map_vcn: * completed ignore errors afterwards as we can assume * that if one buffer worked all of them will work. */ - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); if (should_wait) { should_wait = false; wait_on_buffer(bh); diff --git a/fs/ntfs/mft.c b/fs/ntfs/mft.c index 37b2501..d15d492 100644 --- a/fs/ntfs/mft.c +++ b/fs/ntfs/mft.c @@ -592,7 +592,7 @@ int ntfs_sync_mft_mirror(ntfs_volume *vol, const unsigned long mft_no, clear_buffer_dirty(tbh); get_bh(tbh); tbh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE, tbh); + submit_bh(REQ_OP_WRITE, 0, tbh); } /* Wait on i/o completion of buffers. */ for (i_bhs = 0; i_bhs < nr_bhs; i_bhs++) { @@ -785,7 +785,7 @@ int write_mft_record_nolock(ntfs_inode *ni, MFT_RECORD *m, int sync) clear_buffer_dirty(tbh); get_bh(tbh); tbh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE, tbh); + submit_bh(REQ_OP_WRITE, 0, tbh); } /* Synchronize the mft mirror now if not @sync. */ if (!sync && ni->mft_no < vol->mftmirr_size) diff --git a/fs/ocfs2/buffer_head_io.c b/fs/ocfs2/buffer_head_io.c index fe50ded..fb775c9 100644 --- a/fs/ocfs2/buffer_head_io.c +++ b/fs/ocfs2/buffer_head_io.c @@ -79,7 +79,7 @@ int ocfs2_write_block(struct ocfs2_super *osb, struct buffer_head *bh, get_bh(bh); /* for end_buffer_write_sync() */ bh->b_end_io = end_buffer_write_sync; - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); wait_on_buffer(bh); @@ -149,7 +149,7 @@ int ocfs2_read_blocks_sync(struct ocfs2_super *osb, u64 block, clear_buffer_uptodate(bh); get_bh(bh); /* for end_buffer_read_sync() */ bh->b_end_io = end_buffer_read_sync; - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); } for (i = nr; i > 0; i--) { @@ -305,7 +305,7 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr, if (validate) set_buffer_needs_validate(bh); bh->b_end_io = end_buffer_read_sync; - submit_bh(READ, bh); + submit_bh(REQ_OP_READ, 0, bh); continue; } } @@ -419,7 +419,7 @@ int ocfs2_write_super_or_backup(struct ocfs2_super *osb, get_bh(bh); /* for end_buffer_write_sync() */ bh->b_end_io = end_buffer_write_sync; ocfs2_compute_meta_ecc(osb->sb, bh->b_data, &di->i_check); - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); wait_on_buffer(bh); diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 825455d..c2c59f9 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -2668,7 +2668,7 @@ static int reiserfs_write_full_page(struct page *page, do { struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); nr++; } put_bh(bh); @@ -2728,7 +2728,7 @@ fail: struct buffer_head *next = bh->b_this_page; if (buffer_async_write(bh)) { clear_buffer_dirty(bh); - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); nr++; } put_bh(bh); diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 2ace90e..6945e71 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -652,7 +652,7 @@ static void submit_logged_buffer(struct buffer_head *bh) BUG(); if (!buffer_uptodate(bh)) BUG(); - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); } static void submit_ordered_buffer(struct buffer_head *bh) @@ -662,7 +662,7 @@ static void submit_ordered_buffer(struct buffer_head *bh) clear_buffer_dirty(bh); if (!buffer_uptodate(bh)) BUG(); - submit_bh(WRITE, bh); + submit_bh(REQ_OP_WRITE, 0, bh); } #define CHUNK_SIZE 32 @@ -2269,7 +2269,7 @@ abort_replay: /* flush out the real blocks */ for (i = 0; i < get_desc_trans_len(desc); i++) { set_buffer_dirty(real_blocks[i]); - write_dirty_buffer(real_blocks[i], WRITE); + write_dirty_buffer(real_blocks[i], 0); } for (i = 0; i < get_desc_trans_len(desc); i++) { wait_on_buffer(real_blocks[i]); diff --git a/fs/ufs/util.c b/fs/ufs/util.c index a409e3e..f41ad0a 100644 --- a/fs/ufs/util.c +++ b/fs/ufs/util.c @@ -118,7 +118,7 @@ void ubh_sync_block(struct ufs_buffer_head *ubh) unsigned i; for (i = 0; i < ubh->count; i++) - write_dirty_buffer(ubh->bh[i], WRITE); + write_dirty_buffer(ubh->bh[i], 0); for (i = 0; i < ubh->count; i++) wait_on_buffer(ubh->bh[i]); diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index d48daa3..bc9a45d 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -189,10 +189,11 @@ void unlock_buffer(struct buffer_head *bh); void __lock_buffer(struct buffer_head *bh); void ll_rw_block(int, int, struct buffer_head * bh[]); int sync_dirty_buffer(struct buffer_head *bh); -int __sync_dirty_buffer(struct buffer_head *bh, int rw); -void write_dirty_buffer(struct buffer_head *bh, int rw); -int _submit_bh(int rw, struct buffer_head *bh, unsigned long bio_flags); -int submit_bh(int, struct buffer_head *); +int __sync_dirty_buffer(struct buffer_head *bh, int op_flags); +void write_dirty_buffer(struct buffer_head *bh, int op_flags); +int _submit_bh(int op, int op_flags, struct buffer_head *bh, + unsigned long bio_flags); +int submit_bh(int, int, struct buffer_head *); void write_boundary_block(struct block_device *bdev, sector_t bblock, unsigned blocksize); int bh_uptodate_or_lock(struct buffer_head *bh); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D6EED7CA1 for ; Sun, 5 Jun 2016 14:32:47 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id A8F2E304043 for ; Sun, 5 Jun 2016 12:32:44 -0700 (PDT) X-ASG-Debug-ID: 1465155162-04cb6c2dbab58d90001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id NOurqWvyGfB85wKD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:42 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1BE9290E50; Sun, 5 Jun 2016 19:32:42 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9B003130; Sun, 5 Jun 2016 15:32:39 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 04/45] fs: have ll_rw_block users pass in op and flags separately Date: Sun, 5 Jun 2016 14:31:44 -0500 X-ASG-Orig-Subj: [PATCH 04/45] fs: have ll_rw_block users pass in op and flags separately Message-Id: <1465155145-10812-5-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:32:42 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155162 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 16093 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This has ll_rw_block users pass in the operation and flags separately, so ll_rw_block can setup the bio op and bi_rw flags on the bio that is submitted. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- v2: 1. Fix for kbuild error in ll_rw_block comments. fs/buffer.c | 19 ++++++++++--------- fs/ext4/inode.c | 6 +++--- fs/ext4/namei.c | 3 ++- fs/ext4/super.c | 2 +- fs/gfs2/bmap.c | 2 +- fs/gfs2/meta_io.c | 4 ++-- fs/gfs2/quota.c | 2 +- fs/isofs/compress.c | 2 +- fs/jbd2/journal.c | 2 +- fs/jbd2/recovery.c | 4 ++-- fs/ocfs2/aops.c | 2 +- fs/ocfs2/super.c | 2 +- fs/reiserfs/journal.c | 8 ++++---- fs/reiserfs/stree.c | 4 ++-- fs/reiserfs/super.c | 2 +- fs/squashfs/block.c | 4 ++-- fs/udf/dir.c | 2 +- fs/udf/directory.c | 2 +- fs/udf/inode.c | 2 +- fs/ufs/balloc.c | 2 +- include/linux/buffer_head.h | 2 +- 21 files changed, 40 insertions(+), 38 deletions(-) diff --git a/fs/buffer.c b/fs/buffer.c index 881d336..373aacb 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -588,7 +588,7 @@ void write_boundary_block(struct block_device *bdev, struct buffer_head *bh = __find_get_block(bdev, bblock + 1, blocksize); if (bh) { if (buffer_dirty(bh)) - ll_rw_block(WRITE, 1, &bh); + ll_rw_block(REQ_OP_WRITE, 0, 1, &bh); put_bh(bh); } } @@ -1395,7 +1395,7 @@ void __breadahead(struct block_device *bdev, sector_t block, unsigned size) { struct buffer_head *bh = __getblk(bdev, block, size); if (likely(bh)) { - ll_rw_block(READA, 1, &bh); + ll_rw_block(REQ_OP_READ, READA, 1, &bh); brelse(bh); } } @@ -1955,7 +1955,7 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh) && (block_start < from || block_end > to)) { - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); *wait_bh++=bh; } } @@ -2852,7 +2852,7 @@ int block_truncate_page(struct address_space *mapping, if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh)) { err = -EIO; - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); wait_on_buffer(bh); /* Uhhuh. Read error. Complain and punt. */ if (!buffer_uptodate(bh)) @@ -3051,7 +3051,8 @@ EXPORT_SYMBOL(submit_bh); /** * ll_rw_block: low-level access to block devices (DEPRECATED) - * @rw: whether to %READ or %WRITE or maybe %READA (readahead) + * @op: whether to %READ or %WRITE + * @op_flags: rq_flag_bits or %READA (readahead) * @nr: number of &struct buffer_heads in the array * @bhs: array of pointers to &struct buffer_head * @@ -3074,7 +3075,7 @@ EXPORT_SYMBOL(submit_bh); * All of the buffers must be for the same device, and must also be a * multiple of the current approved size for the device. */ -void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) +void ll_rw_block(int op, int op_flags, int nr, struct buffer_head *bhs[]) { int i; @@ -3083,18 +3084,18 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) if (!trylock_buffer(bh)) continue; - if (rw == WRITE) { + if (op == WRITE) { if (test_clear_buffer_dirty(bh)) { bh->b_end_io = end_buffer_write_sync; get_bh(bh); - submit_bh(rw, 0, bh); + submit_bh(op, op_flags, bh); continue; } } else { if (!buffer_uptodate(bh)) { bh->b_end_io = end_buffer_read_sync; get_bh(bh); - submit_bh(rw, 0, bh); + submit_bh(op, op_flags, bh); continue; } } diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index ee3c7d8..ae44916 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -981,7 +981,7 @@ struct buffer_head *ext4_bread(handle_t *handle, struct inode *inode, return bh; if (!bh || buffer_uptodate(bh)) return bh; - ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &bh); + ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) return bh; @@ -1135,7 +1135,7 @@ static int ext4_block_write_begin(struct page *page, loff_t pos, unsigned len, if (!buffer_uptodate(bh) && !buffer_delay(bh) && !buffer_unwritten(bh) && (block_start < from || block_end > to)) { - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); *wait_bh++ = bh; decrypt = ext4_encrypted_inode(inode) && S_ISREG(inode->i_mode); @@ -3698,7 +3698,7 @@ static int __ext4_block_zero_page_range(handle_t *handle, if (!buffer_uptodate(bh)) { err = -EIO; - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); wait_on_buffer(bh); /* Uhhuh. Read error. Complain and punt. */ if (!buffer_uptodate(bh)) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index ec4c399..6569c6b 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1443,7 +1443,8 @@ restart: } bh_use[ra_max] = bh; if (bh) - ll_rw_block(READ | REQ_META | REQ_PRIO, + ll_rw_block(REQ_OP_READ, + REQ_META | REQ_PRIO, 1, &bh); } } diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 3822a5a..b1a3471 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4204,7 +4204,7 @@ static journal_t *ext4_get_dev_journal(struct super_block *sb, goto out_bdev; } journal->j_private = sb; - ll_rw_block(READ | REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer); + ll_rw_block(REQ_OP_READ, REQ_META | REQ_PRIO, 1, &journal->j_sb_buffer); wait_on_buffer(journal->j_sb_buffer); if (!buffer_uptodate(journal->j_sb_buffer)) { ext4_msg(sb, KERN_ERR, "I/O error on journal device"); diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 06d79aa..fd6389c 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -974,7 +974,7 @@ static int gfs2_block_truncate_page(struct address_space *mapping, loff_t from) if (!buffer_uptodate(bh)) { err = -EIO; - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); wait_on_buffer(bh); /* Uhhuh. Read error. Complain and punt. */ if (!buffer_uptodate(bh)) diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index 091483e..b718447 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -449,7 +449,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) if (buffer_uptodate(first_bh)) goto out; if (!buffer_locked(first_bh)) - ll_rw_block(READ_SYNC | REQ_META, 1, &first_bh); + ll_rw_block(REQ_OP_READ, READ_SYNC | REQ_META, 1, &first_bh); dblock++; extlen--; @@ -458,7 +458,7 @@ struct buffer_head *gfs2_meta_ra(struct gfs2_glock *gl, u64 dblock, u32 extlen) bh = gfs2_getbuf(gl, dblock, CREATE); if (!buffer_uptodate(bh) && !buffer_locked(bh)) - ll_rw_block(READA | REQ_META, 1, &bh); + ll_rw_block(REQ_OP_READ, READA | REQ_META, 1, &bh); brelse(bh); dblock++; extlen--; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index ce7d69a..62a6823 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -730,7 +730,7 @@ static int gfs2_write_buf_to_page(struct gfs2_inode *ip, unsigned long index, if (PageUptodate(page)) set_buffer_uptodate(bh); if (!buffer_uptodate(bh)) { - ll_rw_block(READ | REQ_META, 1, &bh); + ll_rw_block(REQ_OP_READ, REQ_META, 1, &bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) goto unlock_out; diff --git a/fs/isofs/compress.c b/fs/isofs/compress.c index 2e4e834..2ce5b75 100644 --- a/fs/isofs/compress.c +++ b/fs/isofs/compress.c @@ -81,7 +81,7 @@ static loff_t zisofs_uncompress_block(struct inode *inode, loff_t block_start, blocknum = block_start >> bufshift; memset(bhs, 0, (needblocks + 1) * sizeof(struct buffer_head *)); haveblocks = isofs_get_blocks(inode, blocknum, bhs, needblocks); - ll_rw_block(READ, haveblocks, bhs); + ll_rw_block(REQ_OP_READ, 0, haveblocks, bhs); curbh = 0; curpage = 0; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 2606de4..34bc996 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1498,7 +1498,7 @@ static int journal_get_superblock(journal_t *journal) J_ASSERT(bh != NULL); if (!buffer_uptodate(bh)) { - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) { printk(KERN_ERR diff --git a/fs/jbd2/recovery.c b/fs/jbd2/recovery.c index 805bc6b..02dd3360 100644 --- a/fs/jbd2/recovery.c +++ b/fs/jbd2/recovery.c @@ -104,7 +104,7 @@ static int do_readahead(journal_t *journal, unsigned int start) if (!buffer_uptodate(bh) && !buffer_locked(bh)) { bufs[nbufs++] = bh; if (nbufs == MAXBUF) { - ll_rw_block(READ, nbufs, bufs); + ll_rw_block(REQ_OP_READ, 0, nbufs, bufs); journal_brelse_array(bufs, nbufs); nbufs = 0; } @@ -113,7 +113,7 @@ static int do_readahead(journal_t *journal, unsigned int start) } if (nbufs) - ll_rw_block(READ, nbufs, bufs); + ll_rw_block(REQ_OP_READ, 0, nbufs, bufs); err = 0; failed: diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index c034edf..e97a371 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -640,7 +640,7 @@ int ocfs2_map_page_blocks(struct page *page, u64 *p_blkno, !buffer_new(bh) && ocfs2_should_read_blk(inode, page, block_start) && (block_start < from || block_end > to)) { - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); *wait_bh++=bh; } diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index d7cae33..3971146 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -1819,7 +1819,7 @@ static int ocfs2_get_sector(struct super_block *sb, if (!buffer_dirty(*bh)) clear_buffer_uptodate(*bh); unlock_buffer(*bh); - ll_rw_block(READ, 1, bh); + ll_rw_block(REQ_OP_READ, 0, 1, bh); wait_on_buffer(*bh); if (!buffer_uptodate(*bh)) { mlog_errno(-EIO); diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 6945e71..bc2dde2 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -870,7 +870,7 @@ loop_next: */ if (buffer_dirty(bh) && unlikely(bh->b_page->mapping == NULL)) { spin_unlock(lock); - ll_rw_block(WRITE, 1, &bh); + ll_rw_block(REQ_OP_WRITE, 0, 1, &bh); spin_lock(lock); } put_bh(bh); @@ -1057,7 +1057,7 @@ static int flush_commit_list(struct super_block *s, if (tbh) { if (buffer_dirty(tbh)) { depth = reiserfs_write_unlock_nested(s); - ll_rw_block(WRITE, 1, &tbh); + ll_rw_block(REQ_OP_WRITE, 0, 1, &tbh); reiserfs_write_lock_nested(s, depth); } put_bh(tbh) ; @@ -2244,7 +2244,7 @@ abort_replay: } } /* read in the log blocks, memcpy to the corresponding real block */ - ll_rw_block(READ, get_desc_trans_len(desc), log_blocks); + ll_rw_block(REQ_OP_READ, 0, get_desc_trans_len(desc), log_blocks); for (i = 0; i < get_desc_trans_len(desc); i++) { wait_on_buffer(log_blocks[i]); @@ -2346,7 +2346,7 @@ static struct buffer_head *reiserfs_breada(struct block_device *dev, } else bhlist[j++] = bh; } - ll_rw_block(READ, j, bhlist); + ll_rw_block(REQ_OP_READ, 0, j, bhlist); for (i = 1; i < j; i++) brelse(bhlist[i]); bh = bhlist[0]; diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index 5feacd6..64b29b5 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -551,7 +551,7 @@ static int search_by_key_reada(struct super_block *s, if (!buffer_uptodate(bh[j])) { if (depth == -1) depth = reiserfs_write_unlock_nested(s); - ll_rw_block(READA, 1, bh + j); + ll_rw_block(REQ_OP_READ, READA, 1, bh + j); } brelse(bh[j]); } @@ -660,7 +660,7 @@ int search_by_key(struct super_block *sb, const struct cpu_key *key, if (!buffer_uptodate(bh) && depth == -1) depth = reiserfs_write_unlock_nested(sb); - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); wait_on_buffer(bh); if (depth != -1) diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index b8f2d1e..9938a51 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -1661,7 +1661,7 @@ static int read_super_block(struct super_block *s, int offset) /* after journal replay, reread all bitmap and super blocks */ static int reread_meta_blocks(struct super_block *s) { - ll_rw_block(READ, 1, &SB_BUFFER_WITH_SB(s)); + ll_rw_block(REQ_OP_READ, 0, 1, &SB_BUFFER_WITH_SB(s)); wait_on_buffer(SB_BUFFER_WITH_SB(s)); if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { reiserfs_warning(s, "reiserfs-2504", "error reading the super"); diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 2c26184..ce62a38 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c @@ -124,7 +124,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length, goto block_release; bytes += msblk->devblksize; } - ll_rw_block(READ, b, bh); + ll_rw_block(REQ_OP_READ, 0, b, bh); } else { /* * Metadata block. @@ -156,7 +156,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length, goto block_release; bytes += msblk->devblksize; } - ll_rw_block(READ, b - 1, bh + 1); + ll_rw_block(REQ_OP_READ, 0, b - 1, bh + 1); } for (i = 0; i < b; i++) { diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 4c5593a..80c8a21 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -113,7 +113,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) brelse(tmp); } if (num) { - ll_rw_block(READA, num, bha); + ll_rw_block(REQ_OP_READ, READA, num, bha); for (i = 0; i < num; i++) brelse(bha[i]); } diff --git a/fs/udf/directory.c b/fs/udf/directory.c index c763fda..71f3e0b 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c @@ -87,7 +87,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, brelse(tmp); } if (num) { - ll_rw_block(READA, num, bha); + ll_rw_block(REQ_OP_READ, READA, num, bha); for (i = 0; i < num; i++) brelse(bha[i]); } diff --git a/fs/udf/inode.c b/fs/udf/inode.c index f323aff..55aa587 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1199,7 +1199,7 @@ struct buffer_head *udf_bread(struct inode *inode, int block, if (buffer_uptodate(bh)) return bh; - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); wait_on_buffer(bh); if (buffer_uptodate(bh)) diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 0447b94..67e085d 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -292,7 +292,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg, if (!buffer_mapped(bh)) map_bh(bh, inode->i_sb, oldb + pos); if (!buffer_uptodate(bh)) { - ll_rw_block(READ, 1, &bh); + ll_rw_block(REQ_OP_READ, 0, 1, &bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) { ufs_error(inode->i_sb, __func__, diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index bc9a45d..d1dd293 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -187,7 +187,7 @@ struct buffer_head *alloc_buffer_head(gfp_t gfp_flags); void free_buffer_head(struct buffer_head * bh); void unlock_buffer(struct buffer_head *bh); void __lock_buffer(struct buffer_head *bh); -void ll_rw_block(int, int, struct buffer_head * bh[]); +void ll_rw_block(int, int, int, struct buffer_head * bh[]); int sync_dirty_buffer(struct buffer_head *bh); int __sync_dirty_buffer(struct buffer_head *bh, int op_flags); void write_dirty_buffer(struct buffer_head *bh, int op_flags); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5207A7CA0 for ; Sun, 5 Jun 2016 14:32:49 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id C9202AC003 for ; Sun, 5 Jun 2016 12:32:48 -0700 (PDT) X-ASG-Debug-ID: 1465155167-04cb6c2dbbb58da0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 67A5tv3z6fw8qbog (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:47 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B0E6DC04D29F; Sun, 5 Jun 2016 19:32:46 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9D003130; Sun, 5 Jun 2016 15:32:44 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 06/45] dm: use op_is_write instead of checking for REQ_WRITE Date: Sun, 5 Jun 2016 14:31:46 -0500 X-ASG-Orig-Subj: [PATCH 06/45] dm: use op_is_write instead of checking for REQ_WRITE Message-Id: <1465155145-10812-7-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sun, 05 Jun 2016 19:32:46 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155167 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2147 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie We currently set REQ_WRITE/WRITE for all non READ IOs like discard, flush, writesame, etc. In the next patches where we no longer set up the op as a bitmap, we will not be able to detect a operation direction like writesame by testing if REQ_WRITE is set. This has dm use the op_is_write helper which will do the right thing. Signed-off-by: Mike Christie --- drivers/md/dm-io.c | 4 ++-- drivers/md/dm-kcopyd.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 50f17e3..26e9a85 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -409,7 +409,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, struct io *io; struct sync_io sio; - if (num_regions > 1 && (rw & RW_MASK) != WRITE) { + if (num_regions > 1 && !op_is_write(rw)) { WARN_ON(1); return -EIO; } @@ -442,7 +442,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, { struct io *io; - if (num_regions > 1 && (rw & RW_MASK) != WRITE) { + if (num_regions > 1 && !op_is_write(rw)) { WARN_ON(1); fn(1, context); return -EIO; diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index 1452ed9..9f390e4 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c @@ -465,7 +465,7 @@ static void complete_io(unsigned long error, void *context) io_job_finish(kc->throttle); if (error) { - if (job->rw & WRITE) + if (op_is_write(job->rw)) job->write_err |= error; else job->read_err = 1; @@ -477,7 +477,7 @@ static void complete_io(unsigned long error, void *context) } } - if (job->rw & WRITE) + if (op_is_write(job->rw)) push(&kc->complete_jobs, job); else { @@ -550,7 +550,7 @@ static int process_jobs(struct list_head *jobs, struct dm_kcopyd_client *kc, if (r < 0) { /* error this rogue job */ - if (job->rw & WRITE) + if (op_is_write(job->rw)) job->write_err = (unsigned long) -1L; else job->read_err = 1; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 45C6A7CA0 for ; Sun, 5 Jun 2016 14:32:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8F5B08F8040 for ; Sun, 5 Jun 2016 12:32:50 -0700 (PDT) X-ASG-Debug-ID: 1465155169-04cbb0356bb8abb0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 8DSFEFkjzV0N4Quu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:49 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F2C0AC04D2A2; Sun, 5 Jun 2016 19:32:48 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9E003130; Sun, 5 Jun 2016 15:32:46 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 07/45] bcache: use op_is_write instead of checking for REQ_WRITE Date: Sun, 5 Jun 2016 14:31:47 -0500 X-ASG-Orig-Subj: [PATCH 07/45] bcache: use op_is_write instead of checking for REQ_WRITE Message-Id: <1465155145-10812-8-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sun, 05 Jun 2016 19:32:49 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155169 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2174 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie We currently set REQ_WRITE/WRITE for all non READ IOs like discard, flush, writesame, etc. In the next patches where we no longer set up the op as a bitmap, we will not be able to detect a operation direction like writesame by testing if REQ_WRITE is set. This has bcache use the op_is_write helper which will do the right thing. Signed-off-by: Mike Christie --- drivers/md/bcache/io.c | 2 +- drivers/md/bcache/request.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/md/bcache/io.c b/drivers/md/bcache/io.c index 86a0bb8..fd885cc 100644 --- a/drivers/md/bcache/io.c +++ b/drivers/md/bcache/io.c @@ -111,7 +111,7 @@ void bch_bbio_count_io_errors(struct cache_set *c, struct bio *bio, struct bbio *b = container_of(bio, struct bbio, bio); struct cache *ca = PTR_CACHE(c, &b->key, 0); - unsigned threshold = bio->bi_rw & REQ_WRITE + unsigned threshold = op_is_write(bio_op(bio)) ? c->congested_write_threshold_us : c->congested_read_threshold_us; diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 25fa844..6b85a23 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -383,7 +383,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) if (mode == CACHE_MODE_NONE || (mode == CACHE_MODE_WRITEAROUND && - (bio->bi_rw & REQ_WRITE))) + op_is_write(bio_op(bio)))) goto skip; if (bio->bi_iter.bi_sector & (c->sb.block_size - 1) || @@ -404,7 +404,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) if (!congested && mode == CACHE_MODE_WRITEBACK && - (bio->bi_rw & REQ_WRITE) && + op_is_write(bio_op(bio)) && (bio->bi_rw & REQ_SYNC)) goto rescale; @@ -657,7 +657,7 @@ static inline struct search *search_alloc(struct bio *bio, s->cache_miss = NULL; s->d = d; s->recoverable = 1; - s->write = (bio->bi_rw & REQ_WRITE) != 0; + s->write = op_is_write(bio_op(bio)); s->read_dirty_data = 0; s->start_time = jiffies; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6DE557CC9 for ; Sun, 5 Jun 2016 14:32:54 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3F9B38F8040 for ; Sun, 5 Jun 2016 12:32:54 -0700 (PDT) X-ASG-Debug-ID: 1465155171-04cbb0356ab8abb0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 4wZ3u5LD6z1grMsn (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:51 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 36D2563E21; Sun, 5 Jun 2016 19:32:51 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9F003130; Sun, 5 Jun 2016 15:32:49 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 08/45] block, fs, mm, drivers: use bio set/get op accessors Date: Sun, 5 Jun 2016 14:31:48 -0500 X-ASG-Orig-Subj: [PATCH 08/45] block, fs, mm, drivers: use bio set/get op accessors Message-Id: <1465155145-10812-9-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Sun, 05 Jun 2016 19:32:51 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155171 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 22577 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch converts the simple bi_rw use cases in the block, drivers, mm and fs code to set/get the bio operation using bio_set_op_attrs/bio_op These should be simple one or two liner cases, so I just did them in one patch. The next patches handle the more complicated cases in a module per patch. Signed-off-by: Mike Christie --- v5: 1. Add missed crypto call. 2. Change nfs bi_rw check to bi_op. block/bio.c | 13 ++++++------- block/blk-core.c | 6 +++--- block/blk-flush.c | 2 +- block/blk-lib.c | 4 ++-- block/blk-map.c | 2 +- block/blk-merge.c | 12 ++++++------ drivers/block/brd.c | 2 +- drivers/block/floppy.c | 2 +- drivers/block/pktcdvd.c | 4 ++-- drivers/block/rsxx/dma.c | 2 +- drivers/block/zram/zram_drv.c | 2 +- drivers/lightnvm/rrpc.c | 6 +++--- drivers/scsi/osd/osd_initiator.c | 8 ++++---- drivers/staging/lustre/lustre/llite/lloop.c | 6 +++--- fs/crypto/crypto.c | 2 +- fs/exofs/ore.c | 2 +- fs/ext4/page-io.c | 6 +++--- fs/ext4/readpage.c | 2 +- fs/jfs/jfs_logmgr.c | 4 ++-- fs/jfs/jfs_metapage.c | 4 ++-- fs/logfs/dev_bdev.c | 12 ++++++------ fs/nfs/blocklayout/blocklayout.c | 4 ++-- include/linux/bio.h | 15 ++++++++++----- mm/page_io.c | 4 ++-- 24 files changed, 65 insertions(+), 61 deletions(-) diff --git a/block/bio.c b/block/bio.c index fc779eb..848cd35 100644 --- a/block/bio.c +++ b/block/bio.c @@ -656,16 +656,15 @@ struct bio *bio_clone_bioset(struct bio *bio_src, gfp_t gfp_mask, bio = bio_alloc_bioset(gfp_mask, bio_segments(bio_src), bs); if (!bio) return NULL; - bio->bi_bdev = bio_src->bi_bdev; bio->bi_rw = bio_src->bi_rw; bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) goto integrity_clone; - if (bio->bi_rw & REQ_WRITE_SAME) { + if (bio_op(bio) == REQ_OP_WRITE_SAME) { bio->bi_io_vec[bio->bi_vcnt++] = bio_src->bi_io_vec[0]; goto integrity_clone; } @@ -1166,7 +1165,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, goto out_bmd; if (iter->type & WRITE) - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); ret = 0; @@ -1336,7 +1335,7 @@ struct bio *bio_map_user_iov(struct request_queue *q, * set data direction, and check if mapped pages need bouncing */ if (iter->type & WRITE) - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio_set_flag(bio, BIO_USER_MAPPED); @@ -1529,7 +1528,7 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, bio->bi_private = data; } else { bio->bi_end_io = bio_copy_kern_endio; - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); } return bio; @@ -1784,7 +1783,7 @@ struct bio *bio_split(struct bio *bio, int sectors, * Discards need a mutable bio_vec to accommodate the payload * required by the DSM TRIM and UNMAP commands. */ - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) split = bio_clone_bioset(bio, gfp, bs); else split = bio_clone_fast(bio, gfp, bs); diff --git a/block/blk-core.c b/block/blk-core.c index e8e5865..7e943dc 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1973,14 +1973,14 @@ generic_make_request_checks(struct bio *bio) } } - if ((bio->bi_rw & REQ_DISCARD) && + if ((bio_op(bio) == REQ_OP_DISCARD) && (!blk_queue_discard(q) || ((bio->bi_rw & REQ_SECURE) && !blk_queue_secdiscard(q)))) { err = -EOPNOTSUPP; goto end_io; } - if (bio->bi_rw & REQ_WRITE_SAME && !bdev_write_same(bio->bi_bdev)) { + if (bio_op(bio) == REQ_OP_WRITE_SAME && !bdev_write_same(bio->bi_bdev)) { err = -EOPNOTSUPP; goto end_io; } @@ -2110,7 +2110,7 @@ blk_qc_t submit_bio(struct bio *bio) if (bio_has_data(bio)) { unsigned int count; - if (unlikely(bio->bi_rw & REQ_WRITE_SAME)) + if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME)) count = bdev_logical_block_size(bio->bi_bdev) >> 9; else count = bio_sectors(bio); diff --git a/block/blk-flush.c b/block/blk-flush.c index 3af4a5a..9fd1f63 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -485,7 +485,7 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, bio = bio_alloc(gfp_mask, 0); bio->bi_bdev = bdev; - bio->bi_rw = WRITE_FLUSH; + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); ret = submit_bio_wait(bio); diff --git a/block/blk-lib.c b/block/blk-lib.c index 1f6dec5..c614eaa 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -155,7 +155,7 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, bio->bi_io_vec->bv_page = page; bio->bi_io_vec->bv_offset = 0; bio->bi_io_vec->bv_len = bdev_logical_block_size(bdev); - bio->bi_rw = REQ_WRITE | REQ_WRITE_SAME; + bio_set_op_attrs(bio, REQ_OP_WRITE_SAME, 0); if (nr_sects > max_write_same_sectors) { bio->bi_iter.bi_size = max_write_same_sectors << 9; @@ -196,7 +196,7 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, gfp_mask); bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; - bio->bi_rw = REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); while (nr_sects != 0) { sz = min((sector_t) PAGE_SIZE >> 9 , nr_sects); diff --git a/block/blk-map.c b/block/blk-map.c index b9f88b7..61733a6 100644 --- a/block/blk-map.c +++ b/block/blk-map.c @@ -224,7 +224,7 @@ int blk_rq_map_kern(struct request_queue *q, struct request *rq, void *kbuf, return PTR_ERR(bio); if (!reading) - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); if (do_copy) rq->cmd_flags |= REQ_COPY_USER; diff --git a/block/blk-merge.c b/block/blk-merge.c index b198070..5a03f96 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -172,9 +172,9 @@ void blk_queue_split(struct request_queue *q, struct bio **bio, struct bio *split, *res; unsigned nsegs; - if ((*bio)->bi_rw & REQ_DISCARD) + if (bio_op(*bio) == REQ_OP_DISCARD) split = blk_bio_discard_split(q, *bio, bs, &nsegs); - else if ((*bio)->bi_rw & REQ_WRITE_SAME) + else if (bio_op(*bio) == REQ_OP_WRITE_SAME) split = blk_bio_write_same_split(q, *bio, bs, &nsegs); else split = blk_bio_segment_split(q, *bio, q->bio_split, &nsegs); @@ -213,10 +213,10 @@ static unsigned int __blk_recalc_rq_segments(struct request_queue *q, * This should probably be returning 0, but blk_add_request_payload() * (Christoph!!!!) */ - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) return 1; - if (bio->bi_rw & REQ_WRITE_SAME) + if (bio_op(bio) == REQ_OP_WRITE_SAME) return 1; fbio = bio; @@ -385,7 +385,7 @@ static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, nsegs = 0; cluster = blk_queue_cluster(q); - if (bio->bi_rw & REQ_DISCARD) { + if (bio_op(bio) == REQ_OP_DISCARD) { /* * This is a hack - drivers should be neither modifying the * biovec, nor relying on bi_vcnt - but because of @@ -400,7 +400,7 @@ static int __blk_bios_map_sg(struct request_queue *q, struct bio *bio, return 0; } - if (bio->bi_rw & REQ_WRITE_SAME) { + if (bio_op(bio) == REQ_OP_WRITE_SAME) { single_segment: *sg = sglist; bvec = bio_iovec(bio); diff --git a/drivers/block/brd.c b/drivers/block/brd.c index c04bd9b..f5b0d6f 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -339,7 +339,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio) if (bio_end_sector(bio) > get_capacity(bdev->bd_disk)) goto io_error; - if (unlikely(bio->bi_rw & REQ_DISCARD)) { + if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) { if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) || bio->bi_iter.bi_size & ~PAGE_MASK) goto io_error; diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 73ded25..f9bfecd 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3822,7 +3822,7 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive) bio.bi_flags |= (1 << BIO_QUIET); bio.bi_private = &cbdata; bio.bi_end_io = floppy_rb0_cb; - bio.bi_rw = READ; + bio_set_op_attrs(&bio, REQ_OP_READ, 0); submit_bio(&bio); process_fd_request(); diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index d06c62e..9393bc7 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1074,7 +1074,7 @@ static void pkt_gather_data(struct pktcdvd_device *pd, struct packet_data *pkt) BUG(); atomic_inc(&pkt->io_wait); - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); pkt_queue_bio(pd, bio); frames_read++; } @@ -1336,7 +1336,7 @@ static void pkt_start_write(struct pktcdvd_device *pd, struct packet_data *pkt) /* Start the write request */ atomic_set(&pkt->io_wait, 1); - pkt->w_bio->bi_rw = WRITE; + bio_set_op_attrs(pkt->w_bio, REQ_OP_WRITE, 0); pkt_queue_bio(pd, pkt->w_bio); } diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c index cf8cd29..5a20385f8 100644 --- a/drivers/block/rsxx/dma.c +++ b/drivers/block/rsxx/dma.c @@ -705,7 +705,7 @@ int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, dma_cnt[i] = 0; } - if (bio->bi_rw & REQ_DISCARD) { + if (bio_op(bio) == REQ_OP_DISCARD) { bv_len = bio->bi_iter.bi_size; while (bv_len > 0) { diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 8fcad8b..e5e5d19 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -874,7 +874,7 @@ static void __zram_make_request(struct zram *zram, struct bio *bio) offset = (bio->bi_iter.bi_sector & (SECTORS_PER_PAGE - 1)) << SECTOR_SHIFT; - if (unlikely(bio->bi_rw & REQ_DISCARD)) { + if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) { zram_bio_discard(zram, index, offset, bio); bio_endio(bio); return; diff --git a/drivers/lightnvm/rrpc.c b/drivers/lightnvm/rrpc.c index 2103e97..de86d72 100644 --- a/drivers/lightnvm/rrpc.c +++ b/drivers/lightnvm/rrpc.c @@ -342,7 +342,7 @@ try: /* Perform read to do GC */ bio->bi_iter.bi_sector = rrpc_get_sector(rev->addr); - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); bio->bi_private = &wait; bio->bi_end_io = rrpc_end_sync_bio; @@ -364,7 +364,7 @@ try: reinit_completion(&wait); bio->bi_iter.bi_sector = rrpc_get_sector(rev->addr); - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_private = &wait; bio->bi_end_io = rrpc_end_sync_bio; @@ -908,7 +908,7 @@ static blk_qc_t rrpc_make_rq(struct request_queue *q, struct bio *bio) struct nvm_rq *rqd; int err; - if (bio->bi_rw & REQ_DISCARD) { + if (bio_op(bio) == REQ_OP_DISCARD) { rrpc_discard(rrpc, bio); return BLK_QC_T_NONE; } diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 14ed39b..daa4dc1 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c @@ -726,7 +726,7 @@ static int _osd_req_list_objects(struct osd_request *or, return PTR_ERR(bio); } - bio->bi_rw &= ~REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_READ, 0); or->in.bio = bio; or->in.total_bytes = bio->bi_iter.bi_size; return 0; @@ -839,7 +839,7 @@ int osd_req_write_kern(struct osd_request *or, if (IS_ERR(bio)) return PTR_ERR(bio); - bio->bi_rw |= REQ_WRITE; /* FIXME: bio_set_dir() */ + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); osd_req_write(or, obj, offset, bio, len); return 0; } @@ -956,7 +956,7 @@ static int _osd_req_finalize_cdb_cont(struct osd_request *or, const u8 *cap_key) if (IS_ERR(bio)) return PTR_ERR(bio); - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); /* integrity check the continuation before the bio is linked * with the other data segments since the continuation @@ -1077,7 +1077,7 @@ int osd_req_write_sg_kern(struct osd_request *or, if (IS_ERR(bio)) return PTR_ERR(bio); - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); osd_req_write_sg(or, obj, bio, sglist, numentries); return 0; diff --git a/drivers/staging/lustre/lustre/llite/lloop.c b/drivers/staging/lustre/lustre/llite/lloop.c index 813a9a3..b677930 100644 --- a/drivers/staging/lustre/lustre/llite/lloop.c +++ b/drivers/staging/lustre/lustre/llite/lloop.c @@ -211,9 +211,9 @@ static int do_bio_lustrebacked(struct lloop_device *lo, struct bio *head) return io->ci_result; io->ci_lockreq = CILR_NEVER; - rw = head->bi_rw; + rw = bio_data_dir(head); for (bio = head; bio ; bio = bio->bi_next) { - LASSERT(rw == bio->bi_rw); + LASSERT(rw == bio_data_dir(bio)); offset = (pgoff_t)(bio->bi_iter.bi_sector << 9) + lo->lo_offset; bio_for_each_segment(bvec, bio, iter) { @@ -305,7 +305,7 @@ static unsigned int loop_get_bio(struct lloop_device *lo, struct bio **req) /* TODO: need to split the bio, too bad. */ LASSERT(first->bi_vcnt <= LLOOP_MAX_SEGMENTS); - rw = first->bi_rw; + rw = bio_data_dir(first); bio = &lo->lo_bio; while (*bio && (*bio)->bi_rw == rw) { CDEBUG(D_INFO, "bio sector %llu size %u count %u vcnt%u\n", diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index 5b75856..c502c11 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -318,7 +318,7 @@ int fscrypt_zeroout_range(struct inode *inode, pgoff_t lblk, bio->bi_bdev = inode->i_sb->s_bdev; bio->bi_iter.bi_sector = pblk << (inode->i_sb->s_blocksize_bits - 9); - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); ret = bio_add_page(bio, ciphertext_page, inode->i_sb->s_blocksize, 0); if (ret != inode->i_sb->s_blocksize) { diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 7bd8ac8..8bb7280 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c @@ -878,7 +878,7 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) } else { bio = master_dev->bio; /* FIXME: bio_set_dir() */ - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); } osd_req_write(or, _ios_obj(ios, cur_comp), diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index a72dbcc..5185fed 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -340,9 +340,9 @@ void ext4_io_submit(struct ext4_io_submit *io) struct bio *bio = io->io_bio; if (bio) { - int io_op = io->io_wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC : WRITE; - io->io_bio->bi_rw = io_op; + int io_op_flags = io->io_wbc->sync_mode == WB_SYNC_ALL ? + WRITE_SYNC : 0; + bio_set_op_attrs(io->io_bio, REQ_OP_WRITE, io_op_flags); submit_bio(io->io_bio); } io->io_bio = NULL; diff --git a/fs/ext4/readpage.c b/fs/ext4/readpage.c index 130bd45..2ced5a8 100644 --- a/fs/ext4/readpage.c +++ b/fs/ext4/readpage.c @@ -294,7 +294,7 @@ int ext4_mpage_readpages(struct address_space *mapping, bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9); bio->bi_end_io = mpage_end_io; bio->bi_private = ctx; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); } length = first_hole << blkbits; diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 3ee3f32..a747521 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -2002,7 +2002,7 @@ static int lbmRead(struct jfs_log * log, int pn, struct lbuf ** bpp) bio->bi_end_io = lbmIODone; bio->bi_private = bp; - bio->bi_rw = READ_SYNC; + bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC); /*check if journaling to disk has been disabled*/ if (log->no_integrity) { bio->bi_iter.bi_size = 0; @@ -2146,7 +2146,7 @@ static void lbmStartIO(struct lbuf * bp) bio->bi_end_io = lbmIODone; bio->bi_private = bp; - bio->bi_rw = WRITE_SYNC; + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC); /* check if journaling to disk has been disabled */ if (log->no_integrity) { diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 9725443..e7fa9e5 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -434,7 +434,7 @@ static int metapage_writepage(struct page *page, struct writeback_control *wbc) bio->bi_iter.bi_sector = pblock << (inode->i_blkbits - 9); bio->bi_end_io = metapage_write_end_io; bio->bi_private = page; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); /* Don't call bio_add_page yet, we may add to this vec */ bio_offset = offset; @@ -515,7 +515,7 @@ static int metapage_readpage(struct file *fp, struct page *page) pblock << (inode->i_blkbits - 9); bio->bi_end_io = metapage_read_end_io; bio->bi_private = page; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); len = xlen << inode->i_blkbits; offset = block_offset << inode->i_blkbits; if (bio_add_page(bio, page, len, offset) < len) diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 29704bd..a8329cc 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -14,7 +14,7 @@ #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) -static int sync_request(struct page *page, struct block_device *bdev, int rw) +static int sync_request(struct page *page, struct block_device *bdev, int op) { struct bio bio; struct bio_vec bio_vec; @@ -29,7 +29,7 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw) bio.bi_bdev = bdev; bio.bi_iter.bi_sector = page->index * (PAGE_SIZE >> 9); bio.bi_iter.bi_size = PAGE_SIZE; - bio.bi_rw = rw; + bio_set_op_attrs(&bio, op, 0); return submit_bio_wait(&bio); } @@ -96,7 +96,7 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = writeseg_end_io; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); atomic_inc(&super->s_pending_writes); submit_bio(bio); @@ -124,7 +124,7 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = writeseg_end_io; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); atomic_inc(&super->s_pending_writes); submit_bio(bio); return 0; @@ -188,7 +188,7 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = erase_end_io; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); atomic_inc(&super->s_pending_writes); submit_bio(bio); @@ -210,7 +210,7 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index, bio->bi_iter.bi_sector = ofs >> 9; bio->bi_private = sb; bio->bi_end_io = erase_end_io; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); atomic_inc(&super->s_pending_writes); submit_bio(bio); return 0; diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 4c79f4d..f55a4e7 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -107,7 +107,7 @@ bl_submit_bio(struct bio *bio) if (bio) { get_parallel(bio->bi_private); dprintk("%s submitting %s bio %u@%llu\n", __func__, - bio->bi_rw == READ ? "read" : "write", + bio_op(bio) == READ ? "read" : "write", bio->bi_iter.bi_size, (unsigned long long)bio->bi_iter.bi_sector); submit_bio(bio); @@ -175,7 +175,7 @@ retry: disk_addr >> SECTOR_SHIFT, end_io, par); if (!bio) return ERR_PTR(-ENOMEM); - bio->bi_rw = rw; + bio_set_op_attrs(bio, rw, 0); } if (bio_add_page(bio, page, *len, offset) < *len) { bio = bl_submit_bio(bio); diff --git a/include/linux/bio.h b/include/linux/bio.h index 09c5308..4568647 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -109,18 +109,23 @@ static inline bool bio_has_data(struct bio *bio) { if (bio && bio->bi_iter.bi_size && - !(bio->bi_rw & REQ_DISCARD)) + bio_op(bio) != REQ_OP_DISCARD) return true; return false; } +static inline bool bio_no_advance_iter(struct bio *bio) +{ + return bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_WRITE_SAME; +} + static inline bool bio_is_rw(struct bio *bio) { if (!bio_has_data(bio)) return false; - if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) + if (bio_no_advance_iter(bio)) return false; return true; @@ -228,7 +233,7 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, { iter->bi_sector += bytes >> 9; - if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) + if (bio_no_advance_iter(bio)) iter->bi_size -= bytes; else bvec_iter_advance(bio->bi_io_vec, iter, bytes); @@ -256,10 +261,10 @@ static inline unsigned bio_segments(struct bio *bio) * differently: */ - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) return 1; - if (bio->bi_rw & REQ_WRITE_SAME) + if (bio_op(bio) == REQ_OP_WRITE_SAME) return 1; bio_for_each_segment(bv, bio, iter) diff --git a/mm/page_io.c b/mm/page_io.c index 5a5fd66..dcc5d37 100644 --- a/mm/page_io.c +++ b/mm/page_io.c @@ -317,7 +317,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, ret = -ENOMEM; goto out; } - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); if (wbc->sync_mode == WB_SYNC_ALL) bio->bi_rw |= REQ_SYNC; count_vm_event(PSWPOUT); @@ -370,7 +370,7 @@ int swap_readpage(struct page *page) ret = -ENOMEM; goto out; } - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); count_vm_event(PSWPIN); submit_bio(bio); out: -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7EDD17CD2 for ; Sun, 5 Jun 2016 14:32:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 445468F8040 for ; Sun, 5 Jun 2016 12:32:55 -0700 (PDT) X-ASG-Debug-ID: 1465155173-04cbb0356bb8abc0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id l4bWHubsPAB5ZsEz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:54 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7F9E475742; Sun, 5 Jun 2016 19:32:53 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9G003130; Sun, 5 Jun 2016 15:32:51 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 09/45] block discard: use bio set op accessor Date: Sun, 5 Jun 2016 14:31:49 -0500 X-ASG-Orig-Subj: [PATCH 09/45] block discard: use bio set op accessor Message-Id: <1465155145-10812-10-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Sun, 05 Jun 2016 19:32:53 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155174 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3694 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This converts the block issue discard helper and users to use the bio_set_op_attrs accessor and only pass in the operation flags like REQ_SEQURE. Signed-off-by: Mike Christie --- block/blk-lib.c | 13 +++++++------ drivers/md/dm-thin.c | 2 +- include/linux/blkdev.h | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/block/blk-lib.c b/block/blk-lib.c index c614eaa..ff2a7f0 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -23,7 +23,8 @@ static struct bio *next_bio(struct bio *bio, unsigned int nr_pages, } int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, - sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop) + sector_t nr_sects, gfp_t gfp_mask, int op_flags, + struct bio **biop) { struct request_queue *q = bdev_get_queue(bdev); struct bio *bio = *biop; @@ -34,7 +35,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, return -ENXIO; if (!blk_queue_discard(q)) return -EOPNOTSUPP; - if ((type & REQ_SECURE) && !blk_queue_secdiscard(q)) + if ((op_flags & REQ_SECURE) && !blk_queue_secdiscard(q)) return -EOPNOTSUPP; /* Zero-sector (unknown) and one-sector granularities are the same. */ @@ -65,7 +66,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, bio = next_bio(bio, 1, gfp_mask); bio->bi_iter.bi_sector = sector; bio->bi_bdev = bdev; - bio->bi_rw = type; + bio_set_op_attrs(bio, REQ_OP_DISCARD, op_flags); bio->bi_iter.bi_size = req_sects << 9; nr_sects -= req_sects; @@ -99,16 +100,16 @@ EXPORT_SYMBOL(__blkdev_issue_discard); int blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, unsigned long flags) { - int type = REQ_WRITE | REQ_DISCARD; + int op_flags = 0; struct bio *bio = NULL; struct blk_plug plug; int ret; if (flags & BLKDEV_DISCARD_SECURE) - type |= REQ_SECURE; + op_flags |= REQ_SECURE; blk_start_plug(&plug); - ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, type, + ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, op_flags, &bio); if (!ret && bio) { ret = submit_bio_wait(bio); diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 8c070ee..e8661c2 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -360,7 +360,7 @@ static int issue_discard(struct discard_op *op, dm_block_t data_b, dm_block_t da sector_t len = block_to_sectors(tc->pool, data_e - data_b); return __blkdev_issue_discard(tc->pool_dev->bdev, s, len, - GFP_NOWAIT, REQ_WRITE | REQ_DISCARD, &op->bio); + GFP_NOWAIT, 0, &op->bio); } static void end_discard(struct discard_op *op, int r) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 49c2dbc..8c78aca 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1149,7 +1149,8 @@ extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *); extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, unsigned long flags); extern int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, - sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop); + sector_t nr_sects, gfp_t gfp_mask, int op_flags, + struct bio **biop); extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, sector_t nr_sects, gfp_t gfp_mask, struct page *page); extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:32:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id ED01C7CCD for ; Sun, 5 Jun 2016 14:32:57 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id AD9F68F8039 for ; Sun, 5 Jun 2016 12:32:57 -0700 (PDT) X-ASG-Debug-ID: 1465155176-04bdf05ad7b78470001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id sGaMV1KhvVUNBUKD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:56 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C2C6B7AE85; Sun, 5 Jun 2016 19:32:55 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9H003130; Sun, 5 Jun 2016 15:32:53 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 10/45] direct-io: use bio set/get op accessors Date: Sun, 5 Jun 2016 14:31:50 -0500 X-ASG-Orig-Subj: [PATCH 10/45] direct-io: use bio set/get op accessors Message-Id: <1465155145-10812-11-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Sun, 05 Jun 2016 19:32:55 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155176 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6573 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch has the dio code use a REQ_OP for the op and rq_flag_bits for bi_rw flags. To set/get the op it uses the bio_set_op_attrs/bio_op accssors. It also begins to convert btrfs's dio_submit_t because of the dio submit_io callout use. The next patches will completely convert this code and the reset of the btrfs code paths. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/btrfs/inode.c | 8 ++++---- fs/direct-io.c | 34 ++++++++++++++++++++-------------- include/linux/fs.h | 2 +- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2704995..96f9192 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8422,14 +8422,14 @@ out_err: return 0; } -static void btrfs_submit_direct(int rw, struct bio *dio_bio, - struct inode *inode, loff_t file_offset) +static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode, + loff_t file_offset) { struct btrfs_dio_private *dip = NULL; struct bio *io_bio = NULL; struct btrfs_io_bio *btrfs_bio; int skip_sum; - int write = rw & REQ_WRITE; + bool write = (bio_op(dio_bio) == REQ_OP_WRITE); int ret = 0; skip_sum = BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM; @@ -8480,7 +8480,7 @@ static void btrfs_submit_direct(int rw, struct bio *dio_bio, dio_data->unsubmitted_oe_range_end; } - ret = btrfs_submit_direct_hook(rw, dip, skip_sum); + ret = btrfs_submit_direct_hook(dio_bio->bi_rw, dip, skip_sum); if (!ret) return; diff --git a/fs/direct-io.c b/fs/direct-io.c index 1bcdd5d..7c3ce73 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -108,7 +108,8 @@ struct dio_submit { /* dio_state communicated between submission path and end_io */ struct dio { int flags; /* doesn't change */ - int rw; + int op; + int op_flags; blk_qc_t bio_cookie; struct block_device *bio_bdev; struct inode *inode; @@ -163,7 +164,7 @@ static inline int dio_refill_pages(struct dio *dio, struct dio_submit *sdio) ret = iov_iter_get_pages(sdio->iter, dio->pages, LONG_MAX, DIO_PAGES, &sdio->from); - if (ret < 0 && sdio->blocks_available && (dio->rw & WRITE)) { + if (ret < 0 && sdio->blocks_available && (dio->op == REQ_OP_WRITE)) { struct page *page = ZERO_PAGE(0); /* * A memory fault, but the filesystem has some outstanding @@ -242,7 +243,8 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) transferred = dio->result; /* Check for short read case */ - if ((dio->rw == READ) && ((offset + transferred) > dio->i_size)) + if ((dio->op == REQ_OP_READ) && + ((offset + transferred) > dio->i_size)) transferred = dio->i_size - offset; } @@ -273,7 +275,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, bool is_async) */ dio->iocb->ki_pos += transferred; - if (dio->rw & WRITE) + if (dio->op == REQ_OP_WRITE) ret = generic_write_sync(dio->iocb, transferred); dio->iocb->ki_complete(dio->iocb, ret, 0); } @@ -375,7 +377,7 @@ dio_bio_alloc(struct dio *dio, struct dio_submit *sdio, bio->bi_bdev = bdev; bio->bi_iter.bi_sector = first_sector; - bio->bi_rw = dio->rw; + bio_set_op_attrs(bio, dio->op, dio->op_flags); if (dio->is_async) bio->bi_end_io = dio_bio_end_aio; else @@ -403,14 +405,13 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio) dio->refcount++; spin_unlock_irqrestore(&dio->bio_lock, flags); - if (dio->is_async && dio->rw == READ && dio->should_dirty) + if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) bio_set_pages_dirty(bio); dio->bio_bdev = bio->bi_bdev; if (sdio->submit_io) { - sdio->submit_io(dio->rw, bio, dio->inode, - sdio->logical_offset_in_bio); + sdio->submit_io(bio, dio->inode, sdio->logical_offset_in_bio); dio->bio_cookie = BLK_QC_T_NONE; } else dio->bio_cookie = submit_bio(bio); @@ -479,14 +480,14 @@ static int dio_bio_complete(struct dio *dio, struct bio *bio) if (bio->bi_error) dio->io_error = -EIO; - if (dio->is_async && dio->rw == READ && dio->should_dirty) { + if (dio->is_async && dio->op == REQ_OP_READ && dio->should_dirty) { err = bio->bi_error; bio_check_pages_dirty(bio); /* transfers ownership */ } else { bio_for_each_segment_all(bvec, bio, i) { struct page *page = bvec->bv_page; - if (dio->rw == READ && !PageCompound(page) && + if (dio->op == REQ_OP_READ && !PageCompound(page) && dio->should_dirty) set_page_dirty_lock(page); put_page(page); @@ -639,7 +640,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, * which may decide to handle it or also return an unmapped * buffer head. */ - create = dio->rw & WRITE; + create = dio->op == REQ_OP_WRITE; if (dio->flags & DIO_SKIP_HOLES) { if (fs_startblk <= ((i_size_read(dio->inode) - 1) >> i_blkbits)) @@ -789,7 +790,7 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, { int ret = 0; - if (dio->rw & WRITE) { + if (dio->op == REQ_OP_WRITE) { /* * Read accounting is performed in submit_bio() */ @@ -989,7 +990,7 @@ do_holes: loff_t i_size_aligned; /* AKPM: eargh, -ENOTBLK is a hack */ - if (dio->rw & WRITE) { + if (dio->op == REQ_OP_WRITE) { put_page(page); return -ENOTBLK; } @@ -1203,7 +1204,12 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode, dio->is_async = true; dio->inode = inode; - dio->rw = iov_iter_rw(iter) == WRITE ? WRITE_ODIRECT : READ; + if (iov_iter_rw(iter) == WRITE) { + dio->op = REQ_OP_WRITE; + dio->op_flags = WRITE_ODIRECT; + } else { + dio->op = REQ_OP_READ; + } /* * For AIO O_(D)SYNC writes we need to defer completions to a workqueue diff --git a/include/linux/fs.h b/include/linux/fs.h index 62ca2f9..af6f3c7 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2824,7 +2824,7 @@ extern int generic_file_open(struct inode * inode, struct file * filp); extern int nonseekable_open(struct inode * inode, struct file * filp); #ifdef CONFIG_BLOCK -typedef void (dio_submit_t)(int rw, struct bio *bio, struct inode *inode, +typedef void (dio_submit_t)(struct bio *bio, struct inode *inode, loff_t file_offset); enum { -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:00 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 886297CD1 for ; Sun, 5 Jun 2016 14:33:00 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5B1998F8039 for ; Sun, 5 Jun 2016 12:33:00 -0700 (PDT) X-ASG-Debug-ID: 1465155178-04cb6c2db9b58db0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id jd4p4eJbS5gcV9MT (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:32:58 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 18A0D63E2B; Sun, 5 Jun 2016 19:32:58 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9I003130; Sun, 5 Jun 2016 15:32:55 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 11/45] btrfs: have submit_one_bio users use bio op accessors Date: Sun, 5 Jun 2016 14:31:51 -0500 X-ASG-Orig-Subj: [PATCH 11/45] btrfs: have submit_one_bio users use bio op accessors Message-Id: <1465155145-10812-12-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Sun, 05 Jun 2016 19:32:58 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155178 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11609 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch has btrfs's submit_one_bio users set the bio op using bio_set_op_attrs and get the op using bio_op. The next patches will continue to convert btrfs, so submit_bio_hook and merge_bio_hook related code will be modified to take only the bio. I did not do it in this patch to try and keep it smaller. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/btrfs/extent_io.c | 88 +++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 45 deletions(-) diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c1e6f20..48f0302 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2377,7 +2377,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, int read_mode; int ret; - BUG_ON(failed_bio->bi_rw & REQ_WRITE); + BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE); ret = btrfs_get_io_failure_record(inode, start, end, &failrec); if (ret) @@ -2403,6 +2403,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, free_io_failure(inode, failrec); return -EIO; } + bio_set_op_attrs(bio, REQ_OP_READ, read_mode); pr_debug("Repair Read Error: submitting new read[%#x] to this_mirror=%d, in_validation=%d\n", read_mode, failrec->this_mirror, failrec->in_validation); @@ -2714,8 +2715,8 @@ struct bio *btrfs_io_bio_alloc(gfp_t gfp_mask, unsigned int nr_iovecs) } -static int __must_check submit_one_bio(int rw, struct bio *bio, - int mirror_num, unsigned long bio_flags) +static int __must_check submit_one_bio(struct bio *bio, int mirror_num, + unsigned long bio_flags) { int ret = 0; struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; @@ -2726,12 +2727,12 @@ static int __must_check submit_one_bio(int rw, struct bio *bio, start = page_offset(page) + bvec->bv_offset; bio->bi_private = NULL; - bio->bi_rw = rw; bio_get(bio); if (tree->ops && tree->ops->submit_bio_hook) - ret = tree->ops->submit_bio_hook(page->mapping->host, rw, bio, - mirror_num, bio_flags, start); + ret = tree->ops->submit_bio_hook(page->mapping->host, + bio->bi_rw, bio, mirror_num, + bio_flags, start); else btrfsic_submit_bio(bio); @@ -2739,20 +2740,20 @@ static int __must_check submit_one_bio(int rw, struct bio *bio, return ret; } -static int merge_bio(int rw, struct extent_io_tree *tree, struct page *page, +static int merge_bio(struct extent_io_tree *tree, struct page *page, unsigned long offset, size_t size, struct bio *bio, unsigned long bio_flags) { int ret = 0; if (tree->ops && tree->ops->merge_bio_hook) - ret = tree->ops->merge_bio_hook(rw, page, offset, size, bio, - bio_flags); + ret = tree->ops->merge_bio_hook(bio_op(bio), page, offset, size, + bio, bio_flags); BUG_ON(ret < 0); return ret; } -static int submit_extent_page(int rw, struct extent_io_tree *tree, +static int submit_extent_page(int op, int op_flags, struct extent_io_tree *tree, struct writeback_control *wbc, struct page *page, sector_t sector, size_t size, unsigned long offset, @@ -2780,10 +2781,9 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, if (prev_bio_flags != bio_flags || !contig || force_bio_submit || - merge_bio(rw, tree, page, offset, page_size, bio, bio_flags) || + merge_bio(tree, page, offset, page_size, bio, bio_flags) || bio_add_page(bio, page, page_size, offset) < page_size) { - ret = submit_one_bio(rw, bio, mirror_num, - prev_bio_flags); + ret = submit_one_bio(bio, mirror_num, prev_bio_flags); if (ret < 0) { *bio_ret = NULL; return ret; @@ -2804,6 +2804,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, bio_add_page(bio, page, page_size, offset); bio->bi_end_io = end_io_func; bio->bi_private = tree; + bio_set_op_attrs(bio, op, op_flags); if (wbc) { wbc_init_bio(wbc, bio); wbc_account_io(wbc, page, page_size); @@ -2812,7 +2813,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, if (bio_ret) *bio_ret = bio; else - ret = submit_one_bio(rw, bio, mirror_num, bio_flags); + ret = submit_one_bio(bio, mirror_num, bio_flags); return ret; } @@ -2876,7 +2877,7 @@ static int __do_readpage(struct extent_io_tree *tree, get_extent_t *get_extent, struct extent_map **em_cached, struct bio **bio, int mirror_num, - unsigned long *bio_flags, int rw, + unsigned long *bio_flags, int read_flags, u64 *prev_em_start) { struct inode *inode = page->mapping->host; @@ -3059,8 +3060,8 @@ static int __do_readpage(struct extent_io_tree *tree, } pnr -= page->index; - ret = submit_extent_page(rw, tree, NULL, page, - sector, disk_io_size, pg_offset, + ret = submit_extent_page(REQ_OP_READ, read_flags, tree, NULL, + page, sector, disk_io_size, pg_offset, bdev, bio, pnr, end_bio_extent_readpage, mirror_num, *bio_flags, @@ -3091,7 +3092,7 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree, get_extent_t *get_extent, struct extent_map **em_cached, struct bio **bio, int mirror_num, - unsigned long *bio_flags, int rw, + unsigned long *bio_flags, u64 *prev_em_start) { struct inode *inode; @@ -3112,7 +3113,7 @@ static inline void __do_contiguous_readpages(struct extent_io_tree *tree, for (index = 0; index < nr_pages; index++) { __do_readpage(tree, pages[index], get_extent, em_cached, bio, - mirror_num, bio_flags, rw, prev_em_start); + mirror_num, bio_flags, 0, prev_em_start); put_page(pages[index]); } } @@ -3122,7 +3123,7 @@ static void __extent_readpages(struct extent_io_tree *tree, int nr_pages, get_extent_t *get_extent, struct extent_map **em_cached, struct bio **bio, int mirror_num, - unsigned long *bio_flags, int rw, + unsigned long *bio_flags, u64 *prev_em_start) { u64 start = 0; @@ -3144,7 +3145,7 @@ static void __extent_readpages(struct extent_io_tree *tree, index - first_index, start, end, get_extent, em_cached, bio, mirror_num, bio_flags, - rw, prev_em_start); + prev_em_start); start = page_start; end = start + PAGE_SIZE - 1; first_index = index; @@ -3155,7 +3156,7 @@ static void __extent_readpages(struct extent_io_tree *tree, __do_contiguous_readpages(tree, &pages[first_index], index - first_index, start, end, get_extent, em_cached, bio, - mirror_num, bio_flags, rw, + mirror_num, bio_flags, prev_em_start); } @@ -3163,7 +3164,7 @@ static int __extent_read_full_page(struct extent_io_tree *tree, struct page *page, get_extent_t *get_extent, struct bio **bio, int mirror_num, - unsigned long *bio_flags, int rw) + unsigned long *bio_flags, int read_flags) { struct inode *inode = page->mapping->host; struct btrfs_ordered_extent *ordered; @@ -3183,7 +3184,7 @@ static int __extent_read_full_page(struct extent_io_tree *tree, } ret = __do_readpage(tree, page, get_extent, NULL, bio, mirror_num, - bio_flags, rw, NULL); + bio_flags, read_flags, NULL); return ret; } @@ -3195,9 +3196,9 @@ int extent_read_full_page(struct extent_io_tree *tree, struct page *page, int ret; ret = __extent_read_full_page(tree, page, get_extent, &bio, mirror_num, - &bio_flags, READ); + &bio_flags, 0); if (bio) - ret = submit_one_bio(READ, bio, mirror_num, bio_flags); + ret = submit_one_bio(bio, mirror_num, bio_flags); return ret; } @@ -3431,8 +3432,8 @@ static noinline_for_stack int __extent_writepage_io(struct inode *inode, page->index, cur, end); } - ret = submit_extent_page(write_flags, tree, wbc, page, - sector, iosize, pg_offset, + ret = submit_extent_page(REQ_OP_WRITE, write_flags, tree, wbc, + page, sector, iosize, pg_offset, bdev, &epd->bio, max_nr, end_bio_extent_writepage, 0, 0, 0, false); @@ -3471,13 +3472,11 @@ static int __extent_writepage(struct page *page, struct writeback_control *wbc, size_t pg_offset = 0; loff_t i_size = i_size_read(inode); unsigned long end_index = i_size >> PAGE_SHIFT; - int write_flags; + int write_flags = 0; unsigned long nr_written = 0; if (wbc->sync_mode == WB_SYNC_ALL) write_flags = WRITE_SYNC; - else - write_flags = WRITE; trace___extent_writepage(page, inode, wbc); @@ -3721,7 +3720,7 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, u64 offset = eb->start; unsigned long i, num_pages; unsigned long bio_flags = 0; - int rw = (epd->sync_io ? WRITE_SYNC : WRITE) | REQ_META; + int write_flags = (epd->sync_io ? WRITE_SYNC : 0) | REQ_META; int ret = 0; clear_bit(EXTENT_BUFFER_WRITE_ERR, &eb->bflags); @@ -3735,9 +3734,10 @@ static noinline_for_stack int write_one_eb(struct extent_buffer *eb, clear_page_dirty_for_io(p); set_page_writeback(p); - ret = submit_extent_page(rw, tree, wbc, p, offset >> 9, - PAGE_SIZE, 0, bdev, &epd->bio, - -1, end_bio_extent_buffer_writepage, + ret = submit_extent_page(REQ_OP_WRITE, write_flags, tree, wbc, + p, offset >> 9, PAGE_SIZE, 0, bdev, + &epd->bio, -1, + end_bio_extent_buffer_writepage, 0, epd->bio_flags, bio_flags, false); epd->bio_flags = bio_flags; if (ret) { @@ -4047,13 +4047,12 @@ retry: static void flush_epd_write_bio(struct extent_page_data *epd) { if (epd->bio) { - int rw = WRITE; int ret; - if (epd->sync_io) - rw = WRITE_SYNC; + bio_set_op_attrs(epd->bio, REQ_OP_WRITE, + epd->sync_io ? WRITE_SYNC : 0); - ret = submit_one_bio(rw, epd->bio, 0, epd->bio_flags); + ret = submit_one_bio(epd->bio, 0, epd->bio_flags); BUG_ON(ret < 0); /* -ENOMEM */ epd->bio = NULL; } @@ -4180,19 +4179,19 @@ int extent_readpages(struct extent_io_tree *tree, if (nr < ARRAY_SIZE(pagepool)) continue; __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, - &bio, 0, &bio_flags, READ, &prev_em_start); + &bio, 0, &bio_flags, &prev_em_start); nr = 0; } if (nr) __extent_readpages(tree, pagepool, nr, get_extent, &em_cached, - &bio, 0, &bio_flags, READ, &prev_em_start); + &bio, 0, &bio_flags, &prev_em_start); if (em_cached) free_extent_map(em_cached); BUG_ON(!list_empty(pages)); if (bio) - return submit_one_bio(READ, bio, 0, bio_flags); + return submit_one_bio(bio, 0, bio_flags); return 0; } @@ -5218,7 +5217,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, err = __extent_read_full_page(tree, page, get_extent, &bio, mirror_num, &bio_flags, - READ | REQ_META); + REQ_META); if (err) ret = err; } else { @@ -5227,8 +5226,7 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, } if (bio) { - err = submit_one_bio(READ | REQ_META, bio, mirror_num, - bio_flags); + err = submit_one_bio(bio, mirror_num, bio_flags); if (err) return err; } -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0FC4D7CE6 for ; Sun, 5 Jun 2016 14:33:03 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id D572A304043 for ; Sun, 5 Jun 2016 12:33:02 -0700 (PDT) X-ASG-Debug-ID: 1465155180-04cb6c2dbbb58dc0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id crFM1VoOPBc9VLkw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:01 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 571FB3F139; Sun, 5 Jun 2016 19:33:00 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9J003130; Sun, 5 Jun 2016 15:32:58 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 12/45] btrfs: use bio op accessors Date: Sun, 5 Jun 2016 14:31:52 -0500 X-ASG-Orig-Subj: [PATCH 12/45] btrfs: use bio op accessors Message-Id: <1465155145-10812-13-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:33:00 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155180 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15721 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This should be the easier cases to convert btrfs to bio_set_op_attrs/bio_op. They are mostly just cut and replace type of changes. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- v5: - Misset bi_rw to REQ_OP_WRITE in finish_parity_scrub fs/btrfs/check-integrity.c | 19 +++++++++---------- fs/btrfs/compression.c | 4 ++++ fs/btrfs/disk-io.c | 8 ++++---- fs/btrfs/inode.c | 21 ++++++++++++--------- fs/btrfs/raid56.c | 10 +++++----- fs/btrfs/scrub.c | 10 +++++----- fs/btrfs/volumes.c | 15 ++++++++------- 7 files changed, 47 insertions(+), 40 deletions(-) diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 0d3748b..80a4389 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -1673,7 +1673,7 @@ static int btrfsic_read_block(struct btrfsic_state *state, } bio->bi_bdev = block_ctx->dev->bdev; bio->bi_iter.bi_sector = dev_bytenr >> 9; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); for (j = i; j < num_pages; j++) { ret = bio_add_page(bio, block_ctx->pagev[j], @@ -2922,7 +2922,6 @@ int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh) static void __btrfsic_submit_bio(struct bio *bio) { struct btrfsic_dev_state *dev_state; - int rw = bio->bi_rw; if (!btrfsic_is_initialized) return; @@ -2932,7 +2931,7 @@ static void __btrfsic_submit_bio(struct bio *bio) * btrfsic_mount(), this might return NULL */ dev_state = btrfsic_dev_state_lookup(bio->bi_bdev); if (NULL != dev_state && - (rw & WRITE) && NULL != bio->bi_io_vec) { + (bio_op(bio) == REQ_OP_WRITE) && NULL != bio->bi_io_vec) { unsigned int i; u64 dev_bytenr; u64 cur_bytenr; @@ -2944,9 +2943,9 @@ static void __btrfsic_submit_bio(struct bio *bio) if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO - "submit_bio(rw=0x%x, bi_vcnt=%u," + "submit_bio(rw=%d,0x%lx, bi_vcnt=%u," " bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n", - rw, bio->bi_vcnt, + bio_op(bio), bio->bi_rw, bio->bi_vcnt, (unsigned long long)bio->bi_iter.bi_sector, dev_bytenr, bio->bi_bdev); @@ -2977,18 +2976,18 @@ static void __btrfsic_submit_bio(struct bio *bio) btrfsic_process_written_block(dev_state, dev_bytenr, mapped_datav, bio->bi_vcnt, bio, &bio_is_patched, - NULL, rw); + NULL, bio->bi_rw); while (i > 0) { i--; kunmap(bio->bi_io_vec[i].bv_page); } kfree(mapped_datav); - } else if (NULL != dev_state && (rw & REQ_FLUSH)) { + } else if (NULL != dev_state && (bio->bi_rw & REQ_FLUSH)) { if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO - "submit_bio(rw=0x%x FLUSH, bdev=%p)\n", - rw, bio->bi_bdev); + "submit_bio(rw=%d,0x%lx FLUSH, bdev=%p)\n", + bio_op(bio), bio->bi_rw, bio->bi_bdev); if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) { if ((dev_state->state->print_mask & (BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH | @@ -3006,7 +3005,7 @@ static void __btrfsic_submit_bio(struct bio *bio) block->never_written = 0; block->iodone_w_error = 0; block->flush_gen = dev_state->last_flush_gen + 1; - block->submit_bio_bh_rw = rw; + block->submit_bio_bh_rw = bio->bi_rw; block->orig_bio_bh_private = bio->bi_private; block->orig_bio_bh_end_io.bio = bio->bi_end_io; block->next_in_same_bio = NULL; diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 658c39b..029bd79 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -363,6 +363,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, kfree(cb); return -ENOMEM; } + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_private = cb; bio->bi_end_io = end_compressed_bio_write; atomic_inc(&cb->pending_bios); @@ -408,6 +409,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS); BUG_ON(!bio); + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_private = cb; bio->bi_end_io = end_compressed_bio_write; bio_add_page(bio, page, PAGE_SIZE, 0); @@ -646,6 +648,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS); if (!comp_bio) goto fail2; + bio_set_op_attrs (comp_bio, REQ_OP_READ, 0); comp_bio->bi_private = cb; comp_bio->bi_end_io = end_compressed_bio_read; atomic_inc(&cb->pending_bios); @@ -699,6 +702,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, comp_bio = compressed_bio_alloc(bdev, cur_disk_byte, GFP_NOFS); BUG_ON(!comp_bio); + bio_set_op_attrs(comp_bio, REQ_OP_READ, 0); comp_bio->bi_private = cb; comp_bio->bi_end_io = end_compressed_bio_read; diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 11033ce..93278c2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -727,7 +727,7 @@ static void end_workqueue_bio(struct bio *bio) fs_info = end_io_wq->info; end_io_wq->error = bio->bi_error; - if (bio->bi_rw & REQ_WRITE) { + if (bio_op(bio) == REQ_OP_WRITE) { if (end_io_wq->metadata == BTRFS_WQ_ENDIO_METADATA) { wq = fs_info->endio_meta_write_workers; func = btrfs_endio_meta_write_helper; @@ -873,7 +873,7 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, atomic_inc(&fs_info->nr_async_submits); - if (rw & REQ_SYNC) + if (bio->bi_rw & REQ_SYNC) btrfs_set_work_high_priority(&async->work); btrfs_queue_work(fs_info->workers, &async->work); @@ -951,7 +951,7 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, int async = check_async_write(inode, bio_flags); int ret; - if (!(rw & REQ_WRITE)) { + if (bio_op(bio) != REQ_OP_WRITE) { /* * called for a read, do the setup so that checksum validation * can happen in the async kernel threads @@ -3486,7 +3486,7 @@ static int write_dev_flush(struct btrfs_device *device, int wait) bio->bi_end_io = btrfs_end_empty_barrier; bio->bi_bdev = device->bdev; - bio->bi_rw = WRITE_FLUSH; + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); init_completion(&device->flush_wait); bio->bi_private = &device->flush_wait; device->flush_bio = bio; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 96f9192..b07e1d9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1910,7 +1910,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, if (btrfs_is_free_space_inode(inode)) metadata = BTRFS_WQ_ENDIO_FREE_SPACE; - if (!(rw & REQ_WRITE)) { + if (bio_op(bio) != REQ_OP_WRITE) { ret = btrfs_bio_wq_end_io(root->fs_info, bio, metadata); if (ret) goto out; @@ -7772,7 +7772,7 @@ static inline int submit_dio_repair_bio(struct inode *inode, struct bio *bio, struct btrfs_root *root = BTRFS_I(inode)->root; int ret; - BUG_ON(rw & REQ_WRITE); + BUG_ON(bio_op(bio) == REQ_OP_WRITE); bio_get(bio); @@ -7832,7 +7832,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, int read_mode; int ret; - BUG_ON(failed_bio->bi_rw & REQ_WRITE); + BUG_ON(bio_op(failed_bio) == REQ_OP_WRITE); ret = btrfs_get_io_failure_record(inode, start, end, &failrec); if (ret) @@ -7860,6 +7860,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, free_io_failure(inode, failrec); return -EIO; } + bio_set_op_attrs(bio, REQ_OP_READ, read_mode); btrfs_debug(BTRFS_I(inode)->root->fs_info, "Repair DIO Read Error: submitting new dio read[%#x] to this_mirror=%d, in_validation=%d\n", @@ -8174,8 +8175,8 @@ static void btrfs_end_dio_bio(struct bio *bio) if (err) btrfs_warn(BTRFS_I(dip->inode)->root->fs_info, - "direct IO failed ino %llu rw %lu sector %#Lx len %u err no %d", - btrfs_ino(dip->inode), bio->bi_rw, + "direct IO failed ino %llu rw %d,%lu sector %#Lx len %u err no %d", + btrfs_ino(dip->inode), bio_op(bio), bio->bi_rw, (unsigned long long)bio->bi_iter.bi_sector, bio->bi_iter.bi_size, err); @@ -8253,7 +8254,7 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, int async_submit) { struct btrfs_dio_private *dip = bio->bi_private; - int write = rw & REQ_WRITE; + bool write = bio_op(bio) == REQ_OP_WRITE; struct btrfs_root *root = BTRFS_I(inode)->root; int ret; @@ -8319,8 +8320,8 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, int i; map_length = orig_bio->bi_iter.bi_size; - ret = btrfs_map_block(root->fs_info, rw, start_sector << 9, - &map_length, NULL, 0); + ret = btrfs_map_block(root->fs_info, bio_op(orig_bio), + start_sector << 9, &map_length, NULL, 0); if (ret) return -EIO; @@ -8340,6 +8341,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, if (!bio) return -ENOMEM; + bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_rw); bio->bi_private = dip; bio->bi_end_io = btrfs_end_dio_bio; btrfs_io_bio(bio)->logical = file_offset; @@ -8377,12 +8379,13 @@ next_block: start_sector, GFP_NOFS); if (!bio) goto out_err; + bio_set_op_attrs(bio, bio_op(orig_bio), orig_bio->bi_rw); bio->bi_private = dip; bio->bi_end_io = btrfs_end_dio_bio; btrfs_io_bio(bio)->logical = file_offset; map_length = orig_bio->bi_iter.bi_size; - ret = btrfs_map_block(root->fs_info, rw, + ret = btrfs_map_block(root->fs_info, bio_op(orig_bio), start_sector << 9, &map_length, NULL, 0); if (ret) { diff --git a/fs/btrfs/raid56.c b/fs/btrfs/raid56.c index 36d5bf7..cd8d302 100644 --- a/fs/btrfs/raid56.c +++ b/fs/btrfs/raid56.c @@ -1320,7 +1320,7 @@ write_data: bio->bi_private = rbio; bio->bi_end_io = raid_write_end_io; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); submit_bio(bio); } @@ -1575,7 +1575,7 @@ static int raid56_rmw_stripe(struct btrfs_raid_bio *rbio) bio->bi_private = rbio; bio->bi_end_io = raid_rmw_end_io; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); btrfs_bio_wq_end_io(rbio->fs_info, bio, BTRFS_WQ_ENDIO_RAID56); @@ -2100,7 +2100,7 @@ static int __raid56_parity_recover(struct btrfs_raid_bio *rbio) bio->bi_private = rbio; bio->bi_end_io = raid_recover_end_io; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); btrfs_bio_wq_end_io(rbio->fs_info, bio, BTRFS_WQ_ENDIO_RAID56); @@ -2437,7 +2437,7 @@ submit_write: bio->bi_private = rbio; bio->bi_end_io = raid_write_end_io; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); submit_bio(bio); } @@ -2616,7 +2616,7 @@ static void raid56_parity_scrub_stripe(struct btrfs_raid_bio *rbio) bio->bi_private = rbio; bio->bi_end_io = raid56_parity_scrub_end_io; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); btrfs_bio_wq_end_io(rbio->fs_info, bio, BTRFS_WQ_ENDIO_RAID56); diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 44da605..980a555 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -1504,7 +1504,7 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info, sblock->no_io_error_seen = 0; } else { bio->bi_iter.bi_sector = page->physical >> 9; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); if (btrfsic_submit_bio_wait(bio)) sblock->no_io_error_seen = 0; @@ -1584,7 +1584,7 @@ static int scrub_repair_page_from_good_copy(struct scrub_block *sblock_bad, return -EIO; bio->bi_bdev = page_bad->dev->bdev; bio->bi_iter.bi_sector = page_bad->physical >> 9; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); ret = bio_add_page(bio, page_good->page, PAGE_SIZE, 0); if (PAGE_SIZE != ret) { @@ -1686,7 +1686,7 @@ again: bio->bi_end_io = scrub_wr_bio_end_io; bio->bi_bdev = sbio->dev->bdev; bio->bi_iter.bi_sector = sbio->physical >> 9; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); sbio->err = 0; } else if (sbio->physical + sbio->page_count * PAGE_SIZE != spage->physical_for_dev_replace || @@ -2091,7 +2091,7 @@ again: bio->bi_end_io = scrub_bio_end_io; bio->bi_bdev = sbio->dev->bdev; bio->bi_iter.bi_sector = sbio->physical >> 9; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); sbio->err = 0; } else if (sbio->physical + sbio->page_count * PAGE_SIZE != spage->physical || @@ -4396,7 +4396,7 @@ static int write_page_nocow(struct scrub_ctx *sctx, bio->bi_iter.bi_size = 0; bio->bi_iter.bi_sector = physical_for_dev_replace >> 9; bio->bi_bdev = dev->bdev; - bio->bi_rw = WRITE_SYNC; + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_SYNC); ret = bio_add_page(bio, page, PAGE_SIZE, 0); if (ret != PAGE_SIZE) { leave_with_eio: diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index d549f23..4dc2249 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -5934,7 +5934,7 @@ static void btrfs_end_bio(struct bio *bio) BUG_ON(stripe_index >= bbio->num_stripes); dev = bbio->stripes[stripe_index].dev; if (dev->bdev) { - if (bio->bi_rw & WRITE) + if (bio_op(bio) == REQ_OP_WRITE) btrfs_dev_stat_inc(dev, BTRFS_DEV_STAT_WRITE_ERRS); else @@ -5999,7 +5999,7 @@ static noinline void btrfs_schedule_bio(struct btrfs_root *root, } /* don't bother with additional async steps for reads, right now */ - if (!(bio->bi_rw & REQ_WRITE)) { + if (bio_op(bio) == REQ_OP_READ) { bio_get(bio); btrfsic_submit_bio(bio); bio_put(bio); @@ -6103,8 +6103,8 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, map_length = length; btrfs_bio_counter_inc_blocked(root->fs_info); - ret = __btrfs_map_block(root->fs_info, rw, logical, &map_length, &bbio, - mirror_num, 1); + ret = __btrfs_map_block(root->fs_info, bio_op(bio), logical, + &map_length, &bbio, mirror_num, 1); if (ret) { btrfs_bio_counter_dec(root->fs_info); return ret; @@ -6118,10 +6118,10 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, atomic_set(&bbio->stripes_pending, bbio->num_stripes); if ((bbio->map_type & BTRFS_BLOCK_GROUP_RAID56_MASK) && - ((rw & WRITE) || (mirror_num > 1))) { + ((bio_op(bio) == REQ_OP_WRITE) || (mirror_num > 1))) { /* In this case, map_length has been set to the length of a single stripe; not the whole write */ - if (rw & WRITE) { + if (bio_op(bio) == REQ_OP_WRITE) { ret = raid56_parity_write(root, bio, bbio, map_length); } else { ret = raid56_parity_recover(root, bio, bbio, map_length, @@ -6140,7 +6140,8 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, for (dev_nr = 0; dev_nr < total_devs; dev_nr++) { dev = bbio->stripes[dev_nr].dev; - if (!dev || !dev->bdev || (rw & WRITE && !dev->writeable)) { + if (!dev || !dev->bdev || + (bio_op(bio) == REQ_OP_WRITE && !dev->writeable)) { bbio_error(bbio, first_bio, logical); continue; } -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E192B7CB1 for ; Sun, 5 Jun 2016 14:33:04 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9CDE28F8040 for ; Sun, 5 Jun 2016 12:33:04 -0700 (PDT) X-ASG-Debug-ID: 1465155182-04cb6c2dbcb58dd0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id sCMmM0Vcp14bEQPr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:03 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 915E44629B; Sun, 5 Jun 2016 19:33:02 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9K003130; Sun, 5 Jun 2016 15:33:00 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 13/45] btrfs: update __btrfs_map_block for REQ_OP transition Date: Sun, 5 Jun 2016 14:31:53 -0500 X-ASG-Orig-Subj: [PATCH 13/45] btrfs: update __btrfs_map_block for REQ_OP transition Message-Id: <1465155145-10812-14-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sun, 05 Jun 2016 19:33:02 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155183 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9957 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie We no longer pass in a bitmap of rq_flag_bits bits to __btrfs_map_block. It will always be a REQ_OP, or the btrfs specific REQ_GET_READ_MIRRORS, so this drops the bit tests. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/btrfs/extent-tree.c | 2 +- fs/btrfs/inode.c | 2 +- fs/btrfs/volumes.c | 55 +++++++++++++++++++++++++++----------------------- fs/btrfs/volumes.h | 4 ++-- 4 files changed, 34 insertions(+), 29 deletions(-) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index a400951..70af591 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2043,7 +2043,7 @@ int btrfs_discard_extent(struct btrfs_root *root, u64 bytenr, /* Tell the block device(s) that the sectors can be discarded */ - ret = btrfs_map_block(root->fs_info, REQ_DISCARD, + ret = btrfs_map_block(root->fs_info, REQ_OP_DISCARD, bytenr, &num_bytes, &bbio, 0); /* Error condition is -ENOMEM */ if (!ret) { diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index b07e1d9..1575944 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1838,7 +1838,7 @@ int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset, length = bio->bi_iter.bi_size; map_length = length; - ret = btrfs_map_block(root->fs_info, rw, logical, + ret = btrfs_map_block(root->fs_info, bio_op(bio), logical, &map_length, NULL, 0); /* Will always return 0 with map_multi == NULL */ BUG_ON(ret < 0); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 4dc2249..345b183 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -5248,7 +5248,7 @@ void btrfs_put_bbio(struct btrfs_bio *bbio) kfree(bbio); } -static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, +static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int op, u64 logical, u64 *length, struct btrfs_bio **bbio_ret, int mirror_num, int need_raid_map) @@ -5334,7 +5334,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, raid56_full_stripe_start *= full_stripe_len; } - if (rw & REQ_DISCARD) { + if (op == REQ_OP_DISCARD) { /* we don't discard raid56 yet */ if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) { ret = -EOPNOTSUPP; @@ -5347,7 +5347,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, For other RAID types and for RAID[56] reads, just allow a single stripe (on a single disk). */ if ((map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) && - (rw & REQ_WRITE)) { + (op == REQ_OP_WRITE)) { max_len = stripe_len * nr_data_stripes(map) - (offset - raid56_full_stripe_start); } else { @@ -5372,8 +5372,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, btrfs_dev_replace_set_lock_blocking(dev_replace); if (dev_replace_is_ongoing && mirror_num == map->num_stripes + 1 && - !(rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS)) && - dev_replace->tgtdev != NULL) { + op != REQ_OP_WRITE && op != REQ_OP_DISCARD && + op != REQ_GET_READ_MIRRORS && dev_replace->tgtdev != NULL) { /* * in dev-replace case, for repair case (that's the only * case where the mirror is selected explicitly when @@ -5460,15 +5460,17 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, (offset + *length); if (map->type & BTRFS_BLOCK_GROUP_RAID0) { - if (rw & REQ_DISCARD) + if (op == REQ_OP_DISCARD) num_stripes = min_t(u64, map->num_stripes, stripe_nr_end - stripe_nr_orig); stripe_nr = div_u64_rem(stripe_nr, map->num_stripes, &stripe_index); - if (!(rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS))) + if (op != REQ_OP_WRITE && op != REQ_OP_DISCARD && + op != REQ_GET_READ_MIRRORS) mirror_num = 1; } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) { - if (rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS)) + if (op == REQ_OP_WRITE || op == REQ_OP_DISCARD || + op == REQ_GET_READ_MIRRORS) num_stripes = map->num_stripes; else if (mirror_num) stripe_index = mirror_num - 1; @@ -5481,7 +5483,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, } } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { - if (rw & (REQ_WRITE | REQ_DISCARD | REQ_GET_READ_MIRRORS)) { + if (op == REQ_OP_WRITE || REQ_OP_DISCARD || + op == REQ_GET_READ_MIRRORS) { num_stripes = map->num_stripes; } else if (mirror_num) { stripe_index = mirror_num - 1; @@ -5495,9 +5498,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index); stripe_index *= map->sub_stripes; - if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) + if (op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS) num_stripes = map->sub_stripes; - else if (rw & REQ_DISCARD) + else if (op == REQ_OP_DISCARD) num_stripes = min_t(u64, map->sub_stripes * (stripe_nr_end - stripe_nr_orig), map->num_stripes); @@ -5515,7 +5518,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, } else if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) { if (need_raid_map && - ((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) || + (op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS || mirror_num > 1)) { /* push stripe_nr back to the start of the full stripe */ stripe_nr = div_u64(raid56_full_stripe_start, @@ -5543,8 +5546,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, /* We distribute the parity blocks across stripes */ div_u64_rem(stripe_nr + stripe_index, map->num_stripes, &stripe_index); - if (!(rw & (REQ_WRITE | REQ_DISCARD | - REQ_GET_READ_MIRRORS)) && mirror_num <= 1) + if ((op != REQ_OP_WRITE && op != REQ_OP_DISCARD && + op != REQ_GET_READ_MIRRORS) && mirror_num <= 1) mirror_num = 1; } } else { @@ -5567,9 +5570,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, num_alloc_stripes = num_stripes; if (dev_replace_is_ongoing) { - if (rw & (REQ_WRITE | REQ_DISCARD)) + if (op == REQ_OP_WRITE || op == REQ_OP_DISCARD) num_alloc_stripes <<= 1; - if (rw & REQ_GET_READ_MIRRORS) + if (op == REQ_GET_READ_MIRRORS) num_alloc_stripes++; tgtdev_indexes = num_stripes; } @@ -5584,7 +5587,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, /* build raid_map */ if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK && - need_raid_map && ((rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) || + need_raid_map && + ((op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS) || mirror_num > 1)) { u64 tmp; unsigned rot; @@ -5609,7 +5613,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, RAID6_Q_STRIPE; } - if (rw & REQ_DISCARD) { + if (op == REQ_OP_DISCARD) { u32 factor = 0; u32 sub_stripes = 0; u64 stripes_per_dev = 0; @@ -5689,14 +5693,15 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, } } - if (rw & (REQ_WRITE | REQ_GET_READ_MIRRORS)) + if (op == REQ_OP_WRITE || op == REQ_GET_READ_MIRRORS) max_errors = btrfs_chunk_max_errors(map); if (bbio->raid_map) sort_parity_stripes(bbio, num_stripes); tgtdev_indexes = 0; - if (dev_replace_is_ongoing && (rw & (REQ_WRITE | REQ_DISCARD)) && + if (dev_replace_is_ongoing && + (op == REQ_OP_WRITE || op == REQ_OP_DISCARD) && dev_replace->tgtdev != NULL) { int index_where_to_add; u64 srcdev_devid = dev_replace->srcdev->devid; @@ -5731,7 +5736,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, } } num_stripes = index_where_to_add; - } else if (dev_replace_is_ongoing && (rw & REQ_GET_READ_MIRRORS) && + } else if (dev_replace_is_ongoing && (op == REQ_GET_READ_MIRRORS) && dev_replace->tgtdev != NULL) { u64 srcdev_devid = dev_replace->srcdev->devid; int index_srcdev = 0; @@ -5806,21 +5811,21 @@ out: return ret; } -int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, +int btrfs_map_block(struct btrfs_fs_info *fs_info, int op, u64 logical, u64 *length, struct btrfs_bio **bbio_ret, int mirror_num) { - return __btrfs_map_block(fs_info, rw, logical, length, bbio_ret, + return __btrfs_map_block(fs_info, op, logical, length, bbio_ret, mirror_num, 0); } /* For Scrub/replace */ -int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw, +int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int op, u64 logical, u64 *length, struct btrfs_bio **bbio_ret, int mirror_num, int need_raid_map) { - return __btrfs_map_block(fs_info, rw, logical, length, bbio_ret, + return __btrfs_map_block(fs_info, op, logical, length, bbio_ret, mirror_num, need_raid_map); } diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 0ac90f8..3b78700 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -375,10 +375,10 @@ int btrfs_account_dev_extents_size(struct btrfs_device *device, u64 start, u64 end, u64 *length); void btrfs_get_bbio(struct btrfs_bio *bbio); void btrfs_put_bbio(struct btrfs_bio *bbio); -int btrfs_map_block(struct btrfs_fs_info *fs_info, int rw, +int btrfs_map_block(struct btrfs_fs_info *fs_info, int op, u64 logical, u64 *length, struct btrfs_bio **bbio_ret, int mirror_num); -int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int rw, +int btrfs_map_sblock(struct btrfs_fs_info *fs_info, int op, u64 logical, u64 *length, struct btrfs_bio **bbio_ret, int mirror_num, int need_raid_map); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 66F7D7CB1 for ; Sun, 5 Jun 2016 14:33:08 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id D516AAC002 for ; Sun, 5 Jun 2016 12:33:07 -0700 (PDT) X-ASG-Debug-ID: 1465155185-04cbb0356ab8abd0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id aHjwCkkGqHKWIMm7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:05 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D26CA2197; Sun, 5 Jun 2016 19:33:04 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9L003130; Sun, 5 Jun 2016 15:33:02 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 14/45] btrfs: use bio fields for op and flags Date: Sun, 5 Jun 2016 14:31:54 -0500 X-ASG-Orig-Subj: [PATCH 14/45] btrfs: use bio fields for op and flags Message-Id: <1465155145-10812-15-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:33:04 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155185 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19943 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie The bio REQ_OP and bi_rw rq_flag_bits are now always setup, so there is no need to pass around the rq_flag_bits bits too. btrfs users should should access the bio insead. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- v2: 1. Fix merge_bio issue where instead of removing rw/op argument I passed it in again to the merge_bio related functions. fs/btrfs/compression.c | 13 ++++++------- fs/btrfs/ctree.h | 2 +- fs/btrfs/disk-io.c | 30 ++++++++++++------------------ fs/btrfs/disk-io.h | 2 +- fs/btrfs/extent_io.c | 12 +++++------- fs/btrfs/extent_io.h | 8 ++++---- fs/btrfs/inode.c | 41 +++++++++++++++++++---------------------- fs/btrfs/volumes.c | 11 +++++------ fs/btrfs/volumes.h | 2 +- 9 files changed, 54 insertions(+), 67 deletions(-) diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 029bd79..cefedab 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c @@ -374,7 +374,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, page = compressed_pages[pg_index]; page->mapping = inode->i_mapping; if (bio->bi_iter.bi_size) - ret = io_tree->ops->merge_bio_hook(WRITE, page, 0, + ret = io_tree->ops->merge_bio_hook(page, 0, PAGE_SIZE, bio, 0); else @@ -402,7 +402,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, BUG_ON(ret); /* -ENOMEM */ } - ret = btrfs_map_bio(root, WRITE, bio, 0, 1); + ret = btrfs_map_bio(root, bio, 0, 1); BUG_ON(ret); /* -ENOMEM */ bio_put(bio); @@ -433,7 +433,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, BUG_ON(ret); /* -ENOMEM */ } - ret = btrfs_map_bio(root, WRITE, bio, 0, 1); + ret = btrfs_map_bio(root, bio, 0, 1); BUG_ON(ret); /* -ENOMEM */ bio_put(bio); @@ -659,7 +659,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, page->index = em_start >> PAGE_SHIFT; if (comp_bio->bi_iter.bi_size) - ret = tree->ops->merge_bio_hook(READ, page, 0, + ret = tree->ops->merge_bio_hook(page, 0, PAGE_SIZE, comp_bio, 0); else @@ -690,8 +690,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, sums += DIV_ROUND_UP(comp_bio->bi_iter.bi_size, root->sectorsize); - ret = btrfs_map_bio(root, READ, comp_bio, - mirror_num, 0); + ret = btrfs_map_bio(root, comp_bio, mirror_num, 0); if (ret) { bio->bi_error = ret; bio_endio(comp_bio); @@ -721,7 +720,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, BUG_ON(ret); /* -ENOMEM */ } - ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0); + ret = btrfs_map_bio(root, comp_bio, mirror_num, 0); if (ret) { bio->bi_error = ret; bio_endio(comp_bio); diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 101c3cf..4088d7f 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h @@ -3091,7 +3091,7 @@ int btrfs_create_subvol_root(struct btrfs_trans_handle *trans, struct btrfs_root *new_root, struct btrfs_root *parent_root, u64 new_dirid); -int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset, +int btrfs_merge_bio_hook(struct page *page, unsigned long offset, size_t size, struct bio *bio, unsigned long bio_flags); int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 93278c2..e80ef6e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -124,7 +124,6 @@ struct async_submit_bio { struct list_head list; extent_submit_bio_hook_t *submit_bio_start; extent_submit_bio_hook_t *submit_bio_done; - int rw; int mirror_num; unsigned long bio_flags; /* @@ -797,7 +796,7 @@ static void run_one_async_start(struct btrfs_work *work) int ret; async = container_of(work, struct async_submit_bio, work); - ret = async->submit_bio_start(async->inode, async->rw, async->bio, + ret = async->submit_bio_start(async->inode, async->bio, async->mirror_num, async->bio_flags, async->bio_offset); if (ret) @@ -830,9 +829,8 @@ static void run_one_async_done(struct btrfs_work *work) return; } - async->submit_bio_done(async->inode, async->rw, async->bio, - async->mirror_num, async->bio_flags, - async->bio_offset); + async->submit_bio_done(async->inode, async->bio, async->mirror_num, + async->bio_flags, async->bio_offset); } static void run_one_async_free(struct btrfs_work *work) @@ -844,7 +842,7 @@ static void run_one_async_free(struct btrfs_work *work) } int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, - int rw, struct bio *bio, int mirror_num, + struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset, extent_submit_bio_hook_t *submit_bio_start, @@ -857,7 +855,6 @@ int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, return -ENOMEM; async->inode = inode; - async->rw = rw; async->bio = bio; async->mirror_num = mirror_num; async->submit_bio_start = submit_bio_start; @@ -903,9 +900,8 @@ static int btree_csum_one_bio(struct bio *bio) return ret; } -static int __btree_submit_bio_start(struct inode *inode, int rw, - struct bio *bio, int mirror_num, - unsigned long bio_flags, +static int __btree_submit_bio_start(struct inode *inode, struct bio *bio, + int mirror_num, unsigned long bio_flags, u64 bio_offset) { /* @@ -915,7 +911,7 @@ static int __btree_submit_bio_start(struct inode *inode, int rw, return btree_csum_one_bio(bio); } -static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio, +static int __btree_submit_bio_done(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset) { @@ -925,7 +921,7 @@ static int __btree_submit_bio_done(struct inode *inode, int rw, struct bio *bio, * when we're called for a write, we're already in the async * submission context. Just jump into btrfs_map_bio */ - ret = btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, mirror_num, 1); + ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 1); if (ret) { bio->bi_error = ret; bio_endio(bio); @@ -944,7 +940,7 @@ static int check_async_write(struct inode *inode, unsigned long bio_flags) return 1; } -static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, +static int btree_submit_bio_hook(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset) { @@ -960,21 +956,19 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, bio, BTRFS_WQ_ENDIO_METADATA); if (ret) goto out_w_error; - ret = btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, - mirror_num, 0); + ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 0); } else if (!async) { ret = btree_csum_one_bio(bio); if (ret) goto out_w_error; - ret = btrfs_map_bio(BTRFS_I(inode)->root, rw, bio, - mirror_num, 0); + ret = btrfs_map_bio(BTRFS_I(inode)->root, bio, mirror_num, 0); } else { /* * kthread helpers are used to submit writes so that * checksumming can happen in parallel across all CPUs */ ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, - inode, rw, bio, mirror_num, 0, + inode, bio, mirror_num, 0, bio_offset, __btree_submit_bio_start, __btree_submit_bio_done); diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h index 8e79d00..73c21a2 100644 --- a/fs/btrfs/disk-io.h +++ b/fs/btrfs/disk-io.h @@ -122,7 +122,7 @@ void btrfs_csum_final(u32 crc, char *result); int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, enum btrfs_wq_endio_type metadata); int btrfs_wq_submit_bio(struct btrfs_fs_info *fs_info, struct inode *inode, - int rw, struct bio *bio, int mirror_num, + struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset, extent_submit_bio_hook_t *submit_bio_start, extent_submit_bio_hook_t *submit_bio_done); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 48f0302..cbaf305 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -2408,8 +2408,7 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset, pr_debug("Repair Read Error: submitting new read[%#x] to this_mirror=%d, in_validation=%d\n", read_mode, failrec->this_mirror, failrec->in_validation); - ret = tree->ops->submit_bio_hook(inode, read_mode, bio, - failrec->this_mirror, + ret = tree->ops->submit_bio_hook(inode, bio, failrec->this_mirror, failrec->bio_flags, 0); if (ret) { free_io_failure(inode, failrec); @@ -2730,9 +2729,8 @@ static int __must_check submit_one_bio(struct bio *bio, int mirror_num, bio_get(bio); if (tree->ops && tree->ops->submit_bio_hook) - ret = tree->ops->submit_bio_hook(page->mapping->host, - bio->bi_rw, bio, mirror_num, - bio_flags, start); + ret = tree->ops->submit_bio_hook(page->mapping->host, bio, + mirror_num, bio_flags, start); else btrfsic_submit_bio(bio); @@ -2746,8 +2744,8 @@ static int merge_bio(struct extent_io_tree *tree, struct page *page, { int ret = 0; if (tree->ops && tree->ops->merge_bio_hook) - ret = tree->ops->merge_bio_hook(bio_op(bio), page, offset, size, - bio, bio_flags); + ret = tree->ops->merge_bio_hook(page, offset, size, bio, + bio_flags); BUG_ON(ret < 0); return ret; diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 1baf19c..fb9dcc9 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -63,16 +63,16 @@ struct btrfs_root; struct btrfs_io_bio; struct io_failure_record; -typedef int (extent_submit_bio_hook_t)(struct inode *inode, int rw, - struct bio *bio, int mirror_num, - unsigned long bio_flags, u64 bio_offset); +typedef int (extent_submit_bio_hook_t)(struct inode *inode, struct bio *bio, + int mirror_num, unsigned long bio_flags, + u64 bio_offset); struct extent_io_ops { int (*fill_delalloc)(struct inode *inode, struct page *locked_page, u64 start, u64 end, int *page_started, unsigned long *nr_written); int (*writepage_start_hook)(struct page *page, u64 start, u64 end); extent_submit_bio_hook_t *submit_bio_hook; - int (*merge_bio_hook)(int rw, struct page *page, unsigned long offset, + int (*merge_bio_hook)(struct page *page, unsigned long offset, size_t size, struct bio *bio, unsigned long bio_flags); int (*readpage_io_failed_hook)(struct page *page, int failed_mirror); diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 1575944..128b02b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -1823,7 +1823,7 @@ static void btrfs_clear_bit_hook(struct inode *inode, * extent_io.c merge_bio_hook, this must check the chunk tree to make sure * we don't create bios that span stripes or chunks */ -int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset, +int btrfs_merge_bio_hook(struct page *page, unsigned long offset, size_t size, struct bio *bio, unsigned long bio_flags) { @@ -1855,9 +1855,8 @@ int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset, * At IO completion time the cums attached on the ordered extent record * are inserted into the btree */ -static int __btrfs_submit_bio_start(struct inode *inode, int rw, - struct bio *bio, int mirror_num, - unsigned long bio_flags, +static int __btrfs_submit_bio_start(struct inode *inode, struct bio *bio, + int mirror_num, unsigned long bio_flags, u64 bio_offset) { struct btrfs_root *root = BTRFS_I(inode)->root; @@ -1876,14 +1875,14 @@ static int __btrfs_submit_bio_start(struct inode *inode, int rw, * At IO completion time the cums attached on the ordered extent record * are inserted into the btree */ -static int __btrfs_submit_bio_done(struct inode *inode, int rw, struct bio *bio, +static int __btrfs_submit_bio_done(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset) { struct btrfs_root *root = BTRFS_I(inode)->root; int ret; - ret = btrfs_map_bio(root, rw, bio, mirror_num, 1); + ret = btrfs_map_bio(root, bio, mirror_num, 1); if (ret) { bio->bi_error = ret; bio_endio(bio); @@ -1895,7 +1894,7 @@ static int __btrfs_submit_bio_done(struct inode *inode, int rw, struct bio *bio, * extent_io.c submission hook. This does the right thing for csum calculation * on write, or reading the csums from the tree before a read */ -static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, +static int btrfs_submit_bio_hook(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 bio_offset) { @@ -1932,7 +1931,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, goto mapit; /* we're doing a write, do the async checksumming */ ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, - inode, rw, bio, mirror_num, + inode, bio, mirror_num, bio_flags, bio_offset, __btrfs_submit_bio_start, __btrfs_submit_bio_done); @@ -1944,7 +1943,7 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, } mapit: - ret = btrfs_map_bio(root, rw, bio, mirror_num, 0); + ret = btrfs_map_bio(root, bio, mirror_num, 0); out: if (ret < 0) { @@ -7767,7 +7766,7 @@ err: } static inline int submit_dio_repair_bio(struct inode *inode, struct bio *bio, - int rw, int mirror_num) + int mirror_num) { struct btrfs_root *root = BTRFS_I(inode)->root; int ret; @@ -7781,7 +7780,7 @@ static inline int submit_dio_repair_bio(struct inode *inode, struct bio *bio, if (ret) goto err; - ret = btrfs_map_bio(root, rw, bio, mirror_num, 0); + ret = btrfs_map_bio(root, bio, mirror_num, 0); err: bio_put(bio); return ret; @@ -7866,8 +7865,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, "Repair DIO Read Error: submitting new dio read[%#x] to this_mirror=%d, in_validation=%d\n", read_mode, failrec->this_mirror, failrec->in_validation); - ret = submit_dio_repair_bio(inode, bio, read_mode, - failrec->this_mirror); + ret = submit_dio_repair_bio(inode, bio, failrec->this_mirror); if (ret) { free_io_failure(inode, failrec); bio_put(bio); @@ -8157,7 +8155,7 @@ static void btrfs_endio_direct_write(struct bio *bio) bio_put(bio); } -static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw, +static int __btrfs_submit_bio_start_direct_io(struct inode *inode, struct bio *bio, int mirror_num, unsigned long bio_flags, u64 offset) { @@ -8250,7 +8248,7 @@ static inline int btrfs_lookup_and_bind_dio_csum(struct btrfs_root *root, } static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, - int rw, u64 file_offset, int skip_sum, + u64 file_offset, int skip_sum, int async_submit) { struct btrfs_dio_private *dip = bio->bi_private; @@ -8275,8 +8273,7 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, if (write && async_submit) { ret = btrfs_wq_submit_bio(root->fs_info, - inode, rw, bio, 0, 0, - file_offset, + inode, bio, 0, 0, file_offset, __btrfs_submit_bio_start_direct_io, __btrfs_submit_bio_done); goto err; @@ -8295,13 +8292,13 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, goto err; } map: - ret = btrfs_map_bio(root, rw, bio, 0, async_submit); + ret = btrfs_map_bio(root, bio, 0, async_submit); err: bio_put(bio); return ret; } -static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, +static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip, int skip_sum) { struct inode *inode = dip->inode; @@ -8361,7 +8358,7 @@ next_block: * before we're done setting it up */ atomic_inc(&dip->pending_bios); - ret = __btrfs_submit_dio_bio(bio, inode, rw, + ret = __btrfs_submit_dio_bio(bio, inode, file_offset, skip_sum, async_submit); if (ret) { @@ -8405,7 +8402,7 @@ next_block: } submit: - ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, + ret = __btrfs_submit_dio_bio(bio, inode, file_offset, skip_sum, async_submit); if (!ret) return 0; @@ -8483,7 +8480,7 @@ static void btrfs_submit_direct(struct bio *dio_bio, struct inode *inode, dio_data->unsubmitted_oe_range_end; } - ret = btrfs_submit_direct_hook(dio_bio->bi_rw, dip, skip_sum); + ret = btrfs_submit_direct_hook(dip, skip_sum); if (!ret) return; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 345b183..125d13b 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6045,7 +6045,7 @@ static noinline void btrfs_schedule_bio(struct btrfs_root *root, static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio, struct bio *bio, u64 physical, int dev_nr, - int rw, int async) + int async) { struct btrfs_device *dev = bbio->stripes[dev_nr].dev; @@ -6053,15 +6053,14 @@ static void submit_stripe_bio(struct btrfs_root *root, struct btrfs_bio *bbio, btrfs_io_bio(bio)->stripe_index = dev_nr; bio->bi_end_io = btrfs_end_bio; bio->bi_iter.bi_sector = physical >> 9; - bio->bi_rw |= rw; #ifdef DEBUG { struct rcu_string *name; rcu_read_lock(); name = rcu_dereference(dev->name); - pr_debug("btrfs_map_bio: rw %d, sector=%llu, dev=%lu " - "(%s id %llu), size=%u\n", rw, + pr_debug("btrfs_map_bio: rw %d 0x%x, sector=%llu, dev=%lu " + "(%s id %llu), size=%u\n", bio_op(bio), bio->bi_rw, (u64)bio->bi_iter.bi_sector, (u_long)dev->bdev->bd_dev, name->str, dev->devid, bio->bi_iter.bi_size); rcu_read_unlock(); @@ -6091,7 +6090,7 @@ static void bbio_error(struct btrfs_bio *bbio, struct bio *bio, u64 logical) } } -int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, +int btrfs_map_bio(struct btrfs_root *root, struct bio *bio, int mirror_num, int async_submit) { struct btrfs_device *dev; @@ -6158,7 +6157,7 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, bio = first_bio; submit_stripe_bio(root, bbio, bio, - bbio->stripes[dev_nr].physical, dev_nr, rw, + bbio->stripes[dev_nr].physical, dev_nr, async_submit); } btrfs_bio_counter_dec(root->fs_info); diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 3b78700..6613e63 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -391,7 +391,7 @@ int btrfs_alloc_chunk(struct btrfs_trans_handle *trans, struct btrfs_root *extent_root, u64 type); void btrfs_mapping_init(struct btrfs_mapping_tree *tree); void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree); -int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, +int btrfs_map_bio(struct btrfs_root *root, struct bio *bio, int mirror_num, int async_submit); int btrfs_open_devices(struct btrfs_fs_devices *fs_devices, fmode_t flags, void *holder); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EDAA77CED for ; Sun, 5 Jun 2016 14:33:09 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 79126AC002 for ; Sun, 5 Jun 2016 12:33:09 -0700 (PDT) X-ASG-Debug-ID: 1465155187-04bdf05ad4b78480001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id MTxramBMKfIVL70e (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:07 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 208EF1555B; Sun, 5 Jun 2016 19:33:07 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9M003130; Sun, 5 Jun 2016 15:33:04 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 15/45] f2fs: use bio op accessors Date: Sun, 5 Jun 2016 14:31:55 -0500 X-ASG-Orig-Subj: [PATCH 15/45] f2fs: use bio op accessors Message-Id: <1465155145-10812-16-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sun, 05 Jun 2016 19:33:07 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155187 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 16155 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have f2fs set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/f2fs/checkpoint.c | 10 ++++++---- fs/f2fs/data.c | 47 ++++++++++++++++++++++++++------------------- fs/f2fs/f2fs.h | 5 +++-- fs/f2fs/gc.c | 9 ++++++--- fs/f2fs/inline.c | 3 ++- fs/f2fs/node.c | 8 +++++--- fs/f2fs/segment.c | 12 +++++++----- fs/f2fs/trace.c | 7 ++++--- include/trace/events/f2fs.h | 34 +++++++++++++++++++------------- 9 files changed, 81 insertions(+), 54 deletions(-) diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 3891600..b6d600e 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -63,14 +63,15 @@ static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index, struct f2fs_io_info fio = { .sbi = sbi, .type = META, - .rw = READ_SYNC | REQ_META | REQ_PRIO, + .op = REQ_OP_READ, + .op_flags = READ_SYNC | REQ_META | REQ_PRIO, .old_blkaddr = index, .new_blkaddr = index, .encrypted_page = NULL, }; if (unlikely(!is_meta)) - fio.rw &= ~REQ_META; + fio.op_flags &= ~REQ_META; repeat: page = f2fs_grab_cache_page(mapping, index, false); if (!page) { @@ -157,13 +158,14 @@ int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, struct f2fs_io_info fio = { .sbi = sbi, .type = META, - .rw = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : READA, + .op = REQ_OP_READ, + .op_flags = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : READA, .encrypted_page = NULL, }; struct blk_plug plug; if (unlikely(type == META_POR)) - fio.rw &= ~REQ_META; + fio.op_flags &= ~REQ_META; blk_start_plug(&plug); for (; nrpages-- > 0; blkno++) { diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index c595c8f..8769e83 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -97,12 +97,10 @@ static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr, return bio; } -static inline void __submit_bio(struct f2fs_sb_info *sbi, int rw, - struct bio *bio) +static inline void __submit_bio(struct f2fs_sb_info *sbi, struct bio *bio) { - if (!is_read_io(rw)) + if (!is_read_io(bio_op(bio))) atomic_inc(&sbi->nr_wb_bios); - bio->bi_rw = rw; submit_bio(bio); } @@ -113,12 +111,14 @@ static void __submit_merged_bio(struct f2fs_bio_info *io) if (!io->bio) return; - if (is_read_io(fio->rw)) + if (is_read_io(fio->op)) trace_f2fs_submit_read_bio(io->sbi->sb, fio, io->bio); else trace_f2fs_submit_write_bio(io->sbi->sb, fio, io->bio); - __submit_bio(io->sbi, fio->rw, io->bio); + bio_set_op_attrs(io->bio, fio->op, fio->op_flags); + + __submit_bio(io->sbi, io->bio); io->bio = NULL; } @@ -184,10 +184,12 @@ static void __f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, /* change META to META_FLUSH in the checkpoint procedure */ if (type >= META_FLUSH) { io->fio.type = META_FLUSH; + io->fio.op = REQ_OP_WRITE; if (test_opt(sbi, NOBARRIER)) - io->fio.rw = WRITE_FLUSH | REQ_META | REQ_PRIO; + io->fio.op_flags = WRITE_FLUSH | REQ_META | REQ_PRIO; else - io->fio.rw = WRITE_FLUSH_FUA | REQ_META | REQ_PRIO; + io->fio.op_flags = WRITE_FLUSH_FUA | REQ_META | + REQ_PRIO; } __submit_merged_bio(io); out: @@ -229,14 +231,16 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) f2fs_trace_ios(fio, 0); /* Allocate a new bio */ - bio = __bio_alloc(fio->sbi, fio->new_blkaddr, 1, is_read_io(fio->rw)); + bio = __bio_alloc(fio->sbi, fio->new_blkaddr, 1, is_read_io(fio->op)); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); return -EFAULT; } + bio->bi_rw = fio->op_flags; + bio_set_op_attrs(bio, fio->op, fio->op_flags); - __submit_bio(fio->sbi, fio->rw, bio); + __submit_bio(fio->sbi, bio); return 0; } @@ -245,7 +249,7 @@ void f2fs_submit_page_mbio(struct f2fs_io_info *fio) struct f2fs_sb_info *sbi = fio->sbi; enum page_type btype = PAGE_TYPE_OF_BIO(fio->type); struct f2fs_bio_info *io; - bool is_read = is_read_io(fio->rw); + bool is_read = is_read_io(fio->op); struct page *bio_page; io = is_read ? &sbi->read_io : &sbi->write_io[btype]; @@ -257,7 +261,7 @@ void f2fs_submit_page_mbio(struct f2fs_io_info *fio) down_write(&io->io_rwsem); if (io->bio && (io->last_block_in_bio != fio->new_blkaddr - 1 || - io->fio.rw != fio->rw)) + (io->fio.op != fio->op || io->fio.op_flags != fio->op_flags))) __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { @@ -391,7 +395,7 @@ int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index) } struct page *get_read_data_page(struct inode *inode, pgoff_t index, - int rw, bool for_write) + int op_flags, bool for_write) { struct address_space *mapping = inode->i_mapping; struct dnode_of_data dn; @@ -401,7 +405,8 @@ struct page *get_read_data_page(struct inode *inode, pgoff_t index, struct f2fs_io_info fio = { .sbi = F2FS_I_SB(inode), .type = DATA, - .rw = rw, + .op = REQ_OP_READ, + .op_flags = op_flags, .encrypted_page = NULL, }; @@ -1052,7 +1057,7 @@ got_it: */ if (bio && (last_block_in_bio != block_nr - 1)) { submit_and_realloc: - __submit_bio(F2FS_I_SB(inode), READ, bio); + __submit_bio(F2FS_I_SB(inode), bio); bio = NULL; } if (bio == NULL) { @@ -1081,7 +1086,7 @@ submit_and_realloc: bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(block_nr); bio->bi_end_io = f2fs_read_end_io; bio->bi_private = ctx; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); } if (bio_add_page(bio, page, blocksize, 0) < blocksize) @@ -1096,7 +1101,7 @@ set_error_page: goto next_page; confused: if (bio) { - __submit_bio(F2FS_I_SB(inode), READ, bio); + __submit_bio(F2FS_I_SB(inode), bio); bio = NULL; } unlock_page(page); @@ -1106,7 +1111,7 @@ next_page: } BUG_ON(pages && !list_empty(pages)); if (bio) - __submit_bio(F2FS_I_SB(inode), READ, bio); + __submit_bio(F2FS_I_SB(inode), bio); return 0; } @@ -1223,7 +1228,8 @@ static int f2fs_write_data_page(struct page *page, struct f2fs_io_info fio = { .sbi = sbi, .type = DATA, - .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE, + .op = REQ_OP_WRITE, + .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0, .page = page, .encrypted_page = NULL, }; @@ -1664,7 +1670,8 @@ repeat: struct f2fs_io_info fio = { .sbi = sbi, .type = DATA, - .rw = READ_SYNC, + .op = REQ_OP_READ, + .op_flags = READ_SYNC, .old_blkaddr = blkaddr, .new_blkaddr = blkaddr, .page = page, diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 916e7c2..23ae6a8 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -686,14 +686,15 @@ enum page_type { struct f2fs_io_info { struct f2fs_sb_info *sbi; /* f2fs_sb_info pointer */ enum page_type type; /* contains DATA/NODE/META/META_FLUSH */ - int rw; /* contains R/RS/W/WS with REQ_META/REQ_PRIO */ + int op; /* contains REQ_OP_ */ + int op_flags; /* rq_flag_bits */ block_t new_blkaddr; /* new block address to be written */ block_t old_blkaddr; /* old block address before Cow */ struct page *page; /* page to be written */ struct page *encrypted_page; /* encrypted page */ }; -#define is_read_io(rw) (((rw) & 1) == READ) +#define is_read_io(rw) (rw == READ) struct f2fs_bio_info { struct f2fs_sb_info *sbi; /* f2fs superblock */ struct bio *bio; /* bios to merge */ diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 38d56f6..3649d86 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -538,7 +538,8 @@ static void move_encrypted_block(struct inode *inode, block_t bidx) struct f2fs_io_info fio = { .sbi = F2FS_I_SB(inode), .type = DATA, - .rw = READ_SYNC, + .op = REQ_OP_READ, + .op_flags = READ_SYNC, .encrypted_page = NULL, }; struct dnode_of_data dn; @@ -612,7 +613,8 @@ static void move_encrypted_block(struct inode *inode, block_t bidx) /* allocate block address */ f2fs_wait_on_page_writeback(dn.node_page, NODE, true); - fio.rw = WRITE_SYNC; + fio.op = REQ_OP_WRITE; + fio.op_flags = WRITE_SYNC; fio.new_blkaddr = newaddr; f2fs_submit_page_mbio(&fio); @@ -649,7 +651,8 @@ static void move_data_page(struct inode *inode, block_t bidx, int gc_type) struct f2fs_io_info fio = { .sbi = F2FS_I_SB(inode), .type = DATA, - .rw = WRITE_SYNC, + .op = REQ_OP_WRITE, + .op_flags = WRITE_SYNC, .page = page, .encrypted_page = NULL, }; diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index a4bb155..c15e53c 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -108,7 +108,8 @@ int f2fs_convert_inline_page(struct dnode_of_data *dn, struct page *page) struct f2fs_io_info fio = { .sbi = F2FS_I_SB(dn->inode), .type = DATA, - .rw = WRITE_SYNC | REQ_PRIO, + .op = REQ_OP_WRITE, + .op_flags = WRITE_SYNC | REQ_PRIO, .page = page, .encrypted_page = NULL, }; diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 1f21aae..e534039 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1070,14 +1070,15 @@ fail: * 0: f2fs_put_page(page, 0) * LOCKED_PAGE or error: f2fs_put_page(page, 1) */ -static int read_node_page(struct page *page, int rw) +static int read_node_page(struct page *page, int op_flags) { struct f2fs_sb_info *sbi = F2FS_P_SB(page); struct node_info ni; struct f2fs_io_info fio = { .sbi = sbi, .type = NODE, - .rw = rw, + .op = REQ_OP_READ, + .op_flags = op_flags, .page = page, .encrypted_page = NULL, }; @@ -1568,7 +1569,8 @@ static int f2fs_write_node_page(struct page *page, struct f2fs_io_info fio = { .sbi = sbi, .type = NODE, - .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE, + .op = REQ_OP_WRITE, + .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0, .page = page, .encrypted_page = NULL, }; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 3fe2fab..4c2d1fa 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -257,7 +257,8 @@ static int __commit_inmem_pages(struct inode *inode, struct f2fs_io_info fio = { .sbi = sbi, .type = DATA, - .rw = WRITE_SYNC | REQ_PRIO, + .op = REQ_OP_WRITE, + .op_flags = WRITE_SYNC | REQ_PRIO, .encrypted_page = NULL, }; bool submit_bio = false; @@ -406,7 +407,7 @@ repeat: fcc->dispatch_list = llist_reverse_order(fcc->dispatch_list); bio->bi_bdev = sbi->sb->s_bdev; - bio->bi_rw = WRITE_FLUSH; + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); ret = submit_bio_wait(bio); llist_for_each_entry_safe(cmd, next, @@ -439,7 +440,7 @@ int f2fs_issue_flush(struct f2fs_sb_info *sbi) int ret; bio->bi_bdev = sbi->sb->s_bdev; - bio->bi_rw = WRITE_FLUSH; + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH); ret = submit_bio_wait(bio); bio_put(bio); return ret; @@ -1403,7 +1404,8 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) struct f2fs_io_info fio = { .sbi = sbi, .type = META, - .rw = WRITE_SYNC | REQ_META | REQ_PRIO, + .op = REQ_OP_WRITE, + .op_flags = WRITE_SYNC | REQ_META | REQ_PRIO, .old_blkaddr = page->index, .new_blkaddr = page->index, .page = page, @@ -1411,7 +1413,7 @@ void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) }; if (unlikely(page->index >= MAIN_BLKADDR(sbi))) - fio.rw &= ~REQ_META; + fio.op_flags &= ~REQ_META; set_page_writeback(page); f2fs_submit_page_mbio(&fio); diff --git a/fs/f2fs/trace.c b/fs/f2fs/trace.c index 562ce08..73b4e1d 100644 --- a/fs/f2fs/trace.c +++ b/fs/f2fs/trace.c @@ -25,11 +25,11 @@ static inline void __print_last_io(void) if (!last_io.len) return; - trace_printk("%3x:%3x %4x %-16s %2x %5x %12x %4x\n", + trace_printk("%3x:%3x %4x %-16s %2x %5x %5x %12x %4x\n", last_io.major, last_io.minor, last_io.pid, "----------------", last_io.type, - last_io.fio.rw, + last_io.fio.op, last_io.fio.op_flags, last_io.fio.new_blkaddr, last_io.len); memset(&last_io, 0, sizeof(last_io)); @@ -101,7 +101,8 @@ void f2fs_trace_ios(struct f2fs_io_info *fio, int flush) if (last_io.major == major && last_io.minor == minor && last_io.pid == pid && last_io.type == __file_type(inode, pid) && - last_io.fio.rw == fio->rw && + last_io.fio.op == fio->op && + last_io.fio.op_flags == fio->op_flags && last_io.fio.new_blkaddr + last_io.len == fio->new_blkaddr) { last_io.len++; diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 3a09bb4..733b896 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -56,17 +56,21 @@ TRACE_DEFINE_ENUM(CP_DISCARD); { IPU, "IN-PLACE" }, \ { OPU, "OUT-OF-PLACE" }) -#define F2FS_BIO_MASK(t) (t & (READA | WRITE_FLUSH_FUA)) +#define F2FS_BIO_FLAG_MASK(t) (t & (READA | WRITE_FLUSH_FUA)) #define F2FS_BIO_EXTRA_MASK(t) (t & (REQ_META | REQ_PRIO)) -#define show_bio_type(type) show_bio_base(type), show_bio_extra(type) +#define show_bio_type(op, op_flags) show_bio_op(op), \ + show_bio_op_flags(op_flags), show_bio_extra(op_flags) -#define show_bio_base(type) \ - __print_symbolic(F2FS_BIO_MASK(type), \ +#define show_bio_op(op) \ + __print_symbolic(op, \ { READ, "READ" }, \ + { WRITE, "WRITE" }) + +#define show_bio_op_flags(flags) \ + __print_symbolic(F2FS_BIO_FLAG_MASK(flags), \ { READA, "READAHEAD" }, \ { READ_SYNC, "READ_SYNC" }, \ - { WRITE, "WRITE" }, \ { WRITE_SYNC, "WRITE_SYNC" }, \ { WRITE_FLUSH, "WRITE_FLUSH" }, \ { WRITE_FUA, "WRITE_FUA" }, \ @@ -734,7 +738,8 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio, __field(pgoff_t, index) __field(block_t, old_blkaddr) __field(block_t, new_blkaddr) - __field(int, rw) + __field(int, op) + __field(int, op_flags) __field(int, type) ), @@ -744,17 +749,18 @@ DECLARE_EVENT_CLASS(f2fs__submit_page_bio, __entry->index = page->index; __entry->old_blkaddr = fio->old_blkaddr; __entry->new_blkaddr = fio->new_blkaddr; - __entry->rw = fio->rw; + __entry->op = fio->op; + __entry->op_flags = fio->op_flags; __entry->type = fio->type; ), TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, " - "oldaddr = 0x%llx, newaddr = 0x%llx rw = %s%s, type = %s", + "oldaddr = 0x%llx, newaddr = 0x%llx rw = %s%si%s, type = %s", show_dev_ino(__entry), (unsigned long)__entry->index, (unsigned long long)__entry->old_blkaddr, (unsigned long long)__entry->new_blkaddr, - show_bio_type(__entry->rw), + show_bio_type(__entry->op, __entry->op_flags), show_block_type(__entry->type)) ); @@ -785,7 +791,8 @@ DECLARE_EVENT_CLASS(f2fs__submit_bio, TP_STRUCT__entry( __field(dev_t, dev) - __field(int, rw) + __field(int, op) + __field(int, op_flags) __field(int, type) __field(sector_t, sector) __field(unsigned int, size) @@ -793,15 +800,16 @@ DECLARE_EVENT_CLASS(f2fs__submit_bio, TP_fast_assign( __entry->dev = sb->s_dev; - __entry->rw = fio->rw; + __entry->op = fio->op; + __entry->op_flags = fio->op_flags; __entry->type = fio->type; __entry->sector = bio->bi_iter.bi_sector; __entry->size = bio->bi_iter.bi_size; ), - TP_printk("dev = (%d,%d), %s%s, %s, sector = %lld, size = %u", + TP_printk("dev = (%d,%d), %s%s%s, %s, sector = %lld, size = %u", show_dev(__entry), - show_bio_type(__entry->rw), + show_bio_type(__entry->op, __entry->op_flags), show_block_type(__entry->type), (unsigned long long)__entry->sector, __entry->size) -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:12 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 723D97CB6 for ; Sun, 5 Jun 2016 14:33:11 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 439038F8037 for ; Sun, 5 Jun 2016 12:33:11 -0700 (PDT) X-ASG-Debug-ID: 1465155189-04cb6c2dbbb58dd0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id C3gVefYVXr5rijtd (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:10 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6B0C180085; Sun, 5 Jun 2016 19:33:09 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9N003130; Sun, 5 Jun 2016 15:33:07 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 16/45] gfs2: use bio op accessors Date: Sun, 5 Jun 2016 14:31:56 -0500 X-ASG-Orig-Subj: [PATCH 16/45] gfs2: use bio op accessors Message-Id: <1465155145-10812-17-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sun, 05 Jun 2016 19:33:09 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155190 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5624 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have gfs2 set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/gfs2/log.c | 8 ++++---- fs/gfs2/lops.c | 11 ++++++----- fs/gfs2/lops.h | 2 +- fs/gfs2/meta_io.c | 7 ++++--- fs/gfs2/ops_fstype.c | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 0ff028c..e58ccef0 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -657,7 +657,7 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) struct gfs2_log_header *lh; unsigned int tail; u32 hash; - int rw = WRITE_FLUSH_FUA | REQ_META; + int op_flags = WRITE_FLUSH_FUA | REQ_META; struct page *page = mempool_alloc(gfs2_page_pool, GFP_NOIO); enum gfs2_freeze_state state = atomic_read(&sdp->sd_freeze_state); lh = page_address(page); @@ -682,12 +682,12 @@ static void log_write_header(struct gfs2_sbd *sdp, u32 flags) if (test_bit(SDF_NOBARRIERS, &sdp->sd_flags)) { gfs2_ordered_wait(sdp); log_flush_wait(sdp); - rw = WRITE_SYNC | REQ_META | REQ_PRIO; + op_flags = WRITE_SYNC | REQ_META | REQ_PRIO; } sdp->sd_log_idle = (tail == sdp->sd_log_flush_head); gfs2_log_write_page(sdp, page); - gfs2_log_flush_bio(sdp, rw); + gfs2_log_flush_bio(sdp, REQ_OP_WRITE, op_flags); log_flush_wait(sdp); if (sdp->sd_log_tail != tail) @@ -738,7 +738,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, gfs2_ordered_write(sdp); lops_before_commit(sdp, tr); - gfs2_log_flush_bio(sdp, WRITE); + gfs2_log_flush_bio(sdp, REQ_OP_WRITE, 0); if (sdp->sd_log_head != sdp->sd_log_flush_head) { log_flush_wait(sdp); diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index ce28242..58d1c98 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -230,17 +230,18 @@ static void gfs2_end_log_write(struct bio *bio) /** * gfs2_log_flush_bio - Submit any pending log bio * @sdp: The superblock - * @rw: The rw flags + * @op: REQ_OP + * @op_flags: rq_flag_bits * * Submit any pending part-built or full bio to the block device. If * there is no pending bio, then this is a no-op. */ -void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int rw) +void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int op, int op_flags) { if (sdp->sd_log_bio) { atomic_inc(&sdp->sd_log_in_flight); - sdp->sd_log_bio->bi_rw = rw; + bio_set_op_attrs(sdp->sd_log_bio, op, op_flags); submit_bio(sdp->sd_log_bio); sdp->sd_log_bio = NULL; } @@ -300,7 +301,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno) nblk >>= sdp->sd_fsb2bb_shift; if (blkno == nblk) return bio; - gfs2_log_flush_bio(sdp, WRITE); + gfs2_log_flush_bio(sdp, REQ_OP_WRITE, 0); } return gfs2_log_alloc_bio(sdp, blkno); @@ -329,7 +330,7 @@ static void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page, bio = gfs2_log_get_bio(sdp, blkno); ret = bio_add_page(bio, page, size, offset); if (ret == 0) { - gfs2_log_flush_bio(sdp, WRITE); + gfs2_log_flush_bio(sdp, REQ_OP_WRITE, 0); bio = gfs2_log_alloc_bio(sdp, blkno); ret = bio_add_page(bio, page, size, offset); WARN_ON(ret == 0); diff --git a/fs/gfs2/lops.h b/fs/gfs2/lops.h index a65a7ba..e529f53 100644 --- a/fs/gfs2/lops.h +++ b/fs/gfs2/lops.h @@ -27,7 +27,7 @@ extern const struct gfs2_log_operations gfs2_databuf_lops; extern const struct gfs2_log_operations *gfs2_log_ops[]; extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page); -extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int rw); +extern void gfs2_log_flush_bio(struct gfs2_sbd *sdp, int op, int op_flags); extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh); static inline unsigned int buf_limit(struct gfs2_sbd *sdp) diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index b718447..052c113 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -213,7 +213,8 @@ static void gfs2_meta_read_endio(struct bio *bio) * Submit several consecutive buffer head I/O requests as a single bio I/O * request. (See submit_bh_wbc.) */ -static void gfs2_submit_bhs(int rw, struct buffer_head *bhs[], int num) +static void gfs2_submit_bhs(int op, int op_flags, struct buffer_head *bhs[], + int num) { struct buffer_head *bh = bhs[0]; struct bio *bio; @@ -230,7 +231,7 @@ static void gfs2_submit_bhs(int rw, struct buffer_head *bhs[], int num) bio_add_page(bio, bh->b_page, bh->b_size, bh_offset(bh)); } bio->bi_end_io = gfs2_meta_read_endio; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); submit_bio(bio); } @@ -281,7 +282,7 @@ int gfs2_meta_read(struct gfs2_glock *gl, u64 blkno, int flags, } } - gfs2_submit_bhs(READ_SYNC | REQ_META | REQ_PRIO, bhs, num); + gfs2_submit_bhs(REQ_OP_READ, READ_SYNC | REQ_META | REQ_PRIO, bhs, num); if (!(flags & DIO_WAIT)) return 0; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index d9e19f6..f423c68 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -246,7 +246,7 @@ static int gfs2_read_super(struct gfs2_sbd *sdp, sector_t sector, int silent) bio->bi_end_io = end_bio_io_page; bio->bi_private = page; - bio->bi_rw = READ_SYNC | REQ_META; + bio_set_op_attrs(bio, REQ_OP_READ, READ_SYNC | REQ_META); submit_bio(bio); wait_on_page_locked(page); bio_put(bio); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 705A97CA0 for ; Sun, 5 Jun 2016 14:33:14 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 618D5304043 for ; Sun, 5 Jun 2016 12:33:13 -0700 (PDT) X-ASG-Debug-ID: 1465155191-04cb6c2db9b58dd0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id DrHGMTgJEKumBkmt (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:12 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A99ABC04D29F; Sun, 5 Jun 2016 19:33:11 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9O003130; Sun, 5 Jun 2016 15:33:09 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 17/45] xfs: use bio op accessors Date: Sun, 5 Jun 2016 14:31:57 -0500 X-ASG-Orig-Subj: [PATCH 17/45] xfs: use bio op accessors Message-Id: <1465155145-10812-18-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sun, 05 Jun 2016 19:33:11 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155192 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3541 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have xfs set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie --- v8: 1. Handled changes due to rebase and dropped signed offs due to upstream changes since last review. fs/xfs/xfs_aops.c | 12 ++++-------- fs/xfs/xfs_buf.c | 26 ++++++++++++++------------ 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 0cd1603..87d2b21 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -438,10 +438,8 @@ xfs_submit_ioend( ioend->io_bio->bi_private = ioend; ioend->io_bio->bi_end_io = xfs_end_bio; - if (wbc->sync_mode == WB_SYNC_ALL) - ioend->io_bio->bi_rw = WRITE_SYNC; - else - ioend->io_bio->bi_rw = WRITE; + bio_set_op_attrs(ioend->io_bio, REQ_OP_WRITE, + (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0); /* * If we are failing the IO now, just mark the ioend with an * error and finish it. This will run IO completion immediately @@ -512,10 +510,8 @@ xfs_chain_bio( bio_chain(ioend->io_bio, new); bio_get(ioend->io_bio); /* for xfs_destroy_ioend */ - if (wbc->sync_mode == WB_SYNC_ALL) - ioend->io_bio->bi_rw = WRITE_SYNC; - else - ioend->io_bio->bi_rw = WRITE; + bio_set_op_attrs(ioend->io_bio, REQ_OP_WRITE, + (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0); submit_bio(ioend->io_bio); ioend->io_bio = new; } diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 0777c67..d8acd37 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1127,7 +1127,8 @@ xfs_buf_ioapply_map( int map, int *buf_offset, int *count, - int rw) + int op, + int op_flags) { int page_index; int total_nr_pages = bp->b_page_count; @@ -1166,7 +1167,7 @@ next_chunk: bio->bi_iter.bi_sector = sector; bio->bi_end_io = xfs_buf_bio_end_io; bio->bi_private = bp; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); for (; size && nr_pages; nr_pages--, page_index++) { int rbytes, nbytes = PAGE_SIZE - offset; @@ -1210,7 +1211,8 @@ _xfs_buf_ioapply( struct xfs_buf *bp) { struct blk_plug plug; - int rw; + int op; + int op_flags = 0; int offset; int size; int i; @@ -1229,14 +1231,13 @@ _xfs_buf_ioapply( bp->b_ioend_wq = bp->b_target->bt_mount->m_buf_workqueue; if (bp->b_flags & XBF_WRITE) { + op = REQ_OP_WRITE; if (bp->b_flags & XBF_SYNCIO) - rw = WRITE_SYNC; - else - rw = WRITE; + op_flags = WRITE_SYNC; if (bp->b_flags & XBF_FUA) - rw |= REQ_FUA; + op_flags |= REQ_FUA; if (bp->b_flags & XBF_FLUSH) - rw |= REQ_FLUSH; + op_flags |= REQ_FLUSH; /* * Run the write verifier callback function if it exists. If @@ -1266,13 +1267,14 @@ _xfs_buf_ioapply( } } } else if (bp->b_flags & XBF_READ_AHEAD) { - rw = READA; + op = REQ_OP_READ; + op_flags = REQ_RAHEAD; } else { - rw = READ; + op = REQ_OP_READ; } /* we only use the buffer cache for meta-data */ - rw |= REQ_META; + op_flags |= REQ_META; /* * Walk all the vectors issuing IO on them. Set up the initial offset @@ -1284,7 +1286,7 @@ _xfs_buf_ioapply( size = BBTOB(bp->b_io_length); blk_start_plug(&plug); for (i = 0; i < bp->b_map_count; i++) { - xfs_buf_ioapply_map(bp, i, &offset, &size, rw); + xfs_buf_ioapply_map(bp, i, &offset, &size, op, op_flags); if (bp->b_error) break; if (size <= 0) -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A3BDB7CB6 for ; Sun, 5 Jun 2016 14:33:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 14BDFAC004 for ; Sun, 5 Jun 2016 12:33:16 -0700 (PDT) X-ASG-Debug-ID: 1465155194-04cbb03569b8abe0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id Lwg9IDOgm5Ffwfxc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:14 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EE0ED50F42; Sun, 5 Jun 2016 19:33:13 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9P003130; Sun, 5 Jun 2016 15:33:11 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 18/45] hfsplus: use bio op accessors Date: Sun, 5 Jun 2016 14:31:58 -0500 X-ASG-Orig-Subj: [PATCH 18/45] hfsplus: use bio op accessors Message-Id: <1465155145-10812-19-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sun, 05 Jun 2016 19:33:14 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155194 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4328 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have gfs2 set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/hfsplus/hfsplus_fs.h | 2 +- fs/hfsplus/part_tbl.c | 5 +++-- fs/hfsplus/super.c | 6 ++++-- fs/hfsplus/wrapper.c | 14 ++++++++------ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index fdc3446..047245b 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -526,7 +526,7 @@ int hfsplus_compare_dentry(const struct dentry *parent, /* wrapper.c */ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, void *buf, - void **data, int rw); + void **data, int op, int op_flags); int hfsplus_read_wrapper(struct super_block *sb); /* time macros */ diff --git a/fs/hfsplus/part_tbl.c b/fs/hfsplus/part_tbl.c index eb355d8..63164eb 100644 --- a/fs/hfsplus/part_tbl.c +++ b/fs/hfsplus/part_tbl.c @@ -112,7 +112,8 @@ static int hfs_parse_new_pmap(struct super_block *sb, void *buf, if ((u8 *)pm - (u8 *)buf >= buf_size) { res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK + i, - buf, (void **)&pm, READ); + buf, (void **)&pm, REQ_OP_READ, + 0); if (res) return res; } @@ -136,7 +137,7 @@ int hfs_part_find(struct super_block *sb, return -ENOMEM; res = hfsplus_submit_bio(sb, *part_start + HFS_PMAP_BLK, - buf, &data, READ); + buf, &data, REQ_OP_READ, 0); if (res) goto out; diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 755bf30..11854dd 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -220,7 +220,8 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait) error2 = hfsplus_submit_bio(sb, sbi->part_start + HFSPLUS_VOLHEAD_SECTOR, - sbi->s_vhdr_buf, NULL, WRITE_SYNC); + sbi->s_vhdr_buf, NULL, REQ_OP_WRITE, + WRITE_SYNC); if (!error) error = error2; if (!write_backup) @@ -228,7 +229,8 @@ static int hfsplus_sync_fs(struct super_block *sb, int wait) error2 = hfsplus_submit_bio(sb, sbi->part_start + sbi->sect_count - 2, - sbi->s_backup_vhdr_buf, NULL, WRITE_SYNC); + sbi->s_backup_vhdr_buf, NULL, REQ_OP_WRITE, + WRITE_SYNC); if (!error) error2 = error; out: diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index d026bb3..ebb85e5 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -30,7 +30,8 @@ struct hfsplus_wd { * @sector: block to read or write, for blocks of HFSPLUS_SECTOR_SIZE bytes * @buf: buffer for I/O * @data: output pointer for location of requested data - * @rw: direction of I/O + * @op: direction of I/O + * @op_flags: request op flags * * The unit of I/O is hfsplus_min_io_size(sb), which may be bigger than * HFSPLUS_SECTOR_SIZE, and @buf must be sized accordingly. On reads @@ -44,7 +45,7 @@ struct hfsplus_wd { * will work correctly. */ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, - void *buf, void **data, int rw) + void *buf, void **data, int op, int op_flags) { struct bio *bio; int ret = 0; @@ -65,9 +66,9 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, bio = bio_alloc(GFP_NOIO, 1); bio->bi_iter.bi_sector = sector; bio->bi_bdev = sb->s_bdev; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); - if (!(rw & WRITE) && data) + if (op != WRITE && data) *data = (u8 *)buf + offset; while (io_size > 0) { @@ -182,7 +183,7 @@ int hfsplus_read_wrapper(struct super_block *sb) reread: error = hfsplus_submit_bio(sb, part_start + HFSPLUS_VOLHEAD_SECTOR, sbi->s_vhdr_buf, (void **)&sbi->s_vhdr, - READ); + REQ_OP_READ, 0); if (error) goto out_free_backup_vhdr; @@ -214,7 +215,8 @@ reread: error = hfsplus_submit_bio(sb, part_start + part_size - 2, sbi->s_backup_vhdr_buf, - (void **)&sbi->s_backup_vhdr, READ); + (void **)&sbi->s_backup_vhdr, REQ_OP_READ, + 0); if (error) goto out_free_backup_vhdr; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2FCCF7CA0 for ; Sun, 5 Jun 2016 14:33:18 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id E7128304043 for ; Sun, 5 Jun 2016 12:33:17 -0700 (PDT) X-ASG-Debug-ID: 1465155196-04bdf05ad7b78490001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id nXh0x9NZMgV0kDCI (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:16 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3F84AC04D2A2; Sun, 5 Jun 2016 19:33:16 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9Q003130; Sun, 5 Jun 2016 15:33:14 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 19/45] mpage: use bio op accessors Date: Sun, 5 Jun 2016 14:31:59 -0500 X-ASG-Orig-Subj: [PATCH 19/45] mpage: use bio op accessors Message-Id: <1465155145-10812-20-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sun, 05 Jun 2016 19:33:16 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155196 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5147 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have the mpage code set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/mpage.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/fs/mpage.c b/fs/mpage.c index 2c251ec..37b2828 100644 --- a/fs/mpage.c +++ b/fs/mpage.c @@ -56,11 +56,11 @@ static void mpage_end_io(struct bio *bio) bio_put(bio); } -static struct bio *mpage_bio_submit(int rw, struct bio *bio) +static struct bio *mpage_bio_submit(int op, int op_flags, struct bio *bio) { bio->bi_end_io = mpage_end_io; - bio->bi_rw = rw; - guard_bio_eod(rw, bio); + bio_set_op_attrs(bio, op, op_flags); + guard_bio_eod(op, bio); submit_bio(bio); return NULL; } @@ -270,7 +270,7 @@ do_mpage_readpage(struct bio *bio, struct page *page, unsigned nr_pages, * This page will go to BIO. Do we need to send this BIO off first? */ if (bio && (*last_block_in_bio != blocks[0] - 1)) - bio = mpage_bio_submit(READ, bio); + bio = mpage_bio_submit(REQ_OP_READ, 0, bio); alloc_new: if (bio == NULL) { @@ -287,7 +287,7 @@ alloc_new: length = first_hole << blkbits; if (bio_add_page(bio, page, length, 0) < length) { - bio = mpage_bio_submit(READ, bio); + bio = mpage_bio_submit(REQ_OP_READ, 0, bio); goto alloc_new; } @@ -295,7 +295,7 @@ alloc_new: nblocks = map_bh->b_size >> blkbits; if ((buffer_boundary(map_bh) && relative_block == nblocks) || (first_hole != blocks_per_page)) - bio = mpage_bio_submit(READ, bio); + bio = mpage_bio_submit(REQ_OP_READ, 0, bio); else *last_block_in_bio = blocks[blocks_per_page - 1]; out: @@ -303,7 +303,7 @@ out: confused: if (bio) - bio = mpage_bio_submit(READ, bio); + bio = mpage_bio_submit(REQ_OP_READ, 0, bio); if (!PageUptodate(page)) block_read_full_page(page, get_block); else @@ -385,7 +385,7 @@ mpage_readpages(struct address_space *mapping, struct list_head *pages, } BUG_ON(!list_empty(pages)); if (bio) - mpage_bio_submit(READ, bio); + mpage_bio_submit(REQ_OP_READ, 0, bio); return 0; } EXPORT_SYMBOL(mpage_readpages); @@ -406,7 +406,7 @@ int mpage_readpage(struct page *page, get_block_t get_block) bio = do_mpage_readpage(bio, page, 1, &last_block_in_bio, &map_bh, &first_logical_block, get_block, gfp); if (bio) - mpage_bio_submit(READ, bio); + mpage_bio_submit(REQ_OP_READ, 0, bio); return 0; } EXPORT_SYMBOL(mpage_readpage); @@ -487,7 +487,7 @@ static int __mpage_writepage(struct page *page, struct writeback_control *wbc, struct buffer_head map_bh; loff_t i_size = i_size_read(inode); int ret = 0; - int wr = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); + int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : 0); if (page_has_buffers(page)) { struct buffer_head *head = page_buffers(page); @@ -596,7 +596,7 @@ page_is_mapped: * This page will go to BIO. Do we need to send this BIO off first? */ if (bio && mpd->last_block_in_bio != blocks[0] - 1) - bio = mpage_bio_submit(wr, bio); + bio = mpage_bio_submit(REQ_OP_WRITE, op_flags, bio); alloc_new: if (bio == NULL) { @@ -623,7 +623,7 @@ alloc_new: wbc_account_io(wbc, page, PAGE_SIZE); length = first_unmapped << blkbits; if (bio_add_page(bio, page, length, 0) < length) { - bio = mpage_bio_submit(wr, bio); + bio = mpage_bio_submit(REQ_OP_WRITE, op_flags, bio); goto alloc_new; } @@ -633,7 +633,7 @@ alloc_new: set_page_writeback(page); unlock_page(page); if (boundary || (first_unmapped != blocks_per_page)) { - bio = mpage_bio_submit(wr, bio); + bio = mpage_bio_submit(REQ_OP_WRITE, op_flags, bio); if (boundary_block) { write_boundary_block(boundary_bdev, boundary_block, 1 << blkbits); @@ -645,7 +645,7 @@ alloc_new: confused: if (bio) - bio = mpage_bio_submit(wr, bio); + bio = mpage_bio_submit(REQ_OP_WRITE, op_flags, bio); if (mpd->use_writepage) { ret = mapping->a_ops->writepage(page, wbc); @@ -702,9 +702,9 @@ mpage_writepages(struct address_space *mapping, ret = write_cache_pages(mapping, wbc, __mpage_writepage, &mpd); if (mpd.bio) { - int wr = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC : WRITE); - mpage_bio_submit(wr, mpd.bio); + int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? + WRITE_SYNC : 0); + mpage_bio_submit(REQ_OP_WRITE, op_flags, mpd.bio); } } blk_finish_plug(&plug); @@ -723,9 +723,9 @@ int mpage_writepage(struct page *page, get_block_t get_block, }; int ret = __mpage_writepage(page, wbc, &mpd); if (mpd.bio) { - int wr = (wbc->sync_mode == WB_SYNC_ALL ? - WRITE_SYNC : WRITE); - mpage_bio_submit(wr, mpd.bio); + int op_flags = (wbc->sync_mode == WB_SYNC_ALL ? + WRITE_SYNC : 0); + mpage_bio_submit(REQ_OP_WRITE, op_flags, mpd.bio); } return ret; } -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 57C657CA0 for ; Sun, 5 Jun 2016 14:33:20 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0DDC4304043 for ; Sun, 5 Jun 2016 12:33:20 -0700 (PDT) X-ASG-Debug-ID: 1465155198-04bdf05ad6b78490001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id afOHA0wUjKhHHiZ3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:18 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8999675736; Sun, 5 Jun 2016 19:33:18 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9R003130; Sun, 5 Jun 2016 15:33:16 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 20/45] nilfs: use bio op accessors Date: Sun, 5 Jun 2016 14:32:00 -0500 X-ASG-Orig-Subj: [PATCH 20/45] nilfs: use bio op accessors Message-Id: <1465155145-10812-21-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Sun, 05 Jun 2016 19:33:18 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155198 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2615 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have nilfs set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke Acked-by: Ryusuke Konishi --- fs/nilfs2/segbuf.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index 0f62909..a962d7d 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -346,7 +346,8 @@ static void nilfs_end_bio_write(struct bio *bio) } static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, - struct nilfs_write_info *wi, int mode) + struct nilfs_write_info *wi, int mode, + int mode_flags) { struct bio *bio = wi->bio; int err; @@ -364,7 +365,7 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, bio->bi_end_io = nilfs_end_bio_write; bio->bi_private = segbuf; - bio->bi_rw = mode; + bio_set_op_attrs(bio, mode, mode_flags); submit_bio(bio); segbuf->sb_nbio++; @@ -438,7 +439,7 @@ static int nilfs_segbuf_submit_bh(struct nilfs_segment_buffer *segbuf, return 0; } /* bio is FULL */ - err = nilfs_segbuf_submit_bio(segbuf, wi, mode); + err = nilfs_segbuf_submit_bio(segbuf, wi, mode, 0); /* never submit current bh */ if (likely(!err)) goto repeat; @@ -462,19 +463,19 @@ static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, { struct nilfs_write_info wi; struct buffer_head *bh; - int res = 0, rw = WRITE; + int res = 0; wi.nilfs = nilfs; nilfs_segbuf_prepare_write(segbuf, &wi); list_for_each_entry(bh, &segbuf->sb_segsum_buffers, b_assoc_buffers) { - res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, rw); + res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, REQ_OP_WRITE); if (unlikely(res)) goto failed_bio; } list_for_each_entry(bh, &segbuf->sb_payload_buffers, b_assoc_buffers) { - res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, rw); + res = nilfs_segbuf_submit_bh(segbuf, &wi, bh, REQ_OP_WRITE); if (unlikely(res)) goto failed_bio; } @@ -484,8 +485,8 @@ static int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf, * Last BIO is always sent through the following * submission. */ - rw |= REQ_SYNC; - res = nilfs_segbuf_submit_bio(segbuf, &wi, rw); + res = nilfs_segbuf_submit_bio(segbuf, &wi, REQ_OP_WRITE, + REQ_SYNC); } failed_bio: -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5BAA67D02 for ; Sun, 5 Jun 2016 14:33:23 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id C93A4AC005 for ; Sun, 5 Jun 2016 12:33:22 -0700 (PDT) X-ASG-Debug-ID: 1465155201-04cbb03569b8ac00001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id vj12ZltrHBm75ru1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:21 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 05BC7B0433; Sun, 5 Jun 2016 19:33:21 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9S003130; Sun, 5 Jun 2016 15:33:18 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 21/45] ocfs2: use bio op accessors Date: Sun, 5 Jun 2016 14:32:01 -0500 X-ASG-Orig-Subj: [PATCH 21/45] ocfs2: use bio op accessors Message-Id: <1465155145-10812-22-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Sun, 05 Jun 2016 19:33:21 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155201 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1933 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have ocfs2 set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- fs/ocfs2/cluster/heartbeat.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 8b1d86e..636abcb 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -530,7 +530,8 @@ static void o2hb_bio_end_io(struct bio *bio) static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, struct o2hb_bio_wait_ctxt *wc, unsigned int *current_slot, - unsigned int max_slots, int rw) + unsigned int max_slots, int op, + int op_flags) { int len, current_page; unsigned int vec_len, vec_start; @@ -556,7 +557,7 @@ static struct bio *o2hb_setup_one_bio(struct o2hb_region *reg, bio->bi_bdev = reg->hr_bdev; bio->bi_private = wc; bio->bi_end_io = o2hb_bio_end_io; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); vec_start = (cs << bits) % PAGE_SIZE; while(cs < max_slots) { @@ -593,7 +594,7 @@ static int o2hb_read_slots(struct o2hb_region *reg, while(current_slot < max_slots) { bio = o2hb_setup_one_bio(reg, &wc, ¤t_slot, max_slots, - READ); + REQ_OP_READ, 0); if (IS_ERR(bio)) { status = PTR_ERR(bio); mlog_errno(status); @@ -625,7 +626,8 @@ static int o2hb_issue_node_write(struct o2hb_region *reg, slot = o2nm_this_node(); - bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1, WRITE_SYNC); + bio = o2hb_setup_one_bio(reg, write_wc, &slot, slot+1, REQ_OP_WRITE, + WRITE_SYNC); if (IS_ERR(bio)) { status = PTR_ERR(bio); mlog_errno(status); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E68ED7D09 for ; Sun, 5 Jun 2016 14:33:24 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id B7ED38F8049 for ; Sun, 5 Jun 2016 12:33:24 -0700 (PDT) X-ASG-Debug-ID: 1465155203-04cbb0356bb8ac10001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id iAJMzuBjv35tTBz9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:23 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 110AD50F48; Sun, 5 Jun 2016 19:33:23 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9T003130; Sun, 5 Jun 2016 15:33:20 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 22/45] pm: use bio op accessors Date: Sun, 5 Jun 2016 14:32:02 -0500 X-ASG-Orig-Subj: [PATCH 22/45] pm: use bio op accessors Message-Id: <1465155145-10812-23-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sun, 05 Jun 2016 19:33:23 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155203 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4607 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have the pm code set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- kernel/power/swap.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/kernel/power/swap.c b/kernel/power/swap.c index be227f5..c1aaac4 100644 --- a/kernel/power/swap.c +++ b/kernel/power/swap.c @@ -261,7 +261,7 @@ static void hib_end_io(struct bio *bio) bio_put(bio); } -static int hib_submit_io(int rw, pgoff_t page_off, void *addr, +static int hib_submit_io(int op, int op_flags, pgoff_t page_off, void *addr, struct hib_bio_batch *hb) { struct page *page = virt_to_page(addr); @@ -271,7 +271,7 @@ static int hib_submit_io(int rw, pgoff_t page_off, void *addr, bio = bio_alloc(__GFP_RECLAIM | __GFP_HIGH, 1); bio->bi_iter.bi_sector = page_off * (PAGE_SIZE >> 9); bio->bi_bdev = hib_resume_bdev; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { printk(KERN_ERR "PM: Adding page to bio failed at %llu\n", @@ -307,7 +307,8 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) { int error; - hib_submit_io(READ_SYNC, swsusp_resume_block, swsusp_header, NULL); + hib_submit_io(REQ_OP_READ, READ_SYNC, swsusp_resume_block, + swsusp_header, NULL); if (!memcmp("SWAP-SPACE",swsusp_header->sig, 10) || !memcmp("SWAPSPACE2",swsusp_header->sig, 10)) { memcpy(swsusp_header->orig_sig,swsusp_header->sig, 10); @@ -316,8 +317,8 @@ static int mark_swapfiles(struct swap_map_handle *handle, unsigned int flags) swsusp_header->flags = flags; if (flags & SF_CRC32_MODE) swsusp_header->crc32 = handle->crc32; - error = hib_submit_io(WRITE_SYNC, swsusp_resume_block, - swsusp_header, NULL); + error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, + swsusp_resume_block, swsusp_header, NULL); } else { printk(KERN_ERR "PM: Swap header not found!\n"); error = -ENODEV; @@ -390,7 +391,7 @@ static int write_page(void *buf, sector_t offset, struct hib_bio_batch *hb) } else { src = buf; } - return hib_submit_io(WRITE_SYNC, offset, src, hb); + return hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, offset, src, hb); } static void release_swap_writer(struct swap_map_handle *handle) @@ -993,7 +994,8 @@ static int get_swap_reader(struct swap_map_handle *handle, return -ENOMEM; } - error = hib_submit_io(READ_SYNC, offset, tmp->map, NULL); + error = hib_submit_io(REQ_OP_READ, READ_SYNC, offset, + tmp->map, NULL); if (error) { release_swap_reader(handle); return error; @@ -1017,7 +1019,7 @@ static int swap_read_page(struct swap_map_handle *handle, void *buf, offset = handle->cur->entries[handle->k]; if (!offset) return -EFAULT; - error = hib_submit_io(READ_SYNC, offset, buf, hb); + error = hib_submit_io(REQ_OP_READ, READ_SYNC, offset, buf, hb); if (error) return error; if (++handle->k >= MAP_PAGE_ENTRIES) { @@ -1526,7 +1528,8 @@ int swsusp_check(void) if (!IS_ERR(hib_resume_bdev)) { set_blocksize(hib_resume_bdev, PAGE_SIZE); clear_page(swsusp_header); - error = hib_submit_io(READ_SYNC, swsusp_resume_block, + error = hib_submit_io(REQ_OP_READ, READ_SYNC, + swsusp_resume_block, swsusp_header, NULL); if (error) goto put; @@ -1534,7 +1537,8 @@ int swsusp_check(void) if (!memcmp(HIBERNATE_SIG, swsusp_header->sig, 10)) { memcpy(swsusp_header->sig, swsusp_header->orig_sig, 10); /* Reset swap signature now */ - error = hib_submit_io(WRITE_SYNC, swsusp_resume_block, + error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, + swsusp_resume_block, swsusp_header, NULL); } else { error = -EINVAL; @@ -1578,10 +1582,12 @@ int swsusp_unmark(void) { int error; - hib_submit_io(READ_SYNC, swsusp_resume_block, swsusp_header, NULL); + hib_submit_io(REQ_OP_READ, READ_SYNC, swsusp_resume_block, + swsusp_header, NULL); if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) { memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10); - error = hib_submit_io(WRITE_SYNC, swsusp_resume_block, + error = hib_submit_io(REQ_OP_WRITE, WRITE_SYNC, + swsusp_resume_block, swsusp_header, NULL); } else { printk(KERN_ERR "PM: Cannot find swsusp signature!\n"); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 4009D7D0B for ; Sun, 5 Jun 2016 14:33:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id F3BA58F8037 for ; Sun, 5 Jun 2016 12:33:26 -0700 (PDT) X-ASG-Debug-ID: 1465155205-04cb6c2dbcb58e10001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id TVBDWDWNME93349Z (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:26 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 58444C003586; Sun, 5 Jun 2016 19:33:25 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9U003130; Sun, 5 Jun 2016 15:33:23 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 23/45] dm: pass dm stats data dir instead of bi_rw Date: Sun, 5 Jun 2016 14:32:03 -0500 X-ASG-Orig-Subj: [PATCH 23/45] dm: pass dm stats data dir instead of bi_rw Message-Id: <1465155145-10812-24-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sun, 05 Jun 2016 19:33:25 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155205 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4783 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie It looks like dm stats cares about the data direction (READ vs WRITE) and does not need the bio/request flags. Commands like REQ_FLUSH, REQ_DISCARD and REQ_WRITE_SAME are currently always set with REQ_WRITE, so the extra check for REQ_DISCARD in dm_stats_account_io is not needed. This patch has it use the bio and request data_dir helpers instead of accessing the bi_rw/cmd_flags directly. This makes the next patches that remove the operation from the cmd_flags and bi_rw easier, because we will no longer have the REQ_WRITE bit set for operations like discards. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- v2: 1. Merged Mike Snitzer's fixes to pass in int instead of unsigned long. 2. Fix 80 char col issues. drivers/md/dm-stats.c | 9 ++++----- drivers/md/dm.c | 21 ++++++++++++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/drivers/md/dm-stats.c b/drivers/md/dm-stats.c index 8289804..4fba26c 100644 --- a/drivers/md/dm-stats.c +++ b/drivers/md/dm-stats.c @@ -514,11 +514,10 @@ static void dm_stat_round(struct dm_stat *s, struct dm_stat_shared *shared, } static void dm_stat_for_entry(struct dm_stat *s, size_t entry, - unsigned long bi_rw, sector_t len, + int idx, sector_t len, struct dm_stats_aux *stats_aux, bool end, unsigned long duration_jiffies) { - unsigned long idx = bi_rw & REQ_WRITE; struct dm_stat_shared *shared = &s->stat_shared[entry]; struct dm_stat_percpu *p; @@ -584,7 +583,7 @@ static void dm_stat_for_entry(struct dm_stat *s, size_t entry, #endif } -static void __dm_stat_bio(struct dm_stat *s, unsigned long bi_rw, +static void __dm_stat_bio(struct dm_stat *s, int bi_rw, sector_t bi_sector, sector_t end_sector, bool end, unsigned long duration_jiffies, struct dm_stats_aux *stats_aux) @@ -645,8 +644,8 @@ void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw, last = raw_cpu_ptr(stats->last); stats_aux->merged = (bi_sector == (ACCESS_ONCE(last->last_sector) && - ((bi_rw & (REQ_WRITE | REQ_DISCARD)) == - (ACCESS_ONCE(last->last_rw) & (REQ_WRITE | REQ_DISCARD))) + ((bi_rw == WRITE) == + (ACCESS_ONCE(last->last_rw) == WRITE)) )); ACCESS_ONCE(last->last_sector) = end_sector; ACCESS_ONCE(last->last_rw) = bi_rw; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 1b2f962..f5ac0a3 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -723,8 +723,9 @@ static void start_io_acct(struct dm_io *io) atomic_inc_return(&md->pending[rw])); if (unlikely(dm_stats_used(&md->stats))) - dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_iter.bi_sector, - bio_sectors(bio), false, 0, &io->stats_aux); + dm_stats_account_io(&md->stats, bio_data_dir(bio), + bio->bi_iter.bi_sector, bio_sectors(bio), + false, 0, &io->stats_aux); } static void end_io_acct(struct dm_io *io) @@ -738,8 +739,9 @@ static void end_io_acct(struct dm_io *io) generic_end_io_acct(rw, &dm_disk(md)->part0, io->start_time); if (unlikely(dm_stats_used(&md->stats))) - dm_stats_account_io(&md->stats, bio->bi_rw, bio->bi_iter.bi_sector, - bio_sectors(bio), true, duration, &io->stats_aux); + dm_stats_account_io(&md->stats, bio_data_dir(bio), + bio->bi_iter.bi_sector, bio_sectors(bio), + true, duration, &io->stats_aux); /* * After this is decremented the bio must not be touched if it is @@ -1121,9 +1123,9 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig) if (unlikely(dm_stats_used(&md->stats))) { struct dm_rq_target_io *tio = tio_from_request(orig); tio->duration_jiffies = jiffies - tio->duration_jiffies; - dm_stats_account_io(&md->stats, orig->cmd_flags, blk_rq_pos(orig), - tio->n_sectors, true, tio->duration_jiffies, - &tio->stats_aux); + dm_stats_account_io(&md->stats, rq_data_dir(orig), + blk_rq_pos(orig), tio->n_sectors, true, + tio->duration_jiffies, &tio->stats_aux); } } @@ -2082,8 +2084,9 @@ static void dm_start_request(struct mapped_device *md, struct request *orig) struct dm_rq_target_io *tio = tio_from_request(orig); tio->duration_jiffies = jiffies; tio->n_sectors = blk_rq_sectors(orig); - dm_stats_account_io(&md->stats, orig->cmd_flags, blk_rq_pos(orig), - tio->n_sectors, false, 0, &tio->stats_aux); + dm_stats_account_io(&md->stats, rq_data_dir(orig), + blk_rq_pos(orig), tio->n_sectors, false, 0, + &tio->stats_aux); } /* -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id DE4277D0F for ; Sun, 5 Jun 2016 14:33:30 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id A046F8F8037 for ; Sun, 5 Jun 2016 12:33:30 -0700 (PDT) X-ASG-Debug-ID: 1465155207-04bdf05ad7b784a0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id tbEPCpnQgdG6yCHg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:28 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9A61863309; Sun, 5 Jun 2016 19:33:27 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9V003130; Sun, 5 Jun 2016 15:33:25 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 24/45] dm: use bio op accessors Date: Sun, 5 Jun 2016 14:32:04 -0500 X-ASG-Orig-Subj: [PATCH 24/45] dm: use bio op accessors Message-Id: <1465155145-10812-25-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 05 Jun 2016 19:33:27 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155208 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 25464 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com From: Mike Christie Separate the op from the rq_flag_bits and have dm set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie v8: - Moved op_is_write changes to its own patch. - Dropped signed offs due to changes in dm. --- drivers/md/dm-bufio.c | 8 +++--- drivers/md/dm-cache-target.c | 10 +++++--- drivers/md/dm-crypt.c | 8 +++--- drivers/md/dm-io.c | 56 ++++++++++++++++++++++------------------- drivers/md/dm-kcopyd.c | 5 ++-- drivers/md/dm-log-writes.c | 8 +++--- drivers/md/dm-log.c | 5 ++-- drivers/md/dm-raid1.c | 19 ++++++++------ drivers/md/dm-region-hash.c | 4 +-- drivers/md/dm-snap-persistent.c | 24 ++++++++++-------- drivers/md/dm-stripe.c | 4 +-- drivers/md/dm-thin.c | 17 +++++++------ drivers/md/dm.c | 8 +++--- include/linux/dm-io.h | 3 ++- 14 files changed, 99 insertions(+), 80 deletions(-) diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 9d3ee7f..6571c81 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -574,7 +574,8 @@ static void use_dmio(struct dm_buffer *b, int rw, sector_t block, { int r; struct dm_io_request io_req = { - .bi_rw = rw, + .bi_op = rw, + .bi_op_flags = 0, .notify.fn = dmio_complete, .notify.context = b, .client = b->c->dm_io, @@ -634,7 +635,7 @@ static void use_inline_bio(struct dm_buffer *b, int rw, sector_t block, * the dm_buffer's inline bio is local to bufio. */ b->bio.bi_private = end_io; - b->bio.bi_rw = rw; + bio_set_op_attrs(&b->bio, rw, 0); /* * We assume that if len >= PAGE_SIZE ptr is page-aligned. @@ -1327,7 +1328,8 @@ EXPORT_SYMBOL_GPL(dm_bufio_write_dirty_buffers); int dm_bufio_issue_flush(struct dm_bufio_client *c) { struct dm_io_request io_req = { - .bi_rw = WRITE_FLUSH, + .bi_op = REQ_OP_WRITE, + .bi_op_flags = WRITE_FLUSH, .mem.type = DM_IO_KMEM, .mem.ptr.addr = NULL, .client = c->dm_io, diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index ee0510f..540e80e 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -788,7 +788,8 @@ static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio) spin_lock_irqsave(&cache->lock, flags); if (cache->need_tick_bio && - !(bio->bi_rw & (REQ_FUA | REQ_FLUSH | REQ_DISCARD))) { + !(bio->bi_rw & (REQ_FUA | REQ_FLUSH)) && + bio_op(bio) != REQ_OP_DISCARD) { pb->tick = true; cache->need_tick_bio = false; } @@ -851,7 +852,7 @@ static void inc_ds(struct cache *cache, struct bio *bio, static bool accountable_bio(struct cache *cache, struct bio *bio) { return ((bio->bi_bdev == cache->origin_dev->bdev) && - !(bio->bi_rw & REQ_DISCARD)); + bio_op(bio) != REQ_OP_DISCARD); } static void accounted_begin(struct cache *cache, struct bio *bio) @@ -1067,7 +1068,8 @@ static void dec_io_migrations(struct cache *cache) static bool discard_or_flush(struct bio *bio) { - return bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD); + return bio_op(bio) == REQ_OP_DISCARD || + bio->bi_rw & (REQ_FLUSH | REQ_FUA); } static void __cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell) @@ -1980,7 +1982,7 @@ static void process_deferred_bios(struct cache *cache) if (bio->bi_rw & REQ_FLUSH) process_flush_bio(cache, bio); - else if (bio->bi_rw & REQ_DISCARD) + else if (bio_op(bio) == REQ_OP_DISCARD) process_discard_bio(cache, &structs, bio); else process_bio(cache, &structs, bio); diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 4f3cb35..057d19b 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1136,7 +1136,7 @@ static void clone_init(struct dm_crypt_io *io, struct bio *clone) clone->bi_private = io; clone->bi_end_io = crypt_endio; clone->bi_bdev = cc->dev->bdev; - clone->bi_rw = io->base_bio->bi_rw; + bio_set_op_attrs(clone, bio_op(io->base_bio), io->base_bio->bi_rw); } static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp) @@ -1911,11 +1911,11 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) struct crypt_config *cc = ti->private; /* - * If bio is REQ_FLUSH or REQ_DISCARD, just bypass crypt queues. + * If bio is REQ_FLUSH or REQ_OP_DISCARD, just bypass crypt queues. * - for REQ_FLUSH device-mapper core ensures that no IO is in-flight - * - for REQ_DISCARD caller must use flush if IO ordering matters + * - for REQ_OP_DISCARD caller must use flush if IO ordering matters */ - if (unlikely(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) { + if (unlikely(bio->bi_rw & REQ_FLUSH || bio_op(bio) == REQ_OP_DISCARD)) { bio->bi_bdev = cc->dev->bdev; if (bio_sectors(bio)) bio->bi_iter.bi_sector = cc->start + diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 26e9a85..22e0597 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -278,8 +278,9 @@ static void km_dp_init(struct dpages *dp, void *data) /*----------------------------------------------------------------- * IO routines that accept a list of pages. *---------------------------------------------------------------*/ -static void do_region(int rw, unsigned region, struct dm_io_region *where, - struct dpages *dp, struct io *io) +static void do_region(int op, int op_flags, unsigned region, + struct dm_io_region *where, struct dpages *dp, + struct io *io) { struct bio *bio; struct page *page; @@ -295,24 +296,25 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, /* * Reject unsupported discard and write same requests. */ - if (rw & REQ_DISCARD) + if (op == REQ_OP_DISCARD) special_cmd_max_sectors = q->limits.max_discard_sectors; - else if (rw & REQ_WRITE_SAME) + else if (op == REQ_OP_WRITE_SAME) special_cmd_max_sectors = q->limits.max_write_same_sectors; - if ((rw & (REQ_DISCARD | REQ_WRITE_SAME)) && special_cmd_max_sectors == 0) { + if ((op == REQ_OP_DISCARD || op == REQ_OP_WRITE_SAME) && + special_cmd_max_sectors == 0) { dec_count(io, region, -EOPNOTSUPP); return; } /* - * where->count may be zero if rw holds a flush and we need to + * where->count may be zero if op holds a flush and we need to * send a zero-sized flush. */ do { /* * Allocate a suitably sized-bio. */ - if ((rw & REQ_DISCARD) || (rw & REQ_WRITE_SAME)) + if ((op == REQ_OP_DISCARD) || (op == REQ_OP_WRITE_SAME)) num_bvecs = 1; else num_bvecs = min_t(int, BIO_MAX_PAGES, @@ -322,14 +324,14 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, bio->bi_iter.bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; bio->bi_end_io = endio; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); store_io_and_region_in_bio(bio, io, region); - if (rw & REQ_DISCARD) { + if (op == REQ_OP_DISCARD) { num_sectors = min_t(sector_t, special_cmd_max_sectors, remaining); bio->bi_iter.bi_size = num_sectors << SECTOR_SHIFT; remaining -= num_sectors; - } else if (rw & REQ_WRITE_SAME) { + } else if (op == REQ_OP_WRITE_SAME) { /* * WRITE SAME only uses a single page. */ @@ -360,7 +362,7 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, } while (remaining); } -static void dispatch_io(int rw, unsigned int num_regions, +static void dispatch_io(int op, int op_flags, unsigned int num_regions, struct dm_io_region *where, struct dpages *dp, struct io *io, int sync) { @@ -370,7 +372,7 @@ static void dispatch_io(int rw, unsigned int num_regions, BUG_ON(num_regions > DM_IO_MAX_REGIONS); if (sync) - rw |= REQ_SYNC; + op_flags |= REQ_SYNC; /* * For multiple regions we need to be careful to rewind @@ -378,8 +380,8 @@ static void dispatch_io(int rw, unsigned int num_regions, */ for (i = 0; i < num_regions; i++) { *dp = old_pages; - if (where[i].count || (rw & REQ_FLUSH)) - do_region(rw, i, where + i, dp, io); + if (where[i].count || (op_flags & REQ_FLUSH)) + do_region(op, op_flags, i, where + i, dp, io); } /* @@ -403,13 +405,13 @@ static void sync_io_complete(unsigned long error, void *context) } static int sync_io(struct dm_io_client *client, unsigned int num_regions, - struct dm_io_region *where, int rw, struct dpages *dp, - unsigned long *error_bits) + struct dm_io_region *where, int op, int op_flags, + struct dpages *dp, unsigned long *error_bits) { struct io *io; struct sync_io sio; - if (num_regions > 1 && !op_is_write(rw)) { + if (num_regions > 1 && !op_is_write(op)) { WARN_ON(1); return -EIO; } @@ -426,7 +428,7 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, io->vma_invalidate_address = dp->vma_invalidate_address; io->vma_invalidate_size = dp->vma_invalidate_size; - dispatch_io(rw, num_regions, where, dp, io, 1); + dispatch_io(op, op_flags, num_regions, where, dp, io, 1); wait_for_completion_io(&sio.wait); @@ -437,12 +439,12 @@ static int sync_io(struct dm_io_client *client, unsigned int num_regions, } static int async_io(struct dm_io_client *client, unsigned int num_regions, - struct dm_io_region *where, int rw, struct dpages *dp, - io_notify_fn fn, void *context) + struct dm_io_region *where, int op, int op_flags, + struct dpages *dp, io_notify_fn fn, void *context) { struct io *io; - if (num_regions > 1 && !op_is_write(rw)) { + if (num_regions > 1 && !op_is_write(op)) { WARN_ON(1); fn(1, context); return -EIO; @@ -458,7 +460,7 @@ static int async_io(struct dm_io_client *client, unsigned int num_regions, io->vma_invalidate_address = dp->vma_invalidate_address; io->vma_invalidate_size = dp->vma_invalidate_size; - dispatch_io(rw, num_regions, where, dp, io, 0); + dispatch_io(op, op_flags, num_regions, where, dp, io, 0); return 0; } @@ -481,7 +483,7 @@ static int dp_init(struct dm_io_request *io_req, struct dpages *dp, case DM_IO_VMA: flush_kernel_vmap_range(io_req->mem.ptr.vma, size); - if ((io_req->bi_rw & RW_MASK) == READ) { + if (io_req->bi_op == REQ_OP_READ) { dp->vma_invalidate_address = io_req->mem.ptr.vma; dp->vma_invalidate_size = size; } @@ -519,10 +521,12 @@ int dm_io(struct dm_io_request *io_req, unsigned num_regions, if (!io_req->notify.fn) return sync_io(io_req->client, num_regions, where, - io_req->bi_rw, &dp, sync_error_bits); + io_req->bi_op, io_req->bi_op_flags, &dp, + sync_error_bits); - return async_io(io_req->client, num_regions, where, io_req->bi_rw, - &dp, io_req->notify.fn, io_req->notify.context); + return async_io(io_req->client, num_regions, where, io_req->bi_op, + io_req->bi_op_flags, &dp, io_req->notify.fn, + io_req->notify.context); } EXPORT_SYMBOL(dm_io); diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c index 9f390e4..9da1d54 100644 --- a/drivers/md/dm-kcopyd.c +++ b/drivers/md/dm-kcopyd.c @@ -496,7 +496,8 @@ static int run_io_job(struct kcopyd_job *job) { int r; struct dm_io_request io_req = { - .bi_rw = job->rw, + .bi_op = job->rw, + .bi_op_flags = 0, .mem.type = DM_IO_PAGE_LIST, .mem.ptr.pl = job->pages, .mem.offset = 0, @@ -734,7 +735,7 @@ int dm_kcopyd_copy(struct dm_kcopyd_client *kc, struct dm_io_region *from, /* * Use WRITE SAME to optimize zeroing if all dests support it. */ - job->rw = WRITE | REQ_WRITE_SAME; + job->rw = REQ_OP_WRITE_SAME; for (i = 0; i < job->num_dests; i++) if (!bdev_write_same(job->dests[i].bdev)) { job->rw = WRITE; diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index addcc4b..0edb8ea 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c @@ -205,7 +205,7 @@ static int write_metadata(struct log_writes_c *lc, void *entry, bio->bi_bdev = lc->logdev->bdev; bio->bi_end_io = log_end_io; bio->bi_private = lc; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); page = alloc_page(GFP_KERNEL); if (!page) { @@ -270,7 +270,7 @@ static int log_one_block(struct log_writes_c *lc, bio->bi_bdev = lc->logdev->bdev; bio->bi_end_io = log_end_io; bio->bi_private = lc; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); for (i = 0; i < block->vec_cnt; i++) { /* @@ -292,7 +292,7 @@ static int log_one_block(struct log_writes_c *lc, bio->bi_bdev = lc->logdev->bdev; bio->bi_end_io = log_end_io; bio->bi_private = lc; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); ret = bio_add_page(bio, block->vecs[i].bv_page, block->vecs[i].bv_len, 0); @@ -557,7 +557,7 @@ static int log_writes_map(struct dm_target *ti, struct bio *bio) int i = 0; bool flush_bio = (bio->bi_rw & REQ_FLUSH); bool fua_bio = (bio->bi_rw & REQ_FUA); - bool discard_bio = (bio->bi_rw & REQ_DISCARD); + bool discard_bio = (bio_op(bio) == REQ_OP_DISCARD); pb->block = NULL; diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 627d191..4ca2d1d 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -293,7 +293,7 @@ static void header_from_disk(struct log_header_core *core, struct log_header_dis static int rw_header(struct log_c *lc, int rw) { - lc->io_req.bi_rw = rw; + lc->io_req.bi_op = rw; return dm_io(&lc->io_req, 1, &lc->header_location, NULL); } @@ -306,7 +306,8 @@ static int flush_header(struct log_c *lc) .count = 0, }; - lc->io_req.bi_rw = WRITE_FLUSH; + lc->io_req.bi_op = REQ_OP_WRITE; + lc->io_req.bi_op_flags = WRITE_FLUSH; return dm_io(&lc->io_req, 1, &null_location, NULL); } diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index b3ccf1e..907df2b 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -260,7 +260,8 @@ static int mirror_flush(struct dm_target *ti) struct dm_io_region io[ms->nr_mirrors]; struct mirror *m; struct dm_io_request io_req = { - .bi_rw = WRITE_FLUSH, + .bi_op = REQ_OP_WRITE, + .bi_op_flags = WRITE_FLUSH, .mem.type = DM_IO_KMEM, .mem.ptr.addr = NULL, .client = ms->io_client, @@ -541,7 +542,8 @@ static void read_async_bio(struct mirror *m, struct bio *bio) { struct dm_io_region io; struct dm_io_request io_req = { - .bi_rw = READ, + .bi_op = REQ_OP_READ, + .bi_op_flags = 0, .mem.type = DM_IO_BIO, .mem.ptr.bio = bio, .notify.fn = read_callback, @@ -624,7 +626,7 @@ static void write_callback(unsigned long error, void *context) * If the bio is discard, return an error, but do not * degrade the array. */ - if (bio->bi_rw & REQ_DISCARD) { + if (bio_op(bio) == REQ_OP_DISCARD) { bio->bi_error = -EOPNOTSUPP; bio_endio(bio); return; @@ -654,7 +656,8 @@ static void do_write(struct mirror_set *ms, struct bio *bio) struct dm_io_region io[ms->nr_mirrors], *dest = io; struct mirror *m; struct dm_io_request io_req = { - .bi_rw = WRITE | (bio->bi_rw & WRITE_FLUSH_FUA), + .bi_op = REQ_OP_WRITE, + .bi_op_flags = bio->bi_rw & WRITE_FLUSH_FUA, .mem.type = DM_IO_BIO, .mem.ptr.bio = bio, .notify.fn = write_callback, @@ -662,8 +665,8 @@ static void do_write(struct mirror_set *ms, struct bio *bio) .client = ms->io_client, }; - if (bio->bi_rw & REQ_DISCARD) { - io_req.bi_rw |= REQ_DISCARD; + if (bio_op(bio) == REQ_OP_DISCARD) { + io_req.bi_op = REQ_OP_DISCARD; io_req.mem.type = DM_IO_KMEM; io_req.mem.ptr.addr = NULL; } @@ -702,7 +705,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) while ((bio = bio_list_pop(writes))) { if ((bio->bi_rw & REQ_FLUSH) || - (bio->bi_rw & REQ_DISCARD)) { + (bio_op(bio) == REQ_OP_DISCARD)) { bio_list_add(&sync, bio); continue; } @@ -1250,7 +1253,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) * We need to dec pending if this was a write. */ if (rw == WRITE) { - if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))) + if (!(bio->bi_rw & REQ_FLUSH) && bio_op(bio) != REQ_OP_DISCARD) dm_rh_dec(ms->rh, bio_record->write_region); return error; } diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index 74cb7b9..3550ca7 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -403,7 +403,7 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio) return; } - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) return; /* We must inform the log that the sync count has changed. */ @@ -526,7 +526,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios) struct bio *bio; for (bio = bios->head; bio; bio = bio->bi_next) { - if (bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)) + if (bio->bi_rw & REQ_FLUSH || bio_op(bio) == REQ_OP_DISCARD) continue; rh_inc(rh, dm_rh_bio_to_region(rh, bio)); } diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 4d39093..b8cf956 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -226,8 +226,8 @@ static void do_metadata(struct work_struct *work) /* * Read or write a chunk aligned and sized block of data from a device. */ -static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, - int metadata) +static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int op, + int op_flags, int metadata) { struct dm_io_region where = { .bdev = dm_snap_cow(ps->store->snap)->bdev, @@ -235,7 +235,8 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, .count = ps->store->chunk_size, }; struct dm_io_request io_req = { - .bi_rw = rw, + .bi_op = op, + .bi_op_flags = op_flags, .mem.type = DM_IO_VMA, .mem.ptr.vma = area, .client = ps->io_client, @@ -281,14 +282,14 @@ static void skip_metadata(struct pstore *ps) * Read or write a metadata area. Remembering to skip the first * chunk which holds the header. */ -static int area_io(struct pstore *ps, int rw) +static int area_io(struct pstore *ps, int op, int op_flags) { int r; chunk_t chunk; chunk = area_location(ps, ps->current_area); - r = chunk_io(ps, ps->area, chunk, rw, 0); + r = chunk_io(ps, ps->area, chunk, op, op_flags, 0); if (r) return r; @@ -302,7 +303,8 @@ static void zero_memory_area(struct pstore *ps) static int zero_disk_area(struct pstore *ps, chunk_t area) { - return chunk_io(ps, ps->zero_area, area_location(ps, area), WRITE, 0); + return chunk_io(ps, ps->zero_area, area_location(ps, area), + REQ_OP_WRITE, 0, 0); } static int read_header(struct pstore *ps, int *new_snapshot) @@ -334,7 +336,7 @@ static int read_header(struct pstore *ps, int *new_snapshot) if (r) return r; - r = chunk_io(ps, ps->header_area, 0, READ, 1); + r = chunk_io(ps, ps->header_area, 0, REQ_OP_READ, 0, 1); if (r) goto bad; @@ -395,7 +397,7 @@ static int write_header(struct pstore *ps) dh->version = cpu_to_le32(ps->version); dh->chunk_size = cpu_to_le32(ps->store->chunk_size); - return chunk_io(ps, ps->header_area, 0, WRITE, 1); + return chunk_io(ps, ps->header_area, 0, REQ_OP_WRITE, 0, 1); } /* @@ -739,7 +741,7 @@ static void persistent_commit_exception(struct dm_exception_store *store, /* * Commit exceptions to disk. */ - if (ps->valid && area_io(ps, WRITE_FLUSH_FUA)) + if (ps->valid && area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA)) ps->valid = 0; /* @@ -779,7 +781,7 @@ static int persistent_prepare_merge(struct dm_exception_store *store, return 0; ps->current_area--; - r = area_io(ps, READ); + r = area_io(ps, REQ_OP_READ, 0); if (r < 0) return r; ps->current_committed = ps->exceptions_per_area; @@ -816,7 +818,7 @@ static int persistent_commit_merge(struct dm_exception_store *store, for (i = 0; i < nr_merged; i++) clear_exception(ps, ps->current_committed - 1 - i); - r = area_io(ps, WRITE_FLUSH_FUA); + r = area_io(ps, REQ_OP_WRITE, WRITE_FLUSH_FUA); if (r < 0) return r; diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 797ddb9..b738178 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -292,8 +292,8 @@ static int stripe_map(struct dm_target *ti, struct bio *bio) bio->bi_bdev = sc->stripe[target_bio_nr].dev->bdev; return DM_MAPIO_REMAPPED; } - if (unlikely(bio->bi_rw & REQ_DISCARD) || - unlikely(bio->bi_rw & REQ_WRITE_SAME)) { + if (unlikely(bio_op(bio) == REQ_OP_DISCARD) || + unlikely(bio_op(bio) == REQ_OP_WRITE_SAME)) { target_bio_nr = dm_bio_get_target_bio_nr(bio); BUG_ON(target_bio_nr >= sc->stripes); return stripe_map_range(sc, bio, target_bio_nr); diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index e8661c2..1b684cb 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -371,7 +371,7 @@ static void end_discard(struct discard_op *op, int r) * need to wait for the chain to complete. */ bio_chain(op->bio, op->parent_bio); - op->bio->bi_rw = REQ_WRITE | REQ_DISCARD; + bio_set_op_attrs(op->bio, REQ_OP_DISCARD, 0); submit_bio(op->bio); } @@ -705,7 +705,7 @@ static void inc_all_io_entry(struct pool *pool, struct bio *bio) { struct dm_thin_endio_hook *h; - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) return; h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook)); @@ -868,7 +868,8 @@ static void __inc_remap_and_issue_cell(void *context, struct bio *bio; while ((bio = bio_list_pop(&cell->bios))) { - if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)) + if (bio->bi_rw & (REQ_FLUSH | REQ_FUA) || + bio_op(bio) == REQ_OP_DISCARD) bio_list_add(&info->defer_bios, bio); else { inc_all_io_entry(info->tc->pool, bio); @@ -1640,7 +1641,8 @@ static void __remap_and_issue_shared_cell(void *context, while ((bio = bio_list_pop(&cell->bios))) { if ((bio_data_dir(bio) == WRITE) || - (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA))) + (bio->bi_rw & (REQ_FLUSH | REQ_FUA) || + bio_op(bio) == REQ_OP_DISCARD)) bio_list_add(&info->defer_bios, bio); else { struct dm_thin_endio_hook *h = dm_per_bio_data(bio, sizeof(struct dm_thin_endio_hook));; @@ -2029,7 +2031,7 @@ static void process_thin_deferred_bios(struct thin_c *tc) break; } - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) pool->process_discard(tc, bio); else pool->process_bio(tc, bio); @@ -2116,7 +2118,7 @@ static void process_thin_deferred_cells(struct thin_c *tc) return; } - if (cell->holder->bi_rw & REQ_DISCARD) + if (bio_op(cell->holder) == REQ_OP_DISCARD) pool->process_discard_cell(tc, cell); else pool->process_cell(tc, cell); @@ -2554,7 +2556,8 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_SUBMITTED; } - if (bio->bi_rw & (REQ_DISCARD | REQ_FLUSH | REQ_FUA)) { + if (bio->bi_rw & (REQ_FLUSH | REQ_FUA) || + bio_op(bio) == REQ_OP_DISCARD) { thin_defer_bio_with_throttle(tc, bio); return DM_MAPIO_SUBMITTED; } diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f5ac0a3..9204a2d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1053,7 +1053,7 @@ static void clone_endio(struct bio *bio) } } - if (unlikely(r == -EREMOTEIO && (bio->bi_rw & REQ_WRITE_SAME) && + if (unlikely(r == -EREMOTEIO && (bio_op(bio) == REQ_OP_WRITE_SAME) && !bdev_get_queue(bio->bi_bdev)->limits.max_write_same_sectors)) disable_write_same(md); @@ -1748,9 +1748,9 @@ static int __split_and_process_non_flush(struct clone_info *ci) unsigned len; int r; - if (unlikely(bio->bi_rw & REQ_DISCARD)) + if (unlikely(bio_op(bio) == REQ_OP_DISCARD)) return __send_discard(ci); - else if (unlikely(bio->bi_rw & REQ_WRITE_SAME)) + else if (unlikely(bio_op(bio) == REQ_OP_WRITE_SAME)) return __send_write_same(ci); ti = dm_table_find_target(ci->map, ci->sector); @@ -2415,7 +2415,7 @@ static struct mapped_device *alloc_dev(int minor) bio_init(&md->flush_bio); md->flush_bio.bi_bdev = md->bdev; - md->flush_bio.bi_rw = WRITE_FLUSH; + bio_set_op_attrs(&md->flush_bio, REQ_OP_WRITE, WRITE_FLUSH); dm_stats_init(&md->stats); diff --git a/include/linux/dm-io.h b/include/linux/dm-io.h index a68cbe5..b91b023 100644 --- a/include/linux/dm-io.h +++ b/include/linux/dm-io.h @@ -57,7 +57,8 @@ struct dm_io_notify { */ struct dm_io_client; struct dm_io_request { - int bi_rw; /* READ|WRITE - not READA */ + int bi_op; /* REQ_OP */ + int bi_op_flags; /* rq_flag_bits */ struct dm_io_memory mem; /* Memory to use for io */ struct dm_io_notify notify; /* Synchronous if notify.fn is NULL */ struct dm_io_client *client; /* Client memory handler */ -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 93C207D15 for ; Sun, 5 Jun 2016 14:33:32 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 577FC8F8037 for ; Sun, 5 Jun 2016 12:33:32 -0700 (PDT) X-ASG-Debug-ID: 1465155210-04cb6c2db9b58e10001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id SANhGvWY5AIR6v8O (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:30 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EF652828; Sun, 5 Jun 2016 19:33:29 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9W003130; Sun, 5 Jun 2016 15:33:27 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 25/45] bcache: use bio op accessors Date: Sun, 5 Jun 2016 14:32:05 -0500 X-ASG-Orig-Subj: [PATCH 25/45] bcache: use bio op accessors Message-Id: <1465155145-10812-26-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sun, 05 Jun 2016 19:33:30 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155210 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11606 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have bcache set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie --- drivers/md/bcache/btree.c | 4 ++-- drivers/md/bcache/debug.c | 4 ++-- drivers/md/bcache/journal.c | 7 ++++--- drivers/md/bcache/movinggc.c | 2 +- drivers/md/bcache/request.c | 14 +++++++------- drivers/md/bcache/super.c | 24 +++++++++++++----------- drivers/md/bcache/writeback.c | 4 ++-- 7 files changed, 31 insertions(+), 28 deletions(-) diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index eab505e..76f7534 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -294,10 +294,10 @@ static void bch_btree_node_read(struct btree *b) closure_init_stack(&cl); bio = bch_bbio_alloc(b->c); - bio->bi_rw = REQ_META|READ_SYNC; bio->bi_iter.bi_size = KEY_SIZE(&b->key) << 9; bio->bi_end_io = btree_node_read_endio; bio->bi_private = &cl; + bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC); bch_bio_map(bio, b->keys.set[0].data); @@ -396,8 +396,8 @@ static void do_btree_node_write(struct btree *b) b->bio->bi_end_io = btree_node_write_endio; b->bio->bi_private = cl; - b->bio->bi_rw = REQ_META|WRITE_SYNC|REQ_FUA; b->bio->bi_iter.bi_size = roundup(set_bytes(i), block_bytes(b->c)); + bio_set_op_attrs(b->bio, REQ_OP_WRITE, REQ_META|WRITE_SYNC|REQ_FUA); bch_bio_map(b->bio, i); /* diff --git a/drivers/md/bcache/debug.c b/drivers/md/bcache/debug.c index 52b6bcf..c28df164 100644 --- a/drivers/md/bcache/debug.c +++ b/drivers/md/bcache/debug.c @@ -52,7 +52,7 @@ void bch_btree_verify(struct btree *b) bio->bi_bdev = PTR_CACHE(b->c, &b->key, 0)->bdev; bio->bi_iter.bi_sector = PTR_OFFSET(&b->key, 0); bio->bi_iter.bi_size = KEY_SIZE(&v->key) << 9; - bio->bi_rw = REQ_META|READ_SYNC; + bio_set_op_attrs(bio, REQ_OP_READ, REQ_META|READ_SYNC); bch_bio_map(bio, sorted); submit_bio_wait(bio); @@ -114,7 +114,7 @@ void bch_data_verify(struct cached_dev *dc, struct bio *bio) check = bio_clone(bio, GFP_NOIO); if (!check) return; - check->bi_rw |= READ_SYNC; + bio_set_op_attrs(check, REQ_OP_READ, READ_SYNC); if (bio_alloc_pages(check, GFP_NOIO)) goto out_put; diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index af3f9f7..a3c3b30 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -54,11 +54,11 @@ reread: left = ca->sb.bucket_size - offset; bio_reset(bio); bio->bi_iter.bi_sector = bucket + offset; bio->bi_bdev = ca->bdev; - bio->bi_rw = READ; bio->bi_iter.bi_size = len << 9; bio->bi_end_io = journal_read_endio; bio->bi_private = &cl; + bio_set_op_attrs(bio, REQ_OP_READ, 0); bch_bio_map(bio, data); closure_bio_submit(bio, &cl); @@ -449,10 +449,10 @@ static void do_journal_discard(struct cache *ca) atomic_set(&ja->discard_in_flight, DISCARD_IN_FLIGHT); bio_init(bio); + bio_set_op_attrs(bio, REQ_OP_DISCARD, 0); bio->bi_iter.bi_sector = bucket_to_sector(ca->set, ca->sb.d[ja->discard_idx]); bio->bi_bdev = ca->bdev; - bio->bi_rw = REQ_WRITE|REQ_DISCARD; bio->bi_max_vecs = 1; bio->bi_io_vec = bio->bi_inline_vecs; bio->bi_iter.bi_size = bucket_bytes(ca); @@ -626,11 +626,12 @@ static void journal_write_unlocked(struct closure *cl) bio_reset(bio); bio->bi_iter.bi_sector = PTR_OFFSET(k, i); bio->bi_bdev = ca->bdev; - bio->bi_rw = REQ_WRITE|REQ_SYNC|REQ_META|REQ_FLUSH|REQ_FUA; bio->bi_iter.bi_size = sectors << 9; bio->bi_end_io = journal_write_endio; bio->bi_private = w; + bio_set_op_attrs(bio, REQ_OP_WRITE, + REQ_SYNC|REQ_META|REQ_FLUSH|REQ_FUA); bch_bio_map(bio, w->data); trace_bcache_journal_write(bio); diff --git a/drivers/md/bcache/movinggc.c b/drivers/md/bcache/movinggc.c index b929fc9..1881319 100644 --- a/drivers/md/bcache/movinggc.c +++ b/drivers/md/bcache/movinggc.c @@ -163,7 +163,7 @@ static void read_moving(struct cache_set *c) moving_init(io); bio = &io->bio.bio; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); bio->bi_end_io = read_moving_endio; if (bio_alloc_pages(bio, GFP_KERNEL)) diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 6b85a23..016b0aa 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -253,7 +253,7 @@ static void bch_data_insert_start(struct closure *cl) trace_bcache_cache_insert(k); bch_keylist_push(&op->insert_keys); - n->bi_rw |= REQ_WRITE; + bio_set_op_attrs(n, REQ_OP_WRITE, 0); bch_submit_bbio(n, op->c, k, 0); } while (n != bio); @@ -378,7 +378,7 @@ static bool check_should_bypass(struct cached_dev *dc, struct bio *bio) if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags) || c->gc_stats.in_use > CUTOFF_CACHE_ADD || - (bio->bi_rw & REQ_DISCARD)) + (bio_op(bio) == REQ_OP_DISCARD)) goto skip; if (mode == CACHE_MODE_NONE || @@ -899,7 +899,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) * But check_overlapping drops dirty keys for which io hasn't started, * so we still want to call it. */ - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) s->iop.bypass = true; if (should_writeback(dc, s->orig_bio, @@ -913,7 +913,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) s->iop.bio = s->orig_bio; bio_get(s->iop.bio); - if (!(bio->bi_rw & REQ_DISCARD) || + if ((bio_op(bio) != REQ_OP_DISCARD) || blk_queue_discard(bdev_get_queue(dc->bdev))) closure_bio_submit(bio, cl); } else if (s->iop.writeback) { @@ -925,10 +925,10 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) struct bio *flush = bio_alloc_bioset(GFP_NOIO, 0, dc->disk.bio_split); - flush->bi_rw = WRITE_FLUSH; flush->bi_bdev = bio->bi_bdev; flush->bi_end_io = request_endio; flush->bi_private = cl; + bio_set_op_attrs(flush, REQ_OP_WRITE, WRITE_FLUSH); closure_bio_submit(flush, cl); } @@ -992,7 +992,7 @@ static blk_qc_t cached_dev_make_request(struct request_queue *q, cached_dev_read(dc, s); } } else { - if ((bio->bi_rw & REQ_DISCARD) && + if ((bio_op(bio) == REQ_OP_DISCARD) && !blk_queue_discard(bdev_get_queue(dc->bdev))) bio_endio(bio); else @@ -1103,7 +1103,7 @@ static blk_qc_t flash_dev_make_request(struct request_queue *q, &KEY(d->id, bio->bi_iter.bi_sector, 0), &KEY(d->id, bio_end_sector(bio), 0)); - s->iop.bypass = (bio->bi_rw & REQ_DISCARD) != 0; + s->iop.bypass = (bio_op(bio) == REQ_OP_DISCARD) != 0; s->iop.writeback = true; s->iop.bio = bio; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 1eb526a7..c944daf7 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -212,8 +212,8 @@ static void __write_super(struct cache_sb *sb, struct bio *bio) unsigned i; bio->bi_iter.bi_sector = SB_SECTOR; - bio->bi_rw = REQ_WRITE|REQ_SYNC|REQ_META; bio->bi_iter.bi_size = SB_SIZE; + bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_SYNC|REQ_META); bch_bio_map(bio, NULL); out->offset = cpu_to_le64(sb->offset); @@ -333,7 +333,7 @@ static void uuid_io_unlock(struct closure *cl) up(&c->uuid_write_mutex); } -static void uuid_io(struct cache_set *c, unsigned long rw, +static void uuid_io(struct cache_set *c, int op, unsigned long op_flags, struct bkey *k, struct closure *parent) { struct closure *cl = &c->uuid_write; @@ -348,21 +348,22 @@ static void uuid_io(struct cache_set *c, unsigned long rw, for (i = 0; i < KEY_PTRS(k); i++) { struct bio *bio = bch_bbio_alloc(c); - bio->bi_rw = REQ_SYNC|REQ_META|rw; + bio->bi_rw = REQ_SYNC|REQ_META|op_flags; bio->bi_iter.bi_size = KEY_SIZE(k) << 9; bio->bi_end_io = uuid_endio; bio->bi_private = cl; + bio_set_op_attrs(bio, op, REQ_SYNC|REQ_META|op_flags); bch_bio_map(bio, c->uuids); bch_submit_bbio(bio, c, k, i); - if (!(rw & WRITE)) + if (op != REQ_OP_WRITE) break; } bch_extent_to_text(buf, sizeof(buf), k); - pr_debug("%s UUIDs at %s", rw & REQ_WRITE ? "wrote" : "read", buf); + pr_debug("%s UUIDs at %s", op == REQ_OP_WRITE ? "wrote" : "read", buf); for (u = c->uuids; u < c->uuids + c->nr_uuids; u++) if (!bch_is_zero(u->uuid, 16)) @@ -381,7 +382,7 @@ static char *uuid_read(struct cache_set *c, struct jset *j, struct closure *cl) return "bad uuid pointer"; bkey_copy(&c->uuid_bucket, k); - uuid_io(c, READ_SYNC, k, cl); + uuid_io(c, REQ_OP_READ, READ_SYNC, k, cl); if (j->version < BCACHE_JSET_VERSION_UUIDv1) { struct uuid_entry_v0 *u0 = (void *) c->uuids; @@ -426,7 +427,7 @@ static int __uuid_write(struct cache_set *c) return 1; SET_KEY_SIZE(&k.key, c->sb.bucket_size); - uuid_io(c, REQ_WRITE, &k.key, &cl); + uuid_io(c, REQ_OP_WRITE, 0, &k.key, &cl); closure_sync(&cl); bkey_copy(&c->uuid_bucket, &k.key); @@ -498,7 +499,8 @@ static void prio_endio(struct bio *bio) closure_put(&ca->prio); } -static void prio_io(struct cache *ca, uint64_t bucket, unsigned long rw) +static void prio_io(struct cache *ca, uint64_t bucket, int op, + unsigned long op_flags) { struct closure *cl = &ca->prio; struct bio *bio = bch_bbio_alloc(ca->set); @@ -507,11 +509,11 @@ static void prio_io(struct cache *ca, uint64_t bucket, unsigned long rw) bio->bi_iter.bi_sector = bucket * ca->sb.bucket_size; bio->bi_bdev = ca->bdev; - bio->bi_rw = REQ_SYNC|REQ_META|rw; bio->bi_iter.bi_size = bucket_bytes(ca); bio->bi_end_io = prio_endio; bio->bi_private = ca; + bio_set_op_attrs(bio, op, REQ_SYNC|REQ_META|op_flags); bch_bio_map(bio, ca->disk_buckets); closure_bio_submit(bio, &ca->prio); @@ -557,7 +559,7 @@ void bch_prio_write(struct cache *ca) BUG_ON(bucket == -1); mutex_unlock(&ca->set->bucket_lock); - prio_io(ca, bucket, REQ_WRITE); + prio_io(ca, bucket, REQ_OP_WRITE, 0); mutex_lock(&ca->set->bucket_lock); ca->prio_buckets[i] = bucket; @@ -599,7 +601,7 @@ static void prio_read(struct cache *ca, uint64_t bucket) ca->prio_last_buckets[bucket_nr] = bucket; bucket_nr++; - prio_io(ca, bucket, READ_SYNC); + prio_io(ca, bucket, REQ_OP_READ, READ_SYNC); if (p->csum != bch_crc64(&p->magic, bucket_bytes(ca) - 8)) pr_warn("bad csum reading priorities"); diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 6012367..d9fd2a6 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -182,7 +182,7 @@ static void write_dirty(struct closure *cl) struct keybuf_key *w = io->bio.bi_private; dirty_init(w); - io->bio.bi_rw = WRITE; + bio_set_op_attrs(&io->bio, REQ_OP_WRITE, 0); io->bio.bi_iter.bi_sector = KEY_START(&w->key); io->bio.bi_bdev = io->dc->bdev; io->bio.bi_end_io = dirty_endio; @@ -251,10 +251,10 @@ static void read_dirty(struct cached_dev *dc) io->dc = dc; dirty_init(w); + bio_set_op_attrs(&io->bio, REQ_OP_READ, 0); io->bio.bi_iter.bi_sector = PTR_OFFSET(&w->key, 0); io->bio.bi_bdev = PTR_CACHE(dc->disk.c, &w->key, 0)->bdev; - io->bio.bi_rw = READ; io->bio.bi_end_io = read_dirty_endio; if (bio_alloc_pages(&io->bio, GFP_KERNEL)) -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id F0B527D1D for ; Sun, 5 Jun 2016 14:33:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id B25A6304048 for ; Sun, 5 Jun 2016 12:33:34 -0700 (PDT) X-ASG-Debug-ID: 1465155212-04cb6c2db9b58e20001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id sdehPZZjieg7MVZm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:33 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 319D590E55; Sun, 5 Jun 2016 19:33:32 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9X003130; Sun, 5 Jun 2016 15:33:30 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 26/45] drbd: use bio op accessors Date: Sun, 5 Jun 2016 14:32:06 -0500 X-ASG-Orig-Subj: [PATCH 26/45] drbd: use bio op accessors Message-Id: <1465155145-10812-27-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:33:32 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155212 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15185 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have drbd set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- v8: 1. Combined this patch with what was the cleanup/completion path handling patch so all bio op drbd changes are now only in this patch. drivers/block/drbd/drbd_actlog.c | 28 +++++++++++++++------------- drivers/block/drbd/drbd_bitmap.c | 6 +++--- drivers/block/drbd/drbd_int.h | 4 ++-- drivers/block/drbd/drbd_main.c | 20 +++++++++++--------- drivers/block/drbd/drbd_receiver.c | 36 ++++++++++++++++++++++++------------ drivers/block/drbd/drbd_worker.c | 7 ++++--- 6 files changed, 59 insertions(+), 42 deletions(-) diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index 6069e15..f236a31 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -137,19 +137,19 @@ void wait_until_done_or_force_detached(struct drbd_device *device, struct drbd_b static int _drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bdev, - sector_t sector, int rw) + sector_t sector, int op) { struct bio *bio; /* we do all our meta data IO in aligned 4k blocks. */ const int size = 4096; - int err; + int err, op_flags = 0; device->md_io.done = 0; device->md_io.error = -ENODEV; - if ((rw & WRITE) && !test_bit(MD_NO_FUA, &device->flags)) - rw |= REQ_FUA | REQ_FLUSH; - rw |= REQ_SYNC | REQ_NOIDLE; + if ((op == REQ_OP_WRITE) && !test_bit(MD_NO_FUA, &device->flags)) + op_flags |= REQ_FUA | REQ_FLUSH; + op_flags |= REQ_SYNC | REQ_NOIDLE; bio = bio_alloc_drbd(GFP_NOIO); bio->bi_bdev = bdev->md_bdev; @@ -159,9 +159,9 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, goto out; bio->bi_private = device; bio->bi_end_io = drbd_md_endio; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); - if (!(rw & WRITE) && device->state.disk == D_DISKLESS && device->ldev == NULL) + if (op != REQ_OP_WRITE && device->state.disk == D_DISKLESS && device->ldev == NULL) /* special case, drbd_md_read() during drbd_adm_attach(): no get_ldev */ ; else if (!get_ldev_if_state(device, D_ATTACHING)) { @@ -174,7 +174,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, bio_get(bio); /* one bio_put() is in the completion handler */ atomic_inc(&device->md_io.in_use); /* drbd_md_put_buffer() is in the completion handler */ device->md_io.submit_jif = jiffies; - if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) + if (drbd_insert_fault(device, (op == REQ_OP_WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) bio_io_error(bio); else submit_bio(bio); @@ -188,7 +188,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, } int drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bdev, - sector_t sector, int rw) + sector_t sector, int op) { int err; D_ASSERT(device, atomic_read(&device->md_io.in_use) == 1); @@ -197,19 +197,21 @@ int drbd_md_sync_page_io(struct drbd_device *device, struct drbd_backing_dev *bd dynamic_drbd_dbg(device, "meta_data io: %s [%d]:%s(,%llus,%s) %pS\n", current->comm, current->pid, __func__, - (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ", + (unsigned long long)sector, (op == REQ_OP_WRITE) ? "WRITE" : "READ", (void*)_RET_IP_ ); if (sector < drbd_md_first_sector(bdev) || sector + 7 > drbd_md_last_sector(bdev)) drbd_alert(device, "%s [%d]:%s(,%llus,%s) out of range md access!\n", current->comm, current->pid, __func__, - (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ"); + (unsigned long long)sector, + (op == REQ_OP_WRITE) ? "WRITE" : "READ"); - err = _drbd_md_sync_page_io(device, bdev, sector, rw); + err = _drbd_md_sync_page_io(device, bdev, sector, op); if (err) { drbd_err(device, "drbd_md_sync_page_io(,%llus,%s) failed with error %d\n", - (unsigned long long)sector, (rw & WRITE) ? "WRITE" : "READ", err); + (unsigned long long)sector, + (op == REQ_OP_WRITE) ? "WRITE" : "READ", err); } return err; } diff --git a/drivers/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c index e8959fe..e5d89f6 100644 --- a/drivers/block/drbd/drbd_bitmap.c +++ b/drivers/block/drbd/drbd_bitmap.c @@ -980,7 +980,7 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho struct drbd_bitmap *b = device->bitmap; struct page *page; unsigned int len; - unsigned int rw = (ctx->flags & BM_AIO_READ) ? READ : WRITE; + unsigned int op = (ctx->flags & BM_AIO_READ) ? REQ_OP_READ : REQ_OP_WRITE; sector_t on_disk_sector = device->ldev->md.md_offset + device->ldev->md.bm_offset; @@ -1011,9 +1011,9 @@ static void bm_page_io_async(struct drbd_bm_aio_ctx *ctx, int page_nr) __must_ho bio_add_page(bio, page, len, 0); bio->bi_private = ctx; bio->bi_end_io = drbd_bm_endio; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, 0); - if (drbd_insert_fault(device, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) { + if (drbd_insert_fault(device, (op == REQ_OP_WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) { bio_io_error(bio); } else { submit_bio(bio); diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 7a1cf7e..33f0b82 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -1507,7 +1507,7 @@ extern int drbd_resync_finished(struct drbd_device *device); extern void *drbd_md_get_buffer(struct drbd_device *device, const char *intent); extern void drbd_md_put_buffer(struct drbd_device *device); extern int drbd_md_sync_page_io(struct drbd_device *device, - struct drbd_backing_dev *bdev, sector_t sector, int rw); + struct drbd_backing_dev *bdev, sector_t sector, int op); extern void drbd_ov_out_of_sync_found(struct drbd_device *, sector_t, int); extern void wait_until_done_or_force_detached(struct drbd_device *device, struct drbd_backing_dev *bdev, unsigned int *done); @@ -1557,7 +1557,7 @@ extern bool drbd_rs_should_slow_down(struct drbd_device *device, sector_t sector bool throttle_if_app_is_waiting); extern int drbd_submit_peer_request(struct drbd_device *, struct drbd_peer_request *, const unsigned, - const int); + const unsigned, const int); extern int drbd_free_peer_reqs(struct drbd_device *, struct list_head *); extern struct drbd_peer_request *drbd_alloc_peer_req(struct drbd_peer_device *, u64, sector_t, unsigned int, diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 2ba1494..d55febc 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1603,15 +1603,16 @@ static int _drbd_send_zc_ee(struct drbd_peer_device *peer_device, return 0; } -static u32 bio_flags_to_wire(struct drbd_connection *connection, unsigned long bi_rw) +static u32 bio_flags_to_wire(struct drbd_connection *connection, + struct bio *bio) { if (connection->agreed_pro_version >= 95) - return (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) | - (bi_rw & REQ_FUA ? DP_FUA : 0) | - (bi_rw & REQ_FLUSH ? DP_FLUSH : 0) | - (bi_rw & REQ_DISCARD ? DP_DISCARD : 0); + return (bio->bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) | + (bio->bi_rw & REQ_FUA ? DP_FUA : 0) | + (bio->bi_rw & REQ_FLUSH ? DP_FLUSH : 0) | + (bio_op(bio) == REQ_OP_DISCARD ? DP_DISCARD : 0); else - return bi_rw & REQ_SYNC ? DP_RW_SYNC : 0; + return bio->bi_rw & REQ_SYNC ? DP_RW_SYNC : 0; } /* Used to send write or TRIM aka REQ_DISCARD requests @@ -1636,7 +1637,7 @@ int drbd_send_dblock(struct drbd_peer_device *peer_device, struct drbd_request * p->sector = cpu_to_be64(req->i.sector); p->block_id = (unsigned long)req; p->seq_num = cpu_to_be32(atomic_inc_return(&device->packet_seq)); - dp_flags = bio_flags_to_wire(peer_device->connection, req->master_bio->bi_rw); + dp_flags = bio_flags_to_wire(peer_device->connection, req->master_bio); if (device->state.conn >= C_SYNC_SOURCE && device->state.conn <= C_PAUSED_SYNC_T) dp_flags |= DP_MAY_SET_IN_SYNC; @@ -3061,7 +3062,7 @@ void drbd_md_write(struct drbd_device *device, void *b) D_ASSERT(device, drbd_md_ss(device->ldev) == device->ldev->md.md_offset); sector = device->ldev->md.md_offset; - if (drbd_md_sync_page_io(device, device->ldev, sector, WRITE)) { + if (drbd_md_sync_page_io(device, device->ldev, sector, REQ_OP_WRITE)) { /* this was a try anyways ... */ drbd_err(device, "meta data update failed!\n"); drbd_chk_io_error(device, 1, DRBD_META_IO_ERROR); @@ -3263,7 +3264,8 @@ int drbd_md_read(struct drbd_device *device, struct drbd_backing_dev *bdev) * Affects the paranoia out-of-range access check in drbd_md_sync_page_io(). */ bdev->md.md_size_sect = 8; - if (drbd_md_sync_page_io(device, bdev, bdev->md.md_offset, READ)) { + if (drbd_md_sync_page_io(device, bdev, bdev->md.md_offset, + REQ_OP_READ)) { /* NOTE: can't do normal error processing here as this is called BEFORE disk is attached */ drbd_err(device, "Error while reading metadata.\n"); diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 050aaa1..6c59978 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -1398,7 +1398,8 @@ void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backin /* TODO allocate from our own bio_set. */ int drbd_submit_peer_request(struct drbd_device *device, struct drbd_peer_request *peer_req, - const unsigned rw, const int fault_type) + const unsigned op, const unsigned op_flags, + const int fault_type) { struct bio *bios = NULL; struct bio *bio; @@ -1450,7 +1451,7 @@ next_bio: /* > peer_req->i.sector, unless this is the first bio */ bio->bi_iter.bi_sector = sector; bio->bi_bdev = device->ldev->backing_bdev; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); bio->bi_private = peer_req; bio->bi_end_io = drbd_peer_request_endio; @@ -1458,7 +1459,7 @@ next_bio: bios = bio; ++n_bios; - if (rw & REQ_DISCARD) { + if (op == REQ_OP_DISCARD) { bio->bi_iter.bi_size = data_size; goto submit; } @@ -1830,7 +1831,8 @@ static int recv_resync_read(struct drbd_peer_device *peer_device, sector_t secto spin_unlock_irq(&device->resource->req_lock); atomic_add(pi->size >> 9, &device->rs_sect_ev); - if (drbd_submit_peer_request(device, peer_req, WRITE, DRBD_FAULT_RS_WR) == 0) + if (drbd_submit_peer_request(device, peer_req, REQ_OP_WRITE, 0, + DRBD_FAULT_RS_WR) == 0) return 0; /* don't care for the reason here */ @@ -2152,12 +2154,19 @@ static int wait_for_and_update_peer_seq(struct drbd_peer_device *peer_device, co /* see also bio_flags_to_wire() * DRBD_REQ_*, because we need to semantically map the flags to data packet * flags and back. We may replicate to other kernel versions. */ -static unsigned long wire_flags_to_bio(u32 dpf) +static unsigned long wire_flags_to_bio_flags(u32 dpf) { return (dpf & DP_RW_SYNC ? REQ_SYNC : 0) | (dpf & DP_FUA ? REQ_FUA : 0) | - (dpf & DP_FLUSH ? REQ_FLUSH : 0) | - (dpf & DP_DISCARD ? REQ_DISCARD : 0); + (dpf & DP_FLUSH ? REQ_FLUSH : 0); +} + +static unsigned long wire_flags_to_bio_op(u32 dpf) +{ + if (dpf & DP_DISCARD) + return REQ_OP_DISCARD; + else + return REQ_OP_WRITE; } static void fail_postponed_requests(struct drbd_device *device, sector_t sector, @@ -2303,7 +2312,7 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info * struct drbd_peer_request *peer_req; struct p_data *p = pi->data; u32 peer_seq = be32_to_cpu(p->seq_num); - int rw = WRITE; + int op, op_flags; u32 dp_flags; int err, tp; @@ -2342,14 +2351,15 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info * peer_req->flags |= EE_APPLICATION; dp_flags = be32_to_cpu(p->dp_flags); - rw |= wire_flags_to_bio(dp_flags); + op = wire_flags_to_bio_op(dp_flags); + op_flags = wire_flags_to_bio_flags(dp_flags); if (pi->cmd == P_TRIM) { struct request_queue *q = bdev_get_queue(device->ldev->backing_bdev); peer_req->flags |= EE_IS_TRIM; if (!blk_queue_discard(q)) peer_req->flags |= EE_IS_TRIM_USE_ZEROOUT; D_ASSERT(peer_device, peer_req->i.size > 0); - D_ASSERT(peer_device, rw & REQ_DISCARD); + D_ASSERT(peer_device, op == REQ_OP_DISCARD); D_ASSERT(peer_device, peer_req->pages == NULL); } else if (peer_req->pages == NULL) { D_ASSERT(device, peer_req->i.size == 0); @@ -2433,7 +2443,8 @@ static int receive_Data(struct drbd_connection *connection, struct packet_info * peer_req->flags |= EE_CALL_AL_COMPLETE_IO; } - err = drbd_submit_peer_request(device, peer_req, rw, DRBD_FAULT_DT_WR); + err = drbd_submit_peer_request(device, peer_req, op, op_flags, + DRBD_FAULT_DT_WR); if (!err) return 0; @@ -2723,7 +2734,8 @@ submit_for_resync: submit: update_receiver_timing_details(connection, drbd_submit_peer_request); inc_unacked(device); - if (drbd_submit_peer_request(device, peer_req, READ, fault_type) == 0) + if (drbd_submit_peer_request(device, peer_req, REQ_OP_READ, 0, + fault_type) == 0) return 0; /* don't care for the reason here */ diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 4d87499..51fab97 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c @@ -174,7 +174,7 @@ void drbd_peer_request_endio(struct bio *bio) struct drbd_peer_request *peer_req = bio->bi_private; struct drbd_device *device = peer_req->peer_device->device; int is_write = bio_data_dir(bio) == WRITE; - int is_discard = !!(bio->bi_rw & REQ_DISCARD); + int is_discard = !!(bio_op(bio) == REQ_OP_DISCARD); if (bio->bi_error && __ratelimit(&drbd_ratelimit_state)) drbd_warn(device, "%s: error=%d s=%llus\n", @@ -248,7 +248,7 @@ void drbd_request_endio(struct bio *bio) /* to avoid recursion in __req_mod */ if (unlikely(bio->bi_error)) { - if (bio->bi_rw & REQ_DISCARD) + if (bio_op(bio) == REQ_OP_DISCARD) what = (bio->bi_error == -EOPNOTSUPP) ? DISCARD_COMPLETED_NOTSUPP : DISCARD_COMPLETED_WITH_ERROR; @@ -397,7 +397,8 @@ static int read_for_csum(struct drbd_peer_device *peer_device, sector_t sector, spin_unlock_irq(&device->resource->req_lock); atomic_add(size >> 9, &device->rs_sect_ev); - if (drbd_submit_peer_request(device, peer_req, READ, DRBD_FAULT_RS_RD) == 0) + if (drbd_submit_peer_request(device, peer_req, REQ_OP_READ, 0, + DRBD_FAULT_RS_RD) == 0) return 0; /* If it failed because of ENOMEM, retry should help. If it failed -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B4BAF7D23 for ; Sun, 5 Jun 2016 14:33:38 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 7B336304048 for ; Sun, 5 Jun 2016 12:33:38 -0700 (PDT) X-ASG-Debug-ID: 1465155216-04cb6c2dbbb58e30001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id ddNiUczQy9uXS8gq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:37 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id B6C1611274B; Sun, 5 Jun 2016 19:33:36 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9Z003130; Sun, 5 Jun 2016 15:33:34 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 28/45] target: use bio op accessors Date: Sun, 5 Jun 2016 14:32:08 -0500 X-ASG-Orig-Subj: [PATCH 28/45] target: use bio op accessors Message-Id: <1465155145-10812-29-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 05 Jun 2016 19:33:36 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155217 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3905 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have the target layer set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie --- drivers/target/target_core_iblock.c | 29 ++++++++++++++--------------- drivers/target/target_core_pscsi.c | 2 +- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index c25109c..22af12f 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -312,7 +312,8 @@ static void iblock_bio_done(struct bio *bio) } static struct bio * -iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num, int rw) +iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num, int op, + int op_flags) { struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev); struct bio *bio; @@ -334,7 +335,7 @@ iblock_get_bio(struct se_cmd *cmd, sector_t lba, u32 sg_num, int rw) bio->bi_private = cmd; bio->bi_end_io = &iblock_bio_done; bio->bi_iter.bi_sector = lba; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); return bio; } @@ -480,7 +481,7 @@ iblock_execute_write_same(struct se_cmd *cmd) goto fail; cmd->priv = ibr; - bio = iblock_get_bio(cmd, block_lba, 1, WRITE); + bio = iblock_get_bio(cmd, block_lba, 1, REQ_OP_WRITE, 0); if (!bio) goto fail_free_ibr; @@ -493,7 +494,8 @@ iblock_execute_write_same(struct se_cmd *cmd) while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset) != sg->length) { - bio = iblock_get_bio(cmd, block_lba, 1, WRITE); + bio = iblock_get_bio(cmd, block_lba, 1, REQ_OP_WRITE, + 0); if (!bio) goto fail_put_bios; @@ -679,8 +681,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, struct scatterlist *sg; u32 sg_num = sgl_nents; unsigned bio_cnt; - int rw = 0; - int i; + int i, op, op_flags = 0; if (data_direction == DMA_TO_DEVICE) { struct iblock_dev *ib_dev = IBLOCK_DEV(dev); @@ -689,18 +690,15 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, * Force writethrough using WRITE_FUA if a volatile write cache * is not enabled, or if initiator set the Force Unit Access bit. */ + op = REQ_OP_WRITE; if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { if (cmd->se_cmd_flags & SCF_FUA) - rw = WRITE_FUA; + op_flags = WRITE_FUA; else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) - rw = WRITE_FUA; - else - rw = WRITE; - } else { - rw = WRITE; + op_flags = WRITE_FUA; } } else { - rw = READ; + op = REQ_OP_READ; } ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); @@ -714,7 +712,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, return 0; } - bio = iblock_get_bio(cmd, block_lba, sgl_nents, rw); + bio = iblock_get_bio(cmd, block_lba, sgl_nents, op, op_flags); if (!bio) goto fail_free_ibr; @@ -738,7 +736,8 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, bio_cnt = 0; } - bio = iblock_get_bio(cmd, block_lba, sg_num, rw); + bio = iblock_get_bio(cmd, block_lba, sg_num, op, + op_flags); if (!bio) goto fail_put_bios; diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index de18790..81564c8 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -922,7 +922,7 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, goto fail; if (rw) - bio->bi_rw |= REQ_WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); pr_debug("PSCSI: Allocated bio: %p," " dir: %s nr_vecs: %d\n", bio, -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D7FB87CB8 for ; Sun, 5 Jun 2016 14:33:40 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9A0148F8037 for ; Sun, 5 Jun 2016 12:33:40 -0700 (PDT) X-ASG-Debug-ID: 1465155219-04bdf05ad5b784b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id oCFwWh8siSECBOkh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:39 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0491D3DB; Sun, 5 Jun 2016 19:33:39 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9a003130; Sun, 5 Jun 2016 15:33:36 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 29/45] xen: use bio op accessors Date: Sun, 5 Jun 2016 14:32:09 -0500 X-ASG-Orig-Subj: [PATCH 29/45] xen: use bio op accessors Message-Id: <1465155145-10812-30-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sun, 05 Jun 2016 19:33:39 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155219 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4537 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have xen set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- drivers/block/xen-blkback/blkback.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 79fe493..4a80ee7 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -501,7 +501,7 @@ static int xen_vbd_translate(struct phys_req *req, struct xen_blkif *blkif, struct xen_vbd *vbd = &blkif->vbd; int rc = -EACCES; - if ((operation != READ) && vbd->readonly) + if ((operation != REQ_OP_READ) && vbd->readonly) goto out; if (likely(req->nr_sects)) { @@ -1014,7 +1014,7 @@ static int dispatch_discard_io(struct xen_blkif_ring *ring, preq.sector_number = req->u.discard.sector_number; preq.nr_sects = req->u.discard.nr_sectors; - err = xen_vbd_translate(&preq, blkif, WRITE); + err = xen_vbd_translate(&preq, blkif, REQ_OP_WRITE); if (err) { pr_warn("access denied: DISCARD [%llu->%llu] on dev=%04x\n", preq.sector_number, @@ -1229,6 +1229,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, struct bio **biolist = pending_req->biolist; int i, nbio = 0; int operation; + int operation_flags = 0; struct blk_plug plug; bool drain = false; struct grant_page **pages = pending_req->segments; @@ -1247,17 +1248,19 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, switch (req_operation) { case BLKIF_OP_READ: ring->st_rd_req++; - operation = READ; + operation = REQ_OP_READ; break; case BLKIF_OP_WRITE: ring->st_wr_req++; - operation = WRITE_ODIRECT; + operation = REQ_OP_WRITE; + operation_flags = WRITE_ODIRECT; break; case BLKIF_OP_WRITE_BARRIER: drain = true; case BLKIF_OP_FLUSH_DISKCACHE: ring->st_f_req++; - operation = WRITE_FLUSH; + operation = REQ_OP_WRITE; + operation_flags = WRITE_FLUSH; break; default: operation = 0; /* make gcc happy */ @@ -1269,7 +1272,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, nseg = req->operation == BLKIF_OP_INDIRECT ? req->u.indirect.nr_segments : req->u.rw.nr_segments; - if (unlikely(nseg == 0 && operation != WRITE_FLUSH) || + if (unlikely(nseg == 0 && operation_flags != WRITE_FLUSH) || unlikely((req->operation != BLKIF_OP_INDIRECT) && (nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) || unlikely((req->operation == BLKIF_OP_INDIRECT) && @@ -1310,7 +1313,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, if (xen_vbd_translate(&preq, ring->blkif, operation) != 0) { pr_debug("access denied: %s of [%llu,%llu] on dev=%04x\n", - operation == READ ? "read" : "write", + operation == REQ_OP_READ ? "read" : "write", preq.sector_number, preq.sector_number + preq.nr_sects, ring->blkif->vbd.pdevice); @@ -1369,7 +1372,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; bio->bi_iter.bi_sector = preq.sector_number; - bio->bi_rw = operation; + bio_set_op_attrs(bio, operation, operation_flags); } preq.sector_number += seg[i].nsec; @@ -1377,7 +1380,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, /* This will be hit if the operation was a flush or discard. */ if (!bio) { - BUG_ON(operation != WRITE_FLUSH); + BUG_ON(operation_flags != WRITE_FLUSH); bio = bio_alloc(GFP_KERNEL, 0); if (unlikely(bio == NULL)) @@ -1387,7 +1390,7 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, bio->bi_bdev = preq.bdev; bio->bi_private = pending_req; bio->bi_end_io = end_block_io_op; - bio->bi_rw = operation; + bio_set_op_attrs(bio, operation, operation_flags); } atomic_set(&pending_req->pendcnt, nbio); @@ -1399,9 +1402,9 @@ static int dispatch_rw_block_io(struct xen_blkif_ring *ring, /* Let the I/Os go.. */ blk_finish_plug(&plug); - if (operation == READ) + if (operation == REQ_OP_READ) ring->st_rd_sect += preq.nr_sects; - else if (operation & WRITE) + else if (operation == REQ_OP_WRITE) ring->st_wr_sect += preq.nr_sects; return 0; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 085637D0E for ; Sun, 5 Jun 2016 14:33:37 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id B1014304043 for ; Sun, 5 Jun 2016 12:33:37 -0700 (PDT) X-ASG-Debug-ID: 1465155214-04bdf05ad5b784a0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id DFDkXmO2CpLi6hlI (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:34 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 76B5D7D0D9; Sun, 5 Jun 2016 19:33:34 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9Y003130; Sun, 5 Jun 2016 15:33:32 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 27/45] md: use bio op accessors Date: Sun, 5 Jun 2016 14:32:07 -0500 X-ASG-Orig-Subj: [PATCH 27/45] md: use bio op accessors Message-Id: <1465155145-10812-28-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Sun, 05 Jun 2016 19:33:34 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155214 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 27535 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Separate the op from the rq_flag_bits and have md set/get the bio using bio_set_op_attrs/bio_op. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- drivers/md/bitmap.c | 2 +- drivers/md/dm-raid.c | 5 +++-- drivers/md/linear.c | 2 +- drivers/md/md.c | 12 ++++++------ drivers/md/md.h | 3 ++- drivers/md/raid0.c | 2 +- drivers/md/raid1.c | 32 +++++++++++++++----------------- drivers/md/raid10.c | 48 +++++++++++++++++++++++------------------------- drivers/md/raid5-cache.c | 26 ++++++++++++++++---------- drivers/md/raid5.c | 40 ++++++++++++++++++++-------------------- 10 files changed, 88 insertions(+), 84 deletions(-) diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index bc6dced..6fff794 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -162,7 +162,7 @@ static int read_sb_page(struct mddev *mddev, loff_t offset, if (sync_page_io(rdev, target, roundup(size, bdev_logical_block_size(rdev->bdev)), - page, READ, true)) { + page, REQ_OP_READ, 0, true)) { page->index = index; return 0; } diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 5253274..8cbac62 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -792,7 +792,7 @@ static int read_disk_sb(struct md_rdev *rdev, int size) if (rdev->sb_loaded) return 0; - if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, 1)) { + if (!sync_page_io(rdev, 0, size, rdev->sb_page, REQ_OP_READ, 0, 1)) { DMERR("Failed to read superblock of device at position %d", rdev->raid_disk); md_error(rdev->mddev, rdev); @@ -1651,7 +1651,8 @@ static void attempt_restore_of_faulty_devices(struct raid_set *rs) for (i = 0; i < rs->md.raid_disks; i++) { r = &rs->dev[i].rdev; if (test_bit(Faulty, &r->flags) && r->sb_page && - sync_page_io(r, 0, r->sb_size, r->sb_page, READ, 1)) { + sync_page_io(r, 0, r->sb_size, r->sb_page, REQ_OP_READ, 0, + 1)) { DMINFO("Faulty %s device #%d has readable super block." " Attempting to revive it.", rs->raid_type->name, i); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index b7fe7e9..1ad3f48 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -252,7 +252,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) split->bi_iter.bi_sector = split->bi_iter.bi_sector - start_sector + data_offset; - if (unlikely((split->bi_rw & REQ_DISCARD) && + if (unlikely((bio_op(split) == REQ_OP_DISCARD) && !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) { /* Just ignore it */ bio_endio(split); diff --git a/drivers/md/md.c b/drivers/md/md.c index fb3950b..bd4844f 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -394,7 +394,7 @@ static void submit_flushes(struct work_struct *ws) bi->bi_end_io = md_end_flush; bi->bi_private = rdev; bi->bi_bdev = rdev->bdev; - bi->bi_rw = WRITE_FLUSH; + bio_set_op_attrs(bi, REQ_OP_WRITE, WRITE_FLUSH); atomic_inc(&mddev->flush_pending); submit_bio(bi); rcu_read_lock(); @@ -743,7 +743,7 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; - bio->bi_rw = WRITE_FLUSH_FUA; + bio_set_op_attrs(bio, REQ_OP_WRITE, WRITE_FLUSH_FUA); atomic_inc(&mddev->pending_writes); submit_bio(bio); @@ -756,14 +756,14 @@ void md_super_wait(struct mddev *mddev) } int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, - struct page *page, int rw, bool metadata_op) + struct page *page, int op, int op_flags, bool metadata_op) { struct bio *bio = bio_alloc_mddev(GFP_NOIO, 1, rdev->mddev); int ret; bio->bi_bdev = (metadata_op && rdev->meta_bdev) ? rdev->meta_bdev : rdev->bdev; - bio->bi_rw = rw; + bio_set_op_attrs(bio, op, op_flags); if (metadata_op) bio->bi_iter.bi_sector = sector + rdev->sb_start; else if (rdev->mddev->reshape_position != MaxSector && @@ -789,7 +789,7 @@ static int read_disk_sb(struct md_rdev *rdev, int size) if (rdev->sb_loaded) return 0; - if (!sync_page_io(rdev, 0, size, rdev->sb_page, READ, true)) + if (!sync_page_io(rdev, 0, size, rdev->sb_page, REQ_OP_READ, 0, true)) goto fail; rdev->sb_loaded = 1; return 0; @@ -1475,7 +1475,7 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ return -EINVAL; bb_sector = (long long)offset; if (!sync_page_io(rdev, bb_sector, sectors << 9, - rdev->bb_page, READ, true)) + rdev->bb_page, REQ_OP_READ, 0, true)) return -EIO; bbp = (u64 *)page_address(rdev->bb_page); rdev->badblocks.shift = sb->bblog_shift; diff --git a/drivers/md/md.h b/drivers/md/md.h index b5c4be7..2e0918f 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -618,7 +618,8 @@ extern void md_super_write(struct mddev *mddev, struct md_rdev *rdev, sector_t sector, int size, struct page *page); extern void md_super_wait(struct mddev *mddev); extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size, - struct page *page, int rw, bool metadata_op); + struct page *page, int op, int op_flags, + bool metadata_op); extern void md_do_sync(struct md_thread *thread); extern void md_new_event(struct mddev *mddev); extern int md_allow_write(struct mddev *mddev); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 34783a3..051a10c 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -488,7 +488,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) split->bi_iter.bi_sector = sector + zone->dev_start + tmp_dev->data_offset; - if (unlikely((split->bi_rw & REQ_DISCARD) && + if (unlikely((bio_op(split) == REQ_OP_DISCARD) && !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) { /* Just ignore it */ bio_endio(split); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index bc95d4d..a342723 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -759,7 +759,7 @@ static void flush_pending_writes(struct r1conf *conf) while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next; bio->bi_next = NULL; - if (unlikely((bio->bi_rw & REQ_DISCARD) && + if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) /* Just ignore it */ bio_endio(bio); @@ -1033,7 +1033,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next; bio->bi_next = NULL; - if (unlikely((bio->bi_rw & REQ_DISCARD) && + if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) /* Just ignore it */ bio_endio(bio); @@ -1053,12 +1053,11 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio) int i, disks; struct bitmap *bitmap; unsigned long flags; + const int op = bio_op(bio); const int rw = bio_data_dir(bio); const unsigned long do_sync = (bio->bi_rw & REQ_SYNC); const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); - const unsigned long do_discard = (bio->bi_rw - & (REQ_DISCARD | REQ_SECURE)); - const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); + const unsigned long do_sec = (bio->bi_rw & REQ_SECURE); struct md_rdev *blocked_rdev; struct blk_plug_cb *cb; struct raid1_plug_cb *plug = NULL; @@ -1166,7 +1165,7 @@ read_again: mirror->rdev->data_offset; read_bio->bi_bdev = mirror->rdev->bdev; read_bio->bi_end_io = raid1_end_read_request; - read_bio->bi_rw = READ | do_sync; + bio_set_op_attrs(read_bio, op, do_sync); read_bio->bi_private = r1_bio; if (max_sectors < r1_bio->sectors) { @@ -1376,8 +1375,7 @@ read_again: conf->mirrors[i].rdev->data_offset); mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = raid1_end_write_request; - mbio->bi_rw = - WRITE | do_flush_fua | do_sync | do_discard | do_same; + bio_set_op_attrs(mbio, op, do_flush_fua | do_sync | do_sec); mbio->bi_private = r1_bio; atomic_inc(&r1_bio->remaining); @@ -1771,7 +1769,7 @@ static void end_sync_write(struct bio *bio) static int r1_sync_page_io(struct md_rdev *rdev, sector_t sector, int sectors, struct page *page, int rw) { - if (sync_page_io(rdev, sector, sectors << 9, page, rw, false)) + if (sync_page_io(rdev, sector, sectors << 9, page, rw, 0, false)) /* success */ return 1; if (rw == WRITE) { @@ -1825,7 +1823,7 @@ static int fix_sync_read_error(struct r1bio *r1_bio) rdev = conf->mirrors[d].rdev; if (sync_page_io(rdev, sect, s<<9, bio->bi_io_vec[idx].bv_page, - READ, false)) { + REQ_OP_READ, 0, false)) { success = 1; break; } @@ -2030,7 +2028,7 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio) !test_bit(MD_RECOVERY_SYNC, &mddev->recovery)))) continue; - wbio->bi_rw = WRITE; + bio_set_op_attrs(wbio, REQ_OP_WRITE, 0); wbio->bi_end_io = end_sync_write; atomic_inc(&r1_bio->remaining); md_sync_acct(conf->mirrors[i].rdev->bdev, bio_sectors(wbio)); @@ -2090,7 +2088,7 @@ static void fix_read_error(struct r1conf *conf, int read_disk, is_badblock(rdev, sect, s, &first_bad, &bad_sectors) == 0 && sync_page_io(rdev, sect, s<<9, - conf->tmppage, READ, false)) + conf->tmppage, REQ_OP_READ, 0, false)) success = 1; else { d++; @@ -2201,7 +2199,7 @@ static int narrow_write_error(struct r1bio *r1_bio, int i) wbio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev); } - wbio->bi_rw = WRITE; + bio_set_op_attrs(wbio, REQ_OP_WRITE, 0); wbio->bi_iter.bi_sector = r1_bio->sector; wbio->bi_iter.bi_size = r1_bio->sectors << 9; @@ -2344,7 +2342,7 @@ read_more: bio->bi_iter.bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_bdev = rdev->bdev; bio->bi_end_io = raid1_end_read_request; - bio->bi_rw = READ | do_sync; + bio_set_op_attrs(bio, REQ_OP_READ, do_sync); bio->bi_private = r1_bio; if (max_sectors < r1_bio->sectors) { /* Drat - have to split this up more */ @@ -2572,7 +2570,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, if (i < conf->raid_disks) still_degraded = 1; } else if (!test_bit(In_sync, &rdev->flags)) { - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_end_io = end_sync_write; write_targets ++; } else { @@ -2599,7 +2597,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, if (disk < 0) disk = i; } - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); bio->bi_end_io = end_sync_read; read_targets++; } else if (!test_bit(WriteErrorSeen, &rdev->flags) && @@ -2611,7 +2609,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr, * if we are doing resync or repair. Otherwise, leave * this device alone for this sync request. */ - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_end_io = end_sync_write; write_targets++; } diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 0be6497..615045a 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -865,7 +865,7 @@ static void flush_pending_writes(struct r10conf *conf) while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next; bio->bi_next = NULL; - if (unlikely((bio->bi_rw & REQ_DISCARD) && + if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) /* Just ignore it */ bio_endio(bio); @@ -1041,7 +1041,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next; bio->bi_next = NULL; - if (unlikely((bio->bi_rw & REQ_DISCARD) && + if (unlikely((bio_op(bio) == REQ_OP_DISCARD) && !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) /* Just ignore it */ bio_endio(bio); @@ -1058,12 +1058,11 @@ static void __make_request(struct mddev *mddev, struct bio *bio) struct r10bio *r10_bio; struct bio *read_bio; int i; + const int op = bio_op(bio); const int rw = bio_data_dir(bio); const unsigned long do_sync = (bio->bi_rw & REQ_SYNC); const unsigned long do_fua = (bio->bi_rw & REQ_FUA); - const unsigned long do_discard = (bio->bi_rw - & (REQ_DISCARD | REQ_SECURE)); - const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); + const unsigned long do_sec = (bio->bi_rw & REQ_SECURE); unsigned long flags; struct md_rdev *blocked_rdev; struct blk_plug_cb *cb; @@ -1156,7 +1155,7 @@ read_again: choose_data_offset(r10_bio, rdev); read_bio->bi_bdev = rdev->bdev; read_bio->bi_end_io = raid10_end_read_request; - read_bio->bi_rw = READ | do_sync; + bio_set_op_attrs(read_bio, op, do_sync); read_bio->bi_private = r10_bio; if (max_sectors < r10_bio->sectors) { @@ -1363,8 +1362,7 @@ retry_write: rdev)); mbio->bi_bdev = rdev->bdev; mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = - WRITE | do_sync | do_fua | do_discard | do_same; + bio_set_op_attrs(mbio, op, do_sync | do_fua | do_sec); mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); @@ -1406,8 +1404,7 @@ retry_write: r10_bio, rdev)); mbio->bi_bdev = rdev->bdev; mbio->bi_end_io = raid10_end_write_request; - mbio->bi_rw = - WRITE | do_sync | do_fua | do_discard | do_same; + bio_set_op_attrs(mbio, op, do_sync | do_fua | do_sec); mbio->bi_private = r10_bio; atomic_inc(&r10_bio->remaining); @@ -1992,10 +1989,10 @@ static void sync_request_write(struct mddev *mddev, struct r10bio *r10_bio) tbio->bi_vcnt = vcnt; tbio->bi_iter.bi_size = fbio->bi_iter.bi_size; - tbio->bi_rw = WRITE; tbio->bi_private = r10_bio; tbio->bi_iter.bi_sector = r10_bio->devs[i].addr; tbio->bi_end_io = end_sync_write; + bio_set_op_attrs(tbio, REQ_OP_WRITE, 0); bio_copy_data(tbio, fbio); @@ -2078,7 +2075,7 @@ static void fix_recovery_read_error(struct r10bio *r10_bio) addr, s << 9, bio->bi_io_vec[idx].bv_page, - READ, false); + REQ_OP_READ, 0, false); if (ok) { rdev = conf->mirrors[dw].rdev; addr = r10_bio->devs[1].addr + sect; @@ -2086,7 +2083,7 @@ static void fix_recovery_read_error(struct r10bio *r10_bio) addr, s << 9, bio->bi_io_vec[idx].bv_page, - WRITE, false); + REQ_OP_WRITE, 0, false); if (!ok) { set_bit(WriteErrorSeen, &rdev->flags); if (!test_and_set_bit(WantReplacement, @@ -2213,7 +2210,7 @@ static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector, if (is_badblock(rdev, sector, sectors, &first_bad, &bad_sectors) && (rw == READ || test_bit(WriteErrorSeen, &rdev->flags))) return -1; - if (sync_page_io(rdev, sector, sectors << 9, page, rw, false)) + if (sync_page_io(rdev, sector, sectors << 9, page, rw, 0, false)) /* success */ return 1; if (rw == WRITE) { @@ -2299,7 +2296,8 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10 r10_bio->devs[sl].addr + sect, s<<9, - conf->tmppage, READ, false); + conf->tmppage, + REQ_OP_READ, 0, false); rdev_dec_pending(rdev, mddev); rcu_read_lock(); if (success) @@ -2474,7 +2472,7 @@ static int narrow_write_error(struct r10bio *r10_bio, int i) choose_data_offset(r10_bio, rdev) + (sector - r10_bio->sector)); wbio->bi_bdev = rdev->bdev; - wbio->bi_rw = WRITE; + bio_set_op_attrs(wbio, REQ_OP_WRITE, 0); if (submit_bio_wait(wbio) < 0) /* Failure! */ @@ -2550,7 +2548,7 @@ read_more: bio->bi_iter.bi_sector = r10_bio->devs[slot].addr + choose_data_offset(r10_bio, rdev); bio->bi_bdev = rdev->bdev; - bio->bi_rw = READ | do_sync; + bio_set_op_attrs(bio, REQ_OP_READ, do_sync); bio->bi_private = r10_bio; bio->bi_end_io = raid10_end_read_request; if (max_sectors < r10_bio->sectors) { @@ -3040,7 +3038,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_read; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); from_addr = r10_bio->devs[j].addr; bio->bi_iter.bi_sector = from_addr + rdev->data_offset; @@ -3066,7 +3064,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_write; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_iter.bi_sector = to_addr + rdev->data_offset; bio->bi_bdev = rdev->bdev; @@ -3095,7 +3093,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_write; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_iter.bi_sector = to_addr + rdev->data_offset; bio->bi_bdev = rdev->bdev; @@ -3215,7 +3213,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_read; - bio->bi_rw = READ; + bio_set_op_attrs(bio, REQ_OP_READ, 0); bio->bi_iter.bi_sector = sector + conf->mirrors[d].rdev->data_offset; bio->bi_bdev = conf->mirrors[d].rdev->bdev; @@ -3237,7 +3235,7 @@ static sector_t raid10_sync_request(struct mddev *mddev, sector_t sector_nr, biolist = bio; bio->bi_private = r10_bio; bio->bi_end_io = end_sync_write; - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_iter.bi_sector = sector + conf->mirrors[d].replacement->data_offset; bio->bi_bdev = conf->mirrors[d].replacement->bdev; @@ -4322,7 +4320,7 @@ read_more: + rdev->data_offset); read_bio->bi_private = r10_bio; read_bio->bi_end_io = end_sync_read; - read_bio->bi_rw = READ; + bio_set_op_attrs(read_bio, REQ_OP_READ, 0); read_bio->bi_flags &= (~0UL << BIO_RESET_BITS); read_bio->bi_error = 0; read_bio->bi_vcnt = 0; @@ -4356,7 +4354,7 @@ read_more: rdev2->new_data_offset; b->bi_private = r10_bio; b->bi_end_io = end_reshape_write; - b->bi_rw = WRITE; + bio_set_op_attrs(b, REQ_OP_WRITE, 0); b->bi_next = blist; blist = b; } @@ -4524,7 +4522,7 @@ static int handle_reshape_read_error(struct mddev *mddev, addr, s << 9, bvec[idx].bv_page, - READ, false); + REQ_OP_READ, 0, false); if (success) break; failed: diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 0b01453..9265138 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -261,7 +261,7 @@ static struct bio *r5l_bio_alloc(struct r5l_log *log) { struct bio *bio = bio_alloc_bioset(GFP_NOIO, BIO_MAX_PAGES, log->bs); - bio->bi_rw = WRITE; + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); bio->bi_bdev = log->rdev->bdev; bio->bi_iter.bi_sector = log->rdev->data_offset + log->log_start; @@ -686,7 +686,7 @@ void r5l_flush_stripe_to_raid(struct r5l_log *log) bio_reset(&log->flush_bio); log->flush_bio.bi_bdev = log->rdev->bdev; log->flush_bio.bi_end_io = r5l_log_flush_endio; - log->flush_bio.bi_rw = WRITE_FLUSH; + bio_set_op_attrs(&log->flush_bio, REQ_OP_WRITE, WRITE_FLUSH); submit_bio(&log->flush_bio); } @@ -882,7 +882,8 @@ static int r5l_read_meta_block(struct r5l_log *log, struct r5l_meta_block *mb; u32 crc, stored_crc; - if (!sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page, READ, false)) + if (!sync_page_io(log->rdev, ctx->pos, PAGE_SIZE, page, REQ_OP_READ, 0, + false)) return -EIO; mb = page_address(page); @@ -927,7 +928,8 @@ static int r5l_recovery_flush_one_stripe(struct r5l_log *log, &disk_index, sh); sync_page_io(log->rdev, *log_offset, PAGE_SIZE, - sh->dev[disk_index].page, READ, false); + sh->dev[disk_index].page, REQ_OP_READ, 0, + false); sh->dev[disk_index].log_checksum = le32_to_cpu(payload->checksum[0]); set_bit(R5_Wantwrite, &sh->dev[disk_index].flags); @@ -935,7 +937,8 @@ static int r5l_recovery_flush_one_stripe(struct r5l_log *log, } else { disk_index = sh->pd_idx; sync_page_io(log->rdev, *log_offset, PAGE_SIZE, - sh->dev[disk_index].page, READ, false); + sh->dev[disk_index].page, REQ_OP_READ, 0, + false); sh->dev[disk_index].log_checksum = le32_to_cpu(payload->checksum[0]); set_bit(R5_Wantwrite, &sh->dev[disk_index].flags); @@ -945,7 +948,7 @@ static int r5l_recovery_flush_one_stripe(struct r5l_log *log, sync_page_io(log->rdev, r5l_ring_add(log, *log_offset, BLOCK_SECTORS), PAGE_SIZE, sh->dev[disk_index].page, - READ, false); + REQ_OP_READ, 0, false); sh->dev[disk_index].log_checksum = le32_to_cpu(payload->checksum[1]); set_bit(R5_Wantwrite, @@ -987,11 +990,13 @@ static int r5l_recovery_flush_one_stripe(struct r5l_log *log, rdev = rcu_dereference(conf->disks[disk_index].rdev); if (rdev) sync_page_io(rdev, stripe_sect, PAGE_SIZE, - sh->dev[disk_index].page, WRITE, false); + sh->dev[disk_index].page, REQ_OP_WRITE, 0, + false); rrdev = rcu_dereference(conf->disks[disk_index].replacement); if (rrdev) sync_page_io(rrdev, stripe_sect, PAGE_SIZE, - sh->dev[disk_index].page, WRITE, false); + sh->dev[disk_index].page, REQ_OP_WRITE, 0, + false); } raid5_release_stripe(sh); return 0; @@ -1063,7 +1068,8 @@ static int r5l_log_write_empty_meta_block(struct r5l_log *log, sector_t pos, crc = crc32c_le(log->uuid_checksum, mb, PAGE_SIZE); mb->checksum = cpu_to_le32(crc); - if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, WRITE_FUA, false)) { + if (!sync_page_io(log->rdev, pos, PAGE_SIZE, page, REQ_OP_WRITE, + WRITE_FUA, false)) { __free_page(page); return -EIO; } @@ -1138,7 +1144,7 @@ static int r5l_load_log(struct r5l_log *log) if (!page) return -ENOMEM; - if (!sync_page_io(rdev, cp, PAGE_SIZE, page, READ, false)) { + if (!sync_page_io(rdev, cp, PAGE_SIZE, page, REQ_OP_READ, 0, false)) { ret = -EIO; goto ioerr; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 8959e6d..e35c163 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -806,7 +806,8 @@ static void stripe_add_to_batch_list(struct r5conf *conf, struct stripe_head *sh dd_idx = 0; while (dd_idx == sh->pd_idx || dd_idx == sh->qd_idx) dd_idx++; - if (head->dev[dd_idx].towrite->bi_rw != sh->dev[dd_idx].towrite->bi_rw) + if (head->dev[dd_idx].towrite->bi_rw != sh->dev[dd_idx].towrite->bi_rw || + bio_op(head->dev[dd_idx].towrite) != bio_op(sh->dev[dd_idx].towrite)) goto unlock_out; if (head->batch_head) { @@ -891,29 +892,28 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) if (r5l_write_stripe(conf->log, sh) == 0) return; for (i = disks; i--; ) { - int rw; + int op, op_flags = 0; int replace_only = 0; struct bio *bi, *rbi; struct md_rdev *rdev, *rrdev = NULL; sh = head_sh; if (test_and_clear_bit(R5_Wantwrite, &sh->dev[i].flags)) { + op = REQ_OP_WRITE; if (test_and_clear_bit(R5_WantFUA, &sh->dev[i].flags)) - rw = WRITE_FUA; - else - rw = WRITE; + op_flags = WRITE_FUA; if (test_bit(R5_Discard, &sh->dev[i].flags)) - rw |= REQ_DISCARD; + op = REQ_OP_DISCARD; } else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags)) - rw = READ; + op = REQ_OP_READ; else if (test_and_clear_bit(R5_WantReplace, &sh->dev[i].flags)) { - rw = WRITE; + op = REQ_OP_WRITE; replace_only = 1; } else continue; if (test_and_clear_bit(R5_SyncIO, &sh->dev[i].flags)) - rw |= REQ_SYNC; + op_flags |= REQ_SYNC; again: bi = &sh->dev[i].req; @@ -927,7 +927,7 @@ again: rdev = rrdev; rrdev = NULL; } - if (rw & WRITE) { + if (op_is_write(op)) { if (replace_only) rdev = NULL; if (rdev == rrdev) @@ -953,7 +953,7 @@ again: * need to check for writes. We never accept write errors * on the replacement, so we don't to check rrdev. */ - while ((rw & WRITE) && rdev && + while (op_is_write(op) && rdev && test_bit(WriteErrorSeen, &rdev->flags)) { sector_t first_bad; int bad_sectors; @@ -995,8 +995,8 @@ again: bio_reset(bi); bi->bi_bdev = rdev->bdev; - bi->bi_rw = rw; - bi->bi_end_io = (rw & WRITE) + bio_set_op_attrs(bi, op, op_flags); + bi->bi_end_io = op_is_write(op) ? raid5_end_write_request : raid5_end_read_request; bi->bi_private = sh; @@ -1027,7 +1027,7 @@ again: * If this is discard request, set bi_vcnt 0. We don't * want to confuse SCSI because SCSI will replace payload */ - if (rw & REQ_DISCARD) + if (op == REQ_OP_DISCARD) bi->bi_vcnt = 0; if (rrdev) set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags); @@ -1047,8 +1047,8 @@ again: bio_reset(rbi); rbi->bi_bdev = rrdev->bdev; - rbi->bi_rw = rw; - BUG_ON(!(rw & WRITE)); + bio_set_op_attrs(rbi, op, op_flags); + BUG_ON(!op_is_write(op)); rbi->bi_end_io = raid5_end_write_request; rbi->bi_private = sh; @@ -1076,7 +1076,7 @@ again: * If this is discard request, set bi_vcnt 0. We don't * want to confuse SCSI because SCSI will replace payload */ - if (rw & REQ_DISCARD) + if (op == REQ_OP_DISCARD) rbi->bi_vcnt = 0; if (conf->mddev->gendisk) trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev), @@ -1085,7 +1085,7 @@ again: generic_make_request(rbi); } if (!rdev && !rrdev) { - if (rw & WRITE) + if (op_is_write(op)) set_bit(STRIPE_DEGRADED, &sh->state); pr_debug("skip op %ld on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); @@ -1623,7 +1623,7 @@ again: set_bit(R5_WantFUA, &dev->flags); if (wbi->bi_rw & REQ_SYNC) set_bit(R5_SyncIO, &dev->flags); - if (wbi->bi_rw & REQ_DISCARD) + if (bio_op(wbi) == REQ_OP_DISCARD) set_bit(R5_Discard, &dev->flags); else { tx = async_copy_data(1, wbi, &dev->page, @@ -5176,7 +5176,7 @@ static void raid5_make_request(struct mddev *mddev, struct bio * bi) return; } - if (unlikely(bi->bi_rw & REQ_DISCARD)) { + if (unlikely(bio_op(bi) == REQ_OP_DISCARD)) { make_discard_request(mddev, bi); return; } -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 201FA7CA6 for ; Sun, 5 Jun 2016 14:33:43 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id D99868F8037 for ; Sun, 5 Jun 2016 12:33:42 -0700 (PDT) X-ASG-Debug-ID: 1465155221-04cb6c2dbab58e30001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id Yg2TAcUTYoudRppR (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:42 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4925EA793; Sun, 5 Jun 2016 19:33:41 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9b003130; Sun, 5 Jun 2016 15:33:39 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 30/45] block: copy bio op to request op Date: Sun, 5 Jun 2016 14:32:10 -0500 X-ASG-Orig-Subj: [PATCH 30/45] block: copy bio op to request op Message-Id: <1465155145-10812-31-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sun, 05 Jun 2016 19:33:41 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155221 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1275 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie The bio users should now always be setting up the bio op. This patch has the block layer copy that to the request. Signed-off-by: Mike Christie --- block/blk-core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 7e943dc..3c45254 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2976,8 +2976,7 @@ EXPORT_SYMBOL_GPL(__blk_end_request_err); void blk_rq_bio_prep(struct request_queue *q, struct request *rq, struct bio *bio) { - /* Bit 0 (R/W) is identical in rq->cmd_flags and bio->bi_rw */ - rq->cmd_flags |= bio->bi_rw & REQ_WRITE; + req_set_op(rq, bio_op(bio)); if (bio_has_data(bio)) rq->nr_phys_segments = bio_phys_segments(q, bio); @@ -3062,7 +3061,8 @@ EXPORT_SYMBOL_GPL(blk_rq_unprep_clone); static void __blk_rq_prep_clone(struct request *dst, struct request *src) { dst->cpu = src->cpu; - dst->cmd_flags |= (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE; + req_set_op_attrs(dst, req_op(src), + (src->cmd_flags & REQ_CLONE_MASK) | REQ_NOMERGE); dst->cmd_type = src->cmd_type; dst->__sector = blk_rq_pos(src); dst->__data_len = blk_rq_bytes(src); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4B3DA7D2F for ; Sun, 5 Jun 2016 14:33:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id C4F96AC003 for ; Sun, 5 Jun 2016 12:33:45 -0700 (PDT) X-ASG-Debug-ID: 1465155223-04cb6c2dbbb58e40001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id D342CXBqD5J0BjyM (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:44 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8C5B7C01605A; Sun, 5 Jun 2016 19:33:43 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9c003130; Sun, 5 Jun 2016 15:33:41 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 31/45] block: prepare request creation/destruction code to use REQ_OPs Date: Sun, 5 Jun 2016 14:32:11 -0500 X-ASG-Orig-Subj: [PATCH 31/45] block: prepare request creation/destruction code to use REQ_OPs Message-Id: <1465155145-10812-32-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sun, 05 Jun 2016 19:33:43 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155224 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7709 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch prepares *_get_request/*_put_request and freed_request, to use separate variables for the operation and flags. In the next patches the struct request users will be converted like was done for bios where the op and flags are set separately. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/blk-core.c | 54 +++++++++++++++++++++++++++++------------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 3c45254..a68dc07 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -959,10 +959,10 @@ static void __freed_request(struct request_list *rl, int sync) * A request has just been released. Account for it, update the full and * congestion status, wake up any waiters. Called under q->queue_lock. */ -static void freed_request(struct request_list *rl, unsigned int flags) +static void freed_request(struct request_list *rl, int op, unsigned int flags) { struct request_queue *q = rl->q; - int sync = rw_is_sync(flags); + int sync = rw_is_sync(op | flags); q->nr_rqs[sync]--; rl->count[sync]--; @@ -1054,7 +1054,8 @@ static struct io_context *rq_ioc(struct bio *bio) /** * __get_request - get a free request * @rl: request list to allocate from - * @rw_flags: RW and SYNC flags + * @op: REQ_OP_READ/REQ_OP_WRITE + * @op_flags: rq_flag_bits * @bio: bio to allocate request for (can be %NULL) * @gfp_mask: allocation mask * @@ -1065,21 +1066,22 @@ static struct io_context *rq_ioc(struct bio *bio) * Returns ERR_PTR on failure, with @q->queue_lock held. * Returns request pointer on success, with @q->queue_lock *not held*. */ -static struct request *__get_request(struct request_list *rl, int rw_flags, - struct bio *bio, gfp_t gfp_mask) +static struct request *__get_request(struct request_list *rl, int op, + int op_flags, struct bio *bio, + gfp_t gfp_mask) { struct request_queue *q = rl->q; struct request *rq; struct elevator_type *et = q->elevator->type; struct io_context *ioc = rq_ioc(bio); struct io_cq *icq = NULL; - const bool is_sync = rw_is_sync(rw_flags) != 0; + const bool is_sync = rw_is_sync(op | op_flags) != 0; int may_queue; if (unlikely(blk_queue_dying(q))) return ERR_PTR(-ENODEV); - may_queue = elv_may_queue(q, rw_flags); + may_queue = elv_may_queue(q, op | op_flags); if (may_queue == ELV_MQUEUE_NO) goto rq_starved; @@ -1123,7 +1125,7 @@ static struct request *__get_request(struct request_list *rl, int rw_flags, /* * Decide whether the new request will be managed by elevator. If - * so, mark @rw_flags and increment elvpriv. Non-zero elvpriv will + * so, mark @op_flags and increment elvpriv. Non-zero elvpriv will * prevent the current elevator from being destroyed until the new * request is freed. This guarantees icq's won't be destroyed and * makes creating new ones safe. @@ -1132,14 +1134,14 @@ static struct request *__get_request(struct request_list *rl, int rw_flags, * it will be created after releasing queue_lock. */ if (blk_rq_should_init_elevator(bio) && !blk_queue_bypass(q)) { - rw_flags |= REQ_ELVPRIV; + op_flags |= REQ_ELVPRIV; q->nr_rqs_elvpriv++; if (et->icq_cache && ioc) icq = ioc_lookup_icq(ioc, q); } if (blk_queue_io_stat(q)) - rw_flags |= REQ_IO_STAT; + op_flags |= REQ_IO_STAT; spin_unlock_irq(q->queue_lock); /* allocate and init request */ @@ -1149,10 +1151,10 @@ static struct request *__get_request(struct request_list *rl, int rw_flags, blk_rq_init(q, rq); blk_rq_set_rl(rq, rl); - rq->cmd_flags = rw_flags | REQ_ALLOCED; + req_set_op_attrs(rq, op, op_flags | REQ_ALLOCED); /* init elvpriv */ - if (rw_flags & REQ_ELVPRIV) { + if (op_flags & REQ_ELVPRIV) { if (unlikely(et->icq_cache && !icq)) { if (ioc) icq = ioc_create_icq(ioc, q, gfp_mask); @@ -1178,7 +1180,7 @@ out: if (ioc_batching(q, ioc)) ioc->nr_batch_requests--; - trace_block_getrq(q, bio, rw_flags & 1); + trace_block_getrq(q, bio, op); return rq; fail_elvpriv: @@ -1208,7 +1210,7 @@ fail_alloc: * queue, but this is pretty rare. */ spin_lock_irq(q->queue_lock); - freed_request(rl, rw_flags); + freed_request(rl, op, op_flags); /* * in the very unlikely event that allocation failed and no @@ -1226,7 +1228,8 @@ rq_starved: /** * get_request - get a free request * @q: request_queue to allocate request from - * @rw_flags: RW and SYNC flags + * @op: REQ_OP_READ/REQ_OP_WRITE + * @op_flags: rq_flag_bits * @bio: bio to allocate request for (can be %NULL) * @gfp_mask: allocation mask * @@ -1237,17 +1240,18 @@ rq_starved: * Returns ERR_PTR on failure, with @q->queue_lock held. * Returns request pointer on success, with @q->queue_lock *not held*. */ -static struct request *get_request(struct request_queue *q, int rw_flags, - struct bio *bio, gfp_t gfp_mask) +static struct request *get_request(struct request_queue *q, int op, + int op_flags, struct bio *bio, + gfp_t gfp_mask) { - const bool is_sync = rw_is_sync(rw_flags) != 0; + const bool is_sync = rw_is_sync(op | op_flags) != 0; DEFINE_WAIT(wait); struct request_list *rl; struct request *rq; rl = blk_get_rl(q, bio); /* transferred to @rq on success */ retry: - rq = __get_request(rl, rw_flags, bio, gfp_mask); + rq = __get_request(rl, op, op_flags, bio, gfp_mask); if (!IS_ERR(rq)) return rq; @@ -1260,7 +1264,7 @@ retry: prepare_to_wait_exclusive(&rl->wait[is_sync], &wait, TASK_UNINTERRUPTIBLE); - trace_block_sleeprq(q, bio, rw_flags & 1); + trace_block_sleeprq(q, bio, op); spin_unlock_irq(q->queue_lock); io_schedule(); @@ -1289,7 +1293,7 @@ static struct request *blk_old_get_request(struct request_queue *q, int rw, create_io_context(gfp_mask, q->node); spin_lock_irq(q->queue_lock); - rq = get_request(q, rw, NULL, gfp_mask); + rq = get_request(q, rw, 0, NULL, gfp_mask); if (IS_ERR(rq)) spin_unlock_irq(q->queue_lock); /* q->queue_lock is unlocked at this point */ @@ -1491,13 +1495,14 @@ void __blk_put_request(struct request_queue *q, struct request *req) */ if (req->cmd_flags & REQ_ALLOCED) { unsigned int flags = req->cmd_flags; + int op = req_op(req); struct request_list *rl = blk_rq_rl(req); BUG_ON(!list_empty(&req->queuelist)); BUG_ON(ELV_ON_HASH(req)); blk_free_request(rl, req); - freed_request(rl, flags); + freed_request(rl, op, flags); blk_put_rl(rl); } } @@ -1712,7 +1717,7 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio) { const bool sync = !!(bio->bi_rw & REQ_SYNC); struct blk_plug *plug; - int el_ret, rw_flags, where = ELEVATOR_INSERT_SORT; + int el_ret, rw_flags = 0, where = ELEVATOR_INSERT_SORT; struct request *req; unsigned int request_count = 0; @@ -1772,7 +1777,6 @@ get_rq: * but we need to set it earlier to expose the sync flag to the * rq allocator and io schedulers. */ - rw_flags = bio_data_dir(bio); if (sync) rw_flags |= REQ_SYNC; @@ -1780,7 +1784,7 @@ get_rq: * Grab a free request. This is might sleep but can not fail. * Returns with the queue unlocked. */ - req = get_request(q, rw_flags, bio, GFP_NOIO); + req = get_request(q, bio_data_dir(bio), rw_flags, bio, GFP_NOIO); if (IS_ERR(req)) { bio->bi_error = PTR_ERR(req); bio_endio(bio); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 7A7347CAE for ; Sun, 5 Jun 2016 14:33:47 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3A729304043 for ; Sun, 5 Jun 2016 12:33:47 -0700 (PDT) X-ASG-Debug-ID: 1465155226-04bdf05ad7b784c0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id fghsyZzgOlrUUgQZ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:46 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CD3E88B135; Sun, 5 Jun 2016 19:33:45 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9d003130; Sun, 5 Jun 2016 15:33:43 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 32/45] block: prepare mq request creation to use REQ_OPs Date: Sun, 5 Jun 2016 14:32:12 -0500 X-ASG-Orig-Subj: [PATCH 32/45] block: prepare mq request creation to use REQ_OPs Message-Id: <1465155145-10812-33-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sun, 05 Jun 2016 19:33:45 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155226 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4161 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch modifies the blk mq request creation code to use separate variables for the operation and flags, because in the the next patches the struct request users will be converted like was done for bios. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/blk-mq.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/block/blk-mq.c b/block/blk-mq.c index 29cbc1b..3393f29 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -159,16 +159,17 @@ bool blk_mq_can_queue(struct blk_mq_hw_ctx *hctx) EXPORT_SYMBOL(blk_mq_can_queue); static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, - struct request *rq, unsigned int rw_flags) + struct request *rq, int op, + unsigned int op_flags) { if (blk_queue_io_stat(q)) - rw_flags |= REQ_IO_STAT; + op_flags |= REQ_IO_STAT; INIT_LIST_HEAD(&rq->queuelist); /* csd/requeue_work/fifo_time is initialized before use */ rq->q = q; rq->mq_ctx = ctx; - rq->cmd_flags |= rw_flags; + req_set_op_attrs(rq, op, op_flags); /* do not touch atomic flags, it needs atomic ops against the timer */ rq->cpu = -1; INIT_HLIST_NODE(&rq->hash); @@ -203,11 +204,11 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, rq->end_io_data = NULL; rq->next_rq = NULL; - ctx->rq_dispatched[rw_is_sync(rw_flags)]++; + ctx->rq_dispatched[rw_is_sync(op | op_flags)]++; } static struct request * -__blk_mq_alloc_request(struct blk_mq_alloc_data *data, int rw) +__blk_mq_alloc_request(struct blk_mq_alloc_data *data, int op, int op_flags) { struct request *rq; unsigned int tag; @@ -222,7 +223,7 @@ __blk_mq_alloc_request(struct blk_mq_alloc_data *data, int rw) } rq->tag = tag; - blk_mq_rq_ctx_init(data->q, data->ctx, rq, rw); + blk_mq_rq_ctx_init(data->q, data->ctx, rq, op, op_flags); return rq; } @@ -246,7 +247,7 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw, hctx = q->mq_ops->map_queue(q, ctx->cpu); blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx); - rq = __blk_mq_alloc_request(&alloc_data, rw); + rq = __blk_mq_alloc_request(&alloc_data, rw, 0); if (!rq && !(flags & BLK_MQ_REQ_NOWAIT)) { __blk_mq_run_hw_queue(hctx); blk_mq_put_ctx(ctx); @@ -254,7 +255,7 @@ struct request *blk_mq_alloc_request(struct request_queue *q, int rw, ctx = blk_mq_get_ctx(q); hctx = q->mq_ops->map_queue(q, ctx->cpu); blk_mq_set_alloc_data(&alloc_data, q, flags, ctx, hctx); - rq = __blk_mq_alloc_request(&alloc_data, rw); + rq = __blk_mq_alloc_request(&alloc_data, rw, 0); ctx = alloc_data.ctx; } blk_mq_put_ctx(ctx); @@ -1169,7 +1170,8 @@ static struct request *blk_mq_map_request(struct request_queue *q, struct blk_mq_hw_ctx *hctx; struct blk_mq_ctx *ctx; struct request *rq; - int rw = bio_data_dir(bio); + int op = bio_data_dir(bio); + int op_flags = 0; struct blk_mq_alloc_data alloc_data; blk_queue_enter_live(q); @@ -1177,20 +1179,20 @@ static struct request *blk_mq_map_request(struct request_queue *q, hctx = q->mq_ops->map_queue(q, ctx->cpu); if (rw_is_sync(bio->bi_rw)) - rw |= REQ_SYNC; + op_flags |= REQ_SYNC; - trace_block_getrq(q, bio, rw); + trace_block_getrq(q, bio, op); blk_mq_set_alloc_data(&alloc_data, q, BLK_MQ_REQ_NOWAIT, ctx, hctx); - rq = __blk_mq_alloc_request(&alloc_data, rw); + rq = __blk_mq_alloc_request(&alloc_data, op, op_flags); if (unlikely(!rq)) { __blk_mq_run_hw_queue(hctx); blk_mq_put_ctx(ctx); - trace_block_sleeprq(q, bio, rw); + trace_block_sleeprq(q, bio, op); ctx = blk_mq_get_ctx(q); hctx = q->mq_ops->map_queue(q, ctx->cpu); blk_mq_set_alloc_data(&alloc_data, q, 0, ctx, hctx); - rq = __blk_mq_alloc_request(&alloc_data, rw); + rq = __blk_mq_alloc_request(&alloc_data, op, op_flags); ctx = alloc_data.ctx; hctx = alloc_data.hctx; } -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0106E7D2A for ; Sun, 5 Jun 2016 14:33:50 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 7C1FCAC003 for ; Sun, 5 Jun 2016 12:33:49 -0700 (PDT) X-ASG-Debug-ID: 1465155228-04bdf05ad4b784c0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id BFgonCVDHSOnQz4t (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:48 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1D056A70D; Sun, 5 Jun 2016 19:33:48 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9e003130; Sun, 5 Jun 2016 15:33:45 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 33/45] block: prepare elevator to use REQ_OPs. Date: Sun, 5 Jun 2016 14:32:13 -0500 X-ASG-Orig-Subj: [PATCH 33/45] block: prepare elevator to use REQ_OPs. Message-Id: <1465155145-10812-34-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sun, 05 Jun 2016 19:33:48 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155228 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4179 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch converts the elevator code to use separate variables for the operation and flags, and to check req_op for the REQ_OP. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/blk-core.c | 2 +- block/cfq-iosched.c | 4 ++-- block/elevator.c | 7 +++---- include/linux/elevator.h | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index a68dc07..090e55d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1081,7 +1081,7 @@ static struct request *__get_request(struct request_list *rl, int op, if (unlikely(blk_queue_dying(q))) return ERR_PTR(-ENODEV); - may_queue = elv_may_queue(q, op | op_flags); + may_queue = elv_may_queue(q, op, op_flags); if (may_queue == ELV_MQUEUE_NO) goto rq_starved; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 4a34978..3fcc598 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -4285,7 +4285,7 @@ static inline int __cfq_may_queue(struct cfq_queue *cfqq) return ELV_MQUEUE_MAY; } -static int cfq_may_queue(struct request_queue *q, int rw) +static int cfq_may_queue(struct request_queue *q, int op, int op_flags) { struct cfq_data *cfqd = q->elevator->elevator_data; struct task_struct *tsk = current; @@ -4302,7 +4302,7 @@ static int cfq_may_queue(struct request_queue *q, int rw) if (!cic) return ELV_MQUEUE_MAY; - cfqq = cic_to_cfqq(cic, rw_is_sync(rw)); + cfqq = cic_to_cfqq(cic, rw_is_sync(op | op_flags)); if (cfqq) { cfq_init_prio_data(cfqq, cic); diff --git a/block/elevator.c b/block/elevator.c index c3555c9..ea9319d 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -366,8 +366,7 @@ void elv_dispatch_sort(struct request_queue *q, struct request *rq) list_for_each_prev(entry, &q->queue_head) { struct request *pos = list_entry_rq(entry); - if ((rq->cmd_flags & REQ_DISCARD) != - (pos->cmd_flags & REQ_DISCARD)) + if ((req_op(rq) == REQ_OP_DISCARD) != (req_op(pos) == REQ_OP_DISCARD)) break; if (rq_data_dir(rq) != rq_data_dir(pos)) break; @@ -717,12 +716,12 @@ void elv_put_request(struct request_queue *q, struct request *rq) e->type->ops.elevator_put_req_fn(rq); } -int elv_may_queue(struct request_queue *q, int rw) +int elv_may_queue(struct request_queue *q, int op, int op_flags) { struct elevator_queue *e = q->elevator; if (e->type->ops.elevator_may_queue_fn) - return e->type->ops.elevator_may_queue_fn(q, rw); + return e->type->ops.elevator_may_queue_fn(q, op, op_flags); return ELV_MQUEUE_MAY; } diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 638b324..953d286 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -26,7 +26,7 @@ typedef int (elevator_dispatch_fn) (struct request_queue *, int); typedef void (elevator_add_req_fn) (struct request_queue *, struct request *); typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *); typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); -typedef int (elevator_may_queue_fn) (struct request_queue *, int); +typedef int (elevator_may_queue_fn) (struct request_queue *, int, int); typedef void (elevator_init_icq_fn) (struct io_cq *); typedef void (elevator_exit_icq_fn) (struct io_cq *); @@ -134,7 +134,7 @@ extern struct request *elv_former_request(struct request_queue *, struct request extern struct request *elv_latter_request(struct request_queue *, struct request *); extern int elv_register_queue(struct request_queue *q); extern void elv_unregister_queue(struct request_queue *q); -extern int elv_may_queue(struct request_queue *, int); +extern int elv_may_queue(struct request_queue *, int, int); extern void elv_completed_request(struct request_queue *, struct request *); extern int elv_set_request(struct request_queue *q, struct request *rq, struct bio *bio, gfp_t gfp_mask); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 1FDC47D4E for ; Sun, 5 Jun 2016 14:33:52 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D653A8F8037 for ; Sun, 5 Jun 2016 12:33:51 -0700 (PDT) X-ASG-Debug-ID: 1465155230-04bdf05ad6b784d0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 1YXFrxi2GoaD5ZPS (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:50 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 569908E39A; Sun, 5 Jun 2016 19:33:50 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9f003130; Sun, 5 Jun 2016 15:33:48 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 34/45] blkg_rwstat: separate op from flags Date: Sun, 5 Jun 2016 14:32:14 -0500 X-ASG-Orig-Subj: [PATCH 34/45] blkg_rwstat: separate op from flags Message-Id: <1465155145-10812-35-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:33:50 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155230 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7723 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie The bio and request operation and flags are going to be separate definitions, so we cannot pass them in as a bitmap. This patch converts the blkg_rwstat code and its caller, cfq, to pass in the values separately. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/cfq-iosched.c | 49 +++++++++++++++++++++++++++------------------- include/linux/blk-cgroup.h | 13 ++++++------ 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3fcc598..3dafdba 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -667,9 +667,10 @@ static inline void cfqg_put(struct cfq_group *cfqg) } while (0) static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg, - struct cfq_group *curr_cfqg, int rw) + struct cfq_group *curr_cfqg, int op, + int op_flags) { - blkg_rwstat_add(&cfqg->stats.queued, rw, 1); + blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, 1); cfqg_stats_end_empty_time(&cfqg->stats); cfqg_stats_set_start_group_wait_time(cfqg, curr_cfqg); } @@ -683,26 +684,30 @@ static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg, #endif } -static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int rw) +static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op, + int op_flags) { - blkg_rwstat_add(&cfqg->stats.queued, rw, -1); + blkg_rwstat_add(&cfqg->stats.queued, op, op_flags, -1); } -static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int rw) +static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op, + int op_flags) { - blkg_rwstat_add(&cfqg->stats.merged, rw, 1); + blkg_rwstat_add(&cfqg->stats.merged, op, op_flags, 1); } static inline void cfqg_stats_update_completion(struct cfq_group *cfqg, - uint64_t start_time, uint64_t io_start_time, int rw) + uint64_t start_time, uint64_t io_start_time, int op, + int op_flags) { struct cfqg_stats *stats = &cfqg->stats; unsigned long long now = sched_clock(); if (time_after64(now, io_start_time)) - blkg_rwstat_add(&stats->service_time, rw, now - io_start_time); + blkg_rwstat_add(&stats->service_time, op, op_flags, + now - io_start_time); if (time_after64(io_start_time, start_time)) - blkg_rwstat_add(&stats->wait_time, rw, + blkg_rwstat_add(&stats->wait_time, op, op_flags, io_start_time - start_time); } @@ -781,13 +786,16 @@ static inline void cfqg_put(struct cfq_group *cfqg) { } #define cfq_log_cfqg(cfqd, cfqg, fmt, args...) do {} while (0) static inline void cfqg_stats_update_io_add(struct cfq_group *cfqg, - struct cfq_group *curr_cfqg, int rw) { } + struct cfq_group *curr_cfqg, int op, int op_flags) { } static inline void cfqg_stats_update_timeslice_used(struct cfq_group *cfqg, unsigned long time, unsigned long unaccounted_time) { } -static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int rw) { } -static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int rw) { } +static inline void cfqg_stats_update_io_remove(struct cfq_group *cfqg, int op, + int op_flags) { } +static inline void cfqg_stats_update_io_merged(struct cfq_group *cfqg, int op, + int op_flags) { } static inline void cfqg_stats_update_completion(struct cfq_group *cfqg, - uint64_t start_time, uint64_t io_start_time, int rw) { } + uint64_t start_time, uint64_t io_start_time, int op, + int op_flags) { } #endif /* CONFIG_CFQ_GROUP_IOSCHED */ @@ -2461,10 +2469,10 @@ static void cfq_reposition_rq_rb(struct cfq_queue *cfqq, struct request *rq) { elv_rb_del(&cfqq->sort_list, rq); cfqq->queued[rq_is_sync(rq)]--; - cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags); + cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags); cfq_add_rq_rb(rq); cfqg_stats_update_io_add(RQ_CFQG(rq), cfqq->cfqd->serving_group, - rq->cmd_flags); + req_op(rq), rq->cmd_flags); } static struct request * @@ -2517,7 +2525,7 @@ static void cfq_remove_request(struct request *rq) cfq_del_rq_rb(rq); cfqq->cfqd->rq_queued--; - cfqg_stats_update_io_remove(RQ_CFQG(rq), rq->cmd_flags); + cfqg_stats_update_io_remove(RQ_CFQG(rq), req_op(rq), rq->cmd_flags); if (rq->cmd_flags & REQ_PRIO) { WARN_ON(!cfqq->prio_pending); cfqq->prio_pending--; @@ -2552,7 +2560,7 @@ static void cfq_merged_request(struct request_queue *q, struct request *req, static void cfq_bio_merged(struct request_queue *q, struct request *req, struct bio *bio) { - cfqg_stats_update_io_merged(RQ_CFQG(req), bio->bi_rw); + cfqg_stats_update_io_merged(RQ_CFQG(req), bio_op(bio), bio->bi_rw); } static void @@ -2575,7 +2583,7 @@ cfq_merged_requests(struct request_queue *q, struct request *rq, if (cfqq->next_rq == next) cfqq->next_rq = rq; cfq_remove_request(next); - cfqg_stats_update_io_merged(RQ_CFQG(rq), next->cmd_flags); + cfqg_stats_update_io_merged(RQ_CFQG(rq), req_op(next), next->cmd_flags); cfqq = RQ_CFQQ(next); /* @@ -4108,7 +4116,7 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) rq->fifo_time = jiffies + cfqd->cfq_fifo_expire[rq_is_sync(rq)]; list_add_tail(&rq->queuelist, &cfqq->fifo); cfq_add_rq_rb(rq); - cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group, + cfqg_stats_update_io_add(RQ_CFQG(rq), cfqd->serving_group, req_op(rq), rq->cmd_flags); cfq_rq_enqueued(cfqd, cfqq, rq); } @@ -4206,7 +4214,8 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) cfqq->dispatched--; (RQ_CFQG(rq))->dispatched--; cfqg_stats_update_completion(cfqq->cfqg, rq_start_time_ns(rq), - rq_io_start_time_ns(rq), rq->cmd_flags); + rq_io_start_time_ns(rq), req_op(rq), + rq->cmd_flags); cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--; diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 04f9c8d..f77150a 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -590,25 +590,26 @@ static inline void blkg_rwstat_exit(struct blkg_rwstat *rwstat) /** * blkg_rwstat_add - add a value to a blkg_rwstat * @rwstat: target blkg_rwstat - * @rw: mask of REQ_{WRITE|SYNC} + * @op: REQ_OP + * @op_flags: rq_flag_bits * @val: value to add * * Add @val to @rwstat. The counters are chosen according to @rw. The * caller is responsible for synchronizing calls to this function. */ static inline void blkg_rwstat_add(struct blkg_rwstat *rwstat, - int rw, uint64_t val) + int op, int op_flags, uint64_t val) { struct percpu_counter *cnt; - if (op_is_write(rw)) + if (op_is_write(op)) cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_WRITE]; else cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_READ]; __percpu_counter_add(cnt, val, BLKG_STAT_CPU_BATCH); - if (rw & REQ_SYNC) + if (op_flags & REQ_SYNC) cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_SYNC]; else cnt = &rwstat->cpu_cnt[BLKG_RWSTAT_ASYNC]; @@ -713,9 +714,9 @@ static inline bool blkcg_bio_issue_check(struct request_queue *q, if (!throtl) { blkg = blkg ?: q->root_blkg; - blkg_rwstat_add(&blkg->stat_bytes, bio->bi_rw, + blkg_rwstat_add(&blkg->stat_bytes, bio_op(bio), bio->bi_rw, bio->bi_iter.bi_size); - blkg_rwstat_add(&blkg->stat_ios, bio->bi_rw, 1); + blkg_rwstat_add(&blkg->stat_ios, bio_op(bio), bio->bi_rw, 1); } rcu_read_unlock(); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A252E7D2C for ; Sun, 5 Jun 2016 14:33:54 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 66776304043 for ; Sun, 5 Jun 2016 12:33:54 -0700 (PDT) X-ASG-Debug-ID: 1465155232-04cbb0356ab8ac40001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 9RACriPhsxU0uK26 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:53 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9C2088F4E5; Sun, 5 Jun 2016 19:33:52 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9g003130; Sun, 5 Jun 2016 15:33:50 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 35/45] block: convert merge/insert code to check for REQ_OPs. Date: Sun, 5 Jun 2016 14:32:15 -0500 X-ASG-Orig-Subj: [PATCH 35/45] block: convert merge/insert code to check for REQ_OPs. Message-Id: <1465155145-10812-36-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Sun, 05 Jun 2016 19:33:52 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155233 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4565 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch converts the block layer merging code to use separate variables for the operation and flags, and to check req_op for the REQ_OP. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/blk-core.c | 2 +- block/blk-merge.c | 10 ++++++---- include/linux/blkdev.h | 20 ++++++++++---------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 090e55d..1333bb7 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2161,7 +2161,7 @@ EXPORT_SYMBOL(submit_bio); static int blk_cloned_rq_check_limits(struct request_queue *q, struct request *rq) { - if (blk_rq_sectors(rq) > blk_queue_get_max_sectors(q, rq->cmd_flags)) { + if (blk_rq_sectors(rq) > blk_queue_get_max_sectors(q, req_op(rq))) { printk(KERN_ERR "%s: over max size limit.\n", __func__); return -EIO; } diff --git a/block/blk-merge.c b/block/blk-merge.c index 5a03f96..c265348 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -649,7 +649,8 @@ static int attempt_merge(struct request_queue *q, struct request *req, if (!rq_mergeable(req) || !rq_mergeable(next)) return 0; - if (!blk_check_merge_flags(req->cmd_flags, next->cmd_flags)) + if (!blk_check_merge_flags(req->cmd_flags, req_op(req), next->cmd_flags, + req_op(next))) return 0; /* @@ -663,7 +664,7 @@ static int attempt_merge(struct request_queue *q, struct request *req, || req_no_special_merge(next)) return 0; - if (req->cmd_flags & REQ_WRITE_SAME && + if (req_op(req) == REQ_OP_WRITE_SAME && !blk_write_same_mergeable(req->bio, next->bio)) return 0; @@ -751,7 +752,8 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) if (!rq_mergeable(rq) || !bio_mergeable(bio)) return false; - if (!blk_check_merge_flags(rq->cmd_flags, bio->bi_rw)) + if (!blk_check_merge_flags(rq->cmd_flags, req_op(rq), bio->bi_rw, + bio_op(bio))) return false; /* different data direction or already started, don't merge */ @@ -767,7 +769,7 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio) return false; /* must be using the same buffer */ - if (rq->cmd_flags & REQ_WRITE_SAME && + if (req_op(rq) == REQ_OP_WRITE_SAME && !blk_write_same_mergeable(rq->bio, bio)) return false; diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 8c78aca..25f01ff 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -666,16 +666,16 @@ static inline bool rq_mergeable(struct request *rq) return true; } -static inline bool blk_check_merge_flags(unsigned int flags1, - unsigned int flags2) +static inline bool blk_check_merge_flags(unsigned int flags1, unsigned int op1, + unsigned int flags2, unsigned int op2) { - if ((flags1 & REQ_DISCARD) != (flags2 & REQ_DISCARD)) + if ((op1 == REQ_OP_DISCARD) != (op2 == REQ_OP_DISCARD)) return false; if ((flags1 & REQ_SECURE) != (flags2 & REQ_SECURE)) return false; - if ((flags1 & REQ_WRITE_SAME) != (flags2 & REQ_WRITE_SAME)) + if ((op1 == REQ_OP_WRITE_SAME) != (op2 == REQ_OP_WRITE_SAME)) return false; return true; @@ -887,12 +887,12 @@ static inline unsigned int blk_rq_cur_sectors(const struct request *rq) } static inline unsigned int blk_queue_get_max_sectors(struct request_queue *q, - unsigned int cmd_flags) + int op) { - if (unlikely(cmd_flags & REQ_DISCARD)) + if (unlikely(op == REQ_OP_DISCARD)) return min(q->limits.max_discard_sectors, UINT_MAX >> 9); - if (unlikely(cmd_flags & REQ_WRITE_SAME)) + if (unlikely(op == REQ_OP_WRITE_SAME)) return q->limits.max_write_same_sectors; return q->limits.max_sectors; @@ -919,11 +919,11 @@ static inline unsigned int blk_rq_get_max_sectors(struct request *rq) if (unlikely(rq->cmd_type != REQ_TYPE_FS)) return q->limits.max_hw_sectors; - if (!q->limits.chunk_sectors || (rq->cmd_flags & REQ_DISCARD)) - return blk_queue_get_max_sectors(q, rq->cmd_flags); + if (!q->limits.chunk_sectors || (req_op(rq) == REQ_OP_DISCARD)) + return blk_queue_get_max_sectors(q, req_op(rq)); return min(blk_max_size_offset(q, blk_rq_pos(rq)), - blk_queue_get_max_sectors(q, rq->cmd_flags)); + blk_queue_get_max_sectors(q, req_op(rq))); } static inline unsigned int blk_rq_count_bios(struct request *rq) -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:58 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1C2B77CEE for ; Sun, 5 Jun 2016 14:33:58 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 87740AC003 for ; Sun, 5 Jun 2016 12:33:57 -0700 (PDT) X-ASG-Debug-ID: 1465155235-04cbb03569b8ac40001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id Dfmp2iG72a3YSflN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:56 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 53F9319D04D; Sun, 5 Jun 2016 19:33:55 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9h003130; Sun, 5 Jun 2016 15:33:52 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 36/45] block: convert is_sync helpers to use REQ_OPs. Date: Sun, 5 Jun 2016 14:32:16 -0500 X-ASG-Orig-Subj: [PATCH 36/45] block: convert is_sync helpers to use REQ_OPs. Message-Id: <1465155145-10812-37-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sun, 05 Jun 2016 19:33:55 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155236 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4388 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch converts the is_sync helpers to use separate variables for the operation and flags. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- block/blk-core.c | 6 +++--- block/blk-mq.c | 8 ++++---- block/cfq-iosched.c | 2 +- include/linux/blkdev.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 1333bb7..f9f4228 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -962,7 +962,7 @@ static void __freed_request(struct request_list *rl, int sync) static void freed_request(struct request_list *rl, int op, unsigned int flags) { struct request_queue *q = rl->q; - int sync = rw_is_sync(op | flags); + int sync = rw_is_sync(op, flags); q->nr_rqs[sync]--; rl->count[sync]--; @@ -1075,7 +1075,7 @@ static struct request *__get_request(struct request_list *rl, int op, struct elevator_type *et = q->elevator->type; struct io_context *ioc = rq_ioc(bio); struct io_cq *icq = NULL; - const bool is_sync = rw_is_sync(op | op_flags) != 0; + const bool is_sync = rw_is_sync(op, op_flags) != 0; int may_queue; if (unlikely(blk_queue_dying(q))) @@ -1244,7 +1244,7 @@ static struct request *get_request(struct request_queue *q, int op, int op_flags, struct bio *bio, gfp_t gfp_mask) { - const bool is_sync = rw_is_sync(op | op_flags) != 0; + const bool is_sync = rw_is_sync(op, op_flags) != 0; DEFINE_WAIT(wait); struct request_list *rl; struct request *rq; diff --git a/block/blk-mq.c b/block/blk-mq.c index 3393f29..29bcd9c 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -204,7 +204,7 @@ static void blk_mq_rq_ctx_init(struct request_queue *q, struct blk_mq_ctx *ctx, rq->end_io_data = NULL; rq->next_rq = NULL; - ctx->rq_dispatched[rw_is_sync(op | op_flags)]++; + ctx->rq_dispatched[rw_is_sync(op, op_flags)]++; } static struct request * @@ -1178,7 +1178,7 @@ static struct request *blk_mq_map_request(struct request_queue *q, ctx = blk_mq_get_ctx(q); hctx = q->mq_ops->map_queue(q, ctx->cpu); - if (rw_is_sync(bio->bi_rw)) + if (rw_is_sync(bio_op(bio), bio->bi_rw)) op_flags |= REQ_SYNC; trace_block_getrq(q, bio, op); @@ -1246,7 +1246,7 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie) */ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) { - const int is_sync = rw_is_sync(bio->bi_rw); + const int is_sync = rw_is_sync(bio_op(bio), bio->bi_rw); const int is_flush_fua = bio->bi_rw & (REQ_FLUSH | REQ_FUA); struct blk_map_ctx data; struct request *rq; @@ -1343,7 +1343,7 @@ done: */ static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) { - const int is_sync = rw_is_sync(bio->bi_rw); + const int is_sync = rw_is_sync(bio_op(bio), bio->bi_rw); const int is_flush_fua = bio->bi_rw & (REQ_FLUSH | REQ_FUA); struct blk_plug *plug; unsigned int request_count = 0; diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3dafdba..b115486 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -4311,7 +4311,7 @@ static int cfq_may_queue(struct request_queue *q, int op, int op_flags) if (!cic) return ELV_MQUEUE_MAY; - cfqq = cic_to_cfqq(cic, rw_is_sync(op | op_flags)); + cfqq = cic_to_cfqq(cic, rw_is_sync(op, op_flags)); if (cfqq) { cfq_init_prio_data(cfqq, cic); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 25f01ff..4937c05 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -624,14 +624,14 @@ static inline unsigned int blk_queue_cluster(struct request_queue *q) /* * We regard a request as sync, if either a read or a sync write */ -static inline bool rw_is_sync(unsigned int rw_flags) +static inline bool rw_is_sync(int op, unsigned int rw_flags) { - return !(rw_flags & REQ_WRITE) || (rw_flags & REQ_SYNC); + return op == REQ_OP_READ || (rw_flags & REQ_SYNC); } static inline bool rq_is_sync(struct request *rq) { - return rw_is_sync(rq->cmd_flags); + return rw_is_sync(req_op(rq), rq->cmd_flags); } static inline bool blk_rl_full(struct request_list *rl, bool sync) -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:33:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9CC047CB6 for ; Sun, 5 Jun 2016 14:33:59 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6E7FB304043 for ; Sun, 5 Jun 2016 12:33:59 -0700 (PDT) X-ASG-Debug-ID: 1465155237-04cbb03568b8ac40001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id vB5aB4h4PD5hKw36 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:33:57 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3CE73C04D2A9; Sun, 5 Jun 2016 19:33:57 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9i003130; Sun, 5 Jun 2016 15:33:55 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 37/45] drivers: use req op accessor Date: Sun, 5 Jun 2016 14:32:17 -0500 X-ASG-Orig-Subj: [PATCH 37/45] drivers: use req op accessor Message-Id: <1465155145-10812-38-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sun, 05 Jun 2016 19:33:57 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155237 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12052 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie The req operation REQ_OP is separated from the rq_flag_bits definition. This converts the block layer drivers to use req_op to get the op from the request struct. Signed-off-by: Mike Christie --- drivers/block/loop.c | 6 +++--- drivers/block/mtip32xx/mtip32xx.c | 2 +- drivers/block/nbd.c | 2 +- drivers/block/rbd.c | 4 ++-- drivers/block/xen-blkfront.c | 8 +++++--- drivers/ide/ide-floppy.c | 2 +- drivers/md/dm.c | 2 +- drivers/mmc/card/block.c | 7 +++---- drivers/mmc/card/queue.c | 6 ++---- drivers/mmc/card/queue.h | 5 ++++- drivers/mtd/mtd_blkdevs.c | 2 +- drivers/nvme/host/core.c | 2 +- drivers/nvme/host/nvme.h | 4 ++-- drivers/scsi/sd.c | 25 ++++++++++++++++--------- 14 files changed, 43 insertions(+), 34 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e9f1701..b9b737c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -544,7 +544,7 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) if (op_is_write(req_op(rq))) { if (rq->cmd_flags & REQ_FLUSH) ret = lo_req_flush(lo, rq); - else if (rq->cmd_flags & REQ_DISCARD) + else if (req_op(rq) == REQ_OP_DISCARD) ret = lo_discard(lo, rq, pos); else if (lo->transfer) ret = lo_write_transfer(lo, rq, pos); @@ -1659,8 +1659,8 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx, if (lo->lo_state != Lo_bound) return -EIO; - if (lo->use_dio && !(cmd->rq->cmd_flags & (REQ_FLUSH | - REQ_DISCARD))) + if (lo->use_dio && (!(cmd->rq->cmd_flags & REQ_FLUSH) || + req_op(cmd->rq) == REQ_OP_DISCARD)) cmd->use_aio = true; else cmd->use_aio = false; diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 6053e46..8e3e708 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -3765,7 +3765,7 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq) return -ENODATA; } - if (rq->cmd_flags & REQ_DISCARD) { + if (req_op(rq) == REQ_OP_DISCARD) { int err; err = mtip_send_trim(dd, blk_rq_pos(rq), blk_rq_sectors(rq)); diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 31e73a7..6c2c28d 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -282,7 +282,7 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req) if (req->cmd_type == REQ_TYPE_DRV_PRIV) type = NBD_CMD_DISC; - else if (req->cmd_flags & REQ_DISCARD) + else if (req_op(req) == REQ_OP_DISCARD) type = NBD_CMD_TRIM; else if (req->cmd_flags & REQ_FLUSH) type = NBD_CMD_FLUSH; diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 81666a5..4506620 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -3286,9 +3286,9 @@ static void rbd_queue_workfn(struct work_struct *work) goto err; } - if (rq->cmd_flags & REQ_DISCARD) + if (req_op(rq) == REQ_OP_DISCARD) op_type = OBJ_OP_DISCARD; - else if (rq->cmd_flags & REQ_WRITE) + else if (req_op(rq) == REQ_OP_WRITE) op_type = OBJ_OP_WRITE; else op_type = OBJ_OP_READ; diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 52963a2..6fd1601 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -844,7 +844,8 @@ static int blkif_queue_request(struct request *req, struct blkfront_ring_info *r if (unlikely(rinfo->dev_info->connected != BLKIF_STATE_CONNECTED)) return 1; - if (unlikely(req->cmd_flags & (REQ_DISCARD | REQ_SECURE))) + if (unlikely(req_op(req) == REQ_OP_DISCARD || + req->cmd_flags & REQ_SECURE)) return blkif_queue_discard_req(req, rinfo); else return blkif_queue_rw_req(req, rinfo); @@ -2054,8 +2055,9 @@ static int blkif_recover(struct blkfront_info *info) /* * Get the bios in the request so we can re-queue them. */ - if (copy[i].request->cmd_flags & - (REQ_FLUSH | REQ_FUA | REQ_DISCARD | REQ_SECURE)) { + if (copy[i].request->cmd_flags & REQ_FLUSH || + req_op(copy[i].request) == REQ_OP_DISCARD || + copy[i].request->cmd_flags & (REQ_FUA | REQ_SECURE)) { /* * Flush operations don't contain bios, so * we need to requeue the whole request diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 2fb5350..f079d8d 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -206,7 +206,7 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive, memcpy(rq->cmd, pc->c, 12); pc->rq = rq; - if (rq->cmd_flags & REQ_WRITE) + if (cmd == WRITE) pc->flags |= PC_FLAG_WRITING; pc->flags |= PC_FLAG_DMA_OK; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 9204a2d..f6b104c 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1322,7 +1322,7 @@ static void dm_done(struct request *clone, int error, bool mapped) r = rq_end_io(tio->ti, clone, error, &tio->info); } - if (unlikely(r == -EREMOTEIO && (clone->cmd_flags & REQ_WRITE_SAME) && + if (unlikely(r == -EREMOTEIO && (req_op(clone) == REQ_OP_WRITE_SAME) && !clone->q->limits.max_write_same_sectors)) disable_write_same(tio->md); diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index e62fde3..201a871 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1722,8 +1722,7 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req) !IS_ALIGNED(blk_rq_sectors(next), 8)) break; - if (next->cmd_flags & REQ_DISCARD || - next->cmd_flags & REQ_FLUSH) + if (req_op(next) == REQ_OP_DISCARD || next->cmd_flags & REQ_FLUSH) break; if (rq_data_dir(cur) != rq_data_dir(next)) @@ -2164,7 +2163,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) } mq->flags &= ~MMC_QUEUE_NEW_REQUEST; - if (cmd_flags & REQ_DISCARD) { + if (req && req_op(req) == REQ_OP_DISCARD) { /* complete ongoing async transfer before issuing discard */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); @@ -2188,7 +2187,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) out: if ((!req && !(mq->flags & MMC_QUEUE_NEW_REQUEST)) || - (cmd_flags & MMC_REQ_SPECIAL_MASK)) + mmc_req_is_special(req)) /* * Release host when there are no more requests * and after special request(discard, flush) is done. diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 6f4323c..c2d5f6f 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c @@ -33,7 +33,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) /* * We only like normal block requests and discards. */ - if (req->cmd_type != REQ_TYPE_FS && !(req->cmd_flags & REQ_DISCARD)) { + if (req->cmd_type != REQ_TYPE_FS && req_op(req) != REQ_OP_DISCARD) { blk_dump_rq_flags(req, "MMC bad request"); return BLKPREP_KILL; } @@ -56,7 +56,6 @@ static int mmc_queue_thread(void *d) down(&mq->thread_sem); do { struct request *req = NULL; - unsigned int cmd_flags = 0; spin_lock_irq(q->queue_lock); set_current_state(TASK_INTERRUPTIBLE); @@ -66,7 +65,6 @@ static int mmc_queue_thread(void *d) if (req || mq->mqrq_prev->req) { set_current_state(TASK_RUNNING); - cmd_flags = req ? req->cmd_flags : 0; mq->issue_fn(mq, req); cond_resched(); if (mq->flags & MMC_QUEUE_NEW_REQUEST) { @@ -81,7 +79,7 @@ static int mmc_queue_thread(void *d) * has been finished. Do not assign it to previous * request. */ - if (cmd_flags & MMC_REQ_SPECIAL_MASK) + if (mmc_req_is_special(req)) mq->mqrq_cur->req = NULL; mq->mqrq_prev->brq.mrq.data = NULL; diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index 36cddab..9fb26f2 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -1,7 +1,10 @@ #ifndef MMC_QUEUE_H #define MMC_QUEUE_H -#define MMC_REQ_SPECIAL_MASK (REQ_DISCARD | REQ_FLUSH) +static inline bool mmc_req_is_special(struct request *req) +{ + return req && (req->cmd_flags & REQ_FLUSH || req_op(req) == REQ_OP_DISCARD); +} struct request; struct task_struct; diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 74ae243..4eb9a5f 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -94,7 +94,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, get_capacity(req->rq_disk)) return -EIO; - if (req->cmd_flags & REQ_DISCARD) + if (req_op(req) == REQ_OP_DISCARD) return tr->discard(dev, block, nsect); if (rq_data_dir(req) == READ) { diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 1a51584..089b8b8 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -292,7 +292,7 @@ int nvme_setup_cmd(struct nvme_ns *ns, struct request *req, memcpy(cmd, req->cmd, sizeof(*cmd)); else if (req->cmd_flags & REQ_FLUSH) nvme_setup_flush(ns, cmd); - else if (req->cmd_flags & REQ_DISCARD) + else if (req_op(req) == REQ_OP_DISCARD) ret = nvme_setup_discard(ns, req, cmd); else nvme_setup_rw(ns, req, cmd); diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index 1daa048..4d196d2 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -177,7 +177,7 @@ static inline u64 nvme_block_nr(struct nvme_ns *ns, sector_t sector) static inline unsigned nvme_map_len(struct request *rq) { - if (rq->cmd_flags & REQ_DISCARD) + if (req_op(rq) == REQ_OP_DISCARD) return sizeof(struct nvme_dsm_range); else return blk_rq_bytes(rq); @@ -185,7 +185,7 @@ static inline unsigned nvme_map_len(struct request *rq) static inline void nvme_cleanup_cmd(struct request *req) { - if (req->cmd_flags & REQ_DISCARD) + if (req_op(req) == REQ_OP_DISCARD) kfree(req->completion_data); } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index f459dff..c8dc221 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1012,7 +1012,8 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_6; } else { - scmd_printk(KERN_ERR, SCpnt, "Unknown command %llx\n", (unsigned long long) rq->cmd_flags); + scmd_printk(KERN_ERR, SCpnt, "Unknown command %d,%llx\n", + req_op(rq), (unsigned long long) rq->cmd_flags); goto out; } @@ -1137,21 +1138,27 @@ static int sd_init_command(struct scsi_cmnd *cmd) { struct request *rq = cmd->request; - if (rq->cmd_flags & REQ_DISCARD) + switch (req_op(rq)) { + case REQ_OP_DISCARD: return sd_setup_discard_cmnd(cmd); - else if (rq->cmd_flags & REQ_WRITE_SAME) + case REQ_OP_WRITE_SAME: return sd_setup_write_same_cmnd(cmd); - else if (rq->cmd_flags & REQ_FLUSH) - return sd_setup_flush_cmnd(cmd); - else - return sd_setup_read_write_cmnd(cmd); + case REQ_OP_READ: + case REQ_OP_WRITE: + if (rq->cmd_flags & REQ_FLUSH) + return sd_setup_flush_cmnd(cmd); + else + return sd_setup_read_write_cmnd(cmd); + default: + BUG(); + } } static void sd_uninit_command(struct scsi_cmnd *SCpnt) { struct request *rq = SCpnt->request; - if (rq->cmd_flags & REQ_DISCARD) + if (req_op(rq) == REQ_OP_DISCARD) __free_page(rq->completion_data); if (SCpnt->cmnd != rq->cmd) { @@ -1774,7 +1781,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) unsigned char op = SCpnt->cmnd[0]; unsigned char unmap = SCpnt->cmnd[1] & 8; - if (req->cmd_flags & REQ_DISCARD || req->cmd_flags & REQ_WRITE_SAME) { + if (req_op(req) == REQ_OP_DISCARD || req_op(req) == REQ_OP_WRITE_SAME) { if (!result) { good_bytes = blk_rq_bytes(req); scsi_set_resid(SCpnt, 0); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A5EE57D5B for ; Sun, 5 Jun 2016 14:34:02 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2E66CAC003 for ; Sun, 5 Jun 2016 12:34:02 -0700 (PDT) X-ASG-Debug-ID: 1465155239-04cbb0356bb8ac50001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 7koH6foSOfmorSi9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:00 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7426B90E50; Sun, 5 Jun 2016 19:33:59 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9j003130; Sun, 5 Jun 2016 15:33:57 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 38/45] blktrace: use op accessors Date: Sun, 5 Jun 2016 14:32:18 -0500 X-ASG-Orig-Subj: [PATCH 38/45] blktrace: use op accessors Message-Id: <1465155145-10812-39-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Sun, 05 Jun 2016 19:33:59 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155240 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12996 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie Have blktrace use the req/bio op accessor to get the REQ_OP. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- v8: 1. Fix REQ_OP_WRITE_SAME handling, so it is not reported as a N. include/linux/blktrace_api.h | 2 +- include/trace/events/bcache.h | 12 ++++++--- include/trace/events/block.h | 31 ++++++++++++++-------- kernel/trace/blktrace.c | 62 +++++++++++++++++++++++++------------------ 4 files changed, 65 insertions(+), 42 deletions(-) diff --git a/include/linux/blktrace_api.h b/include/linux/blktrace_api.h index 0f3172b..cceb72f 100644 --- a/include/linux/blktrace_api.h +++ b/include/linux/blktrace_api.h @@ -118,7 +118,7 @@ static inline int blk_cmd_buf_len(struct request *rq) } extern void blk_dump_cmd(char *buf, struct request *rq); -extern void blk_fill_rwbs(char *rwbs, u32 rw, int bytes); +extern void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes); #endif /* CONFIG_EVENT_TRACING && CONFIG_BLOCK */ diff --git a/include/trace/events/bcache.h b/include/trace/events/bcache.h index 981acf7..65673d8 100644 --- a/include/trace/events/bcache.h +++ b/include/trace/events/bcache.h @@ -27,7 +27,8 @@ DECLARE_EVENT_CLASS(bcache_request, __entry->sector = bio->bi_iter.bi_sector; __entry->orig_sector = bio->bi_iter.bi_sector - 16; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u (from %d,%d @ %llu)", @@ -101,7 +102,8 @@ DECLARE_EVENT_CLASS(bcache_bio, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u", @@ -136,7 +138,8 @@ TRACE_EVENT(bcache_read, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); __entry->cache_hit = hit; __entry->bypass = bypass; ), @@ -167,7 +170,8 @@ TRACE_EVENT(bcache_write, __entry->inode = inode; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio->bi_iter.bi_size >> 9; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); __entry->writeback = writeback; __entry->bypass = bypass; ), diff --git a/include/trace/events/block.h b/include/trace/events/block.h index e8a5eca..5a2a759 100644 --- a/include/trace/events/block.h +++ b/include/trace/events/block.h @@ -84,7 +84,8 @@ DECLARE_EVENT_CLASS(block_rq_with_error, 0 : blk_rq_sectors(rq); __entry->errors = rq->errors; - blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); + blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, + blk_rq_bytes(rq)); blk_dump_cmd(__get_str(cmd), rq); ), @@ -162,7 +163,7 @@ TRACE_EVENT(block_rq_complete, __entry->nr_sector = nr_bytes >> 9; __entry->errors = rq->errors; - blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, nr_bytes); + blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, nr_bytes); blk_dump_cmd(__get_str(cmd), rq); ), @@ -198,7 +199,8 @@ DECLARE_EVENT_CLASS(block_rq, __entry->bytes = (rq->cmd_type == REQ_TYPE_BLOCK_PC) ? blk_rq_bytes(rq) : 0; - blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); + blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, + blk_rq_bytes(rq)); blk_dump_cmd(__get_str(cmd), rq); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -272,7 +274,8 @@ TRACE_EVENT(block_bio_bounce, bio->bi_bdev->bd_dev : 0; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -310,7 +313,8 @@ TRACE_EVENT(block_bio_complete, __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); __entry->error = error; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u [%d]", @@ -337,7 +341,8 @@ DECLARE_EVENT_CLASS(block_bio_merge, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -404,7 +409,8 @@ TRACE_EVENT(block_bio_queue, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->nr_sector = bio_sectors(bio); - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -432,7 +438,7 @@ DECLARE_EVENT_CLASS(block_get_rq, __entry->dev = bio ? bio->bi_bdev->bd_dev : 0; __entry->sector = bio ? bio->bi_iter.bi_sector : 0; __entry->nr_sector = bio ? bio_sectors(bio) : 0; - blk_fill_rwbs(__entry->rwbs, + blk_fill_rwbs(__entry->rwbs, bio ? bio_op(bio) : 0, bio ? bio->bi_rw : 0, __entry->nr_sector); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -567,7 +573,8 @@ TRACE_EVENT(block_split, __entry->dev = bio->bi_bdev->bd_dev; __entry->sector = bio->bi_iter.bi_sector; __entry->new_sector = new_sector; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); memcpy(__entry->comm, current->comm, TASK_COMM_LEN); ), @@ -610,7 +617,8 @@ TRACE_EVENT(block_bio_remap, __entry->nr_sector = bio_sectors(bio); __entry->old_dev = dev; __entry->old_sector = from; - blk_fill_rwbs(__entry->rwbs, bio->bi_rw, bio->bi_iter.bi_size); + blk_fill_rwbs(__entry->rwbs, bio_op(bio), bio->bi_rw, + bio->bi_iter.bi_size); ), TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu", @@ -656,7 +664,8 @@ TRACE_EVENT(block_rq_remap, __entry->old_dev = dev; __entry->old_sector = from; __entry->nr_bios = blk_rq_count_bios(rq); - blk_fill_rwbs(__entry->rwbs, rq->cmd_flags, blk_rq_bytes(rq)); + blk_fill_rwbs(__entry->rwbs, req_op(rq), rq->cmd_flags, + blk_rq_bytes(rq)); ), TP_printk("%d,%d %s %llu + %u <- (%d,%d) %llu %u", diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 9aef865..2d16fad 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -199,7 +199,8 @@ static const u32 ddir_act[2] = { BLK_TC_ACT(BLK_TC_READ), * blk_io_trace structure and places it in a per-cpu subbuffer. */ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, - int rw, u32 what, int error, int pdu_len, void *pdu_data) + int op, int op_flags, u32 what, int error, int pdu_len, + void *pdu_data) { struct task_struct *tsk = current; struct ring_buffer_event *event = NULL; @@ -214,13 +215,14 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, if (unlikely(bt->trace_state != Blktrace_running && !blk_tracer)) return; - what |= ddir_act[rw & WRITE]; - what |= MASK_TC_BIT(rw, SYNC); - what |= MASK_TC_BIT(rw, RAHEAD); - what |= MASK_TC_BIT(rw, META); - what |= MASK_TC_BIT(rw, DISCARD); - what |= MASK_TC_BIT(rw, FLUSH); - what |= MASK_TC_BIT(rw, FUA); + what |= ddir_act[op_is_write(op) ? WRITE : READ]; + what |= MASK_TC_BIT(op_flags, SYNC); + what |= MASK_TC_BIT(op_flags, RAHEAD); + what |= MASK_TC_BIT(op_flags, META); + what |= MASK_TC_BIT(op_flags, FLUSH); + what |= MASK_TC_BIT(op_flags, FUA); + if (op == REQ_OP_DISCARD) + what |= BLK_TC_ACT(BLK_TC_DISCARD); pid = tsk->pid; if (act_log_check(bt, what, sector, pid)) @@ -708,11 +710,11 @@ static void blk_add_trace_rq(struct request_queue *q, struct request *rq, if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { what |= BLK_TC_ACT(BLK_TC_PC); - __blk_add_trace(bt, 0, nr_bytes, rq->cmd_flags, + __blk_add_trace(bt, 0, nr_bytes, req_op(rq), rq->cmd_flags, what, rq->errors, rq->cmd_len, rq->cmd); } else { what |= BLK_TC_ACT(BLK_TC_FS); - __blk_add_trace(bt, blk_rq_pos(rq), nr_bytes, + __blk_add_trace(bt, blk_rq_pos(rq), nr_bytes, req_op(rq), rq->cmd_flags, what, rq->errors, 0, NULL); } } @@ -770,7 +772,7 @@ static void blk_add_trace_bio(struct request_queue *q, struct bio *bio, return; __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size, - bio->bi_rw, what, error, 0, NULL); + bio_op(bio), bio->bi_rw, what, error, 0, NULL); } static void blk_add_trace_bio_bounce(void *ignore, @@ -818,7 +820,8 @@ static void blk_add_trace_getrq(void *ignore, struct blk_trace *bt = q->blk_trace; if (bt) - __blk_add_trace(bt, 0, 0, rw, BLK_TA_GETRQ, 0, 0, NULL); + __blk_add_trace(bt, 0, 0, rw, 0, BLK_TA_GETRQ, 0, 0, + NULL); } } @@ -833,7 +836,7 @@ static void blk_add_trace_sleeprq(void *ignore, struct blk_trace *bt = q->blk_trace; if (bt) - __blk_add_trace(bt, 0, 0, rw, BLK_TA_SLEEPRQ, + __blk_add_trace(bt, 0, 0, rw, 0, BLK_TA_SLEEPRQ, 0, 0, NULL); } } @@ -843,7 +846,7 @@ static void blk_add_trace_plug(void *ignore, struct request_queue *q) struct blk_trace *bt = q->blk_trace; if (bt) - __blk_add_trace(bt, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL); + __blk_add_trace(bt, 0, 0, 0, 0, BLK_TA_PLUG, 0, 0, NULL); } static void blk_add_trace_unplug(void *ignore, struct request_queue *q, @@ -860,7 +863,7 @@ static void blk_add_trace_unplug(void *ignore, struct request_queue *q, else what = BLK_TA_UNPLUG_TIMER; - __blk_add_trace(bt, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu); + __blk_add_trace(bt, 0, 0, 0, 0, what, 0, sizeof(rpdu), &rpdu); } } @@ -874,8 +877,9 @@ static void blk_add_trace_split(void *ignore, __be64 rpdu = cpu_to_be64(pdu); __blk_add_trace(bt, bio->bi_iter.bi_sector, - bio->bi_iter.bi_size, bio->bi_rw, BLK_TA_SPLIT, - bio->bi_error, sizeof(rpdu), &rpdu); + bio->bi_iter.bi_size, bio_op(bio), bio->bi_rw, + BLK_TA_SPLIT, bio->bi_error, sizeof(rpdu), + &rpdu); } } @@ -907,7 +911,7 @@ static void blk_add_trace_bio_remap(void *ignore, r.sector_from = cpu_to_be64(from); __blk_add_trace(bt, bio->bi_iter.bi_sector, bio->bi_iter.bi_size, - bio->bi_rw, BLK_TA_REMAP, bio->bi_error, + bio_op(bio), bio->bi_rw, BLK_TA_REMAP, bio->bi_error, sizeof(r), &r); } @@ -940,7 +944,7 @@ static void blk_add_trace_rq_remap(void *ignore, r.sector_from = cpu_to_be64(from); __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), - rq_data_dir(rq), BLK_TA_REMAP, !!rq->errors, + rq_data_dir(rq), 0, BLK_TA_REMAP, !!rq->errors, sizeof(r), &r); } @@ -965,10 +969,10 @@ void blk_add_driver_data(struct request_queue *q, return; if (rq->cmd_type == REQ_TYPE_BLOCK_PC) - __blk_add_trace(bt, 0, blk_rq_bytes(rq), 0, + __blk_add_trace(bt, 0, blk_rq_bytes(rq), 0, 0, BLK_TA_DRV_DATA, rq->errors, len, data); else - __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0, + __blk_add_trace(bt, blk_rq_pos(rq), blk_rq_bytes(rq), 0, 0, BLK_TA_DRV_DATA, rq->errors, len, data); } EXPORT_SYMBOL_GPL(blk_add_driver_data); @@ -1769,21 +1773,27 @@ void blk_dump_cmd(char *buf, struct request *rq) } } -void blk_fill_rwbs(char *rwbs, u32 rw, int bytes) +void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes) { int i = 0; if (rw & REQ_FLUSH) rwbs[i++] = 'F'; - if (rw & WRITE) + switch (op) { + case REQ_OP_WRITE: + case REQ_OP_WRITE_SAME: rwbs[i++] = 'W'; - else if (rw & REQ_DISCARD) + break; + case REQ_OP_DISCARD: rwbs[i++] = 'D'; - else if (bytes) + break; + case REQ_OP_READ: rwbs[i++] = 'R'; - else + break; + default: rwbs[i++] = 'N'; + } if (rw & REQ_FUA) rwbs[i++] = 'F'; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9D4F77D62 for ; Sun, 5 Jun 2016 14:34:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6278F8F8037 for ; Sun, 5 Jun 2016 12:34:03 -0700 (PDT) X-ASG-Debug-ID: 1465155242-04cbb0356bb8ac60001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id JGhQUFnL2dfEgsIo (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:02 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C410A486D6; Sun, 5 Jun 2016 19:34:01 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9k003130; Sun, 5 Jun 2016 15:33:59 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 39/45] ide cd: do not set REQ_WRITE on requests. Date: Sun, 5 Jun 2016 14:32:19 -0500 X-ASG-Orig-Subj: [PATCH 39/45] ide cd: do not set REQ_WRITE on requests. Message-Id: <1465155145-10812-40-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Sun, 05 Jun 2016 19:34:01 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155242 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 918 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie The block layer will set the correct READ/WRITE operation flags/fields when creating a request, so there is not need for drivers to set the REQ_WRITE flag. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- drivers/ide/ide-cd_ioctl.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c index 474173e..5887a7a 100644 --- a/drivers/ide/ide-cd_ioctl.c +++ b/drivers/ide/ide-cd_ioctl.c @@ -459,9 +459,6 @@ int ide_cdrom_packet(struct cdrom_device_info *cdi, layer. the packet must be complete, as we do not touch it at all. */ - if (cgc->data_direction == CGC_DATA_WRITE) - flags |= REQ_WRITE; - if (cgc->sense) memset(cgc->sense, 0, sizeof(struct request_sense)); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 838E87D66 for ; Sun, 5 Jun 2016 14:34:06 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0077AAC003 for ; Sun, 5 Jun 2016 12:34:05 -0700 (PDT) X-ASG-Debug-ID: 1465155244-04cbb0356ab8ac60001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 4MAjkNKY3qtoCluX (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:05 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1F5C27267C; Sun, 5 Jun 2016 19:34:04 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9l003130; Sun, 5 Jun 2016 15:34:01 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 40/45] block: move bio io prio to a new field Date: Sun, 5 Jun 2016 14:32:20 -0500 X-ASG-Orig-Subj: [PATCH 40/45] block: move bio io prio to a new field Message-Id: <1465155145-10812-41-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 05 Jun 2016 19:34:04 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155244 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1916 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie In the next patch, we move drop the compat code and make the op a separate value that is hidden in bi_rw. To give the op and rq bits flags room to grow this moves prio to its own field. Signed-off-by: Mike Christie --- include/linux/bio.h | 14 ++------------ include/linux/blk_types.h | 5 ++--- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/include/linux/bio.h b/include/linux/bio.h index 4568647..35108c2 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -47,18 +47,8 @@ #define bio_op(bio) (op_from_rq_bits((bio)->bi_rw)) #define bio_set_op_attrs(bio, op, flags) ((bio)->bi_rw |= (op | flags)) -/* - * upper 16 bits of bi_rw define the io priority of this bio - */ -#define BIO_PRIO_SHIFT (8 * sizeof(unsigned long) - IOPRIO_BITS) -#define bio_prio(bio) ((bio)->bi_rw >> BIO_PRIO_SHIFT) -#define bio_prio_valid(bio) ioprio_valid(bio_prio(bio)) - -#define bio_set_prio(bio, prio) do { \ - WARN_ON(prio >= (1 << IOPRIO_BITS)); \ - (bio)->bi_rw &= ((1UL << BIO_PRIO_SHIFT) - 1); \ - (bio)->bi_rw |= ((unsigned long) (prio) << BIO_PRIO_SHIFT); \ -} while (0) +#define bio_prio(bio) (bio)->bi_ioprio +#define bio_set_prio(bio, prio) ((bio)->bi_ioprio = prio) /* * various member access, note that bio_data should of course not be used diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 6e60baa..2738413 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -48,9 +48,8 @@ struct bio { struct block_device *bi_bdev; unsigned int bi_flags; /* status, command, etc */ int bi_error; - unsigned long bi_rw; /* bottom bits READ/WRITE, - * top bits priority - */ + unsigned long bi_rw; /* READ/WRITE */ + unsigned short bi_ioprio; struct bvec_iter bi_iter; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B2E137D68 for ; Sun, 5 Jun 2016 14:34:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3BB91AC005 for ; Sun, 5 Jun 2016 12:34:08 -0700 (PDT) X-ASG-Debug-ID: 1465155246-04cb6c2dbcb58e60001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id VBD9nkilYv0uzDiK (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:07 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4AD527302D; Sun, 5 Jun 2016 19:34:06 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9m003130; Sun, 5 Jun 2016 15:34:04 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 41/45] block, drivers, fs: shrink bi_rw from long to int Date: Sun, 5 Jun 2016 14:32:21 -0500 X-ASG-Orig-Subj: [PATCH 41/45] block, drivers, fs: shrink bi_rw from long to int Message-Id: <1465155145-10812-42-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 05 Jun 2016 19:34:06 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155246 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4825 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie We don't need bi_rw to be so large on 64 bit archs, so reduce it to unsigned int. Signed-off-by: Mike Christie --- block/blk-core.c | 2 +- drivers/md/dm-flakey.c | 2 +- drivers/md/raid5.c | 6 +++--- fs/btrfs/check-integrity.c | 4 ++-- fs/btrfs/inode.c | 2 +- include/linux/blk_types.h | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index f9f4228..c7d66c2 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1853,7 +1853,7 @@ static void handle_bad_sector(struct bio *bio) char b[BDEVNAME_SIZE]; printk(KERN_INFO "attempt to access beyond end of device\n"); - printk(KERN_INFO "%s: rw=%ld, want=%Lu, limit=%Lu\n", + printk(KERN_INFO "%s: rw=%d, want=%Lu, limit=%Lu\n", bdevname(bio->bi_bdev, b), bio->bi_rw, (unsigned long long)bio_end_sector(bio), diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index b7341de..29b99fb 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -266,7 +266,7 @@ static void corrupt_bio_data(struct bio *bio, struct flakey_c *fc) data[fc->corrupt_bio_byte - 1] = fc->corrupt_bio_value; DMDEBUG("Corrupting data bio=%p by writing %u to byte %u " - "(rw=%c bi_rw=%lu bi_sector=%llu cur_bytes=%u)\n", + "(rw=%c bi_rw=%u bi_sector=%llu cur_bytes=%u)\n", bio, fc->corrupt_bio_value, fc->corrupt_bio_byte, (bio_data_dir(bio) == WRITE) ? 'w' : 'r', bio->bi_rw, (unsigned long long)bio->bi_iter.bi_sector, bio_bytes); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index e35c163..b9122e2 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1001,7 +1001,7 @@ again: : raid5_end_read_request; bi->bi_private = sh; - pr_debug("%s: for %llu schedule op %ld on disc %d\n", + pr_debug("%s: for %llu schedule op %d on disc %d\n", __func__, (unsigned long long)sh->sector, bi->bi_rw, i); atomic_inc(&sh->count); @@ -1052,7 +1052,7 @@ again: rbi->bi_end_io = raid5_end_write_request; rbi->bi_private = sh; - pr_debug("%s: for %llu schedule op %ld on " + pr_debug("%s: for %llu schedule op %d on " "replacement disc %d\n", __func__, (unsigned long long)sh->sector, rbi->bi_rw, i); @@ -1087,7 +1087,7 @@ again: if (!rdev && !rrdev) { if (op_is_write(op)) set_bit(STRIPE_DEGRADED, &sh->state); - pr_debug("skip op %ld on disc %d for sector %llu\n", + pr_debug("skip op %d on disc %d for sector %llu\n", bi->bi_rw, i, (unsigned long long)sh->sector); clear_bit(R5_LOCKED, &sh->dev[i].flags); set_bit(STRIPE_HANDLE, &sh->state); diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index 80a4389..da944ff 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -2943,7 +2943,7 @@ static void __btrfsic_submit_bio(struct bio *bio) if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO - "submit_bio(rw=%d,0x%lx, bi_vcnt=%u," + "submit_bio(rw=%d,0x%x, bi_vcnt=%u," " bi_sector=%llu (bytenr %llu), bi_bdev=%p)\n", bio_op(bio), bio->bi_rw, bio->bi_vcnt, (unsigned long long)bio->bi_iter.bi_sector, @@ -2986,7 +2986,7 @@ static void __btrfsic_submit_bio(struct bio *bio) if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO - "submit_bio(rw=%d,0x%lx FLUSH, bdev=%p)\n", + "submit_bio(rw=%d,0x%x FLUSH, bdev=%p)\n", bio_op(bio), bio->bi_rw, bio->bi_bdev); if (!dev_state->dummy_block_for_bio_bh_flush.is_iodone) { if ((dev_state->state->print_mask & diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 128b02b..412e582 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8173,7 +8173,7 @@ static void btrfs_end_dio_bio(struct bio *bio) if (err) btrfs_warn(BTRFS_I(dip->inode)->root->fs_info, - "direct IO failed ino %llu rw %d,%lu sector %#Lx len %u err no %d", + "direct IO failed ino %llu rw %d,%u sector %#Lx len %u err no %d", btrfs_ino(dip->inode), bio_op(bio), bio->bi_rw, (unsigned long long)bio->bi_iter.bi_sector, bio->bi_iter.bi_size, err); diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 2738413..5efb6f1 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -48,7 +48,7 @@ struct bio { struct block_device *bi_bdev; unsigned int bi_flags; /* status, command, etc */ int bi_error; - unsigned long bi_rw; /* READ/WRITE */ + unsigned int bi_rw; /* READ/WRITE */ unsigned short bi_ioprio; struct bvec_iter bi_iter; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A2A137CFF for ; Sun, 5 Jun 2016 14:34:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2AC1FAC003 for ; Sun, 5 Jun 2016 12:34:11 -0700 (PDT) X-ASG-Debug-ID: 1465155248-04cbb03568b8ac60001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id YMqfpHLeOpdFADIi (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:09 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 97AC673058; Sun, 5 Jun 2016 19:34:08 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9n003130; Sun, 5 Jun 2016 15:34:06 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code Date: Sun, 5 Jun 2016 14:32:22 -0500 X-ASG-Orig-Subj: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code Message-Id: <1465155145-10812-43-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 05 Jun 2016 19:34:08 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155249 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10659 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This patch drops the compat definition of req_op where it matches the rq_flag_bits definitions, and drops the related old and compat code that allowed users to set either the op or flags for the operation. We also then store the operation in the bi_rw/cmd_flags field similar to how we used to store the bio ioprio where it sat in the upper bits of the field. Signed-off-by: Mike Christie --- drivers/scsi/sd.c | 2 +- include/linux/bio.h | 3 --- include/linux/blk_types.h | 52 +++++++++++++++++---------------------------- include/linux/blkdev.h | 14 ++++++++---- include/linux/fs.h | 37 +++++++++++++------------------- include/trace/events/f2fs.h | 1 - 6 files changed, 46 insertions(+), 63 deletions(-) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index c8dc221..fad86ad 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1012,7 +1012,7 @@ static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_6; } else { - scmd_printk(KERN_ERR, SCpnt, "Unknown command %d,%llx\n", + scmd_printk(KERN_ERR, SCpnt, "Unknown command %llu,%llx\n", req_op(rq), (unsigned long long) rq->cmd_flags); goto out; } diff --git a/include/linux/bio.h b/include/linux/bio.h index 35108c2..0bbb2e3 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -44,9 +44,6 @@ #define BIO_MAX_SIZE (BIO_MAX_PAGES << PAGE_SHIFT) #define BIO_MAX_SECTORS (BIO_MAX_SIZE >> 9) -#define bio_op(bio) (op_from_rq_bits((bio)->bi_rw)) -#define bio_set_op_attrs(bio, op, flags) ((bio)->bi_rw |= (op | flags)) - #define bio_prio(bio) (bio)->bi_ioprio #define bio_set_prio(bio, prio) ((bio)->bi_ioprio = prio) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 5efb6f1..23c1ab2 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -48,7 +48,9 @@ struct bio { struct block_device *bi_bdev; unsigned int bi_flags; /* status, command, etc */ int bi_error; - unsigned int bi_rw; /* READ/WRITE */ + unsigned int bi_rw; /* bottom bits req flags, + * top bits REQ_OP + */ unsigned short bi_ioprio; struct bvec_iter bi_iter; @@ -106,6 +108,16 @@ struct bio { struct bio_vec bi_inline_vecs[0]; }; +#define BIO_OP_SHIFT (8 * sizeof(unsigned int) - REQ_OP_BITS) +#define bio_op(bio) ((bio)->bi_rw >> BIO_OP_SHIFT) + +#define bio_set_op_attrs(bio, op, op_flags) do { \ + WARN_ON(op >= (1 << REQ_OP_BITS)); \ + (bio)->bi_rw &= ((1 << BIO_OP_SHIFT) - 1); \ + (bio)->bi_rw |= ((unsigned int) (op) << BIO_OP_SHIFT); \ + (bio)->bi_rw |= op_flags; \ +} while (0) + #define BIO_RESET_BYTES offsetof(struct bio, bi_max_vecs) /* @@ -144,7 +156,6 @@ struct bio { */ enum rq_flag_bits { /* common flags */ - __REQ_WRITE, /* not set, read. set, write */ __REQ_FAILFAST_DEV, /* no driver retries of device errors */ __REQ_FAILFAST_TRANSPORT, /* no driver retries of transport errors */ __REQ_FAILFAST_DRIVER, /* no driver retries of driver errors */ @@ -152,9 +163,7 @@ enum rq_flag_bits { __REQ_SYNC, /* request is sync (sync write or read) */ __REQ_META, /* metadata io request */ __REQ_PRIO, /* boost priority in cfq */ - __REQ_DISCARD, /* request to discard sectors */ - __REQ_SECURE, /* secure discard (used with __REQ_DISCARD) */ - __REQ_WRITE_SAME, /* write same block many times */ + __REQ_SECURE, /* secure discard (used with REQ_OP_DISCARD) */ __REQ_NOIDLE, /* don't anticipate more IO after this one */ __REQ_INTEGRITY, /* I/O includes block integrity payload */ @@ -190,28 +199,22 @@ enum rq_flag_bits { __REQ_NR_BITS, /* stops here */ }; -#define REQ_WRITE (1ULL << __REQ_WRITE) #define REQ_FAILFAST_DEV (1ULL << __REQ_FAILFAST_DEV) #define REQ_FAILFAST_TRANSPORT (1ULL << __REQ_FAILFAST_TRANSPORT) #define REQ_FAILFAST_DRIVER (1ULL << __REQ_FAILFAST_DRIVER) #define REQ_SYNC (1ULL << __REQ_SYNC) #define REQ_META (1ULL << __REQ_META) #define REQ_PRIO (1ULL << __REQ_PRIO) -#define REQ_DISCARD (1ULL << __REQ_DISCARD) -#define REQ_WRITE_SAME (1ULL << __REQ_WRITE_SAME) #define REQ_NOIDLE (1ULL << __REQ_NOIDLE) #define REQ_INTEGRITY (1ULL << __REQ_INTEGRITY) #define REQ_FAILFAST_MASK \ (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) #define REQ_COMMON_MASK \ - (REQ_WRITE | REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | \ - REQ_DISCARD | REQ_WRITE_SAME | REQ_NOIDLE | REQ_FLUSH | REQ_FUA | \ - REQ_SECURE | REQ_INTEGRITY | REQ_NOMERGE) + (REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | REQ_NOIDLE | \ + REQ_FLUSH | REQ_FUA | REQ_SECURE | REQ_INTEGRITY | REQ_NOMERGE) #define REQ_CLONE_MASK REQ_COMMON_MASK -#define BIO_NO_ADVANCE_ITER_MASK (REQ_DISCARD|REQ_WRITE_SAME) - /* This mask is used for both bio and request merge checking */ #define REQ_NOMERGE_FLAGS \ (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_FLUSH_SEQ) @@ -243,27 +246,12 @@ enum rq_flag_bits { enum req_op { REQ_OP_READ, - REQ_OP_WRITE = REQ_WRITE, - REQ_OP_DISCARD = REQ_DISCARD, - REQ_OP_WRITE_SAME = REQ_WRITE_SAME, + REQ_OP_WRITE, + REQ_OP_DISCARD, /* request to discard sectors */ + REQ_OP_WRITE_SAME, /* write same block many times */ }; -/* - * tmp cpmpat. Users used to set the write bit for all non reads, but - * we will be dropping the bitmap use for ops. Support both until - * the end of the patchset. - */ -static inline int op_from_rq_bits(u64 flags) -{ - if (flags & REQ_OP_DISCARD) - return REQ_OP_DISCARD; - else if (flags & REQ_OP_WRITE_SAME) - return REQ_OP_WRITE_SAME; - else if (flags & REQ_OP_WRITE) - return REQ_OP_WRITE; - else - return REQ_OP_READ; -} +#define REQ_OP_BITS 2 typedef unsigned int blk_qc_t; #define BLK_QC_T_NONE -1U diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 4937c05..78ae3db 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -200,8 +200,15 @@ struct request { struct request *next_rq; }; -#define req_op(req) (op_from_rq_bits((req)->cmd_flags)) -#define req_set_op(req, op) ((req)->cmd_flags |= op) +#define REQ_OP_SHIFT (8 * sizeof(u64) - REQ_OP_BITS) +#define req_op(req) ((req)->cmd_flags >> REQ_OP_SHIFT) + +#define req_set_op(req, op) do { \ + WARN_ON(op >= (1 << REQ_OP_BITS)); \ + (req)->cmd_flags &= ((1ULL << REQ_OP_SHIFT) - 1); \ + (req)->cmd_flags |= ((u64) (op) << REQ_OP_SHIFT); \ +} while (0) + #define req_set_op_attrs(req, op, flags) do { \ req_set_op(req, op); \ (req)->cmd_flags |= flags; \ @@ -604,8 +611,7 @@ static inline void queue_flag_clear(unsigned int flag, struct request_queue *q) #define list_entry_rq(ptr) list_entry((ptr), struct request, queuelist) -#define rq_data_dir(rq) \ - (op_is_write(op_from_rq_bits(rq->cmd_flags)) ? WRITE : READ) +#define rq_data_dir(rq) (op_is_write(req_op(rq)) ? WRITE : READ) /* * Driver can handle struct request, if it either has an old style diff --git a/include/linux/fs.h b/include/linux/fs.h index af6f3c7..ccd1664 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -152,9 +152,10 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define CHECK_IOVEC_ONLY -1 /* - * The below are the various read and write types that we support. Some of + * The below are the various read and write flags that we support. Some of * them include behavioral modifiers that send information down to the - * block layer and IO scheduler. Terminology: + * block layer and IO scheduler. They should be used along with a req_op. + * Terminology: * * The block layer uses device plugging to defer IO a little bit, in * the hope that we will see more IO very shortly. This increases @@ -193,19 +194,19 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, * non-volatile media on completion. * */ -#define RW_MASK REQ_WRITE +#define RW_MASK REQ_OP_WRITE #define RWA_MASK REQ_RAHEAD -#define READ 0 +#define READ REQ_OP_READ #define WRITE RW_MASK #define READA RWA_MASK -#define READ_SYNC (READ | REQ_SYNC) -#define WRITE_SYNC (WRITE | REQ_SYNC | REQ_NOIDLE) -#define WRITE_ODIRECT (WRITE | REQ_SYNC) -#define WRITE_FLUSH (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH) -#define WRITE_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FUA) -#define WRITE_FLUSH_FUA (WRITE | REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA) +#define READ_SYNC REQ_SYNC +#define WRITE_SYNC (REQ_SYNC | REQ_NOIDLE) +#define WRITE_ODIRECT REQ_SYNC +#define WRITE_FLUSH (REQ_SYNC | REQ_NOIDLE | REQ_FLUSH) +#define WRITE_FUA (REQ_SYNC | REQ_NOIDLE | REQ_FUA) +#define WRITE_FLUSH_FUA (REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA) /* * Attribute flags. These should be or-ed together to figure out what @@ -2464,17 +2465,9 @@ extern void make_bad_inode(struct inode *); extern bool is_bad_inode(struct inode *); #ifdef CONFIG_BLOCK -/* - * tmp cpmpat. Users used to set the write bit for all non reads, but - * we will be dropping the bitmap use for ops. Support both until - * the end of the patchset. - */ -static inline bool op_is_write(unsigned long flags) +static inline bool op_is_write(unsigned int op) { - if (flags & (REQ_OP_WRITE | REQ_OP_WRITE_SAME | REQ_OP_DISCARD)) - return true; - else - return false; + return op == REQ_OP_READ ? false : true; } /* @@ -2482,7 +2475,7 @@ static inline bool op_is_write(unsigned long flags) */ static inline int bio_rw(struct bio *bio) { - if (op_is_write(op_from_rq_bits(bio->bi_rw))) + if (op_is_write(bio_op(bio))) return WRITE; return bio->bi_rw & RWA_MASK; @@ -2493,7 +2486,7 @@ static inline int bio_rw(struct bio *bio) */ static inline int bio_data_dir(struct bio *bio) { - return op_is_write(op_from_rq_bits(bio->bi_rw)) ? WRITE : READ; + return op_is_write(bio_op(bio)) ? WRITE : READ; } extern void check_disk_size_change(struct gendisk *disk, diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 733b896..30efa44 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -31,7 +31,6 @@ TRACE_DEFINE_ENUM(BG_GC); TRACE_DEFINE_ENUM(LFS); TRACE_DEFINE_ENUM(SSR); TRACE_DEFINE_ENUM(__REQ_RAHEAD); -TRACE_DEFINE_ENUM(__REQ_WRITE); TRACE_DEFINE_ENUM(__REQ_SYNC); TRACE_DEFINE_ENUM(__REQ_NOIDLE); TRACE_DEFINE_ENUM(__REQ_FLUSH); -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 939E97CB7 for ; Sun, 5 Jun 2016 14:34:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5379F304043 for ; Sun, 5 Jun 2016 12:34:13 -0700 (PDT) X-ASG-Debug-ID: 1465155251-04bdf05ad5b78500001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id QCbxPXbeEESWjylW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:11 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DD7C9C04D2AD; Sun, 5 Jun 2016 19:34:10 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9o003130; Sun, 5 Jun 2016 15:34:08 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 43/45] block, drivers: add REQ_OP_FLUSH operation Date: Sun, 5 Jun 2016 14:32:23 -0500 X-ASG-Orig-Subj: [PATCH 43/45] block, drivers: add REQ_OP_FLUSH operation Message-Id: <1465155145-10812-44-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Sun, 05 Jun 2016 19:34:11 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155251 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15621 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie This adds a REQ_OP_FLUSH operation that is sent to request_fn based drivers by the block layer's flush code, instead of sending requests with the request->cmd_flags REQ_FLUSH bit set. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- v2. 1. Fix kbuild failures. Forgot to update ubd driver. Documentation/block/writeback_cache_control.txt | 6 +++--- arch/um/drivers/ubd_kern.c | 2 +- block/blk-flush.c | 4 ++-- drivers/block/loop.c | 4 ++-- drivers/block/nbd.c | 2 +- drivers/block/osdblk.c | 2 +- drivers/block/ps3disk.c | 4 ++-- drivers/block/skd_main.c | 2 +- drivers/block/virtio_blk.c | 2 +- drivers/block/xen-blkfront.c | 8 ++++---- drivers/ide/ide-disk.c | 2 +- drivers/md/dm.c | 2 +- drivers/mmc/card/block.c | 6 +++--- drivers/mmc/card/queue.h | 3 ++- drivers/mtd/mtd_blkdevs.c | 2 +- drivers/nvme/host/core.c | 2 +- drivers/scsi/sd.c | 7 +++---- include/linux/blk_types.h | 3 ++- include/linux/blkdev.h | 3 +++ kernel/trace/blktrace.c | 5 +++++ 20 files changed, 40 insertions(+), 31 deletions(-) diff --git a/Documentation/block/writeback_cache_control.txt b/Documentation/block/writeback_cache_control.txt index 59e0516..da70bda 100644 --- a/Documentation/block/writeback_cache_control.txt +++ b/Documentation/block/writeback_cache_control.txt @@ -73,9 +73,9 @@ doing: blk_queue_write_cache(sdkp->disk->queue, true, false); -and handle empty REQ_FLUSH requests in its prep_fn/request_fn. Note that +and handle empty REQ_OP_FLUSH requests in its prep_fn/request_fn. Note that REQ_FLUSH requests with a payload are automatically turned into a sequence -of an empty REQ_FLUSH request followed by the actual write by the block +of an empty REQ_OP_FLUSH request followed by the actual write by the block layer. For devices that also support the FUA bit the block layer needs to be told to pass through the REQ_FUA bit using: @@ -83,4 +83,4 @@ to be told to pass through the REQ_FUA bit using: and the driver must handle write requests that have the REQ_FUA bit set in prep_fn/request_fn. If the FUA bit is not natively supported the block -layer turns it into an empty REQ_FLUSH request after the actual write. +layer turns it into an empty REQ_OP_FLUSH request after the actual write. diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 17e96dc..ef6b4d9 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1286,7 +1286,7 @@ static void do_ubd_request(struct request_queue *q) req = dev->request; - if (req->cmd_flags & REQ_FLUSH) { + if (req_op(req) == REQ_OP_FLUSH) { io_req = kmalloc(sizeof(struct io_thread_req), GFP_ATOMIC); if (io_req == NULL) { diff --git a/block/blk-flush.c b/block/blk-flush.c index 9fd1f63..21f0d5b 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -29,7 +29,7 @@ * The actual execution of flush is double buffered. Whenever a request * needs to execute PRE or POSTFLUSH, it queues at * fq->flush_queue[fq->flush_pending_idx]. Once certain criteria are met, a - * flush is issued and the pending_idx is toggled. When the flush + * REQ_OP_FLUSH is issued and the pending_idx is toggled. When the flush * completes, all the requests which were pending are proceeded to the next * step. This allows arbitrary merging of different types of FLUSH/FUA * requests. @@ -330,7 +330,7 @@ static bool blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq) } flush_rq->cmd_type = REQ_TYPE_FS; - flush_rq->cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ; + req_set_op_attrs(flush_rq, REQ_OP_FLUSH, WRITE_FLUSH | REQ_FLUSH_SEQ); flush_rq->rq_disk = first_rq->rq_disk; flush_rq->end_io = flush_end_io; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index b9b737c..364d491 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -542,7 +542,7 @@ static int do_req_filebacked(struct loop_device *lo, struct request *rq) pos = ((loff_t) blk_rq_pos(rq) << 9) + lo->lo_offset; if (op_is_write(req_op(rq))) { - if (rq->cmd_flags & REQ_FLUSH) + if (req_op(rq) == REQ_OP_FLUSH) ret = lo_req_flush(lo, rq); else if (req_op(rq) == REQ_OP_DISCARD) ret = lo_discard(lo, rq, pos); @@ -1659,7 +1659,7 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx, if (lo->lo_state != Lo_bound) return -EIO; - if (lo->use_dio && (!(cmd->rq->cmd_flags & REQ_FLUSH) || + if (lo->use_dio && (req_op(cmd->rq) != REQ_OP_FLUSH || req_op(cmd->rq) == REQ_OP_DISCARD)) cmd->use_aio = true; else diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 6c2c28d..d6f3c93 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -284,7 +284,7 @@ static int nbd_send_req(struct nbd_device *nbd, struct request *req) type = NBD_CMD_DISC; else if (req_op(req) == REQ_OP_DISCARD) type = NBD_CMD_TRIM; - else if (req->cmd_flags & REQ_FLUSH) + else if (req_op(req) == REQ_OP_FLUSH) type = NBD_CMD_FLUSH; else if (rq_data_dir(req) == WRITE) type = NBD_CMD_WRITE; diff --git a/drivers/block/osdblk.c b/drivers/block/osdblk.c index c2854a2..92900f5 100644 --- a/drivers/block/osdblk.c +++ b/drivers/block/osdblk.c @@ -321,7 +321,7 @@ static void osdblk_rq_fn(struct request_queue *q) * driver-specific, etc. */ - do_flush = rq->cmd_flags & REQ_FLUSH; + do_flush = (req_op(rq) == REQ_OP_FLUSH); do_write = (rq_data_dir(rq) == WRITE); if (!do_flush) { /* osd_flush does not use a bio */ diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index 4b7e405..acb4452 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c @@ -196,7 +196,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); while ((req = blk_fetch_request(q))) { - if (req->cmd_flags & REQ_FLUSH) { + if (req_op(req) == REQ_OP_FLUSH) { if (ps3disk_submit_flush_request(dev, req)) break; } else if (req->cmd_type == REQ_TYPE_FS) { @@ -256,7 +256,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) return IRQ_HANDLED; } - if (req->cmd_flags & REQ_FLUSH) { + if (req_op(req) == REQ_OP_FLUSH) { read = 0; op = "flush"; } else { diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 910e065..5c07a23 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -597,7 +597,7 @@ static void skd_request_fn(struct request_queue *q) data_dir = rq_data_dir(req); io_flags = req->cmd_flags; - if (io_flags & REQ_FLUSH) + if (req_op(req) == REQ_OP_FLUSH) flush++; if (io_flags & REQ_FUA) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 42758b5..18e4069 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -172,7 +172,7 @@ static int virtio_queue_rq(struct blk_mq_hw_ctx *hctx, BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); vbr->req = req; - if (req->cmd_flags & REQ_FLUSH) { + if (req_op(req) == REQ_OP_FLUSH) { vbr->out_hdr.type = cpu_to_virtio32(vblk->vdev, VIRTIO_BLK_T_FLUSH); vbr->out_hdr.sector = 0; vbr->out_hdr.ioprio = cpu_to_virtio32(vblk->vdev, req_get_ioprio(vbr->req)); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 6fd1601..3aeb25b 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -743,7 +743,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri * The indirect operation can only be a BLKIF_OP_READ or * BLKIF_OP_WRITE */ - BUG_ON(req->cmd_flags & (REQ_FLUSH | REQ_FUA)); + BUG_ON(req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA); ring_req->operation = BLKIF_OP_INDIRECT; ring_req->u.indirect.indirect_op = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; @@ -755,7 +755,7 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri ring_req->u.rw.handle = info->handle; ring_req->operation = rq_data_dir(req) ? BLKIF_OP_WRITE : BLKIF_OP_READ; - if (req->cmd_flags & (REQ_FLUSH | REQ_FUA)) { + if (req_op(req) == REQ_OP_FLUSH || req->cmd_flags & REQ_FUA) { /* * Ideally we can do an unordered flush-to-disk. * In case the backend onlysupports barriers, use that. @@ -865,7 +865,7 @@ static inline bool blkif_request_flush_invalid(struct request *req, struct blkfront_info *info) { return ((req->cmd_type != REQ_TYPE_FS) || - ((req->cmd_flags & REQ_FLUSH) && + ((req_op(req) == REQ_OP_FLUSH) && !(info->feature_flush & REQ_FLUSH)) || ((req->cmd_flags & REQ_FUA) && !(info->feature_flush & REQ_FUA))); @@ -2055,7 +2055,7 @@ static int blkif_recover(struct blkfront_info *info) /* * Get the bios in the request so we can re-queue them. */ - if (copy[i].request->cmd_flags & REQ_FLUSH || + if (req_op(copy[i].request) == REQ_OP_FLUSH || req_op(copy[i].request) == REQ_OP_DISCARD || copy[i].request->cmd_flags & (REQ_FUA | REQ_SECURE)) { /* diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 05dbcce..e378ef7 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -431,7 +431,7 @@ static int idedisk_prep_fn(struct request_queue *q, struct request *rq) ide_drive_t *drive = q->queuedata; struct ide_cmd *cmd; - if (!(rq->cmd_flags & REQ_FLUSH)) + if (req_op(rq) != REQ_OP_FLUSH) return BLKPREP_OK; if (rq->special) { diff --git a/drivers/md/dm.c b/drivers/md/dm.c index f6b104c..fcc68c8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2171,7 +2171,7 @@ static void dm_request_fn(struct request_queue *q) /* always use block 0 to find the target for flushes for now */ pos = 0; - if (!(rq->cmd_flags & REQ_FLUSH)) + if (req_op(rq) != REQ_OP_FLUSH) pos = blk_rq_pos(rq); if ((dm_request_peeked_before_merge_deadline(md) && diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 201a871..bca20f8 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1722,7 +1722,8 @@ static u8 mmc_blk_prep_packed_list(struct mmc_queue *mq, struct request *req) !IS_ALIGNED(blk_rq_sectors(next), 8)) break; - if (req_op(next) == REQ_OP_DISCARD || next->cmd_flags & REQ_FLUSH) + if (req_op(next) == REQ_OP_DISCARD || + req_op(next) == REQ_OP_FLUSH) break; if (rq_data_dir(cur) != rq_data_dir(next)) @@ -2147,7 +2148,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) struct mmc_card *card = md->queue.card; struct mmc_host *host = card->host; unsigned long flags; - unsigned int cmd_flags = req ? req->cmd_flags : 0; if (req && !mq->mqrq_prev->req) /* claim host only for the first request */ @@ -2171,7 +2171,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) ret = mmc_blk_issue_secdiscard_rq(mq, req); else ret = mmc_blk_issue_discard_rq(mq, req); - } else if (cmd_flags & REQ_FLUSH) { + } else if (req && req_op(req) == REQ_OP_FLUSH) { /* complete ongoing async transfer before issuing flush */ if (card->host->areq) mmc_blk_issue_rw_rq(mq, NULL); diff --git a/drivers/mmc/card/queue.h b/drivers/mmc/card/queue.h index 9fb26f2..d625311 100644 --- a/drivers/mmc/card/queue.h +++ b/drivers/mmc/card/queue.h @@ -3,7 +3,8 @@ static inline bool mmc_req_is_special(struct request *req) { - return req && (req->cmd_flags & REQ_FLUSH || req_op(req) == REQ_OP_DISCARD); + return req && + (req_op(req) == REQ_OP_FLUSH || req_op(req) == REQ_OP_DISCARD); } struct request; diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 4eb9a5f..78b3eb4 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -87,7 +87,7 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, if (req->cmd_type != REQ_TYPE_FS) return -EIO; - if (req->cmd_flags & REQ_FLUSH) + if (req_op(req) == REQ_OP_FLUSH) return tr->flush(dev); if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 089b8b8..abdfdcf 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -290,7 +290,7 @@ int nvme_setup_cmd(struct nvme_ns *ns, struct request *req, if (req->cmd_type == REQ_TYPE_DRV_PRIV) memcpy(cmd, req->cmd, sizeof(*cmd)); - else if (req->cmd_flags & REQ_FLUSH) + else if (req_op(req) == REQ_OP_FLUSH) nvme_setup_flush(ns, cmd); else if (req_op(req) == REQ_OP_DISCARD) ret = nvme_setup_discard(ns, req, cmd); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fad86ad..5a9db0f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1143,12 +1143,11 @@ static int sd_init_command(struct scsi_cmnd *cmd) return sd_setup_discard_cmnd(cmd); case REQ_OP_WRITE_SAME: return sd_setup_write_same_cmnd(cmd); + case REQ_OP_FLUSH: + return sd_setup_flush_cmnd(cmd); case REQ_OP_READ: case REQ_OP_WRITE: - if (rq->cmd_flags & REQ_FLUSH) - return sd_setup_flush_cmnd(cmd); - else - return sd_setup_read_write_cmnd(cmd); + return sd_setup_read_write_cmnd(cmd); default: BUG(); } diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 23c1ab2..32d8752 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -249,9 +249,10 @@ enum req_op { REQ_OP_WRITE, REQ_OP_DISCARD, /* request to discard sectors */ REQ_OP_WRITE_SAME, /* write same block many times */ + REQ_OP_FLUSH, /* request for cache flush */ }; -#define REQ_OP_BITS 2 +#define REQ_OP_BITS 3 typedef unsigned int blk_qc_t; #define BLK_QC_T_NONE -1U diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 78ae3db..0c9f879 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -666,6 +666,9 @@ static inline bool rq_mergeable(struct request *rq) if (rq->cmd_type != REQ_TYPE_FS) return false; + if (req_op(rq) == REQ_OP_FLUSH) + return false; + if (rq->cmd_flags & REQ_NOMERGE_FLAGS) return false; diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 2d16fad..0c70fbb 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -223,6 +223,8 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, what |= MASK_TC_BIT(op_flags, FUA); if (op == REQ_OP_DISCARD) what |= BLK_TC_ACT(BLK_TC_DISCARD); + if (op == REQ_OP_FLUSH) + what |= BLK_TC_ACT(BLK_TC_FLUSH); pid = tsk->pid; if (act_log_check(bt, what, sector, pid)) @@ -1788,6 +1790,9 @@ void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes) case REQ_OP_DISCARD: rwbs[i++] = 'D'; break; + case REQ_OP_FLUSH: + rwbs[i++] = 'F'; + break; case REQ_OP_READ: rwbs[i++] = 'R'; break; -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D3B187CE3 for ; Sun, 5 Jun 2016 14:34:15 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 99CAE8F8037 for ; Sun, 5 Jun 2016 12:34:15 -0700 (PDT) X-ASG-Debug-ID: 1465155254-04cbb0356ab8ac70001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id iniAamjPHBSEKVUN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:14 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 992A8C01605A; Sun, 5 Jun 2016 19:34:13 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9p003130; Sun, 5 Jun 2016 15:34:10 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie , Juergen Gross Subject: [PATCH 44/45] block: do not use REQ_FLUSH for tracking flush support Date: Sun, 5 Jun 2016 14:32:24 -0500 X-ASG-Orig-Subj: [PATCH 44/45] block: do not use REQ_FLUSH for tracking flush support Message-Id: <1465155145-10812-45-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Sun, 05 Jun 2016 19:34:13 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155254 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4945 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie The last patch added a REQ_OP_FLUSH for request_fn drivers and the next patch renames REQ_FLUSH to REQ_PREFLUSH which will be used by file systems and make_request_fn drivers so they can send a write/flush combo. This patch drops xen's use of REQ_FLUSH to track if it supports REQ_OP_FLUSH requests, so REQ_FLUSH can be deleted. Signed-off-by: Mike Christie Reviewed-by: Hannes Reinecke Signed-off-by: Juergen Gross --- v7: - Fix feature_flush/fua use. v6: - Dropped parts of patch handled by Jens's QUEUE_FLAG_WC/FUA patches and modified patch to check feature_flush/fua bits. drivers/block/xen-blkfront.c | 47 ++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 3aeb25b..343ef7a 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -196,6 +196,7 @@ struct blkfront_info unsigned int nr_ring_pages; struct request_queue *rq; unsigned int feature_flush; + unsigned int feature_fua; unsigned int feature_discard:1; unsigned int feature_secdiscard:1; unsigned int discard_granularity; @@ -763,19 +764,14 @@ static int blkif_queue_rw_req(struct request *req, struct blkfront_ring_info *ri * implement it the same way. (It's also a FLUSH+FUA, * since it is guaranteed ordered WRT previous writes.) */ - switch (info->feature_flush & - ((REQ_FLUSH|REQ_FUA))) { - case REQ_FLUSH|REQ_FUA: + if (info->feature_flush && info->feature_fua) ring_req->operation = BLKIF_OP_WRITE_BARRIER; - break; - case REQ_FLUSH: + else if (info->feature_flush) ring_req->operation = BLKIF_OP_FLUSH_DISKCACHE; - break; - default: + else ring_req->operation = 0; - } } ring_req->u.rw.nr_segments = num_grant; if (unlikely(require_extra_req)) { @@ -866,9 +862,9 @@ static inline bool blkif_request_flush_invalid(struct request *req, { return ((req->cmd_type != REQ_TYPE_FS) || ((req_op(req) == REQ_OP_FLUSH) && - !(info->feature_flush & REQ_FLUSH)) || + !info->feature_flush) || ((req->cmd_flags & REQ_FUA) && - !(info->feature_flush & REQ_FUA))); + !info->feature_fua)); } static int blkif_queue_rq(struct blk_mq_hw_ctx *hctx, @@ -985,24 +981,22 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size, return 0; } -static const char *flush_info(unsigned int feature_flush) +static const char *flush_info(struct blkfront_info *info) { - switch (feature_flush & ((REQ_FLUSH | REQ_FUA))) { - case REQ_FLUSH|REQ_FUA: + if (info->feature_flush && info->feature_fua) return "barrier: enabled;"; - case REQ_FLUSH: + else if (info->feature_flush) return "flush diskcache: enabled;"; - default: + else return "barrier or flush: disabled;"; - } } static void xlvbd_flush(struct blkfront_info *info) { - blk_queue_write_cache(info->rq, info->feature_flush & REQ_FLUSH, - info->feature_flush & REQ_FUA); + blk_queue_write_cache(info->rq, info->feature_flush ? true : false, + info->feature_fua ? true : false); pr_info("blkfront: %s: %s %s %s %s %s\n", - info->gd->disk_name, flush_info(info->feature_flush), + info->gd->disk_name, flush_info(info), "persistent grants:", info->feature_persistent ? "enabled;" : "disabled;", "indirect descriptors:", info->max_indirect_segments ? "enabled;" : "disabled;"); @@ -1621,6 +1615,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) if (unlikely(error)) { if (error == -EOPNOTSUPP) error = 0; + info->feature_fua = 0; info->feature_flush = 0; xlvbd_flush(info); } @@ -2315,6 +2310,7 @@ static void blkfront_gather_backend_features(struct blkfront_info *info) unsigned int indirect_segments; info->feature_flush = 0; + info->feature_fua = 0; err = xenbus_gather(XBT_NIL, info->xbdev->otherend, "feature-barrier", "%d", &barrier, @@ -2327,8 +2323,11 @@ static void blkfront_gather_backend_features(struct blkfront_info *info) * * If there are barriers, then we use flush. */ - if (!err && barrier) - info->feature_flush = REQ_FLUSH | REQ_FUA; + if (!err && barrier) { + info->feature_flush = 1; + info->feature_fua = 1; + } + /* * And if there is "feature-flush-cache" use that above * barriers. @@ -2337,8 +2336,10 @@ static void blkfront_gather_backend_features(struct blkfront_info *info) "feature-flush-cache", "%d", &flush, NULL); - if (!err && flush) - info->feature_flush = REQ_FLUSH; + if (!err && flush) { + info->feature_flush = 1; + info->feature_fua = 0; + } err = xenbus_gather(XBT_NIL, info->xbdev->otherend, "feature-discard", "%d", &discard, -- 2.7.2 From mchristi@redhat.com Sun Jun 5 14:34:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 115347D05 for ; Sun, 5 Jun 2016 14:34:20 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id B56D78F8037 for ; Sun, 5 Jun 2016 12:34:19 -0700 (PDT) X-ASG-Debug-ID: 1465155256-04bdf05ad4b78510001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id jnjI3kpQ5xEZADld (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 12:34:16 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E065411277A; Sun, 5 Jun 2016 19:34:15 +0000 (UTC) Received: from rh2.redhat.com (vpn-57-172.rdu2.redhat.com [10.10.57.172]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u55JWR9q003130; Sun, 5 Jun 2016 15:34:13 -0400 From: mchristi@redhat.com To: linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com Cc: Mike Christie Subject: [PATCH 45/45] block, drivers, fs: rename REQ_FLUSH to REQ_PREFLUSH Date: Sun, 5 Jun 2016 14:32:25 -0500 X-ASG-Orig-Subj: [PATCH 45/45] block, drivers, fs: rename REQ_FLUSH to REQ_PREFLUSH Message-Id: <1465155145-10812-46-git-send-email-mchristi@redhat.com> In-Reply-To: <1465155145-10812-1-git-send-email-mchristi@redhat.com> References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sun, 05 Jun 2016 19:34:16 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465155256 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 40335 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: Mike Christie To avoid confusion between REQ_OP_FLUSH, which is handled by request_fn drivers, and upper layers requesting the block layer perform a flush sequence along with possibly a WRITE, this patch renames REQ_FLUSH to REQ_PREFLUSH. Signed-off-by: Mike Christie Reviewed-by: Christoph Hellwig Reviewed-by: Hannes Reinecke --- Documentation/block/writeback_cache_control.txt | 22 +++++++++++----------- Documentation/device-mapper/log-writes.txt | 10 +++++----- block/blk-core.c | 12 ++++++------ block/blk-flush.c | 16 ++++++++-------- block/blk-mq.c | 4 ++-- drivers/block/drbd/drbd_actlog.c | 4 ++-- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_protocol.h | 2 +- drivers/block/drbd/drbd_receiver.c | 2 +- drivers/block/drbd/drbd_req.c | 2 +- drivers/md/bcache/journal.c | 2 +- drivers/md/bcache/request.c | 8 ++++---- drivers/md/dm-cache-target.c | 12 ++++++------ drivers/md/dm-crypt.c | 7 ++++--- drivers/md/dm-era-target.c | 4 ++-- drivers/md/dm-io.c | 2 +- drivers/md/dm-log-writes.c | 2 +- drivers/md/dm-raid1.c | 5 +++-- drivers/md/dm-region-hash.c | 4 ++-- drivers/md/dm-snap.c | 6 +++--- drivers/md/dm-stripe.c | 2 +- drivers/md/dm-thin.c | 8 ++++---- drivers/md/dm.c | 12 ++++++------ drivers/md/linear.c | 2 +- drivers/md/md.c | 2 +- drivers/md/md.h | 2 +- drivers/md/multipath.c | 2 +- drivers/md/raid0.c | 2 +- drivers/md/raid1.c | 3 ++- drivers/md/raid10.c | 2 +- drivers/md/raid5-cache.c | 2 +- drivers/md/raid5.c | 2 +- fs/btrfs/check-integrity.c | 8 ++++---- fs/jbd2/journal.c | 2 +- fs/xfs/xfs_buf.c | 2 +- include/linux/blk_types.h | 8 ++++---- include/linux/fs.h | 4 ++-- include/trace/events/f2fs.h | 2 +- kernel/trace/blktrace.c | 5 +++-- 39 files changed, 102 insertions(+), 98 deletions(-) diff --git a/Documentation/block/writeback_cache_control.txt b/Documentation/block/writeback_cache_control.txt index da70bda..8a6bdad 100644 --- a/Documentation/block/writeback_cache_control.txt +++ b/Documentation/block/writeback_cache_control.txt @@ -20,11 +20,11 @@ a forced cache flush, and the Force Unit Access (FUA) flag for requests. Explicit cache flushes ---------------------- -The REQ_FLUSH flag can be OR ed into the r/w flags of a bio submitted from +The REQ_PREFLUSH flag can be OR ed into the r/w flags of a bio submitted from the filesystem and will make sure the volatile cache of the storage device has been flushed before the actual I/O operation is started. This explicitly guarantees that previously completed write requests are on non-volatile -storage before the flagged bio starts. In addition the REQ_FLUSH flag can be +storage before the flagged bio starts. In addition the REQ_PREFLUSH flag can be set on an otherwise empty bio structure, which causes only an explicit cache flush without any dependent I/O. It is recommend to use the blkdev_issue_flush() helper for a pure cache flush. @@ -41,21 +41,21 @@ signaled after the data has been committed to non-volatile storage. Implementation details for filesystems -------------------------------------- -Filesystems can simply set the REQ_FLUSH and REQ_FUA bits and do not have to +Filesystems can simply set the REQ_PREFLUSH and REQ_FUA bits and do not have to worry if the underlying devices need any explicit cache flushing and how -the Forced Unit Access is implemented. The REQ_FLUSH and REQ_FUA flags +the Forced Unit Access is implemented. The REQ_PREFLUSH and REQ_FUA flags may both be set on a single bio. Implementation details for make_request_fn based block drivers -------------------------------------------------------------- -These drivers will always see the REQ_FLUSH and REQ_FUA bits as they sit +These drivers will always see the REQ_PREFLUSH and REQ_FUA bits as they sit directly below the submit_bio interface. For remapping drivers the REQ_FUA bits need to be propagated to underlying devices, and a global flush needs -to be implemented for bios with the REQ_FLUSH bit set. For real device -drivers that do not have a volatile cache the REQ_FLUSH and REQ_FUA bits -on non-empty bios can simply be ignored, and REQ_FLUSH requests without +to be implemented for bios with the REQ_PREFLUSH bit set. For real device +drivers that do not have a volatile cache the REQ_PREFLUSH and REQ_FUA bits +on non-empty bios can simply be ignored, and REQ_PREFLUSH requests without data can be completed successfully without doing any work. Drivers for devices with volatile caches need to implement the support for these flags themselves without any help from the block layer. @@ -65,8 +65,8 @@ Implementation details for request_fn based block drivers -------------------------------------------------------------- For devices that do not support volatile write caches there is no driver -support required, the block layer completes empty REQ_FLUSH requests before -entering the driver and strips off the REQ_FLUSH and REQ_FUA bits from +support required, the block layer completes empty REQ_PREFLUSH requests before +entering the driver and strips off the REQ_PREFLUSH and REQ_FUA bits from requests that have a payload. For devices with volatile write caches the driver needs to tell the block layer that it supports flushing caches by doing: @@ -74,7 +74,7 @@ doing: blk_queue_write_cache(sdkp->disk->queue, true, false); and handle empty REQ_OP_FLUSH requests in its prep_fn/request_fn. Note that -REQ_FLUSH requests with a payload are automatically turned into a sequence +REQ_PREFLUSH requests with a payload are automatically turned into a sequence of an empty REQ_OP_FLUSH request followed by the actual write by the block layer. For devices that also support the FUA bit the block layer needs to be told to pass through the REQ_FUA bit using: diff --git a/Documentation/device-mapper/log-writes.txt b/Documentation/device-mapper/log-writes.txt index c10f30c..f4ebcba 100644 --- a/Documentation/device-mapper/log-writes.txt +++ b/Documentation/device-mapper/log-writes.txt @@ -14,14 +14,14 @@ Log Ordering We log things in order of completion once we are sure the write is no longer in cache. This means that normal WRITE requests are not actually logged until the -next REQ_FLUSH request. This is to make it easier for userspace to replay the -log in a way that correlates to what is on disk and not what is in cache, to -make it easier to detect improper waiting/flushing. +next REQ_PREFLUSH request. This is to make it easier for userspace to replay +the log in a way that correlates to what is on disk and not what is in cache, +to make it easier to detect improper waiting/flushing. This works by attaching all WRITE requests to a list once the write completes. -Once we see a REQ_FLUSH request we splice this list onto the request and once +Once we see a REQ_PREFLUSH request we splice this list onto the request and once the FLUSH request completes we log all of the WRITEs and then the FLUSH. Only -completed WRITEs, at the time the REQ_FLUSH is issued, are added in order to +completed WRITEs, at the time the REQ_PREFLUSH is issued, are added in order to simulate the worst case scenario with regard to power failures. Consider the following example (W means write, C means complete): diff --git a/block/blk-core.c b/block/blk-core.c index c7d66c2..32a283e 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1029,7 +1029,7 @@ static bool blk_rq_should_init_elevator(struct bio *bio) * Flush requests do not use the elevator so skip initialization. * This allows a request to share the flush and elevator data. */ - if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) + if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA)) return false; return true; @@ -1736,7 +1736,7 @@ static blk_qc_t blk_queue_bio(struct request_queue *q, struct bio *bio) return BLK_QC_T_NONE; } - if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) { + if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA)) { spin_lock_irq(q->queue_lock); where = ELEVATOR_INSERT_FLUSH; goto get_rq; @@ -1968,9 +1968,9 @@ generic_make_request_checks(struct bio *bio) * drivers without flush support don't have to worry * about them. */ - if ((bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && + if ((bio->bi_rw & (REQ_PREFLUSH | REQ_FUA)) && !test_bit(QUEUE_FLAG_WC, &q->queue_flags)) { - bio->bi_rw &= ~(REQ_FLUSH | REQ_FUA); + bio->bi_rw &= ~(REQ_PREFLUSH | REQ_FUA); if (!nr_sectors) { err = 0; goto end_io; @@ -2217,7 +2217,7 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq) */ BUG_ON(blk_queued_rq(rq)); - if (rq->cmd_flags & (REQ_FLUSH|REQ_FUA)) + if (rq->cmd_flags & (REQ_PREFLUSH | REQ_FUA)) where = ELEVATOR_INSERT_FLUSH; add_acct_request(q, rq, where); @@ -3311,7 +3311,7 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule) /* * rq is already accounted, so use raw insert */ - if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) + if (rq->cmd_flags & (REQ_PREFLUSH | REQ_FUA)) __elv_add_request(q, rq, ELEVATOR_INSERT_FLUSH); else __elv_add_request(q, rq, ELEVATOR_INSERT_SORT_MERGE); diff --git a/block/blk-flush.c b/block/blk-flush.c index 21f0d5b..d308def 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -10,8 +10,8 @@ * optional steps - PREFLUSH, DATA and POSTFLUSH - according to the request * properties and hardware capability. * - * If a request doesn't have data, only REQ_FLUSH makes sense, which - * indicates a simple flush request. If there is data, REQ_FLUSH indicates + * If a request doesn't have data, only REQ_PREFLUSH makes sense, which + * indicates a simple flush request. If there is data, REQ_PREFLUSH indicates * that the device cache should be flushed before the data is executed, and * REQ_FUA means that the data must be on non-volatile media on request * completion. @@ -20,11 +20,11 @@ * difference. The requests are either completed immediately if there's no * data or executed as normal requests otherwise. * - * If the device has writeback cache and supports FUA, REQ_FLUSH is + * If the device has writeback cache and supports FUA, REQ_PREFLUSH is * translated to PREFLUSH but REQ_FUA is passed down directly with DATA. * - * If the device has writeback cache and doesn't support FUA, REQ_FLUSH is - * translated to PREFLUSH and REQ_FUA to POSTFLUSH. + * If the device has writeback cache and doesn't support FUA, REQ_PREFLUSH + * is translated to PREFLUSH and REQ_FUA to POSTFLUSH. * * The actual execution of flush is double buffered. Whenever a request * needs to execute PRE or POSTFLUSH, it queues at @@ -103,7 +103,7 @@ static unsigned int blk_flush_policy(unsigned long fflags, struct request *rq) policy |= REQ_FSEQ_DATA; if (fflags & (1UL << QUEUE_FLAG_WC)) { - if (rq->cmd_flags & REQ_FLUSH) + if (rq->cmd_flags & REQ_PREFLUSH) policy |= REQ_FSEQ_PREFLUSH; if (!(fflags & (1UL << QUEUE_FLAG_FUA)) && (rq->cmd_flags & REQ_FUA)) @@ -391,9 +391,9 @@ void blk_insert_flush(struct request *rq) /* * @policy now records what operations need to be done. Adjust - * REQ_FLUSH and FUA for the driver. + * REQ_PREFLUSH and FUA for the driver. */ - rq->cmd_flags &= ~REQ_FLUSH; + rq->cmd_flags &= ~REQ_PREFLUSH; if (!(fflags & (1UL << QUEUE_FLAG_FUA))) rq->cmd_flags &= ~REQ_FUA; diff --git a/block/blk-mq.c b/block/blk-mq.c index 29bcd9c..13f4603 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1247,7 +1247,7 @@ static int blk_mq_direct_issue_request(struct request *rq, blk_qc_t *cookie) static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio) { const int is_sync = rw_is_sync(bio_op(bio), bio->bi_rw); - const int is_flush_fua = bio->bi_rw & (REQ_FLUSH | REQ_FUA); + const int is_flush_fua = bio->bi_rw & (REQ_PREFLUSH | REQ_FUA); struct blk_map_ctx data; struct request *rq; unsigned int request_count = 0; @@ -1344,7 +1344,7 @@ done: static blk_qc_t blk_sq_make_request(struct request_queue *q, struct bio *bio) { const int is_sync = rw_is_sync(bio_op(bio), bio->bi_rw); - const int is_flush_fua = bio->bi_rw & (REQ_FLUSH | REQ_FUA); + const int is_flush_fua = bio->bi_rw & (REQ_PREFLUSH | REQ_FUA); struct blk_plug *plug; unsigned int request_count = 0; struct blk_map_ctx data; diff --git a/drivers/block/drbd/drbd_actlog.c b/drivers/block/drbd/drbd_actlog.c index f236a31..d524973 100644 --- a/drivers/block/drbd/drbd_actlog.c +++ b/drivers/block/drbd/drbd_actlog.c @@ -148,7 +148,7 @@ static int _drbd_md_sync_page_io(struct drbd_device *device, device->md_io.error = -ENODEV; if ((op == REQ_OP_WRITE) && !test_bit(MD_NO_FUA, &device->flags)) - op_flags |= REQ_FUA | REQ_FLUSH; + op_flags |= REQ_FUA | REQ_PREFLUSH; op_flags |= REQ_SYNC | REQ_NOIDLE; bio = bio_alloc_drbd(GFP_NOIO); @@ -847,7 +847,7 @@ int __drbd_change_sync(struct drbd_device *device, sector_t sector, int size, unsigned long count = 0; sector_t esector, nr_sectors; - /* This would be an empty REQ_FLUSH, be silent. */ + /* This would be an empty REQ_PREFLUSH, be silent. */ if ((mode == SET_OUT_OF_SYNC) && size == 0) return 0; diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index d55febc..2b37744 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -1609,7 +1609,7 @@ static u32 bio_flags_to_wire(struct drbd_connection *connection, if (connection->agreed_pro_version >= 95) return (bio->bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) | (bio->bi_rw & REQ_FUA ? DP_FUA : 0) | - (bio->bi_rw & REQ_FLUSH ? DP_FLUSH : 0) | + (bio->bi_rw & REQ_PREFLUSH ? DP_FLUSH : 0) | (bio_op(bio) == REQ_OP_DISCARD ? DP_DISCARD : 0); else return bio->bi_rw & REQ_SYNC ? DP_RW_SYNC : 0; diff --git a/drivers/block/drbd/drbd_protocol.h b/drivers/block/drbd/drbd_protocol.h index ef92453..129f8c7 100644 --- a/drivers/block/drbd/drbd_protocol.h +++ b/drivers/block/drbd/drbd_protocol.h @@ -112,7 +112,7 @@ struct p_header100 { #define DP_MAY_SET_IN_SYNC 4 #define DP_UNPLUG 8 /* not used anymore */ #define DP_FUA 16 /* equals REQ_FUA */ -#define DP_FLUSH 32 /* equals REQ_FLUSH */ +#define DP_FLUSH 32 /* equals REQ_PREFLUSH */ #define DP_DISCARD 64 /* equals REQ_DISCARD */ #define DP_SEND_RECEIVE_ACK 128 /* This is a proto B write request */ #define DP_SEND_WRITE_ACK 256 /* This is a proto C write request */ diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 6c59978..1ee0023 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2158,7 +2158,7 @@ static unsigned long wire_flags_to_bio_flags(u32 dpf) { return (dpf & DP_RW_SYNC ? REQ_SYNC : 0) | (dpf & DP_FUA ? REQ_FUA : 0) | - (dpf & DP_FLUSH ? REQ_FLUSH : 0); + (dpf & DP_FLUSH ? REQ_PREFLUSH : 0); } static unsigned long wire_flags_to_bio_op(u32 dpf) diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 2255dcf..eef6e95 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -1132,7 +1132,7 @@ static int drbd_process_write_request(struct drbd_request *req) * replicating, in which case there is no point. */ if (unlikely(req->i.size == 0)) { /* The only size==0 bios we expect are empty flushes. */ - D_ASSERT(device, req->master_bio->bi_rw & REQ_FLUSH); + D_ASSERT(device, req->master_bio->bi_rw & REQ_PREFLUSH); if (remote) _req_mod(req, QUEUE_AS_DRBD_BARRIER); return remote; diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index a3c3b30..6925023 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -631,7 +631,7 @@ static void journal_write_unlocked(struct closure *cl) bio->bi_end_io = journal_write_endio; bio->bi_private = w; bio_set_op_attrs(bio, REQ_OP_WRITE, - REQ_SYNC|REQ_META|REQ_FLUSH|REQ_FUA); + REQ_SYNC|REQ_META|REQ_PREFLUSH|REQ_FUA); bch_bio_map(bio, w->data); trace_bcache_journal_write(bio); diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c index 016b0aa..69f16f4 100644 --- a/drivers/md/bcache/request.c +++ b/drivers/md/bcache/request.c @@ -205,10 +205,10 @@ static void bch_data_insert_start(struct closure *cl) return bch_data_invalidate(cl); /* - * Journal writes are marked REQ_FLUSH; if the original write was a + * Journal writes are marked REQ_PREFLUSH; if the original write was a * flush, it'll wait on the journal write. */ - bio->bi_rw &= ~(REQ_FLUSH|REQ_FUA); + bio->bi_rw &= ~(REQ_PREFLUSH|REQ_FUA); do { unsigned i; @@ -668,7 +668,7 @@ static inline struct search *search_alloc(struct bio *bio, s->iop.write_prio = 0; s->iop.error = 0; s->iop.flags = 0; - s->iop.flush_journal = (bio->bi_rw & (REQ_FLUSH|REQ_FUA)) != 0; + s->iop.flush_journal = (bio->bi_rw & (REQ_PREFLUSH|REQ_FUA)) != 0; s->iop.wq = bcache_wq; return s; @@ -920,7 +920,7 @@ static void cached_dev_write(struct cached_dev *dc, struct search *s) bch_writeback_add(dc); s->iop.bio = bio; - if (bio->bi_rw & REQ_FLUSH) { + if (bio->bi_rw & REQ_PREFLUSH) { /* Also need to send a flush to the backing device */ struct bio *flush = bio_alloc_bioset(GFP_NOIO, 0, dc->disk.bio_split); diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 540e80e..718744d 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -788,7 +788,7 @@ static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio) spin_lock_irqsave(&cache->lock, flags); if (cache->need_tick_bio && - !(bio->bi_rw & (REQ_FUA | REQ_FLUSH)) && + !(bio->bi_rw & (REQ_FUA | REQ_PREFLUSH)) && bio_op(bio) != REQ_OP_DISCARD) { pb->tick = true; cache->need_tick_bio = false; @@ -830,7 +830,7 @@ static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio) static int bio_triggers_commit(struct cache *cache, struct bio *bio) { - return bio->bi_rw & (REQ_FLUSH | REQ_FUA); + return bio->bi_rw & (REQ_PREFLUSH | REQ_FUA); } /* @@ -1069,7 +1069,7 @@ static void dec_io_migrations(struct cache *cache) static bool discard_or_flush(struct bio *bio) { return bio_op(bio) == REQ_OP_DISCARD || - bio->bi_rw & (REQ_FLUSH | REQ_FUA); + bio->bi_rw & (REQ_PREFLUSH | REQ_FUA); } static void __cell_defer(struct cache *cache, struct dm_bio_prison_cell *cell) @@ -1614,8 +1614,8 @@ static void process_flush_bio(struct cache *cache, struct bio *bio) remap_to_cache(cache, bio, 0); /* - * REQ_FLUSH is not directed at any particular block so we don't - * need to inc_ds(). REQ_FUA's are split into a write + REQ_FLUSH + * REQ_PREFLUSH is not directed at any particular block so we don't + * need to inc_ds(). REQ_FUA's are split into a write + REQ_PREFLUSH * by dm-core. */ issue(cache, bio); @@ -1980,7 +1980,7 @@ static void process_deferred_bios(struct cache *cache) bio = bio_list_pop(&bios); - if (bio->bi_rw & REQ_FLUSH) + if (bio->bi_rw & REQ_PREFLUSH) process_flush_bio(cache, bio); else if (bio_op(bio) == REQ_OP_DISCARD) process_discard_bio(cache, &structs, bio); diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 057d19b..96dd5d7 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1911,11 +1911,12 @@ static int crypt_map(struct dm_target *ti, struct bio *bio) struct crypt_config *cc = ti->private; /* - * If bio is REQ_FLUSH or REQ_OP_DISCARD, just bypass crypt queues. - * - for REQ_FLUSH device-mapper core ensures that no IO is in-flight + * If bio is REQ_PREFLUSH or REQ_OP_DISCARD, just bypass crypt queues. + * - for REQ_PREFLUSH device-mapper core ensures that no IO is in-flight * - for REQ_OP_DISCARD caller must use flush if IO ordering matters */ - if (unlikely(bio->bi_rw & REQ_FLUSH || bio_op(bio) == REQ_OP_DISCARD)) { + if (unlikely(bio->bi_rw & REQ_PREFLUSH || + bio_op(bio) == REQ_OP_DISCARD)) { bio->bi_bdev = cc->dev->bdev; if (bio_sectors(bio)) bio->bi_iter.bi_sector = cc->start + diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c index 665bf32..2faf49d8 100644 --- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -1540,9 +1540,9 @@ static int era_map(struct dm_target *ti, struct bio *bio) remap_to_origin(era, bio); /* - * REQ_FLUSH bios carry no data, so we're not interested in them. + * REQ_PREFLUSH bios carry no data, so we're not interested in them. */ - if (!(bio->bi_rw & REQ_FLUSH) && + if (!(bio->bi_rw & REQ_PREFLUSH) && (bio_data_dir(bio) == WRITE) && !metadata_current_marked(era->md, block)) { defer_bio(era, bio); diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index 22e0597..0e225fd 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -380,7 +380,7 @@ static void dispatch_io(int op, int op_flags, unsigned int num_regions, */ for (i = 0; i < num_regions; i++) { *dp = old_pages; - if (where[i].count || (op_flags & REQ_FLUSH)) + if (where[i].count || (op_flags & REQ_PREFLUSH)) do_region(op, op_flags, i, where + i, dp, io); } diff --git a/drivers/md/dm-log-writes.c b/drivers/md/dm-log-writes.c index 0edb8ea..b5dbf7a 100644 --- a/drivers/md/dm-log-writes.c +++ b/drivers/md/dm-log-writes.c @@ -555,7 +555,7 @@ static int log_writes_map(struct dm_target *ti, struct bio *bio) struct bio_vec bv; size_t alloc_size; int i = 0; - bool flush_bio = (bio->bi_rw & REQ_FLUSH); + bool flush_bio = (bio->bi_rw & REQ_PREFLUSH); bool fua_bio = (bio->bi_rw & REQ_FUA); bool discard_bio = (bio_op(bio) == REQ_OP_DISCARD); diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 907df2b..9f5f460 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -704,7 +704,7 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes) bio_list_init(&requeue); while ((bio = bio_list_pop(writes))) { - if ((bio->bi_rw & REQ_FLUSH) || + if ((bio->bi_rw & REQ_PREFLUSH) || (bio_op(bio) == REQ_OP_DISCARD)) { bio_list_add(&sync, bio); continue; @@ -1253,7 +1253,8 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio, int error) * We need to dec pending if this was a write. */ if (rw == WRITE) { - if (!(bio->bi_rw & REQ_FLUSH) && bio_op(bio) != REQ_OP_DISCARD) + if (!(bio->bi_rw & REQ_PREFLUSH) && + bio_op(bio) != REQ_OP_DISCARD) dm_rh_dec(ms->rh, bio_record->write_region); return error; } diff --git a/drivers/md/dm-region-hash.c b/drivers/md/dm-region-hash.c index 3550ca7..b118134 100644 --- a/drivers/md/dm-region-hash.c +++ b/drivers/md/dm-region-hash.c @@ -398,7 +398,7 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio) region_t region = dm_rh_bio_to_region(rh, bio); int recovering = 0; - if (bio->bi_rw & REQ_FLUSH) { + if (bio->bi_rw & REQ_PREFLUSH) { rh->flush_failure = 1; return; } @@ -526,7 +526,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios) struct bio *bio; for (bio = bios->head; bio; bio = bio->bi_next) { - if (bio->bi_rw & REQ_FLUSH || bio_op(bio) == REQ_OP_DISCARD) + if (bio->bi_rw & REQ_PREFLUSH || bio_op(bio) == REQ_OP_DISCARD) continue; rh_inc(rh, dm_rh_bio_to_region(rh, bio)); } diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 70bb0e8..69ab1ff 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1680,7 +1680,7 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio) init_tracked_chunk(bio); - if (bio->bi_rw & REQ_FLUSH) { + if (bio->bi_rw & REQ_PREFLUSH) { bio->bi_bdev = s->cow->bdev; return DM_MAPIO_REMAPPED; } @@ -1799,7 +1799,7 @@ static int snapshot_merge_map(struct dm_target *ti, struct bio *bio) init_tracked_chunk(bio); - if (bio->bi_rw & REQ_FLUSH) { + if (bio->bi_rw & REQ_PREFLUSH) { if (!dm_bio_get_target_bio_nr(bio)) bio->bi_bdev = s->origin->bdev; else @@ -2285,7 +2285,7 @@ static int origin_map(struct dm_target *ti, struct bio *bio) bio->bi_bdev = o->dev->bdev; - if (unlikely(bio->bi_rw & REQ_FLUSH)) + if (unlikely(bio->bi_rw & REQ_PREFLUSH)) return DM_MAPIO_REMAPPED; if (bio_rw(bio) != WRITE) diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index b738178..48f1c01 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -286,7 +286,7 @@ static int stripe_map(struct dm_target *ti, struct bio *bio) uint32_t stripe; unsigned target_bio_nr; - if (bio->bi_rw & REQ_FLUSH) { + if (bio->bi_rw & REQ_PREFLUSH) { target_bio_nr = dm_bio_get_target_bio_nr(bio); BUG_ON(target_bio_nr >= sc->stripes); bio->bi_bdev = sc->stripe[target_bio_nr].dev->bdev; diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 1b684cb..5f9e3d7 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -697,7 +697,7 @@ static void remap_to_origin(struct thin_c *tc, struct bio *bio) static int bio_triggers_commit(struct thin_c *tc, struct bio *bio) { - return (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) && + return (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA)) && dm_thin_changed_this_transaction(tc->td); } @@ -868,7 +868,7 @@ static void __inc_remap_and_issue_cell(void *context, struct bio *bio; while ((bio = bio_list_pop(&cell->bios))) { - if (bio->bi_rw & (REQ_FLUSH | REQ_FUA) || + if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA) || bio_op(bio) == REQ_OP_DISCARD) bio_list_add(&info->defer_bios, bio); else { @@ -1641,7 +1641,7 @@ static void __remap_and_issue_shared_cell(void *context, while ((bio = bio_list_pop(&cell->bios))) { if ((bio_data_dir(bio) == WRITE) || - (bio->bi_rw & (REQ_FLUSH | REQ_FUA) || + (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA) || bio_op(bio) == REQ_OP_DISCARD)) bio_list_add(&info->defer_bios, bio); else { @@ -2556,7 +2556,7 @@ static int thin_bio_map(struct dm_target *ti, struct bio *bio) return DM_MAPIO_SUBMITTED; } - if (bio->bi_rw & (REQ_FLUSH | REQ_FUA) || + if (bio->bi_rw & (REQ_PREFLUSH | REQ_FUA) || bio_op(bio) == REQ_OP_DISCARD) { thin_defer_bio_with_throttle(tc, bio); return DM_MAPIO_SUBMITTED; diff --git a/drivers/md/dm.c b/drivers/md/dm.c index fcc68c8..aba7ed9 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1003,12 +1003,12 @@ static void dec_pending(struct dm_io *io, int error) if (io_error == DM_ENDIO_REQUEUE) return; - if ((bio->bi_rw & REQ_FLUSH) && bio->bi_iter.bi_size) { + if ((bio->bi_rw & REQ_PREFLUSH) && bio->bi_iter.bi_size) { /* * Preflush done for flush with data, reissue - * without REQ_FLUSH. + * without REQ_PREFLUSH. */ - bio->bi_rw &= ~REQ_FLUSH; + bio->bi_rw &= ~REQ_PREFLUSH; queue_io(md, bio); } else { /* done with normal IO or empty flush */ @@ -1477,7 +1477,7 @@ EXPORT_SYMBOL_GPL(dm_set_target_max_io_len); /* * A target may call dm_accept_partial_bio only from the map routine. It is - * allowed for all bio types except REQ_FLUSH. + * allowed for all bio types except REQ_PREFLUSH. * * dm_accept_partial_bio informs the dm that the target only wants to process * additional n_sectors sectors of the bio and the rest of the data should be @@ -1507,7 +1507,7 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) { struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone); unsigned bi_size = bio->bi_iter.bi_size >> SECTOR_SHIFT; - BUG_ON(bio->bi_rw & REQ_FLUSH); + BUG_ON(bio->bi_rw & REQ_PREFLUSH); BUG_ON(bi_size > *tio->len_ptr); BUG_ON(n_sectors > bi_size); *tio->len_ptr -= bi_size - n_sectors; @@ -1795,7 +1795,7 @@ static void __split_and_process_bio(struct mapped_device *md, start_io_acct(ci.io); - if (bio->bi_rw & REQ_FLUSH) { + if (bio->bi_rw & REQ_PREFLUSH) { ci.bio = &ci.md->flush_bio; ci.sector_count = 0; error = __send_empty_flush(&ci); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 1ad3f48..70ff888 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -221,7 +221,7 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio) struct bio *split; sector_t start_sector, end_sector, data_offset; - if (unlikely(bio->bi_rw & REQ_FLUSH)) { + if (unlikely(bio->bi_rw & REQ_PREFLUSH)) { md_flush_request(mddev, bio); return; } diff --git a/drivers/md/md.c b/drivers/md/md.c index bd4844f..1f123f5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -414,7 +414,7 @@ static void md_submit_flush_data(struct work_struct *ws) /* an empty barrier - all done */ bio_endio(bio); else { - bio->bi_rw &= ~REQ_FLUSH; + bio->bi_rw &= ~REQ_PREFLUSH; mddev->pers->make_request(mddev, bio); } diff --git a/drivers/md/md.h b/drivers/md/md.h index 2e0918f..b4f3352 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -424,7 +424,7 @@ struct mddev { /* Generic flush handling. * The last to finish preflush schedules a worker to submit - * the rest of the request (without the REQ_FLUSH flag). + * the rest of the request (without the REQ_PREFLUSH flag). */ struct bio *flush_bio; atomic_t flush_pending; diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index dd483bb..72ea98e 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -111,7 +111,7 @@ static void multipath_make_request(struct mddev *mddev, struct bio * bio) struct multipath_bh * mp_bh; struct multipath_info *multipath; - if (unlikely(bio->bi_rw & REQ_FLUSH)) { + if (unlikely(bio->bi_rw & REQ_PREFLUSH)) { md_flush_request(mddev, bio); return; } diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 051a10c..c3d4390 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -458,7 +458,7 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio) struct md_rdev *tmp_dev; struct bio *split; - if (unlikely(bio->bi_rw & REQ_FLUSH)) { + if (unlikely(bio->bi_rw & REQ_PREFLUSH)) { md_flush_request(mddev, bio); return; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index a342723..10e53cd 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1056,7 +1056,8 @@ static void raid1_make_request(struct mddev *mddev, struct bio * bio) const int op = bio_op(bio); const int rw = bio_data_dir(bio); const unsigned long do_sync = (bio->bi_rw & REQ_SYNC); - const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); + const unsigned long do_flush_fua = (bio->bi_rw & + (REQ_PREFLUSH | REQ_FUA)); const unsigned long do_sec = (bio->bi_rw & REQ_SECURE); struct md_rdev *blocked_rdev; struct blk_plug_cb *cb; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 615045a..245640b 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1447,7 +1447,7 @@ static void raid10_make_request(struct mddev *mddev, struct bio *bio) struct bio *split; - if (unlikely(bio->bi_rw & REQ_FLUSH)) { + if (unlikely(bio->bi_rw & REQ_PREFLUSH)) { md_flush_request(mddev, bio); return; } diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 9265138..5504ce2 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -536,7 +536,7 @@ int r5l_handle_flush_request(struct r5l_log *log, struct bio *bio) bio_endio(bio); return 0; } - bio->bi_rw &= ~REQ_FLUSH; + bio->bi_rw &= ~REQ_PREFLUSH; return -EAGAIN; } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index b9122e2..7aacf5b 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -5150,7 +5150,7 @@ static void raid5_make_request(struct mddev *mddev, struct bio * bi) DEFINE_WAIT(w); bool do_prepare; - if (unlikely(bi->bi_rw & REQ_FLUSH)) { + if (unlikely(bi->bi_rw & REQ_PREFLUSH)) { int ret = r5l_handle_flush_request(conf->log, bi); if (ret == 0) diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c index da944ff..ca70bc7 100644 --- a/fs/btrfs/check-integrity.c +++ b/fs/btrfs/check-integrity.c @@ -2207,7 +2207,7 @@ static void btrfsic_bio_end_io(struct bio *bp) block->dev_bytenr, block->mirror_num); next_block = block->next_in_same_bio; block->iodone_w_error = iodone_w_error; - if (block->submit_bio_bh_rw & REQ_FLUSH) { + if (block->submit_bio_bh_rw & REQ_PREFLUSH) { dev_state->last_flush_gen++; if ((dev_state->state->print_mask & BTRFSIC_PRINT_MASK_END_IO_BIO_BH)) @@ -2243,7 +2243,7 @@ static void btrfsic_bh_end_io(struct buffer_head *bh, int uptodate) block->dev_bytenr, block->mirror_num); block->iodone_w_error = iodone_w_error; - if (block->submit_bio_bh_rw & REQ_FLUSH) { + if (block->submit_bio_bh_rw & REQ_PREFLUSH) { dev_state->last_flush_gen++; if ((dev_state->state->print_mask & BTRFSIC_PRINT_MASK_END_IO_BIO_BH)) @@ -2884,7 +2884,7 @@ int btrfsic_submit_bh(int op, int op_flags, struct buffer_head *bh) btrfsic_process_written_block(dev_state, dev_bytenr, &bh->b_data, 1, NULL, NULL, bh, op_flags); - } else if (NULL != dev_state && (op_flags & REQ_FLUSH)) { + } else if (NULL != dev_state && (op_flags & REQ_PREFLUSH)) { if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO @@ -2982,7 +2982,7 @@ static void __btrfsic_submit_bio(struct bio *bio) kunmap(bio->bi_io_vec[i].bv_page); } kfree(mapped_datav); - } else if (NULL != dev_state && (bio->bi_rw & REQ_FLUSH)) { + } else if (NULL != dev_state && (bio->bi_rw & REQ_PREFLUSH)) { if (dev_state->state->print_mask & BTRFSIC_PRINT_MASK_SUBMIT_BIO_BH) printk(KERN_INFO diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 34bc996..dc68f56 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1354,7 +1354,7 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags) trace_jbd2_write_superblock(journal, write_flags); if (!(journal->j_flags & JBD2_BARRIER)) - write_flags &= ~(REQ_FUA | REQ_FLUSH); + write_flags &= ~(REQ_FUA | REQ_PREFLUSH); lock_buffer(bh); if (buffer_write_io_error(bh)) { /* diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index d8acd37..686d8f1 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1237,7 +1237,7 @@ _xfs_buf_ioapply( if (bp->b_flags & XBF_FUA) op_flags |= REQ_FUA; if (bp->b_flags & XBF_FLUSH) - op_flags |= REQ_FLUSH; + op_flags |= REQ_PREFLUSH; /* * Run the write verifier callback function if it exists. If diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 32d8752..562ab83 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -168,7 +168,7 @@ enum rq_flag_bits { __REQ_NOIDLE, /* don't anticipate more IO after this one */ __REQ_INTEGRITY, /* I/O includes block integrity payload */ __REQ_FUA, /* forced unit access */ - __REQ_FLUSH, /* request for cache flush */ + __REQ_PREFLUSH, /* request for cache flush */ /* bio only flags */ __REQ_RAHEAD, /* read ahead, can fail anytime */ @@ -212,12 +212,12 @@ enum rq_flag_bits { (REQ_FAILFAST_DEV | REQ_FAILFAST_TRANSPORT | REQ_FAILFAST_DRIVER) #define REQ_COMMON_MASK \ (REQ_FAILFAST_MASK | REQ_SYNC | REQ_META | REQ_PRIO | REQ_NOIDLE | \ - REQ_FLUSH | REQ_FUA | REQ_SECURE | REQ_INTEGRITY | REQ_NOMERGE) + REQ_PREFLUSH | REQ_FUA | REQ_SECURE | REQ_INTEGRITY | REQ_NOMERGE) #define REQ_CLONE_MASK REQ_COMMON_MASK /* This mask is used for both bio and request merge checking */ #define REQ_NOMERGE_FLAGS \ - (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_FLUSH_SEQ) + (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_PREFLUSH | REQ_FUA | REQ_FLUSH_SEQ) #define REQ_RAHEAD (1ULL << __REQ_RAHEAD) #define REQ_THROTTLED (1ULL << __REQ_THROTTLED) @@ -235,7 +235,7 @@ enum rq_flag_bits { #define REQ_PREEMPT (1ULL << __REQ_PREEMPT) #define REQ_ALLOCED (1ULL << __REQ_ALLOCED) #define REQ_COPY_USER (1ULL << __REQ_COPY_USER) -#define REQ_FLUSH (1ULL << __REQ_FLUSH) +#define REQ_PREFLUSH (1ULL << __REQ_PREFLUSH) #define REQ_FLUSH_SEQ (1ULL << __REQ_FLUSH_SEQ) #define REQ_IO_STAT (1ULL << __REQ_IO_STAT) #define REQ_MIXED_MERGE (1ULL << __REQ_MIXED_MERGE) diff --git a/include/linux/fs.h b/include/linux/fs.h index ccd1664..1830245 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -204,9 +204,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define READ_SYNC REQ_SYNC #define WRITE_SYNC (REQ_SYNC | REQ_NOIDLE) #define WRITE_ODIRECT REQ_SYNC -#define WRITE_FLUSH (REQ_SYNC | REQ_NOIDLE | REQ_FLUSH) +#define WRITE_FLUSH (REQ_SYNC | REQ_NOIDLE | REQ_PREFLUSH) #define WRITE_FUA (REQ_SYNC | REQ_NOIDLE | REQ_FUA) -#define WRITE_FLUSH_FUA (REQ_SYNC | REQ_NOIDLE | REQ_FLUSH | REQ_FUA) +#define WRITE_FLUSH_FUA (REQ_SYNC | REQ_NOIDLE | REQ_PREFLUSH | REQ_FUA) /* * Attribute flags. These should be or-ed together to figure out what diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h index 30efa44..878963a 100644 --- a/include/trace/events/f2fs.h +++ b/include/trace/events/f2fs.h @@ -33,7 +33,7 @@ TRACE_DEFINE_ENUM(SSR); TRACE_DEFINE_ENUM(__REQ_RAHEAD); TRACE_DEFINE_ENUM(__REQ_SYNC); TRACE_DEFINE_ENUM(__REQ_NOIDLE); -TRACE_DEFINE_ENUM(__REQ_FLUSH); +TRACE_DEFINE_ENUM(__REQ_PREFLUSH); TRACE_DEFINE_ENUM(__REQ_FUA); TRACE_DEFINE_ENUM(__REQ_PRIO); TRACE_DEFINE_ENUM(__REQ_META); diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 0c70fbb..03b0dd9 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -189,6 +189,7 @@ static const u32 ddir_act[2] = { BLK_TC_ACT(BLK_TC_READ), BLK_TC_ACT(BLK_TC_WRITE) }; #define BLK_TC_RAHEAD BLK_TC_AHEAD +#define BLK_TC_PREFLUSH BLK_TC_FLUSH /* The ilog2() calls fall out because they're constant */ #define MASK_TC_BIT(rw, __name) ((rw & REQ_ ## __name) << \ @@ -219,7 +220,7 @@ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, what |= MASK_TC_BIT(op_flags, SYNC); what |= MASK_TC_BIT(op_flags, RAHEAD); what |= MASK_TC_BIT(op_flags, META); - what |= MASK_TC_BIT(op_flags, FLUSH); + what |= MASK_TC_BIT(op_flags, PREFLUSH); what |= MASK_TC_BIT(op_flags, FUA); if (op == REQ_OP_DISCARD) what |= BLK_TC_ACT(BLK_TC_DISCARD); @@ -1779,7 +1780,7 @@ void blk_fill_rwbs(char *rwbs, int op, u32 rw, int bytes) { int i = 0; - if (rw & REQ_FLUSH) + if (rw & REQ_PREFLUSH) rwbs[i++] = 'F'; switch (op) { -- 2.7.2 From fengguang.wu@intel.com Sun Jun 5 15:44:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=FAKE_REPLY_C autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 431257CD3 for ; Sun, 5 Jun 2016 15:44:28 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C2F0DAC002 for ; Sun, 5 Jun 2016 13:44:24 -0700 (PDT) X-ASG-Debug-ID: 1465159460-04bdf05ad5b79da0001-NocioJ Received: from mga01.intel.com ([192.55.52.88]) by cuda.sgi.com with ESMTP id 6N0pODKCnKDkvBhR for ; Sun, 05 Jun 2016 13:44:20 -0700 (PDT) X-Barracuda-Envelope-From: fengguang.wu@intel.com X-Barracuda-Effective-Source-IP: UNKNOWN[192.55.52.88] X-Barracuda-Apparent-Source-IP: 192.55.52.88 X-ASG-Whitelist: Client Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga101.fm.intel.com with ESMTP; 05 Jun 2016 13:44:20 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,423,1459839600"; d="gz'50?scan'50,208,50";a="116512141" Received: from bee.sh.intel.com (HELO bee) ([10.239.97.14]) by fmsmga004.fm.intel.com with ESMTP; 05 Jun 2016 13:44:16 -0700 Received: from kbuild by bee with local (Exim 4.83) (envelope-from ) id 1b9eu2-000Lu9-JQ; Mon, 06 Jun 2016 04:44:10 +0800 Date: Mon, 6 Jun 2016 04:30:07 +0800 From: kbuild test robot To: mchristi@redhat.com Cc: kbuild-all@01.org, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com, Mike Christie Subject: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio Message-ID: <201606060411.oSFVvcx1%fengguang.wu@intel.com> X-ASG-Orig-Subj: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="J/dobhs11T7y2rNN" Content-Disposition: inline In-Reply-To: <1465155145-10812-2-git-send-email-mchristi@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: fengguang.wu@intel.com X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false X-Barracuda-Connect: UNKNOWN[192.55.52.88] X-Barracuda-Start-Time: 1465159460 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3576 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 --J/dobhs11T7y2rNN Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, [auto build test ERROR on v4.7-rc1] [cannot apply to dm/for-next md/for-next next-20160603] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/mchristi-redhat-com/v8-separate-operations-from-flags-in-the-bio-request-structs/20160606-040240 config: x86_64-randconfig-i0-201623 (attached as .config) compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All error/warnings (new ones prefixed by >>): In file included from include/linux/fs.h:31:0, from include/linux/genhd.h:67, from include/linux/blkdev.h:9, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: fs/ext4/crypto.c: In function 'ext4_encrypted_zeroout': include/linux/blk_types.h:194:20: warning: passing argument 1 of 'submit_bio_wait' makes pointer from integer without a cast [-Wint-conversion] #define REQ_WRITE (1ULL << __REQ_WRITE) ^ include/linux/fs.h:196:19: note: in expansion of macro 'REQ_WRITE' #define RW_MASK REQ_WRITE ^~~~~~~~~ >> include/linux/fs.h:200:17: note: in expansion of macro 'RW_MASK' #define WRITE RW_MASK ^~~~~~~ >> fs/ext4/crypto.c:442:25: note: in expansion of macro 'WRITE' err = submit_bio_wait(WRITE, bio); ^~~~~ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:476:12: note: expected 'struct bio *' but argument is of type 'long long unsigned int' extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ >> fs/ext4/crypto.c:442:9: error: too many arguments to function 'submit_bio_wait' err = submit_bio_wait(WRITE, bio); ^~~~~~~~~~~~~~~ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:476:12: note: declared here extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ vim +/submit_bio_wait +442 fs/ext4/crypto.c 36086d43 Theodore Ts'o 2015-10-03 436 "bio_add_page failed: %d", ret); 36086d43 Theodore Ts'o 2015-10-03 437 WARN_ON(1); b30ab0e0 Michael Halcrow 2015-04-12 438 bio_put(bio); 36086d43 Theodore Ts'o 2015-10-03 439 err = -EIO; b30ab0e0 Michael Halcrow 2015-04-12 440 goto errout; b30ab0e0 Michael Halcrow 2015-04-12 441 } b30ab0e0 Michael Halcrow 2015-04-12 @442 err = submit_bio_wait(WRITE, bio); 36086d43 Theodore Ts'o 2015-10-03 443 if ((err == 0) && bio->bi_error) 36086d43 Theodore Ts'o 2015-10-03 444 err = -EIO; 95ea68b4 Theodore Ts'o 2015-05-31 445 bio_put(bio); :::::: The code at line 442 was first introduced by commit :::::: b30ab0e03407d2aa2d9316cba199c757e4bfc8ad ext4 crypto: add ext4 encryption facilities :::::: TO: Michael Halcrow :::::: CC: Theodore Ts'o --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation --J/dobhs11T7y2rNN Content-Type: application/octet-stream Content-Disposition: attachment; filename=".config.gz" Content-Transfer-Encoding: base64 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 8yRQNV7WWvcII0om4ZU3i4D8H6gwKNOoagEA --J/dobhs11T7y2rNN-- From fengguang.wu@intel.com Sun Jun 5 15:52:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=FAKE_REPLY_C autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3454E7CD3 for ; Sun, 5 Jun 2016 15:52:03 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9F822AC002 for ; Sun, 5 Jun 2016 13:52:02 -0700 (PDT) X-ASG-Debug-ID: 1465159921-04cb6c2dbab5ab20001-NocioJ Received: from mga14.intel.com ([192.55.52.115]) by cuda.sgi.com with ESMTP id jZbMkrr7Nvmro7at for ; Sun, 05 Jun 2016 13:52:01 -0700 (PDT) X-Barracuda-Envelope-From: fengguang.wu@intel.com X-Barracuda-Effective-Source-IP: UNKNOWN[192.55.52.115] X-Barracuda-Apparent-Source-IP: 192.55.52.115 X-ASG-Whitelist: Client Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga103.fm.intel.com with ESMTP; 05 Jun 2016 13:52:00 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,423,1459839600"; d="gz'50?scan'50,208,50";a="116513652" Received: from bee.sh.intel.com (HELO bee) ([10.239.97.14]) by fmsmga004.fm.intel.com with ESMTP; 05 Jun 2016 13:51:57 -0700 Received: from kbuild by bee with local (Exim 4.83) (envelope-from ) id 1b9f1T-000BNH-0y; Mon, 06 Jun 2016 04:51:51 +0800 Date: Mon, 6 Jun 2016 04:37:53 +0800 From: kbuild test robot To: mchristi@redhat.com Cc: kbuild-all@01.org, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com, Mike Christie Subject: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code Message-ID: <201606060429.qfDh91VE%fengguang.wu@intel.com> X-ASG-Orig-Subj: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="0F1p//8PRICkK4MW" Content-Disposition: inline In-Reply-To: <1465155145-10812-43-git-send-email-mchristi@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: fengguang.wu@intel.com X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false X-Barracuda-Connect: UNKNOWN[192.55.52.115] X-Barracuda-Start-Time: 1465159921 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3668 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 --0F1p//8PRICkK4MW Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, [auto build test WARNING on v4.7-rc1] [cannot apply to dm/for-next md/for-next next-20160603] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/mchristi-redhat-com/v8-separate-operations-from-flags-in-the-bio-request-structs/20160606-040240 config: x86_64-randconfig-i0-201623 (attached as .config) compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430 reproduce: # save the attached .config to linux build tree make ARCH=x86_64 All warnings (new ones prefixed by >>): In file included from include/linux/genhd.h:67:0, from include/linux/blkdev.h:9, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: fs/ext4/crypto.c: In function 'ext4_encrypted_zeroout': >> include/linux/fs.h:197:19: warning: passing argument 1 of 'submit_bio_wait' makes pointer from integer without a cast [-Wint-conversion] #define RW_MASK REQ_OP_WRITE ^ include/linux/fs.h:201:17: note: in expansion of macro 'RW_MASK' #define WRITE RW_MASK ^~~~~~~ fs/ext4/crypto.c:442:25: note: in expansion of macro 'WRITE' err = submit_bio_wait(WRITE, bio); ^~~~~ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:471:12: note: expected 'struct bio *' but argument is of type 'int' extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ fs/ext4/crypto.c:442:9: error: too many arguments to function 'submit_bio_wait' err = submit_bio_wait(WRITE, bio); ^~~~~~~~~~~~~~~ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:471:12: note: declared here extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ vim +/submit_bio_wait +197 include/linux/fs.h 181 * READA Used for read-ahead operations. Lower priority, and the 182 * block layer could (in theory) choose to ignore this 183 * request if it runs into resource problems. 184 * WRITE A normal async write. Device will be plugged. 185 * WRITE_SYNC Synchronous write. Identical to WRITE, but passes down 186 * the hint that someone will be waiting on this IO 187 * shortly. The write equivalent of READ_SYNC. 188 * WRITE_ODIRECT Special case write for O_DIRECT only. 189 * WRITE_FLUSH Like WRITE_SYNC but with preceding cache flush. 190 * WRITE_FUA Like WRITE_SYNC but data is guaranteed to be on 191 * non-volatile media on completion. 192 * WRITE_FLUSH_FUA Combination of WRITE_FLUSH and FUA. The IO is preceded 193 * by a cache flush and data is guaranteed to be on 194 * non-volatile media on completion. 195 * 196 */ > 197 #define RW_MASK REQ_OP_WRITE 198 #define RWA_MASK REQ_RAHEAD 199 200 #define READ REQ_OP_READ 201 #define WRITE RW_MASK 202 #define READA RWA_MASK 203 204 #define READ_SYNC REQ_SYNC 205 #define WRITE_SYNC (REQ_SYNC | REQ_NOIDLE) --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation --0F1p//8PRICkK4MW Content-Type: application/octet-stream Content-Disposition: attachment; filename=".config.gz" Content-Transfer-Encoding: base64 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 8yRQNV7WWvcII0om4ZU3i4D8H6gwKNOoagEA --0F1p//8PRICkK4MW-- From fengguang.wu@intel.com Sun Jun 5 16:23:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=FAKE_REPLY_C autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EF8DD7CA4 for ; Sun, 5 Jun 2016 16:23:06 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id C138B8F8037 for ; Sun, 5 Jun 2016 14:23:03 -0700 (PDT) X-ASG-Debug-ID: 1465161782-04cbb0356bb8df90001-NocioJ Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by cuda.sgi.com with ESMTP id XGSmY7XcGD8bP8Sd for ; Sun, 05 Jun 2016 14:23:02 -0700 (PDT) X-Barracuda-Envelope-From: fengguang.wu@intel.com X-Barracuda-Effective-Source-IP: mga09.intel.com[134.134.136.24] X-Barracuda-Apparent-Source-IP: 134.134.136.24 X-ASG-Whitelist: Client Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga102.jf.intel.com with ESMTP; 05 Jun 2016 14:23:01 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,423,1459839600"; d="scan'208";a="969434174" Received: from bee.sh.intel.com (HELO bee) ([10.239.97.14]) by orsmga001.jf.intel.com with ESMTP; 05 Jun 2016 14:22:58 -0700 Received: from kbuild by bee with local (Exim 4.83) (envelope-from ) id 1b9fVU-0004Zx-AI; Mon, 06 Jun 2016 05:22:52 +0800 Date: Mon, 6 Jun 2016 05:22:09 +0800 From: kbuild test robot To: mchristi@redhat.com Cc: kbuild-all@01.org, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com, Mike Christie Subject: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio Message-ID: <201606060538.MXS5FrrY%fengguang.wu@intel.com> X-ASG-Orig-Subj: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1465155145-10812-2-git-send-email-mchristi@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: fengguang.wu@intel.com X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false X-Barracuda-Connect: mga09.intel.com[134.134.136.24] X-Barracuda-Start-Time: 1465161782 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4913 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Hi, [auto build test WARNING on v4.7-rc1] [cannot apply to dm/for-next md/for-next next-20160603] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/mchristi-redhat-com/v8-separate-operations-from-flags-in-the-bio-request-structs/20160606-040240 reproduce: # apt-get install sparse make ARCH=x86_64 allmodconfig make C=1 CF=-D__CHECK_ENDIAN__ sparse warnings: (new ones prefixed by >>) include/linux/compiler.h:232:8: sparse: attribute 'no_sanitize_address': unknown attribute >> fs/ext4/crypto.c:442:38: sparse: too many arguments for function submit_bio_wait In file included from include/linux/fs.h:31:0, from include/linux/seq_file.h:10, from include/linux/pinctrl/consumer.h:17, from include/linux/pinctrl/devinfo.h:21, from include/linux/device.h:24, from include/linux/genhd.h:64, from include/linux/blkdev.h:9, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: fs/ext4/crypto.c: In function 'ext4_encrypted_zeroout': include/linux/blk_types.h:194:20: warning: passing argument 1 of 'submit_bio_wait' makes pointer from integer without a cast [-Wint-conversion] #define REQ_WRITE (1ULL << __REQ_WRITE) ^ include/linux/fs.h:196:19: note: in expansion of macro 'REQ_WRITE' #define RW_MASK REQ_WRITE ^~~~~~~~~ include/linux/fs.h:200:17: note: in expansion of macro 'RW_MASK' #define WRITE RW_MASK ^~~~~~~ fs/ext4/crypto.c:442:25: note: in expansion of macro 'WRITE' err = submit_bio_wait(WRITE, bio); ^~~~~ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:476:12: note: expected 'struct bio *' but argument is of type 'long long unsigned int' extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ fs/ext4/crypto.c:442:9: error: too many arguments to function 'submit_bio_wait' err = submit_bio_wait(WRITE, bio); ^~~~~~~~~~~~~~~ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:476:12: note: declared here extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ vim +442 fs/ext4/crypto.c b30ab0e0 Michael Halcrow 2015-04-12 426 goto errout; b30ab0e0 Michael Halcrow 2015-04-12 427 } b30ab0e0 Michael Halcrow 2015-04-12 428 bio->bi_bdev = inode->i_sb->s_bdev; 36086d43 Theodore Ts'o 2015-10-03 429 bio->bi_iter.bi_sector = 36086d43 Theodore Ts'o 2015-10-03 430 pblk << (inode->i_sb->s_blocksize_bits - 9); 36086d43 Theodore Ts'o 2015-10-03 431 ret = bio_add_page(bio, ciphertext_page, b30ab0e0 Michael Halcrow 2015-04-12 432 inode->i_sb->s_blocksize, 0); 36086d43 Theodore Ts'o 2015-10-03 433 if (ret != inode->i_sb->s_blocksize) { 36086d43 Theodore Ts'o 2015-10-03 434 /* should never happen! */ 36086d43 Theodore Ts'o 2015-10-03 435 ext4_msg(inode->i_sb, KERN_ERR, 36086d43 Theodore Ts'o 2015-10-03 436 "bio_add_page failed: %d", ret); 36086d43 Theodore Ts'o 2015-10-03 437 WARN_ON(1); b30ab0e0 Michael Halcrow 2015-04-12 438 bio_put(bio); 36086d43 Theodore Ts'o 2015-10-03 439 err = -EIO; b30ab0e0 Michael Halcrow 2015-04-12 440 goto errout; b30ab0e0 Michael Halcrow 2015-04-12 441 } b30ab0e0 Michael Halcrow 2015-04-12 @442 err = submit_bio_wait(WRITE, bio); 36086d43 Theodore Ts'o 2015-10-03 443 if ((err == 0) && bio->bi_error) 36086d43 Theodore Ts'o 2015-10-03 444 err = -EIO; 95ea68b4 Theodore Ts'o 2015-05-31 445 bio_put(bio); b30ab0e0 Michael Halcrow 2015-04-12 446 if (err) b30ab0e0 Michael Halcrow 2015-04-12 447 goto errout; 36086d43 Theodore Ts'o 2015-10-03 448 lblk++; pblk++; b30ab0e0 Michael Halcrow 2015-04-12 449 } b30ab0e0 Michael Halcrow 2015-04-12 450 err = 0; :::::: The code at line 442 was first introduced by commit :::::: b30ab0e03407d2aa2d9316cba199c757e4bfc8ad ext4 crypto: add ext4 encryption facilities :::::: TO: Michael Halcrow :::::: CC: Theodore Ts'o --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation From fengguang.wu@intel.com Sun Jun 5 16:36:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=FAKE_REPLY_C autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 60B617CA1 for ; Sun, 5 Jun 2016 16:36:38 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1FA9C304039 for ; Sun, 5 Jun 2016 14:36:34 -0700 (PDT) X-ASG-Debug-ID: 1465162593-04bdf05ad7b7ad70001-NocioJ Received: from mga01.intel.com ([192.55.52.88]) by cuda.sgi.com with ESMTP id 27uAwOZwAwKQ5cAW for ; Sun, 05 Jun 2016 14:36:33 -0700 (PDT) X-Barracuda-Envelope-From: fengguang.wu@intel.com X-Barracuda-Effective-Source-IP: UNKNOWN[192.55.52.88] X-Barracuda-Apparent-Source-IP: 192.55.52.88 X-ASG-Whitelist: Client Received: from orsmga003.jf.intel.com ([10.7.209.27]) by fmsmga101.fm.intel.com with ESMTP; 05 Jun 2016 14:36:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,424,1459839600"; d="gz'50?scan'50,208,50";a="822240966" Received: from bee.sh.intel.com (HELO bee) ([10.239.97.14]) by orsmga003.jf.intel.com with ESMTP; 05 Jun 2016 14:36:29 -0700 Received: from kbuild by bee with local (Exim 4.83) (envelope-from ) id 1b9fiZ-000C4w-Ok; Mon, 06 Jun 2016 05:36:23 +0800 Date: Mon, 6 Jun 2016 05:43:50 +0800 From: kbuild test robot To: mchristi@redhat.com Cc: kbuild-all@01.org, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com, Mike Christie Subject: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code Message-ID: <201606060540.nWhFU0Cr%fengguang.wu@intel.com> X-ASG-Orig-Subj: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="dDRMvlgZJXvWKvBx" Content-Disposition: inline In-Reply-To: <1465155145-10812-43-git-send-email-mchristi@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: fengguang.wu@intel.com X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false X-Barracuda-Connect: UNKNOWN[192.55.52.88] X-Barracuda-Start-Time: 1465162593 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 964 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 --dDRMvlgZJXvWKvBx Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, [auto build test ERROR on v4.7-rc1] [cannot apply to dm/for-next md/for-next next-20160603] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/mchristi-redhat-com/v8-separate-operations-from-flags-in-the-bio-request-structs/20160606-040240 config: m32r-opsput_defconfig (attached as .config) compiler: m32r-linux-gcc (GCC) 4.9.0 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=m32r All errors (new ones prefixed by >>): >> ERROR: "__ucmpdi2" [drivers/scsi/sd_mod.ko] undefined! --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation --dDRMvlgZJXvWKvBx Content-Type: application/octet-stream Content-Disposition: attachment; filename=".config.gz" Content-Transfer-Encoding: base64 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 --dDRMvlgZJXvWKvBx-- From fengguang.wu@intel.com Sun Jun 5 16:40:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=FAKE_REPLY_C autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 71DF37CA1 for ; Sun, 5 Jun 2016 16:40:09 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id EE7E7AC002 for ; Sun, 5 Jun 2016 14:40:05 -0700 (PDT) X-ASG-Debug-ID: 1465162804-04bdf05ad4b7ae90001-NocioJ Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by cuda.sgi.com with ESMTP id IVWd8GYQiEUMUJ5S for ; Sun, 05 Jun 2016 14:40:04 -0700 (PDT) X-Barracuda-Envelope-From: fengguang.wu@intel.com X-Barracuda-Effective-Source-IP: mga03.intel.com[134.134.136.65] X-Barracuda-Apparent-Source-IP: 134.134.136.65 X-ASG-Whitelist: Client Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP; 05 Jun 2016 14:40:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,424,1459839600"; d="gz'50?scan'50,208,50";a="969439953" Received: from bee.sh.intel.com (HELO bee) ([10.239.97.14]) by orsmga001.jf.intel.com with ESMTP; 05 Jun 2016 14:40:00 -0700 Received: from kbuild by bee with local (Exim 4.83) (envelope-from ) id 1b9fly-000MM4-1h; Mon, 06 Jun 2016 05:39:54 +0800 Date: Mon, 6 Jun 2016 05:48:13 +0800 From: kbuild test robot To: mchristi@redhat.com Cc: kbuild-all@01.org, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com, Mike Christie Subject: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio Message-ID: <201606060504.Kroz5DEN%fengguang.wu@intel.com> X-ASG-Orig-Subj: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="azLHFNyN32YCQGCU" Content-Disposition: inline In-Reply-To: <1465155145-10812-2-git-send-email-mchristi@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: fengguang.wu@intel.com X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false X-Barracuda-Connect: mga03.intel.com[134.134.136.65] X-Barracuda-Start-Time: 1465162804 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3868 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 --azLHFNyN32YCQGCU Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, [auto build test WARNING on v4.7-rc1] [cannot apply to dm/for-next md/for-next next-20160603] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/mchristi-redhat-com/v8-separate-operations-from-flags-in-the-bio-request-structs/20160606-040240 config: i386-allyesconfig (attached as .config) compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430 reproduce: # save the attached .config to linux build tree make ARCH=i386 All warnings (new ones prefixed by >>): fs/ext4/crypto.c: In function 'ext4_encrypted_zeroout': >> fs/ext4/crypto.c:442:25: warning: passing argument 1 of 'submit_bio_wait' makes pointer from integer without a cast [-Wint-conversion] err = submit_bio_wait(WRITE, bio); ^ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:476:12: note: expected 'struct bio *' but argument is of type 'long long unsigned int' extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ fs/ext4/crypto.c:442:9: error: too many arguments to function 'submit_bio_wait' err = submit_bio_wait(WRITE, bio); ^~~~~~~~~~~~~~~ In file included from include/linux/blkdev.h:19:0, from fs/ext4/ext4.h:20, from fs/ext4/ext4_extents.h:22, from fs/ext4/crypto.c:37: include/linux/bio.h:476:12: note: declared here extern int submit_bio_wait(struct bio *bio); ^~~~~~~~~~~~~~~ vim +/submit_bio_wait +442 fs/ext4/crypto.c b30ab0e0 Michael Halcrow 2015-04-12 426 goto errout; b30ab0e0 Michael Halcrow 2015-04-12 427 } b30ab0e0 Michael Halcrow 2015-04-12 428 bio->bi_bdev = inode->i_sb->s_bdev; 36086d43 Theodore Ts'o 2015-10-03 429 bio->bi_iter.bi_sector = 36086d43 Theodore Ts'o 2015-10-03 430 pblk << (inode->i_sb->s_blocksize_bits - 9); 36086d43 Theodore Ts'o 2015-10-03 431 ret = bio_add_page(bio, ciphertext_page, b30ab0e0 Michael Halcrow 2015-04-12 432 inode->i_sb->s_blocksize, 0); 36086d43 Theodore Ts'o 2015-10-03 433 if (ret != inode->i_sb->s_blocksize) { 36086d43 Theodore Ts'o 2015-10-03 434 /* should never happen! */ 36086d43 Theodore Ts'o 2015-10-03 435 ext4_msg(inode->i_sb, KERN_ERR, 36086d43 Theodore Ts'o 2015-10-03 436 "bio_add_page failed: %d", ret); 36086d43 Theodore Ts'o 2015-10-03 437 WARN_ON(1); b30ab0e0 Michael Halcrow 2015-04-12 438 bio_put(bio); 36086d43 Theodore Ts'o 2015-10-03 439 err = -EIO; b30ab0e0 Michael Halcrow 2015-04-12 440 goto errout; b30ab0e0 Michael Halcrow 2015-04-12 441 } b30ab0e0 Michael Halcrow 2015-04-12 @442 err = submit_bio_wait(WRITE, bio); 36086d43 Theodore Ts'o 2015-10-03 443 if ((err == 0) && bio->bi_error) 36086d43 Theodore Ts'o 2015-10-03 444 err = -EIO; 95ea68b4 Theodore Ts'o 2015-05-31 445 bio_put(bio); b30ab0e0 Michael Halcrow 2015-04-12 446 if (err) b30ab0e0 Michael Halcrow 2015-04-12 447 goto errout; 36086d43 Theodore Ts'o 2015-10-03 448 lblk++; pblk++; b30ab0e0 Michael Halcrow 2015-04-12 449 } b30ab0e0 Michael Halcrow 2015-04-12 450 err = 0; :::::: The code at line 442 was first introduced by commit :::::: b30ab0e03407d2aa2d9316cba199c757e4bfc8ad ext4 crypto: add ext4 encryption facilities :::::: TO: Michael Halcrow :::::: CC: Theodore Ts'o --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation --azLHFNyN32YCQGCU Content-Type: application/octet-stream Content-Disposition: attachment; filename=".config.gz" Content-Transfer-Encoding: base64 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 3QUL05g28mkCKrl7bcDiuqcHaMRcwbUDZsleYM/NPZyLdrO9c9l3y6jdeNC2XSE4Cu/0KpcF VjUYt6m5glo8qGM+HmiYr2yefjy+ziRY3H3//PTl7XX2+gluXyDvsi/PX55mH7Wge/4Lfl5r ooGNc7cvg9Tru5a9gAfOxh5nabUXsz+ev33+t05/9vHrv78Yb7VWI0M3/sDsXcCudUXiixnR he0/RqjDkvqKNm3iDAy4cfrbeM/kTWuHenVlji3tXtp4vySSqQc+lZUHvSZ0gOjbU8QIgjV7 spnk/6q1Vjgl+Pptpt4e355m+eOXxz+foJVm/4hKlf+TG1dA+cbkhv5jbyBez3bbDJwNTJwO a6I1aIDI35MsSXLwqE1mXSeJLzq0Knh5enx90uxPs/jrB9PVzKnlr88fn+Df/3n78WaOR8Cf 7a/PX/74Ovv6xejuZt2A1z1a4Wy1OtFRy2WA7f1CRUGtTZAg5hriI3KY3oGmyPVbQPYxf+48 PDwflCaOeTtqgua6jp/do7cYeDQtTeqa7LsgLr96rAl0xWdqS6h7mPiJr1BYQ43rRdsjdRvA mZVu6UEY/vr79z//eP7BW8XZ7hpXAs5u3ags5/Fm5dHbLa51hwMPNnf9IrL6Rbix2UjTsedF En/DqyvRcZoRrSTY/9D/wqPqyprYAI2aeJqGJb200FMmqwPOlDc4Rvmonb6nVznZR5HCDTSR RJuA3NoYCJlcrNulh5DHdyvvG42UradOTWN4+JtaplniIYB6FvhaFdS2KXw9gXtWloeqWW48 +DtjKugZVSpaBL6KraT0FF8228Vd4MWDhadCDe5Jp1Dbu9XC811VHAVz3Whwce8GtUjOnk85 ne89Q19JmRM16ErQlegrtcqi3TzxVWNT51rfdfGTFNsgan1dp4m2m2huVgJm0JVvn56+TQ07 a0j79e3pv/Xsr2fMr3/MNLueHR5fXr/Ovj393+/PWkN4/evpw/Pjy+xf1i3i71/1bPPX47fH z09v9N5YX4SVMWPzVA0MBG9/j5soCO48a+ZDs1lv5qFLeIg3a19Kx1x/v7fLmJE71AqsHIej VEcKmd2NHEdBroWEaaUhW+x28YnfIRbdBil4DECb9sN4x4ISmMA3peyLN3v7z19Ps39o7e9f /3v29vjX0/+eRfEvWiH9p9sAeEsiOtQWa1ysVOR24fC2R7aqGqILx/gYYkx478Hw2aL5snHt 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 fyKhKDuMpmT/D/tvPA62YwMA --azLHFNyN32YCQGCU-- From fengguang.wu@intel.com Sun Jun 5 17:02:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=FAKE_REPLY_C autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A09FA7CA1 for ; Sun, 5 Jun 2016 17:02:21 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5E2818F8033 for ; Sun, 5 Jun 2016 15:02:18 -0700 (PDT) X-ASG-Debug-ID: 1465164137-04bdf05ad7b7b430001-NocioJ Received: from mga11.intel.com ([192.55.52.93]) by cuda.sgi.com with ESMTP id jNeWzXKivihHLr3W for ; Sun, 05 Jun 2016 15:02:17 -0700 (PDT) X-Barracuda-Envelope-From: fengguang.wu@intel.com X-Barracuda-Effective-Source-IP: UNKNOWN[192.55.52.93] X-Barracuda-Apparent-Source-IP: 192.55.52.93 X-ASG-Whitelist: Client Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 05 Jun 2016 15:02:16 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,424,1459839600"; d="gz'50?scan'50,208,50";a="981399463" Received: from bee.sh.intel.com (HELO bee) ([10.239.97.14]) by fmsmga001.fm.intel.com with ESMTP; 05 Jun 2016 15:02:11 -0700 Received: from kbuild by bee with local (Exim 4.83) (envelope-from ) id 1b9g7R-000JNW-Bf; Mon, 06 Jun 2016 06:02:05 +0800 Date: Mon, 6 Jun 2016 05:49:37 +0800 From: kbuild test robot To: mchristi@redhat.com Cc: kbuild-all@01.org, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com, Mike Christie Subject: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code Message-ID: <201606060525.7bWU0DWo%fengguang.wu@intel.com> X-ASG-Orig-Subj: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="8t9RHnE3ZwKMSgU+" Content-Disposition: inline In-Reply-To: <1465155145-10812-43-git-send-email-mchristi@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: fengguang.wu@intel.com X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false X-Barracuda-Connect: UNKNOWN[192.55.52.93] X-Barracuda-Start-Time: 1465164137 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1969 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 --8t9RHnE3ZwKMSgU+ Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Hi, [auto build test ERROR on v4.7-rc1] [cannot apply to dm/for-next md/for-next next-20160603] [if your patch is applied to the wrong git tree, please drop us a note to help improve the system] url: https://github.com/0day-ci/linux/commits/mchristi-redhat-com/v8-separate-operations-from-flags-in-the-bio-request-structs/20160606-040240 config: blackfin-BF526-EZBRD_defconfig (attached as .config) compiler: bfin-uclinux-gcc (GCC) 4.6.3 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # save the attached .config to linux build tree make.cross ARCH=blackfin All errors (new ones prefixed by >>): drivers/built-in.o: In function `sd_init_command': >> drivers/scsi/sd.c:1141: undefined reference to `__ucmpdi2' vim +1141 drivers/scsi/sd.c ^1da177e Linus Torvalds 2005-04-16 1135 } ^1da177e Linus Torvalds 2005-04-16 1136 87949eee Christoph Hellwig 2014-06-28 1137 static int sd_init_command(struct scsi_cmnd *cmd) 87949eee Christoph Hellwig 2014-06-28 1138 { 87949eee Christoph Hellwig 2014-06-28 1139 struct request *rq = cmd->request; 87949eee Christoph Hellwig 2014-06-28 1140 b826ba83 Mike Christie 2016-06-05 @1141 switch (req_op(rq)) { b826ba83 Mike Christie 2016-06-05 1142 case REQ_OP_DISCARD: 87949eee Christoph Hellwig 2014-06-28 1143 return sd_setup_discard_cmnd(cmd); b826ba83 Mike Christie 2016-06-05 1144 case REQ_OP_WRITE_SAME: :::::: The code at line 1141 was first introduced by commit :::::: b826ba83985b86029288d8cc24fb93ce96947b18 drivers: use req op accessor :::::: TO: Mike Christie :::::: CC: 0day robot --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation --8t9RHnE3ZwKMSgU+ Content-Type: application/octet-stream Content-Disposition: attachment; filename=".config.gz" Content-Transfer-Encoding: base64 H4sICBudVFcAAy5jb25maWcAjDxpc9u4kt/fr2DlbW3NVE3GOnzWlj+AICjiiVcIUJb9haXI SqKKLXkleSbZX7/dICnxaGiSqhzubgANoNE38+9//dth74ft6+KwXi5eXn46X1eb1W5xWD07 X9Yvq/9xvMSJE+0IT+o/gThcb95/XHx+WSy/f1lvnMs/b/4cfNwth850tdusXhy+3XxZf32H Gdbbzb/+DSN4EvtyUkRR7qz3zmZ7cParwwnupy14Bc0elIiKiYhFJnmhUhmHCZ/e/zyNKynm PJgwzytYOEkyqYOImMsNGZ/6MobRFaSel6s86kPdfHICPiWxKLyInSB+knFRRGxucEnmiex+ eNmbmoXSzZiGwSJkj6fhuA9PpIXK0zTJ9AmhNLCpMwaT93AlWGaf/JBNVB/vCb+eXip9/+Hi Zf354nX7/P6y2l/8Vx6zSBSZCAVT4uLPpbmiD/VYmLV4SDI8XHNfEyMAL3iC728AqU8xS6Yi LpK4UFF6WlnGUhcinhUsw8Ujqe/HoxrJs0SpgidRKkNx/+HD6fYqWKGF0sSVwSGxcCYyJZMY xxHgguU6OfERsJkopiKLRVhMnmRKY1zAjGhU+NS85DamsU57ieN+mvOTYt5Y5Tw+IY4Drpfl oS6CRGm8y/sPv222m9Xvx4NRj2omU94QphKAf3MdNjlNEyXnRfQpF7kglvIDFntwWY0RuRIg yyTXLAe10MQYCQKJcvbvn/c/94fV60mC6qeBApdmiSv6Tw9RKkgeiKeK70bMRKxVLah6/bra 7amVgqcihVGJJ3lzI3GCGAnbIzdj0CQmkJMA3o8qtIxA+nob5ml+oRf7784BWHIWm2dnf1gc 9s5iudy+bw7rzdcTb1ryaQEDCsZ5ksdaxpMmj67y8HC4gIcDFJrkRzM1BXWh+5xkPHdU/0Bg lccCcC0FyvNCzOGcqAeoOsRmRRxC8oNTAT9hiO86SmKa6UwIQ2mUmXUeZAmEShRuklCcubkM vcKV8agh7nJa/qMPMYfZ1L44gw9CJn3dUNtxJLu4cUNbTbIkTxXJMw8En6aJjDVKiE4yi3DB s1UpbJyeRcE0nlFpZima5lH5CnRBmgkOhsWjjxCtDWkEpzB0ZvR15rX1d8YimFglORi2hrbN vI4mBUBHgQKkrTcBMH/q4JPOz5ennzkvkhQelXwSaFfx1cJfEYt5SwN1yRT8gxLaWtnV2ikG MyHjxBOqo9lz6Q2vTzA39U8/lG/i9HOHNgJFLEElZg1lOxE6ggdiGIBX0FLDeLJHcPMugdUa Q+xlCmD1GKmWkalgRWcIQeCqJMzhEcFWOOlgHUld8AmM1Gg5a2jkNAOJnnZ/xnfSOLa8pbpE 6MP7z6ibMYv4efsMfGBwThCLNOkclpzELPRpgTcq2YIz9sKCgzunjv9k2iRliZk3k7CVamBD rCIRuSzLpJGLEwORKzyv/VSbcojyXrStWuVHp6vdl+3udbFZrhzx12oD1oSBXeFoT8DqNT3r xiTEOrOoxBXG2oD1arw+cMKYBs+ucc8qZG7r7MOcNv0qTGwI5hY+KHt0RYsM3ImE8sqjiKUo yMlDkceohSR4zE/C67wSDU6+xzQrwO2TvgTFJy32BRS9L0Mwp7bDTkqKtm9jHBFaJ5tB15cu OLjA2iRGBc3RMNsWaD0OA2EZD0p7FyRJ45SPgU2UGn+k0EEmWEMtm4EPDK4NvbiUZSB0tT/c VowmbIBdaMHB+NhYixKvnFOlguM5NiQ38fIQfBvQaeYJoy7oqssYghyFbxuuJHKTEA5b+HLe UA8TzVzYRwiyBs9i1DlFs3TAVECbUPCGwPkSPvAlUVR9v+/ZTHgy+/h5sYfA9Hv5RN52WwhR S+fqOBeSVc40/awrTkrCSiKsCtUwX18WRIHwZAKRAYuU9QG5l7HftHYarAXouKb5MZpQRWgO Bp0baF5sCapizTBhlAapaPIY8dbBJZrcHdBVMkU/gGoe8AWPMZflnGpKOTmHRn2Tdd5Pwz2U ETALUugVU7RMpBPTSQKErsd8Wr1X/o6raJYaeFtwc3KZtJhkUj9aqXjkgeIR5TvNeqKbLnaH NeZDHP3zbdXW3SzTUpuj9Wbo9pAXrbxEnUgbroovW+Ay+koctfy2wtjf2Ina0UtKHzNOklbk WsM90D+4CXKTNRH3P50JT6upO9Bq7P2HzXb7dso6xObEMLNjRBSCIgj+mn6pwaNWrPDncOTY hwzDCMvgJrIa3bAkQkQp7iemnJkaPQMXK9YseyTGUpE1YJ6Me2Cuya1TaOluu1zt99udk7yh kOCdlWJzRGBE6W4Xu2dHrQ4YTrZkyPWvhnTSATGXVsy1FXNrw4ys64zGVoyVg9EV9cYBft2K iAFwY5tiPLRirKyOrayOrayOrYc1tvNmPcbxnQ1zOSr2h2c7NrKiLs8OvLQPvDk78MY+8Pbs wFv7wLuzA++sA69tl309uCMlCVTErIhkfDK1NYzN70cd2KAYtMWugtoWrdA2MTNoFluMRom2 KJhJKhOwBw1nEqKLItKXt8F4FA2vQ5//p7i5anMLejRAdxkMrMSca6yzhAosTfYtDMG5nIo8 vb9pwsHDGRQiy5KsB88GaOn64CENHhTJjJhk2AenqaSWjBinwArz3iSPBjOkMDmzDEEEOSLT /P62w2QbUPGRze/vCLCmwEOaetij1g/yfjjo7wCGU2BNgYc09bBPnaRaCX4/HDaBPNYdCN4H TtkCIv8B+keMoNZWareDMCH84H446gGHFHBEAccU8JICXlHAawp40wHiBibVdmmE20Hgu8VH hdnEPnjYAT8wzYMODKf2qzVphNtAoK380dULYD4L8TSVdC65RVHMbOqsJHLDXECgGcRyDk4v qXOR8BpmczOPYoR5N8PrgZgxOpCoyXQYXsPfrSVKt8l4A+pttVx/WS975UZDw14OECEC6K+V E72/HNZvL6sf4DUZv/h11fGdYLXq2ZojtbgkLaJGnrmF04pDNJBOhoOeA9MjubQuVD5Uw0x/ mhPSEtcYqpjF4NH/w4YaREHtlQZYONit9uv9BRzW6/pwcPRu/fXraodHfdhtX+pDlpiH2r2/ HcBPXW9368NPh+3366+b19XmcHJhS1QjDDF6r6vgFG0EYp80AgFG4hZ4R8MrtxASldmgCwbo oKOHKvCQBo8IMC4I0FIyjYO+fN8ftq/r/1vUrvwpy1EFiW5C2mUsd5hI/37wYzgYHPlNg8ci Y1GZOGCehwE0kAyqytPLdvn9Auw5RgbNci1IGXoET/ejq4H51fEVqnqjKatRISebFzOOBbH7 y0H164iD4RXuqouCYUbAATccV7+a42rk6KYa2Mx5moLexTF4bR5e8FTAoVDZracCdth8JwAZ t0k7s9DT4EF16zFBhtU6Ktcj9LnKpLkVZ4VpW+d59dd62dI5OGdZbAFPT0cZxU+DBtNuQNWe e79937Vn5Y8cs3iGm3IkeQTlijYyM2G03i8bdX/fXFuGtgmcVqww6bjnenYI6LV7lCXPfR1f h8aVXGBc3HxSJZer1+3uZw9XP9AC7iN7LMJhs7DDIWo36uZR8RbKSwy8CTLZTuMG9FAmY2sA bXnJDZiqGpjWFAGXCu6Was1VZpSLZNqZEFwEFLKQjj4Ay9NHejGlMx6lrUUAFBOwcooOWQ1r JuGrm6u6cGxMVUWRQjPXRsLT0C3Ug0QB6JPVx8sZnGbhh7kK2rdkQ7A0LfPgJdTIB7gIq2eb eJj9yBiuInlIZiILWsl3ULelemyVy5Oon1aucH7INFxJo0cIAAUWHsvIjbUybiapjOoecZgx NpTUTaYhuGSpNofO01zd35lfjWwThHzGKBS6rFRQBSCZ6UInhZs30tBxEkV5UZVdytwrPA9j Wo4kAjRgCuKP6flp1Co7hILF5jLIW35KOybuhHFzKsFprmOSlt0V968nejT0ebmSV4wt2Y8W 0fD6F4gsuYkWjSVj0qIZUS5wm53WubVQV8PR9BeWuLr+Barh6PYXqLrphtJ8LMDeOur97W27 O3RfiBnYdHYBKOal4BocFn06eK8e1Nb71eN1WTxlNhGopvZsU1d4k7t1WbsU0CPQQZbkk6Bv 3krDke62h9XSZOXzzfrQalVsV8zLmGL/c7P8tttutu/7egoy+BCuzAsWTbgOncnL9vPipeE5 1+8HCMBnaGTywY3w0kwmrVcGVK6gi50VrnBpR+eELlyLJm5SFO6IuJKapGxdaG7Oxc31doVX WwzAN71x3UELOKSAIwo4BuDdnTuqHAE4622ZFHd+S7n8w0l5xCX7wxFSwZ8Rhz/gX7+3Siqc s8zrXaD4sVq+HxafX1amsdUx1fVD0yaAKo60KYH6XtqskAIIvYGGMJak4MrIVPfAqPx7wKcK epLXao6AZfA0EWuvQLIktwTv5SSRVJy6QGDay023ZhmNbf+GOO51sVl8XWGUVp/t6QxUrlIR N0xhBWgUL07mvkKpqQTr+xhTHKRRoUIhWuYPYNjnZOB0IT8yyUnjoZJzdmbzhJvTwfADpkke wISdSstVVYp00rA8Xm0qTZSSLQUEC5VeEPIN04i0fRwtfL8EuIXYGGVPve/fVptnVCHOhROs P5tMxcp5WHxffczfHGUc+3aNsJoZDwUs/nVfhYO+8ner/31fbZY/nf1yURXFzyJb1Xe4Xqqw Fwtdy068Ovy93X3HLEpPalJQxaIl3CWk8CSjujHy2LQOnJowMJ3UpT1i534WYXNCRmKBRYhl qY43Gbd5Aik1vVucKfoxAUFdhAVvL9eC6qYAojROO/MCpPACTotzhUeH7yxBxjIaj1uUqTyH nGTYZx7l8zM0hc5jW1cEPF/QFslUWlphcIbcOzsFkvgJ3R+KV1EwuvnD4ISyHE3JOjYO2PFG QM5wZoj+CW8midBj1xmLTbLul4h/eVpXiDMzWqVf8xSLOZNz/QFHGp67TbtVV+Br/P2H5fvn 9fJDe/bIu7L1bch0Rtc9gWX8ZKBQgkcso11P3FaqYeWQgS716UJYPRFmudD9hyguSjs9XE1i X4baoglAwj1uf4OKW55f5lkaUkDuSATEeiQ8HFlWcDPpTagAr+waw+tXrKlSZiGLi9vBaPiJ nM8TPLYIUxhyOoMvU1o3MM1C+v7m7fL8aQmW0v0yaZDY2JJCCNzPFV1gxyMwGRR6u9zSnwMX wUzjDIlOwJDPylwDiZ8pzNtpq8ILJfij1ncZpaGla1DZDVXJjSdohpEiHBcRwypuYaNSJhlg usRNYyRttotsjgH/Y1H10tZH9insGHTnsNofOh6BeblTPbHEHgGLMua122NP3gSjB8nMoz98 cWmJYT5sIbO9QL+YcvoRPkj8zsnSY/YgI0Y/g8yfSktvG57GHf2wOZN09xkXaVDY+spin95V +HDGmnhKF/aMi9EhYoYiSybzH013Z0VRS4BnMtOOt1v/VXaKnT7/Wi8rcKMnqXbWym7iQIRp swe+BQb/Twf3Hy72n9ebi2/bw9vL+9eG1QE+dJT6lHMP+j/2WAiKpNl6Xs7tyyx6gGip/ASk 1Un+YConpMNWthhjH18jHGqwArFD4WVyZrEqFYGYZbYvNx5VETzCpmdSJfQcx0oBeNowk+x8 BFKLoJiUicLWz4VsfudSwbCA1kkrVXGkm/s+0YGIgXRZiGiXpBKQN0vbcKTbPaXaMx/rWTpF AQvLmxoWNiTaqRqtkmeoWHbTpzCc53sQyqj8stF0xOvdYrN/MSkYJ1z8bPU84lRuOIUzb3bq G2CnkdTXlsdvQ0grJvM963RK+R79+FVkHYQMJ4nl8yNEHltAQQBK69E7toxFF1kSXfgvi/03 Z/lt/eY8H99983p82b31/wjwN0ybPC0lKN7H7/nad+1LtM7m251Oj3GDCgXa5H4epKeDYti+ qQ52dBZ72eWgg6cb8igmaLeXoBxTmbN687KzGQMbUcckacfoiL49t0qsweTNNXn8ERgOS/d3 RQIql3IianSuZdjeBchSB5BEzaS9ecCu6nTJl7nXxdsbphAq2cMkXCmMiyW2unZkEaI+2Bee OIYEnSeMpY9OYaUBrr5tsW68arHzaIWNFDkHPWUJqM1CIcMP56z40FQ5u0uUpanVy5ePy+3m sFhvVs8OUFfKufEmW3Ohn+eHnc8nmjI5ukpvB92jUEqPruwqRYXn2E+Dc1j4fQ5t1Oso0v0s rLfef/+YbD5yvPSeA9LedMInY8uGTeuK4LwrdjUc1CmVjqxJrMNcS6xgzis693XrcRqUrPMU iVEhIBzGjzm3Q+kpklXXv5rbJbPs65FqmsQ8sKSNTnRwynbdY0jwDyXtt22I8Dngp5vnqQKp 5NXAvh6YMKTriU2Y4jv67/LvEVYBnNeyBmN5MeUA+mix2ShOsp6t0LfDHz8Qc36ccaUvTe4D PCfVnSZ3JR2O0pEC2O5urqkOjMrPT1o1g+qLlDgPQ/yBDqgqIg5u7xmBrclCcC3OEniZa/mC subGJWu6FbZlLRrA8nvE++E1hcMPfO8vB3fXDV/VAzODYSn3ZjQ/+JUgFvMLoelXXK8QnN9P Z7/HnhjKgwYrB16/wv92YxzOBiMLZ97V6GpeeGlCWySISqJHbDOhXU2u7sYjdTmgK3ki5mGi cvw2D4MQ2xfmLPXU3e1gxCx5C6nC0d1gQH8bUSJHdLGxPgMNRFdX52ncYHhz+88kN+dJzF7u BrQKDCJ+Pb6is2CeGl7f0igtwczyG+unNFE6uL3CaOwcGlQEicZewartxVfs7tJyBKBDNVwg mKJ0XJQw+hxsxpePusqkrH0K8M8jZ38s8p+Ex2Dg6Vi+0jnh6WRghQ/FhHE6w1tRRGx+fXtz dpK7MZ/TfveRYD6/7Je/9OrHYu/Izf6we381X0rvvy124FgdMDTEHTsv4Gg5z/CG12/4z3Y3 XmGpBzXftvVmW0Qd6Tg1Iy8cP50w58t69/o3sOY8b//evGwXz075f/Q0+WGY4GboladhbzJs un1xIslNRF86TnXiRnHpE+AZqPc+9DRRsN0frEiOLa3EMlb67dvxozV1wLpmdKo2/8YTFf3e zTchf8fpTjfOA0t+cR6aVlgrsmpsZZb7QhIhKEfaJOOl14pipddvmFFcydpf33fbZhCJ9Z5W 5xiTEBBpnZEJLxjQKLfj8PJ/mzpJGMKqfDQtgmbNT1Rpu02D/xVKQXxabXZUbcU5/HxbOb/B W/n+h3NYvK3+cLj3EV7f741OicpQqtY2eZCVUJqDGp0o8n98Os6ZNT3eE7SYidiz5NeOK9Pa 8oi2OPfmbODfmHu05KQMSZhMJrbSlCFQHMsR3VaI0xHrWh+1XQgzFHzLnoi0SXz+TxTS/PkP RIqpXyEJpQt/naHJ/p+xK1luHGfSr6LoU/ehp0Rqo2aiDhRJSShzKwKUaF8UKlvV5RjbqvAS 8/fbTyZAUSCJBH1w2GZ+BLEmEolc8qFi4mwvwwHQiNAyIBkPa/tEQQx75/LjKoUTgUL8YhMJ KkIJLLBaNaupGZi2NNP63ZY8nqUhNSOkTGfezb6XMtQFfU8kIupw7Qd4N2ik7SqKAm/BYYX6 Gs78jAqJFQm8QCIrisSLr2FMNEiURDyoMj3sZK/KKHFEDXaUMJ/GnZONWlN4I3Pd9x/ae034 CDLC448PjG7I/+/x/f7XyH+9//WIhoAfr6e+ShQ+jttJS7VWb9CCE9Oo5lRoT6S/plPKIiuo i7vAD6NO+CMYvxWBXrXiGkozIUB3ngg4ekQ8gGNjojnCSFKhkdyxsbarIvPDIKPMYZdjwtki 7FwG90uO7lA/QXSS1GqSE68GJX4BDGYYxoLiE4UBKiM1Jhow9WHwE2ZvHPxZZGmWtEYS5lNm Ukxp7yFzwGN7m/PUxCJKI2DLZhpeZxdGEvcTXrbjzPFqs4rIk7L+bhSZj6U6JuEke2kwQvav vfGwd2Y5vzU3cMd84/M9u+ssUfXksJ85xNxsABOjN1C+vYX973JPCtvACJ5YdLQ+DFoKOxW+ SGxV3nhS0eQkJGn1FCfpoQ+7FmpGCPp3nKokNa4ESQsY8CK6TTsmIs4jko5cMkWfF05CcN6Q xAvfoQFBsqgquleB7i0sdBbkcUlXroiQ09+Q9FSGovLpkeEicsaVmZvEIOFEwhk7Dt0BimvR A597E2/q2enzhbV4ye5IxJpVkWVihiw7rJhY+YQEpAABRvVhsCnZ2njDveVyRoRGzXMiHmLc ZtX1Y9S1SHsIeanf0s8iKfCFuSpIvPH3FEtEch5tfF6aRV6kFyL2HEIDdqWbFUxIBwFu4RGa faTDD2VhJZ1U8y1V+31HNlRqoRdpDr9/RKuYP/sWvn+N3s+APo3ef11QBua3pyx+eGgmpLu+ Wzd7+f3xTp6qWZqXmkm9/PewXqNzFdr66CdGRUO5lDKgUgguYzXdJD5lWIqgxBcFq7qgxg7h CePyPKIf9M9jRy9cv59hOCtrPb5lt3ZAtBuid6zftf6kL9jUuzfR7SrrOEuYmmCvP+86yXYg MjIcZfsqAVkZbDkwgrbBWbsecLhtaWbkU4wmMDWvFwVYJT61IOvum1Tjw6oUgrgmqb+e+N7U Wk6Sl5OxFbHJXTN/u5CRW0q3giGUYLGa4oTBZN03gsEelmQiIixCL1MAlkJaI23ASnwzhy26 LLl9VMCCsZVxC1sqpcVSiCBxxravlPKXrRrB2pstzMpsrQuLDAN34d1JFlo7XJ2SJNrW12EV T6wTMUj8CXVSUoiw2LnzcXXY+jkKTUPI+ezTyIUVWSRs2tOKqGAQx9cHqa5mX7JRX2+FEbaN JW78JDLeQwS/jq/He+CX2lXaRVoUWoz8ncbsA6WeUGb5sZS5uI68AEzPGuejmrLda+irICs0 ArpUdXU6ly02ZdUS5C1x2xIqgD3ngivfkhwKYFKRSF3DqZsSWYjhE3K2fRO+jM3aMqrB3gZZ M1VqypBi2ulhw80n9TqzgNlCFNqg/Jf1Vt3Ao94Q8tPr4/HJJAfUNfTcNhdUxsbnl78l4U29 LpUzhuuougyQNCbU0a0FMYUPrgFtzYj2sD9hdGJX+a6RKMMOHSNDMtkrpUK49FxXVWCXQHDK LrIuAnExE0Z/cYVo+ypqD02TvybzIEiJo0qDcOaMLwjpVG8f7TxTo2oNGs5zbM0noEMwtq7m 1dw6YfyCMLxU5DWPD3FOfgfYUx0Cm1q1mch7YwrP6kCTUYpCkLHo7S64rnszL8/hBK/yMpi3 KmBf/TjLVwY/Wc7NG2Lh7222zyKAn9wgrLuBQUZvxeN3oU0oWbYD4uJjZZjXebYFaLRryfHw uOPPplFqM/M6BUhTqWbDwgvPaw2vlZZpEUY/0Bq6tkD88/n89v707+j0/OP08HB6GH2pUX8D y0LTxL9aTWySycgobf9SFAy/c7jBIDh64B3Z1FXJaRsxRIQRxjuXhu5WoyrEWgvKcM0T0gGQ 88Af/kBeASgwX6UinbNEEFcLSK4wIHfVm0DRf2SAricclC88wdE6Phx/S8HAcFbBTmEZ+kSV hPmFrKqypDrEbLMlJERAFdkqE+vy7u6QccJ5A2HCzzgcreiOkRk14NDda1sGh+VXrWHaZOs2 igsitrokxv6OkKXlJEG3hK7UZoBgYqQByKo0Xky3fQzwgrLnaK3RlN15E3wlZ6PkiKHELmEC nuBPwzlU3ntKHm9mzkiu1PVolG6YMVwmEmXcuKrq1nhoP0KIRYOF9Po+hqRflysJIVcpEjM1 l0g6rEAXlZjEIkQIav7JewsEwN7tMT4fmw+CiKhQ3qSpvWXcIt/dpt+T/LD53jGSaaYCxto4 35+f6jnRmwHwQ7q75UyaKGK4j162qBZKxNHcrQgZIE/M3bfl/RrnOTfJpnnet5zAZ3XCtPNr b8vJRT66V+G6DMWBbODMPK8fgk3XzambCBkAmnSV1ZR0x4cHGWgcWKv88Nt/XXevOvL9DsTA kossUQfhrRZFqZBhub6XrIgkUd2BXA51pge1Y1Tfo6o75fV3ZFKU5nJFmfE+H3//hs1Xvmbg lupbe8rzVJIvXlbWPU0i7/o7EkoH8uOn//yGzjZ93g/zGYwXXSwcSRZU5LkrwDWvIwmALXk5 m1gBqN2wAHjlzAi7SKU6ylngek7/hJasw34HNAt4oGtUy83mqQoQTCYeYfSoGsZ4xg2eEvDt 8+tnRicJcnfCx16vCNyj6Xf35kqrqCGYZi82c2YFgKlPKDYV3d8Zc4Xsk3YWD/ngsGPmI72i 1ht+h8urw7WKdGo8ktf2suFiQgSC1yDTz0DM8/8KSZyxS4SHa2HMlqBtjNkYtI0xKwtbGCJG vIZZutMBg+NQQA8OY6afwgzVBzBzYqvWMUNG0hIz0M88WMyHxktUuR0R8vmAaTjaXQ98Zr1w vPHMLJHrGM9dE8JaA5pNFjNKh6Iwm3jmeISiTMO44yHMYj4mJNcrwj6UknutiTu0C2jLtnNn Yu9jJjxzKoIL4FswtVcFmFbhuANDid67/oYQdi8YEbjLqX3qScxy4FsimDoz+7xBjOsMfmvq ErkrWpjhOk9dUs2kY+x1hv3ScQbYAGLm47m9QhLk2HmgxMztfBsxS/vskQrXxUAnopX/nMhu 0cIMzESJGXAlkZhPVXpgloHoMBnetAJS81mPezI3+85cAQMMGwCDJQzMz2Rh7w8A2CdCnAx4 5wBgqJLeUCUH+FScDLEF2LCHAEOVXM5cIttLCzMdYD4SY29vHniLyQDTQMyUyHJzwaQiOKA5 asI4ZRHdQAMBK97eBYhZDMwnwCw8SmugYZaES+e1eXBsWRKidrIiLGoub/OtGODvgBhYv4AI BoSYJHIWRDKfCyZKAmdKuMhpGNcZxsz3LnFgaqqc8GC6SD4HGlgQCraaDLBLHmxn86qyuY22 oAMzVmKIzEnXmiXzgU0OeK/jeqE3ePbgznhgogBm4bmD5Sy8xcB2AAPoDUw5lvouYcugQwa2 FREQxgwNYJsEAzulSHJnYBVLiH3SAoRyQdUhA72yE447IPnsvcnCc8yHYR2z/AyG8MhtYezt lhD7tAJIvPBm5MWtjppTuuYrCtbV1n4QUqCIQMldwjcFKpcZZsKsZQl+eUbfJjSINNv7t1Qs 2gYl9Xs9LcX++H7/6+H8j8UojWdr0RRj/IZSRNsxd4wVqOW0gmqtvh0U7u10lEAnlbk6NUQF bg3bsVkwprLr4ONeL5V8VSc5bfoLfTBb3QSYPLB8k6Ol6jV+rVKknV8e799G/PHp8f78Mlod 7//399Ox7QnLucnLZBUkfq+41ev5+HB/fh69XRLx+MnK1wvD13qtk8l4fn68qLDblpgn65Ce jUj0+WRBcJE8YYHS1RIHWfm+L1xvMbZ/BJowW46pQBtYSpW744r0CZc1Cf3lmNDoYhFInrmk d7EGob7SQMws6kImtBAN2cwDazJlQinJcUoXDfLSBE30be27YKgGguR2yH3OAnMVkQyv5jFl CymiGIMmyuEgK3ETJVQJSPa8HA5GdCcoOj0Ckj4nFPOyE+AAPp0Rp7casFjMia2qAXhTK8Bb jq1f8JaEXrahEwLklU6E2EK6mFPypyRH6dp1Vol5jKI7vAIljLXx9R3Lo4I2ZkZIEQlzeGIk whFlBquA7r5CzMZWMq+69gBtQDATM+JMJunpTMwJERfpPArs7Iqz6WJeDWCSGSHCSerNrQez kF7OpJ+Xv6pm4wF2iulhqOBJQBYYrGwymVWYIs0nouQhMM4nS8s0j3NvQdzSyXH244TwaxY5 nzvjmXmRIhH6zswCFJG4l5ONkwCPiCrXAAi9RwNwHXr91AC65RLgzQcquSSaqAHse1EDsvF8 AAE7JS5mxD6GQ7ZlNgFgPp4OTLd97LiLiR0TJxMqG7CsZUKF8sLNv2B3Wepb++KCsXXFPvGm lp0FyBOH3hw1yMBHJrPxUCnLJWEmGG3KmHTDT6KQ+fKu1GTyvXk9/v6FomfHNsIP8tGf/sfD 43kUnJtM13+Zc6qsX4/Pp9GPj58/0YqoH4VpTQWIDm6kNdghDkJTDRvkbuNz0fFdUB84v7yd n2TsGJCXL+HG+taPKoJT0LUsbj2G33GZpPyrNzbTi2zPv7oz/UBUGoKhbVnYrwA8bF0psxDj Y4uouMW0XlG6IRzDAFj4eyOp3DJTYC8sura10HJt3aNZN77Q86FHvD/FrKHdCvpBYbTwlLQ8 bxsqNw8ZYQOL9BKdNokSVxGmROx1UiSy/LA2ZclEcgBH6ULzTFDPGPx32y0pkAuBrFuQu047 tpROvM1lXsdOkTA0mywtGOGBhZAo4Z3at8lxRLnuK7LJSkdS7m6iXhM3UbJihIQl6WvC7AaJ 2wzdaUkyfE76gdGAW7oXyiDONoR4j/S9H4t2mDu91reFdCvpthbdn+lPij1Lt8S1rWpPyhks O0LkQUgcSDMRmh6l2Y4aIGywaVFdnuM/hONsAyEmDtKLMoHzfu6Hrg21WcI2bKHvt1EUWydo 4sO49ZwMdQC6KaNmqL0IkyzFXOe9KSrdcOwTKRUFEVcNqbBFRCYjf6Tlfoq6tThr5zbWHtua mkdpgjEPqcIj4ce3adVtUQ7cBvYvutjYx/grKeXfJTEFGfkeyUUWBFT+KSBzn9F9YogtIR/n URSSzn4SIXBuwDZijIYuEWWKHvrdogvKlhPXMjqR+tzCh3niF+Jbdosl04ub7cySnyRmOY8I 10tJ3xYlF/1A3B2OZOPLFYOpQlLvoiKzVv/uNoS91cJ5lB75sC379ut4hjVKGOhhbpAycsJs rYZ37HqvrhqtT1zVNejcYRQ7sLxsG7BDzISI0aMGdlvNw0uGWFQiXvuhusxqP6ttYflhG4Qt SjdagJ+msGQDzNKyN8Xub4KDnp5QnYrJAbEDeymyZLLoOh1PHhWccdH9VHib+qgxTFiaEWG1 ZB8Qib9r2mG/hcUaM2OQtQtGuqogBmdAtx5ljFbxRp8AJHdsF/HRXnbzyl+bJxMGGLR7Acj3 54tqPMYBIZtX4fDbANEQIKtK1xlvcyuI8dxx5tUgZjJ3rZg1dDV8zYpBA5Wp69grPdQqHnuO vYjC8+dwKl9YQUCTFvYyX5VxKOurm+Dp+GZ0apErhkjMIuNnoAcdwRTlRArpd0XSj6qXZiL6 75HsAjidolXawwmz672Nzi8q5N6Pj/fRNVzh6Pn47+VMeXx6O49+nEYvp9PD6eF/RmhCr5e0 PT39lvHpn8+vp9Hjy89zezXXuO5aqB9bkhLqqDrGzCBOBoD3zadcHYdpGql9RccxHrqE0kGH wd+EWKCjeBgWxEV3F0ZcUuiwb2WS8y0RKFkH+rFfEjmFdBjmpCLFQR144xdEABodVZ/UMPgg kZZKR8Mx+VCu5q4lJkzp9zcUXGvs+fiPTJXQV3dIxhEG1IWEJKPUbJlZLKc1Y/J9yRBCwmdW bld74kKmJtJRbpB3LtoGUU2rO1H72p0qPXWNr7V3YOL9KGHELVhNJQzOJVcLS0Ekg1BV2/GI Xu4Fy2aWwYqjTSbIk6BEWNg2FQVEbqr1bA1uFwFxxadg0mSAHrGQDgMjdzoRskNEhZ+U/Yea mxBGPvbNDhWyJXRDMPpDAOLXqiD1kLKi2d4voLdpBOlCpuQHLqNvckw2VYnSskAYR8XimtCc AeAW3qYnTHQn+62i5+OWgywIf0xmhF2O7DHMUQddGhW9hjVrI//179vj/fFJZUeiFgcZ5SzL lewVRMzsoYdUacS+owz5GoGJuHuSJfjhhgpttSdu1Yi7wiRK6JBEKMfDTCRi5Acg3nO2YnDG MKWULURwaPnA4QOZ37L9aBuIrBXFUHtYnyK+/vH6fj/+QwcAUYCs136rfth5q6kxQnqihhzb AsOc6bGptDdACls3bnjd5xgl2vC4k4pCf34oGWx1SUnkw8IqFjvzBMWjINbUMCsv7/mr1ewu 4uZFcAVVHnG9foGEHCag+f5MhxDmdhpkvjCv2gsEzYKWBLu/YAo+CyYD5TAeO+7YfKHXxhBW +W3QzN72CiFWhLTide3jIDGUNUkL9BkMcV3edPTUEYS5+gWy+j5xzYzgguCT2WRJOPFcMOtk QnnfNAMK84+4OtUgM8/MAfVSCBOMCyRKJmPC7rYpZed57U2jcaYcWGvYo4SNSQsyuEYmhL1p C2JvKEKIe/4WZHhJE9fqTXctF8TGdB2W6fDIzZ2h8cc1P7WvZ8U77H0HS8N1BtZhEuQdo1Wd b7vBAbMxqRAPzdxAJ/NP8OOQT9zJZ2o4NElhjizbxwTlNf90fIdz9/NwPRyXsKjQIDPCTFCH zAZn2dybHdZ+wghvYA25IDybrhB3SnhLNBxJ3DgL4Q9MlKknBlqPkIl9jSFkZj66NxCezN2B Rq2+Tyk3kWa481kwsMpwQvRPheeXv4O87EyG7vdVrK/mdpyfXjADycAE0hThGE/BWLcw8Smt L5BW5VpT9TYvYQYIOEAQ8Z78srIdhHasaGLX9r65e3yFr5kaha+hG3zHZKXWT9+/nt/OP99H 239/n17/3o3++Ti9vRsDsAm/m+OiHQqQ/358kSEtOqH1A/mQnz9eiRDZIsFYxoyI37GVQ1Ac gmQAkIiS8GS4IERitvKLkhoAhwPzucFn8Srrx4YoTs/n9xMmtjH62ItIKkwTmOJF1tdRFr+f 3/7p9hYH4J9cRaPKXkaYDfGvqy21yTS+TDEMDpX3icsoMkZSnqCIvi6IKO5RhQkgqHNURkW9 JAyj8n2rfpexL5LDBm82/OqQFl8drZwcw7pQ50YZXmEovcTaoBfGwyz/+KECebVCRVxihBCn XYytgiGvXC9N5Al8GAWHVyJjWJAcbtD6CxHdL15KQq1P0MliGvQv5XI4xsGWeHyBxfV8fnl8 P7+aVm9h0CX6Lw+v58eH1lpMwyIjru3SXSfqozbRiWhY0sK6bV6krLYw5VXLngsGpVdnieq9 ekmUZVgKTRpwqKgpMvP68elUx3DTM3lUwj2sW6Gi60eHCvPYUItj0kmYpNOmFK2IGI8KKJqg f6NJK2F5L2XxmrsUde3Sb67Ru5+z6uAHJvuoqMJ7U10dgNvXASMTMXm337DINEQF3G2Xrn8o SoPiVqZ8NnxpzdNMsHXLbiNUjwxopiiYcrOVr3Pt919piN/LjMgMJCkBkWYbgwmuOTmma0z7 SdAw6yTs56bcWsHx/lfHWJEHfrA1mBrKNFtfMLslTuHeDGY8W87nYzWJLxMpi1k79cUdwIha luHaVMMw41/WvviSCvN3gdZZOAmHdzpFXcSQBq29fbn4xljLOd6ZTScLE51lGAgSeP7XPx7f zp43W/7t/KEP+hVairVZPk5FbxEoDvp2+ng4j36aWljnRbtOc/kA7dVF3LLzwcfBlsVhYYxU jqnn9GIuGramgG25iUS8OuRUAA31q9eCS78zruRKVApGSavorPDTTUQzAD+00NY0bWslyQQa FCez1GZFk/pvNUxT8T5t9tdPlAb067j3XMZeBSF93eYeVzrQDrB2KU6igLyEfYYQhJqi6E1E QTDsKV7FAFc8ZJI50m28UzrmTgnxnckUUNEKlGz7rxTliplluzjbEP0fgIxJkPj30udbgrir 6DFNWApbD8U8E8sUy2na/zd2bb1t40r4rxjnaQ9wTlGn2SB96AMl0bZq3UxJsZMXIXWNJOjm AtvBbv/9zpCiTFIcOkCL1pxPvA6Hw+GQsyo2l0HqFU0VoUIrPL0lHri5rW+oz1qKcfXDffbM 1UT51Ymn8ffNhfP7iyl9VYq7kNtkv4EBSfWauEQFRJ/b1Vw+G17hW+/JqVa48Ls/oVS7Wa7j FexhRGWFbFcpAV+JmFcLqr/jlNKS4or8pkwYLQWp8cvM8cpqvQhZq5RB1stcB8ucNXAmjXpq wgYR73NYoGvCucAB+TcpDuhDxX2g4tfEeycOyG8PckAfqThxmOCAiFlhgz7SBVd+w5sD+urn pRPk65crkj++fmRUvxJ2WBt06Tfw2bUljr0QBBolcnlHKFxmNlPK08VF0SPP6jj1htYzajJ1 u00T6O7QCJpRNOJ8R9AsohE0f2gEPYk0gh61oRvON4Z40tGC0M1Zlul1R4Qp1WS/sQ3JOcPn tnPCK0QjYp41hJ3lBCka3gq/yWkAiZI16bnCbkWaZWeKmzN+FiI44VulEWmM/jCEjUVjipaw h1rdd65RTSuWae0LaY0I3CnBdJGboOVu/7L7a/J4v8UwX9oY+bZ/ejn+ksc/P593hwefSVvF PhjZybV+B4otTmzQKmXE32GFvDRU/rJsdDYJp6zf2gna79MQvz6/wQbu/8en590E9tXbXwdZ 7a1K34/9rtWzqX0UglMpQ2oneNLGhAeVAYOdDjFUBihZMzHzT7h5EnV1LNKq8WkYKjpEB5/j Q6+wT4hZww3H9J6et3WDN9LipWGnAXVdfflt+vnC6O+6gdJAmuagtOaUmYolMmNGPHPZFhi/ DDOIyoxQlqWP5bqwrbNW35hb4gUUyUU9tMLpxprHuDXCnW6OD5x48nQhqtfKIrNMSqpbqpL2 N+7rVgp8BYazJeq4HZ40eTcweEsJtX+xIpupAs8771onux/vDw9qstl9xjcN3hAjbO8qSwSy LCsJMzRmA02sy4IMQi2zKaPv0Gn+8ev7PSOci3tyg2b6tqbMFgpFREtQxAI2Ay3eJHZ3vg5O HTrIyN+enpbPlxt1QsPbLCvXHk4yyeSY1YtUrPSQybGaZK/bX+9vSq4s7l8eLDGIG522go8b 6NDSz/JI6hZtgRHHa2OmatPVQJLStGybb1Mz8jLKyYoB+xrAChYBX9hgEtvdsKzl34xs16vw W0bqMzROlJVPRFn0IXuLqJszJNcwy5PeOGMGZpDJKDH9e2wk421sKrQ8fq04kheJkiQBhsJa LTmvqCmizwSd8uSoIy+cpvDkj0N/+Hn43+T5/bj7Zwf/2R23nz59+q/JJapg0YDAbviGCMHS MyDUy33/350RZzNZrxUIpnG5rhhx01thsbAuIFMEzBlt1ycsR5ABdlegENaUuIjL6Gtn6gLF dAxDQPBshh6CRNQ0LBQmHLrkBqJAIFPIOGeBQpdKGpIiAf7e4EsyNR8LFfdalSuu03OIOiSm 5ZFGyom7X/0D8KCvcAw1nY25VcQtsd7IQUWyt9dkJFQkB9fLs70vMwB5G0Z8KBt6DJHKV3XA ZNRPiVW/tAt6Ue/HW/IWrMZ4TE5o4/3AdFwIGZn+u9JBvOD+KCOIyUC9K+Jb4ko6rnGztlBq juwKI6q7TZ0LVi38GK1JzyTVzUBFA8xjvI8Mq3KsbjTroQYizsvTdcpT60ZDo1jv/UXq5M3u cHSYL1smxMGx9LOXtxBr6l2OSE9oKR8CTBM1sCOj6ZKtYdHqwjBgX2AWmq7k2tXlIK3odi34 Jmlzv/STANTPi3kfyYx4kAhxSwA2JfEoEQLknop4CBLpUdpQUY4lXSxYvWjI8HSqNcy7v4za NIMFvoxrYQXnVSO7DAw7Huh2cVlRoeOx3lWgUS29hex7lzXA/Bjd1i/0WF5l/ovnOD/k/eAl bNrMVuFv/zYpqpnvPLBXi4fVxF7Wc1G7aYs1SBhj27dhqEraiQqZlC0MmNpk0yTFG+N1zISM YpjYNUL5AJJU3jl3S5KPWy7WaoLa14I9AOsEzPvgyrmPCs+STKKbte+4LPyR6ZrkQfJN5Zh0 xtiilBtB/Y0xmExkOoakEd22yqLODpKoLqGMd8gy+xRdwPzC0IRVNW+TMolQ8tVFPcqmymE3 sOSwlUH1t4tgNRr779S77fv+6fjbZw+iJxaPW5E2t/iedi1duEDOxYS+1mODRO+RjN5LnUpj 8Xinpanf/jOcz0jPlCFmZLz//XZ8nWzxhu/rfvK4++tttz8ZjxQYQ+ixygj2aCVfjNM5M47G jMQxNMqWcVotuBiTUOKOcsHEMVQU8xES0rzAwTI3qqBRk2EM9Hc184xBT8xZweagfbgZ9um+ /FD4n82wS9JaGqfkrsCTy3w2vbh2Lh3ZiKLNslG9MHHcNXhAu2p5yz0FyX/8FkJd5fMQ1jYL mGUhiPeCFHs/Pu5AudreH3c/J/xliyyLrnR/Px0fJ+xweN0+SVJyf7w3Z6iuPHEdX3dimBwv GPy5+FyV2S15YaPH1nxl3xC0yRwySov0RtuiI+kw/Pz60/aO0gVHwa6KCV+LgUz5NvRV8a/j PTkT/ludPbk6U7dNuHCQnGvhcVtc3B8e6e7Imc/+o8UCUM0TMV2RMxW9cTJVRrCnB9DhfVUQ 8Rfi+UATcQbQTD8nRNhVzZGurjnq/w/wYp74zfADOfx1CrzKs456MFiLxTyZErEEDARxEn5C XPzpPy08Ib4QL1nribdgU5o5gAoleNgDCH9Og+PVzAUVWEKLzcrJQjHO09ujdU9jWAR9cpwV bZQGpwxo48HhhC38epaGuSZmOc8y4l2oAVM3QcZAQHCwEsJO15Nn8t+gdFiwOxZcSGqW1SzM EFpqh6U1ceg10EXFi2BdGx7sTVDA3UEZDvH2u8NBve857sFZ5jzEOZLPd37DcU++Ji4rDV8H eQnIC88ljvuXn6/Pk+L9+cduP5mriK/+BrCiTkGtF4XvaX7dSBHJMADtSDuRFCnPxxNF0c5I RwlylscxYlTu9xTfCuV406K69QgLuV9HO+258gdg3SuUHwILwtjs4lCNDqyD60Gx3+2PeJUG NKODfMTn8PTwcn983/fHxo6NKkoLJm49lhR1CvD0Y3+//z3Zv74fn17Mu/RR2giOF7Xsl0oH C8KJ7qm0votScHRnTk0nM01KS1NRjUGZg2GyRyeeUgIp7oKLLeTetJ1vBynXcZv/IMFr87IB WRrz6Pba86miUBNPQphY0/MeERFxAA9UvzNNlkZBpSX2r92sTdJGjR+aBlijh8NveWRFUubh 7kF/Xtzko2A7DahM7cWd4Up5Vw4WiRMWUxPuS7/0pm/uMNn93W2ur0Zp8gpSNcam7OpylMhE 7ktrFm0ejQh4sDDON4q/mwzSpxI9d2pbN79LK3OLPxAiIFx4KdldzryEzR2BL4l0oyfw1cC0 zHnuJqGpHDavlZ2eWFVYZaYnKbqMjye9NjIbFiH9WuFgf5YDNJNXepr0xt60liIheDVJ/NI4 FSvUqv3+xPV87PxyIlVlaV2RGKpaY7BiZnuf/wv8x2kGbeoAAA== --8t9RHnE3ZwKMSgU+-- From simon12@kyled.com Sun Jun 5 20:05:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_MESSAGE,MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 232587CA2 for ; Sun, 5 Jun 2016 20:05:43 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id D84EE304048 for ; Sun, 5 Jun 2016 18:05:39 -0700 (PDT) X-ASG-Debug-ID: 1465175134-04bdf05ad4b7ed80001-NocioJ Received: from kyled.com ([180.159.153.170]) by cuda.sgi.com with SMTP id CWaES77e6MsAwbEH for ; Sun, 05 Jun 2016 18:05:34 -0700 (PDT) X-Barracuda-Envelope-From: simon12@kyled.com X-Barracuda-Effective-Source-IP: UNKNOWN[180.159.153.170] X-Barracuda-Apparent-Source-IP: 180.159.153.170 Received: from lenovo-PC[127.0.0.1] by LENOVO-PC[127.0.0.1] (SMTPD32); Fri, 3 Jun 2016 11:58:45 +0800 From: "info@kygled.com" Subject: KY LED Co from Shanghai To: xfs@oss.sgi.com X-ASG-Orig-Subj: KY LED Co from Shanghai MIME-Version: 1.0 Sender: simon12@kyled.com Reply-To: info@kygled.com Date: Fri, 3 Jun 2016 11:58:45 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline X-Barracuda-Connect: UNKNOWN[180.159.153.170] X-Barracuda-Start-Time: 1465175134 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2232 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.74 X-Barracuda-Spam-Status: No, SCORE=0.74 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, HTML_MESSAGE, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30199 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160606010539.13685A420A0@cuda.sgi.com> PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVU Ri04IiBodHRwLWVxdWl2PWNvbnRlbnQtdHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCA5LjAwLjgxMTIuMTY2ODQiPjwvSEVBRD4NCjxCT0RZPg0KPERJVj48Rk9OVCBj b2xvcj0jMDA4MDAwIHNpemU9NCBmYWNlPUFyaWFsPkRlYXIgTWFuYWdlciw8L0ZPTlQ+PC9ESVY+ DQo8RElWPjxGT05UIGNvbG9yPSMwMDgwMDAgc2l6ZT00IGZhY2U9QXJpYWw+PC9GT05UPiZuYnNw OzwvRElWPg0KPERJVj48Rk9OVCBjb2xvcj0jMDA4MDAwIHNpemU9NCBmYWNlPUFyaWFsPjwvRk9O VD48L0RJVj4NCjxESVY+PEZPTlQgY29sb3I9IzAwODAwMCBzaXplPTQgZmFjZT1BcmlhbD4mbmJz cDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsgDQpXZSBhcmUgcHJvZmVzc2lvbmFsIFQ4 IC8gVDUgTEVEIHR1YmUgc3VwcGxpZXIgaW4gU2hhbmdoYWksIHdpdGggQ0UsIFVMLCBETEMgDQpj ZXJ0aWZpY2F0ZXMsIDEwMC0xNDBsbS9XLCBBQzg1LTI2NVYgaW5wdXQsIDN5ZWFycyB3YXJyYW50 eSwgVDggMThXOiANCiQzLjg4L3BjLjwvRk9OVD48L0RJVj4NCjxESVY+PEZPTlQgY29sb3I9IzAw ODAwMCBzaXplPTQgZmFjZT1BcmlhbD48L0ZPTlQ+Jm5ic3A7PC9ESVY+DQo8RElWPjxGT05UIGNv bG9yPSMwMDgwMDAgc2l6ZT00IGZhY2U9QXJpYWw+PC9GT05UPjwvRElWPg0KPERJVj48Rk9OVCBj b2xvcj0jMDA4MDAwIHNpemU9NCBmYWNlPUFyaWFsPiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZu YnNwOyBBbnkgDQppbnRlcmVzdCwgcGxlYXNlIGNvbnRhY3Qgd2l0aCBubyBoZXNpdGF0ZSwgdGhh bmtzLjwvRk9OVD48L0RJVj4NCjxESVY+PEZPTlQgY29sb3I9IzAwODAwMCBzaXplPTQgZmFjZT1B cmlhbD48L0ZPTlQ+Jm5ic3A7PC9ESVY+DQo8RElWPg0KPFA+PEZPTlQgZmFjZT1BcmlhbD48Rk9O VCBjb2xvcj0jMDA4MDAwPjxTUEFOIGxhbmc9RU4tVVMgYXItc2E9IiIgemgtY249IiIgDQplbi11 cz0iIiByb21hbj0iIiBuZXc9IiI+QmVzdC53aXNoZXM8L1NQQU4+IDwvRk9OVD48L0ZPTlQ+PC9Q Pg0KPFA+PFNQQU4gc3R5bGU9IkZPTlQtRkFNSUxZOiAmIzM5O0FyaWFsJiMzOTssJiMzOTtzYW5z LXNlcmlmJiMzOTsiIGxhbmc9RU4tVVM+PEZPTlQgDQpjb2xvcj0jMDA4MDAwPllvdXJzLCBzaW5j ZXJlbHk8L0ZPTlQ+PC9TUEFOPjwvUD4NCjxQPjxTUEFOIHN0eWxlPSJGT05ULUZBTUlMWTogJiMz OTtBcmlhbCYjMzk7LCYjMzk7c2Fucy1zZXJpZiYjMzk7IiBsYW5nPUVOLVVTPjxGT05UIA0KY29s b3I9IzAwODAwMD5TaW1vbiA8L0ZPTlQ+PC9TUEFOPjwvUD4NCjxQPjxTUEFOIHN0eWxlPSJGT05U LUZBTUlMWTogJiMzOTtBcmlhbCYjMzk7LCYjMzk7c2Fucy1zZXJpZiYjMzk7IiBsYW5nPUVOLVVT PjxGT05UIA0KY29sb3I9IzAwODAwMD5LaW5neW91bmcgQ288L0ZPTlQ+PC9TUEFOPjwvUD4NCjxQ PjxGT05UIGNvbG9yPSMwMDgwMDA+PFNQQU4gc3R5bGU9IkZPTlQtRkFNSUxZOiAmIzM5O0FyaWFs JiMzOTssJiMzOTtzYW5zLXNlcmlmJiMzOTsiIA0KbGFuZz1FTi1VUz5NLlAgKzg2IDEzNjAxODc2 OTMxPEJSPkZheDogKzg2IDIxIDMzODI4NTIxPEJSPkVtYWlsOiA8L1NQQU4+PFNQQU4gDQpsYW5n PUVOLVVTPjxBIGhyZWY9Im1haWx0bzppbmZvQGt5Z2xlZC5jb20iIHRhcmdldD1fYmxhbms+PFNQ QU4gDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICYjMzk7QXJpYWwmIzM5OywmIzM5O3NhbnMtc2VyaWYm IzM5OyI+aW5mb0BreWdsZWQuY29tPC9TUEFOPjwvQT48L1NQQU4+PC9GT05UPjwvUD4NCjxQPjxT UEFOIGxhbmc9RU4tVVM+PEZPTlQgY29sb3I9IzAwODAwMCBmYWNlPUFyaWFsPldlYnNpdGU6IDwv Rk9OVD48QSANCmhyZWY9Imh0dHA6Ly93d3cua3lnbGVkLmNvbS8iPjxGT05UIGNvbG9yPSMwMDgw MDAgDQpmYWNlPUFyaWFsPnd3dy5reWdsZWQuY29tPC9GT05UPjwvQT48L1NQQU4+PC9QPg0KPFA+ PFNQQU4gbGFuZz1FTi1VUz48Rk9OVCBjb2xvcj0jMDA4MDAwIGZhY2U9QXJpYWw+QWRkcmVzczog Tm8uIDMzMyBKaW5nYW5nIFJvYWQgDQpKaW5xaWFvIEluZHVzdHJ5IFBhcmssIFNoYW5naGFpIDIw MTIwNiBDaGluYSA8L0ZPTlQ+PC9TUEFOPjwvUD48L0RJVj4NCjxESVY+PC9ESVY+PC9CT0RZPjwv SFRNTD4NCg0K From malin.broman@lund.se Sun Jun 5 22:15:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,LOTS_OF_MONEY, T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 95D2D7CA0 for ; Sun, 5 Jun 2016 22:15:36 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 599898F8040 for ; Sun, 5 Jun 2016 20:15:36 -0700 (PDT) X-ASG-Debug-ID: 1465182929-04cb6c2dbcb62d80001-NocioJ Received: from emea01-am1-obe.outbound.protection.outlook.com (mail-am1on0059.outbound.protection.outlook.com [157.56.112.59]) by cuda.sgi.com with ESMTP id XXtycRh176UqXTqd (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for ; Sun, 05 Jun 2016 20:15:30 -0700 (PDT) X-Barracuda-Envelope-From: malin.broman@lund.se X-Barracuda-Effective-Source-IP: mail-am1on0059.outbound.protection.outlook.com[157.56.112.59] X-Barracuda-Apparent-Source-IP: 157.56.112.59 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=lund4.onmicrosoft.com; s=selector1-lund-se; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=C/2KYPnShFu/8aH5cEhj1sYn8MWlfXrTp6GbWyJga8I=; b=OdGqY1wVBUbOzVVjAvxo5n3xsUQAbA2rPiUEVj81cFCjYcyg7KLRw7Mpnu9Nrw5kRNQrb/FedZMsBxS72qoBwkGV7AJx7kCGSMObOZ7v+VkUBA8qiQLz479SDOnUvNrXbwRkufYViLFZn/bnTwGPCXosVsf0vZtymFVLeqnRLm8= Received: from AM4PR01CA0050.eurprd01.prod.exchangelabs.com (10.164.74.18) by HE1PR0101MB2089.eurprd01.prod.exchangelabs.com (10.167.186.17) with Microsoft SMTP Server (TLS) id 15.1.511.8; Mon, 6 Jun 2016 03:15:26 +0000 Received: from DB3FFO11FD009.protection.gbl (2a01:111:f400:7e04::170) by AM4PR01CA0050.outlook.office365.com (2a01:111:e400:59dc::18) with Microsoft SMTP Server (TLS) id 15.1.511.8 via Frontend Transport; Mon, 6 Jun 2016 03:15:26 +0000 Authentication-Results: spf=pass (sender IP is 193.12.172.10) smtp.mailfrom=lund.se; hotmail.com; dkim=none (message not signed) header.d=none;hotmail.com; dmarc=bestguesspass action=none header.from=lund.se; Received-SPF: Pass (protection.outlook.com: domain of lund.se designates 193.12.172.10 as permitted sender) receiver=protection.outlook.com; client-ip=193.12.172.10; helo=mail.lund.se; Received: from mail.lund.se (193.12.172.10) by DB3FFO11FD009.mail.protection.outlook.com (10.47.216.165) with Microsoft SMTP Server (TLS) id 15.1.497.8 via Frontend Transport; Mon, 6 Jun 2016 03:15:25 +0000 Received: from S000094.intra.lund.se ([fe80::8c3:b9f8:17ec:4d75]) by S000044.intra.lund.se ([fe80::c198:f85c:7747:899a%11]) with mapi id 14.03.0294.000; Mon, 6 Jun 2016 05:14:11 +0200 From: Malin Broman To: Malin Broman Subject: RE: FYI Thread-Topic: FYI X-ASG-Orig-Subj: RE: FYI Thread-Index: AdG/hXpB4Mh/ZPWZQCS3zSlwIrABvwAGmVcc Date: Mon, 6 Jun 2016 03:14:11 +0000 Message-ID: <17988D28739B7F4EBD2001FC6D9BF797116D23CF@S000094.intra.lund.se> References: <17988D28739B7F4EBD2001FC6D9BF797116D0330@S000094.intra.lund.se> In-Reply-To: <17988D28739B7F4EBD2001FC6D9BF797116D0330@S000094.intra.lund.se> Accept-Language: en-US, sv-SE Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [172.29.0.80] Content-Type: multipart/alternative; boundary="_000_17988D28739B7F4EBD2001FC6D9BF797116D23CFS000094intralun_" MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-Forefront-Antispam-Report: CIP:193.12.172.10;IPV:NLI;CTRY:SE;EFV:NLI;SFV:NSPM;SFS:(10009020)(6009001)(2980300002)(438002)(189002)(69234005)(199003)(377454003)(9170700003)(3846002)(102836003)(11100500001)(110136002)(189998001)(107886002)(5004730100002)(6116002)(74482002)(586003)(6200100001)(5250100002)(3480700004)(2910100002)(19580405001)(19580395003)(5003600100002)(5000100001)(92566002)(8936002)(50986999)(8676002)(54356999)(3900700001)(84326002)(81166006)(8666004)(87936001)(221733001)(4001450100002)(55846006)(16236675004)(2950100001)(106466001)(86362001)(104016004)(2940100001)(6806005)(2906002)(5008740100001)(2900100001)(76176999)(2920100001)(33656002)(512934002)(7059030)(571714004);DIR:OUT;SFP:1101;SCL:1;SRVR:HE1PR0101MB2089;H:mail.lund.se;FPR:;SPF:Pass;MLV:sfv;MX:1;A:1;LANG:en; X-Microsoft-Exchange-Diagnostics: 1;DB3FFO11FD009;1:l5ANfYBZPKyaUD7WEMr8A5mSveQ1zqyjgmf/kRepdRo5XKdglfQ3ffNfxeuByYrl+s5S2bWF1miUr4Qk2A5D5DL+tgZHMKOH4ssFbb02Xru8b9TwqYgOPQAVjK5mdRLczASsH+xqISxcL7XX/i5ntl+/3YqU3IOW6sB7FEpaseA8KUqyDoBFOk6E6yVHY/bAA0thKs3lmVYId2Q2YwEjSzT3mEPK2ISZ9kE18O0qfb2u4DqJjvwPCzngW6g3V/rw7Aqp8mTAcunzDoOFQcf7k2dH2HTpZhE405pUs0h+qAIJknC4qRmBulsMED/x8v/QzVnROGUAWZnusvJNampO5+jyEHKxGG71E84WqSXBtye8SZNJlwTW89mGsfHH1cYa0F15lLGw9pLNlMJ909W2XG+Mzfv70e45iIy58Mk1fPSng7/ZjOdJt4DzJrih7qz5MVpfTPZQMnNNEwjWVS88C+4s9O+YQ3r1wKUoeb0D5Kvy7yTc4so0b/iVSMmSAUmvTwzh7b/nSv88Ej7N/biYut1+M5jJe1FpsHvH0mzW+ec6pvq9qGNfCYWru9Sy1Yz7 X-MS-Office365-Filtering-Correlation-Id: edce0188-ec22-477c-6c00-08d38db8ce03 X-Microsoft-Exchange-Diagnostics: 1;HE1PR0101MB2089;2:IQDNrMJH0Xjkq5KtD7YHj0N1GyNBQVgYZc/MEkLFiN0hg94RA7+naptlcOASod26DoBmMMlJd8MtUsdq+0RF8Xd3twAXZGea/6uyS5AIsWDUgJYb/XdlB7GqLJijO6nDV5Kt99uSK9a6XJ6ihEs+GiKsfm/0yQNNE0PRth3D3rqs/lwvhnamRcfjwxJrxECg;3:vGKBKzonFCke4ESuWF74rEzs31/UG/D0pwgoxXpfD9Cg2OFv2RgZP2Pv+3sCWLlfpJA7TyqJDJYt1ImxY7+WgVZ0mRxcKWE2A4bqPh7lwrGi6GTSAWMYPkvAHKkzNaI+RUFd4omp8aG3+Q0Ex/qdnDTL/rshnym20FTQk2N31NxjuKtWhdVLWwyZVRUnN+DWQPGecn0mP7h0ZmK7z3HEHxomJj64XRLmTqgtvfENXk6+j03DaSuMC1o+PBf9EvtT1tL5R5QXCTmlR8XLRZeuUA== X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:(8251501002);SRVR:HE1PR0101MB2089; X-Microsoft-Exchange-Diagnostics: 1;HE1PR0101MB2089;25:rGzE5VT2ztTo8Sq8WFE9qtLASQSpqq5XMOV+Ebw+7n6fm94pgxj/LTe8mPdZ8642hsxsOyPXFFgZQfKvaRBXxD/a5k4amSH46pGzUITRRCpxBmsb50wkSIbm9ekNGYXj/BGUFk9+kd9b8lheF+plXOtZ5xOTZNDwjFCemzbiP1avaLZeTyLXjGTlw/WAyazAzZTdTdiCKCsJzATLBhd39hH+rKA4uSP5mdZ04rHOhMB4iHje1AKmz7+CViaqfXPiI8ZDowdkbtU1nE5gQw98J6gvIbTJK7WzqFpmorXJ49hFvzM2p8/of+4k70Gr1fHXF7KwMEae8s2bdXM6gwnW9OUex6muACRQCa9lsGT//vFgbx9/azlLI8rNATkg21X1tWqNdISeoGqEXfcwrBjLWFExt59CyYAl75y8E6iKQoWhXEIWJ9DxTCLl9G9bfJL/a/YPITQ+hbUWL+mfke2ZDO4ww3udWGQU/XJzsoBAnxwhlwG4h3n4SFgQcs3rAjEQ8UQrw15s9gLNNsFMe7SJZd6BcOz6aRo48SOw32faoY/+soLU195dGnOed1B8Z+fYWzNjPn9zGprYOQsFwpieTZeZygUqzl3gJnBFW7IFlzAGKjjdR7TXB3C9WS78FpfvwcRulrOD+nrW0c+Im6BaatsrrnPYh56uaIq9PIt7PvGAqJSaS1c0D1XpAILSQi9L/1zjbY0wLxmnd/xvfXfEJaQmRd9dmz55aPBBncMEhEhf5lUds/Fea3sd5LJP2911OyXsvpRN6j0TyjOijv4zFPfKEqZ+ItiHW+0DqdWsQEhIFf9zt3g+yNMXWJQhSiXFX3MfpAWz26X8TGTiJN2m3yoKzJO1oo8VC2+aKZeSvts= X-Microsoft-Exchange-Diagnostics: 1;HE1PR0101MB2089;20:s/G3i9EXFVf3wOncHXchNNCy+Qm41RRndpveGcUkeQIixRuwT/Mh+w2KVBqn/w4LESeC8s1T/7XpeFYYvIJhbLr/zlZQUYkzEaazmbhxN5x/cqcEIs/db22txrJ2MQCQ/Nh6xAKC8/fpfyuRJtT2Smcsgg0uV21oVbQGDVqLIC3i5M8e1r1tQRed3w8Kg+wJZV6nBX0AuKTF3173IF3Mbhijwd0tfbJ3/RJtddf7l9tvbe4k9DnLAJcBHfVOhTbGLMzpDacbFbHknWwmah293i9bEAyG70ff0vdlof7uOlLoh7cClaWHofgE4Z0bV1UfpCOnHOTY31O06TsTJfTgpaT5OouZ0Y4Q7PBEBtj+6204VrsRVVtY1+Fw/CXH50NQHWZTO7EHD5wQ3XqA1dwPNPC5YOgjSzCMp4xX2re4iGQ8ZY2tWzzFjj3Z7q9URhhfv8OIy37m+aEkr/beZ7yvf2zuzETotW3lJLaeed0yvAsHPVsSOMJ6p8WhSMMQTMX2 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(189930954265078); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040130)(601004)(2401047)(13017025)(13024025)(5005006)(8121501046)(13015025)(13018025)(13023025)(10201501046)(3002001)(6041072)(6043046);SRVR:HE1PR0101MB2089;BCL:0;PCL:0;RULEID:;SRVR:HE1PR0101MB2089; X-Microsoft-Exchange-Diagnostics: 1;HE1PR0101MB2089;4:YhUg20uE6+EskxgOMnSipO/tPEaQMMNdQBeixlhkmloCU6fPn3NROvAx5roUFrhuf/YU+tXp1ARQgmLVhllttoqvfQSNNu2lCbFjW6V0Oo54spo54LE+bdO07gDlDhO6HigpQwRDOs0DYq3MRiKD4AcJ0P8ilQZJDGOiiKvl9lSCR+hsYNHCYVHLUTrGQXf1nDg4NJWEt2BfbvOv7UbE08leJLiciOhbDSINtSwCM+tA1lpsce139efYrmNlDXxKeKdHKIocABOtYafMl/tsZ7vAcX0mlu/JssntcTldduQdukm4jiEkGNnrSzTI1pyAAr+URSmBq3Xkhd6Pu9L/92/p0yJHq39WdESRXcRoyZSORDxC2fTrMugPmJJOd/EMDwIDUC5FEPc9ATVo6JjbMolhTIS3nDbhrZdzW9vZCnTz1HysfVYO2+Ksm76YM1LhtPE7U5Bn4RQGtiH90k895oV9TX1zGULNQzGpYiQLYWCWKC6n7Gk2RdZ3EkgNYyWcOxbklGuzloEKkamDJoC8SZJYghZLBwon2/6RXWm9FSI+zOqUuooUmrbKEIWg7L+B X-Forefront-PRVS: 096507C068 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1;HE1PR0101MB2089;23:QXf95bwMO332QHTLz3qNxzov18vqSp0qRKsX6j3?= =?us-ascii?Q?EpMNVXxjwy9cbc51knFIHMxAwUWYDQeEmcU7nT5zyOBlyPiHXVhjkfoMmeJB?= =?us-ascii?Q?2tniHf3NM1IPG08dt0vcZ+cKYHe6VpFq0q6qsA0DNIkHiSiWV9pAMaVqMCIN?= =?us-ascii?Q?uRY/mAMxkdM8774PKjYx8yzQ1zfrsdjOSqrtU/MxZ+01uDKauWfSOgflPfyf?= =?us-ascii?Q?JzQB5GAihFsl2uOzqXZcPyIkmh5A5Kf3j8K327oUovW/WC2Jm2wfZcumDMCJ?= =?us-ascii?Q?SmJOFf5007QqXuKB1cZIE3mLAIhERRhxn6lUkGsqGHxBH7DtWlmlKgJxqgZK?= =?us-ascii?Q?LtdBLETwL7QsAeRan/aEPFRDxCK44fVjiAL5b1gUoNxbodEd79uyhqct8yH3?= =?us-ascii?Q?CTJbzb7wcvpVQsBfoQ+TcA+JPLo+QJj1KCkHd710TdD7UYrtNEHLiNauwk0H?= =?us-ascii?Q?wCcHyCB8vn1SXXPt+1mTeYz6mkMm1dxoMFnbAxZ41KDOxTpF8sTST5g1zgRF?= =?us-ascii?Q?7gynkKQtZzoLqnQDnUnlLExrytGMp5vKj2nsStUSrluItJEYHP2EnQPxAtTW?= =?us-ascii?Q?RrAGhZDfp8jzrq8YwTAt8qGMMvAZMHs0ye+oOT4z6aiE7UEjKTpC7d9Bt56R?= =?us-ascii?Q?7jEWgoCq0H8j5isagF4bV776UPaOTRf+dgSXimfuC5yRJSvyaT3o0/W2OdLk?= =?us-ascii?Q?G8hQ6JsQEYmo0E14L3iYkxwDXDzGXPE9Lo7zGcFYNB0ciZ8Mn4c/tZdE9hJr?= =?us-ascii?Q?UfGDrItCEQUzSdPtSJnqKnZ1+PpvGOdFMyp2qSYwmHfoXNq8b97/hZMwkKvb?= =?us-ascii?Q?84EydKYJTga1HRCl6yQ4f36MVOaa5ZccE+mZVosuBvpMgPT7kWuk2oZZdx/M?= =?us-ascii?Q?Pwakpyr7I1gzIFqVH4043jJg/GCno6elCLMq/Bvike5yjujmxiQvbumPirR9?= =?us-ascii?Q?Lz3y0pQ/Mw1oVV0RQy17pVMoTN2nrGwQArfwqtHomiOqTmKin20EE3EAjHyO?= =?us-ascii?Q?IK5r++UU1Dwq9xbRrV8UwS80spBgSQcTB0qduosYilHyX61ib6T7lNM2Cvka?= =?us-ascii?Q?DQh3r0zA5tKk77E2MKkEU8sos7NIMZ/g0+7QSUKCJOUhBaPTOFUjRx/lfQBH?= =?us-ascii?Q?BnoHOAtuH7orefp8XqsMHGiN1msCQrty3iPTqn/uMO/JTsnsbnqgLknKPWNM?= =?us-ascii?Q?tpFHYjvkAKPsiPyExwSyUUsJLqM9t5z4+bzFOLM12D2DxZWrcEZNGE6o1+tR?= =?us-ascii?Q?cTyan3nEgVQ98Skwu33p5rZLMzEmDYyOIPStUmrb2DcN2pFV46BOAIYFN+7E?= =?us-ascii?Q?WlRYhtUqMrsUsHAiCuzSu7oHTbe3ZCY2WqiNCt6gfdB4tJF5EIVfwR+FlbYX?= =?us-ascii?Q?n5LzGwIPRGW2ROC7VKJDTPspX0NqkkxCA9BUJOeSWOlQJmjdu0FYfx9eoZn6?= =?us-ascii?Q?sJPRUYtmgdA=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;HE1PR0101MB2089;5:u83STnX+7ukMioxw12xTu10IYs+YpDuRmYTo2h69hunp0t2oe4vzoGMvIiLNjJim3uOr2csxHIEQDyuRaw3fgvQFvjnjJDUwUaRNtkf9NTcdPo3b/zi2uvUUuJpkoKweBoo2j6j0EZ4RKnhvqz/cjA==;24:AT3TNAIUH4oEbZMYMnDn/VPMgfN0KHDP3182fnhbdFCh/nZIFrOtgcgaUV09M6/lGtkXf5JY7OvURBTsx0rNc0i5egcyf/qnQrilbuqCeEM=;7:Co2MLRc5qnHrDUDSLk+INQlxEzxwjMjYwTieffY29mK3l2VjpCZ350CD78mbnruCadfs5ye6VB8Bdhx/1D629SHw6kFoqG7wYTSFxQaEz2T7/soB4YGXZaTxBC/ZWS+zcQDCKyxwXYfESj/mREVb5QoJk05OXBUINDysRpf0yfN0qEeGZdJGQrpzyl1IlMaFzMu1HihF5cdgilAVFJyuEnVwlJgudRyD8Oc6mCIe7Ak= SpamDiagnosticOutput: 1:23 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: lund.se X-MS-Exchange-CrossTenant-OriginalArrivalTime: 06 Jun 2016 03:15:25.2649 (UTC) X-MS-Exchange-CrossTenant-Id: cd1dd63f-57dc-4fa4-aa36-d14680fe70d3 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=cd1dd63f-57dc-4fa4-aa36-d14680fe70d3;Ip=[193.12.172.10];Helo=[mail.lund.se] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: HE1PR0101MB2089 X-Barracuda-Connect: mail-am1on0059.outbound.protection.outlook.com[157.56.112.59] X-Barracuda-Start-Time: 1465182929 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1047 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.52 X-Barracuda-Spam-Status: No, SCORE=0.52 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_ADDR_MATCH, DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE, MAILTO_TO_SPAM_ADDR, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30201 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 MAILTO_TO_SPAM_ADDR URI: Includes a link to a likely spammer email 0.00 HTML_MESSAGE BODY: HTML included in message 0.50 BSF_SC0_SA_TO_FROM_ADDR_MATCH Sender Address Matches Recipient Address --_000_17988D28739B7F4EBD2001FC6D9BF797116D23CFS000094intralun_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable ________________________________ From: Malin Broman Sent: Monday, June 06, 2016 1:53 AM To: mal0001@utb.lund.se Subject: FYI $2m donated to you, reply to; lbettencourt97@outlook.com for details. --_000_17988D28739B7F4EBD2001FC6D9BF797116D23CFS000094intralun_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable

From: Malin Broman
Sent: Monday, June 06, 2016 1:53 AM
To: mal0001@utb.lund.se
Subject: FYI

$2m donated to you, reply to; lbettencourt97@outlook.com for details.<= /div>
--_000_17988D28739B7F4EBD2001FC6D9BF797116D23CFS000094intralun_-- From hare@suse.de Mon Jun 6 01:12:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B08127CA0 for ; Mon, 6 Jun 2016 01:12:53 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6F7F3304032 for ; Sun, 5 Jun 2016 23:12:50 -0700 (PDT) X-ASG-Debug-ID: 1465193566-04cb6c2db9b66610001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id IJfbYEEeVLg6YAbn (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:12:47 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id C24B9AAAD; Mon, 6 Jun 2016 06:12:43 +0000 (UTC) Subject: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 01/45] block/fs/drivers: remove rw argument from submit_bio References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-2-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <5755145A.3070500@suse.de> Date: Mon, 6 Jun 2016 08:12:42 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-2-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465193567 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 672 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30204 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:31 PM, mchristi@redhat.com wrote: > From: Mike Christie > > This has callers of submit_bio/submit_bio_wait set the bio->bi_rw > instead of passing it in. This makes that use the same as > generic_make_request and how we set the other bio fields. > > Signed-off-by: Mike Christie > --- Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:13:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 240507CA0 for ; Mon, 6 Jun 2016 01:13:47 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 91047AC002 for ; Sun, 5 Jun 2016 23:13:43 -0700 (PDT) X-ASG-Debug-ID: 1465193620-04cbb03569b9a390001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id 8mawPwM6Uiu3VCR8 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:13:41 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 281C1AB5D; Mon, 6 Jun 2016 06:13:40 +0000 (UTC) Subject: Re: [PATCH 02/45] block: add REQ_OP definitions and helpers To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 02/45] block: add REQ_OP definitions and helpers References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-3-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551493.5050300@suse.de> Date: Mon, 6 Jun 2016 08:13:39 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-3-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465193621 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 994 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30204 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:31 PM, mchristi@redhat.com wrote: > From: Mike Christie > > The following patches separate the operation (WRITE, READ, DISCARD, > etc) from the rq_flag_bits flags. This patch adds definitions for > request/bio operations (REQ_OPs) and adds request/bio accessors to > get/set the op. > > In this patch the REQ_OPs match the REQ rq_flag_bits ones > for compat reasons while all the code is converted to use the > op accessors in the set. In the last patches the op will become a > number and the accessors and helpers in this patch will be dropped > or updated. > > Signed-off-by: Mike Christie > --- Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:14:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B893C7CA0 for ; Mon, 6 Jun 2016 01:14:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 32238AC003 for ; Sun, 5 Jun 2016 23:14:44 -0700 (PDT) X-ASG-Debug-ID: 1465193681-04cb6c2db9b666b0001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id LSv57zsAkXTQ2nYo (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:14:42 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EB62AAAAD; Mon, 6 Jun 2016 06:14:40 +0000 (UTC) Subject: Re: [PATCH 05/45] block, drivers, cgroup: use op_is_write helper instead of checking for REQ_WRITE To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 05/45] block, drivers, cgroup: use op_is_write helper instead of checking for REQ_WRITE References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-6-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <575514D0.3000609@suse.de> Date: Mon, 6 Jun 2016 08:14:40 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-6-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465193681 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 961 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30204 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:31 PM, mchristi@redhat.com wrote: > From: Mike Christie > > We currently set REQ_WRITE/WRITE for all non READ IOs > like discard, flush, writesame, etc. In the next patches where we > no longer set up the op as a bitmap, we will not be able to > detect a operation direction like writesame by testing if REQ_WRITE is > set. > > This patch converts the drivers and cgroup to use the > op_is_write helper. This should just cover the simple > cases. I did dm, md and bcache in their own patches > because they were more involved. > > Signed-off-by: Mike Christie > --- Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:15:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 526D67CA0 for ; Mon, 6 Jun 2016 01:15:53 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 24EFA304051 for ; Sun, 5 Jun 2016 23:15:52 -0700 (PDT) X-ASG-Debug-ID: 1465193750-04cb6c2dbbb66700001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id 1Nzqt31Cgp4YaIbL (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:15:51 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 0B36DAAAD; Mon, 6 Jun 2016 06:15:50 +0000 (UTC) Subject: Re: [PATCH 06/45] dm: use op_is_write instead of checking for REQ_WRITE To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 06/45] dm: use op_is_write instead of checking for REQ_WRITE References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-7-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551515.8060205@suse.de> Date: Mon, 6 Jun 2016 08:15:49 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-7-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465193751 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 888 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30204 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:31 PM, mchristi@redhat.com wrote: > From: Mike Christie > > We currently set REQ_WRITE/WRITE for all non READ IOs > like discard, flush, writesame, etc. In the next patches where we > no longer set up the op as a bitmap, we will not be able to > detect a operation direction like writesame by testing if REQ_WRITE is > set. > > This has dm use the op_is_write helper which will do the right > thing. > > Signed-off-by: Mike Christie > --- (Could probably be folded into the previous patch) Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:16:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3FB527CA0 for ; Mon, 6 Jun 2016 01:16:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id BCEE9AC003 for ; Sun, 5 Jun 2016 23:16:47 -0700 (PDT) X-ASG-Debug-ID: 1465193804-04cbb03569b9a4b0001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id BmHnG5K1UaPzAI7Q (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:16:45 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 869EBAAB6; Mon, 6 Jun 2016 06:16:44 +0000 (UTC) Subject: Re: [PATCH 07/45] bcache: use op_is_write instead of checking for REQ_WRITE To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 07/45] bcache: use op_is_write instead of checking for REQ_WRITE References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-8-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <5755154C.7030007@suse.de> Date: Mon, 6 Jun 2016 08:16:44 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-8-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465193805 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1041 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30204 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:31 PM, mchristi@redhat.com wrote: > From: Mike Christie > > We currently set REQ_WRITE/WRITE for all non READ IOs > like discard, flush, writesame, etc. In the next patches where we > no longer set up the op as a bitmap, we will not be able to > detect a operation direction like writesame by testing if REQ_WRITE is > set. > > This has bcache use the op_is_write helper which will do the right > thing. > > Signed-off-by: Mike Christie > --- > drivers/md/bcache/io.c | 2 +- > drivers/md/bcache/request.c | 6 +++--- > 2 files changed, 4 insertions(+), 4 deletions(-) > (Could probably folded together with the two previous patches) Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:20:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E48D57CA0 for ; Mon, 6 Jun 2016 01:20:20 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id A86CB30404E for ; Sun, 5 Jun 2016 23:20:20 -0700 (PDT) X-ASG-Debug-ID: 1465194017-04cbb03568b9a5b0001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id wDc2hSItEmpDyD50 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:20:18 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 12CC0AAAD; Mon, 6 Jun 2016 06:20:17 +0000 (UTC) Subject: Re: [PATCH 08/45] block, fs, mm, drivers: use bio set/get op accessors To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 08/45] block, fs, mm, drivers: use bio set/get op accessors References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-9-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551620.3070801@suse.de> Date: Mon, 6 Jun 2016 08:20:16 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-9-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465194018 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4586 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:31 PM, mchristi@redhat.com wrote: > From: Mike Christie > > This patch converts the simple bi_rw use cases in the block, > drivers, mm and fs code to set/get the bio operation using > bio_set_op_attrs/bio_op > > These should be simple one or two liner cases, so I just did them > in one patch. The next patches handle the more complicated > cases in a module per patch. > > Signed-off-by: Mike Christie > --- > > v5: > 1. Add missed crypto call. > 2. Change nfs bi_rw check to bi_op. > > block/bio.c | 13 ++++++------- > block/blk-core.c | 6 +++--- > block/blk-flush.c | 2 +- > block/blk-lib.c | 4 ++-- > block/blk-map.c | 2 +- > block/blk-merge.c | 12 ++++++------ > drivers/block/brd.c | 2 +- > drivers/block/floppy.c | 2 +- > drivers/block/pktcdvd.c | 4 ++-- > drivers/block/rsxx/dma.c | 2 +- > drivers/block/zram/zram_drv.c | 2 +- > drivers/lightnvm/rrpc.c | 6 +++--- > drivers/scsi/osd/osd_initiator.c | 8 ++++---- > drivers/staging/lustre/lustre/llite/lloop.c | 6 +++--- > fs/crypto/crypto.c | 2 +- > fs/exofs/ore.c | 2 +- > fs/ext4/page-io.c | 6 +++--- > fs/ext4/readpage.c | 2 +- > fs/jfs/jfs_logmgr.c | 4 ++-- > fs/jfs/jfs_metapage.c | 4 ++-- > fs/logfs/dev_bdev.c | 12 ++++++------ > fs/nfs/blocklayout/blocklayout.c | 4 ++-- > include/linux/bio.h | 15 ++++++++++----- > mm/page_io.c | 4 ++-- > 24 files changed, 65 insertions(+), 61 deletions(-) > [ .. ] > diff --git a/include/linux/bio.h b/include/linux/bio.h > index 09c5308..4568647 100644 > --- a/include/linux/bio.h > +++ b/include/linux/bio.h > @@ -109,18 +109,23 @@ static inline bool bio_has_data(struct bio *bio) > { > if (bio && > bio->bi_iter.bi_size && > - !(bio->bi_rw & REQ_DISCARD)) > + bio_op(bio) != REQ_OP_DISCARD) > return true; > > return false; > } > > +static inline bool bio_no_advance_iter(struct bio *bio) > +{ > + return bio_op(bio) == REQ_OP_DISCARD || bio_op(bio) == REQ_OP_WRITE_SAME; > +} > + > static inline bool bio_is_rw(struct bio *bio) > { > if (!bio_has_data(bio)) > return false; > > - if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) > + if (bio_no_advance_iter(bio)) > return false; > > return true; > @@ -228,7 +233,7 @@ static inline void bio_advance_iter(struct bio *bio, struct bvec_iter *iter, > { > iter->bi_sector += bytes >> 9; > > - if (bio->bi_rw & BIO_NO_ADVANCE_ITER_MASK) > + if (bio_no_advance_iter(bio)) > iter->bi_size -= bytes; > else > bvec_iter_advance(bio->bi_io_vec, iter, bytes); Hmm. Can't you drop 'BIO_NO_ADVANCE_ITER_MASK' after this patch? > @@ -256,10 +261,10 @@ static inline unsigned bio_segments(struct bio *bio) > * differently: > */ > > - if (bio->bi_rw & REQ_DISCARD) > + if (bio_op(bio) == REQ_OP_DISCARD) > return 1; > > - if (bio->bi_rw & REQ_WRITE_SAME) > + if (bio_op(bio) == REQ_OP_WRITE_SAME) > return 1; > > bio_for_each_segment(bv, bio, iter) > diff --git a/mm/page_io.c b/mm/page_io.c > index 5a5fd66..dcc5d37 100644 > --- a/mm/page_io.c > +++ b/mm/page_io.c > @@ -317,7 +317,7 @@ int __swap_writepage(struct page *page, struct writeback_control *wbc, > ret = -ENOMEM; > goto out; > } > - bio->bi_rw = WRITE; > + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); > if (wbc->sync_mode == WB_SYNC_ALL) > bio->bi_rw |= REQ_SYNC; > count_vm_event(PSWPOUT); > @@ -370,7 +370,7 @@ int swap_readpage(struct page *page) > ret = -ENOMEM; > goto out; > } > - bio->bi_rw = READ; > + bio_set_op_attrs(bio, REQ_OP_READ, 0); > count_vm_event(PSWPIN); > submit_bio(bio); > out: > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:21:12 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BE1057CA0 for ; Mon, 6 Jun 2016 01:21:12 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3410CAC002 for ; Sun, 5 Jun 2016 23:21:12 -0700 (PDT) X-ASG-Debug-ID: 1465194069-04cbb0356bb9a630001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id awJy0c69BXxbQtxb (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:21:10 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 91730AAAD; Mon, 6 Jun 2016 06:21:09 +0000 (UTC) Subject: Re: [PATCH 09/45] block discard: use bio set op accessor To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 09/45] block discard: use bio set op accessor References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-10-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551655.3020306@suse.de> Date: Mon, 6 Jun 2016 08:21:09 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-10-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465194070 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 811 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:31 PM, mchristi@redhat.com wrote: > From: Mike Christie > > This converts the block issue discard helper and users to use > the bio_set_op_attrs accessor and only pass in the operation flags > like REQ_SEQURE. > > Signed-off-by: Mike Christie > --- > block/blk-lib.c | 13 +++++++------ > drivers/md/dm-thin.c | 2 +- > include/linux/blkdev.h | 3 ++- > 3 files changed, 10 insertions(+), 8 deletions(-) > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:44:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6776B7CA0 for ; Mon, 6 Jun 2016 01:44:07 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 388CB8F8035 for ; Sun, 5 Jun 2016 23:44:04 -0700 (PDT) X-ASG-Debug-ID: 1465195441-04cb6c2dbbb67180001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id x00fySgq6TsV48sQ (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:44:02 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 41AAAAB5D; Mon, 6 Jun 2016 06:43:59 +0000 (UTC) Subject: Re: [PATCH 24/45] dm: use bio op accessors To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 24/45] dm: use bio op accessors References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-25-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551BA7.8080102@suse.de> Date: Mon, 6 Jun 2016 08:43:51 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-25-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465195442 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 581 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: > From: Mike Christie > > Separate the op from the rq_flag_bits and have dm > set/get the bio using bio_set_op_attrs/bio_op. > > Signed-off-by: Mike Christie > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:45:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B0C6D7CA0 for ; Mon, 6 Jun 2016 01:45:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3AC24AC004 for ; Sun, 5 Jun 2016 23:45:42 -0700 (PDT) X-ASG-Debug-ID: 1465195539-04cb6c2dbcb67230001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id KAA5aBtYm42FoVBe (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:45:40 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id D1BDFABA5; Mon, 6 Jun 2016 06:45:38 +0000 (UTC) Subject: Re: [PATCH 25/45] bcache: use bio op accessors To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 25/45] bcache: use bio op accessors References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-26-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551BF2.6060000@suse.de> Date: Mon, 6 Jun 2016 08:45:06 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-26-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465195540 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 986 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: > From: Mike Christie > > Separate the op from the rq_flag_bits and have bcache > set/get the bio using bio_set_op_attrs/bio_op. > > Signed-off-by: Mike Christie > --- > drivers/md/bcache/btree.c | 4 ++-- > drivers/md/bcache/debug.c | 4 ++-- > drivers/md/bcache/journal.c | 7 ++++--- > drivers/md/bcache/movinggc.c | 2 +- > drivers/md/bcache/request.c | 14 +++++++------- > drivers/md/bcache/super.c | 24 +++++++++++++----------- > drivers/md/bcache/writeback.c | 4 ++-- > 7 files changed, 31 insertions(+), 28 deletions(-) > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:46:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 084C87CA0 for ; Mon, 6 Jun 2016 01:46:52 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 722C7AC007 for ; Sun, 5 Jun 2016 23:46:51 -0700 (PDT) X-ASG-Debug-ID: 1465195608-04cbb0356ab9c210001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id z1GosjrLuX2wEAh1 (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:46:49 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id EB4B9AB5D; Mon, 6 Jun 2016 06:46:47 +0000 (UTC) Subject: Re: [PATCH 28/45] target: use bio op accessors To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 28/45] target: use bio op accessors References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-29-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551C57.5090507@suse.de> Date: Mon, 6 Jun 2016 08:46:47 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-29-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465195608 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2865 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: > From: Mike Christie > > Separate the op from the rq_flag_bits and have the target layer > set/get the bio using bio_set_op_attrs/bio_op. > > Signed-off-by: Mike Christie > --- > drivers/target/target_core_iblock.c | 29 ++++++++++++++--------------- > drivers/target/target_core_pscsi.c | 2 +- > 2 files changed, 15 insertions(+), 16 deletions(-) > > diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c > index c25109c..22af12f 100644 > --- a/drivers/target/target_core_iblock.c > +++ b/drivers/target/target_core_iblock.c [ .. ] > @@ -689,18 +690,15 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, > * Force writethrough using WRITE_FUA if a volatile write cache > * is not enabled, or if initiator set the Force Unit Access bit. > */ > + op = REQ_OP_WRITE; > if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { > if (cmd->se_cmd_flags & SCF_FUA) > - rw = WRITE_FUA; > + op_flags = WRITE_FUA; > else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) > - rw = WRITE_FUA; > - else > - rw = WRITE; > - } else { > - rw = WRITE; > + op_flags = WRITE_FUA; > } Wrong intendation. > } else { > - rw = READ; > + op = REQ_OP_READ; > } > > ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL); > @@ -714,7 +712,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, > return 0; > } > > - bio = iblock_get_bio(cmd, block_lba, sgl_nents, rw); > + bio = iblock_get_bio(cmd, block_lba, sgl_nents, op, op_flags); > if (!bio) > goto fail_free_ibr; > > @@ -738,7 +736,8 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, > bio_cnt = 0; > } > > - bio = iblock_get_bio(cmd, block_lba, sg_num, rw); > + bio = iblock_get_bio(cmd, block_lba, sg_num, op, > + op_flags); > if (!bio) > goto fail_put_bios; > > diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c > index de18790..81564c8 100644 > --- a/drivers/target/target_core_pscsi.c > +++ b/drivers/target/target_core_pscsi.c > @@ -922,7 +922,7 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, > goto fail; > > if (rw) > - bio->bi_rw |= REQ_WRITE; > + bio_set_op_attrs(bio, REQ_OP_WRITE, 0); > > pr_debug("PSCSI: Allocated bio: %p," > " dir: %s nr_vecs: %d\n", bio, > Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:50:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 91FCE7CA0 for ; Mon, 6 Jun 2016 01:50:23 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6036E8F8037 for ; Sun, 5 Jun 2016 23:50:23 -0700 (PDT) X-ASG-Debug-ID: 1465195819-04cb6c2db9b67450001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id IAE3R4DQ9q0IIb4u (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:50:20 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 79984AB5D; Mon, 6 Jun 2016 06:50:19 +0000 (UTC) Subject: Re: [PATCH 37/45] drivers: use req op accessor To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 37/45] drivers: use req op accessor References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-38-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551D2B.1090707@suse.de> Date: Mon, 6 Jun 2016 08:50:19 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-38-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465195820 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1406 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: > From: Mike Christie > > The req operation REQ_OP is separated from the rq_flag_bits > definition. This converts the block layer drivers to > use req_op to get the op from the request struct. > > Signed-off-by: Mike Christie > --- > drivers/block/loop.c | 6 +++--- > drivers/block/mtip32xx/mtip32xx.c | 2 +- > drivers/block/nbd.c | 2 +- > drivers/block/rbd.c | 4 ++-- > drivers/block/xen-blkfront.c | 8 +++++--- > drivers/ide/ide-floppy.c | 2 +- > drivers/md/dm.c | 2 +- > drivers/mmc/card/block.c | 7 +++---- > drivers/mmc/card/queue.c | 6 ++---- > drivers/mmc/card/queue.h | 5 ++++- > drivers/mtd/mtd_blkdevs.c | 2 +- > drivers/nvme/host/core.c | 2 +- > drivers/nvme/host/nvme.h | 4 ++-- > drivers/scsi/sd.c | 25 ++++++++++++++++--------- > 14 files changed, 43 insertions(+), 34 deletions(-) > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:51:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BFF777CA0 for ; Mon, 6 Jun 2016 01:51:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 824FF8F8040 for ; Sun, 5 Jun 2016 23:51:05 -0700 (PDT) X-ASG-Debug-ID: 1465195862-04bdf05ad4b86360001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id mHmnppTtNnNC4DTW (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:51:03 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 3BE25AC76; Mon, 6 Jun 2016 06:51:02 +0000 (UTC) Subject: Re: [PATCH 40/45] block: move bio io prio to a new field To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 40/45] block: move bio io prio to a new field References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-41-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551D55.8070200@suse.de> Date: Mon, 6 Jun 2016 08:51:01 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-41-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465195863 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2381 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: > From: Mike Christie > > In the next patch, we move drop the compat code and make > the op a separate value that is hidden in bi_rw. To give > the op and rq bits flags room to grow this moves prio to > its own field. > > Signed-off-by: Mike Christie > --- > include/linux/bio.h | 14 ++------------ > include/linux/blk_types.h | 5 ++--- > 2 files changed, 4 insertions(+), 15 deletions(-) > > diff --git a/include/linux/bio.h b/include/linux/bio.h > index 4568647..35108c2 100644 > --- a/include/linux/bio.h > +++ b/include/linux/bio.h > @@ -47,18 +47,8 @@ > #define bio_op(bio) (op_from_rq_bits((bio)->bi_rw)) > #define bio_set_op_attrs(bio, op, flags) ((bio)->bi_rw |= (op | flags)) > > -/* > - * upper 16 bits of bi_rw define the io priority of this bio > - */ > -#define BIO_PRIO_SHIFT (8 * sizeof(unsigned long) - IOPRIO_BITS) > -#define bio_prio(bio) ((bio)->bi_rw >> BIO_PRIO_SHIFT) > -#define bio_prio_valid(bio) ioprio_valid(bio_prio(bio)) > - > -#define bio_set_prio(bio, prio) do { \ > - WARN_ON(prio >= (1 << IOPRIO_BITS)); \ > - (bio)->bi_rw &= ((1UL << BIO_PRIO_SHIFT) - 1); \ > - (bio)->bi_rw |= ((unsigned long) (prio) << BIO_PRIO_SHIFT); \ > -} while (0) > +#define bio_prio(bio) (bio)->bi_ioprio > +#define bio_set_prio(bio, prio) ((bio)->bi_ioprio = prio) > > /* > * various member access, note that bio_data should of course not be used > diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h > index 6e60baa..2738413 100644 > --- a/include/linux/blk_types.h > +++ b/include/linux/blk_types.h > @@ -48,9 +48,8 @@ struct bio { > struct block_device *bi_bdev; > unsigned int bi_flags; /* status, command, etc */ > int bi_error; > - unsigned long bi_rw; /* bottom bits READ/WRITE, > - * top bits priority > - */ > + unsigned long bi_rw; /* READ/WRITE */ > + unsigned short bi_ioprio; > > struct bvec_iter bi_iter; > > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:51:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C2C1B7CA0 for ; Mon, 6 Jun 2016 01:51:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3C7EEAC004 for ; Sun, 5 Jun 2016 23:51:44 -0700 (PDT) X-ASG-Debug-ID: 1465195901-04cb6c2dbbb674c0001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id JNxV2IEKCJT0ZZnQ (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:51:42 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 02516AB5D; Mon, 6 Jun 2016 06:51:41 +0000 (UTC) Subject: Re: [PATCH 41/45] block, drivers, fs: shrink bi_rw from long to int To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 41/45] block, drivers, fs: shrink bi_rw from long to int References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-42-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551D7C.8000004@suse.de> Date: Mon, 6 Jun 2016 08:51:40 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-42-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465195901 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 860 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: > From: Mike Christie > > We don't need bi_rw to be so large on 64 bit archs, so > reduce it to unsigned int. > > Signed-off-by: Mike Christie > --- > block/blk-core.c | 2 +- > drivers/md/dm-flakey.c | 2 +- > drivers/md/raid5.c | 6 +++--- > fs/btrfs/check-integrity.c | 4 ++-- > fs/btrfs/inode.c | 2 +- > include/linux/blk_types.h | 2 +- > 6 files changed, 9 insertions(+), 9 deletions(-) > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From hare@suse.de Mon Jun 6 01:53:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 875A67CA0 for ; Mon, 6 Jun 2016 01:53:07 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4970C8F8037 for ; Sun, 5 Jun 2016 23:53:07 -0700 (PDT) X-ASG-Debug-ID: 1465195984-04cb6c2dbab67540001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id W4n0Kr2VM9HeGdrM (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Sun, 05 Jun 2016 23:53:05 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 72651AB5D; Mon, 6 Jun 2016 06:53:04 +0000 (UTC) Subject: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code To: mchristi@redhat.com, linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 42/45] block, fs, drivers: remove REQ_OP compat defs and related code References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-43-git-send-email-mchristi@redhat.com> From: Hannes Reinecke Message-ID: <57551DD0.9090703@suse.de> Date: Mon, 6 Jun 2016 08:53:04 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <1465155145-10812-43-git-send-email-mchristi@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465195985 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1245 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30205 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: > From: Mike Christie > > This patch drops the compat definition of req_op where it matches > the rq_flag_bits definitions, and drops the related old and compat > code that allowed users to set either the op or flags for the operation. > > We also then store the operation in the bi_rw/cmd_flags field similar > to how we used to store the bio ioprio where it sat in the upper bits > of the field. > > Signed-off-by: Mike Christie > --- > drivers/scsi/sd.c | 2 +- > include/linux/bio.h | 3 --- > include/linux/blk_types.h | 52 +++++++++++++++++---------------------------- > include/linux/blkdev.h | 14 ++++++++---- > include/linux/fs.h | 37 +++++++++++++------------------- > include/trace/events/f2fs.h | 1 - > 6 files changed, 46 insertions(+), 63 deletions(-) > Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke Teamlead Storage & Networking hare@suse.de +49 911 74053 688 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: F. Imendrffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton HRB 21284 (AG Nrnberg) From jtulak@redhat.com Mon Jun 6 02:43:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B0D3F7CA0 for ; Mon, 6 Jun 2016 02:43:26 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 72E12304043 for ; Mon, 6 Jun 2016 00:43:23 -0700 (PDT) X-ASG-Debug-ID: 1465198997-04cbb03568b9efe0001-NocioJ Received: from mail-it0-f53.google.com (mail-it0-f53.google.com [209.85.214.53]) by cuda.sgi.com with ESMTP id ofdrrPjkuxdspFnm (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 06 Jun 2016 00:43:18 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mail-it0-f53.google.com[209.85.214.53] X-Barracuda-Apparent-Source-IP: 209.85.214.53 Received: by mail-it0-f53.google.com with SMTP id z189so36070353itg.0 for ; Mon, 06 Jun 2016 00:43:18 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=c+5MD1Og7ICC7/1cbRMhf2xAAy7gj7ewMWdpLZATrHY=; b=l0NjzuaQrzjwQaHFZT9/VyLY+987yd/YP3Dqv00om80yY9EulGNi8LBG1NRR0kUDyP cWpk3w8Px6uFZLzhS4xMhAEb7kPov/6P+5MQdXbe4DsuXHDimLAhKG8+pqcSIYuvzMt+ 3SOvrlTXYxhrv63OuZx5D+Y4Y4uAmetYjti91K6KJ9eFQSqsuape/JJn5nEIVtu7BHVx Z8XbO7slqWP7AGn2P6HrMs/jiBIFzc0S6WkWmEHHo78zO/4aguyypY5hLJQ8npU1oDQ7 2ZhELklhz4UROpv+Gr1PWVRYeKzNOo4H9j5LhqoDlBoD0cLP2HLiofpiX8XZj1Cf6IY3 VpQQ== X-Gm-Message-State: ALyK8tJHw3GImdOPsioII4K0Ot4VdhtoJxiq2RoVGsziW2FymAtUoy7wn4Blgna1qnrxOE9O8c2mZVFlXX+LyLE6 X-Received: by 10.36.95.207 with SMTP id r198mr8620633itb.49.1465198997713; Mon, 06 Jun 2016 00:43:17 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.72.70 with HTTP; Mon, 6 Jun 2016 00:42:58 -0700 (PDT) In-Reply-To: <20160604003259.GV26977@dastard> References: <1461231593-31294-1-git-send-email-jtulak@redhat.com> <20160510061054.GI26977@dastard> <20160603005324.GS12670@dastard> <20160604003259.GV26977@dastard> From: Jan Tulak Date: Mon, 6 Jun 2016 09:42:58 +0200 Message-ID: Subject: Re: [PATCH 00/19 v2] mkfs cleaning To: Dave Chinner X-ASG-Orig-Subj: Re: [PATCH 00/19 v2] mkfs cleaning Cc: xfs-oss , Eric Sandeen Content-Type: multipart/alternative; boundary=001a1144b7d0c8cb1d05349739df X-Barracuda-Connect: mail-it0-f53.google.com[209.85.214.53] X-Barracuda-Start-Time: 1465198998 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6005 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30206 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message --001a1144b7d0c8cb1d05349739df Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Sat, Jun 4, 2016 at 2:32 AM, Dave Chinner wrote: > On Fri, Jun 03, 2016 at 02:09:19PM +0200, Jan Tulak wrote: > > [ > > =E2=80=8Bsnip all, another issue, unrelated to the lsunit one]=E2=80=8B > > > > > > > =E2=80=8BI realised one small glitch with conflicts watching in the cod= e in > > combination with flags. It is not regression, I think, because b=E2=80= =8Before > now, > > it was not possible to do something like -l internal=3D0,logdev=3Dsomet= hing, > > but now it should be possible. > > I think that overly complicates things. My original intent for this > work was to simplify the interface and code, not make it more > elaborate to support configurations that are theoretically possible > but completely redundant. > > i.e. '-l internal=3D0,logdev=3Dsomething' is identical in function to > '-l logdev=3Dsomething', so there is no need to specify internal=3D0. > AFAICT, therxp eis never a need to specify '-l internal=3D[0|1]' > because if '-l logdev=3D' is specified, it implies an external > log is being configured, and in every other case the log is > internal. > > > The code checks only whether an option was seen, not its value, so it > > does't know that we are in fact disabling something. I see two ways how > to > > do solve it. One is a custom conflict solving for these cases, putting > some > > if (flag1 && option2) somewhere once every argument and option is parse= d. > > But this goes against what the patchset did and moves it again out of t= he > > option table... > > > > The other way is to make a special case for flags in the > conflicts-handling > > code. Basically, I would extend the structure with something like: > > > > { .index =3D L_INTERNAL, > > .conflicts =3D { L_FILE, > > L_DEV, > > LAST_CONFLICT }, > > .conflicts_ignore_on_false=3Dtrue, // new item, shorter name to be fo= und > > What happens when you have two conflicts, on which you want to > ignore on false, the other you want to ignore on true? And where do > you draw the line? L_SU vs L_SUNIT conflict and throw an error only > when the values differ? > > =E2=80=8BYeah, that's true... let's call it feature then. Cheers, Jan=E2=80=8B --=20 Jan Tulak jtulak@redhat.com / jan@tulak.me --001a1144b7d0c8cb1d05349739df Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
On Sat, Ju= n 4, 2016 at 2:32 AM, Dave Chinner <david@fromorbit.com> wrote:
On Fri, = Jun 03, 2016 at 02:09:19PM +0200, Jan Tulak wrote:
> [
> =E2=80=8Bsnip all, another issue, unrelated to the lsunit one]=E2=80= =8B
>
> >
> =E2=80=8BI realised one small glitch with conflicts watching in the co= de in
> combination with flags. It is not regression, I think, because b=E2=80= =8Before now,
> it was not possible to do something like -l internal=3D0,logdev=3Dsome= thing,
> but now it should be possible.

I think that overly complicates things. My original intent for this<= br> work was to simplify the interface and code, not make it more
elaborate to support configurations that are theoretically possible
but completely redundant.

i.e. '-l internal=3D0,logdev=3Dsomething' is identical in function = to
'-l logdev=3Dsomething', so there is no need to specify internal=3D= 0.
AFAICT, therxp eis never a need to specify '-l internal=3D[0|1]' because if '-l logdev=3D<foo>' is specified, it implies an ex= ternal
log is being configured, and in every other case the log is
internal.

> The code checks only whether an option was seen, not its value, so it<= br> > does't know that we are in fact disabling something. I see two way= s how to
> do solve it. One is a custom conflict solving for these cases, putting= some
> if (flag1 && option2) somewhere once every argument and option= is parsed.
> But this goes against what the patchset did and moves it again out of = the
> option table...
>
> The other way is to make a special case for flags in the conflicts-han= dling
> code. Basically, I would extend the structure with something like:
>
> { .index =3D L_INTERNAL,
>=C2=A0 =C2=A0.conflicts =3D { L_FILE,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0L_DEV,
>=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0LAST_CONFLICT },
>=C2=A0 =C2=A0.conflicts_ignore_on_false=3Dtrue, // new item, shorter na= me to be found

What happens when you have two conflicts, on which you want to
ignore on false, the other you want to ignore on true?=C2=A0 And where do you draw the line? L_SU vs L_SUNIT conflict and throw an error only
when the values differ?


=E2=80=8BYeah,= that's true... let's call it feature then.

Cheers,
<= div class=3D"gmail_default" style=3D"font-family:arial,helvetica,sans-serif= ;display:inline">Jan=E2=80=8B
=C2=A0

--
=
--001a1144b7d0c8cb1d05349739df-- From jtulak@redhat.com Mon Jun 6 02:55:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0D50D7CA0 for ; Mon, 6 Jun 2016 02:55:35 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id C21FA8F8037 for ; Mon, 6 Jun 2016 00:55:34 -0700 (PDT) X-ASG-Debug-ID: 1465199733-04bdf05ad7b88520001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id LbdGUBGvVpXw4hXU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 00:55:33 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 66D89C05B1DD for ; Mon, 6 Jun 2016 07:55:33 +0000 (UTC) Received: from jtulak.brq.redhat.com (jtulak.brq.redhat.com [10.34.26.85]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u567tWiH027819; Mon, 6 Jun 2016 03:55:32 -0400 From: Jan Tulak To: xfs@oss.sgi.com Cc: Jan Tulak Subject: [PATCH] mkfs: fix -l su minval Date: Mon, 6 Jun 2016 09:55:29 +0200 X-ASG-Orig-Subj: [PATCH] mkfs: fix -l su minval Message-Id: <1465199729-8622-1-git-send-email-jtulak@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 06 Jun 2016 07:55:33 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465199733 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1092 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 -l su should be in range BBTOB(1) <= L_SU <= XLOG_MAX_RECORD_BSIZE, because the upper limit is imposed by kernel on iclogbuf: stripe unit can't be bigger than the log buffer, but the log buffer can span multiple stripe units. L_SUNIT is changed in the same way. Signed-off-by: Jan Tulak --- mkfs/xfs_mkfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 955dcfd..ed7800f 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -462,7 +462,7 @@ struct opt_params lopts = { { .index = L_SUNIT, .conflicts = { L_SU, LAST_CONFLICT }, - .minval = BTOBB(XLOG_MIN_RECORD_BSIZE), + .minval = 1, .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE), .defaultval = SUBOPT_NEEDS_VAL, }, @@ -470,7 +470,7 @@ struct opt_params lopts = { .conflicts = { L_SUNIT, LAST_CONFLICT }, .convert = true, - .minval = XLOG_MIN_RECORD_BSIZE, + .minval = BBTOB(1), .maxval = XLOG_MAX_RECORD_BSIZE, .defaultval = SUBOPT_NEEDS_VAL, }, -- 2.5.5 From cmaiolino@redhat.com Mon Jun 6 06:23:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2B6EA7CA0 for ; Mon, 6 Jun 2016 06:23:52 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D2F858F8033 for ; Mon, 6 Jun 2016 04:23:48 -0700 (PDT) X-ASG-Debug-ID: 1465212227-04bdf05ad4b8ed60001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 77tkkcrqGr0E7cO1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 04:23:47 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2C40964080 for ; Mon, 6 Jun 2016 11:23:47 +0000 (UTC) Received: from redhat.com (vpn-57-209.rdu2.redhat.com [10.10.57.209]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u56BNhZx010157 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 6 Jun 2016 07:23:46 -0400 Date: Mon, 6 Jun 2016 13:23:42 +0200 From: Carlos Maiolino To: xfs@oss.sgi.com Subject: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-ID: <20160606112342.GB23695@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Mail-Followup-To: xfs@oss.sgi.com References: <1464877150-20457-1-git-send-email-hch@lst.de> <1464877150-20457-4-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1464877150-20457-4-git-send-email-hch@lst.de> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 06 Jun 2016 11:23:47 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465212227 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1167 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Hi hch, The patchset looks good, although I'm not quite familiar with the reflink code so, I apologize if it is a stupid question After enabling the reflink feature during mount time, I believe this will not have any problems in future mounts of this filesystem without reflink support? > index 84348af..dfa5077 100644 > --- a/fs/xfs/xfs_super.c > +++ b/fs/xfs/xfs_super.c > @@ -82,7 +82,7 @@ enum { > Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota, Opt_prjquota, > Opt_uquota, Opt_gquota, Opt_pquota, > Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce, > - Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, > + Opt_discard, Opt_nodiscard, Opt_reflink, Opt_dax, Opt_err, > }; > > static const match_table_t tokens = { > @@ -132,6 +132,7 @@ static const match_table_t tokens = { > {Opt_qnoenforce, "qnoenforce"}, /* same as uqnoenforce */ > {Opt_discard, "discard"}, /* Discard unused blocks */ > {Opt_nodiscard, "nodiscard"}, /* Do not discard unused blocks */ > + {Opt_reflink, "reflink"}, /* Do not discard unused blocks */ ^^^^ Also, I believe this comment is wrong!? Cheers -- Carlos From cmaiolino@redhat.com Mon Jun 6 06:29:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A73BF7CA0 for ; Mon, 6 Jun 2016 06:29:56 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 758448F8033 for ; Mon, 6 Jun 2016 04:29:56 -0700 (PDT) X-ASG-Debug-ID: 1465212594-04cb6c2db9b70240001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id MAg5wKPX2BGkl6OK (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 04:29:55 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C685350F4D for ; Mon, 6 Jun 2016 11:29:54 +0000 (UTC) Received: from redhat.com (vpn-57-209.rdu2.redhat.com [10.10.57.209]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u56BTpA1013375 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 6 Jun 2016 07:29:54 -0400 Date: Mon, 6 Jun 2016 13:29:50 +0200 From: Carlos Maiolino To: xfs@oss.sgi.com Subject: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-ID: <20160606112950.GC23695@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Mail-Followup-To: xfs@oss.sgi.com References: <1464877150-20457-1-git-send-email-hch@lst.de> <1464877150-20457-4-git-send-email-hch@lst.de> <20160606112342.GB23695@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160606112342.GB23695@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 06 Jun 2016 11:29:54 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465212595 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1535 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Ugh, I just realized dave and derrick had already replied, pointing issues I didn't figure out, but still I'm curious for the question I asked :) > Hi hch, > > The patchset looks good, although I'm not quite familiar with the reflink code > so, I apologize if it is a stupid question > > After enabling the reflink feature during mount time, I believe this will not > have any problems in future mounts of this filesystem without reflink support? > > > index 84348af..dfa5077 100644 > > --- a/fs/xfs/xfs_super.c > > +++ b/fs/xfs/xfs_super.c > > @@ -82,7 +82,7 @@ enum { > > Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota, Opt_prjquota, > > Opt_uquota, Opt_gquota, Opt_pquota, > > Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce, > > - Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, > > + Opt_discard, Opt_nodiscard, Opt_reflink, Opt_dax, Opt_err, > > }; > > > > static const match_table_t tokens = { > > @@ -132,6 +132,7 @@ static const match_table_t tokens = { > > {Opt_qnoenforce, "qnoenforce"}, /* same as uqnoenforce */ > > {Opt_discard, "discard"}, /* Discard unused blocks */ > > {Opt_nodiscard, "nodiscard"}, /* Do not discard unused blocks */ > > + {Opt_reflink, "reflink"}, /* Do not discard unused blocks */ > ^^^^ > > Also, I believe this comment is wrong!? > > Cheers > > -- > Carlos > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From klthomps@andrew.cmu.edu Mon Jun 6 07:02:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E0F507CA0 for ; Mon, 6 Jun 2016 07:02:29 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id A16878F8040 for ; Mon, 6 Jun 2016 05:02:26 -0700 (PDT) X-ASG-Debug-ID: 1465214541-04bdf05ad4b90080001-NocioJ Received: from mail.yurmail.com (mail.yurmail.com [170.75.245.195]) by cuda.sgi.com with ESMTP id BqzUsSGGPWJZZSca (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 06 Jun 2016 05:02:21 -0700 (PDT) X-Barracuda-Envelope-From: klthomps@andrew.cmu.edu X-Barracuda-Effective-Source-IP: mail.yurmail.com[170.75.245.195] X-Barracuda-Apparent-Source-IP: 170.75.245.195 Received: from [198.186.12.34] (port=34891 helo=uoifl.com) by mail.yurmail.com with esmtpsa (TLSv1:DHE-RSA-AES256-SHA:256) (Exim 4.87) (envelope-from ) id 1b9tEV-0003dv-GG; Mon, 06 Jun 2016 07:02:16 -0500 From: Daniel Bast To: "xfs" , "Bill J Pitre" , "Cary_Lund" , "brahm" , "cmu.edu" Subject: that impressed me Date: Mon, 6 Jun 2016 15:02:04 +0300 X-ASG-Orig-Subj: that impressed me Message-ID: <000021a4c404$f55832d7$d6abc069$@andrew.cmu.edu> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_0001_10755521.0B4031AA" X-Mailer: Microsoft Outlook 15.0 Thread-Index: AdG8KkZCbFuNqTVRSN1EUqJBDRD1sA== Content-Language: en-us X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - mail.yurmail.com X-AntiAbuse: Original Domain - oss.sgi.com X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - andrew.cmu.edu X-Get-Message-Sender-Via: mail.yurmail.com: authenticated_id: staff@schulmanlaw.com X-Authenticated-Sender: mail.yurmail.com: staff@schulmanlaw.com X-Source: X-Source-Args: X-Source-Dir: X-Barracuda-Connect: mail.yurmail.com[170.75.245.195] X-Barracuda-Start-Time: 1465214541 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2956 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE, THREAD_INDEX X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30210 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.00 HTML_MESSAGE BODY: HTML included in message This is a multipart message in MIME format. ------=_NextPart_000_0001_10755521.0B4031AA Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Hey, We've got some great news for you! Just take a look Yours sincerely, Daniel Bast ~ Hello, I'm so excited to tell you that, I was impressed so much, please read here Yours sincerely, Daniel Bast ------=_NextPart_000_0001_10755521.0B4031AA Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

<= span lang=3DEN-US>Hey,

We've got some great news for you! Just take a look http://pintasp= ycro.locksmithkilleen.com/lnqpsvp

 

Yours sincerely, Daniel Bast

~

=

Hello,

I'm so excited to tell you that,= I was impressed so much, please read here http://pintaspycro.locksmithkilleen.= com/lnqpsvp

 

Yours sincerely, Daniel Bast

------=_NextPart_000_0001_10755521.0B4031AA-- From mstsxfx@gmail.com Mon Jun 6 07:20:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 09ED57CA0 for ; Mon, 6 Jun 2016 07:20:32 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id CFD838F8049 for ; Mon, 6 Jun 2016 05:20:31 -0700 (PDT) X-ASG-Debug-ID: 1465215625-04cbb03569ba8d90001-NocioJ Received: from mail-wm0-f50.google.com (mail-wm0-f50.google.com [74.125.82.50]) by cuda.sgi.com with ESMTP id tNfxSBbrSpoivkhf (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 06 Jun 2016 05:20:26 -0700 (PDT) X-Barracuda-Envelope-From: mstsxfx@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f50.google.com[74.125.82.50] X-Barracuda-Apparent-Source-IP: 74.125.82.50 Received: by mail-wm0-f50.google.com with SMTP id k184so3790737wme.1 for ; Mon, 06 Jun 2016 05:20:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=lvjaUrPuh7dpW2vdXuhqeuBgp0DnRQnaSVz+hsRu+5I=; b=TfP4iABgiP0Ci/Y1itWZjToLsbBuvPjgyXJ2Udh7rjU/HzKDTR50s4SZUlwzMuuvsN yj9w4XAwYNOsvi1siS6y2Tvf0MvBRhWf0RBwmBkiC5XPse/KhJBLbkVcYADt8mBTZYph KFI4KJM8rdr8gu5GZuBel+R+TXi63vkZCercrnaSLXGsIlPv0Xsgi33avv/RAakBpe91 sJu5dXesZmSmluEGjxOUhOlMjwrxjPF1c6EaIcBI9Nu/Dg94av7Z4R4tWtNzy4Mj6UIA 4NzOuwvLruCpa6H8mpqGlR+A+xXQl4nSC8VimUSuznsnySVxgu70ob2/d2poajU8DYAz wI1A== X-Gm-Message-State: ALyK8tIm1YxsnorrCtUQF6iiWLy9ujPClxt1tTttYbJvwuZI+xcLgk1kzOd4jWFTZYVQCA== X-Received: by 10.194.201.162 with SMTP id kb2mr17098965wjc.55.1465215624530; Mon, 06 Jun 2016 05:20:24 -0700 (PDT) Received: from localhost (nat1.scz.suse.com. [213.151.88.250]) by smtp.gmail.com with ESMTPSA id f186sm13978082wma.13.2016.06.06.05.20.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 06 Jun 2016 05:20:23 -0700 (PDT) Date: Mon, 6 Jun 2016 14:20:22 +0200 From: Michal Hocko To: Dave Chinner Cc: Peter Zijlstra , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160606122022.GH11895@dhcp22.suse.cz> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160517144912.GZ3193@twins.programming.kicks-ass.net> <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> <20160602232254.GR12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160602232254.GR12670@dastard> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: mail-wm0-f50.google.com[74.125.82.50] X-Barracuda-Start-Time: 1465215626 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2681 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30211 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri 03-06-16 09:22:54, Dave Chinner wrote: > On Thu, Jun 02, 2016 at 05:46:19PM +0200, Michal Hocko wrote: > > On Thu 02-06-16 17:11:16, Peter Zijlstra wrote: > > > With scope I mostly meant the fact that you have two calls that you need > > > to pair up. That's not really nice as you can 'annotate' a _lot_ of code > > > in between. I prefer the narrower annotations where you annotate a > > > single specific site. > > > > Yes, I can see you point. What I meant to say is that we would most > > probably end up with the following pattern > > lockdep_trace_alloc_enable() > > some_foo_with_alloc(gfp_mask); > > lockdep_trace_alloc_disable() > > > > and some_foo_with_alloc might be a lot of code. > > That's the problem I see with this - the only way to make it > maintainable is to precede each enable/disable() pair with a comment > explaining *exactly* what those calls are protecting. And that, in > itself, becomes a maintenance problem, because then code several > layers deep has no idea what context it is being called from and we > are likely to disable warnings in contexts where we probably > shouldn't be. I am not sure I understand what you mean here. I thought the problem is that: func_A (!trans. context) func_B (trans. context) foo1() foo2() bar(inode, GFP_KERNEL) bar(inode, GFP_NOFS) so bar(inode, gfp) can be called from two different contexts which would confuse the lockdep. And the workaround would be annotating bar depending on the context it is called from - either pass a special gfp flag or do disable/enable thing. In both cases that anotation should be global for the whole func_A, no? Or is it possible that something in that path would really need a reclaim lockdep detection? > I think such an annotation approach really requires per-alloc site > annotation, the reason for it should be more obvious from the > context. e.g. any function that does memory alloc and takes an > optional transaction context needs annotation. Hence, from an XFS > perspective, I think it makes more sense to add a new KM_ flag to > indicate this call site requirement, then jump through whatever > lockdep hoop is required within the kmem_* allocation wrappers. > e.g, we can ignore the new KM_* flag if we are in a transaction > context and so the flag is only activated in the situations were > we currently enforce an external GFP_NOFS context from the call > site..... Hmm, I thought we would achive this by using the scope GFP_NOFS usage which would mark those transaction related conctexts and no lockdep specific workarounds would be needed... -- Michal Hocko SUSE Labs From jtulak@redhat.com Mon Jun 6 08:09:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C00FA7CA0 for ; Mon, 6 Jun 2016 08:09:04 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 935018F8037 for ; Mon, 6 Jun 2016 06:09:01 -0700 (PDT) X-ASG-Debug-ID: 1465218539-04cb6c2dbbb72c70001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id xBJd0iI2aCHZH8VV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 06:09:00 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CF659B0439 for ; Mon, 6 Jun 2016 13:08:59 +0000 (UTC) Received: from jtulak.brq.redhat.com (jtulak.brq.redhat.com [10.34.26.85]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u56D8wBq015969; Mon, 6 Jun 2016 09:08:59 -0400 From: Jan Tulak To: xfs@oss.sgi.com Cc: Jan Tulak Subject: [PATCH] mkfs: update manpage for -i size Date: Mon, 6 Jun 2016 15:08:51 +0200 X-ASG-Orig-Subj: [PATCH] mkfs: update manpage for -i size Message-Id: <1465218531-16192-1-git-send-email-jtulak@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 06 Jun 2016 13:08:59 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465218540 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 681 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Adding CRC changed the minimum size for inode size from 256 to 512 bytes, but it is not mentioned in the man page. Signed-off-by: Jan Tulak --- man/man8/mkfs.xfs.8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8 index 980b0e1..c3629d9 100644 --- a/man/man8/mkfs.xfs.8 +++ b/man/man8/mkfs.xfs.8 @@ -358,7 +358,7 @@ or as the number fitting in a filesystem block with .BR perblock= . The minimum (and default) .I value -is 256 bytes. +is 256 bytes without crc, 512 bytes with crc enabled. The maximum .I value is 2048 (2 KiB) subject to the restriction that -- 2.5.5 From eflorac@intellique.com Mon Jun 6 10:33:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 24C177CA0 for ; Mon, 6 Jun 2016 10:33:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 896A4AC003 for ; Mon, 6 Jun 2016 08:33:30 -0700 (PDT) X-ASG-Debug-ID: 1465227205-04cb6c2dbcb76b30001-NocioJ Received: from mail1.g1.pair.com (mail1.g1.pair.com [66.39.3.162]) by cuda.sgi.com with ESMTP id A5eeLKTXPGJnId2g (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 08:33:26 -0700 (PDT) X-Barracuda-Envelope-From: eflorac@intellique.com X-Barracuda-Effective-Source-IP: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Apparent-Source-IP: 66.39.3.162 Received: from localhost (localhost [127.0.0.1]) by mail1.g1.pair.com (Postfix) with SMTP id 641A9547A46; Mon, 6 Jun 2016 11:33:25 -0400 (EDT) Received: from harpe.intellique.com (labo.djinux.com [82.225.196.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail1.g1.pair.com (Postfix) with ESMTPSA id 6D3B1547962; Mon, 6 Jun 2016 11:33:24 -0400 (EDT) Date: Mon, 6 Jun 2016 17:33:36 +0200 From: Emmanuel Florac To: Andrew Ryder Cc: Dave Chinner , Brian Foster , xfs@oss.sgi.com Subject: Re: xfs_repair fails after trying to format log cycle? Message-ID: <20160606173336.027917f5@harpe.intellique.com> X-ASG-Orig-Subj: Re: xfs_repair fails after trying to format log cycle? In-Reply-To: <57523CE6.7020906@shaw.ca> References: <56F6DE67.60403@shaw.ca> <20160328085541.GA27040@bfoster.bfoster> <570C8D4D.3060304@shaw.ca> <20160412140512.GA59690@bfoster.bfoster> <570D578D.5010706@shaw.ca> <570DB6CD.1000007@shaw.ca> <20160413045129.GO567@dastard> <57523CE6.7020906@shaw.ca> Organization: Intellique X-Mailer: Claws Mail 3.13.1 (GTK+ 2.24.30; i486-slackware-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Start-Time: 1465227206 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1221 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30214 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Le Fri, 3 Jun 2016 22:28:54 -0400 Andrew Ryder =C3=A9crivait: > Sorry to dig up old stuff here but after replacing hardware and > pulling my hair out to no end, I traced the source of the problem out. >=20 > On every drive in the array, the points on the PCB which the contacts=20 > for the drives motors and head/actuators make contact with were > oxidized enough to cause the issue. I ended up pulling the PCB off > each drive and cleaning them as well as cleaning out all other cable > and drive connectors from the HBA outward and everything is happy > again. >=20 > http://s33.postimg.org/uhjmvw4dr/Not_Cleaned.jpg > http://s33.postimg.org/xo94ieii7/Partial_Cleaned_1.jpg > http://s33.postimg.org/hoqgyumgf/Partial_Cleaned_2.jpg > http://s33.postimg.org/68k20t8a7/Partial_Cleaned_3.jpg >=20 Good job, that was quite unexpected :) Are you next to the seashore? --=20 ------------------------------------------------------------------------ Emmanuel Florac | Direction technique | Intellique | | +33 1 78 94 84 02 ------------------------------------------------------------------------ From mchristi@redhat.com Mon Jun 6 10:40:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EB7E57CA0 for ; Mon, 6 Jun 2016 10:40:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5925EAC005 for ; Mon, 6 Jun 2016 08:40:42 -0700 (PDT) X-ASG-Debug-ID: 1465227640-04cb6c2dbbb76e40001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id XfvNe3FCIJhCCwFX (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 08:40:41 -0700 (PDT) X-Barracuda-Envelope-From: mchristi@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 04A5FC0586C8; Mon, 6 Jun 2016 15:40:40 +0000 (UTC) Received: from [10.10.48.234] (vpn-48-234.rdu2.redhat.com [10.10.48.234]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u56FeaQk005524; Mon, 6 Jun 2016 11:40:36 -0400 Subject: Re: [PATCH 28/45] target: use bio op accessors To: Hannes Reinecke , linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 28/45] target: use bio op accessors References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-29-git-send-email-mchristi@redhat.com> <57551C57.5090507@suse.de> From: Mike Christie Message-ID: <57559973.1020105@redhat.com> Date: Mon, 6 Jun 2016 10:40:35 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.6.0 MIME-Version: 1.0 In-Reply-To: <57551C57.5090507@suse.de> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 06 Jun 2016 15:40:40 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465227641 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1704 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On 06/06/2016 01:46 AM, Hannes Reinecke wrote: > On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: >> From: Mike Christie >> >> Separate the op from the rq_flag_bits and have the target layer >> set/get the bio using bio_set_op_attrs/bio_op. >> >> Signed-off-by: Mike Christie >> --- >> drivers/target/target_core_iblock.c | 29 ++++++++++++++--------------- >> drivers/target/target_core_pscsi.c | 2 +- >> 2 files changed, 15 insertions(+), 16 deletions(-) >> >> diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c >> index c25109c..22af12f 100644 >> --- a/drivers/target/target_core_iblock.c >> +++ b/drivers/target/target_core_iblock.c > [ .. ] >> @@ -689,18 +690,15 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, >> * Force writethrough using WRITE_FUA if a volatile write cache >> * is not enabled, or if initiator set the Force Unit Access bit. >> */ >> + op = REQ_OP_WRITE; >> if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { >> if (cmd->se_cmd_flags & SCF_FUA) >> - rw = WRITE_FUA; >> + op_flags = WRITE_FUA; >> else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) >> - rw = WRITE_FUA; >> - else >> - rw = WRITE; >> - } else { >> - rw = WRITE; >> + op_flags = WRITE_FUA; >> } > Wrong intendation. It should be ok. That line is for the QUEUE_FLAG_WC test. We end up with: op = REQ_OP_WRITE; if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { if (cmd->se_cmd_flags & SCF_FUA) op_flags = WRITE_FUA; else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) op_flags = WRITE_FUA; } From hare@suse.de Mon Jun 6 10:43:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FRT_OFFER2 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E51A87CA0 for ; Mon, 6 Jun 2016 10:43:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9F3888F8033 for ; Mon, 6 Jun 2016 08:43:47 -0700 (PDT) X-ASG-Debug-ID: 1465227824-04cb6c2db9b76f50001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id XeOiTd9qXeNGKJyz (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 06 Jun 2016 08:43:45 -0700 (PDT) X-Barracuda-Envelope-From: hare@suse.de X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 616C9AAAD; Mon, 6 Jun 2016 15:43:41 +0000 (UTC) Subject: Re: [PATCH 28/45] target: use bio op accessors To: Mike Christie , linux-f2fs-devel@lists.sourceforge.net, linux-ext4@vger.kernel.org, konrad.wilk@oracle.com, drbd-dev@lists.linbit.com, philipp.reisner@linbit.com, lars.ellenberg@linbit.com, linux-raid@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, linux-bcache@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org, linux-mtd@lists.infradead.org, target-devel@vger.kernel.org, linux-btrfs@vger.kernel.org, osd-dev@open-osd.org, xfs@oss.sgi.com, ocfs2-devel@oss.oracle.com X-ASG-Orig-Subj: Re: [PATCH 28/45] target: use bio op accessors References: <1465155145-10812-1-git-send-email-mchristi@redhat.com> <1465155145-10812-29-git-send-email-mchristi@redhat.com> <57551C57.5090507@suse.de> <57559973.1020105@redhat.com> From: Hannes Reinecke Message-ID: <57559A20.10506@suse.de> Date: Mon, 6 Jun 2016 17:43:28 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.7.0 MIME-Version: 1.0 In-Reply-To: <57559973.1020105@redhat.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465227825 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2126 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.59 X-Barracuda-Spam-Status: No, SCORE=1.59 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, FRT_OFFER2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30214 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.59 FRT_OFFER2 BODY: ReplaceTags: Offer (2) On 06/06/2016 05:40 PM, Mike Christie wrote: > On 06/06/2016 01:46 AM, Hannes Reinecke wrote: >> On 06/05/2016 09:32 PM, mchristi@redhat.com wrote: >>> From: Mike Christie >>> >>> Separate the op from the rq_flag_bits and have the target layer >>> set/get the bio using bio_set_op_attrs/bio_op. >>> >>> Signed-off-by: Mike Christie >>> --- >>> drivers/target/target_core_iblock.c | 29 ++++++++++++++--------------- >>> drivers/target/target_core_pscsi.c | 2 +- >>> 2 files changed, 15 insertions(+), 16 deletions(-) >>> >>> diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c >>> index c25109c..22af12f 100644 >>> --- a/drivers/target/target_core_iblock.c >>> +++ b/drivers/target/target_core_iblock.c >> [ .. ] >>> @@ -689,18 +690,15 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, >>> * Force writethrough using WRITE_FUA if a volatile write cache >>> * is not enabled, or if initiator set the Force Unit Access bit. >>> */ >>> + op = REQ_OP_WRITE; >>> if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { >>> if (cmd->se_cmd_flags & SCF_FUA) >>> - rw = WRITE_FUA; >>> + op_flags = WRITE_FUA; >>> else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) >>> - rw = WRITE_FUA; >>> - else >>> - rw = WRITE; >>> - } else { >>> - rw = WRITE; >>> + op_flags = WRITE_FUA; >>> } >> Wrong intendation. > > It should be ok. That line is for the QUEUE_FLAG_WC test. We end up with: > > op = REQ_OP_WRITE; > if (test_bit(QUEUE_FLAG_FUA, &q->queue_flags)) { > if (cmd->se_cmd_flags & SCF_FUA) > op_flags = WRITE_FUA; > else if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags)) > op_flags = WRITE_FUA; > } > > > > Indeed, you are correct. Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes Reinecke zSeries & Storage hare@suse.de +49 911 74053 688 SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nrnberg GF: J. Hawn, J. Guild, F. Imendrffer, HRB 16746 (AG Nrnberg) From darrick.wong@oracle.com Mon Jun 6 11:52:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 673DD7CA0 for ; Mon, 6 Jun 2016 11:52:43 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 18D478F8040 for ; Mon, 6 Jun 2016 09:52:42 -0700 (PDT) X-ASG-Debug-ID: 1465231960-04bdf05ad7b99310001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id F0HkBosj8xszouCG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 09:52:40 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u56GqdeB001814 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 6 Jun 2016 16:52:40 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u56GqcCW000435 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 6 Jun 2016 16:52:39 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u56GqcgJ023900 for ; Mon, 6 Jun 2016 16:52:38 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 06 Jun 2016 09:52:37 -0700 Date: Mon, 6 Jun 2016 09:52:36 -0700 From: "Darrick J. Wong" To: xfs@oss.sgi.com Subject: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-ID: <20160606165236.GB5737@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time References: <1464877150-20457-1-git-send-email-hch@lst.de> <1464877150-20457-4-git-send-email-hch@lst.de> <20160606112342.GB23695@redhat.com> <20160606112950.GC23695@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160606112950.GC23695@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1465231960 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1915 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30216 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 06, 2016 at 01:29:50PM +0200, Carlos Maiolino wrote: > Ugh, I just realized dave and derrick had already replied, pointing issues I > didn't figure out, but still I'm curious for the question I asked :) > > > Hi hch, > > > > The patchset looks good, although I'm not quite familiar with the reflink code > > so, I apologize if it is a stupid question > > > > After enabling the reflink feature during mount time, I believe this will not > > have any problems in future mounts of this filesystem without reflink support? > > > > > index 84348af..dfa5077 100644 > > > --- a/fs/xfs/xfs_super.c > > > +++ b/fs/xfs/xfs_super.c > > > @@ -82,7 +82,7 @@ enum { > > > Opt_quota, Opt_noquota, Opt_usrquota, Opt_grpquota, Opt_prjquota, > > > Opt_uquota, Opt_gquota, Opt_pquota, > > > Opt_uqnoenforce, Opt_gqnoenforce, Opt_pqnoenforce, Opt_qnoenforce, > > > - Opt_discard, Opt_nodiscard, Opt_dax, Opt_err, > > > + Opt_discard, Opt_nodiscard, Opt_reflink, Opt_dax, Opt_err, > > > }; > > > > > > static const match_table_t tokens = { > > > @@ -132,6 +132,7 @@ static const match_table_t tokens = { > > > {Opt_qnoenforce, "qnoenforce"}, /* same as uqnoenforce */ > > > {Opt_discard, "discard"}, /* Discard unused blocks */ > > > {Opt_nodiscard, "nodiscard"}, /* Do not discard unused blocks */ > > > + {Opt_reflink, "reflink"}, /* Do not discard unused blocks */ > > ^^^^ I hadn't noticed the incorrect comment; it's good of you to point it out. :) --D > > > > Also, I believe this comment is wrong!? > > > > Cheers > > > > -- > > Carlos > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs > > -- > Carlos > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Mon Jun 6 12:13:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0CC317CA0 for ; Mon, 6 Jun 2016 12:13:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 862B4AC002 for ; Mon, 6 Jun 2016 10:12:58 -0700 (PDT) X-ASG-Debug-ID: 1465233176-04bdf05ad7b99cd0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id shhsEuxD7Fh2CE4K (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 10:12:57 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C9F6C8E67B for ; Mon, 6 Jun 2016 17:12:56 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-195.bos.redhat.com [10.18.41.195]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u56HCuAO008108 for ; Mon, 6 Jun 2016 13:12:56 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 2FB991204FE; Mon, 6 Jun 2016 13:12:55 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH] xfs: cancel eofblocks background trimming on remount read-only Date: Mon, 6 Jun 2016 13:12:55 -0400 X-ASG-Orig-Subj: [PATCH] xfs: cancel eofblocks background trimming on remount read-only Message-Id: <1465233175-6701-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 06 Jun 2016 17:12:56 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465233177 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3936 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 The filesystem quiesce sequence performs the operations necessary to drain all background work, push pending transactions through the log infrastructure and wait on I/O resulting from the final AIL push. We have had reports of remount,ro hangs in xfs_log_quiesce() -> xfs_wait_buftarg(), however, and some instrumentation code to detect transaction commits at this point in the quiesce sequence has inculpated the eofblocks background scanner as a cause. While higher level remount code generally prevents user modifications by the time the filesystem has made it to xfs_log_quiesce(), the background scanner may still be alive and can perform pending work at any time. If this occurs between the xfs_log_force() and xfs_wait_buftarg() calls within xfs_log_quiesce(), this can lead to an indefinite lockup in xfs_wait_buftarg(). To prevent this problem, cancel the background eofblocks scan worker during the remount read-only quiesce sequence. This suspends background trimming when a filesystem is remounted read-only. This is only done in the remount path because the freeze codepath has already locked out new transactions by the time the filesystem attempts to quiesce (and thus waiting on an active work item could deadlock). Kick the eofblocks worker to pick up where it left off once an fs is remounted back to read-write. Signed-off-by: Brian Foster --- To confirm the problem, I have managed to manufacture the remount,ro hang issue described above by hacking in some delays/coordination between the quiesce and eofblocks background worker. Also, an alternative approach that I was considering is to run a synchronous scan around the same place this patch cancels the background scan. The idea is that the background scan would then have no work to do on the subsequent iteration and then die off naturally (until preallocation occurs once again). I suppose the downside is that a remount might not necessarily be expected to muck with preallocation state of affected files. This patch seemed more simple, but I'm open to either. Thoughts? Brian fs/xfs/xfs_icache.c | 2 +- fs/xfs/xfs_icache.h | 1 + fs/xfs/xfs_super.c | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 99ee6eee..fb39a66 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -765,7 +765,7 @@ restart: * Background scanning to trim post-EOF preallocated space. This is queued * based on the 'speculative_prealloc_lifetime' tunable (5m by default). */ -STATIC void +void xfs_queue_eofblocks( struct xfs_mount *mp) { diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 62f1f91..05bac99 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -68,6 +68,7 @@ void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); int xfs_inode_free_quota_eofblocks(struct xfs_inode *ip); void xfs_eofblocks_worker(struct work_struct *); +void xfs_queue_eofblocks(struct xfs_mount *); int xfs_inode_ag_iterator(struct xfs_mount *mp, int (*execute)(struct xfs_inode *ip, int flags, void *args), diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 4700f09..7965371 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1294,6 +1294,7 @@ xfs_fs_remount( */ xfs_restore_resvblks(mp); xfs_log_work_queue(mp); + xfs_queue_eofblocks(mp); } /* rw -> ro */ @@ -1306,6 +1307,13 @@ xfs_fs_remount( * return it to the same size. */ xfs_save_resvblks(mp); + + /* + * Cancel background eofb scanning so it cannot race with the + * final log force+buftarg wait and deadlock the remount. + */ + cancel_delayed_work_sync(&mp->m_eofblocks_work); + xfs_quiesce_attr(mp); mp->m_flags |= XFS_MOUNT_RDONLY; } -- 2.5.5 From darrick.wong@oracle.com Mon Jun 6 13:52:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5890D7CA0 for ; Mon, 6 Jun 2016 13:52:25 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id D7AB2AC005 for ; Mon, 6 Jun 2016 11:52:21 -0700 (PDT) X-ASG-Debug-ID: 1465239137-04bdf05ad4b9c7c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id CSud56VrG1DFZLCj (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 11:52:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u56IqAlu011080 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 6 Jun 2016 18:52:11 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u56IqAKP009945 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Mon, 6 Jun 2016 18:52:10 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u56Iq8EX007920; Mon, 6 Jun 2016 18:52:09 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 06 Jun 2016 11:52:08 -0700 Date: Mon, 6 Jun 2016 11:52:07 -0700 From: "Darrick J. Wong" To: Dave Chinner Cc: Christoph Hellwig , xfs@oss.sgi.com Subject: Re: [RFC] allow enabling reflinks at runtime Message-ID: <20160606185206.GC5737@birch.djwong.org> X-ASG-Orig-Subj: Re: [RFC] allow enabling reflinks at runtime References: <1464877150-20457-1-git-send-email-hch@lst.de> <20160602225415.GP12670@dastard> <20160603015832.GA5758@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160603015832.GA5758@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1465239138 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3037 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30221 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Thu, Jun 02, 2016 at 06:58:33PM -0700, Darrick J. Wong wrote: > On Fri, Jun 03, 2016 at 08:54:15AM +1000, Dave Chinner wrote: > > On Thu, Jun 02, 2016 at 04:19:07PM +0200, Christoph Hellwig wrote: > > > I've had some vocal user requests to allow enabling reflinks at run time, > > > which happens to be a mostly trivial feature. The only caveat is that we > > > need a large enough log size to support the reflink requirements, but for > > > typical large file systems that's not an issue. > > > > Hmmm - how does this interact with all the rmap code? I was not > > planning on enabling reflink without rmap and vice versa simply > > because it makes the validation and testing matrix vastly more > > complex. Indeed, having reflink turned on after a filesystem has > > aged for some time (i.e. from unknown initial conditions) makes > > validation especially tricky.... > > Well... > > It's not strictly impossible, but there will be some problems running > repair and remounting. > > The patchset doesn't actually check that we satisfy the minimum log > space requirement, which will result in xfs refusing to mount. As > Christoph says, this is only an issue on small FSes, but nevertheless, > we shouldn't trap the user like that. > > Second, mkfs lays out all the AG btree roots at the start of the AG > before finding an aligned inode block for the root inode. xfs_repair > feeds the same algorithm from the on-disk feature fields to check that > s_rootino is sane, and gets very unhappy if it doesn't find the root > inode at the computed location. Adding the two btree root blocks is > enough to shift the root inode from 96 to 128. This all can be fixed, > but it /was/ convenient not to have to support weirdo upgraded XFSes > like ext4. :) We could reprogram mkfs to allocate the root inode at a sufficiently high block offset that we'll probably never see a collision between the rootino block and mkfs-time AG btree roots. That seems like less work than fiddling with everything that assumes that the first xfs_prealloc_blocks are reserved for AG metadata to leave a hole for the rootino chunk. I think we could create an incompat feature flag to mark this 'high offset root inode'. mkfs will turn on the flag if any feature at least as new as rmap is enabled. That way, reflink can be turned on for pre-rmap v5 filesystems (where the increase in AG btree roots won't move the calculated rootino) or for post-rmap v5 filesystems (where we put rootino at a high enough offset that we won't have a problem). --D > > Furthermore, if you turn on reflink, you should enable the per-AG > reservations so we don't crash the FS by running out of space when it > needs a block for the refcountbt. > > --D > > > > > Darrick? > > > > Cheers, > > > > Dave. > > -- > > Dave Chinner > > david@fromorbit.com > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From tireman@shaw.ca Mon Jun 6 14:19:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BE9DC7CA0 for ; Mon, 6 Jun 2016 14:19:56 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8508C8F8035 for ; Mon, 6 Jun 2016 12:19:53 -0700 (PDT) X-ASG-Debug-ID: 1465240790-04cb6c2db9b7c930001-NocioJ Received: from smtp-out-so.shaw.ca (smtp-out-so.shaw.ca [64.59.136.137]) by cuda.sgi.com with ESMTP id PcHZDjUpSUJHiVno (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 12:19:51 -0700 (PDT) X-Barracuda-Envelope-From: tireman@shaw.ca X-Barracuda-Effective-Source-IP: smtp-out-so.shaw.ca[64.59.136.137] X-Barracuda-Apparent-Source-IP: 64.59.136.137 Received: from [192.168.0.3] ([174.5.120.103]) by shaw.ca with SMTP id A03wbqrkUN9d0A03xbE13c; Mon, 06 Jun 2016 13:19:50 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shaw.ca; s=s20150330; t=1465240790; bh=1Y241U/AXgmfnJ0+XFZ2eM0nz7hBprOsKBQSxqzwGOA=; h=Subject:To:References:Cc:From:Date:In-Reply-To; b=jA73g5JSn3BgIdGbj8HKlrf6jUSa/cAx6V8vdPEtFnDoiXhvRMASxvpNGmtKcjMn+ /+7lzDkaAQ2B+jURHWDBgWHzf2fNKcvqur1Jk9+0WJylbokw+XSybeM3Ry72vg9vTP GiKDkskAk80xMBD6LZ9evJLa6Sxod+jnJ40LNK3qNJpNTXYU7XwZsxY3c/GWnup0wa JkOibO9wb8ZJ8RC8UDW3e93feIv/OBRFzNys229S+lax+CNyvNd+fB6IqovmqkNliY kZ82bEqP9NBPQQZGdQD9LGg9DUx0kV0a9dvZBo+n1Z21r0CDoCi2UUwn3DoyMbRk/t Jj6xJlbjtKG3g== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shaw.ca; s=s20150330; t=1465240790; bh=1Y241U/AXgmfnJ0+XFZ2eM0nz7hBprOsKBQSxqzwGOA=; h=Subject:To:References:Cc:From:Date:In-Reply-To; b=jA73g5JSn3BgIdGbj8HKlrf6jUSa/cAx6V8vdPEtFnDoiXhvRMASxvpNGmtKcjMn+ /+7lzDkaAQ2B+jURHWDBgWHzf2fNKcvqur1Jk9+0WJylbokw+XSybeM3Ry72vg9vTP GiKDkskAk80xMBD6LZ9evJLa6Sxod+jnJ40LNK3qNJpNTXYU7XwZsxY3c/GWnup0wa JkOibO9wb8ZJ8RC8UDW3e93feIv/OBRFzNys229S+lax+CNyvNd+fB6IqovmqkNliY kZ82bEqP9NBPQQZGdQD9LGg9DUx0kV0a9dvZBo+n1Z21r0CDoCi2UUwn3DoyMbRk/t Jj6xJlbjtKG3g== X-Authority-Analysis: v=2.2 cv=QZUkhYTv c=1 sm=1 tr=0 a=p2XoxBGfiVgixJHHDgKfSQ==:117 a=p2XoxBGfiVgixJHHDgKfSQ==:17 a=IkcTkHD0fZMA:10 a=9wYxZL4EAAAA:20 a=Sqk-MOYxAAAA:20 a=xBWF7wlVAAAA:20 a=uD6-8160AAAA:20 a=wIjcW7T2S-R-JXrNkUgA:9 Subject: Re: xfs_repair fails after trying to format log cycle? To: Emmanuel Florac X-ASG-Orig-Subj: Re: xfs_repair fails after trying to format log cycle? References: <56F6DE67.60403@shaw.ca> <20160328085541.GA27040@bfoster.bfoster> <570C8D4D.3060304@shaw.ca> <20160412140512.GA59690@bfoster.bfoster> <570D578D.5010706@shaw.ca> <570DB6CD.1000007@shaw.ca> <20160413045129.GO567@dastard> <57523CE6.7020906@shaw.ca> <20160606173336.027917f5@harpe.intellique.com> Cc: Dave Chinner , Brian Foster , xfs@oss.sgi.com, linux-raid@vger.kernel.org From: Andrew Ryder Message-ID: <5755CCD7.1000104@shaw.ca> Date: Mon, 6 Jun 2016 15:19:51 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <20160606173336.027917f5@harpe.intellique.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-CMAE-Envelope: MS4wfPK7qb59noCVynoI1VZFoB1Gz/9Ob8aUdt89rhKag3DdEsysXrmKl7gm6w05uoPeM6tRXvSZLcjIpVjokn9F74RYM4Pg3uemzJA8XKVeF/NCXeQ82L4U Uelx9gLSX1E9PJx7UYA5ZknVDv2/mpUakwhxfr6vebIMgsiPcwkO8hpW2qeqK4P/eoPSiC1wHaVkPuUHxb0xF+lQKZfF7HBstXu/KfWBRqIqJEdf4T2vSdFb XK24kI35OQA4JxDrN6FHVUijQ9da+LnJKvJ7lkt7aqQrxt2Htm7PZNXwxRRxTUUy X-Barracuda-Connect: smtp-out-so.shaw.ca[64.59.136.137] X-Barracuda-Start-Time: 1465240790 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1741 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30221 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/06/2016 11:33 AM, Emmanuel Florac wrote: > Le Fri, 3 Jun 2016 22:28:54 -0400 > Andrew Ryder écrivait: > >> Sorry to dig up old stuff here but after replacing hardware and >> pulling my hair out to no end, I traced the source of the problem out. >> >> On every drive in the array, the points on the PCB which the contacts >> for the drives motors and head/actuators make contact with were >> oxidized enough to cause the issue. I ended up pulling the PCB off >> each drive and cleaning them as well as cleaning out all other cable >> and drive connectors from the HBA outward and everything is happy >> again. >> >> http://s33.postimg.org/uhjmvw4dr/Not_Cleaned.jpg >> http://s33.postimg.org/xo94ieii7/Partial_Cleaned_1.jpg >> http://s33.postimg.org/hoqgyumgf/Partial_Cleaned_2.jpg >> http://s33.postimg.org/68k20t8a7/Partial_Cleaned_3.jpg >> > > Good job, that was quite unexpected :) Are you next to the > seashore? > No. I'm up in NW Ontario in Canada actually, far away from any salt water. I'm guessing it was from the combination of air pollutants/humidity and heat given the drives are not in the most hospitable environment esp during the summer ... but after cleaning the board contacts up as well as the esata cable ends/ports, its working great again. I'm beginning to think when I do replace any drives, after warranty is up on them, pull off the PCB, clean it up and coat the contacts with a good smearing of dielectric grease to keep the issue from happening. Makes me wonder how many other people out there suffer from the same issue given the amount of unresolved similar hw errors I've found while googling the errors.. Thanks again, Andrew From tireman@shaw.ca Mon Jun 6 14:37:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A58B57CA1 for ; Mon, 6 Jun 2016 14:37:45 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 79C708F8035 for ; Mon, 6 Jun 2016 12:37:45 -0700 (PDT) X-ASG-Debug-ID: 1465241859-04cbb0356bbb7330001-NocioJ Received: from smtp-out-no.shaw.ca (smtp-out-no.shaw.ca [64.59.134.13]) by cuda.sgi.com with ESMTP id f2n6wgczkh9eJBad (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 12:37:40 -0700 (PDT) X-Barracuda-Envelope-From: tireman@shaw.ca X-Barracuda-Effective-Source-IP: smtp-out-no.shaw.ca[64.59.134.13] X-Barracuda-Apparent-Source-IP: 64.59.134.13 Received: from [192.168.0.3] ([174.5.120.103]) by shaw.ca with SMTP id A0LBbrlqpEWlrA0LCb9uvP; Mon, 06 Jun 2016 13:37:39 -0600 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shaw.ca; s=s20150330; t=1465241859; bh=jnZGCpmGc111KaFclJS9yOOEQb7mb875RKRTAspUH0I=; h=Subject:To:References:Cc:From:Date:In-Reply-To; b=p6HeXudwISAok6Uoo7kIWTs35+vvXqC9jbjJpgy/KUz6AP+FNk7/xCODcdrFBp2+s 3FGOwUN15m77y1Huheygfv05fA5e2gBc8NcWBsMmTjVxHxw8gJ5DyWhpTGzUTkrCOO b3S22+ZfIWpsMxou9E81TDzUWJrvT+iyhhG5MLQepVJwrclaMkk5YL+4kiQr8TbxbE 9Bi9rRUHlD5J8a4Z32MRM8uIhal6iqg9JY0MMPofExmQWcivnkCOAa9aZARPoutDa0 L05MvHVvCN71wVCjuXeJPm11lmo4AL+2DuqtL9leCRrkVEHqhD8cCnCbxKkbVUrw+v DBvRNzpdNHV5A== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=shaw.ca; s=s20150330; t=1465241859; bh=jnZGCpmGc111KaFclJS9yOOEQb7mb875RKRTAspUH0I=; h=Subject:To:References:Cc:From:Date:In-Reply-To; b=p6HeXudwISAok6Uoo7kIWTs35+vvXqC9jbjJpgy/KUz6AP+FNk7/xCODcdrFBp2+s 3FGOwUN15m77y1Huheygfv05fA5e2gBc8NcWBsMmTjVxHxw8gJ5DyWhpTGzUTkrCOO b3S22+ZfIWpsMxou9E81TDzUWJrvT+iyhhG5MLQepVJwrclaMkk5YL+4kiQr8TbxbE 9Bi9rRUHlD5J8a4Z32MRM8uIhal6iqg9JY0MMPofExmQWcivnkCOAa9aZARPoutDa0 L05MvHVvCN71wVCjuXeJPm11lmo4AL+2DuqtL9leCRrkVEHqhD8cCnCbxKkbVUrw+v DBvRNzpdNHV5A== X-Authority-Analysis: v=2.2 cv=P7p4vWIu c=1 sm=1 tr=0 a=p2XoxBGfiVgixJHHDgKfSQ==:117 a=p2XoxBGfiVgixJHHDgKfSQ==:17 a=IkcTkHD0fZMA:10 a=9wYxZL4EAAAA:20 a=Sqk-MOYxAAAA:20 a=xBWF7wlVAAAA:20 a=uD6-8160AAAA:20 a=eJfxgxciAAAA:8 a=mVfkfAKDGsN9X8xM2pUA:9 a=xM9caqqi1sUkTy8OJ5Uh:22 Subject: Re: xfs_repair fails after trying to format log cycle? To: Emmanuel Florac X-ASG-Orig-Subj: Re: xfs_repair fails after trying to format log cycle? References: <56F6DE67.60403@shaw.ca> <20160328085541.GA27040@bfoster.bfoster> <570C8D4D.3060304@shaw.ca> <20160412140512.GA59690@bfoster.bfoster> <570D578D.5010706@shaw.ca> <570DB6CD.1000007@shaw.ca> <20160413045129.GO567@dastard> <57523CE6.7020906@shaw.ca> <20160606173336.027917f5@harpe.intellique.com> <5755CCD7.1000104@shaw.ca> Cc: linux-raid@vger.kernel.org, Brian Foster , xfs@oss.sgi.com From: Andrew Ryder Message-ID: <5755D107.5060001@shaw.ca> Date: Mon, 6 Jun 2016 15:37:43 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <5755CCD7.1000104@shaw.ca> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit X-CMAE-Envelope: MS4wfCU2/pkkeere3oRcOa1gQ2mltbg+SXIt6tZfA+IVwb90VRmgSanBQ2c7UN7wvfkilXSWX99aKjrJ2wchVfvUoO8oKqVR2GEi9Y+BznMMr4WrPixR9E+o erevD1HpUvNaJw9KAyS0SQas9drJwWvYwvQlxUdh/aoa7sAThIleYUmIa95bIJ9m00SYj0Z1bqYgLcb42IOgV+0k9dXubkeIq4yaRw3Zrqx7HAis8Mln9eWb 7ml7sF57vOfU5xGI+NhPGFBcO/0jURtfzxN33b5v2t0= X-Barracuda-Connect: smtp-out-no.shaw.ca[64.59.134.13] X-Barracuda-Start-Time: 1465241860 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2609 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30221 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/06/2016 03:19 PM, Andrew Ryder wrote: > > > On 06/06/2016 11:33 AM, Emmanuel Florac wrote: >> Le Fri, 3 Jun 2016 22:28:54 -0400 >> Andrew Ryder écrivait: >> >>> Sorry to dig up old stuff here but after replacing hardware and >>> pulling my hair out to no end, I traced the source of the problem out. >>> >>> On every drive in the array, the points on the PCB which the contacts >>> for the drives motors and head/actuators make contact with were >>> oxidized enough to cause the issue. I ended up pulling the PCB off >>> each drive and cleaning them as well as cleaning out all other cable >>> and drive connectors from the HBA outward and everything is happy >>> again. >>> >>> http://s33.postimg.org/uhjmvw4dr/Not_Cleaned.jpg >>> http://s33.postimg.org/xo94ieii7/Partial_Cleaned_1.jpg >>> http://s33.postimg.org/hoqgyumgf/Partial_Cleaned_2.jpg >>> http://s33.postimg.org/68k20t8a7/Partial_Cleaned_3.jpg >>> >> >> Good job, that was quite unexpected :) Are you next to the >> seashore? >> > > > No. I'm up in NW Ontario in Canada actually, far away from any salt > water. I'm guessing it was from the combination of air > pollutants/humidity and heat given the drives are not in the most > hospitable environment esp during the summer ... but after cleaning the > board contacts up as well as the esata cable ends/ports, its working > great again. > > I'm beginning to think when I do replace any drives, after warranty is > up on them, pull off the PCB, clean it up and coat the contacts with a > good smearing of dielectric grease to keep the issue from happening. > > Makes me wonder how many other people out there suffer from the same > issue given the amount of unresolved similar hw errors I've found while > googling the errors.. > > Thanks again, > Andrew > One other thing might be worth noting, before I cleaned up the oxidation on the drives boards, they would work fine if on dedicated SATA channels off the mainboard, but when put on any sata port multiplier, it would do nothing but act up. Which was really weird. I'm assuming there must be some inherent sensitivity with sata PMP chips/hw that make this more prevalent.. and I've tried both the old and new version of SansDigital's TR8M's backplanes, 2 different sata PMP HBAs (rocketraid 2722 and addonics older PCI 4 port sata pmp hba) as well as an older addonics 3gbit sata port multiplier fan out board .. > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From sandeen@sandeen.net Mon Jun 6 15:24:17 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 984BB7CA0 for ; Mon, 6 Jun 2016 15:24:17 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5D310304032 for ; Mon, 6 Jun 2016 13:24:13 -0700 (PDT) X-ASG-Debug-ID: 1465244651-04cb6c2dbab7e3a0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id SeEEc3SJbOSJBK45 for ; Mon, 06 Jun 2016 13:24:11 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 2090E22C5 for ; Mon, 6 Jun 2016 15:24:11 -0500 (CDT) Subject: Re: [PATCH] xfs: cancel eofblocks background trimming on remount read-only To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] xfs: cancel eofblocks background trimming on remount read-only References: <1465233175-6701-1-git-send-email-bfoster@redhat.com> From: Eric Sandeen Message-ID: Date: Mon, 6 Jun 2016 15:24:10 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1465233175-6701-1-git-send-email-bfoster@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465244651 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4449 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30223 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/6/16 12:12 PM, Brian Foster wrote: > The filesystem quiesce sequence performs the operations necessary to > drain all background work, push pending transactions through the log > infrastructure and wait on I/O resulting from the final AIL push. We > have had reports of remount,ro hangs in xfs_log_quiesce() -> > xfs_wait_buftarg(), however, and some instrumentation code to detect > transaction commits at this point in the quiesce sequence has inculpated > the eofblocks background scanner as a cause. > > While higher level remount code generally prevents user modifications by > the time the filesystem has made it to xfs_log_quiesce(), the background > scanner may still be alive and can perform pending work at any time. If > this occurs between the xfs_log_force() and xfs_wait_buftarg() calls > within xfs_log_quiesce(), this can lead to an indefinite lockup in > xfs_wait_buftarg(). > > To prevent this problem, cancel the background eofblocks scan worker > during the remount read-only quiesce sequence. This suspends background > trimming when a filesystem is remounted read-only. This is only done in > the remount path because the freeze codepath has already locked out new > transactions by the time the filesystem attempts to quiesce (and thus > waiting on an active work item could deadlock). Kick the eofblocks > worker to pick up where it left off once an fs is remounted back to > read-write. > > Signed-off-by: Brian Foster > --- > > To confirm the problem, I have managed to manufacture the remount,ro > hang issue described above by hacking in some delays/coordination > between the quiesce and eofblocks background worker. > > Also, an alternative approach that I was considering is to run a > synchronous scan around the same place this patch cancels the background > scan. The idea is that the background scan would then have no work to do > on the subsequent iteration and then die off naturally (until > preallocation occurs once again). I suppose the downside is that a > remount might not necessarily be expected to muck with preallocation > state of affected files. This patch seemed more simple, but I'm open to > either. Thoughts? Your approach makes sense to me - "finishing" the scan prior to quiesce could take a relatively unknown amount of time as well, right? And I guess I don't see a real advantage to that; we don't wait for it on unmount (right?) Reviewed-by: Eric Sandeen > Brian > > fs/xfs/xfs_icache.c | 2 +- > fs/xfs/xfs_icache.h | 1 + > fs/xfs/xfs_super.c | 8 ++++++++ > 3 files changed, 10 insertions(+), 1 deletion(-) > > diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c > index 99ee6eee..fb39a66 100644 > --- a/fs/xfs/xfs_icache.c > +++ b/fs/xfs/xfs_icache.c > @@ -765,7 +765,7 @@ restart: > * Background scanning to trim post-EOF preallocated space. This is queued > * based on the 'speculative_prealloc_lifetime' tunable (5m by default). > */ > -STATIC void > +void > xfs_queue_eofblocks( > struct xfs_mount *mp) > { > diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h > index 62f1f91..05bac99 100644 > --- a/fs/xfs/xfs_icache.h > +++ b/fs/xfs/xfs_icache.h > @@ -68,6 +68,7 @@ void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); > int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); > int xfs_inode_free_quota_eofblocks(struct xfs_inode *ip); > void xfs_eofblocks_worker(struct work_struct *); > +void xfs_queue_eofblocks(struct xfs_mount *); > > int xfs_inode_ag_iterator(struct xfs_mount *mp, > int (*execute)(struct xfs_inode *ip, int flags, void *args), > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c > index 4700f09..7965371 100644 > --- a/fs/xfs/xfs_super.c > +++ b/fs/xfs/xfs_super.c > @@ -1294,6 +1294,7 @@ xfs_fs_remount( > */ > xfs_restore_resvblks(mp); > xfs_log_work_queue(mp); > + xfs_queue_eofblocks(mp); > } > > /* rw -> ro */ > @@ -1306,6 +1307,13 @@ xfs_fs_remount( > * return it to the same size. > */ > xfs_save_resvblks(mp); > + > + /* > + * Cancel background eofb scanning so it cannot race with the > + * final log force+buftarg wait and deadlock the remount. > + */ > + cancel_delayed_work_sync(&mp->m_eofblocks_work); > + > xfs_quiesce_attr(mp); > mp->m_flags |= XFS_MOUNT_RDONLY; > } > From sandeen@sandeen.net Mon Jun 6 15:25:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3FC627CA2 for ; Mon, 6 Jun 2016 15:25:55 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id CA132AC003 for ; Mon, 6 Jun 2016 13:25:51 -0700 (PDT) X-ASG-Debug-ID: 1465244749-04bdf05ad6b9f2b0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id L4UUNgIHjDiRdBRf for ; Mon, 06 Jun 2016 13:25:49 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id A5D3822C5 for ; Mon, 6 Jun 2016 15:25:49 -0500 (CDT) Subject: Re: [PATCH] mkfs: update manpage for -i size To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] mkfs: update manpage for -i size References: <1465218531-16192-1-git-send-email-jtulak@redhat.com> From: Eric Sandeen Message-ID: <218360cc-6e75-1a75-4662-60a7a83ae6ce@sandeen.net> Date: Mon, 6 Jun 2016 15:25:49 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1465218531-16192-1-git-send-email-jtulak@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465244749 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 806 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30223 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/6/16 8:08 AM, Jan Tulak wrote: > Adding CRC changed the minimum size for inode size from 256 to 512 bytes, but > it is not mentioned in the man page. > > Signed-off-by: Jan Tulak Reviewed-by: Eric Sandeen > --- > man/man8/mkfs.xfs.8 | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8 > index 980b0e1..c3629d9 100644 > --- a/man/man8/mkfs.xfs.8 > +++ b/man/man8/mkfs.xfs.8 > @@ -358,7 +358,7 @@ or as the number fitting in a filesystem block with > .BR perblock= . > The minimum (and default) > .I value > -is 256 bytes. > +is 256 bytes without crc, 512 bytes with crc enabled. > The maximum > .I value > is 2048 (2 KiB) subject to the restriction that > From sandeen@sandeen.net Mon Jun 6 15:41:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 30D8C7CA1 for ; Mon, 6 Jun 2016 15:41:26 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id B112CAC003 for ; Mon, 6 Jun 2016 13:41:25 -0700 (PDT) X-ASG-Debug-ID: 1465245683-04bdf05ad7b9f880001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id pDrSCD4Jdt8iRTSL for ; Mon, 06 Jun 2016 13:41:23 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id A2C4322C5 for ; Mon, 6 Jun 2016 15:41:23 -0500 (CDT) Subject: Re: [PATCH] mkfs: fix -l su minval To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] mkfs: fix -l su minval References: <1465199729-8622-1-git-send-email-jtulak@redhat.com> From: Eric Sandeen Message-ID: Date: Mon, 6 Jun 2016 15:41:23 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1465199729-8622-1-git-send-email-jtulak@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465245683 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1369 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30223 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/6/16 2:55 AM, Jan Tulak wrote: > -l su should be in range BBTOB(1) <= L_SU <= XLOG_MAX_RECORD_BSIZE, because the > upper limit is imposed by kernel on iclogbuf: stripe unit can't be bigger than > the log buffer, but the log buffer can span multiple stripe units. L_SUNIT is > changed in the same way. > > Signed-off-by: Jan Tulak Manpage could use documentation on defaults, min, and max I suppose. But for this code change: Reviewed-by: Eric Sandeen Thanks for digging into it :) > --- > mkfs/xfs_mkfs.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c > index 955dcfd..ed7800f 100644 > --- a/mkfs/xfs_mkfs.c > +++ b/mkfs/xfs_mkfs.c > @@ -462,7 +462,7 @@ struct opt_params lopts = { > { .index = L_SUNIT, > .conflicts = { L_SU, > LAST_CONFLICT }, > - .minval = BTOBB(XLOG_MIN_RECORD_BSIZE), > + .minval = 1, > .maxval = BTOBB(XLOG_MAX_RECORD_BSIZE), > .defaultval = SUBOPT_NEEDS_VAL, > }, > @@ -470,7 +470,7 @@ struct opt_params lopts = { > .conflicts = { L_SUNIT, > LAST_CONFLICT }, > .convert = true, > - .minval = XLOG_MIN_RECORD_BSIZE, > + .minval = BBTOB(1), > .maxval = XLOG_MAX_RECORD_BSIZE, > .defaultval = SUBOPT_NEEDS_VAL, > }, > From bfoster@redhat.com Mon Jun 6 15:58:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 603BA7CA0 for ; Mon, 6 Jun 2016 15:58:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 300778F8033 for ; Mon, 6 Jun 2016 13:58:00 -0700 (PDT) X-ASG-Debug-ID: 1465246679-04cbb03568bb9720001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id ZEGHtyi9ckF1UmpG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 06 Jun 2016 13:57:59 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C0F0D2C9DC6; Mon, 6 Jun 2016 20:57:58 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-195.bos.redhat.com [10.18.41.195]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u56KvwPg004061; Mon, 6 Jun 2016 16:57:58 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id D46B61204FE; Mon, 6 Jun 2016 16:57:56 -0400 (EDT) Date: Mon, 6 Jun 2016 16:57:56 -0400 From: Brian Foster To: Eric Sandeen Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs: cancel eofblocks background trimming on remount read-only Message-ID: <20160606205756.GA18035@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH] xfs: cancel eofblocks background trimming on remount read-only References: <1465233175-6701-1-git-send-email-bfoster@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Mon, 06 Jun 2016 20:57:58 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465246679 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5239 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 06, 2016 at 03:24:10PM -0500, Eric Sandeen wrote: > > > On 6/6/16 12:12 PM, Brian Foster wrote: > > The filesystem quiesce sequence performs the operations necessary to > > drain all background work, push pending transactions through the log > > infrastructure and wait on I/O resulting from the final AIL push. We > > have had reports of remount,ro hangs in xfs_log_quiesce() -> > > xfs_wait_buftarg(), however, and some instrumentation code to detect > > transaction commits at this point in the quiesce sequence has inculpated > > the eofblocks background scanner as a cause. > > > > While higher level remount code generally prevents user modifications by > > the time the filesystem has made it to xfs_log_quiesce(), the background > > scanner may still be alive and can perform pending work at any time. If > > this occurs between the xfs_log_force() and xfs_wait_buftarg() calls > > within xfs_log_quiesce(), this can lead to an indefinite lockup in > > xfs_wait_buftarg(). > > > > To prevent this problem, cancel the background eofblocks scan worker > > during the remount read-only quiesce sequence. This suspends background > > trimming when a filesystem is remounted read-only. This is only done in > > the remount path because the freeze codepath has already locked out new > > transactions by the time the filesystem attempts to quiesce (and thus > > waiting on an active work item could deadlock). Kick the eofblocks > > worker to pick up where it left off once an fs is remounted back to > > read-write. > > > > Signed-off-by: Brian Foster > > --- > > > > To confirm the problem, I have managed to manufacture the remount,ro > > hang issue described above by hacking in some delays/coordination > > between the quiesce and eofblocks background worker. > > > > Also, an alternative approach that I was considering is to run a > > synchronous scan around the same place this patch cancels the background > > scan. The idea is that the background scan would then have no work to do > > on the subsequent iteration and then die off naturally (until > > preallocation occurs once again). I suppose the downside is that a > > remount might not necessarily be expected to muck with preallocation > > state of affected files. This patch seemed more simple, but I'm open to > > either. Thoughts? > > Your approach makes sense to me - "finishing" the scan prior to quiesce > could take a relatively unknown amount of time as well, right? And I guess > I don't see a real advantage to that; we don't wait for it on unmount > (right?) > Yes, it could take an unknown amount of time. It would probably be similar to what we would do on an unmount. We don't explicitly wait for a scan on unmount (though we destroy the workqueue at some point), but I believe we have to reclaim all cached inodes, which then trims eofblocks for every inode where appropriate (via xfs_inactive()). > Reviewed-by: Eric Sandeen > Thanks! Brian > > Brian > > > > fs/xfs/xfs_icache.c | 2 +- > > fs/xfs/xfs_icache.h | 1 + > > fs/xfs/xfs_super.c | 8 ++++++++ > > 3 files changed, 10 insertions(+), 1 deletion(-) > > > > diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c > > index 99ee6eee..fb39a66 100644 > > --- a/fs/xfs/xfs_icache.c > > +++ b/fs/xfs/xfs_icache.c > > @@ -765,7 +765,7 @@ restart: > > * Background scanning to trim post-EOF preallocated space. This is queued > > * based on the 'speculative_prealloc_lifetime' tunable (5m by default). > > */ > > -STATIC void > > +void > > xfs_queue_eofblocks( > > struct xfs_mount *mp) > > { > > diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h > > index 62f1f91..05bac99 100644 > > --- a/fs/xfs/xfs_icache.h > > +++ b/fs/xfs/xfs_icache.h > > @@ -68,6 +68,7 @@ void xfs_inode_clear_eofblocks_tag(struct xfs_inode *ip); > > int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); > > int xfs_inode_free_quota_eofblocks(struct xfs_inode *ip); > > void xfs_eofblocks_worker(struct work_struct *); > > +void xfs_queue_eofblocks(struct xfs_mount *); > > > > int xfs_inode_ag_iterator(struct xfs_mount *mp, > > int (*execute)(struct xfs_inode *ip, int flags, void *args), > > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c > > index 4700f09..7965371 100644 > > --- a/fs/xfs/xfs_super.c > > +++ b/fs/xfs/xfs_super.c > > @@ -1294,6 +1294,7 @@ xfs_fs_remount( > > */ > > xfs_restore_resvblks(mp); > > xfs_log_work_queue(mp); > > + xfs_queue_eofblocks(mp); > > } > > > > /* rw -> ro */ > > @@ -1306,6 +1307,13 @@ xfs_fs_remount( > > * return it to the same size. > > */ > > xfs_save_resvblks(mp); > > + > > + /* > > + * Cancel background eofb scanning so it cannot race with the > > + * final log force+buftarg wait and deadlock the remount. > > + */ > > + cancel_delayed_work_sync(&mp->m_eofblocks_work); > > + > > xfs_quiesce_attr(mp); > > mp->m_flags |= XFS_MOUNT_RDONLY; > > } > > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From simon54@kyled.com Mon Jun 6 20:01:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: *** X-Spam-Status: No, score=3.3 required=5.0 tests=DATE_IN_PAST_24_48, HTML_MESSAGE,MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EA98B7CA0 for ; Mon, 6 Jun 2016 20:01:35 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 64C6CAC003 for ; Mon, 6 Jun 2016 18:01:31 -0700 (PDT) X-ASG-Debug-ID: 1465261286-04cbb03569bc0d20001-NocioJ Received: from kyled.com ([180.159.153.170]) by cuda.sgi.com with SMTP id QpTGO9EBnY1ZfZuG for ; Mon, 06 Jun 2016 18:01:27 -0700 (PDT) X-Barracuda-Envelope-From: simon54@kyled.com X-Barracuda-Effective-Source-IP: UNKNOWN[180.159.153.170] X-Barracuda-Apparent-Source-IP: 180.159.153.170 Received: from lenovo-PC[127.0.0.1] by LENOVO-PC[127.0.0.1] (SMTPD32); Mon, 6 Jun 2016 07:24:46 +0800 From: "info@kygled.com" Subject: KY LED Technology Co from Shanghai To: xfs@oss.sgi.com X-ASG-Orig-Subj: KY LED Technology Co from Shanghai MIME-Version: 1.0 Sender: simon54@kyled.com Reply-To: info@kygled.com Date: Mon, 6 Jun 2016 07:24:46 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline X-Barracuda-Connect: UNKNOWN[180.159.153.170] X-Barracuda-Start-Time: 1465261286 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3419 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.24 X-Barracuda-Spam-Status: No, SCORE=1.24 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, DATE_IN_PAST_24_48, DATE_IN_PAST_24_48_2, HTML_MESSAGE, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30231 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.01 DATE_IN_PAST_24_48 Date: is 24 to 48 hours before Received: date 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.48 DATE_IN_PAST_24_48_2 DATE_IN_PAST_24_48_2 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160607010131.6641E106C2A7@cuda.sgi.com> PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVU Ri04IiBodHRwLWVxdWl2PWNvbnRlbnQtdHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCA5LjAwLjgxMTIuMTY2ODQiPjwvSEVBRD4NCjxCT0RZPg0KPFA+PEZPTlQgY29s b3I9IzAwODBmZiBzaXplPTQgZmFjZT1BcmlhbD5EZWFyIFB1cmNoYXNpbmcgTWFuYWdlciw8L0ZP TlQ+PC9QPg0KPFA+PEZPTlQgY29sb3I9I2ZmODA4MD48Rk9OVCBzaXplPTI+PEZPTlQgY29sb3I9 IzAwODBmZj48Rk9OVCBzaXplPTQgDQpmYWNlPUFyaWFsPiZuYnNwOzwvRk9OVD48Rk9OVCBzaXpl PTQgDQpmYWNlPUFyaWFsPiZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNwOyZuYnNw OyA8L0ZPTlQ+PC9GT05UPjxGT05UIHNpemU9MyANCmZhY2U9QXJpYWw+PEZPTlQgY29sb3I9IzAw ODBmZj48Rk9OVCBzaXplPTQ+S2luZ3lvdW5nICZuYnNwO0xFRCBMaWdodGluZyANClRlY2hub2xv Z3kgKFNoYW5naGFpKSBMdGQg4oCTIG9uZSBtZW1iZXIgb2YgS1kgR3JvdXAoNCBmYWN0b3JpZXMp Jm5ic3A7IA0KZXN0YWJsaXNoZWQgaW4gMjAwMy4gSXQgaXMgbWFudWZhY3R1cmVyIG9mIExFRCgg TGlnaHRpbmctZW1pdHRpbmcgZGlvZGUpIA0KbGlnaHRpbmcgcHJvZHVjdHMgdGhhdCBpbnRlZ3Jh dGUgZGVzaWduLCBwcm9kdWN0aW9uLCBkaXN0cmlidXRpb24gYW5kIHNlcnZpY2UgDQphbmQgbWFp bmx5IGluIHByb2R1Y3Rpb24gb2YgTEVEIEZsdW9yZXNjZW50IFR1YmUgaW5jbHVkZXMgVDUsVDgs VDEwIGFuZCBUMSANCihTTUQmYW1wO0RJUCkgLCBMRUQgYmlnIHdhdHRhZ2Ugd2FsbCB3YXNoZXIg bGlnaHQsIExFRCBidWxiIGxpZ2h0LCBMRUQgQ29ybiANCkJ1bGIsIExFRCB0dWJlIGxpZ2h0LCAm bmJzcDtMRUQgc3BvdGxpZ2h0LCBMRUQgY2VpbGluZyBsaWdodCwmbmJzcDsgTEVEIFBBUiANCmxp Z2h0LCBMRUQgcGFuZWwgbGlnaHQsIExFRCBTTUQgZmxleGlibGUgc3RyaXAgbGlnaHQsIExFRCB0 cmFjayBsaWdodCwgTEVEIA0KbWluaW5nIGxpZ2h0LCBMRUQgZmx1b3Jlc2NlbnQgbGFtcCwgTEVE IDJHMTEgMkcxMCBHWTEwIEcyMyBHMjQgRG93biBsaWdodCB0dWJlLCANCkxFRCBzdHJlZXQgbGln aHQsIExFRCB1bmRlcmdyb3VuZCBsaWdodCwmbmJzcDtldGMuPC9GT05UPjxCUiANCnN0eWxlPSJQ QURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsgUEFERElORy1MRUZUOiAwcHg7IFBBRERJ TkctUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+PC9GT05UPjwvRk9OVD48Rk9OVCANCmNv bG9yPSM4MDQwNDA+PEJSIA0Kc3R5bGU9IlBBRERJTkctQk9UVE9NOiAwcHg7IE1BUkdJTjogMHB4 OyBQQURESU5HLUxFRlQ6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4 Ij48L1A+DQo8UD4mbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDsmbmJzcDs8Rk9OVCBzaXplPTQgZmFj ZT1BcmlhbD4mbmJzcDs8Rk9OVCANCmNvbG9yPSMwMDgwZmY+Jm5ic3A7IEhvcGUgdG8gZm91bmQm bmJzcDsgYSBnb29kIHBhcm50ZXIgcmVsYXRpb25zaGlwIG9mIA0KY29vcGVyYXRpb24gd2l0aCB5 b3UgZm9yIGEgbG9uZyB0ZXJtIGluIHRoZSANCmZ1dHVyZSE8L0ZPTlQ+PC9GT05UPjwvRk9OVD48 L0ZPTlQ+PC9GT05UPjxGT05UIA0Kc3R5bGU9IlBBRERJTkctQk9UVE9NOiAwcHg7IExJTkUtSEVJ R0hUOiAxOHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBub25lOyBGT05ULVZBUklBTlQ6 IG5vcm1hbDsgRk9OVC1TVFlMRTogbm9ybWFsOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBw eDsgUEFERElORy1MRUZUOiAwcHg7IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7IFBBRERJTkctUklH SFQ6IDBweDsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsgQ09MT1I6IHJnYigyNTUsMjU1LDI1NSk7IEZP TlQtU0laRTogMTJweDsgRk9OVC1XRUlHSFQ6IG5vcm1hbDsgV09SRC1TUEFDSU5HOiAwcHg7IFBB RERJTkctVE9QOiAwcHg7IC13ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBweCIgDQpjb2xvcj0j ODA0MDQwPjwvUD4NCjxQPjxTUEFOIHN0eWxlPSJGT05ULUZBTUlMWTogJiMzOTtBcmlhbCYjMzk7 LCYjMzk7c2Fucy1zZXJpZiYjMzk7IiBsYW5nPUVOLVVTPjxGT05UIA0KY29sb3I9IzAwODBmZiBz aXplPTQ+QmVzdCByZWdhcmRzPC9GT05UPjwvU1BBTj48L1A+DQo8UD48U1BBTiBzdHlsZT0iRk9O VC1GQU1JTFk6ICYjMzk7QXJpYWwmIzM5OywmIzM5O3NhbnMtc2VyaWYmIzM5OyIgbGFuZz1FTi1V Uz48Rk9OVCANCmNvbG9yPSMwMDgwZmYgc2l6ZT00PllvdXJzLCBzaW5jZXJlbHk8L0ZPTlQ+PC9T UEFOPjwvUD4NCjxQPjxTUEFOIHN0eWxlPSJGT05ULUZBTUlMWTogJiMzOTtBcmlhbCYjMzk7LCYj Mzk7c2Fucy1zZXJpZiYjMzk7IiBsYW5nPUVOLVVTPjxGT05UIA0KY29sb3I9IzAwODBmZiBzaXpl PTQ+U2ltb24gV2FuZyA8L0ZPTlQ+PC9TUEFOPjwvUD4NCjxQPjxTUEFOIHN0eWxlPSJGT05ULUZB TUlMWTogJiMzOTtBcmlhbCYjMzk7LCYjMzk7c2Fucy1zZXJpZiYjMzk7IiBsYW5nPUVOLVVTPjxG T05UIA0KY29sb3I9IzAwODBmZiBzaXplPTQ+S2luZ3lvdW5nIENvcnAuPC9GT05UPjwvU1BBTj48 L1A+DQo8UD48Rk9OVCBjb2xvcj0jMDA4MGZmPjxGT05UIHNpemU9ND48U1BBTiANCnN0eWxlPSJG T05ULUZBTUlMWTogJiMzOTtBcmlhbCYjMzk7LCYjMzk7c2Fucy1zZXJpZiYjMzk7IiBsYW5nPUVO LVVTPk0uUCArODYgMTM2MDE4NzY5MzE8QlI+RmF4OiANCis4NiAyMSAzMzgyODUyMTxCUj5FbWFp bDogPC9TUEFOPjxTUEFOIGxhbmc9RU4tVVM+PEEgDQpocmVmPSJtYWlsdG86aW5mb0BreWdsZWQu Y29tIiB0YXJnZXQ9X2JsYW5rPjxTUEFOIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAmIzM5O0FyaWFs JiMzOTssJiMzOTtzYW5zLXNlcmlmJiMzOTsiPmluZm9Aa3lnbGVkLmNvbTwvU1BBTj48L0E+PC9T UEFOPjwvRk9OVD48L0ZPTlQ+PC9QPg0KPFA+PEZPTlQgY29sb3I9IzAwODBmZj48Rk9OVCBzaXpl PTQ+PFNQQU4gbGFuZz1FTi1VUz48Rk9OVCANCmZhY2U9QXJpYWw+V2Vic2l0ZTombmJzcDsgPC9G T05UPjxBIGhyZWY9Imh0dHA6Ly93d3cua3lnbGVkLmNvbSI+PEZPTlQgDQpmYWNlPUFyaWFsPnd3 dy5reWdsZWQuY29tPC9GT05UPjwvQT48L1NQQU4+PC9GT05UPjwvRk9OVD48L1A+DQo8UD48Rk9O VCBzaXplPTQ+PEZPTlQgY29sb3I9IzAwODBmZiBmYWNlPUFyaWFsPkFkZHJlc3M6IE5vLiAzMzMg SmluZ2FuZyBSb2FkIA0KSmlucWlhbyBJbmR1c3RyeSBQYXJrLCBTaGFuZ2hhaSAyMDEyMDYgQ2hp bmEgUC5SIA0KPEJSPjwvRk9OVD48L0ZPTlQ+PC9GT05UPjwvUD48L0JPRFk+PC9IVE1MPg0KDQo= From reinoudkoornstra@gmail.com Mon Jun 6 20:43:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 597177CA0 for ; Mon, 6 Jun 2016 20:43:18 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2BEEF304032 for ; Mon, 6 Jun 2016 18:43:15 -0700 (PDT) X-ASG-Debug-ID: 1465263792-04cb6c2dbbb8a430001-NocioJ Received: from mail-qk0-f172.google.com (mail-qk0-f172.google.com [209.85.220.172]) by cuda.sgi.com with ESMTP id q5AZa38ceHTC2N4B (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 06 Jun 2016 18:43:12 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qk0-f172.google.com[209.85.220.172] X-Barracuda-Apparent-Source-IP: 209.85.220.172 Received: by mail-qk0-f172.google.com with SMTP id u63so16604830qkh.0 for ; Mon, 06 Jun 2016 18:43:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=KbWwq8IRlHddrPbwaKGI5uPosx0+FlqWOVZhIpli0J0=; b=sLVHn3O8TsaU8Ngdu620Y5102tBhkgWWROO/xyEh0bQMWDh14Qm/swx5QQajQTqphr MNrieEWcjBbwpYXtM3ix0PbG4ukyZwZbRADNV+TptBsj0sAxxHSfz99GHNUNrBI58mQF sqNnT8J6Lb9bYlAe9KJVTLhwisohhoDOqAnwXe3y6Vx4D6PLzPUJxkoCFFG5gjV0PcGD vIt4uyhB637W+MUbLJ1+ms1LhV2s8eNpxBCkIp6TogOfUpwddA1Z97VN1G0nB0wzRhmZ 0i9eRArJ4yCvLkqjBXo6r90lmqn0f98/HKCDBOdW7t3rLeVDBW2nH5oI3DU2FPyqPDXE hiiQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=KbWwq8IRlHddrPbwaKGI5uPosx0+FlqWOVZhIpli0J0=; b=AaWivv1DHo17+L1dwdv/9B6I6I8PfD8JjvcHy7guHEGc2VE/vgl0tVeXbIeDQ3JivB j9RHmJW8nQJ5aUOuQuj8NH5c+8KbkMHcqrfeLofURYHbAvZO4n8l63e1IG7MJg8lDSTD NI1J2eotZ1aCebjrSDJXEkG/bE7S2GoCrPy2xDJGLvnyAAWrpMUyFWzsIXbfHvzQMtSs Y8tTAsBBoM9o2R9G5EMIug7Mk3jSSWHYcKmVJbxOoJkP37iVj2EsQGcYm4qoBjk8ROc2 ELQclhSho3eTHX9pNYq3Mno/4KE3FeSdH/sBno2gPR4iF8Hp7IjdbARuL9rtci4IErK+ RXEg== X-Gm-Message-State: ALyK8tLOSp/EZwcUOMrM0TgWpSsPKX11uAQtBaCnLnvkpfrcDRXzf19wXDrvAY9vy8nGcxxc/uc3Ij55JlC7TA== X-Received: by 10.55.154.142 with SMTP id c136mr19303693qke.63.1465263791777; Mon, 06 Jun 2016 18:43:11 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.8.16 with HTTP; Mon, 6 Jun 2016 18:43:11 -0700 (PDT) From: Reinoud Koornstra Date: Mon, 6 Jun 2016 19:43:11 -0600 Message-ID: Subject: crash in xfs in current To: xfs@oss.sgi.com X-ASG-Orig-Subj: crash in xfs in current Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qk0-f172.google.com[209.85.220.172] X-Barracuda-Start-Time: 1465263792 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6678 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30232 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature Dear Dave and Everyone, Today I crashed twice in a row in 4.7-rc1. This was the message and trace: Jun 6 18:07:34 router-dev kernel: [ 134.297442] XFS: Assertion failed: args->op_flags & XFS_DA_OP_OKNOENT, file: fs/xfs/libxfs/xfs_dir2_leaf.c, line: 1307 Jun 6 18:07:34 router-dev kernel: [ 134.297459] ------------[ cut here ]------------ Jun 6 18:07:34 router-dev kernel: [ 134.297474] kernel BUG at fs/xfs/xfs_message.c:113! Jun 6 18:07:34 router-dev kernel: [ 134.297485] invalid opcode: 0000 [#1] SMP Jun 6 18:07:34 router-dev kernel: [ 134.297494] Modules linked in: pl2303 usbserial snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic 8250_dw snd_hda_intel snd_hda_codec snd_hda_core x86_pkg_temp_thermal snd_hwdep intel_powerclamp i2c_designware_platform i2c_designware_core snd_pcm snd_seq_midi snd_seq_midi_event coretemp kvm_intel kvm snd_rawmidi snd_seq snd_seq_device iwlmvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel aesni_intel aes_x86_64 lrw snd_timer glue_helper ablk_helper snd cryptd iwlwifi input_leds soundcore serio_raw mei_me mei intel_lpss_acpi intel_lpss_pci acpi_als intel_lpss shpchp binfmt_misc kfifo_buf industrialio acpi_pad mac_hid parport_pc ppdev lp parport autofs4 xfs libcrc32c i 915 i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops hid_generic mxm_wmi r8169 ahci usbhid i2c_hid mii drm libahci hid wmi video pinctrl_sunrisepoint pinctrl_intel Jun 6 18:07:34 router-dev kernel: [ 134.297712] CPU: 2 PID: 2115 Comm: aptitude Tainted: G U 4.7.0-rc1-wt+ #8 Jun 6 18:07:34 router-dev kernel: [ 134.297728] Hardware name: MSI MS-7971/Z170A PC MATE (MS-7971), BIOS A.70 01/25/2016 Jun 6 18:07:34 router-dev kernel: [ 134.297744] task: ffff8804165f9e80 ti: ffff8803f7eb8000 task.ti: ffff8803f7eb8000 Jun 6 18:07:34 router-dev kernel: [ 134.297759] RIP: 0010:[] [] assfail+0x20/0x30 [xfs] Jun 6 18:07:34 router-dev kernel: [ 134.297796] RSP: 0018:ffff8803f7ebbbb8 EFLAGS: 00010246 Jun 6 18:07:34 router-dev kernel: [ 134.297808] RAX: 0000000000000000 RBX: ffff8803fd5ce480 RCX: 0000000000000000 Jun 6 18:07:34 router-dev kernel: [ 134.297822] RDX: 00000000ffffffc0 RSI: 000000000000000a RDI: ffffffffc038c74a Jun 6 18:07:34 router-dev kernel: [ 134.297837] RBP: ffff8803f7ebbbb8 R08: 0000000000000000 R09: 0000000000000000 Jun 6 18:07:34 router-dev kernel: [ 134.297852] R10: 000000000000000a R11: f000000000000000 R12: ffff8803fd5ce480 Jun 6 18:07:34 router-dev kernel: [ 134.297874] R13: 0000000000000062 R14: ffff880035b5c000 R15: ffff8803fd5ce480 Jun 6 18:07:34 router-dev kernel: [ 134.297889] FS: 00007ff14ad84780(0000) GS:ffff88046ec80000(0000) knlGS:0000000000000000 Jun 6 18:07:34 router-dev kernel: [ 134.297906] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 Jun 6 18:07:34 router-dev kernel: [ 134.297918] CR2: 000055b4b6869d98 CR3: 00000003f87f3000 CR4: 00000000003406e0 Jun 6 18:07:34 router-dev kernel: [ 134.297932] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 Jun 6 18:07:34 router-dev kernel: [ 134.297947] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Jun 6 18:07:34 router-dev kernel: [ 134.297962] Stack: Jun 6 18:07:34 router-dev kernel: [ 134.297967] ffff8803f7ebbc40 ffffffffc0322277 ffff8803f7ebbc58 00000000ffffffff Jun 6 18:07:34 router-dev kernel: [ 134.297986] ffff8803ffffffff ffff880414673840 ffff8803f610b000 0000000000000000 Jun 6 18:07:34 router-dev kernel: [ 134.298004] ffff880452bed380 0000000000000000 ffff003c00a7d2f1 00000000b56d2e47 Jun 6 18:07:34 router-dev kernel: [ 134.298022] Call Trace: Jun 6 18:07:34 router-dev kernel: [ 134.298039] [] xfs_dir2_leaf_lookup_int+0x237/0x350 [xfs] Jun 6 18:07:34 router-dev kernel: [ 134.298064] [] xfs_dir2_leaf_replace+0x41/0x190 [xfs] Jun 6 18:07:34 router-dev kernel: [ 134.298088] [] xfs_dir_replace+0x18c/0x1b0 [xfs] Jun 6 18:07:34 router-dev kernel: [ 134.298114] [] xfs_rename+0x45f/0x9d0 [xfs] Jun 6 18:07:34 router-dev kernel: [ 134.298128] [] ? _raw_write_lock_irqsave+0x2f/0x40 Jun 6 18:07:34 router-dev kernel: [ 134.298155] [] xfs_vn_rename+0xb2/0xe0 [xfs] Jun 6 18:07:34 router-dev kernel: [ 134.298169] [] vfs_rename+0x5a4/0x940 Jun 6 18:07:34 router-dev kernel: [ 134.298182] [] ? security_path_rename+0x90/0xe0 Jun 6 18:07:34 router-dev kernel: [ 134.298195] [] SyS_rename+0x3d5/0x3f0 Jun 6 18:07:34 router-dev kernel: [ 134.298207] [] entry_SYSCALL_64_fastpath+0x1e/0xa8 Jun 6 18:07:34 router-dev kernel: [ 134.298221] Code: 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 48 89 f1 41 89 d0 48 c7 c6 90 84 39 c0 48 89 fa 31 ff 48 89 e5 e8 b0 f8 ff ff <0f> 0b 0f 1f 40 00 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 Jun 6 18:07:34 router-dev kernel: [ 134.298312] RIP [] assfail+0x20/0x30 [xfs] Jun 6 18:07:34 router-dev kernel: [ 134.298339] RSP Jun 6 18:07:34 router-dev kernel: [ 134.303832] ---[ end trace 7894462e3381a043 ]--- 0x760b0 is in assfail (fs/xfs/xfs_message.c:113). 108 void 109 assfail(char *expr, char *file, int line) 110 { 111 xfs_emerg(NULL, "Assertion failed: %s, file: %s, line: %d", 112 expr, file, line); 113 BUG(); 114 } 115 116 void 117 xfs_hex_dump(void *p, int length) Ok, so this function is called. The line is: ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); The function that the assert was called was: /* * Look up name/hash in the leaf block. * Fill in indexp with the found index, and dbpp with the data buffer. * If not found dbpp will be NULL, and ENOENT comes back. * lbpp will always be filled in with the leaf buffer unless there's an error. */ static int /* error */ xfs_dir2_leaf_lookup_int The assert took place right after this loop: /* * Loop over all the entries with the right hash value * looking to match the name. */ for (lep = &ents[index]; index < leafhdr.count && be32_to_cpu(lep->hashval) == args->hashval; lep++, index++) I seem to be able to hit this bug rather frequently. So I put in some instrumentation to print out the flags next time I hit it and save a core file to another fs. Is this is known bug to you or? Thanks, Reinoud. From cj014@yun152.com Mon Jun 6 22:28:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B936A7CA0 for ; Mon, 6 Jun 2016 22:28:15 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7CF4D8F8037 for ; Mon, 6 Jun 2016 20:28:15 -0700 (PDT) X-ASG-Debug-ID: 1465270088-04cb6c2dbcb8dd40001-NocioJ Received: from mail.yun152.com ([61.176.220.141]) by cuda.sgi.com with ESMTP id t0SkxfuEsKv6aNj3 for ; Mon, 06 Jun 2016 20:28:08 -0700 (PDT) X-Barracuda-Envelope-From: cj014@yun152.com X-Barracuda-Effective-Source-IP: UNKNOWN[61.176.220.141] X-Barracuda-Apparent-Source-IP: 61.176.220.141 Received: from 51.net by mail.yun152.com (MDaemon PRO v10.1.1) with ESMTP id md50210014680.msg for ; Tue, 07 Jun 2016 11:27:08 +0800 X-MDHeloLookup-Result: hardfail smtp.helo=51.net (does not match 117.14.27.252) (mail.yun152.com) X-Authenticated-Sender: cj014@yun152.com X-MDRemoteIP: 117.14.27.252 X-Return-Path: cj014@yun152.com X-Envelope-From: cj014@yun152.com X-MDaemon-Deliver-To: xfs@oss.sgi.com Reply-To: Sender: cj014@yun152.com Date: Tue, 7 Jun 2016 11:26:50 +0800 From: "Alice" To: Subject: cashewnut kernels Message-ID: <20160607112655028832@yun152.com> X-ASG-Orig-Subj: cashewnut kernels X-mailer: Foxmail 6, 13, 102, 15 [cn] Disposition-Notification-To: xinyuanexport@126.com Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="=====003_Dragon063134418500_=====" X-Barracuda-Connect: UNKNOWN[61.176.220.141] X-Barracuda-Start-Time: 1465270088 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 748 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.80 X-Barracuda-Spam-Status: No, SCORE=0.80 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_SA148d, BSF_SC5_MJ1963, HTML_MESSAGE, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30233 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.20 BSF_SC0_SA148d Custom Rule SA148d 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 This is a multi-part message in MIME format. --=====003_Dragon063134418500_===== Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 RGVhciBtYW5hZ2VyLCANCg0KV2UgYXJlIHN1cHBsaWVyIGFuZCBleHBvcnRlciBvZiBjYXNoZXdu dXQga2VybmVscyBpbiBDaGluYQ0KaWYgbmVlZCwgZW1haWwgdXMNCnRoYW5rcw0KRW1haWwgOiB4 aW55dWFuZXhwb3J0QDEyNi5jb20NCnNreXBlOiBkYWRhZGVoYW95dW4= --=====003_Dragon063134418500_===== Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: base64 PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PXV0 Zi04IiBodHRwLWVxdWl2PUNvbnRlbnQtVHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCA4LjAwLjYwMDEuMjM1ODgiPjwvSEVBRD4NCjxCT0RZPjxGT05UIHNpemU9MiBm YWNlPUFyaWFsPg0KPERJVj5EZWFyIG1hbmFnZXIsIDwvRElWPg0KPERJVj48QlI+V2UgYXJlIHN1 cHBsaWVyIGFuZCBleHBvcnRlciZuYnNwO29mJm5ic3A7Y2FzaGV3bnV0IGtlcm5lbHMgaW4gDQpD aGluYTwvRElWPg0KPERJVj5pZiBuZWVkLCBlbWFpbCB1czwvRElWPg0KPERJVj50aGFua3M8L0RJ Vj4NCjxESVY+RW1haWwgOiA8QSANCmhyZWY9Im1haWx0bzp4aW55dWFuZXhwb3J0QDEyNi5jb20i Pnhpbnl1YW5leHBvcnRAMTI2LmNvbTwvQT48L0RJVj4NCjxESVY+c2t5cGU6IGRhZGFkZWhhb3l1 bjwvRElWPjwvRk9OVD48L0JPRFk+PC9IVE1MPg0K --=====003_Dragon063134418500_=====-- From sandeen@sandeen.net Mon Jun 6 23:40:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 754E47CA0 for ; Mon, 6 Jun 2016 23:40:02 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4725F8F8037 for ; Mon, 6 Jun 2016 21:40:02 -0700 (PDT) X-ASG-Debug-ID: 1465274399-04cb6c2dbbb904f0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id 4rjiPBtDTMYfjLT3 for ; Mon, 06 Jun 2016 21:39:59 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id AA9E0B55 for ; Mon, 6 Jun 2016 23:39:59 -0500 (CDT) Subject: Re: crash in xfs in current To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: crash in xfs in current References: From: Eric Sandeen Message-ID: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> Date: Mon, 6 Jun 2016 23:39:59 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465274399 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3374 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30234 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/6/16 8:43 PM, Reinoud Koornstra wrote: > Dear Dave and Everyone, > > Today I crashed twice in a row in 4.7-rc1. > This was the message and trace: > > Jun 6 18:07:34 router-dev kernel: [ 134.297442] XFS: Assertion failed: args->op_flags & XFS_DA_OP_OKNOENT, file: fs/xfs/libxfs/xfs_dir2_leaf.c, line: 1307 Ok, that ASSERT has been there since 2005 ... > Jun 6 18:07:34 router-dev kernel: [ 134.297459] ------------[ cut here ]------------ > Jun 6 18:07:34 router-dev kernel: [ 134.297474] kernel BUG at fs/xfs/xfs_message.c:113! > Jun 6 18:07:34 router-dev kernel: [ 134.297485] invalid opcode: 0000 [#1] SMP > Jun 6 18:07:34 router-dev kernel: [ 134.297494] Modules linked in: ... unlinewrapping... > Jun 6 18:07:34 router-dev kernel: [ 134.297962] Stack: > Jun 6 18:07:34 router-dev kernel: [ 134.297967] ffff8803f7ebbc40 ffffffffc0322277 ffff8803f7ebbc58 00000000ffffffff > Jun 6 18:07:34 router-dev kernel: [ 134.297986] ffff8803ffffffff ffff880414673840 ffff8803f610b000 0000000000000000 > Jun 6 18:07:34 router-dev kernel: [ 134.298004] ffff880452bed380 0000000000000000 ffff003c00a7d2f1 00000000b56d2e47 > Jun 6 18:07:34 router-dev kernel: [ 134.298022] Call Trace: > Jun 6 18:07:34 router-dev kernel: [ 134.298039] [] xfs_dir2_leaf_lookup_int+0x237/0x350 [xfs] > Jun 6 18:07:34 router-dev kernel: [ 134.298064] [] xfs_dir2_leaf_replace+0x41/0x190 [xfs] > Jun 6 18:07:34 router-dev kernel: [ 134.298088] [] xfs_dir_replace+0x18c/0x1b0 [xfs] > Jun 6 18:07:34 router-dev kernel: [ 134.298114] [] xfs_rename+0x45f/0x9d0 [xfs] > Jun 6 18:07:34 router-dev kernel: [ 134.298155] [] xfs_vn_rename+0xb2/0xe0 [xfs] > Jun 6 18:07:34 router-dev kernel: [ 134.298169] [] vfs_rename+0x5a4/0x940 > Jun 6 18:07:34 router-dev kernel: [ 134.298195] [] SyS_rename+0x3d5/0x3f0 > Jun 6 18:07:34 router-dev kernel: [ 134.298207] [] entry_SYSCALL_64_fastpath+0x1e/0xa8 > Jun 6 18:07:34 router-dev kernel: [ 134.298221] Code: 00 66 2e 0f 1f > I seem to be able to hit this bug rather frequently. > So I put in some instrumentation to print out the flags next time I > hit it and save a core file to another fs. > Is this is known bug to you or? xfs_dir2_leaf_lookup_int() only hits that ASSERT if it was given a name to rename, and failed to find the original. i.e. that should not happen. /* * Loop over all the entries with the right hash value * looking to match the name. */ ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); /* * Here, we can only be doing a lookup (not a rename or remove). * If a case-insensitive match was found earlier, re-read the * appropriate data block if required and return it. */ A rename should never fail to find the original name. Did this problem only show up after an update? Do you have a reproducer? Have you unmounted and run an "xfs_repair -n" and captured the output to see if there is any on-disk corruption? You might gather an xfs_metadump as well, before you do any live repair that might change the filesystem. -Eric From BATV+75fc7f7cc5699f774dd8+4671+infradead.org+hch@bombadil.srs.infradead.org Tue Jun 7 01:27:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id AB70E7CA0 for ; Tue, 7 Jun 2016 01:27:24 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 432F2AC005 for ; Mon, 6 Jun 2016 23:27:21 -0700 (PDT) X-ASG-Debug-ID: 1465280839-04bdf05ad6bb00b0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id t7nSX7ppsuETHQFI (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 06 Jun 2016 23:27:19 -0700 (PDT) X-Barracuda-Envelope-From: BATV+75fc7f7cc5699f774dd8+4671+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bAATu-0001OL-0O; Tue, 07 Jun 2016 06:27:18 +0000 Date: Mon, 6 Jun 2016 23:27:17 -0700 From: Christoph Hellwig To: Eric Sandeen , reinoudkoornstra@gmail.com Cc: xfs@oss.sgi.com, wagi@monom.org, viro@zeniv.linux.org.uk Subject: Re: crash in xfs in current Message-ID: <20160607062717.GA30022@infradead.org> X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1465280839 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1341 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30237 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Mon, Jun 06, 2016 at 11:39:59PM -0500, Eric Sandeen wrote: > xfs_dir2_leaf_lookup_int() only hits that ASSERT if it was given > a name to rename, and failed to find the original. i.e. that should > not happen. > > /* > * Loop over all the entries with the right hash value > * looking to match the name. > */ > > > > > > ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); > /* > * Here, we can only be doing a lookup (not a rename or remove). > * If a case-insensitive match was found earlier, re-read the > * appropriate data block if required and return it. > */ > > A rename should never fail to find the original name. FYI, this looks very much the same like the Bug Daniel reported, which I tried to help debugging in person over the weekend. His backtrace points to cancelling a dirty transaction after xfs_dir_replace failed, which most likely comes from the failing lookup, except that he probably doen't have XFS_DEBUG enabled. Given that 4.7-rc1 comes with the new shared locks for lookups, and there are very little other changes I wonder if there is any relation It would be good if Reinoud and/or Daniel can confirm that Linux 4.6 is ok. From inmeconatk@nm.ru Tue Jun 7 01:45:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0FC807CA0 for ; Tue, 7 Jun 2016 01:45:56 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9969AAC006 for ; Mon, 6 Jun 2016 23:45:55 -0700 (PDT) X-ASG-Debug-ID: 1465281946-04bdf05ad4bb0700001-NocioJ Received: from mx.qip.ru (web.onlinefusion.co.uk [51.255.102.41]) by cuda.sgi.com with ESMTP id hriMClHNJefh5zSu for ; Mon, 06 Jun 2016 23:45:48 -0700 (PDT) X-Barracuda-Envelope-From: inmeconatk@nm.ru X-Barracuda-Effective-Source-IP: web.onlinefusion.co.uk[51.255.102.41] X-Barracuda-Apparent-Source-IP: 51.255.102.41 Message-ID: <0989975646D96FFAC7358A48F4CB1403@KAPJTXBPU> From: "=?utf-8?B?0J3QvtCy0L7QtSDQsiDQs9C+0YHQvtCx0L7RgNC+0L3Qt9Cw0LrQsNC30LU=?=" To: Subject: =?utf-8?B?0KDQsNC30YrRj9GB0L3QtdC90LjRjyDQv9C+INCT0L7RgdC+0LHQvtGA0L7QvdC30LDQutCw0LfRgw==?= Date: Tue, 7 Jun 2016 09:45:46 +0300 X-ASG-Orig-Subj: =?utf-8?B?0KDQsNC30YrRj9GB0L3QtdC90LjRjyDQv9C+INCT0L7RgdC+0LHQvtGA0L7QvdC30LDQutCw0LfRgw==?= MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_00DD_01D1C0A1.5DDE1C40" X-Priority: 3 X-MSMail-Priority: Normal Importance: Normal X-Mailer: Microsoft Windows Live Mail 15.4.3555.308 X-MimeOLE: Produced By Microsoft MimeOLE V15.4.3555.308 X-Barracuda-Connect: web.onlinefusion.co.uk[51.255.102.41] X-Barracuda-Start-Time: 1465281946 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 21895 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30237 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message MIME. ------=_NextPart_000_00DD_01D1C0A1.5DDE1C40 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable 23 - 24 =D0=B8=D1=8E=D0=BD=D1=8F | =D0=B3. = =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D0=B0 | c 10:00 =D0=B4=D0=BE 17:30 | = =D0=90=D1=80=D1=82=D0=B8=D0=BA=D1=83=D0=BB: 421 =D0=93=D0=9E=D0=A1=D0=A3=D0=94=D0=90=D0=A0=D0=A1=D0=A2=D0=92=D0=95=D0=9D=D0= =9D=D0=AB=D0=99 =D0=9E=D0=91=D0=9E=D0=A0=D0=9E=D0=9D=D0=9D=D0=AB=D0=99 = =D0=97=D0=90=D0=9A=D0=90=D0=97.=20 =D0=9D=D0=9E=D0=92=D0=9E=D0=95 =D0=92 = =D0=9D=D0=9E=D0=A0=D0=9C=D0=90=D0=A2=D0=98=D0=92=D0=9D=D0=9E-=D0=9F=D0=A0= =D0=90=D0=92=D0=9E=D0=92=D0=9E=D0=9C = =D0=A0=D0=95=D0=93=D0=A3=D0=9B=D0=98=D0=A0=D0=9E=D0=92=D0=90=D0=9D=D0=98=D0= =98, =D0=90=D0=9A=D0=A2=D0=A3=D0=90=D0=9B=D0=AC=D0=9D=D0=AB=D0=95=20 =D0=92=D0=9E=D0=9F=D0=A0=D0=9E=D0=A1=D0=AB = =D0=A6=D0=95=D0=9D=D0=9E=D0=9E=D0=91=D0=A0=D0=90=D0=97=D0=9E=D0=92=D0=90=D0= =9D=D0=98=D0=AF, =D0=9E=D0=A2=D0=92=D0=95=D0=A2=D0=A1=D0=A2=D0=92=D0=95=D0= =9D=D0=9D=D0=9E=D0=A1=D0=A2=D0=AC =D0=97=D0=90 = =D0=9D=D0=95=D0=98=D0=A1=D0=9F=D0=9E=D0=9B=D0=9D=D0=95=D0=9D=D0=98=D0=95 = =20 =D0=9A=D0=9E=D0=9D=D0=A2=D0=A0=D0=90=D0=9A=D0=A2=D0=9E=D0=92 =D0=9F=D1=80=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D1=8E=D1=82 = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=B8=D0=B5 = =D1=81=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D1=81=D1=82=D1=8B = =D0=A3=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8F = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D0=BE=D0=B3=D0=BE=20 =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B0 = =D0=A6=D0=B5=D0=BD=D1=82=D1=80=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B0=D0=BF=D0=BF=D0=B0=D1=80=D0=B0=D1=82=D0=B0 =D0=A4=D0=90=D0=A1 = =D0=A0=D0=BE=D1=81=D1=81=D0=B8=D0=B8, = =D0=BF=D1=80=D0=B5=D0=B4=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D0=B5=D0=BB=D0= =B8 =D1=8D=D0=BA=D1=81=D0=BF=D0=B5=D1=80=D1=82=D0=BD=D1=8B=D1=85=20 =D0=B3=D1=80=D1=83=D0=BF=D0=BF =D0=9F=D1=80=D0=B0=D0=B2=D0=B8=D1=82=D0=B5= =D0=BB=D1=8C=D1=81=D1=82=D0=B2=D0=B0 =D0=A0=D0=A4 =20 =D0=9C=D0=B5=D1=81=D1=82=D0=BE =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5= =D0=BD=D0=B8=D1=8F: =D0=BC. =D0=91=D0=B0=D1=83=D0=BC=D0=B0=D0=BD=D1=81=D0= =BA=D0=B0=D1=8F, =D1=83=D0=BB. =D0=91=D0=B0=D1=83=D0=BC=D0=B0=D0=BD=D1=81= =D0=BA=D0=B0=D1=8F, =D0=B4.6, =D1=81=D1=82=D1=80.2, =D0=91.=D0=A6. = "=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D1=8F = =D0=9F=D0=BB=D0=B0=D0=B7=D0=B0". =D0=9F=D0=BE=D0=B4=D1=80=D0=BE=D0=B1=D0=BD=D0=B0=D1=8F = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8F =D0=B8 = =D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D1=8C =D0=BF=D0=BE = =D0=BD=D0=BE=D0=BC=D0=B5=D1=80=D1=83 = =D1=82=D0=B5=D0=BB=D0=B5=D1=84=D0=BE=D0=BD=D0=B0: 8 =D0=BA=D0=BE=D0=B4 =D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=B0 = =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D1=8B (495) =D1=82=D0=B5=D0=BB.: 411 - 90 = - 98. =D0=92=D1=8B =D0=BC=D0=BE=D0=B6=D0=B5=D1=82=D0=B5 = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=B2=D0=BE=D0=B2=D0=B0=D1=82=D1=8C = =D0=B2 =D0=BE=D0=B1=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B8 = =D0=BA=D0=B0=D0=BA =D0=BE=D1=82 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8= =D0=B8, =D1=82=D0=B0=D0=BA =D0=B8 =D0=BA=D0=B0=D0=BA = =D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=BE=D0=B5 =D0=BB=D0=B8=D1=86=D0=BE. (=D0=BF=D0=BE=D0=B6=D0=B0=D0=BB=D1=83=D0=B9=D1=81=D1=82=D0=B0 = =D0=BD=D0=B5 =D0=BE=D1=82=D0=B2=D0=B5=D1=87=D0=B0=D0=B9=D1=82=D0=B5 = =D0=BD=D0=B0 =D0=BE=D0=B1=D1=80=D0=B0=D1=82=D0=BD=D1=8B=D0=B9 = =D0=B0=D0=B4=D1=80=D0=B5=D1=81 =D1=8D=D0=BB.=D0=BF=D0=BE=D1=87=D1=82=D1=8B= ) =20 =D0=9F=D0=A0=D0=9E=D0=93=D0=A0=D0=90=D0=9C=D0=9C=D0=90: 1. =D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F =D0=B2 = =D0=B7=D0=B0=D0=BA=D0=BE=D0=BD=D0=BE=D0=B4=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1= =81=D1=82=D0=B2=D0=B5 =D0=BE =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1= =81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=BC = =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=BC = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B5 (=D0=93=D0=9E=D0=97), = =D0=9A=D0=BE=D0=B4=D0=B5=D0=BA=D1=81=D0=B5 =D0=BE=D0=B1=20 =D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=B8= =D0=B2=D0=BD=D1=8B=D1=85 =D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BD=D0=B0=D1=80= =D1=83=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=D1=85 =D0=B2 =D0=A0=D0=A4 =D0=B8 = =D1=82.=D0=B4. =D0=9D=D0=BE=D1=80=D0=BC=D1=8B =D0=B8 = =D1=82=D1=80=D0=B5=D0=B1=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F = =D0=A4=D0=97 =E2=84=96 275-=D0=A4=D0=97 =D0=BE=D1=82 29 = =D0=B4=D0=B5=D0=BA=D0=B0=D0=B1=D1=80=D1=8F 2012 =D0=B3. "=D0=9E = =D0=93=D0=9E=D0=97"; =D0=9D=D0=BE=D0=B2=D0=BE=D0=B5 =D0=B2 = =D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=B5 =D0=93=D0=9E=D0=97 =D0=B2 = =D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8 = =D1=81 =D0=BF=D0=BE=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=D0=BC=D0=B8= =D0=A4=D0=97 =E2=84=96 159-=D0=A4=D0=97 =D0=BE=D1=82 29 = =D0=B8=D1=8E=D0=BD=D1=8F 2015 =D0=B3.=20 "=D0=9E =D0=B2=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B8=D0=B8 = =D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9 =D0=B2 = =D0=A4=D0=97 "=D0=9E =D0=93=D0=9E=D0=97" =D0=B8 = =D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5 = =D0=B7=D0=B0=D0=BA=D0=BE=D0=BD=D0=BE=D0=B4=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0= =BD=D1=8B=D0=B5 =D0=B0=D0=BA=D1=82=D1=8B =D0=A0=D0=A4". 2. =D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D0=B5 = =D0=BF=D1=80=D0=B0=D0=B2=D0=B0 =D0=B8 = =D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D0=BE=D0=B3=D0=BE =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D1=87=D0=B8=D0=BA=D0= =B0, =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F,=20 =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F. 3. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5 =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1= =8B=D0=B5 =D0=BF=D1=80=D0=B0=D0=B2=D0=B0 =D0=B8 = =D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F. = =D0=9A=D0=BE=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F = =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE=20 =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F. 4. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5 =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1= =8B=D0=B5 =D0=BF=D1=80=D0=B0=D0=B2=D0=B0 =D0=B8 = =D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F. 5. =D0=A4=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5= =D0=BA=D0=BE=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8 = =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D1=8B=D0=BC=D0=B8 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F=D0=BC=D0= =B8 =D0=B8 =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1= =8F=D0=BC=D0=B8 =D0=93=D0=9E=D0=97. =D0=A3=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1= =8F=20 =D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D0=B5=D0=BC=D1=8B=D1=85 = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0=B2 = =D0=BF=D0=BE =D0=93=D0=9E=D0=97. 6. =D0=9E=D0=B1=D0=B5=D1=81=D0=BF=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BE=D0=BA = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8, = =D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D1=8F = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=BE=D0=B2 =D0=BD=D0=B0 = =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BA=D0=B8 = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8. 7. =D0=97=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D0=BE=D0=B3=D0=BE =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0= =B0. =D0=92=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=B8=D0=B4=D0=B5=D0=BD=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D1= =80=D0=B0 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0= =B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20 =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=B0. 8. =D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C =D0=B7=D0=B0 = =D0=BE=D0=B1=D0=B5=D1=81=D0=BF=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=B0 =D0=B8 = =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BE=D0=BA = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F=D0=BC=D0= =B8 =D0=B8/=D0=B8=D0=BB=D0=B8 =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D1=8B=D0= =BC=20 =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D0=B5=D0=BC= =2E 9. =D0=9E=D1=82=D0=BA=D0=B0=D0=B7 =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0= =B8=D0=BA=D0=BE=D0=B2 =D0=BA=D0=BE=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0= =B8=D0=B8 =D0=BE=D1=82 =D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0= =B8=D1=8F =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0=B2 = =D0=B2 =D1=80=D0=B0=D0=BC=D0=BA=D0=B0=D1=85 = =D1=81=D0=BE=D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B6=D0=B4=D0=B0=D0=B5=D0=BC=D0= =BE=D0=B9 =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8.=20 =D0=90=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC = =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B =D0=BF=D0=BE = =D1=83=D1=80=D0=B5=D0=B3=D1=83=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0= =B8=D1=8E =D1=80=D0=B0=D0=B7=D0=BD=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=B8=D0= =B9; =D0=A0=D0=B5=D0=B6=D0=B8=D0=BC =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0= =B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F = =D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE = =D1=81=D1=87=D0=B5=D1=82=D0=B0 =D0=B8=20 =D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82=D1=8B =D0=BD=D0=B0 = =D1=81=D0=BE=D0=B2=D0=B5=D1=80=D1=88=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B9; = =D0=9A=D1=80=D0=B8=D1=82=D0=B5=D1=80=D0=B8=D0=B8 = =D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B9, = =D0=BF=D1=80=D0=B8=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2=D0=BB=D0=B8=D0= =B2=D0=B0=D0=B5=D0=BC=D1=8B=D1=85 =D0=B2 = =D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8 = =D1=81=20 =D0=A4=D0=B5=D0=B4=D0=B5=D1=80=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC = =D0=B7=D0=B0=D0=BA=D0=BE=D0=BD=D0=BE=D0=BC =C2=AB=D0=9E = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D0=BE=D0=BC =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=BC = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B5=C2=BB =D0=B8 =D1=82.=D0=B4. 10. =D0=A3=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1=8F = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D1=8B=D1=85 =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0= =B2, =D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2=D0=BB=D0=B8=D0=B2=D0=B0=D1= =8E=D1=89=D0=B8=D0=B5 =D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80 = =D0=BF=D1=80=D0=B8=D0=B1=D1=8B=D0=BB=D0=B8 =D0=B8 (=D0=B8=D0=BB=D0=B8) = =D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA=20 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B5=D0=BD=D1=81=D0=B0=D1=86=D0=B8=D0=B8 = =D0=BF=D0=BE=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=BD=D1=8B=D1=85 = =D0=B7=D0=B0 =D1=81=D1=87=D0=B5=D1=82 = =D1=81=D0=BE=D0=B1=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D1=8B=D1=85 = =D1=81=D1=80=D0=B5=D0=B4=D1=81=D1=82=D0=B2 = =D1=80=D0=B0=D1=81=D1=85=D0=BE=D0=B4=D0=BE=D0=B2 =D0=BD=D0=B0 = =D1=84=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D0=B7=D0=B0=D0=BF=D0=B0=D1=81=D0=B0=20 =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8, = =D1=81=D1=8B=D1=80=D1=8C=D1=8F, =D0=BC=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=B0= =D0=BB=D0=BE=D0=B2, =D0=BF=D0=BE=D0=BB=D1=83=D1=84=D0=B0=D0=B1=D1=80=D0=B8= =D0=BA=D0=B0=D1=82=D0=BE=D0=B2, =D0=BA=D0=BE=D0=BC=D0=BF=D0=BB=D0=B5=D0=BA= =D1=82=D1=83=D1=8E=D1=89=D0=B8=D1=85 = =D0=B8=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8=D0=B9, = =D0=BD=D0=B5=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=D0=BE=D0=B3=D0=BE = =D0=B4=D0=BB=D1=8F=20 =D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F = =D0=93=D0=9E=D0=97; 11. =D0=98=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=B8 = =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0= =B8=D1=8F =D1=80=D0=B0=D0=B1=D0=BE=D1=82 =D0=BF=D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=B0=D0=BC, = =D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=BD=D1=8B=D0=BC = =D1=81 =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F= =D0=BC=D0=B8 =D0=B8=20 =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D1=87=D0=B8=D0=BA=D0=B0=D0=BC=D0=B8. 12. =D0=91=D0=B0=D0=BD=D0=BA=D0=BE=D0=B2=D1=81=D0=BA=D0=BE=D0=B5 = =D1=81=D0=BE=D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0= =B5 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0= =BD=D0=BD=D0=BE=D0=B3=D0=BE =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1= =82=D0=B0 =D0=B8 =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0= =B2 =D0=BF=D0=BE =D0=93=D0=9E=D0=97 13. =D0=93=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0= =BD=D0=BD=D1=8B=D0=B9 =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C = (=D0=BD=D0=B0=D0=B4=D0=B7=D0=BE=D1=80) =D0=B2 = =D1=81=D1=84=D0=B5=D1=80=D0=B5 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80= =D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE = =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B0. 14. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5 =D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D0= =B0 =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0= =B0=D0=BD=D0=B8=D1=8F =D0=BD=D0=B0 =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1= =86=D0=B8=D1=8E =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0= =BE =D0=BD=D0=B0=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F. 15. =D0=9F=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA = =D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F = =D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE = =D1=83=D1=87=D0=B5=D1=82=D0=B0 =D0=B7=D0=B0=D1=82=D1=80=D0=B0=D1=82 = =D0=B8 =D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0=D1=82=D0=BE=D0=B2= =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=BE=D0=B2=D0=BE-=D1=85=D0=BE=D0=B7= =D1=8F=D0=B9=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9=20 =D0=B4=D0=B5=D1=8F=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D0=B8= =D0=B2 =D1=81=D1=84=D0=B5=D1=80=D0=B5 =D0=93=D0=9E=D0=97. 16. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5 =D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D0=BC=D0= =BE=D1=87=D0=B8=D1=8F =D0=A4=D0=90=D0=A1 = =D0=A0=D0=BE=D1=81=D1=81=D0=B8=D0=B8 =D0=BF=D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8E =D0=B2 = =D1=81=D1=84=D0=B5=D1=80=D0=B5 =D0=93=D0=9E=D0=97, =D0=B0 = =D1=82=D0=B0=D0=BA=D0=B6=D0=B5 =D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80= =D0=B0=D1=86=D0=B8=D0=B8 =D1=86=D0=B5=D0=BD =D0=BD=D0=B0=20 =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D1=8E, = =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5=D0=BC=D1=83=D1=8E = =D0=BF=D0=BE =D0=93=D0=9E=D0=97. 17. =D0=90=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0= =B8=D0=B2=D0=BD=D0=B0=D1=8F =D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0= =B2=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D1=8C =D0=B2 = =D0=9A=D0=BE=D0=B4=D0=B5=D0=BA=D1=81=D0=B5 =D0=BE=D0=B1 = =D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=B8=D0= =B2=D0=BD=D1=8B=D1=85 =D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BD=D0=B0=D1=80=D1= =83=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=D1=85 =D0=B2 =D0=A0=D0=A4:=20 =D0=B2=D0=B8=D0=B4=D1=8B =D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BD=D0=B0=D1=80= =D1=83=D1=88=D0=B5=D0=BD=D0=B8=D0=B9 =D0=B8 = =D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80 = =D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D1= =81=D1=82=D0=B8. =D0=9E=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B5=D0= =BD=D0=BD=D0=BE=D1=81=D1=82=D1=8C =D0=B7=D0=B0 = =D0=BD=D0=B5=D0=B4=D0=BE=D0=B1=D1=80=D0=BE=D1=81=D0=BE=D0=B2=D0=B5=D1=81=D1= =82=D0=BD=D0=BE=D0=B5=20 =D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=93=D0=9E=D0=97 =D0=B2 =D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81= =D1=82=D0=B2=D0=B8=D0=B8 =D1=81 =D1=82=D1=80=D0=B5=D0=B1=D0=BE=D0=B2=D0=B0= =D0=BD=D0=B8=D1=8F=D0=BC=D0=B8 =D0=9F=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE= =D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=9F=D1=80=D0=B0=D0=B2=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D1=82=D0=B2=D0= =B0 =E2=84=96 1211 =D0=BE=D1=82 22 =D0=BD=D0=BE=D1=8F=D0=B1=D1=80=D1=8F 2012 =D0=B3. =D0=A3=D1=87=D0=B0=D1=81=D1=82=D0=B8=D0=B5: 29 800 =D1=80=D1=83=D0=B1.=20 =D0=92 =D1=81=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C = =D0=B2=D1=85=D0=BE=D0=B4=D0=B8=D1=82 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B9 = =D0=BC=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=B0=D0=BB, = =D0=BE=D0=B1=D0=B5=D0=B4=D1=8B, =D0=BA=D0=BE=D1=84=D0=B5-=D0=BF=D0=B0=D1=83= =D0=B7=D1=8B, =D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82= =2E=20 =D0=98=D0=BD=D0=BE=D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=BD=D0=B8=D0=BC = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8=D0=BA=D0=B0=D0=BC = =D0=BF=D0=BE=D0=BC=D0=BE=D0=B3=D0=B0=D0=B5=D0=BC =D0=B2 = =D0=B1=D1=80=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8 = =D0=B3=D0=BE=D1=81=D1=82=D0=B8=D0=BD=D0=B8=D1=86=D1=8B. ------=_NextPart_000_00DD_01D1C0A1.5DDE1C40 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable
     
 
     
 


23 - 24 =D0= =B8=D1=8E=D0=BD=D1=8F  |  =D0=B3. = =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D0=B0  | c 10:00 =D0=B4=D0=BE 17:30 =  | =  =D0=90=D1=80=D1=82= =D0=B8=D0=BA=D1=83=D0=BB: 421

=D0=93=D0=9E=D0=A1=D0=A3=D0=94=D0=90=D0=A0=D0=A1=D0=A2=D0= =92=D0=95=D0=9D=D0=9D=D0=AB=D0=99 =D0=9E=D0=91=D0=9E=D0=A0=D0=9E=D0=9D=D0= =9D=D0=AB=D0=99 =D0=97=D0=90=D0=9A=D0=90=D0=97. 
=D0=9D=D0=9E=D0=92=D0=9E=D0= =95 =D0=92 =D0=9D=D0=9E=D0=A0=D0=9C=D0=90=D0=A2=D0=98=D0=92=D0=9D=D0=9E-=D0= =9F=D0=A0=D0=90=D0=92=D0=9E=D0=92=D0=9E=D0=9C = =D0=A0=D0=95=D0=93=D0=A3=D0=9B=D0=98=D0=A0=D0=9E=D0=92=D0=90=D0=9D=D0=98=D0= =98, =D0=90=D0=9A=D0=A2=D0=A3=D0=90=D0=9B=D0=AC=D0=9D=D0=AB=D0=95 
=D0=92=D0=9E=D0=9F=D0=A0=D0= =9E=D0=A1=D0=AB =D0=A6=D0=95=D0=9D=D0=9E=D0=9E=D0=91=D0=A0=D0=90=D0=97=D0= =9E=D0=92=D0=90=D0=9D=D0=98=D0=AF, =D0=9E=D0=A2=D0=92=D0=95=D0=A2=D0=A1=D0= =A2=D0=92=D0=95=D0=9D=D0=9D=D0=9E=D0=A1=D0=A2=D0=AC =D0=97=D0=90 = =D0=9D=D0=95=D0=98=D0=A1=D0=9F=D0=9E=D0=9B=D0=9D=D0=95=D0=9D=D0=98=D0=95<= SPAN class=3DApple-converted-space> 
=D0=9A=D0=9E=D0=9D=D0= =A2=D0=A0=D0=90=D0=9A=D0=A2=D0=9E=D0=92


=D0=9F=D1=80=D0=B8=D0=BD=D0=B8=D0=BC=D0=B0=D1=8E=D1=82 = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=B8=D0=B5 = =D1=81=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D1=81=D1=82=D1=8B = =D0=A3=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8F = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D0=BE=D0=B3=D0=BE =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B0 = =D0=A6=D0=B5=D0=BD=D1=82=D1=80=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B0=D0=BF=D0=BF=D0=B0=D1=80=D0=B0=D1=82=D0=B0 =D0=A4=D0=90=D0=A1 = =D0=A0=D0=BE=D1=81=D1=81=D0=B8=D0=B8, = =D0=BF=D1=80=D0=B5=D0=B4=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D1=82=D0=B5=D0=BB=D0= =B8 =D1=8D=D0=BA=D1=81=D0=BF=D0=B5=D1=80=D1=82=D0=BD=D1=8B=D1=85 
=D0=B3=D1=80=D1=83=D0=BF=D0= =BF =D0=9F=D1=80=D0=B0=D0=B2=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D1=82=D0= =B2=D0=B0 =D0=A0=D0=A4

 

=D0=9C=D0=B5=D1=81=D1=82=D0=BE = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F: =D0=BC. = =D0=91=D0=B0=D1=83=D0=BC=D0=B0=D0=BD=D1=81=D0=BA=D0=B0=D1=8F, = =D1=83=D0=BB. =D0=91=D0=B0=D1=83=D0=BC=D0=B0=D0=BD=D1=81=D0=BA=D0=B0=D1=8F= , =D0=B4.6, =D1=81=D1=82=D1=80.2, =D0=91.=D0=A6. "=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D1=8F = =D0=9F=D0=BB=D0=B0=D0=B7=D0=B0".

=D0=9F= =D0=BE=D0=B4=D1=80=D0=BE=D0=B1=D0=BD=D0=B0=D1=8F = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8F =D0=B8 = =D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D1=8C =D0=BF=D0=BE = =D0=BD=D0=BE=D0=BC=D0=B5=D1=80=D1=83 = =D1=82=D0=B5=D0=BB=D0=B5=D1=84=D0=BE=D0=BD=D0=B0:

 8 =D0=BA=D0=BE=D0=B4 =D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=B0 = =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D1=8B (495)  =D1=82=D0=B5=D0=BB.: 411 - 90 - 98.

=D0=92=D1=8B = =D0=BC=D0=BE=D0=B6=D0=B5=D1=82=D0=B5 = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=B2=D0=BE=D0=B2=D0=B0=D1=82=D1=8C = =D0=B2 =D0=BE=D0=B1=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B8 = =D0=BA=D0=B0=D0=BA =D0=BE=D1=82 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8= =D0=B8, =D1=82=D0=B0=D0=BA =D0=B8 =D0=BA=D0=B0=D0=BA = =D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=BE=D0=B5 = =D0=BB=D0=B8=D1=86=D0=BE.
(=D0=BF=D0=BE=D0=B6=D0=B0=D0=BB=D1=83=D0=B9=D1= =81=D1=82=D0=B0 =D0=BD=D0=B5 =D0=BE=D1=82=D0=B2=D0=B5=D1=87=D0=B0=D0=B9=D1= =82=D0=B5 =D0=BD=D0=B0 =D0=BE=D0=B1=D1=80=D0=B0=D1=82=D0=BD=D1=8B=D0=B9 = =D0=B0=D0=B4=D1=80=D0=B5=D1=81 =D1=8D=D0=BB.=D0=BF=D0=BE=D1=87=D1=82=D1=8B= )

 
     


=D0=9F=D0=A0=D0=9E=D0=93=D0=A0=D0=90=D0=9C=D0=9C=D0=90= :

1. =D0=98=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F =D0=B2 = =D0=B7=D0=B0=D0=BA=D0=BE=D0=BD=D0=BE=D0=B4=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1= =81=D1=82=D0=B2=D0=B5 =D0=BE =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1= =81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=BC = =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=BC = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B5 (=D0=93=D0=9E=D0=97), = =D0=9A=D0=BE=D0=B4=D0=B5=D0=BA=D1=81=D0=B5 =D0=BE=D0=B1 
    = =D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=B8=D0= =B2=D0=BD=D1=8B=D1=85 =D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BD=D0=B0=D1=80=D1= =83=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=D1=85 =D0=B2 =D0=A0=D0=A4 =D0=B8 = =D1=82.=D0=B4.

    =D0=9D=D0=BE=D1=80=D0=BC= =D1=8B =D0=B8 =D1=82=D1=80=D0=B5=D0=B1=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F= =D0=A4=D0=97 =E2=84=96 275-=D0=A4=D0=97 =D0=BE=D1=82 29 = =D0=B4=D0=B5=D0=BA=D0=B0=D0=B1=D1=80=D1=8F 2012 =D0=B3. "=D0=9E = =D0=93=D0=9E=D0=97";
    =D0=9D=D0=BE=D0=B2=D0=BE= =D0=B5 =D0=B2 =D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=B5 = =D0=93=D0=9E=D0=97 =D0=B2 =D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81= =D1=82=D0=B2=D0=B8=D0=B8 =D1=81 =D0=BF=D0=BE=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD= =D0=B8=D1=8F=D0=BC=D0=B8 =D0=A4=D0=97 =E2=84=96 159-=D0=A4=D0=97 = =D0=BE=D1=82 29 =D0=B8=D1=8E=D0=BD=D1=8F 2015 =D0=B3. 
   =  "=D0=9E = =D0=B2=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B8=D0=B8 = =D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9 =D0=B2 = =D0=A4=D0=97 "=D0=9E =D0=93=D0=9E=D0=97" =D0=B8 = =D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5 = =D0=B7=D0=B0=D0=BA=D0=BE=D0=BD=D0=BE=D0=B4=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0= =BD=D1=8B=D0=B5 =D0=B0=D0=BA=D1=82=D1=8B = =D0=A0=D0=A4".

2. =D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D0=B5 = =D0=BF=D1=80=D0=B0=D0=B2=D0=B0 =D0=B8 = =D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D0=BE=D0=B3=D0=BE =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D1=87=D0=B8=D0=BA=D0= =B0, =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F, 
    = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F.
3. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5= =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D0=B5 = =D0=BF=D1=80=D0=B0=D0=B2=D0=B0 =D0=B8 = =D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F. = =D0=9A=D0=BE=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8F = =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D0=BE=D0=B3=D0=BE 
    = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F.
4. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5= =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D0=B5 = =D0=BF=D1=80=D0=B0=D0=B2=D0=B0 =D0=B8 = =D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F.
5. =D0=A4=D0=BE=D1=80=D0=BC=D0=B8= =D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D0=BA=D0=BE=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8 = =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D1=8B=D0=BC=D0=B8 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F=D0=BC=D0= =B8 =D0=B8 =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1= =8F=D0=BC=D0=B8 =D0=93=D0=9E=D0=97. =D0=A3=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1= =8F 
   = ; =D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D0=B5=D0=BC=D1=8B=D1=85 = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0=B2 = =D0=BF=D0=BE =D0=93=D0=9E=D0=97.

6. =D0=9E=D0=B1=D0=B5=D1=81=D0=BF=D0=B5=D1=87=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BE=D0=BA = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8, = =D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D1=8F = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=BE=D0=B2 =D0=BD=D0=B0 = =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BA=D0=B8 = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8.

7. =D0=97=D0=B0=D0=BA=D0=BB=D1=8E= =D1=87=D0=B5=D0=BD=D0=B8=D0=B5 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80= =D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=B0. = =D0=92=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=B8=D0=B4=D0=B5=D0=BD=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82=D0=BE=D1= =80=D0=B0 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0= =B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE 
    = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=B0.

8. =D0=9A=D0=BE=D0=BD=D1=82=D1=80= =D0=BE=D0=BB=D1=8C =D0=B7=D0=B0 =D0=BE=D0=B1=D0=B5=D1=81=D0=BF=D0=B5=D1=87= =D0=B5=D0=BD=D0=B8=D0=B5=D0=BC =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA= =D1=82=D0=B0 =D0=B8 =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BE=D0=BA = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F=D0=BC=D0= =B8 =D0=B8/=D0=B8=D0=BB=D0=B8 =D0=B3=D0=BE=D0=BB=D0=BE=D0=B2=D0=BD=D1=8B=D0= =BC 
   = ; =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D0=B5=D0=BC= =2E

9. =D0=9E=D1=82=D0=BA=D0=B0=D0=B7= =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2 = =D0=BA=D0=BE=D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B8 = =D0=BE=D1=82 =D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D1=8F= =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0=B2 =D0=B2 = =D1=80=D0=B0=D0=BC=D0=BA=D0=B0=D1=85 = =D1=81=D0=BE=D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B6=D0=B4=D0=B0=D0=B5=D0=BC=D0= =BE=D0=B9 =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8. 
    = =D0=90=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC = =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=8B =D0=BF=D0=BE = =D1=83=D1=80=D0=B5=D0=B3=D1=83=D0=BB=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0= =B8=D1=8E =D1=80=D0=B0=D0=B7=D0=BD=D0=BE=D0=B3=D0=BB=D0=B0=D1=81=D0=B8=D0= =B9; =D0=A0=D0=B5=D0=B6=D0=B8=D0=BC =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0= =B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F = =D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE = =D1=81=D1=87=D0=B5=D1=82=D0=B0 =D0=B8 
    = =D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82=D1=8B =D0=BD=D0=B0 = =D1=81=D0=BE=D0=B2=D0=B5=D1=80=D1=88=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B9; = =D0=9A=D1=80=D0=B8=D1=82=D0=B5=D1=80=D0=B8=D0=B8 = =D0=BE=D0=BF=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D0=B9, = =D0=BF=D1=80=D0=B8=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2=D0=BB=D0=B8=D0= =B2=D0=B0=D0=B5=D0=BC=D1=8B=D1=85 =D0=B2 = =D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8 = =D1=81 
  &n= bsp; =D0=A4=D0=B5=D0=B4=D0=B5=D1=80=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=BC = =D0=B7=D0=B0=D0=BA=D0=BE=D0=BD=D0=BE=D0=BC =C2=AB=D0=9E = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D0=BE=D0=BC =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=BC = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B5=C2=BB =D0=B8 = =D1=82.=D0=B4.

10. =D0=A3=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1=8F = =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0= =BD=D1=8B=D1=85 =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0= =B2, =D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=B0=D0=B2=D0=BB=D0=B8=D0=B2=D0=B0=D1= =8E=D1=89=D0=B8=D0=B5 =D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80 = =D0=BF=D1=80=D0=B8=D0=B1=D1=8B=D0=BB=D0=B8 =D0=B8 (=D0=B8=D0=BB=D0=B8) = =D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA 
    &n= bsp; =D0=BA=D0=BE=D0=BC=D0=BF=D0=B5=D0=BD=D1=81=D0=B0=D1=86=D0=B8=D0=B8 = =D0=BF=D0=BE=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=BD=D1=8B=D1=85 = =D0=B7=D0=B0 =D1=81=D1=87=D0=B5=D1=82 = =D1=81=D0=BE=D0=B1=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D1=8B=D1=85 = =D1=81=D1=80=D0=B5=D0=B4=D1=81=D1=82=D0=B2 = =D1=80=D0=B0=D1=81=D1=85=D0=BE=D0=B4=D0=BE=D0=B2 =D0=BD=D0=B0 = =D1=84=D0=BE=D1=80=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D0=B7=D0=B0=D0=BF=D0=B0=D1=81=D0=B0 
    &n= bsp; =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D0=B8, = =D1=81=D1=8B=D1=80=D1=8C=D1=8F, =D0=BC=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=B0= =D0=BB=D0=BE=D0=B2, =D0=BF=D0=BE=D0=BB=D1=83=D1=84=D0=B0=D0=B1=D1=80=D0=B8= =D0=BA=D0=B0=D1=82=D0=BE=D0=B2, =D0=BA=D0=BE=D0=BC=D0=BF=D0=BB=D0=B5=D0=BA= =D1=82=D1=83=D1=8E=D1=89=D0=B8=D1=85 = =D0=B8=D0=B7=D0=B4=D0=B5=D0=BB=D0=B8=D0=B9, = =D0=BD=D0=B5=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=D0=BE=D0=B3=D0=BE = =D0=B4=D0=BB=D1=8F 
&n= bsp;     =D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0= =BD=D0=B8=D1=8F =D0=93=D0=9E=D0=97;

11. =D0=98=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=B8 = =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0= =B8=D1=8F =D1=80=D0=B0=D0=B1=D0=BE=D1=82 =D0=BF=D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=B0=D0=BC, = =D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=BD=D1=8B=D0=BC = =D1=81 =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8F= =D0=BC=D0=B8 =D0=B8 
&= nbsp;     =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D1=87=D0=B8=D0= =BA=D0=B0=D0=BC=D0=B8.

12. =D0= =91=D0=B0=D0=BD=D0=BA=D0=BE=D0=B2=D1=81=D0=BA=D0=BE=D0=B5 = =D1=81=D0=BE=D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B6=D0=B4=D0=B5=D0=BD=D0=B8=D0= =B5 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0= =BD=D0=BD=D0=BE=D0=B3=D0=BE =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1= =82=D0=B0 =D0=B8 =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=BA=D1=82=D0=BE=D0= =B2 =D0=BF=D0=BE =D0=93=D0=9E=D0=97

13. =D0=93=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80=D1=81=D1=82=D0=B2=D0=B5=D0=BD= =D0=BD=D1=8B=D0=B9 =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C = (=D0=BD=D0=B0=D0=B4=D0=B7=D0=BE=D1=80) =D0=B2 = =D1=81=D1=84=D0=B5=D1=80=D0=B5 =D0=B3=D0=BE=D1=81=D1=83=D0=B4=D0=B0=D1=80= =D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE = =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE = =D0=B7=D0=B0=D0=BA=D0=B0=D0=B7=D0=B0.

14. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5 =D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D0=B0= =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0= =D0=BD=D0=B8=D1=8F =D0=BD=D0=B0 =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86= =D0=B8=D1=8E =D0=BE=D0=B1=D0=BE=D1=80=D0=BE=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE= =D0=BD=D0=B0=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D1=8F.

15.
 =D0=9F=D0=BE=D1=80=D1=8F=D0=B4= =D0=BE=D0=BA =D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F = =D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE = =D1=83=D1=87=D0=B5=D1=82=D0=B0 =D0=B7=D0=B0=D1=82=D1=80=D0=B0=D1=82 = =D0=B8 =D1=80=D0=B5=D0=B7=D1=83=D0=BB=D1=8C=D1=82=D0=B0=D1=82=D0=BE=D0=B2= =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=BE=D0=B2=D0=BE-=D1=85=D0=BE=D0=B7= =D1=8F=D0=B9=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9 
    &n= bsp; =D0=B4=D0=B5=D1=8F=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1=82=D0= =B8 =D0=B2 =D1=81=D1=84=D0=B5=D1=80=D0=B5 = =D0=93=D0=9E=D0=97.

16. =D0=9D=D0=BE=D0=B2=D1=8B=D0=B5 =D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D0=BC=D0=BE= =D1=87=D0=B8=D1=8F =D0=A4=D0=90=D0=A1 = =D0=A0=D0=BE=D1=81=D1=81=D0=B8=D0=B8 =D0=BF=D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8E =D0=B2 = =D1=81=D1=84=D0=B5=D1=80=D0=B5 =D0=93=D0=9E=D0=97, =D0=B0 = =D1=82=D0=B0=D0=BA=D0=B6=D0=B5 =D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80= =D0=B0=D1=86=D0=B8=D0=B8 =D1=86=D0=B5=D0=BD =D0=BD=D0=B0 
    &n= bsp; =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=86=D0=B8=D1=8E, = =D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D1=8F=D0=B5=D0=BC=D1=83=D1=8E = =D0=BF=D0=BE =D0=93=D0=9E=D0=97.

17. =D0=90=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=B8= =D0=B2=D0=BD=D0=B0=D1=8F =D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2= =D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D1=8C =D0=B2 = =D0=9A=D0=BE=D0=B4=D0=B5=D0=BA=D1=81=D0=B5 =D0=BE=D0=B1 = =D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=82=D0=B8=D0= =B2=D0=BD=D1=8B=D1=85 =D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BD=D0=B0=D1=80=D1= =83=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=D1=85 =D0=B2 =D0=A0=D0=A4: 
    &n= bsp; =D0=B2=D0=B8=D0=B4=D1=8B =D0=BF=D1=80=D0=B0=D0=B2=D0=BE=D0=BD=D0=B0=D1= =80=D1=83=D1=88=D0=B5=D0=BD=D0=B8=D0=B9 =D0=B8 = =D1=80=D0=B0=D0=B7=D0=BC=D0=B5=D1=80 = =D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D1= =81=D1=82=D0=B8. =D0=9E=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B5=D0= =BD=D0=BD=D0=BE=D1=81=D1=82=D1=8C =D0=B7=D0=B0 = =D0=BD=D0=B5=D0=B4=D0=BE=D0=B1=D1=80=D0=BE=D1=81=D0=BE=D0=B2=D0=B5=D1=81=D1= =82=D0=BD=D0=BE=D0=B5       =D0=B2=D1=8B=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5= =D0=BD=D0=B8=D0=B5 =D0=93=D0=9E=D0=97 =D0=B2 = =D1=81=D0=BE=D0=BE=D1=82=D0=B2=D0=B5=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8 = =D1=81 =D1=82=D1=80=D0=B5=D0=B1=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=D0=BC= =D0=B8 =D0=9F=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5=D0=BD= =D0=B8=D1=8F =D0=9F=D1=80=D0=B0=D0=B2=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D1=81= =D1=82=D0=B2=D0=B0 =E2=84=96 1211 =D0=BE=D1=82 = 22
      = =D0=BD=D0=BE=D1=8F=D0=B1=D1=80=D1=8F 2012 =D0=B3.

   =D0=A3=D1=87=D0=B0=D1=81=D1=82=D0=B8=D0=B5:<= SPAN class=3DApple-converted-space> 29 800 = =D1=80=D1=83=D0=B1. <= BR>   =D0=92 =D1=81=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1= =8C =D0=B2=D1=85=D0=BE=D0=B4=D0=B8=D1=82 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B9 = =D0=BC=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=B0=D0=BB, = =D0=BE=D0=B1=D0=B5=D0=B4=D1=8B, =D0=BA=D0=BE=D1=84=D0=B5-=D0=BF=D0=B0=D1=83= =D0=B7=D1=8B, =D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82= =2E 
   = =D0=98=D0=BD=D0=BE=D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=BD=D0=B8=D0=BC = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8=D0=BA=D0=B0=D0=BC = =D0=BF=D0=BE=D0=BC=D0=BE=D0=B3=D0=B0=D0=B5=D0=BC =D0=B2 = =D0=B1=D1=80=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8 = =D0=B3=D0=BE=D1=81=D1=82=D0=B8=D0=BD=D0=B8=D1=86=D1=8B.

 
     
= ------=_NextPart_000_00DD_01D1C0A1.5DDE1C40-- From wagi@monom.org Tue Jun 7 02:51:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5D0217CA0 for ; Tue, 7 Jun 2016 02:51:44 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2DF06304043 for ; Tue, 7 Jun 2016 00:51:40 -0700 (PDT) X-ASG-Debug-ID: 1465285895-04cbb03569bce9b0001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id itoCgL5bFFycl45i (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 07 Jun 2016 00:51:36 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id 981F6194072A; Tue, 7 Jun 2016 09:51:34 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 632651940118; Tue, 7 Jun 2016 09:51:34 +0200 (CEST) Subject: Re: crash in xfs in current To: Christoph Hellwig , Eric Sandeen , reinoudkoornstra@gmail.com X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> Cc: xfs@oss.sgi.com, viro@zeniv.linux.org.uk From: Daniel Wagner Message-ID: Date: Tue, 7 Jun 2016 09:51:34 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <20160607062717.GA30022@infradead.org> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1465285896 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 372 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30238 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header > Given that 4.7-rc1 comes with the new shared locks for lookups, and > there are very little other changes I wonder if there is any relation > It would be good if Reinoud and/or Daniel can confirm that Linux 4.6 > is ok. I try to reproduce it on 4.6. My steps do not always trigger the crash. So I can't be really sure if 4.6 doesn't show it, it does not happen. From reinoudkoornstra@gmail.com Tue Jun 7 03:09:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id AA7AA7CA1 for ; Tue, 7 Jun 2016 03:09:56 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0F76AAC004 for ; Tue, 7 Jun 2016 01:09:55 -0700 (PDT) X-ASG-Debug-ID: 1465286990-04cb6c2dbbb97360001-NocioJ Received: from mail-qk0-f170.google.com (mail-qk0-f170.google.com [209.85.220.170]) by cuda.sgi.com with ESMTP id NxqjdGMIZdk82WQq (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 01:09:50 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qk0-f170.google.com[209.85.220.170] X-Barracuda-Apparent-Source-IP: 209.85.220.170 Received: by mail-qk0-f170.google.com with SMTP id p22so37272360qka.2 for ; Tue, 07 Jun 2016 01:09:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=aU1+xmWpoCRgF/M8jB4t3tLoOXYNqWZYUrI3RsBLNSo=; b=do/uAsvwy/j52UPR55nk11VEOpVxv9pg+Wbq8noWMf7mDJ93wQgnIYVarVTRxwzzvI NIQnrN0632SbzRsEkSVb3fx/4hFrYR2u/7pjTNOAUaBhk41EXT8cypZsdwtC4f8Xjt7p dL9slhtNo33zOFYSf46i3nzeZLoso3johoz1Z2/gVO/qtKO1fGrSZ0WQtenKttuOzfO2 FkHHEkE/xCHLkCgz6/0L39p2jRW0i+1r847z6slhtTTXavYnsgAZ9kEEz68H7i0fh1mG dZz5FeVdq92k2yciG3ruaLQEoijZH5CJXwXvykGqRR9A4RO6eAB+EVGv7qHcBG2BurOU /hdg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=aU1+xmWpoCRgF/M8jB4t3tLoOXYNqWZYUrI3RsBLNSo=; b=gVADd3I2N4488mPKfPZVO8KspIEihPSlaHZ26fIVA9kdJZjD2dglPyyJ5MPbah9mW5 NHxrJaNpDsU+LTVUyDHTSBVlZQBxeLZ5UPYrhv0dkKdRLyfCiKomOMsQl/AWAFuEJ0LX 3FKeG6xJ7gdRAHgEyE3I6tObKCuX6DIpPtLwagXbPK1t8ySioNqapeYjV8sDLnWA/qhz ODf0RS6q9rzAf+xTryaNhdd0Cg4PDRC0bnQ/6yTc/9t/sy+/qYC2/E29PRtVWYBVnYIZ 4QHp1OvjtwV1zou3n2kVZNxsN6al3OlDpApmvh45QQ6LqI0MMIMYz63GyGa14dzByCkx ekWg== X-Gm-Message-State: ALyK8tKc4ZIO7h3rbIbCsX3EvC2tRSkBNNZDuesYAycN3ZKnq4q4kUSu6hWoqF8y+hrP65+zTySRjbsWOL3dSw== X-Received: by 10.55.171.75 with SMTP id u72mr20322031qke.114.1465286989919; Tue, 07 Jun 2016 01:09:49 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.8.16 with HTTP; Tue, 7 Jun 2016 01:09:49 -0700 (PDT) In-Reply-To: References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> From: Reinoud Koornstra Date: Tue, 7 Jun 2016 02:09:49 -0600 Message-ID: Subject: Re: crash in xfs in current To: Daniel Wagner X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Christoph Hellwig , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qk0-f170.google.com[209.85.220.170] X-Barracuda-Start-Time: 1465286990 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 851 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30238 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Tue, Jun 7, 2016 at 1:51 AM, Daniel Wagner wrote: >> Given that 4.7-rc1 comes with the new shared locks for lookups, and >> there are very little other changes I wonder if there is any relation >> It would be good if Reinoud and/or Daniel can confirm that Linux 4.6 >> is ok. > > I try to reproduce it on 4.6. My steps do not always trigger the crash. > So I can't be really sure if 4.6 doesn't show it, it does not happen. I have never been able to trigger this in 4.6 and it's my failsafe reboot (4.6.0). In 4.7-rc1 it's just a matter of time before I hit it. I do a lot of transactions, using git, extraction of tar.xz etc normally. I am normally able to trigger this by a move of a big directory. It gets stuck there, a kill -9 doesn't either. So 4.6 is my safehaven to any xfs operation. Thanks, Reinoud. From reinoudkoornstra@gmail.com Tue Jun 7 04:33:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C9DA77CA2 for ; Tue, 7 Jun 2016 04:33:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 99DB38F8037 for ; Tue, 7 Jun 2016 02:33:35 -0700 (PDT) X-ASG-Debug-ID: 1465292013-04cbb03569bd2ce0001-NocioJ Received: from mail-qg0-f49.google.com (mail-qg0-f49.google.com [209.85.192.49]) by cuda.sgi.com with ESMTP id 8FCHhBaXm0lLGMSw (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 02:33:33 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qg0-f49.google.com[209.85.192.49] X-Barracuda-Apparent-Source-IP: 209.85.192.49 Received: by mail-qg0-f49.google.com with SMTP id q32so55236149qgq.3 for ; Tue, 07 Jun 2016 02:33:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=A16Jv5nHKDnACKotxB46Km7GQ25hyKfbU1g5vh+Woos=; b=f4jXpBljtH+jV4RfJcyM8EPPv+meJImkKOcqYt/ZClYge5S3iyYddedwDYMalxXZhd re3+NyUYGVivftlI00XvOwT3xxqgWivy4m42Rm5xshtDnXzKbytHXccxbDR5F/7ZpQIY mf/Nv7yDGpRbBSyM9n0KoqZwlslRwNEraGlbWXeQd0NydI/oHA7ZjiU1DbYnlOgekzrN tZ7zPgMgUN4wcYG0Z0Cw3RL270FSiUU6tShGqV/CwaWG1KxoVH4FdSvy/P3K7gjurZ/d FxcplkBuIrFT/FaZ3TLulaqBBQ1fjjLisvc6l0W2dE6SrdhTJnJhtZRMiBZz9cmWNSW0 rroA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=A16Jv5nHKDnACKotxB46Km7GQ25hyKfbU1g5vh+Woos=; b=J2Q+1SZwxF5WKJMUI8A2dKw2Xy1IFWnQ9FI6QYDBgqWg2ILj2hsqN4eBPvgopvYmd4 SPQJwRzaPrId5GP8+NoI4pptTAhGPCrAI90Z2NdoHmkmNahq8Db/z6n7tfm7mvnAxp9n NfEVBIUrunrBM9r1j7ArUD9kEhl8em5tK4f1GT95ual6wZ5TqflIurEkniNO3rPR3kAt UG8MPd4Sdu21O3AmqOXcRz36N1lwFVy1S/5SKq+wlg0M0sr1B+Rc1Aw4pC0DF96hP9SH 6IT8Rjd205ezikllAdyaKSEm8B/rV5v3eFXho346Od5u3p0sWsaPjFkZumIWh5YDdqy1 NPfw== X-Gm-Message-State: ALyK8tL/Q8czahze3HqdGUVMJpsqZMOVwQuVlgECWtUCUhPigRHA9CN986MKhQWGv+DeVTgmk0ebufNPgNlT5w== X-Received: by 10.140.108.183 with SMTP id j52mr19543572qgf.90.1465292012995; Tue, 07 Jun 2016 02:33:32 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.8.16 with HTTP; Tue, 7 Jun 2016 02:33:32 -0700 (PDT) In-Reply-To: <20160607062717.GA30022@infradead.org> References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> From: Reinoud Koornstra Date: Tue, 7 Jun 2016 03:33:32 -0600 Message-ID: Subject: Re: crash in xfs in current To: Christoph Hellwig X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Eric Sandeen , xfs@oss.sgi.com, Daniel Wagner , viro@zeniv.linux.org.uk Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qg0-f49.google.com[209.85.192.49] X-Barracuda-Start-Time: 1465292013 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2173 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30240 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Tue, Jun 7, 2016 at 12:27 AM, Christoph Hellwig wrote: > On Mon, Jun 06, 2016 at 11:39:59PM -0500, Eric Sandeen wrote: >> xfs_dir2_leaf_lookup_int() only hits that ASSERT if it was given >> a name to rename, and failed to find the original. i.e. that should >> not happen. >> >> /* >> * Loop over all the entries with the right hash value >> * looking to match the name. >> */ >> >> >> >> >> >> ASSERT(args->op_flags & XFS_DA_OP_OKNOENT); >> /* >> * Here, we can only be doing a lookup (not a rename or remove). >> * If a case-insensitive match was found earlier, re-read the >> * appropriate data block if required and return it. >> */ >> >> A rename should never fail to find the original name. > > FYI, this looks very much the same like the Bug Daniel reported, which > I tried to help debugging in person over the weekend. His backtrace > points to cancelling a dirty transaction after xfs_dir_replace failed, > which most likely comes from the failing lookup, except that he probably > doen't have XFS_DEBUG enabled. In my case, it looks like that the lookup failed. First you try to find the xfs_buf, lbp if the pointer to that buffer. Then you try to find the leaf entry with the same hash value. Then you look over the entries with the hash value and look if the names match. Hopefully XFS_CMP_EXACT is returned. What I do NOT get is why this flag needs to be set: XFS_DA_OP_OKNOENT I see it being set in xfs_attr_{get, set, remove}, but I am not able to see that anywhere in the path of this function. In each of these xfs_attrs I see locks acquired and locked released, no problem, other than that it's assumed the you obtain the lock. If the beginning checks during the lock process don't work out you ASSERT. > > Given that 4.7-rc1 comes with the new shared locks for lookups, and > there are very little other changes I wonder if there is any relation > It would be good if Reinoud and/or Daniel can confirm that Linux 4.6 > is ok. From eflorac@intellique.com Tue Jun 7 05:51:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E4DFC7CA4 for ; Tue, 7 Jun 2016 05:51:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id B4DAF304048 for ; Tue, 7 Jun 2016 03:51:28 -0700 (PDT) X-ASG-Debug-ID: 1465296685-04cb6c2dbab9da90001-NocioJ Received: from mail1.g1.pair.com (mail1.g1.pair.com [66.39.3.162]) by cuda.sgi.com with ESMTP id lA8NsAP5BfRUE0Ml (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 07 Jun 2016 03:51:26 -0700 (PDT) X-Barracuda-Envelope-From: eflorac@intellique.com X-Barracuda-Effective-Source-IP: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Apparent-Source-IP: 66.39.3.162 Received: from localhost (localhost [127.0.0.1]) by mail1.g1.pair.com (Postfix) with SMTP id 80728547ADC for ; Tue, 7 Jun 2016 06:51:25 -0400 (EDT) Received: from harpe.intellique.com (labo.djinux.com [82.225.196.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail1.g1.pair.com (Postfix) with ESMTPSA id 28A05547B78 for ; Tue, 7 Jun 2016 06:51:25 -0400 (EDT) Date: Tue, 7 Jun 2016 12:51:27 +0200 From: Emmanuel Florac To: xfs@oss.sgi.com Subject: determining superblock version? Message-ID: <20160607125127.6dd23aef@harpe.intellique.com> X-ASG-Orig-Subj: determining superblock version? Organization: Intellique X-Mailer: Claws Mail 3.13.1 (GTK+ 2.24.30; i486-slackware-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Start-Time: 1465296686 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1458 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30241 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Hi all, as you know kernel prior to 3.16 won't support properly v5 superblocks. xfsprogs v 3.2.4 and higher defaults to v5 superblocks. This bit quite a lot of people a year ago or so, when some distributions shipped 3.2.4 xfsprogs with older kernels. Anyway, I was surprised to find no easy way to find out the superblock version of an xfs FS. The best I've come across is xfs_db /dev/this sb p versionnum = 0xb4a5 So I suppose that the 5 in the end means that the superblock is v5? Can anyone confirm please? The man page still pretends that the last number should be 1 to 4, which is confusing. Oh by the way I think the trick to create a v4 filesystem with mkfs.xfs higher than 3.2.4 ( mkfs.xfs -m crc=0,finobt=0 /dev/this ) should be in the FAQ, with a line like this: Mounting the filesystem fails, and output from dmesg says "Version 5 superblock detected." What should I do? v5 superblocks require a kernel v3.16 of higher. If you need your xfs filesystem to be usable with older kernel, use the following options to mkfs.xfs : mkfs.xfs -m crc=0,finobt=0 /dev/this -- ------------------------------------------------------------------------ Emmanuel Florac | Direction technique | Intellique | | +33 1 78 94 84 02 ------------------------------------------------------------------------ From wagi@monom.org Tue Jun 7 05:52:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8786D7CA7 for ; Tue, 7 Jun 2016 05:52:44 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 49BF0304032 for ; Tue, 7 Jun 2016 03:52:44 -0700 (PDT) X-ASG-Debug-ID: 1465296760-04bdf05ad4bbbc80001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id mJsW6AtMODVvJMKv (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 07 Jun 2016 03:52:42 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id A8D11194072A; Tue, 7 Jun 2016 12:52:39 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 73D391940118; Tue, 7 Jun 2016 12:52:39 +0200 (CEST) Subject: Re: crash in xfs in current To: Reinoud Koornstra X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> Cc: Christoph Hellwig , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk From: Daniel Wagner Message-ID: <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> Date: Tue, 7 Jun 2016 12:52:39 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1465296761 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 503 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30241 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header >> I try to reproduce it on 4.6. My steps do not always trigger the crash. >> So I can't be really sure if 4.6 doesn't show it, it does not happen. > > I have never been able to trigger this in 4.6 and it's my failsafe > reboot (4.6.0). > In 4.7-rc1 it's just a matter of time before I hit it. > I do a lot of transactions, using git, extraction of tar.xz etc normally. This rings a bell. I though the lockperf tests triggered it. Before I compiled a new kernel I did a 'git checkout' step. From reinoudkoornstra@gmail.com Tue Jun 7 06:07:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,HTML_MESSAGE, T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E82297CAF for ; Tue, 7 Jun 2016 06:07:14 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id AD47E304032 for ; Tue, 7 Jun 2016 04:07:11 -0700 (PDT) X-ASG-Debug-ID: 1465297629-04cb6c2dbab9dfa0001-NocioJ Received: from mail-qt0-f177.google.com (mail-qt0-f177.google.com [209.85.216.177]) by cuda.sgi.com with ESMTP id SzuvHV64DJzehps8 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 04:07:09 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qt0-f177.google.com[209.85.216.177] X-Barracuda-Apparent-Source-IP: 209.85.216.177 Received: by mail-qt0-f177.google.com with SMTP id 23so20644098qtq.0 for ; Tue, 07 Jun 2016 04:07:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc; bh=rZdnAFMBnXXTqxT3Z3pumVbot0LMkmmaixir7A6Ak0w=; b=hqioXDBuI9rlJ6WBZtAePBTxDWo+hSfOwHMEnEv7OeaOjyg/RFyNXxaXAvDCUPwldx WOj3mc53sMWQ9tGnIW5tOUIWT8P/VlIQbEapXXPPZGQLoiLFm1vFMV9yd102s7bJ3HEd vPMKKqUY1V1ij6XWIU0yvz8B5aPYaOxf9vsWf93wlxWkYjm94gKWwDExgS8aK3dgwYMN jIIE7PFM7HwREsodrQkSnz+WGA+tgkaLL6q7sM6XED4AnpA7il74/9tLDXI/itg3mQrr 8XID5PUtwwX4fRzeaVkIliegMpmz1bmbRco54iC6v4gwLLrKUOm341317Wri1BuZbOTo kd2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc; bh=rZdnAFMBnXXTqxT3Z3pumVbot0LMkmmaixir7A6Ak0w=; b=VUm3hwGahUla8znoSxxY96VeJY4+WCWiholtybnIbHsoYRVYaTOGEKy5ao7b4nCnYc J2/ex23lN7G2w0Sj3m8pDSrx6etPvJ81hBZd9Aiut9B7iiKGcBvQhPimfTA+QY2d0tBg kP09jUHsM/Bzydz7VkxzEkPx6A70njuYXhceTvBuNu1qK9vpzfFJQ/Qp6pFb1gdBtHcC E9cJqk82w5t0Bwz93eHWug+R7CeqOwAbe43GFrdGskD4iyZj/hGj0kiF7mxQsTKKj930 V5sJsYX3qBPcHN5T48IcrXQRhSsH15XHMXrjxBVrPCWabfJn10r8plcCguXp5i3O/QiE JE6Q== X-Gm-Message-State: ALyK8tKf0wyf1Db50ZhV/pAstcN7p/+G+1C25QFtzapMpgUhLyd90W/lgrIiUw0oD0lOqFC35fwifjnjkL8+Dw== MIME-Version: 1.0 X-Received: by 10.237.56.225 with SMTP id k88mr19275108qte.86.1465297628834; Tue, 07 Jun 2016 04:07:08 -0700 (PDT) Received: by 10.55.8.16 with HTTP; Tue, 7 Jun 2016 04:07:08 -0700 (PDT) Received: by 10.55.8.16 with HTTP; Tue, 7 Jun 2016 04:07:08 -0700 (PDT) In-Reply-To: <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> Date: Tue, 7 Jun 2016 05:07:08 -0600 Message-ID: Subject: Re: crash in xfs in current From: Reinoud Koornstra X-ASG-Orig-Subj: Re: crash in xfs in current To: Daniel Wagner Cc: xfs@oss.sgi.com, viro@zeniv.linux.org.uk, Eric Sandeen , Christoph Hellwig Content-Type: multipart/alternative; boundary=001a113fe944a835110534ae3030 X-Barracuda-Connect: mail-qt0-f177.google.com[209.85.216.177] X-Barracuda-Start-Time: 1465297629 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3265 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30241 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --001a113fe944a835110534ae3030 Content-Type: text/plain; charset=UTF-8 On Jun 7, 2016 4:52 AM, "Daniel Wagner" wrote: > > >> I try to reproduce it on 4.6. My steps do not always trigger the crash. > >> So I can't be really sure if 4.6 doesn't show it, it does not happen. > > > > I have never been able to trigger this in 4.6 and it's my failsafe > > reboot (4.6.0). > > In 4.7-rc1 it's just a matter of time before I hit it. > > I do a lot of transactions, using git, extraction of tar.xz etc normally. > > This rings a bell. I though the lockperf tests triggered it. Before I > compiled a new kernel I did a 'git checkout' step. Yeah, could well be. During big git operations I get into this and while I was trying to compile GCC 6.1.0 and I was moving mpfc dir into gcc/mpfc for example. The move never completed. I do use git to get the latest kernel sources for wireless testing. With the 4.6.0 I didn't hit problems. Ever since I started using 4.7 I kept crashing on asserts in xfs. :) As I hit this frequently I can instrument. I did write some instrumentation to display the args flags before the assert, but from Eric's work, it doesn't seem these are important at all as it might be a locking issue. I will say that it sounds most likely a locking issue to me , because sometimes I just hang in an fs operation and it never completes. Even trying to kill the mv operation doesn't work. I can try to reproduce tomorrow and either reach the assert or get stuck in a lock in which case trace-cmd might help. Thanks, Reinoud. --001a113fe944a835110534ae3030 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable


On Jun 7, 2016 4:52 AM, "Daniel Wagner" <wagi@monom.org> wrote:
>
> >> I try to reproduce it on 4.6. My steps do not always trigger = the crash.
> >> So I can't be really sure if 4.6 doesn't show it, it = does not happen.
> >
> > I have never been able to trigger this in 4.6 and it's my fai= lsafe
> > reboot (4.6.0).
> > In 4.7-rc1 it's just a matter of time before I hit it.
> > I do a lot of transactions, using git, extraction of tar.xz etc n= ormally.
>
> This rings a bell. I though the lockperf tests triggered it. Before I<= br> > compiled a new kernel I did a 'git checkout' step.

Yeah, could well be. During big git operations I get into th= is and while I was trying to compile GCC 6.1.0 and I was moving mpfc dir in= to gcc/mpfc for example. The move never completed. I do use git to get the = latest kernel sources for wireless testing. With the 4.6.0 I didn't hit= problems. Ever since I started using 4.7 I kept crashing on asserts in xfs= . :) As I hit this frequently I can instrument. I did write some instrument= ation to display the args flags before the assert, but from Eric's work= , it doesn't seem these are important at all as it might be a locking i= ssue. I will say that it sounds most likely a locking issue to me , because= sometimes I just hang in an fs operation and it never completes. Even tryi= ng to kill the mv operation doesn't work. I can try to reproduce tomorr= ow and either reach the assert or get stuck in a lock in which case trace-c= md might help.
Thanks,

Reinoud.

--001a113fe944a835110534ae3030-- From e_ogly@inbox.ru Tue Jun 7 08:11:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BC1DF7CA0 for ; Tue, 7 Jun 2016 08:11:31 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6CA218F8035 for ; Tue, 7 Jun 2016 06:11:28 -0700 (PDT) X-ASG-Debug-ID: 1465305079-04bdf05ad6bc3630001-NocioJ Received: from mxs.mail.ru (72.ip-92-222-15.eu [92.222.15.72]) by cuda.sgi.com with ESMTP id 8AONgRm62jaq4vUQ for ; Tue, 07 Jun 2016 06:11:22 -0700 (PDT) X-Barracuda-Envelope-From: e_ogly@inbox.ru X-Barracuda-Effective-Source-IP: 72.ip-92-222-15.eu[92.222.15.72] X-Barracuda-Apparent-Source-IP: 92.222.15.72 Message-ID: <58FED9E7B78ABE52F01FB93A9B87DC56@YEZVQJEOGU> From: "=?utf-8?B?0JIg0K7RgNC40LTQuNGH0LXRgdC60LjQuSDQtNC10L/QsNGA0YLQsNC80LXQvdGC?=" To: Subject: =?utf-8?B?0JrQvtC90YLRgNC+0LvQuNGA0YPQtdC80YvQtSDRgdC00LXQu9C60Lgg0Lgg0LLQt9Cw0LjQvNC+0LfQsNCy0LjRgdC40LzRi9C1INC70LjRhtCwOiAyMjct0KTQlw==?= Date: Tue, 7 Jun 2016 16:11:21 +0300 X-ASG-Orig-Subj: =?utf-8?B?0JrQvtC90YLRgNC+0LvQuNGA0YPQtdC80YvQtSDRgdC00LXQu9C60Lgg0Lgg0LLQt9Cw0LjQvNC+0LfQsNCy0LjRgdC40LzRi9C1INC70LjRhtCwOiAyMjct0KTQlw==?= MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_0039_01D1C0D7.3B490D80" X-Priority: 3 X-MSMail-Priority: Normal Importance: Normal X-Mailer: Microsoft Windows Live Mail 15.4.3555.308 X-MimeOLE: Produced By Microsoft MimeOLE V15.4.3555.308 X-Barracuda-Connect: 72.ip-92-222-15.eu[92.222.15.72] X-Barracuda-Start-Time: 1465305079 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 34944 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30243 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message MIME. ------=_NextPart_000_0039_01D1C0D7.3B490D80 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable =20 =20 20 - 21 =D0=B8=D1=8E=D0=BD=D1=8F | =D0=B3. = =D0=A1=D0=B0=D0=BD=D0=BA=D1=82 - = =D0=9F=D0=B5=D1=82=D0=B5=D1=80=D0=B1=D1=83=D1=80=D0=B3 = (=D0=BF=D1=80=D0=BE=D0=BC=D0=BE=D0=BA=D0=BE=D0=B4:434) = =D0=A2=D0=A0=D0=90=D0=9D=D0=A1=D0=A4=D0=95=D0=A0=D0=A2=D0=9D=D0=9E=D0=95 = =D0=A6=D0=95=D0=9D=D0=9E=D0=9E=D0=91=D0=A0=D0=90=D0=97=D0=9E=D0=92=D0=90=D0= =9D=D0=98=D0=95: =D0=9F=D0=95=D0=A0=D0=92=D0=AB=D0=95 = =D0=9F=D0=A0=D0=9E=D0=92=D0=95=D0=A0=D0=9A=D0=98 =D0=98 = =D0=9F=D0=A0=D0=98=D0=9C=D0=95=D0=A0=D0=AB = =D0=9F=D0=9E=D0=94=D0=93=D0=9E=D0=A2=D0=9E=D0=92=D0=9A=D0=98 = =D0=94=D0=9E=D0=9A=D0=A3=D0=9C=D0=95=D0=9D=D0=A2=D0=90=D0=A6=D0=98=D0=98 =D0=97=D0=B0=D0=BD=D1=8F=D1=82=D0=B8=D0=B5 = =D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=D1=81=D1=8F =D1=81 = 10:00 =D0=B4=D0=BE 17:30 =20 = =D0=9C=D0=B5=D1=80=D0=BE=D0=BF=D1=80=D0=B8=D1=8F=D1=82=D0=B8=D0=B5 = =D1=81=D0=BE=D1=81=D1=82=D0=BE=D0=B8=D1=82=D1=81=D1=8F: = =D0=B1=D0=B8=D0=B7=D0=BD=D0=B5=D1=81-=D1=86=D0=B5=D0=BD=D1=82=D1=80 = =E2=80=9C=D0=9C=D0=B0=D1=80=D0=B8=D0=B8=D0=BD=D1=81=D0=BA=D0=B8=D0=B9=E2=80= =9D, =D0=BD=D0=B0=D0=B1=D0=B5=D1=80=D0=B5=D0=B6=D0=BD=D0=B0=D1=8F = =D1=80=D0=B5=D0=BA=D0=B8 =D0=9C=D0=BE=D0=B9=D0=BA=D0=B8, =D0=B4. 58. =D0=A3=D0=B7=D0=BD=D0=B0=D1=82=D1=8C = =D0=B2=D1=81=D1=8E = =D0=BF=D0=BE=D0=B4=D1=80=D0=BE=D0=B1=D0=BD=D1=83=D1=8E = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8E =D0=B8 = =D0=B7=D0=B0=D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80=D0=B8=D1=80=D0=BE=D0= =B2=D0=B0=D1=82=D1=8C=D1=81=D1=8F =D0=92=D1=8B = =D0=BC=D0=BE=D0=B6=D0=B5=D1=82=D0=B5 =D0=BF=D0=BE = =D0=BD=D0=BE=D0=BC=D0=B5=D1=80=D1=83:=20 8 =D0=BA=D0=BE=D0=B4 = =D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=B0 (812) =D1=82=D0=B5=D0=BB.: 346 - = 54 - 40 = (=D0=BC=D0=BD=D0=BE=D0=B3=D0=BE=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD= =D1=8B=D0=B9) = =20 =D0=94=D0=BB=D1=8F: = =D1=80=D1=83=D0=BA=D0=BE=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D0=B5=D0= =B9 = =D0=BF=D0=BE=D0=B4=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0= =B9 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B9, = =D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5 = =D0=B1=D1=83=D0=B4=D1=83=D1=82 = =D0=B7=D0=B0=D0=BD=D0=B8=D0=BC=D0=B0=D1=82=D1=8C=D1=81=D1=8F = =D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D0=B0=D0=BC=D0=B8=20 = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F, = =D0=B1=D1=83=D1=85=D0=B3=D0=B0=D0=BB=D1=82=D0=B5=D1=80=D0=BE=D0=B2, = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D1=85 = =D1=81=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=B2,= =D1=81=D0=BE=D1=82=D1=80=D1=83=D0=B4=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2 = =D0=BF=D0=BB=D0=B0=D0=BD=D0=BE=D0=B2=D0=BE- = =D1=8D=D0=BA=D0=BE=D0=BD=D0=BE=D0=BC=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D1= =85 =D0=B8 =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=BE=D0=B2=D1=8B=D1=85 = =D1=81=D0=BB=D1=83=D0=B6=D0=B1. = =D0=9F=D1=80=D0=B5=D0=BF=D0=BE=D0=B4=D0=B0=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1= =8C - =D1=8D=D0=BA=D1=81=D0=BF=D0=B5=D1=80=D1=82 IBFS United, = =D1=8F=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=D1=81=D1=8F = =D0=BE=D0=B4=D0=BD=D0=B8=D0=BC=D0=B8 =D0=B8=D0=B7 = =D0=BB=D1=83=D1=87=D1=88=D0=B8=D1=85 = =D1=81=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=B2 = =D0=B2 =D0=BE=D0=B1=D0=BB=D0=B0=D1=81=D1=82=D0=B8=20 = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F =D0=B2 =D0=A0=D0=A4, =D0=B8 = =D1=81=D0=BC=D0=BE=D0=B6=D0=B5=D1=82 = =D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=B8=D1=82=D1=8C =D0=BD=D0=B0 = =D0=B2=D1=81=D0=B5 = =D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1= =8B=D0=B5 =D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D1=8B=20 = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2 = =D1=81=D0=B5=D0=BC=D0=B8=D0=BD=D0=B0=D1=80=D0=B0. =20 =20 = =D0=A1=D0=BE=D0=B4=D0=B5=D1=80=D0=B6=D0=B0=D0=BD=D0=B8=D0=B5: =20 =D0=91=D0=BB=D0=BE=D0=BA 1. = =D0=A2=D0=B5=D0=BE=D1=80=D0=B8=D1=8F = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F =D0=B2 =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D0=B0=D1=85 = =D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F = =D0=B4=D0=BB=D1=8F = =D0=BF=D1=80=D0=B8=D0=B7=D0=BD=D0=B0=D0=BD=D0=B8=D1=8F = =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D0=BC=D0=B8. =D0=9F=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D0=BA=D1=83=D0=BC = =D0=BF=D0=BE =D1=80=D0=B0=D1=81=D1=87=D0=B5=D1=82=D1=83 = =D0=BF=D0=BE=D1=80=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D1=85=20 = =D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8=D0=B9. =D0=A1=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8 =D1=81 = =D0=BB=D0=B8=D1=86=D0=B0=D0=BC=D0=B8, =D0=BD=D0=B5 = =D0=BF=D1=80=D0=B8=D0=B7=D0=BD=D0=B0=D0=B2=D0=B0=D0=B5=D0=BC=D1=8B=D0=BC=D0= =B8 = =D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0= =BC=D1=8B=D0=BC=D0=B8. =D0=92 =D0=BA=D0=B0=D0=BA=D0=BE=D0=BC = =D1=81=D0=BB=D1=83=D1=87=D0=B0=D0=B5 =D0=B5=D1=81=D1=82=D1=8C = =D1=80=D0=B8=D1=81=D0=BA=D0=B8? =D0=9C=D0=B5=D1=82=D0=BE=D0=B4=D1=8B = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F =D0=B8 = =D1=81=D0=BE=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D0=BE=D1=81=D1= =82=D1=8C =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA. = =D0=9C=D0=BE=D0=B6=D0=BD=D0=BE =D0=BB=D0=B8=20 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C = =D0=BE=D1=86=D0=B5=D0=BD=D0=BA=D1=83 =D0=B8 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B, =D0=BD=D0=B5 = =D0=BF=D1=80=D0=B5=D0=B4=D1=83=D1=81=D0=BC=D0=BE=D1=82=D1=80=D0=B5=D0=BD=D0= =BD=D1=8B=D0=B5 =D0=9D=D0=9A =D0=A0=D0=A4? = =D0=A1=D1=82=D0=B0=D1=82=D0=B8=D1=81=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0= =BE=D0=B5 = =D0=B8=D1=81=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D1=81=D0=BE=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D1=8B=D1=85 = =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B9. = =D0=A8=D0=B0=D0=B3=D0=B8 =D0=BF=D0=BE =D0=B5=D0=B3=D0=BE = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8E. = =D0=9F=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D0=BA=D1=83=D0=BC =D0=BF=D0=BE = =D1=80=D0=B0=D1=81=D1=87=D0=B5=D1=82=D1=83 = =D0=B8=D0=BD=D1=82=D0=B5=D1=80=D0=B2=D0=B0=D0=BB=D0=BE=D0=B2 = =D1=80=D1=8B=D0=BD=D0=BE=D1=87=D0=BD=D1=8B=D1=85 =D1=86=D0=B5=D0=BD = =D0=B8 = =D1=80=D0=B5=D0=BD=D1=82=D0=B0=D0=B1=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1= =82=D0=B8. =D0=9D=D0=B5=D1=8F=D1=81=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=9D=D0=9A =D0=A0=D0=A4 =D0=B8=20 = =D0=BC=D0=B5=D0=B6=D0=B4=D1=83=D0=BD=D0=B0=D1=80=D0=BE=D0=B4=D0=BD=D1=8B=D0= =B9 =D0=BE=D0=BF=D1=8B=D1=82.=20 =D0=A0=D0=B0=D1=81=D1=87=D0=B5=D1=82 = =D1=81=D0=BE=D0=B1=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9 = =D1=80=D0=B5=D0=BD=D1=82=D0=B0=D0=B1=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1= =82=D0=B8 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B8. = =D0=94=D0=BE=D1=81=D1=82=D0=B0=D1=82=D0=BE=D1=87=D0=BD=D0=BE = =D0=BB=D0=B8 =D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85 = =D0=B1=D1=83=D1=85=D0=B3=D0=B0=D0=BB=D1=82=D0=B5=D1=80=D1=81=D0=BA=D0=BE=D0= =B3=D0=BE=20 =D1=83=D1=87=D0=B5=D1=82=D0=B0? =D0=91=D0=BB=D0=BE=D0=BA 2. = =D0=9F=D0=BE=D0=B4=D1=85=D0=BE=D0=B4=D1=8B =D0=BA = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B5 = =D0=B7=D0=B0=D1=89=D0=B8=D1=82=D0=BD=D0=BE=D0=B9 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8 = =D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F = =D0=B4=D0=BB=D1=8F = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B8 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8 = =D0=BF=D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D0=BC =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B0=D0=BC. = =D0=9A=D0=BE=D0=B3=D0=B4=D0=B0=20 = =D1=86=D0=B5=D0=BB=D0=B5=D1=81=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BD=D0= =BE =D0=BD=D0=B5 =D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=B8=D1=82=D1=8C = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8E?= =20 = =D0=9E=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D0=B5 = =D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8, = =D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5 = =D0=B4=D0=BE=D0=BF=D1=83=D1=81=D1=82=D0=B8=D0=BB=D0=B8 = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=BF=D0=BB=D0=B0=D1=82=D0=B5=D0=BB=D1= =8C=D1=89=D0=B8=D0=BA=D0=B8 =D0=BF=D1=80=D0=B8 = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B5 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8 =D0=A1=D0=BB=D1=83=D1=87=D0=B0=D0=B8, = =D0=BA=D0=BE=D0=B3=D0=B4=D0=B0 = =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2 =D0=A2=D0=A6 = =D0=BD=D0=B5=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE: = =D1=81=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8 = =D1=81=20 = =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC = =D0=B8=D0=BD=D1=8B=D1=85 = =D0=BF=D0=BE=D0=B4=D1=85=D0=BE=D0=B4=D0=BE=D0=B2=20 = =D0=9F=D0=BE=D1=88=D0=B0=D0=B3=D0=BE=D0=B2=D0=BE=D0=B5 = =D1=80=D1=83=D0=BA=D0=BE=D0=B2=D0=BE=D0=B4=D1=81=D1=82=D0=B2=D0=BE = =D0=BF=D0=BE = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8E = =D0=B8=D1=81=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F = =D0=B2 =D0=A1=D0=9F=D0=90=D0=A0=D0=9A =D0=B8 = =D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=D0=B0 = =D0=90=D0=BB=D0=B3=D0=BE=D1=80=D0=B8=D1=82=D0=BC=D1=8B = =D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2 =D0=B4=D0=BB=D1=8F = =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA =D0=91=D0=BB=D0=BE=D0=BA 3. = =D0=9F=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D0=BA=D1=83=D0=BC =D0=BF=D0=BE = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B5 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8.= =D0=9F=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D1=8B = =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA. = =D0=94=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F = =D1=81 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0= =B5=D0=BC =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0 = =D1=81=D0=BE=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D1=8B=D1=85 = =D1=80=D1=8B=D0=BD=D0=BE=D1=87=D0=BD=D1=8B=D1=85 =D1=86=D0=B5=D0=BD = =D0=BD=D0=B0 = =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D0=B0=D1=85:=D1=8D=D0=BA=D1=81=D0=BF= =D0=BE=D1=80=D1=82=20 = =D0=B1=D0=B8=D1=80=D0=B6=D0=B5=D0=B2=D1=8B=D1=85 = =D1=82=D0=BE=D0=B2=D0=B0=D1=80=D0=BE=D0=B2 = (=D0=BD=D0=B5=D1=84=D1=82=D1=8C, = =D0=BC=D0=B5=D1=82=D0=B0=D0=BB=D0=BB=D1=8B, = =D1=83=D0=B4=D0=BE=D0=B1=D1=80=D0=B5=D0=BD=D0=B8=D1=8F, = =D1=81=D0=B5=D0=BB=D1=8C=D1=85=D0=BE=D0=B7=D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0= =BA=D1=86=D0=B8=D1=8F =D0=B8 =D1=82.=D0=BF.); = =D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20 =D1=82=D0=BE=D0=B2=D0=B0=D1=80=D0=BE=D0=B2 = =D0=B2 =D0=B0=D0=B4=D1=80=D0=B5=D1=81 = =D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0= =BC=D1=8B=D1=85 =D0=B8 =D1=82=D1=80=D0=B5=D1=82=D1=8C=D0=B8=D1=85 = =D0=BB=D0=B8=D1=86; = =D0=94=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F = =D1=81 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0= =B5=D0=BC =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2, = =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D1=85 = =D0=BD=D0=B0 =D0=B0=D0=BD=D0=B0=D0=BB=D0=B8=D0=B7=D0=B5 = =D1=80=D0=B5=D0=BD=D1=82=D0=B0=D0=B1=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1= =82=D0=B8 =D0=BD=D0=B0=20 = =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D0=B0=D1=85: = =D0=BF=D0=BE=D0=BA=D1=83=D0=BF=D0=BA=D0=B0 = =D1=83=D1=81=D0=BB=D1=83=D0=B3 =D1=83 = =D0=B7=D0=B0=D1=80=D1=83=D0=B1=D0=B5=D0=B6=D0=BD=D0=BE=D0=B9 = =D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0= =BC=D0=BE=D0=B9 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B8; = =D0=B4=D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80=D1=8B=20 = =D0=B0=D0=B3=D0=B5=D0=BD=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1= =8F =D0=B8 =D0=BA=D0=BE=D0=BC=D0=B8=D1=81=D1=81=D0=B8=D0=B8; = =D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F = =D1=82=D0=BE=D0=B2=D0=B0=D1=80=D0=BE=D0=B2 =D0=B2 = =D0=B0=D0=B4=D1=80=D0=B5=D1=81 = =D0=BF=D0=B5=D1=80=D0=B5=D0=BF=D1=80=D0=BE=D0=B4=D0=B0=D0=B2=D1=86=D0=B0.= =D0=91=D0=BB=D0=BE=D0=BA 4. = =D0=A3=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D1=85 =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B0=D1=85: = =D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1= =8F =D0=90=D0=BD=D0=B0=D0=BB=D0=B8=D0=B7 = =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D1=85 = =D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA =D0=BF=D1=80=D0=B8 = =D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9: = =D0=B8=D1=82=D0=BE=D0=B3=D0=B8 20 =D0=BD=D0=BE=D1=8F=D0=B1=D1=80=D1=8F = =D0=93=D1=80=D1=83=D0=BF=D0=BF=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8 = =D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=B2 1=D0=90 =D0=B8 1=D0=91 =E2=80=93 = =D1=81=D0=BF=D0=BE=D1=80=D0=BD=D1=8B=D0=B5 = =D1=81=D0=B8=D1=82=D1=83=D0=B0=D1=86=D0=B8=D0=B8 = =D0=90=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1= =8F =D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0 = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9 = =D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D1=85 =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B0=D1=85 = =D0=92=D1=8B=D0=B3=D1=80=D1=83=D0=B7=D0=BA=D0=B0 = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8 = =D0=B8=D0=B7 =D0=B1=D0=B0=D0=B7 =D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85: = =D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D1=8F =D0=9E=D0=B1=D0=BC=D0=B5=D0=BD = =D0=BE=D0=BF=D1=8B=D1=82=D0=BE=D0=BC: = =D0=BA=D0=B0=D0=BA=D0=B8=D0=BC=D0=B8 = =D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=D0=BC=D0=B8 = =D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=D0=B8=D1=81=D1=8C = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=BF=D0=BB=D0=B0=D1=82=D0=B5=D0=BB=D1= =8C=D1=89=D0=B8=D0=BA=D0=B8? =D0=91=D0=BB=D0=BE=D0=BA 5. = =D0=A1=D0=BB=D0=BE=D0=B6=D0=BD=D1=8B=D0=B5 = =D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D1=8B = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F = =D0=9E=D0=B1=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D1=86=D0=B5=D0=BD =D0=BF=D0=BE=D0=BF=D1=83=D1=82=D0=BD=D1=8B=D1=85 = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=82=D0=BE=D0=B2 = =D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D1=81=D1=82=D0=B2=D0=B0 = =D0=BF=D1=80=D0=B8 = =D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8 = =D0=B8=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20 = =D1=81=D0=BE=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D1=8B=D1=85 = =D1=80=D1=8B=D0=BD=D0=BE=D1=87=D0=BD=D1=8B=D1=85 =D1=86=D0=B5=D0=BD = =D0=9F=D1=80=D0=BE=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D1=81=D1=82=D0=B2=D0=BE = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=82=D0=BE=D0=B2 = =D0=BF=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8 = =D1=81=D1=8B=D1=80=D1=8C=D1=8F =D0=B8 =D0=B8=D1=85 = =D0=BF=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D1=83=D1=8E=D1=89=D0=B0=D1=8F = =D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F = =D0=98=D0=BD=D1=82=D0=B5=D0=BB=D0=BB=D0=B5=D0=BA=D1=82=D1=83=D0=B0=D0=BB=D1= =8C=D0=BD=D0=B0=D1=8F = =D1=81=D0=BE=D0=B1=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D1= =8C =D0=B8 =D1=80=D0=BE=D1=8F=D0=BB=D1=82=D0=B8 =D0=97=D0=B0=D0=B9=D0=BC=D1=8B =D0=B8 = =D0=BF=D0=BE=D1=80=D1=83=D1=87=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D1=82=D0= =B2=D0=B0 =D0=A1=D0=B4=D0=B5=D0=BB=D0=BA=D0=B8 =D1=81 = =D0=BE=D1=84=D1=84=D1=88=D0=BE=D1=80=D0=B0=D0=BC=D0=B8: = =D0=BE=D0=B1=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D1=86=D0=B5=D0=BD =D0=B2 = =D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8 = =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=BE=D0=B2=D0=BE=D0=B9 = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8 =D0=BE=20 = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=B0=D0=B3=D0=B5=D0=BD=D1=82=D0=B5 = =D0=AD=D0=BA=D1=81=D0=BF=D0=BE=D1=80=D1=82/=D0=B8=D0=BC=D0=BF=D0=BE=D1=80= =D1=82 =E2=80=93 = =D0=BF=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B5 = =D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D1=8F =D0=9A=D0=BE=D0=B3=D0=B4=D0=B0 = =D1=86=D0=B5=D0=BD=D1=83 = =D0=BD=D0=B5=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE = =D0=BE=D0=B1=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D1=82=D1=8C = =D0=BE=D0=B4=D0=BD=D0=B8=D0=BC = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=BC =D0=A2=D0=A6? = =D0=98=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0= =B5 =D0=BA=D0=BE=D0=BC=D0=B1=D0=B8=D0=BD=D0=B0=D1=86=D0=B8=D0=B8=20 =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2 =D0=91=D0=BB=D0=BE=D0=BA 6. = =D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C =D0=B8 = =D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B8=D1=80=D0=BE=D0= =B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D0=9F=D0=BE=D0=BB=D0=BD=D0=BE=D0=BC=D0=BE=D1=87=D0=B8=D1=8F = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D1=8F=D1=8E=D1=89=D0=B8=D1=85: = =D0=A4=D0=9D=D0=A1, = =D0=9C=D0=B5=D0=B6=D1=80=D0=B5=D0=B3=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=D1=8C=D0= =BD=D0=B0=D1=8F =D0=B8=D0=BD=D1=81=D0=BF=D0=B5=D0=BA=D1=86=D0=B8=D1=8F = =D0=BF=D0=BE =D1=86=D0=B5=D0=BD=D0=B0=D0=BC, = =D1=82=D0=B5=D1=80=D1=80=D0=B8=D1=82=D0=BE=D1=80=D0=B8=D0=B0=D0=BB=D1=8C=D0= =BD=D1=8B=D0=B5=20 = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D0=B5 = =D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D1=8B=20 = =D0=9F=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=BA=D0=B0=D0=BC=D0=B5=D1=80=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9 = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F: = =D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B2=D1=8B=D1=8F=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA =D0=B8=20 = =D0=BD=D0=B5=D0=BF=D0=BE=D0=BB=D0=BD=D0=BE=D1=82=D1=8B = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8 =D0=A1=D1=80=D0=BE=D0=BA=D0=B8 =D0=B8 = =D0=BE=D1=81=D0=BE=D0=B1=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BE=D0=BA = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D1=8B=D1=85 = =D1=86=D0=B5=D0=BD.=20 = =D0=98=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=B8, = =D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=BC=D0=B8 = =D0=B1=D1=83=D0=B4=D1=83=D1=82 = =D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=D1=81=D1=8F = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D0=B5 = =D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D1=8B =D0=B4=D0=BB=D1=8F = =D0=B2=D1=8B=D1=8F=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20 = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D1=85 =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA =D0=B2 = =D1=81=D0=BB=D1=83=D1=87=D0=B0=D1=8F=D1=85 = =D0=BD=D0=B5=D0=BF=D0=BE=D0=B4=D0=B0=D1=87=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9 =D0=A1=D0=BF=D0=BE=D1=80=D1=8B =D1=81 = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D0=BC=D0=B8 = =D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D0=B0=D0=BC=D0=B8 = =D0=A1=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=B8=D1=8F: 21 600 =D1=80.=20 =D0=92 = =D1=81=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C = =D0=B2=D1=85=D0=BE=D0=B4=D0=B8=D1=82 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B9 = =D0=BC=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=B0=D0=BB, = =D0=BE=D0=B1=D0=B5=D0=B4=D1=8B, = =D0=BA=D0=BE=D1=84=D0=B5-=D0=BF=D0=B0=D1=83=D0=B7=D1=8B, = =D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82.=20 = =D0=98=D0=BD=D0=BE=D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=BD=D0=B8=D0=BC = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8=D0=BA=D0=B0=D0=BC = =D0=BF=D0=BE=D0=BC=D0=BE=D0=B3=D0=B0=D0=B5=D0=BC =D0=B2 = =D0=B1=D1=80=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8 = =D0=B3=D0=BE=D1=81=D1=82=D0=B8=D0=BD=D0=B8=D1=86=D1=8B. =20 =20 =20 =20 =20 ------=_NextPart_000_0039_01D1C0D7.3B490D80 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable


=D0=A1=D0=BE=D0=B4=D0=B5=D1=80=D0=B6=D0=B0=D0=BD=D0=B8=D0=B5:

      


20 = - 21 =D0=B8=D1=8E=D0=BD=D1=8F |=20 =D0=B3. 
=D0=A1=D0=B0=D0=BD=D0=BA=D1=82 -=20 = =D0=9F=D0=B5=D1=82=D0=B5=D1=80=D0=B1=D1=83=D1=80=D0=B3
(=D0=BF=D1=80=D0=BE=D0=BC=D0=BE=D0=BA=D0=BE=D0=B4:434)


=D0=A2=D0=A0=D0=90=D0=9D=D0=A1=D0=A4=D0=95=D0=A0=D0=A2=D0=9D=D0=9E= =D0=95=20 = =D0=A6=D0=95=D0=9D=D0=9E=D0=9E=D0=91=D0=A0=D0=90=D0=97=D0=9E=D0=92=D0=90=D0= =9D=D0=98=D0=95:
=D0=9F=D0=95=D0=A0=D0=92=D0=AB=D0=95 = =D0=9F=D0=A0=D0=9E=D0=92=D0=95=D0=A0=D0=9A=D0=98 =D0=98 = =D0=9F=D0=A0=D0=98=D0=9C=D0=95=D0=A0=D0=AB=20 = =D0=9F=D0=9E=D0=94=D0=93=D0=9E=D0=A2=D0=9E=D0=92=D0=9A=D0=98=20 = =D0=94=D0=9E=D0=9A=D0=A3=D0=9C=D0=95=D0=9D=D0=A2=D0=90=D0=A6=D0=98=D0=98<= /FONT>


=D0=97=D0=B0=D0=BD=D1=8F=D1=82=D0=B8=D0=B5=20 = =D0=BF=D1=80=D0=BE=D0=B2=D0=BE=D0=B4=D0=B8=D1=82=D1=81=D1=8F = =D1=81 10:00 =D0=B4=D0=BE = 17:30
 
=D0=9C=D0=B5=D1=80=D0=BE=D0=BF= =D1=80=D0=B8=D1=8F=D1=82=D0=B8=D0=B5=20 = =D1=81=D0=BE=D1=81=D1=82=D0=BE=D0=B8=D1=82=D1=81=D1=8F: = =D0=B1=D0=B8=D0=B7=D0=BD=D0=B5=D1=81-=D1=86=D0=B5=D0=BD=D1=82=D1=80 = =E2=80=9C=D0=9C=D0=B0=D1=80=D0=B8=D0=B8=D0=BD=D1=81=D0=BA=D0=B8=D0=B9=E2=80= =9D,=20 = =D0=BD=D0=B0=D0=B1=D0=B5=D1=80=D0=B5=D0=B6=D0=BD=D0=B0=D1=8F = =D1=80=D0=B5=D0=BA=D0=B8 =D0=9C=D0=BE=D0=B9=D0=BA=D0=B8, =D0=B4.=20 = 58.

=D0=A3=D0=B7=D0=BD=D0=B0=D1=82=D1=8C = =D0=B2=D1=81=D1=8E = =D0=BF=D0=BE=D0=B4=D1=80=D0=BE=D0=B1=D0=BD=D1=83=D1=8E = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8E=20 =D0=B8 = =D0=B7=D0=B0=D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80=D0=B8=D1=80=D0=BE=D0= =B2=D0=B0=D1=82=D1=8C=D1=81=D1=8F =D0=92=D1=8B = =D0=BC=D0=BE=D0=B6=D0=B5=D1=82=D0=B5 =D0=BF=D0=BE = =D0=BD=D0=BE=D0=BC=D0=B5=D1=80=D1=83: 

8  =D0=BA=D0=BE=D0=B4=20 = =D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=B0 (812) =D1=82=D0=B5=D0=BB.:  = 346 -=20 54 - = 40=20 (=D0=BC=D0=BD=D0=BE=D0=B3=D0=BE=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=D1= =8C=D0=BD=D1=8B=D0=B9)

            &nbs= p;            = ;            =             &= nbsp;           &n= bsp;           &nb= sp;           &nbs= p;            = ;=20    
=D0=94=D0=BB=D1=8F: =D1=80=D1=83=D0=BA=D0=BE=D0=B2= =D0=BE=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D0=B5=D0=B9=20 = =D0=BF=D0=BE=D0=B4=D1=80=D0=B0=D0=B7=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=B8=D0= =B9 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B9, = =D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5 = =D0=B1=D1=83=D0=B4=D1=83=D1=82 = =D0=B7=D0=B0=D0=BD=D0=B8=D0=BC=D0=B0=D1=82=D1=8C=D1=81=D1=8F=20 = =D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D0=B0=D0=BC=D0=B8 
=D1=82=D1=80=D0=B0=D0=BD=D1= =81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20 = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F, = =D0=B1=D1=83=D1=85=D0=B3=D0=B0=D0=BB=D1=82=D0=B5=D1=80=D0=BE=D0=B2, = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D1=85=20 = =D1=81=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=B2,= =D1=81=D0=BE=D1=82=D1=80=D1=83=D0=B4=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20 = =D0=BF=D0=BB=D0=B0=D0=BD=D0=BE=D0=B2=D0=BE-
=D1=8D=D0=BA=D0=BE=D0=BD=D0= =BE=D0=BC=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D1=85 =D0=B8 = =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=BE=D0=B2=D1=8B=D1=85=20 = =D1=81=D0=BB=D1=83=D0=B6=D0=B1.

=D0=9F=D1=80=D0=B5=D0=BF=D0=BE=D0= =B4=D0=B0=D0=B2=D0=B0=D1=82=D0=B5=D0=BB=D1=8C - = =D1=8D=D0=BA=D1=81=D0=BF=D0=B5=D1=80=D1=82=20 IBFS United, = =D1=8F=D0=B2=D0=BB=D1=8F=D0=B5=D1=82=D1=81=D1=8F = =D0=BE=D0=B4=D0=BD=D0=B8=D0=BC=D0=B8 =D0=B8=D0=B7 = =D0=BB=D1=83=D1=87=D1=88=D0=B8=D1=85=20 = =D1=81=D0=BF=D0=B5=D1=86=D0=B8=D0=B0=D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=B2 = =D0=B2 =D0=BE=D0=B1=D0=BB=D0=B0=D1=81=D1=82=D0=B8 
=D1=82=D1=80=D0=B0=D0=BD=D1= =81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0=BE=20 = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F =D0=B2 =D0=A0=D0=A4, =D0=B8 = =D1=81=D0=BC=D0=BE=D0=B6=D0=B5=D1=82 = =D0=BE=D1=82=D0=B2=D0=B5=D1=82=D0=B8=D1=82=D1=8C =D0=BD=D0=B0 = =D0=B2=D1=81=D0=B5=20 = =D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1= =8B=D0=B5 =D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D1=8B 
=D1=83=D1=87=D0=B0=D1=81=D1= =82=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2=20 = =D1=81=D0=B5=D0=BC=D0=B8=D0=BD=D0=B0=D1=80=D0=B0.
 

=D0=91=D0=BB=D0=BE=D0=BA 1. = =D0=A2=D0=B5=D0=BE=D1=80=D0=B8=D1=8F=20 = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F =D0=B2 = =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D0=B0=D1=85
   =D0=9E=D1=81=D0=BD=D0=BE= =D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20 =D0=B4=D0=BB=D1=8F = =D0=BF=D1=80=D0=B8=D0=B7=D0=BD=D0=B0=D0=BD=D0=B8=D1=8F = =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D0=BC=D0=B8. =D0=9F=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D0=BA=D1=83=D0=BC = =D0=BF=D0=BE=20 =D1=80=D0=B0=D1=81=D1=87=D0=B5=D1=82=D1=83 = =D0=BF=D0=BE=D1=80=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D1=85 
   =D0=B7=D0=BD=D0=B0=D1=87= =D0=B5=D0=BD=D0=B8=D0=B9.
   =D0=A1=D0=B4=D0=B5=D0=BB= =D0=BA=D0=B8 =D1=81=20 =D0=BB=D0=B8=D1=86=D0=B0=D0=BC=D0=B8, = =D0=BD=D0=B5 = =D0=BF=D1=80=D0=B8=D0=B7=D0=BD=D0=B0=D0=B2=D0=B0=D0=B5=D0=BC=D1=8B=D0=BC=D0= =B8 = =D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0= =BC=D1=8B=D0=BC=D0=B8. =D0=92 =D0=BA=D0=B0=D0=BA=D0=BE=D0=BC=20 =D1=81=D0=BB=D1=83=D1=87=D0=B0=D0=B5 = =D0=B5=D1=81=D1=82=D1=8C =D1=80=D0=B8=D1=81=D0=BA=D0=B8?
   =D0=9C=D0=B5=D1=82=D0=BE= =D0=B4=D1=8B=20 = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F =D0=B8 = =D1=81=D0=BE=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D0=BE=D1=81=D1= =82=D1=8C =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA.=20 =D0=9C=D0=BE=D0=B6=D0=BD=D0=BE =D0=BB=D0=B8 
   =D0=B8=D1=81=D0=BF=D0=BE= =D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=20 =D0=BE=D1=86=D0=B5=D0=BD=D0=BA=D1=83 =D0=B8 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D1=8B, =D0=BD=D0=B5 = =D0=BF=D1=80=D0=B5=D0=B4=D1=83=D1=81=D0=BC=D0=BE=D1=82=D1=80=D0=B5=D0=BD=D0= =BD=D1=8B=D0=B5 =D0=9D=D0=9A =D0=A0=D0=A4?
   =D0=A1=D1=82=D0=B0=D1=82= =D0=B8=D1=81=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=BE=D0=B5=20 = =D0=B8=D1=81=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D1=81=D0=BE=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D1=8B=D1=85 = =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B9. = =D0=A8=D0=B0=D0=B3=D0=B8 =D0=BF=D0=BE =D0=B5=D0=B3=D0=BE=20 = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8E.
   =D0=9F=D1=80=D0=B0=D0=BA= =D1=82=D0=B8=D0=BA=D1=83=D0=BC=20 =D0=BF=D0=BE = =D1=80=D0=B0=D1=81=D1=87=D0=B5=D1=82=D1=83 = =D0=B8=D0=BD=D1=82=D0=B5=D1=80=D0=B2=D0=B0=D0=BB=D0=BE=D0=B2 = =D1=80=D1=8B=D0=BD=D0=BE=D1=87=D0=BD=D1=8B=D1=85 =D1=86=D0=B5=D0=BD = =D0=B8 = =D1=80=D0=B5=D0=BD=D1=82=D0=B0=D0=B1=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1= =82=D0=B8.=20 = =D0=9D=D0=B5=D1=8F=D1=81=D0=BD=D0=BE=D1=81=D1=82=D0=B8 =D0=9D=D0=9A = =D0=A0=D0=A4 =D0=B8 
   =D0=BC=D0=B5=D0=B6=D0=B4= =D1=83=D0=BD=D0=B0=D1=80=D0=BE=D0=B4=D0=BD=D1=8B=D0=B9=20 =D0=BE=D0=BF=D1=8B=D1=82. 
   =D0=A0=D0=B0=D1=81=D1=87= =D0=B5=D1=82=20 = =D1=81=D0=BE=D0=B1=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D0=B9 = =D1=80=D0=B5=D0=BD=D1=82=D0=B0=D0=B1=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1= =82=D0=B8 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B8. = =D0=94=D0=BE=D1=81=D1=82=D0=B0=D1=82=D0=BE=D1=87=D0=BD=D0=BE = =D0=BB=D0=B8=20 =D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85 = =D0=B1=D1=83=D1=85=D0=B3=D0=B0=D0=BB=D1=82=D0=B5=D1=80=D1=81=D0=BA=D0=BE=D0= =B3=D0=BE 
   =D1=83=D1=87=D0=B5=D1=82= =D0=B0?
=D0=91=D0=BB=D0=BE=D0=BA=20 2. =D0=9F=D0=BE=D0=B4=D1=85=D0=BE=D0=B4=D1=8B = =D0=BA =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B5 = =D0=B7=D0=B0=D1=89=D0=B8=D1=82=D0=BD=D0=BE=D0=B9=20 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8<= /B>
   =D0=9E=D1=81=D0=BD=D0=BE= =D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20 =D0=B4=D0=BB=D1=8F = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B8 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8 = =D0=BF=D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D0=BC =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B0=D0=BC.=20 =D0=9A=D0=BE=D0=B3=D0=B4=D0=B0 
   =D1=86=D0=B5=D0=BB=D0=B5= =D1=81=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BD=D0=BE=20 =D0=BD=D0=B5 = =D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=B8=D1=82=D1=8C = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8E?=  
   =D0=9E=D1=81=D0=BD=D0=BE= =D0=B2=D0=BD=D1=8B=D0=B5=20 =D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8, = =D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5 = =D0=B4=D0=BE=D0=BF=D1=83=D1=81=D1=82=D0=B8=D0=BB=D0=B8 = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=BF=D0=BB=D0=B0=D1=82=D0=B5=D0=BB=D1= =8C=D1=89=D0=B8=D0=BA=D0=B8 =D0=BF=D1=80=D0=B8=20 = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B5 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8<= BR>   =D0=A1=D0=BB=D1=83=D1=87= =D0=B0=D0=B8,=20 =D0=BA=D0=BE=D0=B3=D0=B4=D0=B0 = =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2 =D0=A2=D0=A6 = =D0=BD=D0=B5=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE: = =D1=81=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8 = =D1=81 
   =D0=BF=D1=80=D0=B8=D0=BC= =D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5=D0=BC=20 =D0=B8=D0=BD=D1=8B=D1=85 = =D0=BF=D0=BE=D0=B4=D1=85=D0=BE=D0=B4=D0=BE=D0=B2 
   =D0=9F=D0=BE=D1=88=D0=B0= =D0=B3=D0=BE=D0=B2=D0=BE=D0=B5=20 = =D1=80=D1=83=D0=BA=D0=BE=D0=B2=D0=BE=D0=B4=D1=81=D1=82=D0=B2=D0=BE = =D0=BF=D0=BE = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8E = =D0=B8=D1=81=D1=81=D0=BB=D0=B5=D0=B4=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F = =D0=B2 =D0=A1=D0=9F=D0=90=D0=A0=D0=9A =D0=B8=20 = =D0=A0=D1=83=D1=81=D0=BB=D0=B0=D0=BD=D0=B0
  =  =D0=90=D0=BB=D0=B3=D0=BE= =D1=80=D0=B8=D1=82=D0=BC=D1=8B=20 =D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2 =D0=B4=D0=BB=D1=8F = =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA
=D0=91=D0=BB=D0=BE=D0=BA 3. = =D0=9F=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D0=BA=D1=83=D0=BC =D0=BF=D0=BE=20 = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B5 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8.= =D0=9F=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D1=8B = =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA.
   =D0=94=D0=BE=D0=BA=D1=83= =D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F=20 =D1=81 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0= =B5=D0=BC =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0 = =D1=81=D0=BE=D0=BF=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D1=8B=D1=85 = =D1=80=D1=8B=D0=BD=D0=BE=D1=87=D0=BD=D1=8B=D1=85 =D1=86=D0=B5=D0=BD = =D0=BD=D0=B0=20 = =D0=BF=D1=80=D0=B8=D0=BC=D0=B5=D1=80=D0=B0=D1=85:=D1=8D=D0=BA=D1=81=D0=BF= =D0=BE=D1=80=D1=82 
   =D0=B1=D0=B8=D1=80=D0=B6= =D0=B5=D0=B2=D1=8B=D1=85=20 =D1=82=D0=BE=D0=B2=D0=B0=D1=80=D0=BE=D0=B2 = (=D0=BD=D0=B5=D1=84=D1=82=D1=8C, = =D0=BC=D0=B5=D1=82=D0=B0=D0=BB=D0=BB=D1=8B, = =D1=83=D0=B4=D0=BE=D0=B1=D1=80=D0=B5=D0=BD=D0=B8=D1=8F, = =D1=81=D0=B5=D0=BB=D1=8C=D1=85=D0=BE=D0=B7=D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0= =BA=D1=86=D0=B8=D1=8F =D0=B8=20 =D1=82.=D0=BF.); = =D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F 
   =D1=82=D0=BE=D0=B2=D0=B0= =D1=80=D0=BE=D0=B2=20 =D0=B2 =D0=B0=D0=B4=D1=80=D0=B5=D1=81 = =D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0= =BC=D1=8B=D1=85 =D0=B8 =D1=82=D1=80=D0=B5=D1=82=D1=8C=D0=B8=D1=85 = =D0=BB=D0=B8=D1=86;
   =D0=94=D0=BE=D0=BA=D1=83= =D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D1=8F=20 =D1=81 = =D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0= =B5=D0=BC =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=B2, = =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D1=8B=D1=85 = =D0=BD=D0=B0 =D0=B0=D0=BD=D0=B0=D0=BB=D0=B8=D0=B7=D0=B5=20 = =D1=80=D0=B5=D0=BD=D1=82=D0=B0=D0=B1=D0=B5=D0=BB=D1=8C=D0=BD=D0=BE=D1=81=D1= =82=D0=B8 =D0=BD=D0=B0 
   =D0=BF=D1=80=D0=B8=D0=BC= =D0=B5=D1=80=D0=B0=D1=85:=20 =D0=BF=D0=BE=D0=BA=D1=83=D0=BF=D0=BA=D0=B0 = =D1=83=D1=81=D0=BB=D1=83=D0=B3 =D1=83 = =D0=B7=D0=B0=D1=80=D1=83=D0=B1=D0=B5=D0=B6=D0=BD=D0=BE=D0=B9 = =D0=B2=D0=B7=D0=B0=D0=B8=D0=BC=D0=BE=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B8=D0= =BC=D0=BE=D0=B9 =D0=BA=D0=BE=D0=BC=D0=BF=D0=B0=D0=BD=D0=B8=D0=B8;=20 = =D0=B4=D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80=D1=8B 
   =D0=B0=D0=B3=D0=B5=D0=BD= =D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20 =D0=B8 = =D0=BA=D0=BE=D0=BC=D0=B8=D1=81=D1=81=D0=B8=D0=B8; = =D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F = =D1=82=D0=BE=D0=B2=D0=B0=D1=80=D0=BE=D0=B2 =D0=B2 = =D0=B0=D0=B4=D1=80=D0=B5=D1=81=20 = =D0=BF=D0=B5=D1=80=D0=B5=D0=BF=D1=80=D0=BE=D0=B4=D0=B0=D0=B2=D1=86=D0=B0.=
=D0=91=D0=BB=D0=BE=D0=BA 4. = =D0=A3=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D1=85=20 =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B0=D1=85: = =D0=B0=D0=B2=D1=82=D0=BE=D0=BC=D0=B0=D1=82=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1= =8F
 =20  =D0=90=D0=BD=D0=B0=D0=BB= =D0=B8=D0=B7=20 =D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=BD=D1=8B=D1=85 = =D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA =D0=BF=D1=80=D0=B8 = =D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9: = =D0=B8=D1=82=D0=BE=D0=B3=D0=B8 20=20 =D0=BD=D0=BE=D1=8F=D0=B1=D1=80=D1=8F
   =D0=93=D1=80=D1=83=D0=BF= =D0=BF=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8=20 =D0=BB=D0=B8=D1=81=D1=82=D0=BE=D0=B2 1=D0=90 = =D0=B8 1=D0=91 =E2=80=93 =D1=81=D0=BF=D0=BE=D1=80=D0=BD=D1=8B=D0=B5 = =D1=81=D0=B8=D1=82=D1=83=D0=B0=D1=86=D0=B8=D0=B8
   =D0=90=D0=B2=D1=82=D0=BE= =D0=BC=D0=B0=D1=82=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20 =D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81=D1=81=D0=B0 = =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9 = =D0=BE = =D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1= =8B=D1=85=20 = =D1=81=D0=B4=D0=B5=D0=BB=D0=BA=D0=B0=D1=85
  =  =D0=92=D1=8B=D0=B3=D1=80= =D1=83=D0=B7=D0=BA=D0=B0=20 = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8 = =D0=B8=D0=B7 =D0=B1=D0=B0=D0=B7 =D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85: = =D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D1=8F
   =D0=9E=D0=B1=D0=BC=D0=B5= =D0=BD=20 =D0=BE=D0=BF=D1=8B=D1=82=D0=BE=D0=BC: = =D0=BA=D0=B0=D0=BA=D0=B8=D0=BC=D0=B8 = =D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D1=8F=D0=BC=D0=B8 = =D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BB=D0=B8=D1=81=D1=8C = = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=BF=D0=BB=D0=B0=D1=82=D0=B5=D0=BB=D1= =8C=D1=89=D0=B8=D0=BA=D0=B8?
=D0=91=D0=BB=D0=BE=D0=BA 5. = =D0=A1=D0=BB=D0=BE=D0=B6=D0=BD=D1=8B=D0=B5 = =D0=B2=D0=BE=D0=BF=D1=80=D0=BE=D1=81=D1=8B=20 = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D0=BE=D0=B3=D0= =BE = =D1=86=D0=B5=D0=BD=D0=BE=D0=BE=D0=B1=D1=80=D0=B0=D0=B7=D0=BE=D0=B2=D0=B0=D0= =BD=D0=B8=D1=8F
   =D0=9E=D0=B1=D0=BE=D1=81= =D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20 =D1=86=D0=B5=D0=BD = =D0=BF=D0=BE=D0=BF=D1=83=D1=82=D0=BD=D1=8B=D1=85 = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=82=D0=BE=D0=B2 = =D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D1=81=D1=82=D0=B2=D0=B0 = =D0=BF=D1=80=D0=B8 = =D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8=20 = =D0=B8=D1=81=D1=82=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2 
   =D1=81=D0=BE=D0=BF=D0=BE= =D1=81=D1=82=D0=B0=D0=B2=D0=B8=D0=BC=D1=8B=D1=85=20 =D1=80=D1=8B=D0=BD=D0=BE=D1=87=D0=BD=D1=8B=D1=85 = =D1=86=D0=B5=D0=BD
   =D0=9F=D1=80=D0=BE=D0=B8= =D0=B7=D0=B2=D0=BE=D0=B4=D1=81=D1=82=D0=B2=D0=BE=20 = =D0=BF=D1=80=D0=BE=D0=B4=D1=83=D0=BA=D1=82=D0=BE=D0=B2 = =D0=BF=D0=B5=D1=80=D0=B5=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8 = =D1=81=D1=8B=D1=80=D1=8C=D1=8F =D0=B8 =D0=B8=D1=85 = =D0=BF=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D1=83=D1=8E=D1=89=D0=B0=D1=8F=20 = =D1=80=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D1=8F
   =D0=98=D0=BD=D1=82=D0=B5= =D0=BB=D0=BB=D0=B5=D0=BA=D1=82=D1=83=D0=B0=D0=BB=D1=8C=D0=BD=D0=B0=D1=8F = = =D1=81=D0=BE=D0=B1=D1=81=D1=82=D0=B2=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D1= =8C =D0=B8 =D1=80=D0=BE=D1=8F=D0=BB=D1=82=D0=B8
   =D0=97=D0=B0=D0=B9=D0=BC= =D1=8B =D0=B8=20 = =D0=BF=D0=BE=D1=80=D1=83=D1=87=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D1=81=D1=82=D0= =B2=D0=B0
   =D0=A1=D0=B4=D0=B5=D0=BB= =D0=BA=D0=B8 =D1=81=20 = =D0=BE=D1=84=D1=84=D1=88=D0=BE=D1=80=D0=B0=D0=BC=D0=B8: = =D0=BE=D0=B1=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5 = =D1=86=D0=B5=D0=BD =D0=B2 = =D0=BE=D1=82=D1=81=D1=83=D1=82=D1=81=D1=82=D0=B2=D0=B8=D0=B8 = =D1=84=D0=B8=D0=BD=D0=B0=D0=BD=D1=81=D0=BE=D0=B2=D0=BE=D0=B9=20 = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8 =D0=BE 
   =D0=BA=D0=BE=D0=BD=D1=82= =D1=80=D0=B0=D0=B3=D0=B5=D0=BD=D1=82=D0=B5
   =D0=AD=D0=BA=D1=81=D0=BF= =D0=BE=D1=80=D1=82/=D0=B8=D0=BC=D0=BF=D0=BE=D1=80=D1=82=20 =E2=80=93 = =D0=BF=D1=80=D0=B0=D0=BA=D1=82=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B5 = =D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D1=8F
  =  =D0=9A=D0=BE=D0=B3=D0=B4= =D0=B0=20 =D1=86=D0=B5=D0=BD=D1=83 = =D0=BD=D0=B5=D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE = =D0=BE=D0=B1=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=D1=82=D1=8C = =D0=BE=D0=B4=D0=BD=D0=B8=D0=BC = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=BE=D0=BC =D0=A2=D0=A6?=20 = =D0=98=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0= =B5 =D0=BA=D0=BE=D0=BC=D0=B1=D0=B8=D0=BD=D0=B0=D1=86=D0=B8=D0=B8 
   =D0=BC=D0=B5=D1=82=D0=BE= =D0=B4=D0=BE=D0=B2
=D0=91=D0=BB=D0=BE=D0=BA=20 6. = =D0=9A=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D1=8C =D0=B8 = =D0=B0=D0=B4=D0=BC=D0=B8=D0=BD=D0=B8=D1=81=D1=82=D1=80=D0=B8=D1=80=D0=BE=D0= =B2=D0=B0=D0=BD=D0=B8=D0=B5
   =D0=9F=D0=BE=D0=BB=D0=BD= =D0=BE=D0=BC=D0=BE=D1=87=D0=B8=D1=8F=20 = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D1=8F=D1=8E=D1=89=D0=B8=D1=85: = =D0=A4=D0=9D=D0=A1, = =D0=9C=D0=B5=D0=B6=D1=80=D0=B5=D0=B3=D0=B8=D0=BE=D0=BD=D0=B0=D0=BB=D1=8C=D0= =BD=D0=B0=D1=8F =D0=B8=D0=BD=D1=81=D0=BF=D0=B5=D0=BA=D1=86=D0=B8=D1=8F = =D0=BF=D0=BE =D1=86=D0=B5=D0=BD=D0=B0=D0=BC,=20 = =D1=82=D0=B5=D1=80=D1=80=D0=B8=D1=82=D0=BE=D1=80=D0=B8=D0=B0=D0=BB=D1=8C=D0= =BD=D1=8B=D0=B5 
   =D0=BD=D0=B0=D0=BB=D0=BE= =D0=B3=D0=BE=D0=B2=D1=8B=D0=B5=20 =D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D1=8B 
   =D0=9F=D1=80=D0=BE=D0=B2= =D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D0=B5=20 = =D0=BA=D0=B0=D0=BC=D0=B5=D1=80=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE=D0=B9 = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BA=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F: = =D0=B2=D0=BE=D0=B7=D0=BC=D0=BE=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B2=D1=8B=D1=8F=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20 =D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA =D0=B8 
   =D0=BD=D0=B5=D0=BF=D0=BE= =D0=BB=D0=BD=D0=BE=D1=82=D1=8B=20 = =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D0=B8
   =D0=A1=D1=80=D0=BE=D0=BA= =D0=B8 =D0=B8=20 = =D0=BE=D1=81=D0=BE=D0=B1=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BE=D0=BA = =D1=82=D1=80=D0=B0=D0=BD=D1=81=D1=84=D0=B5=D1=80=D1=82=D0=BD=D1=8B=D1=85 = =D1=86=D0=B5=D0=BD. 
   =D0=98=D1=81=D1=82=D0=BE= =D1=87=D0=BD=D0=B8=D0=BA=D0=B8,=20 =D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=BC=D0=B8 = =D0=B1=D1=83=D0=B4=D1=83=D1=82 = =D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D0=BE=D0=B2=D0=B0=D1=82=D1=8C=D1=81=D1=8F = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D0=B5 = =D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D1=8B =D0=B4=D0=BB=D1=8F=20 = =D0=B2=D1=8B=D1=8F=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F 
   =D0=BA=D0=BE=D0=BD=D1=82= =D1=80=D0=BE=D0=BB=D0=B8=D1=80=D1=83=D0=B5=D0=BC=D1=8B=D1=85=20 =D1=81=D0=B4=D0=B5=D0=BB=D0=BE=D0=BA =D0=B2 = =D1=81=D0=BB=D1=83=D1=87=D0=B0=D1=8F=D1=85 = =D0=BD=D0=B5=D0=BF=D0=BE=D0=B4=D0=B0=D1=87=D0=B8 = =D1=83=D0=B2=D0=B5=D0=B4=D0=BE=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D0=B9
   =D0=A1=D0=BF=D0=BE=D1=80= =D1=8B =D1=81=20 = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B3=D0=BE=D0=B2=D1=8B=D0=BC=D0=B8 = =D0=BE=D1=80=D0=B3=D0=B0=D0=BD=D0=B0=D0=BC=D0=B8


=D0=A1=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C=20 = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=B8=D1=8F: 21 600 =D1=80. 
=D0=92 = =D1=81=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C=20 =D0=B2=D1=85=D0=BE=D0=B4=D0=B8=D1=82 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B9 = =D0=BC=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=B0=D0=BB, = =D0=BE=D0=B1=D0=B5=D0=B4=D1=8B, = =D0=BA=D0=BE=D1=84=D0=B5-=D0=BF=D0=B0=D1=83=D0=B7=D1=8B,=20 = =D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82. 
=D0=98=D0=BD=D0=BE=D0=B3=D0= =BE=D1=80=D0=BE=D0=B4=D0=BD=D0=B8=D0=BC=20 = =D1=83=D1=87=D0=B0=D1=81=D1=82=D0=BD=D0=B8=D0=BA=D0=B0=D0=BC = =D0=BF=D0=BE=D0=BC=D0=BE=D0=B3=D0=B0=D0=B5=D0=BC =D0=B2 = =D0=B1=D1=80=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8 = = =D0=B3=D0=BE=D1=81=D1=82=D0=B8=D0=BD=D0=B8=D1=86=D1=8B.

=        
------=_NextPart_000_0039_01D1C0D7.3B490D80-- From BATV+75fc7f7cc5699f774dd8+4671+infradead.org+hch@bombadil.srs.infradead.org Tue Jun 7 08:44:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6DDF67CA0 for ; Tue, 7 Jun 2016 08:44:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3D42D8F8040 for ; Tue, 7 Jun 2016 06:44:48 -0700 (PDT) X-ASG-Debug-ID: 1465307085-04cbb03569be0e90001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id QPuedyCuUWIUfPum (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 06:44:45 -0700 (PDT) X-Barracuda-Envelope-From: BATV+75fc7f7cc5699f774dd8+4671+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bAHJC-0001C6-Aa; Tue, 07 Jun 2016 13:44:42 +0000 Date: Tue, 7 Jun 2016 06:44:42 -0700 From: Christoph Hellwig To: Daniel Wagner Cc: Reinoud Koornstra , Christoph Hellwig , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk Subject: Re: crash in xfs in current Message-ID: <20160607134442.GA1803@infradead.org> X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1465307085 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 887 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30244 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Tue, Jun 07, 2016 at 12:52:39PM +0200, Daniel Wagner wrote: > >> I try to reproduce it on 4.6. My steps do not always trigger the crash. > >> So I can't be really sure if 4.6 doesn't show it, it does not happen. > > > > I have never been able to trigger this in 4.6 and it's my failsafe > > reboot (4.6.0). > > In 4.7-rc1 it's just a matter of time before I hit it. > > I do a lot of transactions, using git, extraction of tar.xz etc normally. > > This rings a bell. I though the lockperf tests triggered it. Before I > compiled a new kernel I did a 'git checkout' step. Thanks for testing this to both of you. Can you try to build a kernel from git commit 555b67e4e729ca544bb4028ab12e532c68b70ddb - this is the XFS pull request that Dave sent to Linux for Linux 4.7-rc, so it has all the XFS changes relative to 4.6, but none of the others like the VFS changes. From public@enkore.de Tue Jun 7 12:04:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4508B7CA0 for ; Tue, 7 Jun 2016 12:04:22 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 88F39AC004 for ; Tue, 7 Jun 2016 10:04:18 -0700 (PDT) X-ASG-Debug-ID: 1465319052-04cb6c2dbbbb9600001-NocioJ Received: from mail-wm0-f68.google.com (mail-wm0-f68.google.com [74.125.82.68]) by cuda.sgi.com with ESMTP id eVLG9ytF7goVeaXZ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 10:04:13 -0700 (PDT) X-Barracuda-Envelope-From: public@enkore.de X-Barracuda-Effective-Source-IP: mail-wm0-f68.google.com[74.125.82.68] X-Barracuda-Apparent-Source-IP: 74.125.82.68 Received: by mail-wm0-f68.google.com with SMTP id n184so25782547wmn.1 for ; Tue, 07 Jun 2016 10:04:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=enkore-de.20150623.gappssmtp.com; s=20150623; h=to:from:subject:message-id:date:user-agent:mime-version :content-transfer-encoding; bh=af7k36Z6iHmWUygqzTuGOjuPr8VrwJDEct6E+/ZHcSU=; b=Alf1tKdHRTQ7zXY/uxygON/5zHBqnVGTDNsVIuCXOJ2oZr3HPTm+Jp1UzddvGM6xyY qln20kkGNfaVoaNvFXF7ryUzodfwTA2c52z8AVXgKXYznY+6vHayEi0zR+xrB/rXdm5s d/ZsFBpa8+AhmlTO1JLqaYp07soErASxI8GyTKZHpJOTbL9PvYAA+3sNL96/7/CAnlsA G1I830KAQO0SukyJ8ZSyYmh8y/Bj/hdDl+TAoMEY9PdFHdiWj5LJ2SpASz8N3quuaWpc lBvL/dyEqypKxNXR2qHD/3r9veL0B/E7lrwfXlZ9ee1El+itsZ1mdQJN8PVVFv6G8HBg VZrA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding; bh=af7k36Z6iHmWUygqzTuGOjuPr8VrwJDEct6E+/ZHcSU=; b=O4DhhnvmYAFJNi+EVmCO2RAqN6E09n2ndtmK9b6rxI4a8LjDkcatRxVwFAgUc8TqAE lBzINTAo8iKJmuswFEVapoqTpkgujlu2Cwb4L6/4ZbngWHoeGLkWzgIp3KEjdi6gEm/4 Jo/zuiKqwakE6QiYeOpbhTcsO9q2gsPZZBrFFd0ppbZ1+lv8FDBWB8FVrrdbgP2Ha7cV fmzF6rW9e5BQjB7Def5uPdQajHOJqVbwGk5S2WllGdWUUjKI/qZ3FBBS1V5JNTa0UTMu P5iWbtztGEPVXtlAsvsf0M4wY+ox0k6TQCvesDgA4Rp693jA8qMZvH3vDIcp0yJw/VG1 HHjw== X-Gm-Message-State: ALyK8tKMFhBq+GAJ3KSYhqyRlX4RTwkOR6ZqA4tM1qkmEmb5TJsSeFD9RlKGnqFrh4PGHg== X-Received: by 10.194.3.51 with SMTP id 19mr420282wjz.57.1465319051910; Tue, 07 Jun 2016 10:04:11 -0700 (PDT) Received: from [192.168.2.44] (p57ACAF14.dip0.t-ipconnect.de. [87.172.175.20]) by smtp.googlemail.com with ESMTPSA id zg2sm11447776wjb.1.2016.06.07.10.04.10 for (version=TLSv1/SSLv3 cipher=OTHER); Tue, 07 Jun 2016 10:04:11 -0700 (PDT) To: xfs@oss.sgi.com From: Marian Beermann Subject: BUG null-pointer dereference on recovery of corrupted FS Message-ID: X-ASG-Orig-Subj: BUG null-pointer dereference on recovery of corrupted FS Date: Tue, 7 Jun 2016 19:04:09 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f68.google.com[74.125.82.68] X-Barracuda-Start-Time: 1465319053 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14165 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30248 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature Hi everyone, on a failing drive containing an XFS the following tracebacks occur when XFS tries to recover. I'm afraid I can't provide more detailed information, since the drive completely failed shortly thereafter and is already disposed. Linux 4.5.6 on x64. Cheers, Marian [20947.408809] scsi 0:0:0:0: Direct-Access ATA SAMSUNG HD501LJ 0-10 PQ: 0 ANSI: 5 [20947.420009] sd 0:0:0:0: [sde] 976771055 512-byte logical blocks: (500 GB/466 GiB) [20947.420185] sd 0:0:0:0: [sde] Write Protect is off [20947.420190] sd 0:0:0:0: [sde] Mode Sense: 00 3a 00 00 [20947.420204] sd 0:0:0:0: [sde] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA [20947.465053] sde: sde1 sde2 sde3 [20947.465984] sd 0:0:0:0: [sde] Attached SCSI removable disk [21043.651589] XFS (sde2): Mounting V5 Filesystem [21043.746426] XFS (sde2): Starting recovery (logdev: internal) [21061.815869] XFS (sde2): _xfs_buf_find: Block out of range: block 0x8031bfdf8, EOFS 0xc6ff800 [21061.815875] ------------[ cut here ]------------ [21061.815902] WARNING: CPU: 5 PID: 4731 at fs/xfs/xfs_buf.c:472 _xfs_buf_find+0x2cb/0x340 [xfs]() [21061.815904] Modules linked in: joydev mousedev input_leds hid_generic usbhid hid it87 hwmon_vid fuse eeepc_wmi asus_wmi sparse_keymap led_class rfkill video evdev mxm_wmi mac_hid amdkfd amd_iommu_v2 kvm_amd kvm radeon psmouse snd_hda_codec_hdmi serio_raw irqbypass pcspkr k10temp snd_hda_intel e1000e edac_mce_amd snd_hda_codec ttm edac_core ptp pps_core snd_ctxfi snd_hda_core drm_kms_helper sp5100_tco snd_hwdep snd_pcm drm i2c_piix4 syscopyarea sysfillrect snd_timer snd sysimgblt fb_sys_fops acpi_cpufreq soundcore i2c_algo_bit tpm_tis tpm fjes shpchp wmi processor button sch_fq_codel vboxnetflt(O) vboxnetadp(O) pci_stub vboxpci(O) vboxdrv(O) nfs lockd grace sunrpc fscache ip_tables x_tables xfs crc32c_generic libcrc32c sd_mod atkbd libps2 ahci libahci ohci_pci xhci_pci ohci_hcd ehci_pci libata xhci_hcd [21061.815960] ehci_hcd scsi_mod usbcore usb_common i8042 serio [21061.815967] CPU: 5 PID: 4731 Comm: mount Tainted: G O 4.5.6-1-ck #1 [21061.815969] Hardware name: To be filled by O.E.M. To be filled by O.E.M./M5A99X EVO, BIOS 1604 10/16/2012 [21061.815972] 0000000000000286 00000000cc91327e ffff880352eaf8f0 ffffffff812e4b22 [21061.815975] 0000000000000000 ffffffffa02a53d7 ffff880352eaf928 ffffffff8107e5a2 [21061.815979] ffff880414f40240 0000000000000008 ffff880414f40240 ffff880352eafa18 [21061.815982] Call Trace: [21061.815988] [] dump_stack+0x63/0x81 [21061.815993] [] warn_slowpath_common+0x82/0xc0 [21061.815997] [] warn_slowpath_null+0x1a/0x20 [21061.816014] [] _xfs_buf_find+0x2cb/0x340 [xfs] [21061.816031] [] xfs_buf_get_map+0x2a/0x1e0 [xfs] [21061.816044] [] ? xfs_free_ag_extent+0x28b/0x7c0 [xfs] [21061.816058] [] xfs_trans_get_buf_map+0x101/0x180 [xfs] [21061.816073] [] xfs_btree_get_bufs+0x5e/0x80 [xfs] [21061.816086] [] xfs_alloc_fix_freelist+0x238/0x400 [xfs] [21061.816102] [] ? xfs_buf_get_map+0x181/0x1e0 [xfs] [21061.816118] [] ? xfs_buf_rele+0x40/0x1a0 [xfs] [21061.816122] [] ? kmem_cache_alloc+0x1bc/0x1e0 [21061.816137] [] ? kmem_zone_alloc+0x78/0x120 [xfs] [21061.816153] [] ? xfs_perag_get+0x51/0xe0 [xfs] [21061.816166] [] xfs_free_extent+0x96/0x140 [xfs] [21061.816181] [] xfs_trans_free_extent+0x26/0x60 [xfs] [21061.816195] [] xlog_recover_process_efi+0x14e/0x1a0 [xfs] [21061.816210] [] xlog_recover_process_efis.isra.19+0x7b/0xe0 [xfs] [21061.816224] [] xlog_recover_finish+0x23/0xc0 [xfs] [21061.816237] [] ? xfs_rtmount_inodes+0x63/0x120 [xfs] [21061.816252] [] xfs_log_mount_finish+0x29/0x60 [xfs] [21061.816268] [] xfs_mountfs+0x594/0x860 [xfs] [21061.816284] [] xfs_fs_fill_super+0x3af/0x4e0 [xfs] [21061.816288] [] mount_bdev+0x17b/0x1c0 [21061.816303] [] ? xfs_parseargs+0xa60/0xa60 [xfs] [21061.816319] [] xfs_fs_mount+0x15/0x20 [xfs] [21061.816322] [] mount_fs+0x38/0x160 [21061.816325] [] ? alloc_vfsmnt+0x19a/0x240 [21061.816329] [] vfs_kern_mount+0x60/0x120 [21061.816332] [] do_mount+0x24e/0xe20 [21061.816335] [] ? mntput+0x24/0x40 [21061.816338] [] ? __fput+0x13d/0x1e0 [21061.816341] [] ? __kmalloc_track_caller+0x31/0x240 [21061.816344] [] ? memdup_user+0x42/0x80 [21061.816348] [] SyS_mount+0x98/0x100 [21061.816352] [] entry_SYSCALL_64_fastpath+0x12/0x6d [21061.816355] ---[ end trace b716ae71022f5e61 ]--- [21061.816359] XFS (sde2): _xfs_buf_find: Block out of range: block 0x8031bfdf8, EOFS 0xc6ff800 [21061.816361] ------------[ cut here ]------------ [21061.816378] WARNING: CPU: 5 PID: 4731 at fs/xfs/xfs_buf.c:472 _xfs_buf_find+0x2cb/0x340 [xfs]() [21061.816380] Modules linked in: joydev mousedev input_leds hid_generic usbhid hid it87 hwmon_vid fuse eeepc_wmi asus_wmi sparse_keymap led_class rfkill video evdev mxm_wmi mac_hid amdkfd amd_iommu_v2 kvm_amd kvm radeon psmouse snd_hda_codec_hdmi serio_raw irqbypass pcspkr k10temp snd_hda_intel e1000e edac_mce_amd snd_hda_codec ttm edac_core ptp pps_core snd_ctxfi snd_hda_core drm_kms_helper sp5100_tco snd_hwdep snd_pcm drm i2c_piix4 syscopyarea sysfillrect snd_timer snd sysimgblt fb_sys_fops acpi_cpufreq soundcore i2c_algo_bit tpm_tis tpm fjes shpchp wmi processor button sch_fq_codel vboxnetflt(O) vboxnetadp(O) pci_stub vboxpci(O) vboxdrv(O) nfs lockd grace sunrpc fscache ip_tables x_tables xfs crc32c_generic libcrc32c sd_mod atkbd libps2 ahci libahci ohci_pci xhci_pci ohci_hcd ehci_pci libata xhci_hcd [21061.816421] ehci_hcd scsi_mod usbcore usb_common i8042 serio [21061.816425] CPU: 5 PID: 4731 Comm: mount Tainted: G W O 4.5.6-1-ck #1 [21061.816427] Hardware name: To be filled by O.E.M. To be filled by O.E.M./M5A99X EVO, BIOS 1604 10/16/2012 [21061.816429] 0000000000000286 00000000cc91327e ffff880352eaf8f0 ffffffff812e4b22 [21061.816432] 0000000000000000 ffffffffa02a53d7 ffff880352eaf928 ffffffff8107e5a2 [21061.816435] ffff880414f40240 0000000000000008 ffff880414f40240 ffff880352eafa18 [21061.816437] Call Trace: [21061.816440] [] dump_stack+0x63/0x81 [21061.816444] [] warn_slowpath_common+0x82/0xc0 [21061.816447] [] warn_slowpath_null+0x1a/0x20 [21061.816464] [] _xfs_buf_find+0x2cb/0x340 [xfs] [21061.816480] [] xfs_buf_get_map+0x154/0x1e0 [xfs] [21061.816494] [] xfs_trans_get_buf_map+0x101/0x180 [xfs] [21061.816509] [] xfs_btree_get_bufs+0x5e/0x80 [xfs] [21061.816522] [] xfs_alloc_fix_freelist+0x238/0x400 [xfs] [21061.816538] [] ? xfs_buf_get_map+0x181/0x1e0 [xfs] [21061.816554] [] ? xfs_buf_rele+0x40/0x1a0 [xfs] [21061.816557] [] ? kmem_cache_alloc+0x1bc/0x1e0 [21061.816572] [] ? kmem_zone_alloc+0x78/0x120 [xfs] [21061.816588] [] ? xfs_perag_get+0x51/0xe0 [xfs] [21061.816601] [] xfs_free_extent+0x96/0x140 [xfs] [21061.816616] [] xfs_trans_free_extent+0x26/0x60 [xfs] [21061.816630] [] xlog_recover_process_efi+0x14e/0x1a0 [xfs] [21061.816645] [] xlog_recover_process_efis.isra.19+0x7b/0xe0 [xfs] [21061.816659] [] xlog_recover_finish+0x23/0xc0 [xfs] [21061.816672] [] ? xfs_rtmount_inodes+0x63/0x120 [xfs] [21061.816687] [] xfs_log_mount_finish+0x29/0x60 [xfs] [21061.816703] [] xfs_mountfs+0x594/0x860 [xfs] [21061.816719] [] xfs_fs_fill_super+0x3af/0x4e0 [xfs] [21061.816722] [] mount_bdev+0x17b/0x1c0 [21061.816737] [] ? xfs_parseargs+0xa60/0xa60 [xfs] [21061.816753] [] xfs_fs_mount+0x15/0x20 [xfs] [21061.816756] [] mount_fs+0x38/0x160 [21061.816759] [] ? alloc_vfsmnt+0x19a/0x240 [21061.816763] [] vfs_kern_mount+0x60/0x120 [21061.816766] [] do_mount+0x24e/0xe20 [21061.816769] [] ? mntput+0x24/0x40 [21061.816771] [] ? __fput+0x13d/0x1e0 [21061.816774] [] ? __kmalloc_track_caller+0x31/0x240 [21061.816777] [] ? memdup_user+0x42/0x80 [21061.816780] [] SyS_mount+0x98/0x100 [21061.816783] [] entry_SYSCALL_64_fastpath+0x12/0x6d [21061.816824] ---[ end trace b716ae71022f5e62 ]--- [21061.816870] BUG: unable to handle kernel NULL pointer dereference at 00000000000000f8 [21061.817005] IP: [] xfs_trans_binval+0x16/0x120 [xfs] [21061.817144] PGD 34426a067 PUD 32caab067 PMD 0 [21061.817227] Oops: 0000 [#1] PREEMPT SMP [21061.817296] Modules linked in: joydev mousedev input_leds hid_generic usbhid hid it87 hwmon_vid fuse eeepc_wmi asus_wmi sparse_keymap led_class rfkill video evdev mxm_wmi mac_hid amdkfd amd_iommu_v2 kvm_amd kvm radeon psmouse snd_hda_codec_hdmi serio_raw irqbypass pcspkr k10temp snd_hda_intel e1000e edac_mce_amd snd_hda_codec ttm edac_core ptp pps_core snd_ctxfi snd_hda_core drm_kms_helper sp5100_tco snd_hwdep snd_pcm drm i2c_piix4 syscopyarea sysfillrect snd_timer snd sysimgblt fb_sys_fops acpi_cpufreq soundcore i2c_algo_bit tpm_tis tpm fjes shpchp wmi processor button sch_fq_codel vboxnetflt(O) vboxnetadp(O) pci_stub vboxpci(O) vboxdrv(O) nfs lockd grace sunrpc fscache ip_tables x_tables xfs crc32c_generic libcrc32c sd_mod atkbd libps2 ahci libahci ohci_pci xhci_pci ohci_hcd ehci_pci libata xhci_hcd [21061.818682] ehci_hcd scsi_mod usbcore usb_common i8042 serio [21061.818772] CPU: 0 PID: 4731 Comm: mount Tainted: G W O 4.5.6-1-ck #1 [21061.818880] Hardware name: To be filled by O.E.M. To be filled by O.E.M./M5A99X EVO, BIOS 1604 10/16/2012 [21061.819017] task: ffff8803e342e900 ti: ffff880352eac000 task.ti: ffff880352eac000 [21061.819124] RIP: 0010:[] [] xfs_trans_binval+0x16/0x120 [xfs] [21061.819283] RSP: 0018:ffff880352eafa10 EFLAGS: 00010246 [21061.819362] RAX: 0000000000000000 RBX: ffff8800c0bf6000 RCX: 0000000180150014 [21061.819496] RDX: 0000000180150015 RSI: 0000000000000000 RDI: ffff8800c0bf6000 [21061.819598] RBP: ffff880352eafa30 R08: 0000000000000001 R09: 0000000000000000 [21061.819700] R10: ffff8803e116db00 R11: 0000000000000000 R12: ffff8800c0bf6000 [21061.819802] R13: 0000000000000006 R14: 0000000000000000 R15: ffff88041648d000 [21061.819906] FS: 00007fe6397a0780(0000) GS:ffff88042fc00000(0000) knlGS:0000000000000000 [21061.820021] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [21061.820106] CR2: 00000000000000f8 CR3: 000000032e72f000 CR4: 00000000000006f0 [21061.820208] Stack: [21061.820240] ffff880352eafb28 ffff8800c0bf6000 0000000000000006 ffff8803e13bc9c0 [21061.820359] ffff880352eafb10 ffffffffa021e163 ffff8802d913a480 0000000200000000 [21061.820508] ffffffff00020001 ffff8802d913a480 0000000000000000 ffff880352eafaa8 [21061.820627] Call Trace: [21061.820689] [] xfs_alloc_fix_freelist+0x243/0x400 [xfs] [21061.820817] [] ? xfs_buf_get_map+0x181/0x1e0 [xfs] [21061.820937] [] ? xfs_buf_rele+0x40/0x1a0 [xfs] [21061.821028] [] ? kmem_cache_alloc+0x1bc/0x1e0 [21061.821140] [] ? kmem_zone_alloc+0x78/0x120 [xfs] [21061.821258] [] ? xfs_perag_get+0x51/0xe0 [xfs] [21061.821369] [] xfs_free_extent+0x96/0x140 [xfs] [21061.821482] [] xfs_trans_free_extent+0x26/0x60 [xfs] [21061.821620] [] xlog_recover_process_efi+0x14e/0x1a0 [xfs] [21061.821746] [] xlog_recover_process_efis.isra.19+0x7b/0xe0 [xfs] [21061.821879] [] xlog_recover_finish+0x23/0xc0 [xfs] [21061.821994] [] ? xfs_rtmount_inodes+0x63/0x120 [xfs] [21061.822114] [] xfs_log_mount_finish+0x29/0x60 [xfs] [21061.822234] [] xfs_mountfs+0x594/0x860 [xfs] [21061.822350] [] xfs_fs_fill_super+0x3af/0x4e0 [xfs] [21061.822446] [] mount_bdev+0x17b/0x1c0 [21061.822549] [] ? xfs_parseargs+0xa60/0xa60 [xfs] [21061.822670] [] xfs_fs_mount+0x15/0x20 [xfs] [21061.822758] [] mount_fs+0x38/0x160 [21061.822833] [] ? alloc_vfsmnt+0x19a/0x240 [21061.822919] [] vfs_kern_mount+0x60/0x120 [21061.823003] [] do_mount+0x24e/0xe20 [21061.823079] [] ? mntput+0x24/0x40 [21061.823153] [] ? __fput+0x13d/0x1e0 [21061.823229] [] ? __kmalloc_track_caller+0x31/0x240 [21061.823325] [] ? memdup_user+0x42/0x80 [21061.823407] [] SyS_mount+0x98/0x100 [21061.823485] [] entry_SYSCALL_64_fastpath+0x12/0x6d [21061.823611] Code: e8 44 08 d7 e0 e9 50 ff ff ff 90 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 48 89 e5 41 56 41 55 49 89 f6 41 54 53 48 89 fb <4c> 8b ae f8 00 00 00 0f 1f 44 00 00 41 f6 45 78 04 74 5d 5b 41 [21061.824122] RIP [] xfs_trans_binval+0x16/0x120 [xfs] [21061.824245] RSP [21061.824296] CR2: 00000000000000f8 [21061.891732] ---[ end trace b716ae71022f5e63 ]--- From sandeen@sandeen.net Tue Jun 7 12:12:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id BD36A7CA0 for ; Tue, 7 Jun 2016 12:12:28 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 82DD0304039 for ; Tue, 7 Jun 2016 10:12:25 -0700 (PDT) X-ASG-Debug-ID: 1465319542-04cb6c2dbcbb9a90001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id R5UjzRJF6sjPyyDZ for ; Tue, 07 Jun 2016 10:12:22 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 54F2F873 for ; Tue, 7 Jun 2016 12:12:22 -0500 (CDT) Subject: Re: determining superblock version? To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: determining superblock version? References: <20160607125127.6dd23aef@harpe.intellique.com> From: Eric Sandeen Message-ID: Date: Tue, 7 Jun 2016 12:12:21 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160607125127.6dd23aef@harpe.intellique.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465319542 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2162 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30248 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/7/16 5:51 AM, Emmanuel Florac wrote: > Hi all, > > as you know kernel prior to 3.16 won't support properly v5 superblocks. > xfsprogs v 3.2.4 and higher defaults to v5 superblocks. This bit quite > a lot of people a year ago or so, when some distributions shipped 3.2.4 > xfsprogs with older kernels. > > Anyway, I was surprised to find no easy way to find out the superblock > version of an xfs FS. The best I've come across is > > xfs_db /dev/this > sb > p > > > versionnum = 0xb4a5 > There is certainly some confusion about naming. Version 5, compat/incompat features, feature bits, feature names, etc. > So I suppose that the 5 in the end means that the superblock is v5? Can > anyone confirm please? The man page still pretends that the last number > should be 1 to 4, which is confusing. Yes, the last bits contain the version number (masked by 0xf, see below) #define XFS_SB_VERSION_1 1 /* 5.3, 6.0.1, 6.1 */ #define XFS_SB_VERSION_2 2 /* 6.2 - attributes */ #define XFS_SB_VERSION_3 3 /* 6.2 - new inode version */ #define XFS_SB_VERSION_4 4 /* 6.2+ - bitmask version */ #define XFS_SB_VERSION_5 5 /* CRC enabled filesystem */ #define XFS_SB_VERSION_NUMBITS 0x000f feel free to send a man page patch :) > Oh by the way I think the trick to create a v4 filesystem with mkfs.xfs > higher than 3.2.4 ( mkfs.xfs -m crc=0,finobt=0 /dev/this ) should be in > the FAQ, with a line like this: > > Mounting the filesystem fails, and output from dmesg says "Version 5 > superblock detected." What should I do? > > v5 superblocks require a kernel v3.16 of higher. If you need your > xfs filesystem to be usable with older kernel, use the following > options to mkfs.xfs : > > mkfs.xfs -m crc=0,finobt=0 /dev/this finobt=0 should not be needed, it should be off if crc=0 AFAIK. However, -n ftype=1 may still be enabled, and older kernels may have an issue with that as well. Feel free to add this to the wiki (can new accounts still be created?) -Eric From reinoudkoornstra@gmail.com Tue Jun 7 18:40:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8A8B77CA0 for ; Tue, 7 Jun 2016 18:40:09 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 50C65304032 for ; Tue, 7 Jun 2016 16:40:06 -0700 (PDT) X-ASG-Debug-ID: 1465342804-04cbb03569bf8b50001-NocioJ Received: from mail-qg0-f53.google.com (mail-qg0-f53.google.com [209.85.192.53]) by cuda.sgi.com with ESMTP id TE4VXLngSNcnAArs (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 16:40:04 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qg0-f53.google.com[209.85.192.53] X-Barracuda-Apparent-Source-IP: 209.85.192.53 Received: by mail-qg0-f53.google.com with SMTP id p34so66726421qgp.1 for ; Tue, 07 Jun 2016 16:40:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=eCPHtV5QC9qVBTZrntpRFnse/jbBrWaOvfJJRJgjVfI=; b=WgfCiuyfFHqfJOpWWRcnasjV6q8YSOGMs7ofKO4fK53URHaHbAxdaU9NrOP/grXg0J X2eSXQxWcpKU3ogxGN4Gimp8UrJi8ujN+dwSrJ2gXSW3PRdnBkZi8WXb/WydrASDExnZ wCfwmttyWIZ5z7y4NDs2RRPeJk3nSrb2iZCcEJUXcppsUU0ZMaTrZeFv6iyg1Qyushjd /Qb8k9aNlb3CL+Qftz4HiMTXuIlHCS3nxk0LUzrf1RfHfpyPiKYg/NMUVlo8ywPZ//fL AhJov1Fsmdcb4tr7HEhe6oCr2MZ/H+1AIm1MMTiFRz8jbAeELunjjh+X4XUfviWSM/yO FJLQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=eCPHtV5QC9qVBTZrntpRFnse/jbBrWaOvfJJRJgjVfI=; b=Gr9JzxgRPtgIvKQjSVGfKrrXw9DednfD4nIDDcH40ryAr6oIq9fGDY7/1DMWgh/y6m kqLeZSzPS6PTQqoAPiConfNp75Z7x1t5g5Wz9jh4tah/iG50MQd9tKmKSQkzPNBEoVuB NCeCnCOb+5w8CpWv8jGoW6Gbw9YAqoEpJ/TlSCjfc6lKZTVhqWzzW584lKzWhXLCKUnw tfQarjn2pbQOmrMYgWRlqr8l7q/s9UE/arMglNGSRNdqBGhBHp0v7SxNR1MJrj7protn VtMxJVkacH5Qf3zixkvGq8uF2OAwJ4NGeRqEzJFmpurglS+TfX2RDJBARY0WNH+vngCJ bC3A== X-Gm-Message-State: ALyK8tIwV/gCtrzGmz2gEfXg+NWJnWp3Rz+yZS1KT+vZgvhVl/kuc8jCpKDClV47dvKP6i/nR+lmL0RpHw7mLQ== X-Received: by 10.140.108.183 with SMTP id j52mr2000114qgf.90.1465342804022; Tue, 07 Jun 2016 16:40:04 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.8.16 with HTTP; Tue, 7 Jun 2016 16:40:03 -0700 (PDT) In-Reply-To: <20160607134442.GA1803@infradead.org> References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> From: Reinoud Koornstra Date: Tue, 7 Jun 2016 17:40:03 -0600 Message-ID: Subject: Re: crash in xfs in current To: Christoph Hellwig X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Daniel Wagner , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qg0-f53.google.com[209.85.192.53] X-Barracuda-Start-Time: 1465342804 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2160 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30256 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature Hi Christoph, Now my git log show this: commit 555b67e4e729ca544bb4028ab12e532c68b70ddb Merge: 544ad71 ad438c4 Author: Dave Chinner Date: Fri May 20 10:34:00 2016 +1000 Merge branch 'xfs-4.7-inode-reclaim' into for-next commit 544ad71fc8e20fb3a6f50f00d487751492cd8409 Merge: 2a4ad58 e6b3bb7 Author: Dave Chinner Date: Fri May 20 10:33:38 2016 +1000 Merge branch 'xfs-4.7-error-cfg' into for-next commit 2a4ad5894c819978dca5595396d54d51c3aca694 Merge: a7792aa 6e3e6d5 Author: Dave Chinner Date: Fri May 20 10:33:17 2016 +1000 Merge branch 'xfs-4.7-misc-fixes' into for-next commit a7792aad644a259375002db8c9d9e03fd50bf509 Merge: 5b911354 3ab3ffc Author: Dave Chinner Date: Fri May 20 10:32:35 2016 +1000 Is this correct? If so, let me build and test. Building it already as we speak, but it would be nice if you could confirm I'm actually testing the right thing. Though, wouldn't it be good to repro and get a core file as well? Or would the test of this commit narrow down the possibilities as well? Thanks, Reinoud. On Tue, Jun 7, 2016 at 7:44 AM, Christoph Hellwig wrote: > On Tue, Jun 07, 2016 at 12:52:39PM +0200, Daniel Wagner wrote: >> >> I try to reproduce it on 4.6. My steps do not always trigger the crash. >> >> So I can't be really sure if 4.6 doesn't show it, it does not happen. >> > >> > I have never been able to trigger this in 4.6 and it's my failsafe >> > reboot (4.6.0). >> > In 4.7-rc1 it's just a matter of time before I hit it. >> > I do a lot of transactions, using git, extraction of tar.xz etc normally. >> >> This rings a bell. I though the lockperf tests triggered it. Before I >> compiled a new kernel I did a 'git checkout' step. > > Thanks for testing this to both of you. Can you try to build a kernel > from git commit 555b67e4e729ca544bb4028ab12e532c68b70ddb - this is the > XFS pull request that Dave sent to Linux for Linux 4.7-rc, so it has > all the XFS changes relative to 4.6, but none of the others like the VFS > changes. From reinoudkoornstra@gmail.com Tue Jun 7 23:16:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6A0307CA0 for ; Tue, 7 Jun 2016 23:16:08 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3DC8E304051 for ; Tue, 7 Jun 2016 21:16:05 -0700 (PDT) X-ASG-Debug-ID: 1465359362-04cbb03569c033f0001-NocioJ Received: from mail-qt0-f179.google.com (mail-qt0-f179.google.com [209.85.216.179]) by cuda.sgi.com with ESMTP id tXD2WSjCDFU39FQY (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 21:16:03 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qt0-f179.google.com[209.85.216.179] X-Barracuda-Apparent-Source-IP: 209.85.216.179 Received: by mail-qt0-f179.google.com with SMTP id q45so27164054qtq.1 for ; Tue, 07 Jun 2016 21:16:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=S8QSuZqXvVd0ydBkX6gzQ38JRdox2PhI6uBOY0Oz/gc=; b=IsvlU23CQXfrZWCXGzCHYR5hbolU+bABtgOvXiLfqAR1X0T2Y0Jfxgamw+ct+9TXIQ iYjMdoRbOmMgnzvpKUulhiZzKGKtJs/3a92On9w09AoKQ2xyzkFNUAXi8BRN+LET5ZCs 4dtijvCcZzjQuFCMoRn69CwjVc4sCsUX9pDDjnSc4T+sghIgXaOm3DzDO7ZYSE4VlwXH KUgmShxL9baDDAK6rOUD5g29ohDwpD1bt1lhInx+9qKL502RpCp+I3Jf8uhOfKWpS8k3 evJzAE6ZnaO7idGzzN5QRQL1jpds3YVS5kPBXY3iXNXTR2FN9H4IKWRxWNMaKTlUsqSo UvXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=S8QSuZqXvVd0ydBkX6gzQ38JRdox2PhI6uBOY0Oz/gc=; b=m7ei6vVOreRXaERg7pehoIkOMIcE0MiwNztifSwQrOi8OSiV08oLYezCly2WsYdVzI B3E/BYU7hShiSVzCgqaOvinjLaRWlbuXZWV7wUgT41UpfM4afCnwo/jQ0XgN2Cg+OezL q63qc8bs8RklTkbxd8B3IVO6WRelCV33QIuzt01S+pCo0NHe77B4K/aBukzvE0OOczPZ kJx3lc/T1e59L7/I4ylx7v/gQfCHIqCzGNQusSAFZVhpJpKMCUa7kBuKBor37qVwvZkO 0W2ZMk6tqSIY/sl3ev8rrmNGXZnk7G+HqPLlJAZa6i0wA7z11TPvW6KGoT3mUAQhfOlS HiJg== X-Gm-Message-State: ALyK8tJV0srY8hRfdgl5Aonjn/cpUyzer8nu/eC0rT2sinPX54KZv41zbFPPpAz3QKAYq3ADF0z3CQtGDpJfpw== X-Received: by 10.237.56.225 with SMTP id k88mr2628040qte.86.1465359362488; Tue, 07 Jun 2016 21:16:02 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.8.16 with HTTP; Tue, 7 Jun 2016 21:16:01 -0700 (PDT) In-Reply-To: References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> From: Reinoud Koornstra Date: Tue, 7 Jun 2016 22:16:01 -0600 Message-ID: Subject: Re: crash in xfs in current To: Christoph Hellwig X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Daniel Wagner , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qt0-f179.google.com[209.85.216.179] X-Barracuda-Start-Time: 1465359363 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2531 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30261 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Tue, Jun 7, 2016 at 5:40 PM, Reinoud Koornstra wrote: > Hi Christoph, > > Now my git log show this: > > commit 555b67e4e729ca544bb4028ab12e532c68b70ddb > Merge: 544ad71 ad438c4 > Author: Dave Chinner > Date: Fri May 20 10:34:00 2016 +1000 > > Merge branch 'xfs-4.7-inode-reclaim' into for-next > > commit 544ad71fc8e20fb3a6f50f00d487751492cd8409 > Merge: 2a4ad58 e6b3bb7 > Author: Dave Chinner > Date: Fri May 20 10:33:38 2016 +1000 > > Merge branch 'xfs-4.7-error-cfg' into for-next > > commit 2a4ad5894c819978dca5595396d54d51c3aca694 > Merge: a7792aa 6e3e6d5 > Author: Dave Chinner > Date: Fri May 20 10:33:17 2016 +1000 > > Merge branch 'xfs-4.7-misc-fixes' into for-next > > commit a7792aad644a259375002db8c9d9e03fd50bf509 > Merge: 5b911354 3ab3ffc > Author: Dave Chinner > Date: Fri May 20 10:32:35 2016 +1000 > > Is this correct? > If so, let me build and test. > Building it already as we speak, but it would be nice if you could > confirm I'm actually testing the right thing. > Though, wouldn't it be good to repro and get a core file as well? > Or would the test of this commit narrow down the possibilities as well? > Thanks, > > Reinoud. > Ouch, forgive me for not responding inline previously. For what it's worth, i've compiled the kernel and are running it as we speak. Will do testing and let you know. Thanks, Reinoud. > On Tue, Jun 7, 2016 at 7:44 AM, Christoph Hellwig wrote: >> On Tue, Jun 07, 2016 at 12:52:39PM +0200, Daniel Wagner wrote: >>> >> I try to reproduce it on 4.6. My steps do not always trigger the crash. >>> >> So I can't be really sure if 4.6 doesn't show it, it does not happen. >>> > >>> > I have never been able to trigger this in 4.6 and it's my failsafe >>> > reboot (4.6.0). >>> > In 4.7-rc1 it's just a matter of time before I hit it. >>> > I do a lot of transactions, using git, extraction of tar.xz etc normally. >>> >>> This rings a bell. I though the lockperf tests triggered it. Before I >>> compiled a new kernel I did a 'git checkout' step. >> >> Thanks for testing this to both of you. Can you try to build a kernel >> from git commit 555b67e4e729ca544bb4028ab12e532c68b70ddb - this is the >> XFS pull request that Dave sent to Linux for Linux 4.7-rc, so it has >> all the XFS changes relative to 4.6, but none of the others like the VFS >> changes. From reinoudkoornstra@gmail.com Tue Jun 7 23:40:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 785D57CA0 for ; Tue, 7 Jun 2016 23:40:18 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id D033FAC001 for ; Tue, 7 Jun 2016 21:40:14 -0700 (PDT) X-ASG-Debug-ID: 1465360812-04cb6c2dbabcfcf0001-NocioJ Received: from mail-qk0-f175.google.com (mail-qk0-f175.google.com [209.85.220.175]) by cuda.sgi.com with ESMTP id HpjNssv9T4qbIFlg (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 21:40:12 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qk0-f175.google.com[209.85.220.175] X-Barracuda-Apparent-Source-IP: 209.85.220.175 Received: by mail-qk0-f175.google.com with SMTP id p22so52221163qka.2 for ; Tue, 07 Jun 2016 21:40:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=hEl30Bgh+ei/fGqyUXTUYo0KrJZcfv3CIeEPs6HGzFg=; b=Yc2iLs5FsogSMJLc6LZs8/D3djx2IXzuvgWIJa5UNdlktyK8KdK2xarvKatagLQHRS 70GGhKmwRibIoFERLPbePm/3LqIc5g5Ro74HT53cmdCVKGxvMfvJIZ8JEVqrNiUKJx4m hYLXOcXb6679bBg7SsT3jNdC3C2QrKm2D2VuRc++RXWmAkViDO/SS1MptQMeaYlQiZ8l AqPXkbMtIOypOpApaX4zXTSuOQqmhHL4EwQWBpNoNHw9S62IUpei3ZfvMT12A2wQM6jZ EfdOC8OYkTYnj518rYSL8kBAQ9rsC+iGUpUA5aka1JN84Khxd21eSTKUWSsOxLZhUWCD 2+TQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=hEl30Bgh+ei/fGqyUXTUYo0KrJZcfv3CIeEPs6HGzFg=; b=j1a2Hy4GI+d2cLqNf9byf+a77WH6UZpIbBUc8Hp7nSNYYUNQzUv8u1D+AbHSfZYVAy fRZQ2W1OmMg4fOBhmX7guzP/XYhfPHmiwRe9klFHC6TEYIpPUcgneqYqEYgU8BHdSpnT GsWN62efNNVGQqW58V30IjUZsViVyBOwBeB1+LMsrysTYiep5LA6IQ+gPXgEP+mY6YCK PwTCPIxDPCXsJFlZO5ryEgarJ6R4j/gVEuYEw93jGS/o5Ze5EBoTuXtQlBTiOZX9TL3H xJnTg01TXUDw1H0VgyjMJoGuwvAzhTqiR/jAvhhyxzwvgvLnLRNoCXYkouEiBeIhDIi2 aN+g== X-Gm-Message-State: ALyK8tL8FuR4fViQy1Qhhoy2Pk2bEJDfjPlWd1YbtPsvl87C+LQ+nLEeHcs5idcCIUYxKG1gUdAY8NDMKL9www== X-Received: by 10.55.154.142 with SMTP id c136mr2879346qke.63.1465360812394; Tue, 07 Jun 2016 21:40:12 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.8.16 with HTTP; Tue, 7 Jun 2016 21:40:11 -0700 (PDT) In-Reply-To: References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> From: Reinoud Koornstra Date: Tue, 7 Jun 2016 22:40:11 -0600 Message-ID: Subject: Re: crash in xfs in current To: Christoph Hellwig X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Daniel Wagner , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qk0-f175.google.com[209.85.220.175] X-Barracuda-Start-Time: 1465360812 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2967 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30262 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Tue, Jun 7, 2016 at 10:16 PM, Reinoud Koornstra wrote: > On Tue, Jun 7, 2016 at 5:40 PM, Reinoud Koornstra > wrote: >> Hi Christoph, >> >> Now my git log show this: >> >> commit 555b67e4e729ca544bb4028ab12e532c68b70ddb >> Merge: 544ad71 ad438c4 >> Author: Dave Chinner >> Date: Fri May 20 10:34:00 2016 +1000 >> >> Merge branch 'xfs-4.7-inode-reclaim' into for-next >> >> commit 544ad71fc8e20fb3a6f50f00d487751492cd8409 >> Merge: 2a4ad58 e6b3bb7 >> Author: Dave Chinner >> Date: Fri May 20 10:33:38 2016 +1000 >> >> Merge branch 'xfs-4.7-error-cfg' into for-next >> >> commit 2a4ad5894c819978dca5595396d54d51c3aca694 >> Merge: a7792aa 6e3e6d5 >> Author: Dave Chinner >> Date: Fri May 20 10:33:17 2016 +1000 >> >> Merge branch 'xfs-4.7-misc-fixes' into for-next >> >> commit a7792aad644a259375002db8c9d9e03fd50bf509 >> Merge: 5b911354 3ab3ffc >> Author: Dave Chinner >> Date: Fri May 20 10:32:35 2016 +1000 >> >> Is this correct? >> If so, let me build and test. >> Building it already as we speak, but it would be nice if you could >> confirm I'm actually testing the right thing. >> Though, wouldn't it be good to repro and get a core file as well? >> Or would the test of this commit narrow down the possibilities as well? >> Thanks, >> >> Reinoud. >> > > Ouch, forgive me for not responding inline previously. > For what it's worth, i've compiled the kernel and are running it as we speak. > Will do testing and let you know. Ok, going back to commit 555b67e4e729ca544bb4028ab12e532c68b70ddb brings the kernel back to 4.6-rc1. With that kernel I crash all over the place, so that's something I cannot run. Is there a way to get the 4.7-rc1 or rc2 without the commits for XFS? Reinoud. > Thanks, > > Reinoud. > >> On Tue, Jun 7, 2016 at 7:44 AM, Christoph Hellwig wrote: >>> On Tue, Jun 07, 2016 at 12:52:39PM +0200, Daniel Wagner wrote: >>>> >> I try to reproduce it on 4.6. My steps do not always trigger the crash. >>>> >> So I can't be really sure if 4.6 doesn't show it, it does not happen. >>>> > >>>> > I have never been able to trigger this in 4.6 and it's my failsafe >>>> > reboot (4.6.0). >>>> > In 4.7-rc1 it's just a matter of time before I hit it. >>>> > I do a lot of transactions, using git, extraction of tar.xz etc normally. >>>> >>>> This rings a bell. I though the lockperf tests triggered it. Before I >>>> compiled a new kernel I did a 'git checkout' step. >>> >>> Thanks for testing this to both of you. Can you try to build a kernel >>> from git commit 555b67e4e729ca544bb4028ab12e532c68b70ddb - this is the >>> XFS pull request that Dave sent to Linux for Linux 4.7-rc, so it has >>> all the XFS changes relative to 4.6, but none of the others like the VFS >>> changes. From BATV+10e0b2ba6b8830823af0+4672+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 8 00:40:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C01827CA0 for ; Wed, 8 Jun 2016 00:40:38 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 80C198F8033 for ; Tue, 7 Jun 2016 22:40:35 -0700 (PDT) X-ASG-Debug-ID: 1465364433-04bdf05ad5be4820001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id p40gQGnXH3hIF997 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 07 Jun 2016 22:40:33 -0700 (PDT) X-Barracuda-Envelope-From: BATV+10e0b2ba6b8830823af0+4672+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bAWEA-0008GH-Hj; Wed, 08 Jun 2016 05:40:30 +0000 Date: Tue, 7 Jun 2016 22:40:30 -0700 From: Christoph Hellwig To: Reinoud Koornstra Cc: Christoph Hellwig , Daniel Wagner , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk Subject: Re: crash in xfs in current Message-ID: <20160608054030.GA27069@infradead.org> X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1465364433 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 996 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30263 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Tue, Jun 07, 2016 at 10:40:11PM -0600, Reinoud Koornstra wrote: > >> Is this correct? That's correct! > >> If so, let me build and test. > >> Building it already as we speak, but it would be nice if you could > >> confirm I'm actually testing the right thing. > >> Though, wouldn't it be good to repro and get a core file as well? > >> Or would the test of this commit narrow down the possibilities as well? > >> Thanks, > >> > >> Reinoud. > >> > > > > Ouch, forgive me for not responding inline previously. > > For what it's worth, i've compiled the kernel and are running it as we speak. > > Will do testing and let you know. > > Ok, going back to commit 555b67e4e729ca544bb4028ab12e532c68b70ddb > brings the kernel back to 4.6-rc1. > With that kernel I crash all over the place, so that's something I cannot run. Oh. What kinds of crashes? > Is there a way to get the 4.7-rc1 or rc2 without the commits for XFS? I can't think of a good way unfortunately. From BATV+10e0b2ba6b8830823af0+4672+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 8 02:03:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7FE097CA0 for ; Wed, 8 Jun 2016 02:03:48 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 51C9A8F804C for ; Wed, 8 Jun 2016 00:03:45 -0700 (PDT) X-ASG-Debug-ID: 1465369422-04cb6c2dbbbd4500001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id pL8q814AKTByEv1J (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 08 Jun 2016 00:03:43 -0700 (PDT) X-Barracuda-Envelope-From: BATV+10e0b2ba6b8830823af0+4672+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bAXWd-0005Nm-Di; Wed, 08 Jun 2016 07:03:39 +0000 Date: Wed, 8 Jun 2016 00:03:39 -0700 From: Christoph Hellwig To: Gwendal Grignou Cc: hch@infradead.org, vapier@gentoo.org, tytso@mit.edu, fstests@vger.kernel.org, xfs@oss.sgi.com Subject: Re: [PATCH] Allow compiling xfsprogs in a cross compile environment. Message-ID: <20160608070339.GB18458@infradead.org> X-ASG-Orig-Subj: Re: [PATCH] Allow compiling xfsprogs in a cross compile environment. References: <1465000276-16554-1-git-send-email-gwendal@chromium.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1465000276-16554-1-git-send-email-gwendal@chromium.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1465369423 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 60 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30265 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS Looks fine, Reviewed-by: Christoph Hellwig From BATV+10e0b2ba6b8830823af0+4672+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 8 02:05:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A6C5E7CA0 for ; Wed, 8 Jun 2016 02:05:04 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 62FE0304039 for ; Wed, 8 Jun 2016 00:05:01 -0700 (PDT) X-ASG-Debug-ID: 1465369499-04bdf05ad5be86e0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id dtMTzfrtz4DjLSaz (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 08 Jun 2016 00:04:59 -0700 (PDT) X-Barracuda-Envelope-From: BATV+10e0b2ba6b8830823af0+4672+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bAXXv-0005TG-Dg; Wed, 08 Jun 2016 07:04:59 +0000 Date: Wed, 8 Jun 2016 00:04:59 -0700 From: Christoph Hellwig To: xfs@oss.sgi.com, cmaiolino@redhat.com Subject: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-ID: <20160608070459.GC18458@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time References: <1464877150-20457-1-git-send-email-hch@lst.de> <1464877150-20457-4-git-send-email-hch@lst.de> <20160606112342.GB23695@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160606112342.GB23695@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1465369499 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 180 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.60 X-Barracuda-Spam-Status: No, SCORE=2.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_SA606_RN_OB, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30265 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 2.00 BSF_SC0_SA606_RN_OB Custom Outbreak Rule SA606_RN_OB Yes, the comment is wrong. Any reason you didn't include me in the reply? Also it seems your reply-to also magically drops you from the reply. Are you using a new mailer? :) From hch@lst.de Wed Jun 8 02:10:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C2DD37CA0 for ; Wed, 8 Jun 2016 02:10:10 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 67D728F8033 for ; Wed, 8 Jun 2016 00:10:10 -0700 (PDT) X-ASG-Debug-ID: 1465369804-04bdf05ad4be8ad0001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id LSjjIjUspQRz5sDG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 00:10:06 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id EDDAF68D3A; Wed, 8 Jun 2016 09:10:03 +0200 (CEST) Date: Wed, 8 Jun 2016 09:10:03 +0200 From: Christoph Hellwig To: "Darrick J. Wong" Cc: Dave Chinner , Christoph Hellwig , xfs@oss.sgi.com Subject: Re: [RFC] allow enabling reflinks at runtime Message-ID: <20160608071003.GA24663@lst.de> X-ASG-Orig-Subj: Re: [RFC] allow enabling reflinks at runtime References: <1464877150-20457-1-git-send-email-hch@lst.de> <20160602225415.GP12670@dastard> <20160603015832.GA5758@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160603015832.GA5758@birch.djwong.org> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1465369806 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2234 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30265 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 02, 2016 at 06:58:33PM -0700, Darrick J. Wong wrote: > On Fri, Jun 03, 2016 at 08:54:15AM +1000, Dave Chinner wrote: > > On Thu, Jun 02, 2016 at 04:19:07PM +0200, Christoph Hellwig wrote: > > > I've had some vocal user requests to allow enabling reflinks at run time, > > > which happens to be a mostly trivial feature. The only caveat is that we > > > need a large enough log size to support the reflink requirements, but for > > > typical large file systems that's not an issue. > > > > Hmmm - how does this interact with all the rmap code? I was not > > planning on enabling reflink without rmap and vice versa simply > > because it makes the validation and testing matrix vastly more > > complex. Indeed, having reflink turned on after a filesystem has > > aged for some time (i.e. from unknown initial conditions) makes > > validation especially tricky.... > > Well... > > It's not strictly impossible, but there will be some problems running > repair and remounting. > > The patchset doesn't actually check that we satisfy the minimum log > space requirement, which will result in xfs refusing to mount. As > Christoph says, this is only an issue on small FSes, but nevertheless, > we shouldn't trap the user like that. xfs_log_mount always verified the required log size. > Second, mkfs lays out all the AG btree roots at the start of the AG > before finding an aligned inode block for the root inode. xfs_repair > feeds the same algorithm from the on-disk feature fields to check that > s_rootino is sane, and gets very unhappy if it doesn't find the root > inode at the computed location. Adding the two btree root blocks is > enough to shift the root inode from 96 to 128. This all can be fixed, > but it /was/ convenient not to have to support weirdo upgraded XFSes > like ext4. :) Yes, that algorithm might be unhappy, but I don't think it's overly smart to rely on it either. > Furthermore, if you turn on reflink, you should enable the per-AG > reservations so we don't crash the FS by running out of space when it > needs a block for the refcountbt. xfs_refcountbt_calc_reserves is switched to use xfs_mp_hasreflink, so it will do the right thing. From hch@lst.de Wed Jun 8 02:11:37 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1FB3D7CA0 for ; Wed, 8 Jun 2016 02:11:37 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8B115AC001 for ; Wed, 8 Jun 2016 00:11:33 -0700 (PDT) X-ASG-Debug-ID: 1465369890-04cb6c2dbcbd4a20001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id r6WKqZjgar15zAPH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 00:11:31 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 440FE68D3A; Wed, 8 Jun 2016 09:11:30 +0200 (CEST) Date: Wed, 8 Jun 2016 09:11:30 +0200 From: Christoph Hellwig To: Dave Chinner Cc: darrick.wong@oracle.com, xfs@oss.sgi.com Subject: Re: [RFC] allow enabling reflinks at runtime Message-ID: <20160608071130.GB24663@lst.de> X-ASG-Orig-Subj: Re: [RFC] allow enabling reflinks at runtime References: <1464877150-20457-1-git-send-email-hch@lst.de> <20160602225415.GP12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160602225415.GP12670@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1465369891 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 891 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30265 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 03, 2016 at 08:54:15AM +1000, Dave Chinner wrote: > On Thu, Jun 02, 2016 at 04:19:07PM +0200, Christoph Hellwig wrote: > > I've had some vocal user requests to allow enabling reflinks at run time, > > which happens to be a mostly trivial feature. The only caveat is that we > > need a large enough log size to support the reflink requirements, but for > > typical large file systems that's not an issue. > > Hmmm - how does this interact with all the rmap code? I was not > planning on enabling reflink without rmap and vice versa simply > because it makes the validation and testing matrix vastly more > complex. Uh. So far I've only been testing pure reflink code, mostly because rmap really doesn't buy much for the use case I'm working on. Enabling rmap post-mkfs is defintively a different ballpark, and probably not worth it even if it would be doable. From cmaiolino@redhat.com Wed Jun 8 03:07:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C89167CA0 for ; Wed, 8 Jun 2016 03:07:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8A047304051 for ; Wed, 8 Jun 2016 01:07:08 -0700 (PDT) X-ASG-Debug-ID: 1465373227-04cbb03568c0ef00001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id tM4A2buqJoW3rZRE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 01:07:07 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 13D3CC0003FE for ; Wed, 8 Jun 2016 08:07:07 +0000 (UTC) Received: from redhat.com (vpn-48-2.rdu2.redhat.com [10.10.48.2]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u58873vt013585 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 8 Jun 2016 04:07:06 -0400 Date: Wed, 8 Jun 2016 10:07:03 +0200 From: Carlos Maiolino To: xfs@oss.sgi.com Subject: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-ID: <20160608080703.GA8987@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Mail-Followup-To: xfs@oss.sgi.com References: <1464877150-20457-1-git-send-email-hch@lst.de> <1464877150-20457-4-git-send-email-hch@lst.de> <20160606112342.GB23695@redhat.com> <20160608070459.GC18458@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160608070459.GC18458@infradead.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Wed, 08 Jun 2016 08:07:07 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465373227 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 448 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 08, 2016 at 12:04:59AM -0700, Christoph Hellwig wrote: > Yes, the comment is wrong. Any reason you didn't include me in the > reply? Also it seems your reply-to also magically drops you > from the reply. Are you using a new mailer? :) No, no reason, I missed to CC you. Maybe my CTRL-L list-reply in mutt screwed up with the destination fields, I should come back to group replies, thanks for the heads up :) -- Carlos From cmaiolino@redhat.com Wed Jun 8 03:10:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 7CB0C7CA1 for ; Wed, 8 Jun 2016 03:10:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3CF4B304066 for ; Wed, 8 Jun 2016 01:10:13 -0700 (PDT) X-ASG-Debug-ID: 1465373412-04bdf05ad4bebdf0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id btRpMpSLAqlxfTEk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 01:10:12 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EA96580B56; Wed, 8 Jun 2016 08:10:11 +0000 (UTC) Received: from redhat.com (vpn-48-2.rdu2.redhat.com [10.10.48.2]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u588A7C2024415 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 8 Jun 2016 04:10:10 -0400 Date: Wed, 8 Jun 2016 10:10:07 +0200 From: Carlos Maiolino To: xfs@oss.sgi.com Cc: hch@infradead.org Subject: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-ID: <20160608081007.GB8987@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Mail-Followup-To: xfs@oss.sgi.com, hch@infradead.org References: <1464877150-20457-1-git-send-email-hch@lst.de> <1464877150-20457-4-git-send-email-hch@lst.de> <20160606112342.GB23695@redhat.com> <20160608070459.GC18458@infradead.org> <20160608080703.GA8987@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160608080703.GA8987@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Wed, 08 Jun 2016 08:10:11 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465373412 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 746 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 08, 2016 at 10:07:03AM +0200, Carlos Maiolino wrote: > On Wed, Jun 08, 2016 at 12:04:59AM -0700, Christoph Hellwig wrote: > > Yes, the comment is wrong. Any reason you didn't include me in the > > reply? Also it seems your reply-to also magically drops you > > from the reply. Are you using a new mailer? :) > > No, no reason, I missed to CC you. Maybe my CTRL-L list-reply in mutt screwed up > with the destination fields, I should come back to group replies, thanks for the > heads up :) Oh crap, I did it again, ok, no more list-reply for me > > -- > Carlos > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From kenn.anthoony@ms32.hinet.net Wed Jun 8 03:28:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FREEMAIL_FROM,FREEMAIL_REPLYTO, HTML_MESSAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 25E917CA1 for ; Wed, 8 Jun 2016 03:28:35 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id E8EC08F8049 for ; Wed, 8 Jun 2016 01:28:31 -0700 (PDT) X-ASG-Debug-ID: 1465374505-04cbb03569c0f6b0001-NocioJ Received: from mserver.oleaginosa.com (mserver.oleaginosa.com [200.85.50.26]) by cuda.sgi.com with ESMTP id vwWMNCklgkdToeo5; Wed, 08 Jun 2016 01:28:25 -0700 (PDT) X-Barracuda-Envelope-From: kenn.anthoony@ms32.hinet.net X-Barracuda-Effective-Source-IP: mserver.oleaginosa.com[200.85.50.26] X-Barracuda-Apparent-Source-IP: 200.85.50.26 Received: from localhost (localhost.localdomain [127.0.0.1]) by mserver.oleaginosa.com (Postfix) with ESMTP id 64072A299BB; Tue, 7 Jun 2016 21:23:36 -0400 (PYT) X-Virus-Scanned: amavisd-new at oleaginosa.com Received: from mserver.oleaginosa.com ([127.0.0.1]) by localhost (mx1.orsa.local [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id fimd6YahDH_n; Tue, 7 Jun 2016 21:23:36 -0400 (PYT) Received: from localhost (localhost.localdomain [127.0.0.1]) by mserver.oleaginosa.com (Postfix) with ESMTP id 0401FA29988; Tue, 7 Jun 2016 21:23:36 -0400 (PYT) X-Virus-Scanned: amavisd-new at oleaginosa.com Received: from mserver.oleaginosa.com ([127.0.0.1]) by localhost (mx1.orsa.local [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id esnq5-5lb0Ff; Tue, 7 Jun 2016 21:23:35 -0400 (PYT) Received: from [5.196.36.215] (unknown [5.196.36.215]) by mserver.oleaginosa.com (Postfix) with ESMTPSA id 9E9E1A28BC9; Tue, 7 Jun 2016 21:23:22 -0400 (PYT) Content-Type: multipart/alternative; boundary="===============0815524503==" MIME-Version: 1.0 Subject: work from home To: Recipients X-ASG-Orig-Subj: work from home From: "Kenn Anthony" Date: Tue, 07 Jun 2016 18:27:24 -0700 Reply-To: kenn.anthony@hotmail.com Message-Id: <20160608012322.9E9E1A28BC9@mserver.oleaginosa.com> X-Barracuda-Connect: mserver.oleaginosa.com[200.85.50.26] X-Barracuda-Start-Time: 1465374505 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 52 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.50 X-Barracuda-Spam-Status: No, SCORE=0.50 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_ADDR_MATCH, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30266 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message 0.50 BSF_SC0_SA_TO_FROM_ADDR_MATCH Sender Address Matches Recipient Address You will not see this in a MIME-aware mail reader. --===============0815524503== Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body My name is Mr Kenn Anthony,I work for Koffi Trade Sarl. I am presently the recruite officer for the company. The company needs an honest representative in you country and can work from home. This is a part-time job and a work from home. It does not require you to make any payment but you will be receiving commission and weekly allowance for your service. If you are interested,Get back to me via my email. Mr Kenn Anthony Email: kenn.anthony@hotmail.com --===============0815524503== Content-Type: text/html; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body

My name is Mr Kenn Anthony,I work for Koffi= Trade Sarl.
I am presently the recruite officer for the company.
The= company
needs an honest representative in you country and can work from= home.

This is a part-time job and a work from hom= e.

It does not require you to make any payment= but you will be receiving
commission and weekly allowance for your
s= ervice.

If you are interested,Get back to me via my= email.
Mr Kenn Anthony
Email:
kenn.anthony@hotmail.com

--===============0815524503==-- From ntamplin@codefaber.co.uk Wed Jun 8 06:16:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EEBA07CA0 for ; Wed, 8 Jun 2016 06:16:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id BC9058F8033 for ; Wed, 8 Jun 2016 04:16:41 -0700 (PDT) X-ASG-Debug-ID: 1465384598-04cb6c2dbcbde870001-NocioJ Received: from mk-outboundfilter-4.mail.uk.tiscali.com (mk-outboundfilter-4.mail.uk.tiscali.com [212.74.114.32]) by cuda.sgi.com with ESMTP id JBi0ae3FmQNipATi for ; Wed, 08 Jun 2016 04:16:39 -0700 (PDT) X-Barracuda-Envelope-From: ntamplin@codefaber.co.uk X-Barracuda-Effective-Source-IP: mk-outboundfilter-4.mail.uk.tiscali.com[212.74.114.32] X-Barracuda-Apparent-Source-IP: 212.74.114.32 X-Trace: 329262592/mk-outboundfilter-2.mail.uk.tiscali.com/F2S/$THROTTLED_STATIC/TalkTalk_Customers/92.27.244.57/-4.6/ntamplin@codefaber.co.uk X-SBRS: -4.6 X-RemoteIP: 92.27.244.57 X-IP-MAIL-FROM: ntamplin@codefaber.co.uk X-SMTP-AUTH: X-MUA: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.8.0 X-IP-BHB: Once X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0AgBgDU/VdXNjn0G1xdwhOGE4IKAQEBAQEBBwEBAQEiYIRvFR4iNgIFFgsCCwMCAQIBJwonCAKIL5t6j2KRW4EBhSaId0KCVYJZBZhPi2qEPIc2DoVbj2GCCoEDgTY7ikEBAQE X-IPAS-Result: A0AgBgDU/VdXNjn0G1xdwhOGE4IKAQEBAQEBBwEBAQEiYIRvFR4iNgIFFgsCCwMCAQIBJwonCAKIL5t6j2KRW4EBhSaId0KCVYJZBZhPi2qEPIc2DoVbj2GCCoEDgTY7ikEBAQE X-IronPort-AV: E=Sophos;i="5.26,438,1459810800"; d="scan'208";a="329262592" X-IP-Direction: IN Received: from host-92-27-244-57.static.as13285.net (HELO mail.codefaber.co.uk) ([92.27.244.57]) by smtp.f2s.tiscali.co.uk with ESMTP; 08 Jun 2016 12:16:37 +0100 Received: from [192.168.10.10] by host-92-27-244-57.static.as13285.net with esmtpsa (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1bAbT5-000813-SN for xfs@oss.sgi.com; Wed, 08 Jun 2016 12:16:16 +0100 To: xfs@oss.sgi.com From: Nigel Tamplin Subject: invalid inode numbers ? after drive moved from Linux 2.6.32 to Linux 3.16.0 then back again Message-ID: <5757FE7A.8020504@codefaber.co.uk> X-ASG-Orig-Subj: invalid inode numbers ? after drive moved from Linux 2.6.32 to Linux 3.16.0 then back again Date: Wed, 8 Jun 2016 12:16:10 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.8.0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mk-outboundfilter-4.mail.uk.tiscali.com[212.74.114.32] X-Barracuda-Start-Time: 1465384598 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3523 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30269 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Hello, I have a drive with a partition containing an XFS file system. This drive normally resides in a Linux 2.6.32 (Debian 6) server, which is also where the file system was created many months ago. Last week I removed this drive from it's usual 2.6.32 server and for a few hours it was attached to an alternative Linux 3.16.0 (Debian 8) server, where the XFS file system was mounted and during this time I created /modified / deleted some files. Later the drive was moved back to the normal Linux 2.6.32. I've noticed something strange has happened. Some (maybe all) of the files worked on whilst the drive was in the Linux 3.16.0 are not accessible when the file system is mounted on the Linux 2.6.32. If I put the drive back in the 3.16.0 server, all files are again accessible. The few files which are inaccessible on 2.6.32 seem to have no inodes when viewed under 2.6.32 but look ok when the drive is in 3.16.0 "ls -li" on 3.16.0 7249604387 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 01 104207 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 02 101524 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 03 2220005080 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 06 5637828101 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 07 1344499710 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 09 2958135019 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 0b 7516254020 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 0c 5905580833 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 0f 3494120096 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 10 1988369908 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 12 2446706848 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 13 2446706832 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 14 5905580836 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 16 807056393 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 17 2688006922 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 18 "ls -li" on 2.6.32 ? ?????????? ? ? ? ? ? 01 104207 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 02 101524 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 03 2220005080 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 06 ? ?????????? ? ? ? ? ? 07 1344499710 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 09 2958135019 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 0b ? ?????????? ? ? ? ? ? 0c ? ?????????? ? ? ? ? ? 0f 3494120096 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 10 1988369908 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 12 2446706848 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 13 2446706832 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 14 ? ?????????? ? ? ? ? ? 16 807056393 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 17 2688006922 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 18 I notice that the files created on 3.16.0 which cannot be accessed on 2.6.32, seem to have much higher inode numbers than those which can be accessed on both systems. Could the numbers chosen by 3.16.0 be overflowing on 2.6.32 ? I experimented on another almost empty file system, and this seems fine in both systems, but this has very low inode numbers, hence my inode number idea. I can attach the drive to either system and run diagnostic commands if more information is required. Regards, Nigel From cmaiolino@redhat.com Wed Jun 8 06:49:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 553D77CA0 for ; Wed, 8 Jun 2016 06:49:14 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id D4B09AC004 for ; Wed, 8 Jun 2016 04:49:13 -0700 (PDT) X-ASG-Debug-ID: 1465386552-04bdf05ad5bf4370001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 4b7sKzMjp9BfkGbs (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 04:49:13 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8B06D85367; Wed, 8 Jun 2016 11:49:12 +0000 (UTC) Received: from redhat.com (vpn-48-2.rdu2.redhat.com [10.10.48.2]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u58Bn8pd003945 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 8 Jun 2016 07:49:11 -0400 Date: Wed, 8 Jun 2016 13:49:07 +0200 From: Carlos Maiolino To: Nigel Tamplin Cc: xfs@oss.sgi.com Subject: Re: invalid inode numbers ? after drive moved from Linux 2.6.32 to Linux 3.16.0 then back again Message-ID: <20160608114907.GC8987@redhat.com> X-ASG-Orig-Subj: Re: invalid inode numbers ? after drive moved from Linux 2.6.32 to Linux 3.16.0 then back again Mail-Followup-To: Nigel Tamplin , xfs@oss.sgi.com References: <5757FE7A.8020504@codefaber.co.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <5757FE7A.8020504@codefaber.co.uk> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 08 Jun 2016 11:49:12 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465386553 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4327 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 08, 2016 at 12:16:10PM +0100, Nigel Tamplin wrote: > Hello, > > I have a drive with a partition containing an XFS file system. > This drive normally resides in a Linux 2.6.32 (Debian 6) server, which is > also where the file system was created many months ago. > Last week I removed this drive from it's usual 2.6.32 server and for a few > hours it was attached to an alternative Linux 3.16.0 (Debian 8) server, > where the XFS file system was mounted and during this time I created > /modified / deleted some files. > Later the drive was moved back to the normal Linux 2.6.32. > Linux 3.16 has inode64 mount option enabled by default, which will cause inodes to be spread along the whole disk, causing some inodes (those allocated on disk blocks beyond 1TB offset) to have 64bit numbers. 2.6.32 doesn't use inode64 option by default, and so, files with inodes > 2^32 will not be accessible by the kernel 2.6.32, but, you can use `mount -o inode64` mount option in the old system and then be able to access these inodes again. > I've noticed something strange has happened. > Some (maybe all) of the files worked on whilst the drive was in the Linux > 3.16.0 are not accessible when the file system is mounted on the Linux > 2.6.32. > > If I put the drive back in the 3.16.0 server, all files are again > accessible. > > The few files which are inaccessible on 2.6.32 seem to have no inodes when > viewed under 2.6.32 but look ok when the drive is in 3.16.0 > > > "ls -li" on 3.16.0 > > 7249604387 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 01 > 104207 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 02 > 101524 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 03 > 2220005080 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 06 > 5637828101 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 07 > 1344499710 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 09 > 2958135019 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 0b > 7516254020 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 0c > 5905580833 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 0f > 3494120096 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 10 > 1988369908 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 12 > 2446706848 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 13 > 2446706832 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 14 > 5905580836 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 16 > 807056393 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 17 > 2688006922 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 18 > > > "ls -li" on 2.6.32 > > ? ?????????? ? ? ? ? ? 01 > 104207 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 02 > 101524 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 03 > 2220005080 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 06 > ? ?????????? ? ? ? ? ? 07 > 1344499710 drwxrwxr-x 2 nigel users 118 Jun 2 16:40 09 > 2958135019 drwxrwxr-x 2 nigel users 62 Jun 2 16:39 0b > ? ?????????? ? ? ? ? ? 0c > ? ?????????? ? ? ? ? ? 0f > 3494120096 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 10 > 1988369908 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 12 > 2446706848 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 13 > 2446706832 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 14 > ? ?????????? ? ? ? ? ? 16 > 807056393 drwxrwxr-x 2 nigel users 4096 Jun 2 16:40 17 > 2688006922 drwxrwxr-x 2 nigel users 62 Jun 2 16:40 18 > > > I notice that the files created on 3.16.0 which cannot be accessed on > 2.6.32, seem to have much higher inode numbers than those which can be > accessed on both systems. Could the numbers chosen by 3.16.0 be overflowing > on 2.6.32 ? I experimented on another almost empty file system, and this > seems fine in both systems, but this has very low inode numbers, hence my > inode number idea. > > I can attach the drive to either system and run diagnostic commands if more > information is required. > > Regards, > Nigel > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From eflorac@intellique.com Wed Jun 8 06:53:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8BD547CA0 for ; Wed, 8 Jun 2016 06:53:40 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5FA7D304053 for ; Wed, 8 Jun 2016 04:53:37 -0700 (PDT) X-ASG-Debug-ID: 1465386813-04cb6c2db9bdf600001-NocioJ Received: from mail1.g1.pair.com (mail1.g1.pair.com [66.39.3.162]) by cuda.sgi.com with ESMTP id nJJfHQoyOdRUj47F (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 04:53:34 -0700 (PDT) X-Barracuda-Envelope-From: eflorac@intellique.com X-Barracuda-Effective-Source-IP: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Apparent-Source-IP: 66.39.3.162 Received: from localhost (localhost [127.0.0.1]) by mail1.g1.pair.com (Postfix) with SMTP id 94D9D5479FF; Wed, 8 Jun 2016 07:53:33 -0400 (EDT) Received: from harpe.intellique.com (labo.djinux.com [82.225.196.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail1.g1.pair.com (Postfix) with ESMTPSA id 08C4D547984; Wed, 8 Jun 2016 07:53:32 -0400 (EDT) Date: Wed, 8 Jun 2016 13:53:35 +0200 From: Emmanuel Florac To: Eric Sandeen Cc: xfs@oss.sgi.com Subject: Re: determining superblock version? Message-ID: <20160608135335.24cde291@harpe.intellique.com> X-ASG-Orig-Subj: Re: determining superblock version? In-Reply-To: References: <20160607125127.6dd23aef@harpe.intellique.com> Organization: Intellique X-Mailer: Claws Mail 3.13.1 (GTK+ 2.24.30; i486-slackware-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Start-Time: 1465386814 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 838 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30270 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Le Tue, 7 Jun 2016 12:12:21 -0500 Eric Sandeen =C3=A9crivait: > > mkfs.xfs -m crc=3D0,finobt=3D0 /dev/this =20 >=20 > finobt=3D0 should not be needed, it should be off if crc=3D0 AFAIK. Yes, that is in the manpage :) =20 > However, -n ftype=3D1 may still be enabled, and older kernels may have > an issue with that as well. >=20 I'll give it a try. > Feel free to add this to the wiki (can new accounts still be created?) I don't know, who's in charge? I'm pretty sure I haven't got one. --=20 ------------------------------------------------------------------------ Emmanuel Florac | Direction technique | Intellique | | +33 1 78 94 84 02 ------------------------------------------------------------------------ From wagi@monom.org Wed Jun 8 07:08:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C198D7CA0 for ; Wed, 8 Jun 2016 07:08:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 9474F304039 for ; Wed, 8 Jun 2016 05:08:10 -0700 (PDT) X-ASG-Debug-ID: 1465387686-04cb6c2dbabdfb10001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id j17aLgZxpjARa1dS (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 05:08:07 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id BA16919404B8; Wed, 8 Jun 2016 14:08:05 +0200 (CEST) Received: from handman.bmw-carit.intra (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 815D8194043D; Wed, 8 Jun 2016 14:08:05 +0200 (CEST) Subject: Re: crash in xfs in current To: Christoph Hellwig X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> Cc: Reinoud Koornstra , Eric Sandeen , xfs@oss.sgi.com, viro@zeniv.linux.org.uk From: Daniel Wagner Message-ID: <75539b07-d05c-1516-26c1-2c4e2d42de1f@monom.org> Date: Wed, 8 Jun 2016 14:08:02 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <20160607134442.GA1803@infradead.org> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1465387687 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 390 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30270 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header > Thanks for testing this to both of you. Can you try to build a kernel > from git commit 555b67e4e729ca544bb4028ab12e532c68b70ddb - this is the > XFS pull request that Dave sent to Linux for Linux 4.7-rc, so it has > all the XFS changes relative to 4.6, but none of the others like the VFS > changes. For some reason, I can't reproduce it with 4.7-rc1 right now. still trying... From ntamplin@codefaber.co.uk Wed Jun 8 07:32:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 468917CA0 for ; Wed, 8 Jun 2016 07:32:10 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C7963AC004 for ; Wed, 8 Jun 2016 05:32:06 -0700 (PDT) X-ASG-Debug-ID: 1465389122-04bdf05ad6bf55f0001-NocioJ Received: from mk-outboundfilter-5-a-2.mail.uk.tiscali.com (mk-outboundfilter-5-a-2.mail.uk.tiscali.com [212.74.114.4]) by cuda.sgi.com with ESMTP id 4SR4JMt0QzGzOtGe for ; Wed, 08 Jun 2016 05:32:03 -0700 (PDT) X-Barracuda-Envelope-From: ntamplin@codefaber.co.uk X-Barracuda-Effective-Source-IP: mk-outboundfilter-5-a-2.mail.uk.tiscali.com[212.74.114.4] X-Barracuda-Apparent-Source-IP: 212.74.114.4 X-Trace: 340640625/mk-outboundfilter-5.mail.uk.tiscali.com/F2S/$THROTTLED_STATIC/TalkTalk_Customers/92.27.244.57/-4.6/ntamplin@codefaber.co.uk X-SBRS: -4.6 X-RemoteIP: 92.27.244.57 X-IP-MAIL-FROM: ntamplin@codefaber.co.uk X-SMTP-AUTH: X-MUA: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.8.0 X-IP-BHB: Once X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0BiCABfD1hXNjn0G1xdwhOGEwKCCwEBAQEBAQcBAQEBImBBEgGDcgEBBDgeIgEQCw4KCRYPCQMCAQIBJwoUBg0IAogvvR0BAQEBAQUCASSGJ4RNhCqFcAEEmE+XXA6FW49hgw2BNjuHK4MWAQEB X-IPAS-Result: A0BiCABfD1hXNjn0G1xdwhOGEwKCCwEBAQEBAQcBAQEBImBBEgGDcgEBBDgeIgEQCw4KCRYPCQMCAQIBJwoUBg0IAogvvR0BAQEBAQUCASSGJ4RNhCqFcAEEmE+XXA6FW49hgw2BNjuHK4MWAQEB X-IronPort-AV: E=Sophos;i="5.26,439,1459810800"; d="scan'208";a="340640625" X-IP-Direction: IN Received: from host-92-27-244-57.static.as13285.net (HELO mail.codefaber.co.uk) ([92.27.244.57]) by smtp.f2s.tiscali.co.uk with ESMTP; 08 Jun 2016 13:32:01 +0100 Received: from [192.168.10.10] by host-92-27-244-57.static.as13285.net with esmtpsa (TLS1.2:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1bAceN-0008F4-PR; Wed, 08 Jun 2016 13:31:59 +0100 Subject: Re: invalid inode numbers ? after drive moved from Linux 2.6.32 to Linux 3.16.0 then back again To: Carlos Maiolino X-ASG-Orig-Subj: Re: invalid inode numbers ? after drive moved from Linux 2.6.32 to Linux 3.16.0 then back again References: <5757FE7A.8020504@codefaber.co.uk> <20160608114907.GC8987@redhat.com> Cc: xfs@oss.sgi.com From: Nigel Tamplin Message-ID: <5758103A.9090103@codefaber.co.uk> Date: Wed, 8 Jun 2016 13:31:54 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Icedove/38.8.0 MIME-Version: 1.0 In-Reply-To: <20160608114907.GC8987@redhat.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mk-outboundfilter-5-a-2.mail.uk.tiscali.com[212.74.114.4] X-Barracuda-Start-Time: 1465389123 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1369 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30270 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 08/06/16 12:49, Carlos Maiolino wrote: > On Wed, Jun 08, 2016 at 12:16:10PM +0100, Nigel Tamplin wrote: >> Hello, >> >> I have a drive with a partition containing an XFS file system. >> This drive normally resides in a Linux 2.6.32 (Debian 6) server, which is >> also where the file system was created many months ago. >> Last week I removed this drive from it's usual 2.6.32 server and for a few >> hours it was attached to an alternative Linux 3.16.0 (Debian 8) server, >> where the XFS file system was mounted and during this time I created >> /modified / deleted some files. >> Later the drive was moved back to the normal Linux 2.6.32. >> > > Linux 3.16 has inode64 mount option enabled by default, which will cause inodes > to be spread along the whole disk, causing some inodes (those allocated on disk > blocks beyond 1TB offset) to have 64bit numbers. > > 2.6.32 doesn't use inode64 option by default, and so, files with inodes > 2^32 > will not be accessible by the kernel 2.6.32, but, you can use `mount -o inode64` > mount option in the old system and then be able to access these inodes again. > Excellent explanation Carlos. This exactly explains what had happened, the partition being moved between systems is 2TB in size. As you suggested, remounting on the older systems with option inode64 resolved it. Thank you. From eflorac@intellique.com Wed Jun 8 07:37:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2AA477CA1 for ; Wed, 8 Jun 2016 07:37:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id E37698F8037 for ; Wed, 8 Jun 2016 05:37:04 -0700 (PDT) X-ASG-Debug-ID: 1465389422-04cb6c2dbbbe0900001-NocioJ Received: from mail1.g1.pair.com (mail1.g1.pair.com [66.39.3.162]) by cuda.sgi.com with ESMTP id u99Ne8XiuAkWBDkc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 08 Jun 2016 05:37:03 -0700 (PDT) X-Barracuda-Envelope-From: eflorac@intellique.com X-Barracuda-Effective-Source-IP: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Apparent-Source-IP: 66.39.3.162 Received: from localhost (localhost [127.0.0.1]) by mail1.g1.pair.com (Postfix) with SMTP id CC175547AC6; Wed, 8 Jun 2016 08:37:02 -0400 (EDT) Received: from harpe.intellique.com (labo.djinux.com [82.225.196.72]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail1.g1.pair.com (Postfix) with ESMTPSA id 3E717547F4A; Wed, 8 Jun 2016 08:37:02 -0400 (EDT) Date: Wed, 8 Jun 2016 14:37:05 +0200 From: Emmanuel Florac To: Eric Sandeen Cc: xfs@oss.sgi.com Subject: Re: determining superblock version? Message-ID: <20160608143705.2345d2dc@harpe.intellique.com> X-ASG-Orig-Subj: Re: determining superblock version? In-Reply-To: References: <20160607125127.6dd23aef@harpe.intellique.com> Organization: Intellique X-Mailer: Claws Mail 3.13.1 (GTK+ 2.24.30; i486-slackware-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: mail1.g1.pair.com[66.39.3.162] X-Barracuda-Start-Time: 1465389423 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 813 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30270 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Le Tue, 7 Jun 2016 12:12:21 -0500 Eric Sandeen =C3=A9crivait: > However, -n ftype=3D1 may still be enabled, and older kernels may have > an issue with that as well. >=20 Indeed, I've made some tests: mkfs.xfs -f -m crc=3D0, -n ftype=3D1 testxfs=20 3.14 kernel: success 3.13 (ubuntu 14.04): success 3.12 : success 3.10 and lower: failure mkfs.xfs -f -m crc=3D0 -n ftype=3D0 testxfs 3.2 (ubuntu 12.04, Debian oldstable): success 2.6.32 : failure --=20 ------------------------------------------------------------------------ Emmanuel Florac | Direction technique | Intellique | | +33 1 78 94 84 02 ------------------------------------------------------------------------ From mikhail.v.gavrilov@gmail.com Wed Jun 8 12:18:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 20CBB7CA0 for ; Wed, 8 Jun 2016 12:18:33 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id D52ED304053 for ; Wed, 8 Jun 2016 10:18:29 -0700 (PDT) X-ASG-Debug-ID: 1465406306-04bdf05ad5bfe4e0001-NocioJ Received: from mail-wm0-f50.google.com (mail-wm0-f50.google.com [74.125.82.50]) by cuda.sgi.com with ESMTP id lQQFYlOeDTE0REpS (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 08 Jun 2016 10:18:27 -0700 (PDT) X-Barracuda-Envelope-From: mikhail.v.gavrilov@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f50.google.com[74.125.82.50] X-Barracuda-Apparent-Source-IP: 74.125.82.50 Received: by mail-wm0-f50.google.com with SMTP id m124so26550877wme.1 for ; Wed, 08 Jun 2016 10:18:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=nbYxeegG72kaSUfRlmbcCPZnDGqoCJ4r0zvPavtjP0o=; b=uFXVLciz/PMkQuXitZ407cXVJlm9tWZSjItRdZ7qA0n32/msykDgtaBRsdrmdaW6gr JJcrPOovaDSFY+UMNtBQpUJ8H7YY9QV2RrGRjQHBGhlaMqudAjlzoRh671/1EROzCCJl EJD5h9ydukRrWuEpwMuAtaH8HNSBuzh5oaPbbNnyUiHCDsAur0APpErfz054+BeOmHRw 30+v30Ve2Y8fWINw/WRyz/oz0iCOCPBArpDioL4rObZ9BBZGssLPPMgzxugSGwjB/xSX u0bGQg2NRfzxCT7mpjJZITFFrFzZupBtptVT9cfgW2tEMlyr42JUPmgZunNgJHqKos9a 32ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=nbYxeegG72kaSUfRlmbcCPZnDGqoCJ4r0zvPavtjP0o=; b=Nb++xzPh1tg9eS9myK9HYwuvqvdTq+ntkh4d7d2FYJq2Tk+H2kq2ailgLdFkwNONXS OosxbR0XLB48y6478Qm9Iktu3jATIVXFPO5S25MGZOqqPaTpnosWOR/s8zqgud+jaBlG J9WiJPCeTGRMMrWxR45B3xgXteWjJk0DwKAbNjZY6Hozeq+LMe6ejcZZVgUKhO+k+VZB y5unjVLU1SioyisvdUp3LrWLt1svrqRvh4SRKxTHP+wol6PrmODdIiZvH2N2wIkkToti sIk64scY15UhAEQOFNGGNVdOR65lD9mdQ7/n8X1mThAEY1dQIO+tGwFFQ8hp6AN3mzFz 6JuQ== X-Gm-Message-State: ALyK8tKxkO1Zml4vUShKRjSUYx8zo2Rhe//nOFCRZvIaeECI7weAcz1iXEsUDZVCHNFE0wAM2mvmzuvAPsTHBw== X-Received: by 10.194.186.179 with SMTP id fl19mr6236401wjc.2.1465406305839; Wed, 08 Jun 2016 10:18:25 -0700 (PDT) MIME-Version: 1.0 Received: by 10.194.6.72 with HTTP; Wed, 8 Jun 2016 10:18:11 -0700 (PDT) From: =?UTF-8?B?0JzQuNGF0LDQuNC7INCT0LDQstGA0LjQu9C+0LI=?= Date: Wed, 8 Jun 2016 22:18:11 +0500 Message-ID: Subject: possible circular locking dependency detected [4.5.6-300.fc24.x86_64] To: xfs@oss.sgi.com X-ASG-Orig-Subj: possible circular locking dependency detected [4.5.6-300.fc24.x86_64] Content-Type: multipart/mixed; boundary=047d7bb03d8a4fd0940534c77efb X-Barracuda-Connect: mail-wm0-f50.google.com[74.125.82.50] X-Barracuda-Start-Time: 1465406307 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 224 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30275 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature --047d7bb03d8a4fd0940534c77efb Content-Type: text/plain; charset=UTF-8 Hi guys Nothing terrible happens just like a message in the dmesg log. This is false triggering, or have to worry about it? If you need more additional information, please ask. -- Best Regards, Mike Gavrilov. --047d7bb03d8a4fd0940534c77efb Content-Type: application/x-gzip; name="dmesg.txt.tar.gz" Content-Disposition: attachment; filename="dmesg.txt.tar.gz" Content-Transfer-Encoding: base64 X-Attachment-Id: f_ip74zjww0 H4sIAFVSWFcAA9S9a3vbOLYmOl9nfgVm94dydlkOAd5AzXif9i2JO3bitpyq6s7J8UORlK2OJKp0 cez69Wct8IYLKZFm9TznuLtiGSLehYXLwgKw8DKeJ+uHo83z5r/9+34sy/I8h8Bv6ruW/Bt+bN9n jkUo85lnudTyHWJRB5L/G7H+jWUqf7brTbiCosyn3x/D6azxuX3fC2UKpeD3/09+vhL4sY6yUn8j 82m0SqM0Tobk7OaLVf1Ntss43CQxScLV7IVsUrJKnqbrabog1jNNDgl+S44Js6g7sPiA2v9Dg76a LrbP5ClZiUzOkXvkDWzLOppEzDl65t695/wcJ+PtAzmYp9H38XY6i/86/p6sFsnMYkfLx2d2NEni dBUuV+m/kmhzlK4e3pCDhygqUb0jekSxDKIrkYNbKPCHcJOlDxg8/f7s7A15Q/5Cyej6hvwK3/9t uyCQhw4pHTKPfLk7EwB68c/S+TxcxGQ2XUDlnH7+fHd/eX3y/uL47ThNN2+f5vDF9o/BLr1W8ODx ly+X58eh508c32IDmkTJwHECexBGnj2wIx57EyfmLIzgcbJ6fBiT37fTZEOuTj69P04W919GR1/u 3g24Xj6Q9Hay3A7JM3ToTXKfTibrZPOVfRsS4vreYZG+nv6RrLNk5hpaliij7XKZrjbTxQP5bXTy ywWZJOFmu0qgtS06JD89c59MZmkonlim08UGOsTDdL2BlvjpVagMUEeji74wDsCc/PJbG5iLRTie QQ/IaqYAWQOKf0iidLFJnjcE64tM14TbjIxfNsn6kGzXKPknyLWIw1X8E5mkq3m4OWoU9CXLkIQP yeon8u7mS4X+Y7qJHpO1kTfhzIJudvl5NIDu/jSNoZzLx5f1NApn5PbkmszD5VDPJB7Pcn6dJ3Os Du1noCS5/mQy+Qb6YD10AnO5CcYFGFRgsnpK4m5wgQEXJK8tWzAxwSavLhvV640HSRK+qmyYc2yA TagAOzm7uSSffhl1gpswDS4Mote1KebkOhjAv7LeMC9V4YLYDaNXlQ1zxjqY5zivLBvmdQ04Pn5l 2Twe6WC+47+yTTGv1gw4EJLXqooZTbjJ61SdcPFbAosnweS1QytHk+Em48nr4ZLIgMOkV8PFJlxs 2a+Ho5EBR1+vbGKWLnm9shOzKSavbgpaYFRwnE7cnb3u02/k4OI5ibYwD59PxSNvCEx8G/DzwLEb khB+PxnZMvGZa1qUggfjKLIoH4iPcQSzXCGVHB//V0MBGpDG4xIpGvN2SM+bZNFqus5rloCftl3e g+Twz5i326F2n8Bb4nacyduhdp/SW+HWzO2ixf0epZU6jZSkdJ7XoSKEjhr1LmsxVKQkZci8DhUh eAefqRXqK5yndrhdvag2qK9xp1rhdvarWqC+ysFqhdvZ02qH2t3laoX7Ct+rDW53J6wN6mu8sRa4 r3LL2uC+xj9rhfsKR60dbnePrRXuK1y3Nriv8eH2477GmUsm0yG5eHdJntiRTcn4hZzMkxW4Qgty nTyEmxX4R+vaTGL4HlvPMBSpA8lZAmFHlpI4ukbnE5ImlhPB39c34o8YjA3RcbNnAcIHfxLUXZj7 NOfXl0PyfvoQ4v4OuUuix0U6Sx9eyFl6dEiuNvER+Sf3rwfn9oe3xYdD4f+Sd5QSi7+l7C2zqNPG qdTrU6pH4VQ2NVWGtUrm6ZOMFVZYu9tEZJ+F6839crIgx+je0okHtTkPn+/DVfRYpjtFEXWM67vb WxInk3A725DNyzIB3RZRGD3WCRQPT6bP4AivwsVDsiZJtt1muMHwWSgRvIMf8mM13SSDcRh9N587 Ec+diueaJRNyJp47k/DypYT56Ll49Hwv5IV47t1+SKH3U7iaihbdrzoZh+uEWOUPtMf6O/F5+feu CqF5bq7lfnfRJjcrZJ9pucu/d9WIXeQ+aZK9K7dT5A7ecSX3u+LvXbndQm/6mtxeldvTcl/sz+2T OFugGkOUEL7ju6DxO9wnvjm5G4K9WUymD9tViGte8tUa+N+G5NdTQn49I+TL2QD+I8rfv94Rw+DV GR3JWagmhdZGR7EaYinWwWhM0u0iFoct1zeDjZAYbiQDNgGvqzBg8BHKBUvlJVgNfAoLyrOii+e+ GdYdJpUFbq5TEq6ScI1b8WSW/iCAn65eSJSuVtslVqexfYFdIH9qswrnyxRPdnSpgS8eFr+yowDm uL5xbJJt8L8/JcsQhzsWIp6uwDoIZeA7Q/rtR2jfZ8tmwh04JPln0TA37+9OTq8uduSZSHkm7fII 9yDPM7Fa5qFSHtoyD5PysJZ5bCmPvSvP7cn1+eXoY+ml2FGSOFnHxnxijannQRcC/JHs3FJ0wOgx ib6vt3M8N5xOwDER461peGb5b0fnN7L7fZ47I/gHc8jBk8XIydXJ6OPJm3qA30bndwYAzwD8MwSg OQA5IdfkUmBQy4f6DMjJ9aWYJqFBqN0g4B38UgUw64JZWTYhwO0n4LxGAxqggLMzfi5XgSRA/HBO Lj/dXREURSllzRqMVAGOV1SRY1iWLM/JzeWZrvU7O8sTMCyU3bNab3StQcAZzwrl/AntNjKqFZb4 VGjg2kEm4GZ+m0zAsVlurcv1JqtWHDRFtVJm+ZR2EOC6QsDJOdcF3MyLdmst4Prs3XtNALNYVkX2 vq59PXp3l3eTwG8Q8OHmQteAWV4ugO9vg6PCwXLbVxEDxwaz2d55JmAEy6PbRPy6A0MhIGmPNmCO aGTbuaCFgNE63hS/zDbYOXZO39/qAlz+Tq4iq+fovz651QUE+UA7ydsACnpxRciH0a+EVKM/++Kq /KtBwFWKm+ViPIdxDC4JnsQXy2XjwCAln75cn+BBuuQyCWdDf/Rd+B1n55AsMI5FcT6Un7oVriH2 8/nF/fnJ3cmB9YaEsxkUGYNiigMDyFdMRwKjdj76Z7ooFgY1CwKo5qzuakqp7fwVK3xDgkCxWR0K 1XWtdglMlE8Y1zAzUHbuCdSUJXmaRgl8SObLzYuxXkqfxJz8B9YKxmJthPuUgP8tGkx/PpvHc8dN tGhWlaZc8SUk1R6qGFWZH6p0g2k87egE0xxi0AFm1z52F5gdG8wdYHbt/HaB2bF12h6mU3+9XEw3 mFtsiWWQ1v4O1Iz3eVGAbNJNOBMLhCHhYMk9z1hHZMMfh8KQeE6+mtiuwcLgmIBCwHJiVx5W5Gla 0MkP20HgZ48fkqvLd59hVbyJHoeGqS2sSZYrCLjfoWBlPs8OKHNr5Nm00fBkObGmAq+tTCUr+I/c dZxWUjcYxzeExloMrOyPe5yGyHi7IdMNhoAt0g1JJ2Lni1zAyvj+9mJ0cfvLxbmxShG1j5PO5WKT zMjDKlw+TqM12Ld0liwK6wVTEa6nw6JvRjTbv6+fHm+uB3fTebIil5/JTbqColrPlFtGIOArJtM8 Cz59/wlcgYMwWk7vp/FX3C74Rh6nD48kiR8SDH7cQCL9Zkzhl58x91fr25CEy2kEmQk/LOMybXao FCM7Cjgk70eXxBowI1Y0KxA4Dfej27P7z7/ckoPxdo2bZdv1/XT1O3x6mKXjcCb+YCSezPC/Bsdi B04g4wSZprPkKWmEuv27lfXB8QtJQb3VNE6MDeXy2WD/s9nWgdjmPrg+Ob97I3o37peors10kUUZ 1mxlSD7yNMZuAb3CC30r2x0cihqPaxt+PV9mvf4EXJkfWBCOcb8wVCzymG6Ws+2D+FvPd3MNC+I8 wBL0W6Tr8KnYTTGMuLzT/VogKVwhC1N4LZAUSRDU2uu2QMbG+6uAsmiBzGHEj32Aogoo6gcUVUC1 E39boLgCivsAlSf/5Yn/64CqQ/nyMP5VQNJ5eXlO/kqg8ii7PMJ+JVB5dl2eWb8OqDpGDCZ+j54t bTmX59KvAoqrCTIv0CuBpJPt8kT7dUBRBZSM+wBVZ+LlWfirgWgJ1KtEcVWi/BT91UBOCURfb4+k c/jy/P21QKxSrVcdJVUdJb1aLalarVeHrAZt42peidSsG1MkfAqnM7EWRw/k5uySxGLlbsz+p+Ay iGsf4Sp8mq4223A2/QMKl93VIeCsjMNVQh7DVfwDPujZo1kafV+n21WU4IH2ZLpI4sG/ppPJFFdG eBQnXJb8Rxw1RS/RDL+skg9F+jSeJfcL+IIG1Aq8IHAsWGY4NCALo9RZjMMyWUV4JePT7T04NqMh xc37xeoeElHy/Xi6WQ95ngL4+R+4hBN/GcuGm4tbABqSi/k4iTHs0+F2tt54Cwjkr/lhkl+MdbKm gQ2WiJMVpwG4rjajHidbZgU+dZkOvwSQgdhoGu7JmW1HHdP/bIEEfjquauFfKv5l4l9b/OuIf13x ryf+9Y0zxtPtdLaBvLjKmkHfXIN7CisvWOamqzhZQeOk4+lsunmBpU+6xQMw6BVHhNzhEpjka2A/ 4A4PXKNC09k0eskXcNlqTn/kY9bRov+PX8m6uTyHQbB+zE+dksVmJbq4A12VHIiaglX4IayOfGhH cbnIWHZc5yPdpq7tuhb/+NZmjuN5nvNRGrAHPPD4x2IA4n29QwJdgH4kqx8Y1QMyfJvBX2n+F/jT H6HNpht4zmMc8o7X4PXjBrPrfSy3D2Ad8JFE83BQJBjlG119OYW1x69gAh4Wx55zSD6jXsfWABS7 ni4+j/Gq3voYFnu4kDiGRSH2k/WxMZBut9lJ7u3ZFxirM1hnJ9Cx9Kc+TJMVHjxngdXw6HS+nCVz qFuxNDKWV/8dn0GDEyfL7NwPZUzLkAwzA/bteLCBpTYsWf+1XW8QHNf9sySckEm4SLcbvP/oOfXC oKqgnSNhIVFlMlml88LeHAt7A7krA3PMDRyAgSWZEI4oD0k6TzarF2GXV9H2PivEPRZIVLkMpmN9 B4sPD4JNzUdNvvmAaWDgMYRFnFbXn31CsWEZOxp6rg8WB+TAOnk9dDgn5g3J//55gjcCY9Es0Dwz jDrJ1Ye/aheSu/Lg82DyB75RP2fpYp3OYMxH6QzmERJv5/OXfLYi3HpmhlGJshzk62bzgpPholbb K+gnALPE+P0F2KAn6NUwYNIVhmYsX1bTh8cNOYje4FmMR/LLpYfkchEd4b8PKblOZ4twpeMeHR2R 65Pf7q8+n308v7i5H305Pbs6GY0uRkNCjBaTn76Hx+8+DEn54+x8HME/XvxjVGaAicIYaJhBiP9w MvpwP7r854WMD7Zpn4SLT3e3lxe5EGG89uU4+3By+akolee6dq0M8VRdoWplFB252GGZaY2HGyZD wj2fku+nRmbwA8Asr78PYLBuMU4jA5vAfLBcTRebIWEez43yTgfmcZlsXu212LYDcyBn8E+Nx4LQ mbDkKZEu2Jodd7OGSf1duN6Qu9EZjqPpON82yu6q3lzeGe7Qcruapts14cwNTqC2ABhDZcS+lTnk hIRzYS6gum07YEe25ZLrD3/gNR1wEtep0u0dDsO0KAeUIE5mIbZRuiQH6+9TjPB5c4gDbJtgeaPt TBykZcXdiH3OySr5fYtNCV3D87lz5FFwPR/S68ubETmYLf91jMWwtTNdl4KrM43voaKHRbDiMJ9i 5zDjzbdz+NNSRoVnF5toZyk4ruXNdnGRnEpbrMz17HLDzc127U6ur7IJfk3W2whrYrKdzV5IGIGX gD67cFHAxkGzVUDct6Cgg8HgK/kCUysZLUOwXd8gQXmGfdt7GUgE/8lj5aP4ffsr0X/eX52SZ+j6 m0SRwXUZ3JDhTmQZ0Gl3yvj0my6D6nq4dRd6ZBkM3ZBOelBdD/PSkFj/lTJgnbC7rkw9mKYHM9oj P2uqgKhzrcu4GV0oMuaxIsNTZJgHthYNdRnWThlYV6oM7MQmoCIj0mQQlskAF7ilDE0PI/zfonHo yu3hceejLmN3mzuaHhmgIiNR9bA9p2O/chxVhhG+b9lqv4Kq6toeTqDIsM1+Zdt57HteV9Tqqoer 6pEDKjIcVY/A2S3DHB8eVWU4uh5FmGglw2cdx4fnyjIKQPnYW5cB1fV+n4ytIsNX+hWvkRFo/Yq6 vKMevqJHAahFAYzV9rA6tocfaDLqrtAxpa5YbtubfzQZ3NFkmGEI6viwKds9f5h9lyu2vQBUZHC9 zb2OYzBQ9Qi5KSM7PijgKGddx2Cg6VFzSVCz7WyHDPwxZHDVZygAFRla3wWvv7GuChlKXXHLV2WY fTcPIynriu6Yz+v1oFSVYcSlQJIbKXVld/QZOPU0Ga525YuPLbWuvD1+iTEGOVNtSQ4oy0g8rT3c jj4DuPCKjBxQkeHbsdwezOvow3Gm2pIcUJXB5TYnzO/oi3Lb0WRwvc0TP1BkkD3zuamHzTUZgSkj chQ9us613GGajMgxZMSqHm5HX5Q7niYjNvTgTPXb/a7jw1X7bg6oynCU9QeUoaMertbmXL+EC0mh Uld217UBd7U2zwBVGWNfaQ/edXzgItIEVGQETJHh7FlHmXp4qt3NAVUZrtoeQVd75VNNhk4VAUlR rOixx5aYevha380AVRkTxfehvOs451rfzQAVGSFV2oPuWQ+aenDN7maAioyxJa9xSNB5nHPN7maA mgy175Ku7RHYugxTD1dpc7vr2oAHWt/NADUZiapHR7sbaL5PDqjIiJgyPrjVcZwHltZ3M0BNRtBP D2rpMgJDhq3WVdfxEVDN7maAmoxJTz24LsOYPyJHnQf39F1TD6a1eQaoyvBCWQbtugcQML3NBaAq I1DGOd3j+5h62HqbB8Y4jwKvX3vo/lUGqMqIVJ+adpw/At2/iiLdp4akuJ8eun8VmfOHSJH3yLq2 h+5fZYCaDNpPD92/ikwfLlZ9hs52N9D9q9j0GWLVJr5Cj0CXYdjEOFHqyu+6lxF4uh6JUVcJV+rK 6zzOPa3vZoCqjEixu6yz3fW1vpsBqjK0ftXVLwl0/yox+1UWDSUhddVD968yQE2G3a9faXtLOaAm Q+27rGu/4nqbx0bfTeKe87nuX2WAsgyYF2V/l+7a96nXQ/OvckBVhq2sa7vOg1Bmqsmw9XXtxOLK PGh31ANkeJoMrs+DE+oo7eHvGYOmHpp/lQOqMkLV7u5ZO5t6aHtLOaAig8XyXEu77l+Bu6vpwWJ9 rp2wRJnPu+6XgAxHk5EYMrLzihKH7fGpa/RQx2AOqMlQfYaO66jAspkuQ/cZJjZX+pXdcV0LMrQ2 zwBVGaFid7vulwSWo43BDFCVoa6du+6XgAxXk2GsnScOVeeojvslgaX5PjmgIsNV1lGwPN9dV6Ye mu+TA6oyXHUPoON8DjK0vpsBqjJ8VUbH8w9Ycmp9NwNUZahz7b6+a+qh7S3lgIoML1TGIO+4vxtY 2t5SDqjKGKvjvLO90s7VckBVhnrmxTr6VyAj0GQYZ16QpK6dO9srzffJARUZvnr+YXduD833yQFV Gb66ru1srwKt72aAqoxI3af2uo7zQLO7GaAqI1H06GyvqKXZqwxQkcFdxb9y9qzVDD2opbV5BqjJ UPf6Oq5rMU5el2HYEj5RxmDXdVRAqa3JmBhjMNDnj479imp7SzmgIiP05X0f2r09tL2lHFCTodqr zu3BfF2GUVdjdX3udfV3qa3Z3bGxPp+M1bUB6RjjBTI0uzs21wbjQPFL9sVf1eih9d0MUJURqnrs 8alNPXTfJwNUZESR6pd0tbvU0fTIAFUZ2h7Anrg+Uw9XG4Pm3tIkDpX5g3c8HwQZWt/NAFUZY3V9 3rlf6b5PBqjI0OIZ2B7bburhafOHEc8Q5L8lpN1xS3rMREBV36cAVGTQsWKv/K7rD6r6PgWgKiNS 9ei6Pqdc0yMDVGSwiaJH11hOkKHpkQEqMmxL3Qvv3K8CS5WRAaoyJsoY3Bd/ZeqhxhQVgJqMXvtw IIPrMpgpQ9sj6zh/MPVcrQDUZHTaIzP0YGpMUQGoyHCVfR+6by/c1INqfdfV930gyVX3LDvuU4MM T5Ph2oaMidJ3vT1rA1MPpvXdDFCRoccUddaDaX3XiCmCJK7Uldu5XzGt72aAmgx1nHf1r5jNdBlm XXHFL9m3h2zqYXu6jLEhI7C6yDD1cLS+mwEqMnw1Tp933WdgjmZ3fT1OH5I8dR3Vdf5gqu9TAKoy 1DXnvj0AUw/V9ykAVRlcGx9d9XA1e5UBKjJEijQ+uvq7zNPaPAOUZRj3DcjuOGTDL2Hqvk9g3jeA hZWr2t09azVTD833yQE1GaHVa/7QfJ8cUJGhxel3Xtcy9cyrAJRl6HHI1O12FwBkqHqYcchBGATy fE69jnd+QIY6BnNATYZqEzvbXfXMqwBUZXRbq5l6qGdeBaAmo99+ia2eeRWAqoyx1UsP29LaPAPU ZNg99dDbfKzPtZAU9dOD6m0+1l/UAkmTfnpQvc3H+hxlxNB33U+0mdbmRgx9EOn+Fetod201pqgA VGUwNQay6z6Dre77FICKDNVe0X17AGZ7qPs+BaAsI9bvR+25r6bHtwe2es+rAFRljNUz4a7+ru34 moyxPkflrE8FjG119XdtV/VF61+7pPg+ntXtPg7IUP32eiJONcar65mXrcb7NLyQSVlz+sUap7Ue mu9T83KmWJtr/R32Cn/M9lDvkhWAsoxEvyvDmvd9Chlq39V8H/P1PwXJaSnB2uGL1uuh+T41rKk5 Q5CE0rXvqmdegfm6oYLxS0LKbWLzj1ZX6plX7SuuVNtOLabe87o5O9/THqrvIzEhFUkFT1iJYQdW Rz0Cpc3rXqkV6e3hOR31CJQ2lzjJyqREv8PrOF31UGxiwyu8dsZAoh7yj9GvHHVvSWIyq5Jivc2t brbEUc/VGl4ZpvqiWtxrCz24LsMxZFDVvyruZrTXI9Bk1LyiTI3F6a4H1etKj8WZ6DaRd9ZD3SNr eCVaz37FmC5D71eaTazsbms91D0y8xVsJfN0hUA72itH2SOro7I2ZTDe6b5z4Chx4bxGhnhVmCzD tbrd2wYZct8tASUZxt1wt5hrd7SHKsOR1x/cuBteaiadQfrB+30y1LqS48IrwEFG8lIlCBnUp37g 2z7oulfKgyqF5+wgOWtTHT8IPCXqVBdclIUrZSl++F23krgFT8lV+qMozXX2ViOjPC4ty8Mby6P4 hV35SkCGp8vghox+fCWB41majGIfVErqx1cCMnQ9AkNGT76SwPE1Pcp1U5nUl68EZDiKjGr/sErq yVcCMrgqIzRl9OQrCRxuqzIiU0ZPvhKQoelR8pVUST35SgIni7fSAWUZfflKQIavyLDNftWXryRw LVWPiq+kSurJVwIy1Pao+EqKpN58JYFLlX4lzUlFEtdldOUrARlKe/AaGX35SgKXKe0h8ZVISf34 SkCGp8ko+EqkpH58JYFrU01GcV5eJvXlKwEZriIjNMZHb76SwHVUPapzgiqpJ18JyND0KPlKqqSe fCUgI1BlGLa9N19J4LqOKsPsu335SkCGpkfJVyIl9eMrCVzP1mQU8bplUl++EpCh2pKKr6RM6stX Eri+qkfFV1Il9eQrARmqHhVfiZTUj68kcDnVZHC9zfvylYAMV5MRmDL68ZWAjECTETmGjH58JYEb aG1e8pVUST35SkAGV2WUfCVSUj++ksBT/RKJr0RK6sdXAjI8TUZo1lU/vpLAo5Ymo+ArqZJ68pWA DK3vlnwlUlI/vhKQofXdkq9ESurHVxJ4TOu7JV+JlNSPrwRkaPaq5CupknrylQSerfXdkq+kSurJ VwIytL5b8pXISb34SgJP830qvhIpqR9fCchwNBmu0eY9+UoCzzNkJLqMnnwlIEOziSVfiZzU635z 4PlMlxEYMvrxlYAMrV+VfCVyUi++ksDjli7DmD968pWADK3NS74SKakfXwnI0Nu84CuRkvrxlQRe oLd5YIzznnwlIMPXZXiGjH58JYFvabak5CuRk3rxlYAMV5dh2JKefCWBb+ltXvCVyEm9+EoCn9q6 DKPv9uQrARlam8emz9CTryTwtb2Miq9ESurHVxL42l5GxVdSJfXkKwlyHmcdUJXRj68EZGj2quQr kZL68ZWADK3vJma/6slXEvgO02Xo+z59+UpAhqfLsE0Zat/tGgfuu3qbx0bf7clXAjIMPfT5vC9f SeCrZywSX4mU1JOvxNf8q4qvRErqyVfie4Emg+vzYG++El/bL6n4SqSknnwlvnrGIvGVVEl9+Up8 ro7Biq9ESurJV+JzT5ORGDL68pX4gdZ3S74SOakfX4kfuLoM3WfozVfiB1rfLflKpKSefCXc0vpu yVciJfXkK8n5qHVARUZfvhJOtb5b8pVUSX35SnI+ah1QldGTr4QzqslwjXHel68k56PWAVUZPflK uOb7VHwlVVJfvhKu+T4VX4mU1JOvhGu+T8VXIiX15Cvhmu9T8ZXISf34Srjm+1R8JVVSX74Srvk+ FV+JlNSTr4S7Wt8t745JST35Srh2VlTxlUhJPflKuHZWVPGVVEl9+Uq4dlZU8ZXISf3u33Btb6ni K5GSevKVcG1vqeIrqZL68pVw7ayo4iupkvrylXDtrKjiK5GT+vGVcN33KflKqqS+fCU80Ozu2Fif 9+Yr4brvMzbXBn35SgLd9yn5SqSknnwlgbbvU/GVVEl9+UoC3fcp+UqkpJ58JYG27zMx95Z685UE uu9T8pVIST35SgLd9yn5SqqkvnwlAdP6rhHP0J+vJFBjWCS+kiqpL19JYAeqjJKvRErqyVcSqOc4 El9JldSXryRwuCqj5CupkvrylQSurcoo+UqkpJ58JYHrazIm1JTRbx8u8Kgug5kyeJc2N/XwXF0G N2X04ysJ1Nhaia+kSurLVxL4Wt919X2f/nwlga+NwZKvRErqyVcScK3vlnwlVVJfvpKAa2PQiCnq z1cSqGdeEl+JnNSPryQIPF2GWVe9+EqwyJYuY2zI6MVXgjK0vlvylVRJ/fhKUIbW5r4ep9+XrwRk UK3NS74SKakXXwnK0NrcWHP25SsBGUyzuyVfSZXE1THYka8EZWh2lxtjsCdfCchQ930C875BX74S lKH23YqvRE7qw1eCMgJdhu4z9OQrARmOanepEYfcl68EZah6mHHIfflKQIbm+1R8JXJSH74SlOHr MnSb2JOvBGRovk/FVyIn9dkvQRmuLsM3ZPTiK0EZWpuXfCVyUh++Esjr620+1ufannwlKENv83Fk yujDVwIyuN7mY32O6slXgjK0Njdi6PvyldhozRUZkelf9eQrQRmeJoPpY7AnX4ltUc33iUx71ZOv BGWo80ds2t2efCUgg1JNxlifo3rylaAMtT0qvpIqqR9fCcpQfbiKr0RK6sVXAjLU+F2Jr6RK6sdX gjLUMVjxlVRJ2lzbka8EZah2Nzb7bk++EpCh7fsk5t5ST74SlKHqUfGVlEk9+UpAhrbvU93Nr5K4 LqMTXwnKUPvuxGiPvnwlIEP1fSS+kiKpL18JylDaXOIrKZN68pWgDKXNJb6SMqknXwnIUP0ria9E TurDK4EyPF0G1WX04ytBGVyVEZt69OMrARnquZrEVyIl9eIrQRm2JoNGhoxefCUoQ68rPRanL18J yFDjwiemTezLV4IyPF2G3q968pWgDLWuDJvYm68EZCh7ZDJfSZ7ETRnd+EpQhqwHr5HRl68EfCXl 7E7mKymS+vKVoAx5/cGNu+GlZtIZZDe+EpQh2d0KMJcRBZYuw/Msh3dhKwEZtOAIeZqHs1kaHbwh J6skVPlB8Lmyb8iCtbK0Hke1vh6rfFYZUJNRf4axQ19NBtdlMFNGp1hiUw9m1JVtynD66VH5xTKg JkO7w9Hp3Apl+LoMz5TBa2W01yPQZXBThjqXdbsnAjJso64iQwa1amW01qPyvWVATUafuFJcA1Jd RqzL0HhnArvjWog5mh7K+heTdNsJPlJX2+koba7ZziiosZ0upR1tpyvVlWE7k9DSZdg2452YnlCG ndvOX+bJfB4uDaNZkRfIEuVCMH0h43TcsGAuV2QwbshwtMokrKNzzirnXAaUZDD9AMJxd5NimHpU zrkMKMkwJ22rqx7Vwa8MWMr4Uzpe5ZzLgLmMwm+TZMAsH7COHQ8Pl0XHuxjdTKbP9TO2X45kWWpZ kFplOxckqGTUKJtMDBmO43SsUF54KBfvLsntdrGZzhMySlZP0yhZG1pX9xRk8WWJJgnXS0S8/Vpr JZJqtgKUZISBti/seV7Hrsp9WUYBqMlQ594dZzP4Y6xbWEB1GdyQ0cDHtkMPTYatyZDPefOk9nxs DXpwTUZgylBjX+yu86Jt6XrIsS9ZkrpW3ck9VKuHbWltnhhtHmq8Wbu4hwoZSr+yqapH6Jgy9POG mviz3XpQVY/QM2XovHLdeIFABmOqDHN8hGMlZp3aQcfxYTO1X+WAioxY5boJWEc/3q7OxGVAVUZ7 rpt6PaozcRlQldHAddNeD0+TEZgy2nPd1Ovh6HUlc93kSQ1cN631cLR+FceGHkl7rpsGPbS6Sphu r8KkgeumvR5a300c3baHSXuum3o9XM2WJKFZVw1cN631cF1Nhsx1kyVN2nPdNOgRqDImzJTRwHXT Wg+PajJcoz0m7blu6vXwtLqaRIYtmTRw3bTXQ7PtE/m+nkgaW+25bur18NUxmAMqMmgD101rPXzV JuaAmozWXDcNenBdhqlHA9dNaz24pclw9TaHpNZcN/V6qP5uAajIYA1cN+31UG1iDqjJaB33W6+H 5u/mgKqMBq6b1noEWt9ltllX7bluGvTQ68rW548xa+C6aa+H1neZo9v2MWvPdVOrh2PpdSVz3eRJ DVw3bfVwLG2cs8AY56w9102DHnpdyVw3eVID101rPag2zlmk+6KQ1Jrrpl4PqteVMX+MWQPXTXs9 9L4rc90USa25bur1YHpdGT7c2G7gummth7b+yAE1GbynHp4uw7CJdgPXTXs9Ak1GYtSV057rpl4P W/UTc0BVRgPXTWs9bG2OciLD7jrtuW4a9NDqyjH7ldPAddNaD4fqMvR9BkhqfT5Vr4ej15V8/75I Uvtu1zgIR1vj5ICajH7zueMyXYYxn3sNXDet9XA1m+hZhr/rtee6adBDmz88W1/Xjr0GrpvWenia TfS4MQ/67blu6vXQ1h85oCqjgeumvR5aXfmhYUt4e66bej309QePjbmWN3DdtNZDX3/wxJARtOe6 adBDq6tAjq8pkurPJFvroa8/Amb4DEF7rpt6PbhWVwE3+lXQwHXTXg/NXgWhYXeD9lw39XoEel2Z a+ewgeumtR7afnsOqMgYt+e6adBD3QPIAVUZDVw37fXQ5tqxa4zzcXuum1o9XH1tMPZNGQ1cN231 cC2tX43NuTZqz3VTr4e+NohCYwxGDVw3rfWgmk2MxqaM9lw3DXpodRUZZyyQVM91014Prssw1s5x e66bej30tUFsnBuM4waum9Z6MK3vxr4xn8ftuW4a9NDGYByZddXAddNaD1vzd+PE0CNpz3VTr4e+ Nkhcw79KGrhu2uvh6zIMW5K057qp10NfGyQTYwxOGrhuWuuhrw0mxvwRWe25bhr0UPtVDqjJqOe6 aa2HS3UZel1FtD3XTb0e2tlEDqjKaOC6aa+Hr8kw1gYRbc91U6+HdjaRA6oyGu5PttbDczQZoaEH a89106CHattzQFVGA9dNaz18ra7MvaXIbs91U6+Hr/UrO9Tnj8hu4Lppr4fWr+yx0Xe1WINdXDf1 enCtrsxYA+Nu4w6um0KGEgfganEykRlrEPntuW7q9dDODXJAVUYD103r9gi08eFHhh68PddNgx7a +OATQ4+ggeumrR6epfqiOaAqoz3XTa0enua354CajH77cJ7mt+eAmgxe2+at9aB6XU2MMRg0cN20 1kOL98kBFRnj9lw3DXpoY3Bs7PtE4waum9Z6aHv6OaAqoz3XTb0emk+dAyoyjHtunfXQ+lVk2quo PddNvR5aTFEOqMmo57pprYfNdBlmXbXnumnQQ68rbvglUQPXTXs9NJsYBUZ7xO25bur10GKKckBV RgPXTWs9HK3vxp6+jori9lw39Xp4mi0x15xRdq+5Aul6ruZpe8g5oCJDuxO4i+umQQ9t/WHGWcaG X9LMuVDIUPwST9vfjU2/BGqvNddNvR6+qkcOqMmo57pp/tFkaD5cDqjI0EL/O69rPS2+RL0bj0lj z3gHavM1ifr2UH24AlCRMWnPdVOvR+CqMiYBN2XUc920bg9177UAVGW057qp1UN6r44MqMnot1/i q/HUBaAqoz3XTYMeniZjbLZ5A9dNez24LsM2ZbTmuqnXQ917LQA1GfVcN631UGM/CkBZhm9p68Gu +4m+uvdaAMoyuO5f7eC6KWQo49xnar/ihn8FSe25bur1YL4mg+ljkEcqR4zb9dzAV/2rAlCRMWnP EVOvh+r7FICyjIA6qk3sOp/7asx2AajI0Dh7OnOr+KrvUwDKMox3NnflVpHe3SMDKjKMOw0d7034 6l7f2LzToPNsUCuwut3x99W9Po1no0jqx4fgqzHCGs9GltSXZ8NX9/o0no0iqR/Phq/GAWg8G3lS T54NX/UTNZ6NPKknz4av+okaz0aW1Jdnw+davzL8q/48Gz73dRl6v+rNs+Fzta5Ung38sSxtHuzM s+ErZ/Q1dxQn5h1F0vGOoh8UV0Q/TB8eycdktUhm5DpcLqeLB/3SpK84rhPzQuOEG+SftOOFRl9x XEtAWYatX26zd98hNiqWKwHFJaAkI9Qr1vE6Ei5xq6jY6zTezswbqFzxCEuJUiH0Xkpd1rUQuHOY 3YldxI0FUbYXJzVdeTLR6fJIx6v8XHFNS0BNhrYV25GGgjNLl8F0Ga4vu3S263Y0X5xpemSAmgzV 1Bfma5W21cPTZUSGDDXEyO16jYIrVxZLQE1G3NQeN7/e7adp4bZeV9oxNPzo2yddlyNcubJYAmoy zOnky+i2fXs4li6D6jJUt7H7dMIdra5Kt9HSfuT26DYGAw9kjJJou5puXsi7VThPfqSr72S6mG6m 4Wz6R6I+DZPPP8J5OCTjJErnOB3AP/FkOzuSH8PzwdHF1XSxfR4ScllgwePSY1RQbFePjTbhaoOI 0wVZJqv5dL2ePiVknsZSpTg+FuE8WWxWLyQKo8eEPIbrR7IJx7OEYPI0WQ+JQwPHthxykK7iZDUk 1D4kNoxsx7EZGb9skvWbEhPsPN77v1yAoEEzJAO1wNhWkOwQ5jEf/DzqGZBUvGLvOt0uNjsgPde1 vRLQP8Tdesa5icYxAFegLdPpnwLJOHI3nd18GZKbx5f1NApn5GaVRsl6na7I5fmQWMrDrHi4fOYs XSU1D0LLz6NkiE+T9Xa5TFebNQnI9dkFGYeL72v5YQx7geesIbl7hAaHIsxT6CvpCntBskDNYnJw d02VguNiapkVY0i2a9EHf4TTDfabaQyVsXlcJWGsSMJg76twvSGz5AlcmekdjOmqs3w8xUWEcwgT WPHJyT8pILYCErcGgY7y/pRIWDbFU5Z3qyTB0o+ub0g424CXFW6gx6/JPJmnqxfocmBcD8rBz1hm ewekSrLFoqKqHp87uD892axCbARByhWKQSWYSoviYlVRyskyfEiqeuIex2Cn8+uT2yH5kIKiYRyv oJrJj2m8eSR2oDzqF4+e3344h8Zdg8DCNE2yN8daZDILH9YiXc7rlWLiebiC9l8lD/eIcI8SSZn7 KVkROrRgoC9JttZkFvKUeYwkmDYBo0tDBdnbUyqqlIrKeTE6oyoVrSsV1UuFqyFeU6pYKRWuBTPk 2+vbW61UQZJkZ3bJIlZSAwptrMDYO2DiYr5RYOJJILqKApPX/uASkC4/n9xcnsHAIZxsF2A1qooj OPkUSl9+vr7+QtT68iScDzcXd4hiGSgViJLZlzL/fZtsYahPF08wTcTQYdMF9LnZDGaZ0g5s0sKe kGcWLqcRCcF9vYQOPVgl82xtUs0u0JhUlnCRo1ze/p2Uj+MwyLGUWQYzgyuUf5UXQP4W9wlHP6Yb sMIxEfW3SrdimEEpo9l2DYM5zy4XSeyNHx3dXV5fQJGekghM3bH1bFsEn6THFoFS0WMm/mTHA4p/ 4+8SA2ZWNMV3ozMSg42bTRdg7qZzkKaXEp8EN2g9X47TdDPM7SxUVzI7uH0jrDdY1jdk6g8cKJiw 138l9pFjvf/wB1idcD6dvWA/8g5F5czwsx0dEtBNVJ74+40sD12im2Q1ScGUL6KEXDyBuYFhdnNx OiKT+Yb9jDPmIE6SJbk6vT0kH8L1jwRaOREPHhJwI2aDzNZEONklK0gURSY30PniFVjH1ZEsEi/f Hx0d4ZBcQ6cZ6s6OXffwGOYKIUV73OHy0zjl4tMPySJZQTcAYzDFdl3nuRzlYZqXI5xtwWUJ199V bGF9pB8lL8vyzsNn9Humadw972T6nMSD5Xa1TGHEJXnFa/qj54QPi68bCgk/+c66JQkKbGS5fube kJxCbyomrShdTKYP25UYsEPlcV+IOiLoVBHyF+sQO1hRdX8pOzRYBYcC9HwawYwOz4qOSqu/yXYJ 9gBGWRKuZi84vFbJ0xTbGq13ckjwW3IM3hl1BxYfULuCZh5auk/Xl+RHCEM1TqHPFtYE8sPkKAp1 KLzNcAGVAhJAp/V2DlNkCkPr8ccAO17eGY8k6MABDclfWJVkBzj3qIqwP0cRz8a9CfIXKcm30Qap 0uw/R1rgYRgv+YtD/uKSv3jkL375HQ04hmKWHQEEbJeEilY+hAkEq1N5mEsW6C7dgIeXTuC5ZeFF rkkYgc8jinrgOsz3jsBZPU0f0uvLm1FpXSjzPKzwOHnazJcT6Ec16xPqWDaukm+uYX7MByv21JOz m0vy6ZeRGMFQAV/BvYJa4DDD5stb+DjBufYbOWDc8/UVggAOWgNLNPPIBu9nwHg7xNH9cEAWcdkR uGnf1+l2hU7bv6aTiXApsxFaLQDRQtxHL9EsWcvJhyIdPd/7BXxBAwrVhXcoWRaysVhL4sQUFG5g 6RZ5zj2UBRpmGa7XUP9gt7FlB55DlrNwg2YczCTY4rPfuJhrxR+j0YUCB90BZoNos5rBMFklSsuU 36y34/ULVNtcyirWNLd3Z2L+AsPAh8wbWkHWNUE/763F31KvykE5TsqfLu6qVkARq3QDXX5GshmL yDkc8QKyaLnFyinWCg8pTBYL0HWeLLbVsy7FhhBN+u7k/A66WjQLwfmF1URCssKTOE3Wi582pR9y c3aZkJPRzTXMiimJp2uxFptuZFRcNCAqrJi3APayTDBbOZvI3RcehtoMo+V0+bgcZmX5kIKY2fZB ZDpLwdtJZzN0r8RcWM171pErAQn7CzmG5Pr67POnd5fvRevG6TwEl0d4iV+xONBJ7Qn2h6LvyhTw 46x7Qd8t3Lj8yzeKpECXtAcN6jRZPQlvj1xwZslguHGznMf362Rz/7h9QLMWLhZQBWuYYtaTlzpg nu0afsu6Z0gw3wAXNqTw8mKYksECXt+Bz4yNv5rGyZEsFre7hQ5fRA9RprWsyaioP1EPYYSmq8oO viIYZ5hCJvdiYr2fosMyFB4LyAo32zk5/Rtl7JCc/hJw8HpG5ywguMsClRCC47iIIRGcZ5xzSlww hjjnfgBtcJ1Z9RcoCywmhYJrGGQwe62SQb7QS9D/VhZ1AserxWHkuhMO52VXPoljeOT+8+jyINs/ JucJMiq+UR53ax6v9g/qcng1Oewji9yPzm7IxfMmWWBvX6uZ/J1iTh4eQGeweKZED6YLXmS+eE6i 7UZU71hYY5yp5kK5QbbeT8QTYoifXF+RSFoxUJ+Jd3t/fTddzX+A2SCn24dvwxz69PLzKCuW2Op6 Q37fJqsXMn0AKySNf5gqWKnL+csC7FlEPl9ckzsh8yoN46H8MBIKZA+PRmCwrOd38MO55b87OTlB MkYc6Pa5TQ6eLEpu5rfJhJCz5dY6g5W9MAL4Bjpy+enuCv0AZkFPrioH5quAty6NT60dpfHFChL+ c09OlNKcLC+xLGVprMbSBCImrmVpAo87O0pz5mSlAQ9FK81Zu9Jw1/bLzo3rkxWMnY25CIMHHVpW 4kG5HTayyMgmI4eM3DfKs2UdZoYoX5uj6UGjslptl5tipSnn8wLFfj3i1s0YrBwM7R/TRZz+WJPJ Kp0L7P9FphOySHB0hKuXQ5gUE/Ify2h6vEij1fo/xES/SsT0FsKUVcphlAlqlKx8N+kPUPc2yXwW 6Pef0AIfpJPJGymDb7s7MlAzQ8B3ZWBGBnCCvR0ZbDODw3dlcIwMnuDCyzPAFHwLriw5zer2KySg 1rXTavJNQSlmdnLz6caC0Tm0YDUONuFsSMA4lD3jqzByYMbOxBwknAtyhvYIfo+Shzku7Mj16PKb BM7xiL4BvPTk0HchYirNnRcsfQLuxVJ4F9cXEqJvW82IUNxF+gMnSfRFoMgnF7fCEzoLl+F4Optu XhQoPEg0oISLBV1zipPNOlMT5r/tIi9dEh/m7pownsqMXIGDC+mKnq90eZjqs0YAQdWek3gamhK6 +r309RDGE1QKpqzKnjBNSb6Bhmct0cTPh9E3BSzoBBaXh0N1YFhJbcAy9wceCKuToHEjKOsIGleg sd0EancFdSpQvwnU6QrKK9BxE6jbFTSqQBvr1OsCKr+1KQknjaAt+2VlW+TcblZ5ZU7LOoLsXzms sIb4roJvmQsLxglWNOs16ioORCWMwLM0DCZhONiRDAxbx/DtOgxwvnDLAdFy392vot/8bFVAPGc8 3chKBRgR1AjGS7DEKhcCSbFKFmDozU5URL8ZkWHxsoFaBK5atpw9YIFey7ZSy1FNDTlYRxKGoIE2 MWpqKKFFrBh89OtqKHA9poJRpyoQj/BmvFGgCBmDZQy9ljOMugJVTZZYtU0WeK5dBwYzy19IadUz P+TcfoS+fW7Dsj2WEHg+YjWEUbb4/hF+T7bLYpUdk/GLmJal/AHTejH1lCoJa6pEdEYZw6nFqG2j qGoj+GhUCcve72yC1VaJVV8rLHsBiQIylrVideNb7Xkse2mGiVGrVdXQ1K5paGaJzQUTrJtWjlsL 0rKtmeXqFotGcq3QslaobPUcpVY8Wy9D1F0R7jt1IK0VCXy9aaIjJini7FeEWi6vw+ikCDWsUwbS VhHcDDTy25IiXgtFHK5bAIHRTRGf6VZNgLRWhDOzRR1JEd5CkcDSrbPA6KQINIluPgRIW0WYeB2P kn8ijxHHqfUMqKwIcz0TQ+qeVp1nQBFFxuD6WBUYkvUppt5xNvWO/W9Kdr13y9kdKXuYZQ9tJXug 16KcnUvZgyx7oEj3jGEhZ4+k7DzLzhXpHtU7o5RdcTu8LLs/UbPr1kHO7iiGu7hahx/BZ1BgvFol GudmKSs37NNEHtasrgNESIctYwRmJ7Ibpp+g0iKwaqYfFlDdzkhgSo06WY26clXYTrEeFXvsoxkM vK/0W81+vHi2foKABWe11sy8cirL0HwzVrjk1EqiIRdv+TTqjCnuNGBwuw7DGDQ5USl6ZXIRiiVV fXYuVXl19wE/1s34tmfvKAuT2q/yxvGj3eSNM9t3aB1iuQ9yTsk5U56vrdEme4q5G6yqrXmZBVRb q+ra1DTtrL5TsG9KPtOaMzwQV3bq9GadKM0KILXeggFS17jZ+YsMVjPR7QBTGrd5qcVcx1NwbWVF yhwnaZhApTkD3DtWh9HUQVxB62E+/4oOAjMer4Nq3UF8t96Jqekg9gCKLWUNbFqrRU1W3Kpcb8cY 6IdBg3hemcbV4QZOXIFivdzSClHR6WsX9drCwaOqL+WaVqjoaVF5vQk+1i1ZAUz1Z9xmm1TdK4OP tasQjzm1YFUHkXqHZ6srQ7djk3Kb1rqEde3ifpPzGStSka9xuMp6a8MVmVKUnejL8kTgarr4Tr5e ffp4An3i8vbva2ITh7jEI9Qi/0kpoYxQh9DqsIHhfUG2B+20Bk0GI/9pHZaVdiRBSyd/DdBn7QtK rb1qn+to/6mVVEKjTrAH7eKValPxrrmd0O9eC+0wZw/0+wL6PxuwJTTX3VejH15ZUCbemJAfqOaR Vg55f3MhIo7FuSqaGxgs9jspF8elyNNDGK7GMIKTjQgwC9cE44Yw5meKYTF4wFUMI9y7U/J7Vf7s eQxdTmIz12FmJ9fH0/RnGHWH6Y9F+Vkc+x4v0kUiY+M4KbBnaRhLHqKdxYQX3+aDOj8ZIct0vZ7i 6WR9qfHVc9/I6Gx0WYXH1IU1wZMilHU2HYebsIj4IPYRVGRWniP50eqYtIw3+TI6rfNvbZvhZv52 Pc4Cd6TQgEXyIztxnIRQlVncJT44Wcu58XSvde7H7VjOizclm/LmLViJlTJ6GP0vnXWKIBk8IBWB verRKBRQzIHicdxfF9cm7jFo9h5DHrCrYV/0nCwsS8pHHaiZhDMxPYl4FXJ7cg1VOplAkaojA7c6 h3A1e+0KU9MCo3jfoPioY6C6+zB4MB6PwUxiJFsRZqNgsFYYUbQLw2mDUUXU1WK4LTDCIOK7MPz9 GEHsFlwEwaQOg7fBqIL46jC8Fu0SVJcm6zHatIv0AnpOa1BEXOSnZHMVjjHqSL5rpTzF5aeKSDBx g0gMhWNkwFYyBEqGIsxuDU9++XR1cnpxdXFOzi5vRp+fHDkfToJSvu1ihp8wfn8VTiYYtT+bpT8y LytOJuF2tpGy+8i8+rhMNlAp4YZcX19+zu4PiDo4JGJSYoeEHxJL+7+C4pYoHOzxfBmuMAJofQhj fYBLFuoc2RhPaJHrD38U8b0VAhd7gEpUZhnuLyL8yy+EmDKjb1m4X/bLu9GQnE/X38nv23QDE1mM v++9I0+aAOBZfN1T9ix+v+NWl0uLe2eoqmMF+o0zQHPw/cTLxRLmvMVNZhdxNpGeEBQq+USTHzIW nmciTmmzc8rYcUSg3iPOwEmyKCP2ZCjs/yqUiFLE6JGbWZg50Lkhh1Y7X4vTfzAw5CBbr0glB5/M U8BoublheWJTzfKC3eXJ3LpaiMk+XSjFPvfqvKxHXqchLx4nDfDXJNkH4TZBZPEGNN4P4TdBJBlE sh+CN0FMMojJXgivqQ1gjAoIjhAwUGexiGIZJ/UwdhOM5yQD8Wtfq3iGMq16Nqvr2cJFgjFJsp2m NkgwgdYh2VoF2VIFuY6oIGzIXZqJNzyqEHvKc/npzp5Y8S4NPW0AVNvxGKIyEL/21LinjQMZws4g 7L0QXiMEyyDYPgjNojk92h2PBat2d6Ew8TwkVrli+iY/inePpUdbCHVrzSgLxC5tjuTtEgqrBE95 tIVQp7ZfwipG7Zd+VfNOLGreienOmgcIV4d4dc074jXYEhiX57jyxB4+7rXPjgiCa4Sqpkvq74ei dAcUr6B4Cyi2AyqooIIWUE4TVF3g/m4or7lUrKoruw0Ub4YKKqjAFlB7pgRHbME1wTluCcdblIzZ TVAmPco+KLexVFWsTZLkUPuVbOz1/iQuQprwY4uSNfZ6f5KU25OTpAWUbdTX6wd2IA5SZfd2COv+ LUAFOUS1fucOQ2uu+O945He/nOu3qmrvVGk3qsCau76FF/mlu1QgxK6JeNh/PAj56g9x9pwgQb6a wIaOJ0g863l/zgkSgtUGnvQ8QQJcu/40p/YcRM732qMXyGoEOrTZ4sd8ZmO+cosfwPzaSNAiANRp E5qMKLWhyQWK2yYmGVB4bUxygeJ1CUZGNLoLze8ShYxotaHNBRrvEn6MaLUxzQVa0CXuGNFqg5kL NGp1iThGuNow5hKOdok1RjgjgJlJcNY+65FH0TZkp23tBjf6uQzDXmExAqO3uvUF2zkAHdxv3XfF tDpZ5C5Db+Xu7IYka9yzma5xi6iWPshj1KkIiYLDklBI28nhboBthJhjaL4WLD/UKmh+LAOMW3gv DcCGyLaQA63LCxV47VoueV5KIVgIkaHE/Z8v5ze1RYKlN1fUA+/S9Zl+45nxwMfBCzCDq+mmfrur LVZgiQu+e68EVxnAbdeiN7Iw8F+mcZIWBw/iIun6MYzFPuXt52spvzg7EwcKZ1ej8uTgsNjKhBTp YR9L92WxDKPvGdvIdLMK55P10VF5ZON7to97swUXkHgmLhmAXIt5BQkQtKVlR0kieEkzEiCRBL9x 172sFt93KQY5nV+fDE7QTYKxUt3rzLpOnIy3D0WFKxmZlFE89SCTMY1fyPeMDTLrQVJWRrO7OAPI XpzOrNPJRlyHHIOnBjWb7W3jN+LI5jM5GP16+fnu6vSNAoTObJETHsJ7q8V2uItHHfml/ezjN3Lg Odenb8R1X7xRuyFfi7opHy8TIFMoj3mQZ2NYwu3JzVVGMpJskkjcP4IqINsF8kqtCft/BjYjf0uR KvEQ5mHBt1GSlGSVapH5mqRPk1nGyKJIgBZ+/JGhpZNi9325tAZ4AIbo1MnRW2SD7oS3dhtzBXW5 Yuh5jVkw6L2ufHTwsNw25PItPCMbReFiUTToDBydrOciFwAeKeNJZfKEt12hetYJdJpYhhAvjY9W L8tNOn9YCToCZEp4g7cSY/IA/VYkgYGKvkPLLJGyhTq2kw87MksmmwqOWzitTLab5LmBwc3hpVXx DktjpxgVgKHo+YTbeLqR2AxQx0WymeEReXZeSw6KrRU5M3OqzHj6eiz4K0XCAXU8F4Y7uIxHvusP 6ZtaHgvfD0S8fnGUsy75BzYrZBaKYQi+rKTzHZ+74k2If4y3sX5G7XOfYTt9TF6yw+Dx9OEe8tcc CItHXZmRTya7AN0nUyQpI49pWtG4+cIEmY3Ird2NaAfMqmtEzsW1dwPO2QMHbV8P5+PtdwMu2ANn +14tXGDVwQVsDxythwscEYW1b/6yuZwDt5TL1gzXL/N5spH5iaQGhafxdPCkeghbfhmuYKlOfnp2 reCn+mwUs52KcA1Yp8PDIkyhYEI6GK8f3hTH80U8gnXk5F2PHMzDf4E1YK40JwUOw1AJcC7XeIq2 RQ6LRZou6+Uz3MtWni3Zrmqft3HTXnk+mvwuhxUc5POzXCAb+d7WSDpJljDKNgRbrvreFW8DSMAR qvvWK8KQ7x+zK7TZUlGj6wDbXsfQgdnzSL8Eo5Dx4YvnpaDaKxF2kn04MhSuEJLJdDLGqT4dF9ZY JMnP4X3+/LkJEn3mJ80wYVYX6Q6LaRRWu9nSULzTyCm+zS7l4msMvh/CM8joI/5Q5ASlHGQOw/kT N0+efY8/2+yQYDvOksXD5vEYjzIPM6aJY9qAsY6wGgTjGDTlKvxRPedbuP2cP3e32sIEM0vBuOOR 9jEfiv8dgis3nWyOmTOkHiRYUnYXt56hotcp8sOsxRFvweIGSNtVVlHFmXzuH1LGnx1pTHLxjnFw wobk4t0l+eX9SV02+XnUTtCE3GfMNNe/nlzeiWllg/YDd6IcRplUVO6ipyPneYJecEQzbjZ43j5T HqbqwzNklLsXfsn9KplNcdq6z4SRas+yQggEU/V0sdxuiovyp9vNBlmz1uRtvt/29urTb6N/jO6u wY/OPp9+GeFn3MY7s87wo4DI/rVkeIeq1/Bz9K83v96efpMeFNc2O5YDMT5pwqmMGTQLf1cK55bt i8uzOTUpAN99uLi9ztffpWkJ18Uj93+ki8RS8peMKQXB6T+RVuzr3T+F3wormrM31fOOIGA25dFd 8qic32aN8pBtwbZUeYKn9/2HixEsDi9GgoEG95hzZ/9/Vk9msSojsP7hbEg4WPa3FHxeK58EYIHG iAi7FREauHaSKVxLHAxwRkrjbHG+2byMLLQ+l28xyMOegHM2Xf1OjolzKKh27sfgNmFkCnKcgz8B xQuJkHtSQtpWgF7yp3QxeEpn4WYKDl/ughYTFD2yq8ephUsj4eCQ8GH5gNa/ilV7EkRu1dM2wxoK H42bM1IUnvS0uOhU8/TJBzDwkEKRHNnCylrP0g0sG7JKg9/vx0sciDGZzpczMjq5O1EYKQW2XYud U5lmuyKL6HeCy7RolpIlzoez7Rzne2hTWJuES5jGKkhYDOMhRLSeCvoEjLgBeOl78Wrf8ntqfB+I s7bie6Z971iMy/i28b24TF9+7+jf43s9pO9d43sRdxBuQihZVmPhM/kCq8+34L+RcByuyBxd/r9W 16NEfRfXpSj8jf2NeTImHhwAJmhz/uX6+h/KV4I6LbRfJ47Vi7MFpvNKTL4D061TwRFfeeZXDp77 zKbj5ePLkLwTy9vrc1h8n27XmVshjWOHijeiJY/o/kSw5sAIU3ZkkZ8uFo9I/Rn/lPEHSz7MwQUM gje5KyMhCUI6RBqANwQTKA4V9Icq4hIjBw74VJFNYSL86fMyWdTI/dwgF1dFaSn3cwu5eEKwVeR+ WeAza7CzuthLLf61wmEW1t1zjlONZnHX/fmDcCIVLCmrgxSTDVkxchbLlFFGFNPFIcwX6+nDAvdu 4IvFdj5G9uIK0xYv3GnAfIwiNB/hfC0uelmW70eUoBEq3f5nHEa/b6er7+v8YCLg1JLxkfy4AT+L eBN+vYhCTHF7t5iGyms7FRi4i1nMMf4Hw/5TrnPumE0yLrVp/Au47enqmMbeGP+8WaXxNtocg2ym gHk7wNYbnMOg819PVsf2ISlAwIHNJsJPoi6PqYLoy4h5ln3N6gimrSrbdbjYQtfZbFe4UZHNVc6R e+QNYPY4mkTMOXrm3r3n/Jxt42HlDqByFcRARpQLPFTaQMrjo/fxuB0TOoDvsHmwNjBB1Kv0pOCO V56kTj6VFdtn5dOuF+zoYDsrxsXQsj+lvzMJU/Ap5FXDXtOFbAXM2QHWvQshoisjtutCmM2Ts/Xu Qojoy4gtupDri1Au7BhsdxeCJwOqPek19SAP1lsd7ymsRWFlhKDLXYUS4T7f8pCQbDer6HXuDKOC Wd2UzFoSPK7DTQxBqDMFBxwb+NMN9JuU3IzesuLqCE4gosKOsP3Fgj6vm+kK6mb2ciSBBSICC3mj hxkm+Xh6nnkJYmXvWYfwjyP8BCrnc/V8J19+a8pXDSCPicPXeYobXsnTMCu4+LPo9lE6n8PUgLoj x/JcWvxyz6Y4/lab6D6ap+siMBJ5YKNwIa7iZbc0R46Ux7Fq8sDfxGjP8iFYJsFnSwbBjXEdJJyF K5jdtktc8+NaCUq+eTwkL/b3Q8Kc/HSOLJ5gEjwUwd5YIWsJVjAkZJoPxN4JDI+tYAKtlgnQwaVF iGeL92loeaYptOwQRqkNY2og/oIVIvIzU2vA+Jtyq3iN95ri+SBGVsq/gtKP4eYI6rzCdywq9o8F cfpALPOLrj2texcLh4WqCLyf4vYK1Gf4g3y4PM95xIusB2dvyN+mqyn5mK6ni1DKLJjFu4wuEKRk z6Y/SM3GE8oWByOa7+RTEbIWr9Llff6mEPXGA+5Si9fX4CPFy0Swk8sbMAAT4KHodHmfnYYOhWri tVDwj4fXF/KtbrGDd5eEVd36SCX1TRX627vb6+psII2+VzcCuO94VosjZcljgtrAdc18ugQv/RpG P6xoL2+ePOmBwGpz6ulXOQLXMdjCLXC5HsTbB7wI5qblBD7DxFTwhB9j5LeMgLulOk17JwTPZCxn HRF8gyre7oYgGFZVBKcjgsny7nZD4K5Rk143BNH+KoLfBYFbjHEF4bokjv8iiOPz9RJYMFjWUfK/ N9OHVbj4azh9Cv+YhoujyRr6Oxido+33/wK/RpCffl5tx6EkQ4QGn/zyGyvNILj3D9H8PllEb+ME X6zxED5I1xdFHry+eDEiZ3e32ebx+IWTdLmZzqd/ZHzM2qZSQH3XrzkxglXw7kMZ5gV1hzIB5dRW CEHIJlx/RyO6ruy5/DTeXkEC2ow6er6EARsPpgvy25FrBSRKVpvpJOO5lHJxN88F+NWD5Kd3CXid YXHIjp4swn5PYFE+cULHtSBrzBxnYkMncDm+rCGeBN7YDakd22HgBPynSkxg4Vus/1j/CJfFwWC+ g79MwVLM/kjf4qFhmYFZYhFAwH98mEa59wxz0hBvqTmMSg+Kl9Hos2lxdzc/rxQBmDixwjTmDSz4 PyeW4HmnFvkCU355IupXR0UBoxR33ZBt/8N0nL0VCep8OsdDb1wY4kEJvsECTLsSGKvchqXI/+7k +x3FDpGw0DDXe0dWtuV2MBpBw8JCAfdbRrlnTewymkKgeOjwSBs/r0Px0UOXtnpeheJadq7REW5D A86AD8nns38Ofrk4u/t8S13rEB5kh8pOkpLfl/KDauDQgX+NZ/PZBbn5draZEqiwq9MTh5NPZ3/H w7Mlvv6JvrXZm0NyclLheWI7tcSTworQ+zPl+w7ejBB7etBjxP/IuXBqByeCVx0fRLXEb1WxDIMR cvN3WICQk0+jyyFxS2ywAnifbh1XyF/XcfhNUtKlbIAjHnrKg3jjWcb0DfM/c6ARTt8y5pD309Oq wl1OcQSZoL+uMHgJvHNcrAjq9uL4JMtFa4tyjRZtlCzEe5ssYodEMFHLGTF8QM54stmE4t6hqLTi CHb9YOXkHVJe5tcKzYoqtlrK95/gzBDGRqL+goPzm884yt59qZrcYwEe0IOccIj/UPyH4T82/uNU D9p2sYJkAzdbr4+24OqOlgmoIy2Ti0V6bpqK9X6F5Lp2rWZl3Yjj6Xi6/l7m8V0HIwJL6XuW+Yzi myekZT4vljw5lt2MpazyafMq31IAHQmwXOQjKvLdf/hy+j9I3Y8C4UkQ6oL/l6tLchWOxduToiMp ly8IGrJ1t9u4QscnuXgpovJk/R4PDEmLi1egYmHoIMia+nH68DhYd2xqGH8U96HRTJYGDgBHd3gA /enasmx7EPzzmvpg5kafLK/eziGMzSQYH8eV7VPPNHReK0vHmCvCaErEPZaOsez9Yzhr9FIEYAIJ 5k9QhItorxJxryKwhCmOeVgLk61rKLSrN9kMFcnMHZMG9vibrGazzcaGIHenb+0jzyF3ktUGXPHO CxN3l9UWuXhdrj1WGzOKK4wN4v4ky4tiuFa+psmBapMD5A3Kwzb7T25FBxzDrLZtSf2odys6jmDU kXGb9GW6vuj6+XVl2tkDIJdv1eXa1wMcR+wCNYn7s3oAzoN2XUdrnggZDxw7m68jnK8jWn4TWDRw 6gq9Aw2WFEgwU0QrbxdihZWvVoqgZVyXyC8upRl/tPLi0uxdpm8UYK+or2XWPCIS5zEp4LHWBuli 9oJviApFIKjtSUVjYldnd9HwzVhSODWspiJXDae2aHaNQioadGFrr86eo+DGoYGbqLj4Dli0xLCu jtP5MF8zwfosS8g6iQhFtym+slC8kAZjWdPlCwmfwukMO06FBtahvM4Zf6XfKkTGArLaZmG6sC7N F2e4uj4iBz/fnFyTn0++nF/ekZ9HF1eXn778Rn6+vD4hg5Obm5Pb68+3kH59cvYRfv1j9MvlJ3zw y931Dfn56vL07PYfN3eji7sv8Od78Qf8/vTl7moEoGdX5Off/gnP/dNB7LOzz5jr9Orj5Tn5+eLq 3Ze7S3zu4/Vn+Pvy/JNUN2CvNG3Oc6+DhKvocYqfYdLKX1h2pGTkasbbSvV891PwrGC/VvLZWr5P qYg7WGAkVzVLKlkq7oQsyyjZVHlg3fu/Mep+hin/peQLPDWfsp04DzEIDd+tnO2E5/1BWDtkMamQ fLC8VPK7Ojq5THJyBZbbjKU4uVbl5NImJ1cA+hKg4uSyNk4uQIizw+ykMdjhrtq+S3FfTnmyyV2F h8URhtJHkszibcLVA7ThHQbKraWKdl3HVXNc4e6Q6FfpAmPjVwvoVycY5k1GYgtYzu0x2iJ3lo8c YFzbW5go38gQ4k17LSGUfLpoTdUr7KHkHe4yZ3SIitq+7ezMPfoRLuXnA3tXNW1BseL4sqaoQWDt y/wxs7pGXp952ug9E7t+4CnMsPvmTI8j/KPKxrkIdFZGcPES+iw/EaG/YHhXCcY4IN4m3IDPUaxn kEtOOM44UUXb1Qo3prK5obzlg5ICQWhaKwmMxnZJfpmuNltoiTwaVc4cwFKiKXPZ8NkZh5qNWf7u 1sPqkNo7sC1mNQiKV2G03ZBonoVh4yUARRhMZrvH1MVCbNFCwi/pDN+wKmV2JG4STe7Jcgkzft7u v4QrEbq6VkRzcc/KyA2S/oRGlMRwjO6Qr3ZQautXO3zrCByZIXszJMtpfEzJFv7Fh+CXwwI0aOCn wOJtrfy5Hf/ruPAo1g/HP+FNnOPvMEUPsqIOsjLiyerxf+Sa/ge+ke74P95u16u3s+n4bZ78tvy6 mImO/y/xInf4tUlW8yl0F/i4ghKst8L1/6nSMQhY3YBAX7C2l8o58VijTe34Q/vPqJ28kIOnKCvL YC1K+G+uIlgWcdpQRQ1dVc6KZwVt6ogPnT+zjuA3Hif/u+uGOjRoGsf5UBxlIy97FSO4WNirwTHD KU8a04BjN3XEFkAyjN+uVwbe0P0zaxxfUwxz6jrrlXhW/2+vfZdZ+gRa1Jk+S0h5KPIX7Ksg8KdY MPT+zAr6V1ak+N9dLS7jLm3RB+gRtdyh/2eomE2Vg2Kq/HcrCOrhaUNxBDkVq/YNrBrWYh8h4/bG c9wBh55eZWPZ1uL+eoGm539GvUxx1+bf3+Be4KMVur05U+IjECQmXz5d/pbHaEh1lL3n9UiB8E2I bbzck4mbmTbRvkxBfaZP70ZPeMNnHEbfo8dwgZXZCOTh7mCLyYUeMeoMgz+xm+Nrg7f/B+yb5zJH v1vboCF0WGr9mcYK9fu3d1zPxRCXcsV8RFscpNgNByk+vkzbVrD2BbqGjqWcgDGLKmjeLrTO2wMC 0lcgzQ0CWM1/vb67+1Zl8gQHRb7Mh0zNWwL4rOcYz/oNmwK+73Hcbd6sIxyIkylGEN+NzhSuV1gp T8fZS0iHxLYDhuf6yCCroLga85SAVFmnqh+Nf8q2ErDnfuwkjkZCBX0fzBrzqOfxkoaKHgVWZqre ffnb5d3oCyneH1tsJnzKA+JyPym/STqQIxPhr7N0+bKCfrYhBxFGwlG3BLy6vL68uzgv5XnZG8tW HBwH8n76EOK9owu8kbYAcXmIHzuyrz4OPiGDgnwdPcuOkb9Z9oL5JWN3ikLc/s7v1ItXwv4vfNls sS/+GD5lqUWUbIXpCRImE5Mkm0cLg0uv8KU7ydPsLYe5En5nEa7l7VabCh7vQxI4wzgZcmvojYdx PGTQCL9dnhMLn8IXauPltoImORPs1yqTC/4XdPqUTMBf3cKAJ1/FrVBoywDvAuXEIZtnAqtk6C3b +Vzccf2elv098DHC5xv5Gq/mUswhtC4k4CktSMKIRau8cQF5Aov62ZEhdB5y4FJvTxxUWRgpDgpx KOW2jLOHlgFjhwwcGMbYX5g00Au7Nkt/NJo1p9asARjzbAy/5Bajvw/x1xH9O/nl6uQThhaIefGJ HvHycdcV8Ux1DbRYsrW4yJn5BWKnFVutzOu5Iqx1FU5jb0jW64Q9U/jmIVkcvCEEFhacXJ++XZfP cySpM59/Tlf4vOcE2vOIULbtdXZlcZv1/fELVHK4fJxG66JijgV7xbWUm+OGkug6WFPl3fziIjex s+MG8rRGao8qneYf3ihYNl5g1q5AiwvEULzJOKue/HKzlC/AaJ6d96dj6NYvhRLcemZulT3w8L5k VgG3yXIWRpgXr0/nS3ol/lfkEO+NkquYlU1CkU9JqWJKPR8X3PrzeZPgqYz6vG0b+E6Fj/zZ6vOu ZTS5U+LD85atPY/vkS80HhVvqnkaz8LFd0EaAyNqvhQng1gTt+BUMXLAcGlyBEbZLjaEcyi7gMqt evnuG3DJIqQNMZB/3yarFwnEFq9N0t6cgb7mA9qY7E0ZNe/QSGex9hoN9c+h9FaNUpjny5UbPj3L 44lR26VqZXGL4577xW93zmCyJgcYa/QGGQWQcwcGLK6u8/f34CGZoHXBUuNLMrKzrc/LDZ4wL7az 2ZsKNgvEk4sh9aHA4VobB74I+C48wQmSZQ0ewB76eyhJKPdMmhqG7ejjZWq5AFUng/ndd5UCiOed 8vnMLoazh3QFWs+L/Dtzu3ruTGnoJKmg5inRqly2iJ56xvj6cLtJ57jXEs5mLznCGNWVpy0y2S4i 4RdVGBxfhZhfR8/4tXIn5Ov7d7/h9XcRuDJ4TMJ4SF6gmsgKz0EXKcFXp2zwU9lsjFqC40O8SD5/ I4xn3MOP0hR5Iu6zB6gt5RYBSjmPQFaY0+26NZlB9tp6TP7l8vzis8Yt4FZyqHg/ujlfTwNwqSjy /wvvijIwJbjhLA8rPOSAusTUCpD5eGsFfqDRSPYjDthtnFkz85VE5ePM8oqot3Ku3eP3W44Xy35/ ZBeXiXM8ezdex+i3HNTTQBXf/2PyMk7DVazk4FoO7YZb+oBHwo9lFtsSRMl5ixdfK/BK6y+jad4W b+W7bW/x/uRbEPpWCH6biy9+45oCn7eHUI3nwzOoO2wWKveOqjY98JCgTKebFdgz2S/G75iDgRWn d7f4PoiirXC7JGQsjvk4GjAnmQycSeAPxmOPDSw6iWI/sieUZicZMaHZ/gB8Yq5Q7W0VkcmQItzF Q1JVhng9ByxW54kJAktIy6EFUhE6AkhI0sTEfaFB4XjU1MIwq/7D7FqRVd3tecIZrWqHr7XN800c +q3HA7k98uqX+USwOJxiN/33NzataWwmN7ZflMkGU4Anr5NxhItFyZU6mIwzLovlajoPV4VzVGa0 wa2i++qWSXUL+a28jqlex4XFfV0Nlw3uwDTiBvIIZC02J9wGL96BJSz6TZ2Jd5hjPXt+BRO4uOUl bKtK5yi4eBT3tYGOB1D8bPWoqLZvr4TFVLaZ1JkoeD7djafYTLZ3tyQHtTXQ0mZ++HLy68VlfldM yeJoWVSjmee7g36xgEp/eCnyuk55pS/Pa2fNPQFXqrG5vYbm9qgr7m8qaB1nJYvHgYLn7cZr2o+y mmrYg8WYssWFJM57VfYbVPZ938alUas3CG3W5QQeeL7tcq0U+6oqpEy7oU5lPM/ajddUVY0TuACl GmjZGU/vyrfc2Uh34zuKfK9FrfLaWrXBnnncdTS0ru6Ny8YKnrcbr6N7k4NyDVRxb26TKKmWtXmO QMuxy72BLMgSDDUxy9MH8b9WOao8WbjsFCcLd0jUaYKp0wStnyaKcjZPE142TbCyWNDcdtbcg/Um XeGFrcL2lDu113gcNcq/LV71p+zGCqBARDMW5D9i7VILWmVh4p3X9Y/RLrKZrxAX+U2yaZXFKfbH W1+BLvAqDJ85tAtGuC7yMscW8Wm6A4RB3K93fLziN6jK3tZ0KynNsTK/xJOdIV6Vz7HxjmbZXaEb LsWhODZADYrqOdp6d63xHFHVHR11WLYV8wLfr2LF8qOdA5fuISyFdbTJMGqLNwf51ISz9uyW4pvN auA823F4dYhfnpJ/xVjKYTEkYzK6fH93cXud7cvdQMVQcpDnKTaJ7CMOyyaMzC8JXaFngxLh0yYc 56/+QxqyQyiN43OPrLZVuArkZlyEdL0ytw/ZLZlMFq16gvdVqAMLfcGj7Fo0i9yHz7Bgw/e9zvAB sk4WApg5JAo3awXUlkEDlp1vJ1o5qhxcTKhVjhs8hFuLs48nWJzjZed7seDB6JHsrBxW1NvVdPMi 7pXG+VkQ8iGns2n0IqnIHTxBL7Exeiwcp08J2S6+L9Ifi6Js4o0ny1LwmvyYzmZ4YzV/F6KMyBT9 ztL5cpZsCmZwsZ0gzp+UUuDLCqs8o/wS7nZJkmcwIeJCLl68y+5clDkDmsXcKwEj2ZkkTs8vxYXh HDlXHyuCwjB1nGAuYTmOowdD3yZibYl8dGiARCW8XW0XAsHHgLoSwDnCN/h5Ndt9q2SQ7/jV7edB Pmhe16mi6BfpQqhZ3nGerk2OZcyGEcO5kfeK6w9n54Pbz9dE+sldZKLOHMUST7kQwyTsQNxERWy/ +bJNiX33jpyd3J5X8DuwwUTa2aUYf9+lGFu5FIN58SVhkHdVafx1vco59gY0m1jkp1FSFItduS+L qWBFy6son4Nuc3qBIVpCSZDtiUJKgtRC5iggvMrjZK+BbMxTKeZkirlVXi97f6BUKV/XcazfZFkl 8/RJHLBUd1ogN/ccPIm+XICFFjyz5PtiAlgHUXUqeoZ7w4FH0u/T1V/n6SKMj9Y/xkdx8qbswRh/ JYXAVqYblqmy6cYgVJwPYBUwmW3BjMKQwB16kmeQbHoBDeoJ2qFluMIN/vtlVLy4bZVkFGl4ZGS+ W6nK7wsa7Dy/eJMO+B8vUBPiINT2+aHg+XHJ15uz0c3N4d3t5eju5O7iWwkRBA7eD1g/LiOkLB5t QBJOwRrj8X7OYufIt1xLvCRlKQiEcFqAtQC6Nsg1B7lnGQ2RfPoDudzAxRDTKbfo/Xouvw6FTnAJ KG5SiVDlzK84wJUQGfyXcDDeSDBiYhLvnvo1XC3EoWsWH375Ge0IjMCMyK74eWc5+UtapCT3nbgU AiZxs85OID4vMYBHcOLtze28Iwf/9/3o9AhqzToanX4ZHY2uTy/fCMYfvFTP3243GDYCxmLAXFct vltsq19OoMHz12jl/D7r6m5QHtI8LQ4RD8lLuoUWFJwJyNeE7zaAXo8XjdKJmL6Qa+Ep0Woepl3x wpb1Ir5/jMN7sbFS7bjY6NnXVb6VVz57UyHZFr7rfRfSWLzUS9kYP0iXa7HNc4+xPuk9smyki2Sx uccXldzjt1/x62+SIFdcVKsXRMddiuwLeuc6JDePXGiN5AlagB1I5yL6AaGuR5dKRn93xnep2EpI cQIcrAWzekUg62BEsQhbPolFjKDHnMD5f9u79ua2kSN/f++nQJWrstLapDCD1wAX+yJTcuxb2XKt lOQSZwuFFyWW+ApAWtKl7rtf/3oAECBBiaLiVCpl7EplUujuefT0dM/0gzTXGwOpQaA2V6fFsk8q Uj7CfdB9QHtCBn8S2naFESX5rCiCFejFxbuLGr9PI26tmojbwCRMIpOsKYO+wLQN5InQ10k6morZ c3CMVwLOARnOloviNWmy5l16RCum+XPIMj8o5ll0s+JMJuvuQpaeElZTMUHF3KDSQuztiPh6vjtO tSNO2mNmAf8G7teEp4XG3xENm1FF0ITliOtdYA1kBULioFL7cMg08yzbf4yDoecYw1E+4fotUCJ5 psnGHt71acEawwgpcrTQzPKc/tZrkPA5FVlpyr4/OS7zmL0/+fiBfx2dfH41TyavrccsW4iTowLS 5Cihnaq8svNrStL1HHsXSt5+lCqfHJBCuQEidTk4D7/ywVRYXtYjRxw+98rPr1dAtmBV7/H2qT3b J1akaIsxy/bdpougpEQfaYtcJNcnsysdE1dv67DDG+AuFMsV+JKDmiGOkKpnYXw6D385fXt+fsnp ql/VRy9l/RRoL9fUMDDM0dsP5xc1Zs+R1gavo5zRIrupGVacyA25cnw2UH5LrthYncKmJSkc/HLx y2vIFrzaJGzLnQg/SbKUmO1dMVeihYWiiB/GuiEIt2HdJlxKPBtybxuedHTV0wiEOFrHstu0rcso Dby5lWwDNox3OSmdlajyW1h2HhCUuonyColqIdmQ2NuRkJ2cAUFUI0CtBxvZMlNOoW0cKOeRcyZT dhwMOX1h2q5dV43Io/kYez40Ja5c1S4N1QRy5GNAOG5sQViPQSynGzDOYzCoP1VDCJ/r9W2Its+D 96v5fPTkMm5JterOst5KBPGgZ22hUs33nkSsmoilk212EgE/7EnArgnYyMXzEIHz5aIctP1IOStS Nqfsf5jUxZK2bMzuftTcBjXPkY9RG5y9O92Tkrei5Fhm107a7tco3XeyVIOS6zzM2O/J2ppfz/Zm jFrCSd+U4LxJlo6iKsczf1jdFQS6okUFYuE+zkJlp2W2mM0gb6oaRexs1HiPsxc9WpiqDeG3MCNf dbnP41CC9uZpxi5ixiSakpDKN8/lNB7f2sBTBuzoWlTbwNrkz+Tg+PMugJJ9YlaAF6T0PA6mTByd 6kH/yv5kSTTnjBTNwYeTVg0jFHvOXxXzJAohE/kF3FFsFLWit6Vj40qp+bb+9/8m1t1drwSs6j3h mjNYXZITvCWlJZ9wnRQv6FUN7cL5UspV4Z0G4f2vk6zm1VB1WOhqP8+npA9uNKbCIeGuoJ6Agzb0 Hi6KeAOvsUhX4AaR44nCeU5QN2FxE9OmrFzEfowRiVWwmy3OZarJKiF3iA13UHQn8PYJf9aniuEy KP+RB2DLcBEU5pZ4JUSeLsbfOPzQBaNKf4fAM6fvm1bg7RPWvFvf0wmcXHtcOV5nDP32PbfkZkCa 2NLzfcKL/1V77u4WV009t73A2ydu+Gn8PiySm9+B53Gw34vv/3on0yVR6Qnr7Qk+uEq+/eaj4pO6 SVLg4vcfjP95d6HPN44HZ8Wr1Y1itFjko3jJkT/TWV2Gt5HR2O2T3e8iDRlwHBRpfIg04LgjQHCE w6ladCMrANJuOJNUA+B0qtMRj7Noql3m65fJpHF2WK8kmS0RePsERO/ItTp8tLheLlK+K/22s+O4 ps5Vu0O/VeDtE/C8W7+nw6JXHlT8E7qMfDyPCaiyy/sEBf/rddkyd9mNXNhVgdonSHi3Ls/H97Ts Ftc9zlp3q9MAfvO+6+Spj083+i7+rfruCS7+vMu8+4HaJz3Pbn0fcv723miCw9yy9MY37ruSlgvP sYYN8/bT6WfjoI7KPZ0sx6wYHLKpVxdELGHtTVhd/0JXftMmHwfrJFGxaILCfl8Hfdh28sjM9LVt MXefWn/DQwyFjdxtp7EGZRNrw3zyyEAjW4v6NR2GMDwXOY7YVqWKHVwqctF2I16iuUVdDXwS3R1W WGyLviIBGuej9CprhEKV44Mt9ivZ21E+Pxrhf7ds1TVZSXGWTXGql2fI/Z/2q8oK9/BuL5J8NF8U OCHnC5I4D1cFtkdDvqidwjsW17f9uj0OWSLUHpQDCYzjk5NfBuef3h2QmX5y+sfwD58PgzqulbPL l4XUsAzvaxykW8D/bTXIE2ImFODlrhCusw+ffsa5gWWuCHu2w2c185CsigZXuNUbjhKOvyUIu9kk bPUNGBdBXc/pDnDAtXB3uqpvkcGJW4XFcho0Svhd/uHT0eXx5/pyoixtKvpuExArjQFLnxAfPGsb H6M74+c8Kqb30bS4uTd+S3x087u/LaMxVj/K87ypsNjSZk2kpPN1lMe52ZuOUBCjPmeZjIpkOVsW jVtcBT8OLgOsQQLtJSEOVhgOaxTjOnUey6AGBgVXmWdgUKaFYKwdMNTXO20EqL9rd3Uf593b+05g SAa5J12/r5QjzB04dDlvQsC1rps/B++PP/3+dJ1H44ymOisaTCqIb0iq4VJzyE4XJBKNA6RGqOQR iTVbyxyJ0zriDqclVn95Nzj/+NG4vPzzFqlaglmyC+xBeVxCQiBsQuq9orznk7JvOZIN3g8X54bv uqZONsEejWUFmWJGM/jfs/EIiSVRnspoAPsS3g8EjOgzDjIuI37IOprBmejeyIk+A1hu31Pwrf3V OPl43DuGswsbSwxDygUcVso6v71ywukvgBVEzFE6CUJT/DfF93U2nqPyOZcKnCDbHzvJVLKaDyxp lio3TXYcAz/NZlOS4zSJ8JUhAa6l/eCyynFInYnY5aykUFT+NSxJheX1laPZuOT+RTQ3H1z2DIOk H9YG6wP2weVawrJL/tNhif9dR3WImzXYTPtQNUBt0VeW4tS0D4JurlMGdR0bAqY5QlslQwng2I81 s4uW3ydBxPdz7Xwto0l2k2VzdOoWt9/pjBOQosoSAjPyG21aryJ4flwUyY84GV3Ch5AzOBAjLUs+ KW5wBIm9njZ78EnQIM/yvEW++/kRped+NG7TcDq7DepE2vhiHCFY2huqyHREUmaaaZZ0r0mJ3Uhx b5JCU1LS92SS+iLGV5oWqX6kGKnEytaobVL1FEK1doqDQg8BKD2vT+KS/eAnE1QuSq5zxKceSFfB SP3j5ARB/hIlT5RSvksqdZJVsf/L8WhCa1ei2Iwi7dbrG38q1/FwlscIhJnqlUzEkAyjL5C0h6QF LdihPivOl3Ms5tmNnrQZzfeBdKQ03hiSZuzwFbKXaP2vTBMK2JDr5YVI21NE8NsOcyh81E3kAseJ t1DEr56gVUVTcYPEPFl+lN4Dz4GQj6UU8En6Nq+Gf/gihSlJP/EsH2rJ672eFhYErxsfPr07xzIi 6QheTkZ5QvZDblR+1dQc5BiaJvd18IzxawsN7V8PVRt9IYxPpMgtIgx22oIkZunt97TQkIQ9Of9o /EmPsCUcXVZ4kd+Xe06UcCpY7lPQAkW4/cFvirj3pghhR/bejMLJcpHdhTfZ/QtpHv79ZR///d8r kvWB8eW3FdNHpk90humbX427YREiQUWoQ06zNIxGs5At4ZfmnQvvNssxjS/0Xmvg4Gi4nhM7Xi64 Ahm7do5ZryAbccznexutRzwstX4+Qru51Udia4OVkD5NeUYNBkAIbC9RKO4IxZ6baHElt96u2+sR 7XNc4atqlmaMAsKSnUk5y09y029xqt/RR7xdxyo02Iu0hNHUOKCfPIO2lOk0HwifbnUbRz7rOHtv jBdy61g0wFHp4tcKqjk6QpiZj9FBJ8KSY2iAhhggMTRbKKxOFCr2I+ESCs1BjGhKCztLCY+CC5Jt tvF4nXh2myhtV3SBJ34SmQRezJHyOVzMQiB6CfLA4baR2FuQxKSGEJKwKourebzECRYAc1sWYfRE G+OWXiVxLBzC+AA+G85afhub34ENq09GadJcfW1MQiToa7Sx7mw+Pe9sX2SawJjOwnrk0EcgUq02 2d3zL5PEj2zCcHF/UaIgeG8INzRltTE4WzgotWJJGFD64T68+PPF4PjsjGRpOKS9eB4trtE1iTGX LXSqe0kIWhIHvxnNIdZGM3DSIa2OnHnqhaT1wU97fcD0f+b6cLp7RxaZk2Y8wrdTLSBX68MBnqSN pouRaOqlpUynnPpRuTwk+/nJpGO+vW0c5Hhm9Kj89qJu+a3ruHfjjaVo4tU9pZ8cs2cLdkjcRMj1 z7vYSg1TJ+Ol+JVQVg1LeOBbEkGIriZBoJguL70mfMSOka3FJuSWpUF9Uqpk7AreUQSftsG7WWdP rmZzvIurzd227KCFq3tkiCctM+axXeNr4cqYnUZbPMnVQp+3OrgkducoPW33EPAY6ea/5+gltnC6 doTn8LXXPWbE14kVl1wJLKs1F2+wlrdN5Eaxj72O4Zv7QIVLetj0rPYseltWWpI4wl8X4Jbrbwhw 4XUN/v6sDhm1zuoznOiTiTKckcoULYwJR6fhrIHshvI2GSfGwQ9NTMhrOmBNinUsFBIKNiuvPLB+ SCV/Yzywa+i/txStdgMgtT9X9gQZydEwq62JIsmmEarQt0FWi5NrVXc8qEDdAlkJddgDXSBtO8EW Pgs3tGRdT/zP1msrTtv2aBwPbKxthM6OCB9qlLdq+wOirwkjoehuzPxPP/1knJwen5ydD37Ghx9a ECS/JVMpwGfsqr9uWQUtAIzVCzMgM6SI9ZLLixfCO/w7i+CXnVaI5ac2S1wCKZCzvl6rMTSllrCU SKxCekzwjzd0bCk69hdtg8P3C+eIWau3OKAkPkSxoc8fTgJDW5qD2WQSNIapae0+Yhi3kFNH35dh EZy+PNAJd1FHb5W0h6j1Xxlni7Rv/EV5H3sn1vuj6h+vDERTGO+EMEx1REJGmvAsXpHg3d1sPcqt v7DdVKS0eldFzJyhiCPfXBVyE7Y9jJDUs4ETHFC/IGNpu0Oz9QWqVq/hTJs4hZnSbLVweo12Jq4w E99Xaw03ZYXTqt9of9Eyczi4ZhCNx8blxrSi6lGLf3QvoacuJ/OQOaLagpPWnMEBaE3DTUvOg0Nh WB2m0A58BRaMmQdb1pJka+Q5KgmHruyrjEi3Tb6hPvzXvgqExPH1s1Qbqb5Bq1hd/8fitMz1oTel il2fcRY49gyTUvxAhWhNvIXA3jZslmYyYViuJFfDalO2BSzlts7s2xW53hxqjxe53JxJlN+E2BB4 6gpoaJi0qN2k9cVAs54IpRF0zLtUamPiLbi0rLdCJQ4jYYEcInRslP+tCGfTEG66rHwO2ZaJW6js jiHaT4G17HUJ8RTV1bLXR3Y/pdWy1wd4d3WVAznb4+rIONPjCughJgiLkQeyddrBEZrPUXJtsr76 ilYGgiWK69ltiIs44u9JcRUY/hZn6wYYcuzzpcAXS3kKtS6zq2G0HC+Q0GBI20mcZUNjNOctwnEt JxuKTNmeMAr9nUcrwSatI0podnUQqssZYDRWBomdIbLDv3SGFvYpzD/ywPc911Y4wH+bz26LLH9b arJfJFnUa00xqzZ4Qz9xVeJ7mchWbfATR6aJ41iq2YbxCNk++9LqF7MvGjCW3BIR+3VDhNdXynbh dEHLYF4ExtWUmt4raFWOv6BqqdJ/wZWGRe0IvKGZ2Y7lxcKPqQ30eZgmSKnuy3IMAlOjVn3HpBeR o5HHIxxcj8bp5XX+hRQc397WyVJrMJWdqVUnI5G5djaUsjXQ8/HyajSFWyAUoyz/YjPwSzfiHv7H 9+f78/35/nx/vsnz/04nNRAABgIA --047d7bb03d8a4fd0940534c77efb-- From emetcade@memori.ru Wed Jun 8 20:29:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 57B727CA0 for ; Wed, 8 Jun 2016 20:29:07 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2B425304039 for ; Wed, 8 Jun 2016 18:29:04 -0700 (PDT) X-ASG-Debug-ID: 1465435735-04cbb0356bc31dc0001-NocioJ Received: from mx.qip.ru (plesk.ibe.pl [62.121.136.10]) by cuda.sgi.com with ESMTP id CtC6YQ2YZAocVGW7 for ; Wed, 08 Jun 2016 18:28:56 -0700 (PDT) X-Barracuda-Envelope-From: emetcade@memori.ru X-Barracuda-Effective-Source-IP: plesk.ibe.pl[62.121.136.10] X-Barracuda-Apparent-Source-IP: 62.121.136.10 MIME-Version: 1.0 Date: Thu, 9 Jun 2016 04:28:59 +0300 Message-ID: <377610167.20160609042859@EQVYXTDRUHV> Subject: =?utf-8?B?0KDRg9C60L7QstC+0LTQuNGC0LXQu9GP0Lwg0LrQvtC80L/QsNC90LjQuSDQuCBIci3QtNC10L/QsNGA0YLQsNC80LXQvdGC0L7Qsg==?= From: "=?utf-8?B?0KHQvtCx0YHRgtCy0LXQvdC90LjQutCw0Lwg0LHQuNC30L3QtdGB0LA=?=" X-ASG-Orig-Subj: =?utf-8?B?0KDRg9C60L7QstC+0LTQuNGC0LXQu9GP0Lwg0LrQvtC80L/QsNC90LjQuSDQuCBIci3QtNC10L/QsNGA0YLQsNC80LXQvdGC0L7Qsg==?= To: xfs@oss.sgi.com Content-Type: multipart/alternative; boundary=----------8805BC868536F5E X-Barracuda-Connect: plesk.ibe.pl[62.121.136.10] X-Barracuda-Start-Time: 1465435735 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12212 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30289 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message ------------8805BC868536F5E Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: base64 MTQtMTUg0LjRjtC90Y8gfCDQsy4g0JzQvtGB0LrQstCwDQoo0L/RgNC+0LzQvtC60L7QtDogNDE3 KQ0KDQrQn9GA0L7RhNC10YHRgdC40L7QvdCw0Lsg0L/QviBLUEksIE1CTywgQlNDINC4INCh0LjR gdGC0LXQvNCw0LwNCtC+0YbQtdC90LrQuCDRgNC10LfRg9C70YzRgtCw0YLQuNCy0L3QvtGB0YLQ uA0KDQoqKiAqICoqDQoNCirQktGA0LXQvNGPINC/0YDQvtCy0LXQtNC10L3QuNGPINC30LDQvdGP 0YLQuNGPICpjIDEwOjAwINC00L4gMTc6MzANCg0KKtCc0LXRgNC+0L/RgNC40Y/RgtC40LUg0YHQ vtGB0YLQvtC40YLRgdGPINC/0L4g0LDQtNGA0LXRgdGDOiAq0LwuINCR0LDRg9C80LDQvdGB0LrQ sNGPLCDRg9C7LiDQkdCw0YPQvNCw0L3RgdC60LDRjywg0LQuNiwg0JEu0KYuDQoi0JLQuNC60YLQ vtGA0LjRjyDQn9C70LDQt9CwIi4NCg0KDQoq0JjQvdGE0L7RgNC80LDRhtC40Y8g0Lgg0YDQtdCz 0LjRgdGC0YDQsNGG0LjRjyDQv9C+INGD0YHQu9C+0LLQuNGP0Lwg0L7QsdGD0YfQtdC90LjRjzog OCog0LrQvtC0INCz0L7RgNC+0LTQsCDQnNC+0YHQutCy0YsNCiogKDQ5NSkgKtGC0LXQu9C10YTQ vtC9OiAqNzI1IC0gMDQgLSA0OCogKNC80L3QvtCz0L7QutCw0L3QsNC70YzQvdGL0LkpDQoNCn4g KiogKn4gKiogKn4gKiogKn4NCg0KKtCh0L7QtNC10YDQttCw0L3QuNC1OioNCg0KKtCm0LXQu9C4 OiAqDQogLSDQv9C+0LvRg9GH0LjRgtGMINCz0L7RgtC+0LLRi9C1INC90LDRgNCw0LHQvtGC0LrQ uCDQuCDRgNC10YjQtdC90LjRjyDQuNC3INC/0YDQsNC60YLQuNC60Lgg0YDQvtGB0YHQuNC50YHQ utC40YUg0Lgg0LfQsNC/0LDQtNC90YvRhQ0K0LrQvtC80L/QsNC90LjQuSwNCiAtINGD0LfQvdCw 0YLRjCDQsNC70LPQvtGA0LjRgtC8INGA0LDQt9GA0LDQsdC+0YLQutC4INGB0LHQsNC70LDQvdGB 0LjRgNC+0LLQsNC90L3QvtC5INGB0LjRgdGC0LXQvNGLINC/0L7QutCw0LfQsNGC0LXQu9C10Lkg KNCh0KHQnyksDQogLSDQvtGC0YDQsNCx0L7RgtCw0YLRjCDQvdCw0LLRi9C6INC40L3RgtC10LPR gNCw0YbQuNC4INGB0YLRgNCw0YLQtdCz0LjRh9C10YHQutC40YUg0YbQtdC70LXQuSDQuCDQv9C+ 0LrQsNC30LDRgtC10LvQtdC5DQrRgNC10LfRg9C70YzRgtCw0YLQuNCy0L3QvtGB0YLQuCwNCiAt INC/0L7Qu9GD0YfQuNGC0Ywg0L/RgNCw0LrRgtC40YfQtdGB0LrQuNC1INC40L3RgdGC0YDRg9C8 0LXQvdGC0Ysg0LTQtdC60L7QvNC/0L7Qt9C40YbQuNC4INGG0LXQu9C10Lkg0Lgg0L/QvtC60LDQ t9Cw0YLQtdC70LXQuSwNCiAtINC+0YHQstC+0LjRgtGMINC80LXRhdCw0L3QuNC30Lwg0L/RgNC4 0LLRj9C30LrQuCDQv9GA0LXQvNC40Lgg0Log0LLRi9C/0L7Qu9C90LXQvdC40Y4g0YbQtdC70LXQ uSwNCiAtINGD0LfQvdCw0YLRjCDQv9GA0LDQutGC0LjRh9C10YHQutC40LUg0L/QvtC00YXQvtC0 0Ysg0Log0LLQvdC10LTRgNC10L3QuNGOINGB0LjRgdGC0LXQvNGLINGD0L/RgNCw0LLQu9C10L3Q uNGPINC/0L4NCtGA0LXQt9GD0LvRjNGC0LDRgtCw0Lwg0L3QsCDQvtGB0L3QvtCy0LUNCiAgICDQ odCh0J8uDQoNCg0KKjEuINCg0LDQt9GA0LDQsdC+0YLQutCwINGB0LHQsNC70LDQvdGB0LjRgNC+ 0LLQsNC90L3QvtC5INGB0LjRgdGC0LXQvNGLINC/0L7QutCw0LfQsNGC0LXQu9C10LkgKEJTQyk6 Kg0KICAgICAqLSAgKtCY0YHRgtC+0YDQuNGPINC4INC/0YDQuNC90YbQuNC/0Ysg0YDQsNCx0L7R gtGLIEJTQy4NCiAgICAgKi0gICrQkNC70LPQvtGA0LjRgtC8INGB0L7Qt9C00LDQvdC40Y8g0YHR gtGA0LDRgtC10LPQuNGH0LXRgdC60L7QuSDQutCw0YDRgtGLLg0KICAgICAqLSAgKtCh0YbQtdC9 0LDRgNC40Lkg0YHRgtGA0LDRgtC10LPQuNGH0LXRgdC60L7QuSDRgdC10YHRgdC40Lgg0L/QviDR gNCw0LfRgNCw0LHQvtGC0LrQtSBCU0MuDQogICAgICotICAq0J/RgNC40LzQtdGA0YsgQlNDINC0 0LvRjyDRgNCw0LfQu9C40YfQvdGL0YUg0L7RgtGA0LDRgdC70LXQuSDQuCDRhNGD0L3QutGG0LjQ vtC90LDQu9GM0L3Ri9GFINC/0L7QtNGA0LDQt9C00LXQu9C10L3QuNC5Lg0KKjIuINCU0LXQutC+ 0LzQv9C+0LfQuNGG0LjRjyDRgdGC0YDQsNGC0LXQs9C40YfQtdGB0LrQuNGFINGG0LXQu9C10Lkg 0L7RgNCz0LDQvdC40LfQsNGG0LjQuDoqDQogICAgICotICAq0J7RgdC90L7QstGLINGG0LXQu9C1 0LLQvtCz0L4g0YPQv9GA0LDQstC70LXQvdC40Y8gKE1CTykuDQogICAgICotICAq0JTQtdGA0LXQ stC+INGG0LXQu9C10Lkg0LrQvtC80L/QsNC90LjQuC4NCiAgICAgKi0gICrQn9GA0LjQvdGG0LjQ v9GLINC00LXQutC+0LzQv9C+0LfQuNGG0LjQuCDRhtC10LvQtdC5Lg0KICAgICAqLSAgKtCX0LDQ utGA0LXQv9C70LXQvdC40LUg0YbQtdC70LXQuSDQt9CwINGE0YPQvdC60YbQuNGP0LzQuCDQuCDQ uNGB0L/QvtC70L3QuNGC0LXQu9GP0LzQuCwg0LzQsNGC0YDQuNGG0LAg0YbQtdC70LXQuS4NCiAg ICAgKi0gICrQoNCw0LfRgNCw0LHQvtGC0LrQsCDQvNC10YDQvtC/0YDQuNGP0YLQuNC5INC/0L4g 0LTQvtGB0YLQuNC20LXQvdC40Y4g0YbQtdC70LXQuSDQuCDQv9C70LDQvdCwINC00LXQudGB0YLQ stC40LkuDQoqMy4g0J/QvtGB0YLQsNC90L7QstC60LAg0LrQu9GO0YfQtdCy0YvRhSDQv9C+0LrQ sNC30LDRgtC10LvQtdC5INGN0YTRhNC10LrRgtC40LLQvdC+0YHRgtC4IChLUEkpOioNCiAgICAg Ki0gICrQotC10YXQvdC+0LvQvtCz0LjRjyDQstGL0LHQvtGA0LAg0L/QvtC60LDQt9Cw0YLQtdC7 0LXQuSDQuCDRg9GB0YLQsNC90L7QstC70LXQvdC40LUg0LLQtdGB0L7QsiBLUEkuDQogICAgICot ICAq0KPRgNC+0LLQvdC4INC00L7RgdGC0LjQttC10L3QuNGPIEtQSS4NCiAgICAgKi0gICrQoNCw 0LfRgNCw0LHQvtGC0LrQsCDQutCw0YDRgtGLIEtQSS4NCiAgICAgKi0gICrQn9GA0LjQvNC10YDR iyDQutCw0YDRgiDQv9C+0LrQsNC30LDRgtC10LvQtdC5INC00LvRjyDRgNCw0LfQu9C40YfQvdGL 0YUg0L/QvtC00YDQsNC30LTQtdC70LXQvdC40Lkg0Lgg0LTQvtC70LbQvdC+0YHRgtC10LkuDQog ICAgICotICAq0J/RgNC40LHQvtGA0L3Ri9C1INC/0LDQvdC10LvQuCDQtNC70Y8g0LzQvtC90LjR gtC+0YDQuNC90LPQsCDQv9C+0LrQsNC30LDRgtC10LvQtdC5IChkYXNoYm9hcmRzKS4NCio0LiDQ n9GA0LXQvNC40YDQvtCy0LDQvdC40LUg0L3QsCDQvtGB0L3QvtCy0LUgS1BJOioNCiAgICAgKi0g ICrQn9GA0LjQstGP0LfQutCwINC/0YDQtdC80LjQuCDQuiBLUEk6INGD0YDQvtCy0L3QuCDQuCDR gNC10LrQvtC80LXQvdC00YPQtdC80YvQuSDQv9GA0L7RhtC10L3RgiDQv9GA0LXQvNC40LgsDQrR hdCw0YDQsNC60YLQtdGAINC30LDQstC40YHQuNC80L7RgdGC0LgNCiAgICAg0L/RgNC10LzQuNC4 INC+0YIg0L/QvtC60LDQt9Cw0YLQtdC70Y8uDQogICAgICotICAq0JLRi9Cx0L7RgCDQv9C10YDQ uNC+0LTQuNGH0L3QvtGB0YLQuCDQv9GA0LXQvNC40YDQvtCy0LDQvdC40Y8uDQogICAgICotICAq 0J/RgNC40LzQtdGA0Ysg0L/RgNC10LzQuNCw0LvRjNC90YvRhSDQv9C70LDQvdC+0LIg0L3QsCDQ vtGB0L3QvtCy0LUgS1BJLg0KICAgICAqLSAgKtCg0LDRgdGH0LXRgiDQuCDQv9C70LDQvdC40YDQ vtCy0LDQvdC40LUg0YTQvtC90LTQsCDQv9GA0LXQvNC40YDQvtCy0LDQvdC40Y8uDQoqNS4g0KDQ tdC60L7QvNC10L3QtNCw0YbQuNC4INC/0L4g0LLQvdC10LTRgNC10L3QuNGOLioNCiAgICAgKi0g ICrQn9C+0LTQstC+0LTQvdGL0LUg0LrQsNC80L3QuCDQv9GA0Lgg0LLQvdC10LTRgNC10L3QuNC4 INGB0LjRgdGC0LXQvNGLINGD0L/RgNCw0LLQu9C10L3QuNGPINGN0YTRhNC10LrRgtC40LLQvdC+ 0YHRgtGM0Y4uDQogICAgICotICAq0JLQvdGD0YLRgNC10L3QvdC40LUg0LrQvtC80LzRg9C90LjQ utCw0YbQuNC4INGBINGB0L7RgtGA0YPQtNC90LjQutCw0LzQuC4NCiAgICAgKi0gICrQm9GD0YfR iNC40LUg0L/RgNCw0LrRgtC40LrQuCDQstC90LXQtNGA0LXQvdC40Y8uDQoNCiogICAgICAgICAg ICAgICAgICAgICAgICDQo9GH0LDRgdGC0LjQtToqIDIyIDgwMCDRgC4NCiAgICAgICAgICAgICAg ICAgICAgICAgINCSINGB0YLQvtC40LzQvtGB0YLRjCDQstGF0L7QtNC40YIg0LzQtdGC0L7QtNC4 0YfQtdGB0LrQuNC5INC80LDRgtC10YDQuNCw0LssINC+0LHQtdC00YssDQrQutC+0YTQtS3Qv9Cw 0YPQt9GLLCDRgdC10YDRgtC40YTQuNC60LDRgi4NCg== ------------8805BC868536F5E Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: base64 PGRpdiBkaXI9Imx0ciI+PHRhYmxlIGJvcmRlcj0iNiIgYmdjb2xvcj0iI0Y0RjlGOSIgY2VsbHNw YWNpbmc9IjEiIGNlbGxwYWRkaW5nPSIyIiBzdHlsZT0iZm9udC1mYW1pbHk6JiMzOTtUaW1lcyBO ZXcgUm9tYW4mIzM5Oztib3JkZXItd2lkdGg6NXB4Ij48dGJvZHk+PHRyPjx0ZCBiZ2NvbG9yPSIj OThDN0M3IiBzdHlsZT0iYm9yZGVyLXN0eWxlOm5vbmU7Ym9yZGVyLXdpZHRoOm1lZGl1bSI+wqA8 L3RkPjx0ZCBiZ2NvbG9yPSIjOThDN0M3IiBzdHlsZT0iYm9yZGVyLXN0eWxlOm5vbmU7Ym9yZGVy LXdpZHRoOm1lZGl1bSI+wqA8L3RkPjx0ZCBiZ2NvbG9yPSIjOThDN0M3IiBzdHlsZT0iYm9yZGVy LXN0eWxlOm5vbmU7Ym9yZGVyLXdpZHRoOm1lZGl1bSI+wqA8L3RkPjwvdHI+PHRyPjx0ZCBiZ2Nv bG9yPSIjOThDN0M3IiBzdHlsZT0iYm9yZGVyLXN0eWxlOm5vbmU7Ym9yZGVyLXdpZHRoOm1lZGl1 bSI+wqA8L3RkPjx0ZCBzdHlsZT0iYm9yZGVyLXN0eWxlOm5vbmU7Ym9yZGVyLXdpZHRoOm1lZGl1 bSI+PHRhYmxlIGJvcmRlcj0iMTEiIHdpZHRoPSIxMDAlIiBjZWxsc3BhY2luZz0iMyI+PHRib2R5 Pjx0cj48dGQ+PHAgYWxpZ249ImNlbnRlciI+PGZvbnQgZmFjZT0iVGFob21hIj48YnI+PGZvbnQg c2l6ZT0iNCIgY29sb3I9IiNDMTAwMDAiPjE8c3BhbiBsYW5nPSJlbi11cyI+NC0xNTwvc3Bhbj7C oNC40Y7QvdGPIHwg0LMuINCc0L7RgdC60LLQsDxicj48L2ZvbnQ+KNC/0YDQvtC80L7QutC+0LQ6 PHNwYW4gbGFuZz0iZW4tdXMiPsKgNDE3PC9zcGFuPik8L2ZvbnQ+PC9wPjxwIGFsaWduPSJjZW50 ZXIiPjxmb250IHNpemU9IjUiIGZhY2U9IlRhaG9tYSIgY29sb3I9IiMwMDAwRjQiPtCf0YDQvtGE 0LXRgdGB0LjQvtC90LDQuyDQv9C+IEtQSSwgTUJPLCBCU0Mg0Lgg0KHQuNGB0YLQtdC80LDQvMKg PGJyPtC+0YbQtdC90LrQuCDRgNC10LfRg9C70YzRgtCw0YLQuNCy0L3QvtGB0YLQuDwvZm9udD48 L3A+PHAgYWxpZ249ImNlbnRlciI+PHNwYW4gbGFuZz0iZW4tdXMiPjxiPjxmb250IGZhY2U9IlRh aG9tYSIgY29sb3I9IiMzMzMzMzMiPiogKiAqPC9mb250PjwvYj48L3NwYW4+PC9wPjxwIGFsaWdu PSJsZWZ0Ij48Zm9udCBmYWNlPSJUYWhvbWEiPjxiPtCS0YDQtdC80Y8g0L/RgNC+0LLQtdC00LXQ vdC40Y8g0LfQsNC90Y/RgtC40Y/CoDwvYj5jIDEwOjAwINC00L4gMTc6MzA8Yj48YnI+PGJyPtCc 0LXRgNC+0L/RgNC40Y/RgtC40LUg0YHQvtGB0YLQvtC40YLRgdGPINC/0L4g0LDQtNGA0LXRgdGD OsKgPC9iPtC8LiDQkdCw0YPQvNCw0L3RgdC60LDRjywg0YPQuy4g0JHQsNGD0LzQsNC90YHQutCw 0Y8sINC0LjYsINCRLtCmLsKgPHNwYW4gbGFuZz0iZW4tdXMiPiZxdW90Ozwvc3Bhbj7QktC40LrR gtC+0YDQuNGPINCf0LvQsNC30LA8c3BhbiBsYW5nPSJlbi11cyI+JnF1b3Q7PC9zcGFuPi48Yj48 YnI+PGJyPtCY0L3RhNC+0YDQvNCw0YbQuNGPINC4INGA0LXQs9C40YHRgtGA0LDRhtC40Y8g0L/Q viDRg9GB0LvQvtCy0LjRj9C8INC+0LHRg9GH0LXQvdC40Y86PGJyPsKgPGZvbnQgc2l6ZT0iNCI+ ODwvZm9udD48L2I+wqDQutC+0LQg0LPQvtGA0L7QtNCwINCc0L7RgdC60LLRizxiPsKgPGZvbnQg c2l6ZT0iNCI+KDQ5NSk8L2ZvbnQ+wqA8L2I+0YLQtdC70LXRhNC+0L06wqA8Yj48Zm9udCBzaXpl PSI0Ij43MjU8L2ZvbnQ+wqAtwqA8Zm9udCBzaXplPSI0Ij4wNDwvZm9udD7CoC3CoDxmb250IHNp emU9IjQiPjQ4PC9mb250PjwvYj7CoCjQvNC90L7Qs9C+0LrQsNC90LDQu9GM0L3Ri9C5KTwvZm9u dD48L3A+PHAgYWxpZ249ImNlbnRlciI+PGZvbnQgY29sb3I9IiM0MDc1NzUiIGZhY2U9IlRhaG9t YSI+PHNwYW4gbGFuZz0iZW4tdXMiPjxmb250IHNpemU9IjQiPn7CoDwvZm9udD48Yj48Zm9udCBz aXplPSIyIj4qwqA8L2ZvbnQ+PC9iPjxmb250IHNpemU9IjQiPn7CoDwvZm9udD48Yj48Zm9udCBz aXplPSIyIj4qwqA8L2ZvbnQ+PC9iPjxmb250IHNpemU9IjQiPn7CoDwvZm9udD48Yj48Zm9udCBz aXplPSIyIj4qwqA8L2ZvbnQ+PC9iPjxmb250IHNpemU9IjQiPn48L2ZvbnQ+PC9zcGFuPjwvZm9u dD48L3A+PC90ZD48L3RyPjwvdGJvZHk+PC90YWJsZT48cCBhbGlnbj0ibGVmdCI+PHU+PGZvbnQg ZmFjZT0iVGFob21hIiBzaXplPSI0IiBjb2xvcj0iIzQwNzU3NSI+0KHQvtC00LXRgNC20LDQvdC4 0LU6PC9mb250PjwvdT48L3A+PHAgYWxpZ249ImxlZnQiPjxmb250IGZhY2U9IlRhaG9tYSI+PGI+ PGZvbnQgY29sb3I9IiM4MDAwMDAiPtCm0LXQu9C4OjwvZm9udD48Zm9udCBjb2xvcj0iIzk4QzdD NyI+wqA8L2ZvbnQ+PC9iPjxicj7CoC0g0L/QvtC70YPRh9C40YLRjCDQs9C+0YLQvtCy0YvQtSDQ vdCw0YDQsNCx0L7RgtC60Lgg0Lgg0YDQtdGI0LXQvdC40Y8g0LjQtyDQv9GA0LDQutGC0LjQutC4 INGA0L7RgdGB0LjQudGB0LrQuNGFINC4INC30LDQv9Cw0LTQvdGL0YUg0LrQvtC80L/QsNC90LjQ uSzCoDxicj7CoC0g0YPQt9C90LDRgtGMINCw0LvQs9C+0YDQuNGC0Lwg0YDQsNC30YDQsNCx0L7R gtC60Lgg0YHQsdCw0LvQsNC90YHQuNGA0L7QstCw0L3QvdC+0Lkg0YHQuNGB0YLQtdC80Ysg0L/Q vtC60LDQt9Cw0YLQtdC70LXQuSAo0KHQodCfKSw8YnI+wqAtINC+0YLRgNCw0LHQvtGC0LDRgtGM INC90LDQstGL0Log0LjQvdGC0LXQs9GA0LDRhtC40Lgg0YHRgtGA0LDRgtC10LPQuNGH0LXRgdC6 0LjRhSDRhtC10LvQtdC5INC4INC/0L7QutCw0LfQsNGC0LXQu9C10Lkg0YDQtdC30YPQu9GM0YLQ sNGC0LjQstC90L7RgdGC0LgsPGJyPsKgLSDQv9C+0LvRg9GH0LjRgtGMINC/0YDQsNC60YLQuNGH 0LXRgdC60LjQtSDQuNC90YHRgtGA0YPQvNC10L3RgtGLINC00LXQutC+0LzQv9C+0LfQuNGG0LjQ uCDRhtC10LvQtdC5INC4INC/0L7QutCw0LfQsNGC0LXQu9C10LksPGJyPsKgLSDQvtGB0LLQvtC4 0YLRjCDQvNC10YXQsNC90LjQt9C8INC/0YDQuNCy0Y/Qt9C60Lgg0L/RgNC10LzQuNC4INC6INCy 0YvQv9C+0LvQvdC10L3QuNGOINGG0LXQu9C10LksPGJyPsKgLSDRg9C30L3QsNGC0Ywg0L/RgNCw 0LrRgtC40YfQtdGB0LrQuNC1INC/0L7QtNGF0L7QtNGLINC6INCy0L3QtdC00YDQtdC90LjRjiDR gdC40YHRgtC10LzRiyDRg9C/0YDQsNCy0LvQtdC90LjRjyDQv9C+INGA0LXQt9GD0LvRjNGC0LDR gtCw0Lwg0L3QsCDQvtGB0L3QvtCy0LXCoDxicj7CoMKgwqAg0KHQodCfLjwvZm9udD48L3A+PHAg YWxpZ249ImxlZnQiPjxmb250IGZhY2U9IlRhaG9tYSI+PGJyPjxiPjxzcGFuIGxhbmc9ImVuLXVz Ij4xLsKgPC9zcGFuPtCg0LDQt9GA0LDQsdC+0YLQutCwINGB0LHQsNC70LDQvdGB0LjRgNC+0LLQ sNC90L3QvtC5INGB0LjRgdGC0LXQvNGLINC/0L7QutCw0LfQsNGC0LXQu9C10LkgKEJTQyk6PC9i Pjxicj48c3BhbiBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iI0Mx MDAwMCI+PGI+LcKgwqA8L2I+PC9mb250PtCY0YHRgtC+0YDQuNGPINC4INC/0YDQuNC90YbQuNC/ 0Ysg0YDQsNCx0L7RgtGLIEJTQy48YnI+PHNwYW4gbGFuZz0iZW4tdXMiPsKgwqDCoMKgwqA8L3Nw YW4+PGZvbnQgY29sb3I9IiNDMTAwMDAiPjxiPi3CoMKgPC9iPjwvZm9udD7QkNC70LPQvtGA0LjR gtC8INGB0L7Qt9C00LDQvdC40Y8g0YHRgtGA0LDRgtC10LPQuNGH0LXRgdC60L7QuSDQutCw0YDR gtGLLjxicj48c3BhbiBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0i I0MxMDAwMCI+PGI+LcKgwqA8L2I+PC9mb250PtCh0YbQtdC90LDRgNC40Lkg0YHRgtGA0LDRgtC1 0LPQuNGH0LXRgdC60L7QuSDRgdC10YHRgdC40Lgg0L/QviDRgNCw0LfRgNCw0LHQvtGC0LrQtSBC U0MuPGJyPjxzcGFuIGxhbmc9ImVuLXVzIj7CoMKgwqDCoMKgPC9zcGFuPjxmb250IGNvbG9yPSIj QzEwMDAwIj48Yj4twqDCoDwvYj48L2ZvbnQ+0J/RgNC40LzQtdGA0YsgQlNDINC00LvRjyDRgNCw 0LfQu9C40YfQvdGL0YUg0L7RgtGA0LDRgdC70LXQuSDQuCDRhNGD0L3QutGG0LjQvtC90LDQu9GM 0L3Ri9GFINC/0L7QtNGA0LDQt9C00LXQu9C10L3QuNC5Ljxicj48Yj48c3BhbiBsYW5nPSJlbi11 cyI+Mi7CoDwvc3Bhbj7QlNC10LrQvtC80L/QvtC30LjRhtC40Y8g0YHRgtGA0LDRgtC10LPQuNGH 0LXRgdC60LjRhSDRhtC10LvQtdC5INC+0YDQs9Cw0L3QuNC30LDRhtC40Lg6PC9iPjxicj48c3Bh biBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iI0MxMDAwMCI+PGI+ LcKgwqA8L2I+PC9mb250PtCe0YHQvdC+0LLRiyDRhtC10LvQtdCy0L7Qs9C+INGD0L/RgNCw0LLQ u9C10L3QuNGPIChNQk8pLjxicj48c3BhbiBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48 Zm9udCBjb2xvcj0iI0MxMDAwMCI+PGI+LcKgwqA8L2I+PC9mb250PtCU0LXRgNC10LLQviDRhtC1 0LvQtdC5INC60L7QvNC/0LDQvdC40LguPGJyPjxzcGFuIGxhbmc9ImVuLXVzIj7CoMKgwqDCoMKg PC9zcGFuPjxmb250IGNvbG9yPSIjQzEwMDAwIj48Yj4twqDCoDwvYj48L2ZvbnQ+0J/RgNC40L3R htC40L/RiyDQtNC10LrQvtC80L/QvtC30LjRhtC40Lgg0YbQtdC70LXQuS48YnI+PHNwYW4gbGFu Zz0iZW4tdXMiPsKgwqDCoMKgwqA8L3NwYW4+PGZvbnQgY29sb3I9IiNDMTAwMDAiPjxiPi3CoMKg PC9iPjwvZm9udD7Ql9Cw0LrRgNC10L/Qu9C10L3QuNC1INGG0LXQu9C10Lkg0LfQsCDRhNGD0L3Q utGG0LjRj9C80Lgg0Lgg0LjRgdC/0L7Qu9C90LjRgtC10LvRj9C80LgsINC80LDRgtGA0LjRhtCw INGG0LXQu9C10LkuPGJyPjxzcGFuIGxhbmc9ImVuLXVzIj7CoMKgwqDCoMKgPC9zcGFuPjxmb250 IGNvbG9yPSIjQzEwMDAwIj48Yj4twqDCoDwvYj48L2ZvbnQ+0KDQsNC30YDQsNCx0L7RgtC60LAg 0LzQtdGA0L7Qv9GA0LjRj9GC0LjQuSDQv9C+INC00L7RgdGC0LjQttC10L3QuNGOINGG0LXQu9C1 0Lkg0Lgg0L/Qu9Cw0L3QsCDQtNC10LnRgdGC0LLQuNC5Ljxicj48Yj48c3BhbiBsYW5nPSJlbi11 cyI+My7CoDwvc3Bhbj7Qn9C+0YHRgtCw0L3QvtCy0LrQsCDQutC70Y7Rh9C10LLRi9GFINC/0L7Q utCw0LfQsNGC0LXQu9C10Lkg0Y3RhNGE0LXQutGC0LjQstC90L7RgdGC0LggKEtQSSk6PC9iPjxi cj48c3BhbiBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iI0MxMDAw MCI+PGI+LcKgwqA8L2I+PC9mb250PtCi0LXRhdC90L7Qu9C+0LPQuNGPINCy0YvQsdC+0YDQsCDQ v9C+0LrQsNC30LDRgtC10LvQtdC5INC4INGD0YHRgtCw0L3QvtCy0LvQtdC90LjQtSDQstC10YHQ vtCyIEtQSS48YnI+PHNwYW4gbGFuZz0iZW4tdXMiPsKgwqDCoMKgwqA8L3NwYW4+PGZvbnQgY29s b3I9IiNDMTAwMDAiPjxiPi3CoMKgPC9iPjwvZm9udD7Qo9GA0L7QstC90Lgg0LTQvtGB0YLQuNC2 0LXQvdC40Y8gS1BJLjxicj48c3BhbiBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48Zm9u dCBjb2xvcj0iI0MxMDAwMCI+PGI+LcKgwqA8L2I+PC9mb250PtCg0LDQt9GA0LDQsdC+0YLQutCw INC60LDRgNGC0YsgS1BJLjxicj48c3BhbiBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48 Zm9udCBjb2xvcj0iI0MxMDAwMCI+PGI+LcKgwqA8L2I+PC9mb250PtCf0YDQuNC80LXRgNGLINC6 0LDRgNGCINC/0L7QutCw0LfQsNGC0LXQu9C10Lkg0LTQu9GPINGA0LDQt9C70LjRh9C90YvRhSDQ v9C+0LTRgNCw0LfQtNC10LvQtdC90LjQuSDQuCDQtNC+0LvQttC90L7RgdGC0LXQuS48YnI+PHNw YW4gbGFuZz0iZW4tdXMiPsKgwqDCoMKgwqA8L3NwYW4+PGZvbnQgY29sb3I9IiNDMTAwMDAiPjxi Pi3CoMKgPC9iPjwvZm9udD7Qn9GA0LjQsdC+0YDQvdGL0LUg0L/QsNC90LXQu9C4INC00LvRjyDQ vNC+0L3QuNGC0L7RgNC40L3Qs9CwINC/0L7QutCw0LfQsNGC0LXQu9C10LkgKGRhc2hib2FyZHMp Ljxicj48Yj48c3BhbiBsYW5nPSJlbi11cyI+NC7CoDwvc3Bhbj7Qn9GA0LXQvNC40YDQvtCy0LDQ vdC40LUg0L3QsCDQvtGB0L3QvtCy0LUgS1BJOjwvYj48YnI+PHNwYW4gbGFuZz0iZW4tdXMiPsKg wqDCoMKgwqA8L3NwYW4+PGZvbnQgY29sb3I9IiNDMTAwMDAiPjxiPi3CoMKgPC9iPjwvZm9udD7Q n9GA0LjQstGP0LfQutCwINC/0YDQtdC80LjQuCDQuiBLUEk6INGD0YDQvtCy0L3QuCDQuCDRgNC1 0LrQvtC80LXQvdC00YPQtdC80YvQuSDQv9GA0L7RhtC10L3RgiDQv9GA0LXQvNC40LgsINGF0LDR gNCw0LrRgtC10YAg0LfQsNCy0LjRgdC40LzQvtGB0YLQuMKgPGJyPjxzcGFuIGxhbmc9ImVuLXVz Ij7CoMKgwqDCoMKgPC9zcGFuPtC/0YDQtdC80LjQuCDQvtGCINC/0L7QutCw0LfQsNGC0LXQu9GP Ljxicj48c3BhbiBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iI0Mx MDAwMCI+PGI+LcKgwqA8L2I+PC9mb250PtCS0YvQsdC+0YAg0L/QtdGA0LjQvtC00LjRh9C90L7R gdGC0Lgg0L/RgNC10LzQuNGA0L7QstCw0L3QuNGPLjxicj48c3BhbiBsYW5nPSJlbi11cyI+wqDC oMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iI0MxMDAwMCI+PGI+LcKgwqA8L2I+PC9mb250PtCf 0YDQuNC80LXRgNGLINC/0YDQtdC80LjQsNC70YzQvdGL0YUg0L/Qu9Cw0L3QvtCyINC90LAg0L7R gdC90L7QstC1IEtQSS48YnI+PHNwYW4gbGFuZz0iZW4tdXMiPsKgwqDCoMKgwqA8L3NwYW4+PGZv bnQgY29sb3I9IiNDMTAwMDAiPjxiPi3CoMKgPC9iPjwvZm9udD7QoNCw0YHRh9C10YIg0Lgg0L/Q u9Cw0L3QuNGA0L7QstCw0L3QuNC1INGE0L7QvdC00LAg0L/RgNC10LzQuNGA0L7QstCw0L3QuNGP Ljxicj48Yj48c3BhbiBsYW5nPSJlbi11cyI+NS7CoDwvc3Bhbj7QoNC10LrQvtC80LXQvdC00LDR htC40Lgg0L/QviDQstC90LXQtNGA0LXQvdC40Y4uPC9iPjxicj48c3BhbiBsYW5nPSJlbi11cyI+ wqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iI0MxMDAwMCI+PGI+LcKgwqA8L2I+PC9mb250 PtCf0L7QtNCy0L7QtNC90YvQtSDQutCw0LzQvdC4INC/0YDQuCDQstC90LXQtNGA0LXQvdC40Lgg 0YHQuNGB0YLQtdC80Ysg0YPQv9GA0LDQstC70LXQvdC40Y8g0Y3RhNGE0LXQutGC0LjQstC90L7R gdGC0YzRji48YnI+PHNwYW4gbGFuZz0iZW4tdXMiPsKgwqDCoMKgwqA8L3NwYW4+PGZvbnQgY29s b3I9IiNDMTAwMDAiPjxiPi3CoMKgPC9iPjwvZm9udD7QktC90YPRgtGA0LXQvdC90LjQtSDQutC+ 0LzQvNGD0L3QuNC60LDRhtC40Lgg0YEg0YHQvtGC0YDRg9C00L3QuNC60LDQvNC4Ljxicj48c3Bh biBsYW5nPSJlbi11cyI+wqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iI0MxMDAwMCI+PGI+ LcKgwqA8L2I+PC9mb250PtCb0YPRh9GI0LjQtSDQv9GA0LDQutGC0LjQutC4INCy0L3QtdC00YDQ tdC90LjRjy7CoDxicj48YnI+PGI+PHNwYW4gbGFuZz0iZW4tdXMiPsKgwqDCoMKgwqDCoMKgwqDC oMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoDwvc3Bhbj48Zm9udCBjb2xvcj0iIzQwNzU3 NSI+0KPRh9Cw0YHRgtC40LU6PC9mb250PjwvYj7CoDIyIDgwMCDRgC48YnI+PGI+PHNwYW4gbGFu Zz0iZW4tdXMiPsKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDCoMKgwqDC oDwvc3Bhbj48L2I+0JIg0YHRgtC+0LjQvNC+0YHRgtGMINCy0YXQvtC00LjRgiDQvNC10YLQvtC0 0LjRh9C10YHQutC40Lkg0LzQsNGC0LXRgNC40LDQuywg0L7QsdC10LTRiywg0LrQvtGE0LUt0L/Q sNGD0LfRiywg0YHQtdGA0YLQuNGE0LjQutCw0YIuPC9mb250PjwvcD48L3RkPjx0ZCBiZ2NvbG9y PSIjOThDN0M3IiBzdHlsZT0iYm9yZGVyLXN0eWxlOm5vbmU7Ym9yZGVyLXdpZHRoOm1lZGl1bSI+ wqA8L3RkPjwvdHI+PHRyPjx0ZCBiZ2NvbG9yPSIjOThDN0M3IiBzdHlsZT0iYm9yZGVyLXN0eWxl Om5vbmU7Ym9yZGVyLXdpZHRoOm1lZGl1bSI+wqA8L3RkPjx0ZCBiZ2NvbG9yPSIjOThDN0M3IiBz dHlsZT0iYm9yZGVyLXN0eWxlOm5vbmU7Ym9yZGVyLXdpZHRoOm1lZGl1bSI+wqA8L3RkPjx0ZCBi Z2NvbG9yPSIjOThDN0M3IiBzdHlsZT0iYm9yZGVyLXN0eWxlOm5vbmU7Ym9yZGVyLXdpZHRoOm1l ZGl1bSI+wqA8L3RkPjwvdHI+PC90Ym9keT48L3RhYmxlPjwvZGl2Pg0K ------------8805BC868536F5E-- From v-nikishov@list.ru Wed Jun 8 20:37:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F0BFE7CA4 for ; Wed, 8 Jun 2016 20:37:47 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 60322AC002 for ; Wed, 8 Jun 2016 18:37:44 -0700 (PDT) X-ASG-Debug-ID: 1465436235-04cbb03568c320d0001-NocioJ Received: from mxs.mail.ru (187-26-187-213.wifi4all.it [213.187.26.187]) by cuda.sgi.com with ESMTP id hokUGKAkYPO8PNag for ; Wed, 08 Jun 2016 18:37:22 -0700 (PDT) X-Barracuda-Envelope-From: v-nikishov@list.ru X-Barracuda-Effective-Source-IP: 187-26-187-213.wifi4all.it[213.187.26.187] X-Barracuda-Apparent-Source-IP: 213.187.26.187 Message-ID: <8DB91415B747C2971FF77E89EF152172@RLFECHPQMAST> From: "=?utf-8?B?0JDQu9Cz0L7RgNC40YLQvNGLINC+0L/RgtC40LzQuNC30LDRhtC40Lgg0L3QsNC70L7Qs9C+0LI=?=" To: Subject: =?utf-8?B?0JDQu9Cz0L7RgNC40YLQvNGLINC90LDQu9C+0LPQvtCy0L7QuSDQvtC/0YLQuNC80LjQt9Cw0YbQuNC4LCDQsNC90LDQu9C40Lcg0Y3RhNGE0LXQutGC0LjQstC90L7RgdGC0Lgg0Lgg0YDQuNGB0LrQvtCyLg==?= Date: Thu, 9 Jun 2016 04:37:25 +0300 X-ASG-Orig-Subj: =?utf-8?B?0JDQu9Cz0L7RgNC40YLQvNGLINC90LDQu9C+0LPQvtCy0L7QuSDQvtC/0YLQuNC80LjQt9Cw0YbQuNC4LCDQsNC90LDQu9C40Lcg0Y3RhNGE0LXQutGC0LjQstC90L7RgdGC0Lgg0Lgg0YDQuNGB0LrQvtCyLg==?= MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_000B_01D1C208.9F02E8F0" X-Priority: 3 X-MSMail-Priority: Normal Importance: Normal X-Mailer: Microsoft Windows Live Mail 15.4.3538.513 X-MimeOLE: Produced By Microsoft MimeOLE V15.4.3538.513 X-Barracuda-Connect: 187-26-187-213.wifi4all.it[213.187.26.187] X-Barracuda-Start-Time: 1465436235 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15877 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30289 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message MIME. ------=_NextPart_000_000B_01D1C208.9F02E8F0 Content-Type: text/plain; charset="koi8-r" Content-Transfer-Encoding: quoted-printable 22 =C9=C0=CE=D1 | =C7.=ED=CF=D3=CB=D7=C1 =F0=D2=CF=CD=CF=CB=CF=C4: 428 =20 =EE=C1=CC=CF=C7=CF=D7=CF=C5 = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =D7 2016-2017 =C7=CF=C4=D5 =20 =20 =FA=C1=CE=D1=D4=C9=D1 =D0=D2=CF=D7=CF=C4=D1=D4=D3=D1 = =D3 10:00 =C4=CF 17:30. =E1=C4=D2=C5=D3 =CD=C5=D2=CF=D0=D2=C9=D1=D4=C9=D1: = =CD. =E2=C1=D5=CD=C1=CE=D3=CB=C1=D1, =D5=CC. = =E2=C1=D5=CD=C1=CE=D3=CB=C1=D1, =C4.6, =D3=D4=D2.2, =E2.=E3. = "=F7=C9=CB=D4=CF=D2=C9=D1 =F0=CC=C1=DA=C1". =F7=D3=D1 =D0=CF=C4=D2=CF=C2=CE=C1=D1 = =C9=CE=C6=CF=D2=CD=C1=C3=C9=D1 =C9 =D2=C5=C7=C9=D3=D4=D2=C1=C3=C9=D1 = =D0=CF =CE=CF=CD=C5=D2=D5 =D4=C5=CC=C5=C6=CF=CE=C1: 8 =CB=CF=C4 =C7=CF=D2=CF=C4=C1 =ED=CF=D3=CB=D7=D9 = (495) =D4=C5=CC.: 725 - 04 - 48. =20 =20 =F3=CF=C4=C5=D2=D6=C1=CE=C9=C5 =D0=D2=CF=C7=D2=C1=CD=CD=D9: =20 1. =E9=DA=CD=C5=CE=C5=CE=C9=D1 =D7 = =DA=C1=CB=CF=CE=CF=C4=C1=D4=C5=CC=D8=D3=D4=D7=C5, = =D0=CF=D7=CC=C9=D1=D7=DB=C9=C5 =CE=C1 =CE=C1=CC=CF=C7=CF=D7=CF=C5 = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5. =20 =E9=DA=CD=C5=CE=C5=CE=C9=D1 =D7 =D0=CF=D2=D1=C4=CB=C5 = =CB=C1=CD=C5=D2=C1=CC=D8=CE=CF=CA =D0=D2=CF=D7=C5=D2=CB=C9 = =C4=C5=CB=CC=C1=D2=C1=C3=C9=CA =D0=CF =EE=E4=F3 (=D3=C9=D3=D4=C5=CD=C1 = Bigdata; =D0=C5=D2=D7=D9=C5=20 =D2=C5=DA=D5=CC=D8=D4=C1=D4=D9 = =CB=C1=CD=C5=D2=C1=CC=D8=CE=D9=C8 =D0=D2=CF=D7=C5=D2=CF=CB = =D3=CF=C7=CC=C1=D3=CE=CF =CE=CF=D7=CF=CD=D5 =D0=CF=D2=D1=C4=CB=D5, = =DE=D4=CF =CB=C1=D2=C4=C9=CE=C1=CC=D8=CE=CF =CD=C5=CE=D1=C5=D4=D3=D1 =D7 = =CE=C1=CC=CF=C7=CF=D7=CF=CD = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C9 =EE=E4=F3). =EB=C1=CB=C9=C5 =D3=D4=C1=D2=D9=C5 = =D3=D0=CF=D3=CF=C2=D9 =CD=C9=CE=C9=CD=C9=DA=C1=C3=C9=C9 =EE=E4=F3 = =D3=D4=C1=CC=C9 =CE=C5=D7=CF=DA=CD=CF=D6=CE=D9 =C9 =DE=D4=CF = =CE=CF=D7=CF=C7=CF =CD=CF=D6=CE=CF =D0=D2=C9=CD=C5=CE=C9=D4=D8. =FA=C1=CB=CF=CE =CF = =C4=C5=CF=C6=DB=CF=D2=C9=DA=C1=C3=C9=C9, = =CF=D4=D7=C5=D4=D3=D4=D7=C5=CE=CE=CF=D3=D4=D8 =DA=C1 = =CE=C5=D3=CF=C2=CC=C0=C4=C5=CE=C9=C5 = =D0=C5=D2=C5=DE=C5=D2=CB=C9=D7=C1=C5=D4 =CC=C9 =CF=CE = =D7=CF=DA=CD=CF=D6=CE=CF=D3=D4=D8=20 =C9=D3=D0=CF=CC=D8=DA=CF=D7=C1=CE=C9=D1 = =C9=CE=CF=D3=D4=D2=C1=CE=CE=D9=C8 =C0=D2=C9=D3=C4=C9=CB=C3=C9=CA =D7 = =CE=C1=CC=CF=C7=CF=D7=CF=CD =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C9; = =DA=C1=CB=CF=CE =CF =CE=C1=CC=CF=C7=CF=D7=CF=CA=20 =C1=CD=CE=C9=D3=D4=C9=C9 =CB=C1=D0=C9=D4=C1=CC=C1. =EE=CE=CF=D7=D9=CA =D0=CF=D2=D1=C4=CF=CB = =D0=D2=C9=D7=CC=C5=DE=C5=CE=C9=D1 =CB =D5=C7=CF=CC=CF=D7=CE=CF=CA = =CF=D4=D7=C5=D4=D3=D4=D7=C5=CE=CE=CF=D3=D4=C9 =DA=C1 = =CE=C1=CC=CF=C7=CF=D7=D9=C5 =D0=D2=C5=D3=D4=D5=D0=CC=C5=CE=C9=D1:=20 =D0=CF=DE=C5=CD=D5 =D4=C5=D0=C5=D2=D8 =CE=C5 = =D2=C5=DA=D5=CC=D8=D4=C1=D4=C9=D7=CE=CF =C9=D3=CB=C1=D4=D8 = =CB=CF=CD=D0=D2=CF=CD=C9=D3=D3 =CE=C1 =D5=D2=CF=D7=CE=C5 = =CE=C1=CC=CF=C7=CF=D7=CF=CA =C9=CE=D3=D0=C5=CB=C3=C9=C9). 2. =EF=C2=DD=C9=C5 =D0=D2=C1=D7=C9=CC=C1 = =D0=D2=C9=CD=C5=CE=C5=CE=C9=D1 =D3=D0=CF=D3=CF=C2=CF=D7 = =CF=D0=D4=C9=CD=C9=DA=C1=C3=C9=C9 = =CE=C1=CC=CF=C7=CF=CF=C2=CC=CF=D6=C5=CE=C9=D1: =CB=C1=CB = =C9=DA=C2=C5=D6=C1=D4=D8=20 =CF=DB=C9=C2=CF=CB.=20 =F0=CF=D3=D4=D2=CF=C5=CE=C9=C5 = =C8=CF=CC=C4=C9=CE=C7=CF=D7=CF=CA =D3=D4=D2=D5=CB=D4=D5=D2=D9 = =C2=C9=DA=CE=C5=D3=C1 =CB=C1=CB =CF=D3=CE=CF=D7=C1 = =CE=C1=CC=CF=C7=CF=D7=CF=C7=CF =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=D1 = =D3=D2=C5=C4=CE=C5=C7=CF =C9=20 =CB=D2=D5=D0=CE=CF=C7=CF =C2=C9=DA=CE=C5=D3=C1. =EF=D3=CF=C2=C5=CE=CE=CF=D3=D4=C9 = =CE=C1=CC=CF=C7=CF=D7=CF=C7=CF =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=D1 = =CD=C1=CC=CF=C7=CF =C2=C9=DA=CE=C5=D3=C1. 3. =ED=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 = =CE=C1=CC=CF=C7=C1 =CE=C1 =D0=D2=C9=C2=D9=CC=D8 =D7 =C7=D2=D5=D0=D0=C5 = =CB=CF=CD=D0=C1=CE=C9=CA. =20 =ED=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 =CE=C1=CC=CF=C7=C1 = =D3 =D0=CF=CD=CF=DD=D8=C0 =D2=CF=D3=D3=C9=CA=D3=CB=C9=C8 = =D3=D5=C2=DF=C5=CB=D4=CF=D7 =CC=D8=C7=CF=D4=CE=CF=C7=CF = =CE=C1=CC=CF=C7=CF=CF=C2=CC=CF=D6=C5=CE=C9=D1=20 (=C4=C1=D7=C1=CC=D8=DE=C5=D3=CB=C1=D1 =D3=C8=C5=CD=C1, = =D2=C1=DA=C4=C5=CC=C5=CE=C9=C5 =D0=CF=D4=CF=CB=CF=D7, = =C9=D3=D0=CF=CC=D8=DA=CF=D7=C1=CE=C9=C5 =D3=D5=C2=DF=C5=CB=D4=CF=D7 = =CC=D8=C7=CF=D4=CE=CF=C7=CF=20 =CE=C1=CC=CF=C7=CF=CF=C2=CC=CF=D6=C5=CE=C9=D1; = =C4=C5=D1=D4=C5=CC=D8=CE=CF=D3=D4=D8 =D7 =D0=D2=CF=D3=D4=CF=CD = =D4=CF=D7=C1=D2=C9=DD=C5=D3=D4=D7=C5; = =C9=D3=D0=CF=CC=D8=DA=CF=D7=C1=CE=C9=C5 = =D4=D2=C1=CE=D3=C6=C5=D2=D4=CE=CF=C7=CF=20 =C3=C5=CE=CF=CF=C2=D2=C1=DA=CF=D7=C1=CE=C9=D1; = =CC=C9=DA=C9=CE=C7; =D2=C5=CF=D2=C7=C1=CE=C9=DA=C1=C3=C9=D1; = =D3=C8=C5=CD=D9 =D3 =C4=CF=CC=D1=CD=C9 =C9 =D0=D2.) =20 =ED=C5=D6=C4=D5=CE=C1=D2=CF=C4=CE=CF=C5 = =CE=C1=CC=CF=C7=CF=D7=CF=C5 =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 = =D3=C4=C5=CC=CF=CB. 4. =EE=C1=CC=CF=C7=CF=D7=CF=C5 = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =EE=E4=F3 = (=D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =CF=C2=CF=D2=CF=D4=CE=CF=C7=CF = =EE=E4=F3; =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =EE=E4=F3 =D0=D2=C9=20 =CB=D2=D5=D0=CE=D9=C8 =D3=C4=C5=CC=CB=C1=C8; = =CD=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 =CE=C1=CC=CF=C7=C1 =D0=D2=C9 = =CF=C2=D9=DE=CE=CF=CA =C4=C5=D1=D4=C5=CC=D8=CE=CF=D3=D4=C9 = =D0=D2=C5=C4=D0=D2=C9=D1=D4=C9=D1). =20 5. =EE=C1=CC=CF=C7=CF=D7=CF=C5 = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =DA=C1=D2=D0=CC=C1=D4=CE=D9=C8 = =CE=C1=CC=CF=C7=CF=D7 =C9 =D3=C2=CF=D2=CF=D7. =20 =E4=C9=D7=C9=C4=C5=CE=C4=CE=C1=D1 =D3=C8=C5=CD=C1; = =CB=CF=CF=D0=C5=D2=C1=D4=C9=D7=D9. =F0=CF=CE=C9=D6=C5=CE=CE=D9=C5 =D3=D4=C1=D7=CB=C9 = =D3=D4=D2=C1=C8=CF=D7=D9=C8 =D7=DA=CE=CF=D3=CF=D7. =EB=CD=D0=C5=CE=D3=C1=C3=C9=CF=CE=CE=D9=C5 = =D7=D9=D0=CC=C1=D4=D9; =D7=D9=D0=CC=C1=D4=D9 =D0=CF = =D5=DE=C5=CE=C9=DE=C5=D3=CB=C9=CD =C4=CF=C7=CF=D7=CF=D2=C1=CD. =F7=D9=D0=CC=C1=D4=D9 =DE=CC=C5=CE=C1=CD = =D3=CF=D7=C5=D4=C1 =C4=C9=D2=C5=CB=D4=CF=D2=CF=D7; = =D0=C5=D2=C5=D2=C1=D3=D0=D2=C5=C4=C5=CC=C5=CE=C9=C5 =C6=CF=CE=C4=C1 = =CF=D0=CC=C1=D4=D9 =D4=D2=D5=C4=C1 =C9 =C4=D2. =D3=D0=CF=D3=CF=C2=D9=20 =CD=C9=CE=C9=CD=C9=DA=C1=C3=C9=C9 = =DA=C1=D2=D0=CC=C1=D4=CE=D9=C8 =CE=C1=CC=CF=C7=CF=D7 = (=D3=C2=CF=D2=CF=D7): =CE=C0=C1=CE=D3=D9 =D0=D2=C9=CD=C5=CE=C5=CE=C9=D1. 6. =ED=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 = =CE=C1=CC=CF=C7=C1 =CE=C1 =C9=CD=D5=DD=C5=D3=D4=D7=CF. =20 7. =F2=C5=C9=CE=D7=C5=D3=D4=C9=D2=CF=D7=C1=CE=C9=C5 = =C6=C9=CE=C1=CE=D3=CF=D7 =D0=D2=C9 =D0=D2=C9=CD=C5=CE=C5=CE=C9=C9 = =D3=D0=CF=D3=CF=C2=CF=D7 =DC=CB=CF=CE=CF=CD=C9=C9 =CE=C1=CC=CF=C7=C1 = =CE=C1 =D0=D2=C9=C2=D9=CC=D8. =20 8. =EF=C3=C5=CE=CB=C1 =C9 = =CD=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 =D2=C9=D3=CB=CF=D7 =D0=D2=C9 = =CE=C1=CC=CF=C7=CF=D7=CF=CD =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C9 = (=D3=D7=D1=DA=C1=CE=CE=D9=C8 =D3 = =CE=C5=CF=C2=CF=D3=CE=CF=D7=C1=CE=CE=CF=CA=20 =CE=C1=CC=CF=C7=CF=D7=CF=CA =D7=D9=C7=CF=C4=CF=CA; = =CE=C1=CC=CF=C7=CF=D7=D9=C5 =D0=CF=D3=CC=C5=C4=D3=D4=D7=C9=D1 = =CE=C5=C4=C5=CA=D3=D4=D7=C9=D4=C5=CC=D8=CE=CF=D3=D4=C9 = =D3=C4=C5=CC=CF=CB; =D2=C9=D3=CB=C9, =D3=D7=D1=DA=C1=CE=CE=D9=C5 =D3=20 =E6=C9=CE=CD=CF=CE=C9=D4=CF=D2=C9=CE=C7=CF=CD). =20 =F3=D4=CF=C9=CD=CF=D3=D4=D8 = =D5=DE=C1=D3=D4=C9=D1: 11 800 =D2.=20 =F7 =D3=D4=CF=C9=CD=CF=D3=D4=D8 = =D7=C8=CF=C4=C9=D4 =CD=C5=D4=CF=C4=C9=DE=C5=D3=CB=C9=CA = =CD=C1=D4=C5=D2=C9=C1=CC, =CF=C2=C5=C4=D9, =CB=CF=C6=C5-=D0=C1=D5=DA=D9, = =D3=C5=D2=D4=C9=C6=C9=CB=C1=D4.=20 =20 =20 =20 =20 =20 ------=_NextPart_000_000B_01D1C208.9F02E8F0 Content-Type: text/html; charset="koi8-r" Content-Transfer-Encoding: quoted-printable


=EE=C1=CC=CF=C7=CF=D7=CF=C5 =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 = =D7=20 2016-2017 = =C7=CF=C4=D5
 


22 =C9=C0=CE=D1 | = =C7.=ED=CF=D3=CB=D7=C1
=F0=D2=CF=CD=CF=CB=CF=C4: 428
 

=FA=C1=CE=D1=D4=C9=D1=20 =D0=D2=CF=D7=CF=C4=D1=D4=D3=D1 =D3=20 10:00 =C4=CF 17:30.

=E1=C4=D2=C5=D3 = =CD=C5=D2=CF=D0=D2=C9=D1=D4=C9=D1: 
=CD. = =E2=C1=D5=CD=C1=CE=D3=CB=C1=D1, =D5=CC. =E2=C1=D5=CD=C1=CE=D3=CB=C1=D1, = =C4.6,=20 =D3=D4=D2.2, =E2.=E3. "=F7=C9=CB=D4=CF=D2=C9=D1 = =F0=CC=C1=DA=C1".

=F7=D3=D1 = =D0=CF=C4=D2=CF=C2=CE=C1=D1 =C9=CE=C6=CF=D2=CD=C1=C3=C9=D1 =C9 = =D2=C5=C7=C9=D3=D4=D2=C1=C3=C9=D1=20 =D0=CF =CE=CF=CD=C5=D2=D5 = =D4=C5=CC=C5=C6=CF=CE=C1:
8 =CB=CF=C4 = =C7=CF=D2=CF=C4=C1 =ED=CF=D3=CB=D7=D9  (495)  =D4=C5=CC.: 725 - 04 - 48.

 


=F3=CF=C4=C5=D2=D6=C1=CE=C9=C5 = =D0=D2=CF=C7=D2=C1=CD=CD=D9:

 
1.=20 =E9=DA=CD=C5=CE=C5=CE=C9=D1 =D7 = =DA=C1=CB=CF=CE=CF=C4=C1=D4=C5=CC=D8=D3=D4=D7=C5, = =D0=CF=D7=CC=C9=D1=D7=DB=C9=C5 =CE=C1 =CE=C1=CC=CF=C7=CF=D7=CF=C5=20 = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5.
 

=E9=DA=CD=C5=CE=C5=CE=C9=D1 = =D7 =D0=CF=D2=D1=C4=CB=C5 =CB=C1=CD=C5=D2=C1=CC=D8=CE=CF=CA=20 =D0=D2=CF=D7=C5=D2=CB=C9 = =C4=C5=CB=CC=C1=D2=C1=C3=C9=CA =D0=CF =EE=E4=F3 (=D3=C9=D3=D4=C5=CD=C1 = Bigdata; =D0=C5=D2=D7=D9=C5 
=D2=C5=DA=D5=CC=D8=D4=C1=D4= =D9=20 =CB=C1=CD=C5=D2=C1=CC=D8=CE=D9=C8 = =D0=D2=CF=D7=C5=D2=CF=CB =D3=CF=C7=CC=C1=D3=CE=CF =CE=CF=D7=CF=CD=D5 = =D0=CF=D2=D1=C4=CB=D5, =DE=D4=CF =CB=C1=D2=C4=C9=CE=C1=CC=D8=CE=CF=20 =CD=C5=CE=D1=C5=D4=D3=D1 =D7 
=CE=C1=CC=CF=C7=CF=D7=CF=CD= =20 =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C9 = =EE=E4=F3).

=EB=C1=CB=C9=C5 =D3=D4=C1=D2=D9=C5 = =D3=D0=CF=D3=CF=C2=D9 =CD=C9=CE=C9=CD=C9=DA=C1=C3=C9=C9 =EE=E4=F3=20 =D3=D4=C1=CC=C9 =CE=C5=D7=CF=DA=CD=CF=D6=CE=D9 =C9 = =DE=D4=CF =CE=CF=D7=CF=C7=CF =CD=CF=D6=CE=CF = =D0=D2=C9=CD=C5=CE=C9=D4=D8.

=FA=C1=CB=CF=CE =CF=20 =C4=C5=CF=C6=DB=CF=D2=C9=DA=C1=C3=C9=C9, = =CF=D4=D7=C5=D4=D3=D4=D7=C5=CE=CE=CF=D3=D4=D8 =DA=C1 = =CE=C5=D3=CF=C2=CC=C0=C4=C5=CE=C9=C5 = =D0=C5=D2=C5=DE=C5=D2=CB=C9=D7=C1=C5=D4=20 =CC=C9 =CF=CE =D7=CF=DA=CD=CF=D6=CE=CF=D3=D4=D8 
=C9=D3=D0=CF=CC=D8=DA=CF=D7= =C1=CE=C9=D1=20 =C9=CE=CF=D3=D4=D2=C1=CE=CE=D9=C8 = =C0=D2=C9=D3=C4=C9=CB=C3=C9=CA =D7 =CE=C1=CC=CF=C7=CF=D7=CF=CD = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C9; =DA=C1=CB=CF=CE =CF=20 =CE=C1=CC=CF=C7=CF=D7=CF=CA 
=C1=CD=CE=C9=D3=D4=C9=C9=20 =CB=C1=D0=C9=D4=C1=CC=C1.

=EE=CE=CF=D7=D9=CA = =D0=CF=D2=D1=C4=CF=CB =D0=D2=C9=D7=CC=C5=DE=C5=CE=C9=D1 =CB = =D5=C7=CF=CC=CF=D7=CE=CF=CA=20 =CF=D4=D7=C5=D4=D3=D4=D7=C5=CE=CE=CF=D3=D4=C9 =DA=C1 = =CE=C1=CC=CF=C7=CF=D7=D9=C5 =D0=D2=C5=D3=D4=D5=D0=CC=C5=CE=C9=D1: 
=D0=CF=DE=C5=CD=D5 = =D4=C5=D0=C5=D2=D8 =CE=C5=20 =D2=C5=DA=D5=CC=D8=D4=C1=D4=C9=D7=CE=CF = =C9=D3=CB=C1=D4=D8 =CB=CF=CD=D0=D2=CF=CD=C9=D3=D3 =CE=C1 = =D5=D2=CF=D7=CE=C5 =CE=C1=CC=CF=C7=CF=D7=CF=CA=20 =C9=CE=D3=D0=C5=CB=C3=C9=C9).

2.=20 =EF=C2=DD=C9=C5 =D0=D2=C1=D7=C9=CC=C1 = =D0=D2=C9=CD=C5=CE=C5=CE=C9=D1 =D3=D0=CF=D3=CF=C2=CF=D7 = =CF=D0=D4=C9=CD=C9=DA=C1=C3=C9=C9 = =CE=C1=CC=CF=C7=CF=CF=C2=CC=CF=D6=C5=CE=C9=D1:=20 =CB=C1=CB =C9=DA=C2=C5=D6=C1=D4=D8 
   =20 =CF=DB=C9=C2=CF=CB. 

=F0=CF=D3=D4=D2=CF= =C5=CE=C9=C5=20 =C8=CF=CC=C4=C9=CE=C7=CF=D7=CF=CA = =D3=D4=D2=D5=CB=D4=D5=D2=D9 =C2=C9=DA=CE=C5=D3=C1 =CB=C1=CB = =CF=D3=CE=CF=D7=C1 =CE=C1=CC=CF=C7=CF=D7=CF=C7=CF=20 =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=D1 = =D3=D2=C5=C4=CE=C5=C7=CF =C9 
=CB=D2=D5=D0=CE=CF=C7=CF=20 = =C2=C9=DA=CE=C5=D3=C1.

=EF=D3=CF=C2=C5=CE=CE=CF=D3=D4=C9 = =CE=C1=CC=CF=C7=CF=D7=CF=C7=CF =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=D1 = =CD=C1=CC=CF=C7=CF=20 =C2=C9=DA=CE=C5=D3=C1.

3.=20 =ED=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 =CE=C1=CC=CF=C7=C1 = =CE=C1 =D0=D2=C9=C2=D9=CC=D8 =D7 =C7=D2=D5=D0=D0=C5=20 = =CB=CF=CD=D0=C1=CE=C9=CA.
 

=ED=C9=CE=C9=CD=C9=DA=C1=C3=C9= =D1 =CE=C1=CC=CF=C7=C1 =D3 =D0=CF=CD=CF=DD=D8=C0=20 =D2=CF=D3=D3=C9=CA=D3=CB=C9=C8 = =D3=D5=C2=DF=C5=CB=D4=CF=D7 =CC=D8=C7=CF=D4=CE=CF=C7=CF = =CE=C1=CC=CF=C7=CF=CF=C2=CC=CF=D6=C5=CE=C9=D1 
(=C4=C1=D7=C1=CC=D8=DE=C5=D3= =CB=C1=D1=20 =D3=C8=C5=CD=C1, =D2=C1=DA=C4=C5=CC=C5=CE=C9=C5 = =D0=CF=D4=CF=CB=CF=D7, =C9=D3=D0=CF=CC=D8=DA=CF=D7=C1=CE=C9=C5 = =D3=D5=C2=DF=C5=CB=D4=CF=D7=20 =CC=D8=C7=CF=D4=CE=CF=C7=CF 
=CE=C1=CC=CF=C7=CF=CF=C2=CC= =CF=D6=C5=CE=C9=D1;=20 =C4=C5=D1=D4=C5=CC=D8=CE=CF=D3=D4=D8 =D7 = =D0=D2=CF=D3=D4=CF=CD =D4=CF=D7=C1=D2=C9=DD=C5=D3=D4=D7=C5; = =C9=D3=D0=CF=CC=D8=DA=CF=D7=C1=CE=C9=C5=20 =D4=D2=C1=CE=D3=C6=C5=D2=D4=CE=CF=C7=CF 
=C3=C5=CE=CF=CF=C2=D2=C1=DA= =CF=D7=C1=CE=C9=D1;=20 =CC=C9=DA=C9=CE=C7; = =D2=C5=CF=D2=C7=C1=CE=C9=DA=C1=C3=C9=D1; =D3=C8=C5=CD=D9 =D3 = =C4=CF=CC=D1=CD=C9 =C9=20 = =D0=D2.)
 
=ED=C5=D6=C4=D5=CE=C1=D2=CF=C4=CE=CF=C5 = =CE=C1=CC=CF=C7=CF=D7=CF=C5 =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5=20 =D3=C4=C5=CC=CF=CB.

4.=20 =EE=C1=CC=CF=C7=CF=D7=CF=C5 = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =EE=E4=F3 = (=D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =CF=C2=CF=D2=CF=D4=CE=CF=C7=CF = =EE=E4=F3;=20 =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 =EE=E4=F3 = =D0=D2=C9 
   =20 =CB=D2=D5=D0=CE=D9=C8 =D3=C4=C5=CC=CB=C1=C8; = =CD=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 =CE=C1=CC=CF=C7=C1 =D0=D2=C9 = =CF=C2=D9=DE=CE=CF=CA =C4=C5=D1=D4=C5=CC=D8=CE=CF=D3=D4=C9=20 = =D0=D2=C5=C4=D0=D2=C9=D1=D4=C9=D1).
 

5. = =EE=C1=CC=CF=C7=CF=D7=CF=C5 =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C5 = =DA=C1=D2=D0=CC=C1=D4=CE=D9=C8=20 =CE=C1=CC=CF=C7=CF=D7 =C9 = =D3=C2=CF=D2=CF=D7.
 

=E4=C9=D7=C9=C4=C5=CE=C4=CE=C1=D1 = =D3=C8=C5=CD=C1;=20 = =CB=CF=CF=D0=C5=D2=C1=D4=C9=D7=D9.

=F0=CF=CE=C9=D6=C5=CE=CE=D9=C5 = =D3=D4=C1=D7=CB=C9 =D3=D4=D2=C1=C8=CF=D7=D9=C8=20 = =D7=DA=CE=CF=D3=CF=D7.

=EB=CD=D0=C5=CE=D3=C1=C3=C9=CF=CE=CE=D9=C5 = =D7=D9=D0=CC=C1=D4=D9; =D7=D9=D0=CC=C1=D4=D9 =D0=CF = =D5=DE=C5=CE=C9=DE=C5=D3=CB=C9=CD=20 = =C4=CF=C7=CF=D7=CF=D2=C1=CD.

=F7=D9=D0=CC=C1=D4=D9 = =DE=CC=C5=CE=C1=CD =D3=CF=D7=C5=D4=C1 =C4=C9=D2=C5=CB=D4=CF=D2=CF=D7;=20 =D0=C5=D2=C5=D2=C1=D3=D0=D2=C5=C4=C5=CC=C5=CE=C9=C5 = =C6=CF=CE=C4=C1 =CF=D0=CC=C1=D4=D9 =D4=D2=D5=C4=C1 =C9 =C4=D2. = =D3=D0=CF=D3=CF=C2=D9 
=CD=C9=CE=C9=CD=C9=DA=C1=C3= =C9=C9=20 =DA=C1=D2=D0=CC=C1=D4=CE=D9=C8 =CE=C1=CC=CF=C7=CF=D7 = (=D3=C2=CF=D2=CF=D7): =CE=C0=C1=CE=D3=D9=20 =D0=D2=C9=CD=C5=CE=C5=CE=C9=D1.

6.=20 =ED=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 =CE=C1=CC=CF=C7=C1 = =CE=C1 =C9=CD=D5=DD=C5=D3=D4=D7=CF.
 

7. = =F2=C5=C9=CE=D7=C5=D3=D4=C9=D2=CF=D7=C1=CE=C9=C5 = =C6=C9=CE=C1=CE=D3=CF=D7 =D0=D2=C9=20 =D0=D2=C9=CD=C5=CE=C5=CE=C9=C9 = =D3=D0=CF=D3=CF=C2=CF=D7 =DC=CB=CF=CE=CF=CD=C9=C9 =CE=C1=CC=CF=C7=C1 = =CE=C1=20 =D0=D2=C9=C2=D9=CC=D8.
 

8. = =EF=C3=C5=CE=CB=C1 =C9 =CD=C9=CE=C9=CD=C9=DA=C1=C3=C9=D1 = =D2=C9=D3=CB=CF=D7=20 =D0=D2=C9 =CE=C1=CC=CF=C7=CF=D7=CF=CD = =D0=CC=C1=CE=C9=D2=CF=D7=C1=CE=C9=C9 (=D3=D7=D1=DA=C1=CE=CE=D9=C8 = =D3=20 =CE=C5=CF=C2=CF=D3=CE=CF=D7=C1=CE=CE=CF=CA 
=CE=C1=CC=CF=C7=CF=D7=CF=CA= =20 =D7=D9=C7=CF=C4=CF=CA; =CE=C1=CC=CF=C7=CF=D7=D9=C5 = =D0=CF=D3=CC=C5=C4=D3=D4=D7=C9=D1 = =CE=C5=C4=C5=CA=D3=D4=D7=C9=D4=C5=CC=D8=CE=CF=D3=D4=C9 = =D3=C4=C5=CC=CF=CB;=20 =D2=C9=D3=CB=C9, =D3=D7=D1=DA=C1=CE=CE=D9=C5 =D3 
=E6=C9=CE=CD=CF=CE=C9=D4=CF= =D2=C9=CE=C7=CF=CD).
 =20


=F3=D4=CF=C9=CD=CF=D3=D4=D8=20 =D5=DE=C1=D3=D4=C9=D1: 11 = 800=20 =D2. 
=F7 = =D3=D4=CF=C9=CD=CF=D3=D4=D8=20 =D7=C8=CF=C4=C9=D4 = =CD=C5=D4=CF=C4=C9=DE=C5=D3=CB=C9=CA =CD=C1=D4=C5=D2=C9=C1=CC, = =CF=C2=C5=C4=D9, =CB=CF=C6=C5-=D0=C1=D5=DA=D9,=20 =D3=C5=D2=D4=C9=C6=C9=CB=C1=D4. 
 

 
------=_NextPart_000_000B_01D1C208.9F02E8F0-- From david@fromorbit.com Wed Jun 8 21:23:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A89FC7CA1 for ; Wed, 8 Jun 2016 21:23:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 18B7AAC002 for ; Wed, 8 Jun 2016 19:23:12 -0700 (PDT) X-ASG-Debug-ID: 1465438987-04cb6c2dbcbf9760001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id qYVX56pdr3Y8HQrE for ; Wed, 08 Jun 2016 19:23:09 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AikLAOzRWFd5LbJkN2dsb2JhbABegz5WfYZvn1wGiEWDbIoNGoVzAgIBAQKBQ00BAQEBAQEHAQEBAUJAhEYBAQQ6HCMQCAMUBAklDwUNGAMHGhOIFQMWuhkNg38BAQEHAgEkHoVBhRWCQ4dXBZgbNIYDhimBcIFzjTaGPoE4h2yEVCoyiggBAQE Received: from ppp121-45-178-100.lns20.syd7.internode.on.net (HELO dastard) ([121.45.178.100]) by ipmail06.adl2.internode.on.net with ESMTP; 09 Jun 2016 11:52:39 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bApcE-0002Pj-8X; Thu, 09 Jun 2016 12:22:38 +1000 Date: Thu, 9 Jun 2016 12:22:38 +1000 From: Dave Chinner To: Reinoud Koornstra Cc: Christoph Hellwig , Eric Sandeen , Daniel Wagner , viro@zeniv.linux.org.uk, xfs@oss.sgi.com Subject: Re: crash in xfs in current Message-ID: <20160609022238.GY26977@dastard> X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1465438988 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2593 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30290 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 07, 2016 at 10:40:11PM -0600, Reinoud Koornstra wrote: > On Tue, Jun 7, 2016 at 10:16 PM, Reinoud Koornstra > wrote: > > On Tue, Jun 7, 2016 at 5:40 PM, Reinoud Koornstra > > wrote: > >> Hi Christoph, > >> > >> Now my git log show this: > >> > >> commit 555b67e4e729ca544bb4028ab12e532c68b70ddb > >> Merge: 544ad71 ad438c4 > >> Author: Dave Chinner > >> Date: Fri May 20 10:34:00 2016 +1000 > >> > >> Merge branch 'xfs-4.7-inode-reclaim' into for-next > >> > >> commit 544ad71fc8e20fb3a6f50f00d487751492cd8409 > >> Merge: 2a4ad58 e6b3bb7 > >> Author: Dave Chinner > >> Date: Fri May 20 10:33:38 2016 +1000 > >> > >> Merge branch 'xfs-4.7-error-cfg' into for-next > >> > >> commit 2a4ad5894c819978dca5595396d54d51c3aca694 > >> Merge: a7792aa 6e3e6d5 > >> Author: Dave Chinner > >> Date: Fri May 20 10:33:17 2016 +1000 > >> > >> Merge branch 'xfs-4.7-misc-fixes' into for-next > >> > >> commit a7792aad644a259375002db8c9d9e03fd50bf509 > >> Merge: 5b911354 3ab3ffc > >> Author: Dave Chinner > >> Date: Fri May 20 10:32:35 2016 +1000 > >> > >> Is this correct? > >> If so, let me build and test. > >> Building it already as we speak, but it would be nice if you could > >> confirm I'm actually testing the right thing. > >> Though, wouldn't it be good to repro and get a core file as well? > >> Or would the test of this commit narrow down the possibilities as well? > >> Thanks, > >> > >> Reinoud. > >> > > > > Ouch, forgive me for not responding inline previously. > > For what it's worth, i've compiled the kernel and are running it as we speak. > > Will do testing and let you know. > > Ok, going back to commit 555b67e4e729ca544bb4028ab12e532c68b70ddb > brings the kernel back to 4.6-rc1. > With that kernel I crash all over the place, so that's something I cannot run. > Is there a way to get the 4.7-rc1 or rc2 without the commits for XFS? In your Linus git tree: $ git remote add xfsdev git://git.kernel.org/git/dgc/linux-xfs.git $ git remote update $ git checkout -b xfsdev-merge v4.6 $ git merge xfsdev/xfs-for-linus-4.7-rc1 And that should give you the XFS changes for 4.7-rc1 in a vanilla 4.6 tree. This merge is one of the things I test (i.e. send to my test machiens for a round of xfstests and other stress) before sending a pull request to Linus, so it should work just fine. Cheers, Dave. -- Dave Chinner david@fromorbit.com From reinoudkoornstra@gmail.com Wed Jun 8 21:53:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6216C7CAE for ; Wed, 8 Jun 2016 21:53:07 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id EF4C1AC001 for ; Wed, 8 Jun 2016 19:53:06 -0700 (PDT) X-ASG-Debug-ID: 1465440783-04bdf05ad7c0c790001-NocioJ Received: from mail-qk0-f179.google.com (mail-qk0-f179.google.com [209.85.220.179]) by cuda.sgi.com with ESMTP id NMYar432UBCtEtGf (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 08 Jun 2016 19:53:04 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qk0-f179.google.com[209.85.220.179] X-Barracuda-Apparent-Source-IP: 209.85.220.179 Received: by mail-qk0-f179.google.com with SMTP id u63so14461558qkh.0 for ; Wed, 08 Jun 2016 19:53:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=wWd73BGSM6Yn+dIwh0yCkkLM4CwV9pHxclYpw88FNFo=; b=eSXK6NrCHeS4Y+C0yFFuqCQCD1GAafYkCJ1z5+F8VHFHJnvMaqbVwZdxXOysH/LTls gcLqZuQ6+szc8rF3SLArmk/yHiUXaPv7+RoEftGWW05bUuFXNi+d5W7MOMsGrLd9MTJb kTpMqmDEHaGOebn51Sp4hjfiFVkB3EKnjN/Hcu7AYOOf9BKuJHz+SrHXOCDTc5Ah4hQF 4dUPTDTQixFiJ9I8N+rKl8k7zyykDHr1/A2R0zDvRzhLedBOtBaelcJHqZY1d8dni4eN ss3hy5ZeVHcjnEmIvG9qTQhpeP1msjggtOiO6kWoxVAW3mmk7SpBle1ECD5Bi2rqG/vc 77aA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=wWd73BGSM6Yn+dIwh0yCkkLM4CwV9pHxclYpw88FNFo=; b=GT/LVqodZp60NJ/99t+/Cj7s570wI1iKB2FaQeBPO7EozNaqgYmhGhgj1kpwmHkKCw 2ovggDV7oxU5UMc7MPQ7zTSqxTb0zDpVwKapQFFqoXVGqhV53DrpFWGIoKDqfE8FB6L0 tXjmFb85vdyMVTN3iC2lve8qYDtO+nFyMrwb0tyCtW+Zl9j1quMgJUBhc02TifBdvlGR Ibi4u/V+2XeoY82iuwZkrr9bXRkf3DmQag5iZlYlM9BQqRg3FAlFpqAm6RZyL8DY4BIg Opchs5EIVRtVuKREGWQlKTXiBC37IHKbi/1A5VyQnBTH4wZqISk+xagS+K3rgvaWIi48 RPXA== X-Gm-Message-State: ALyK8tKQhXTRjXg4D+QnuSqk7c5nT/eBfcCtgJXNdB0xZf58GCMyCse5VVbdyinCV9kgU9pLeOGk91e28pvn3w== X-Received: by 10.55.154.142 with SMTP id c136mr8015812qke.63.1465440783540; Wed, 08 Jun 2016 19:53:03 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.39.13 with HTTP; Wed, 8 Jun 2016 19:53:02 -0700 (PDT) In-Reply-To: <20160609022238.GY26977@dastard> References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> <20160609022238.GY26977@dastard> From: Reinoud Koornstra Date: Wed, 8 Jun 2016 20:53:02 -0600 Message-ID: Subject: Re: crash in xfs in current To: Dave Chinner X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Christoph Hellwig , Eric Sandeen , Daniel Wagner , viro@zeniv.linux.org.uk, xfs@oss.sgi.com Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qk0-f179.google.com[209.85.220.179] X-Barracuda-Start-Time: 1465440784 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3388 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30291 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Wed, Jun 8, 2016 at 8:22 PM, Dave Chinner wrote: > On Tue, Jun 07, 2016 at 10:40:11PM -0600, Reinoud Koornstra wrote: >> On Tue, Jun 7, 2016 at 10:16 PM, Reinoud Koornstra >> wrote: >> > On Tue, Jun 7, 2016 at 5:40 PM, Reinoud Koornstra >> > wrote: >> >> Hi Christoph, >> >> >> >> Now my git log show this: >> >> >> >> commit 555b67e4e729ca544bb4028ab12e532c68b70ddb >> >> Merge: 544ad71 ad438c4 >> >> Author: Dave Chinner >> >> Date: Fri May 20 10:34:00 2016 +1000 >> >> >> >> Merge branch 'xfs-4.7-inode-reclaim' into for-next >> >> >> >> commit 544ad71fc8e20fb3a6f50f00d487751492cd8409 >> >> Merge: 2a4ad58 e6b3bb7 >> >> Author: Dave Chinner >> >> Date: Fri May 20 10:33:38 2016 +1000 >> >> >> >> Merge branch 'xfs-4.7-error-cfg' into for-next >> >> >> >> commit 2a4ad5894c819978dca5595396d54d51c3aca694 >> >> Merge: a7792aa 6e3e6d5 >> >> Author: Dave Chinner >> >> Date: Fri May 20 10:33:17 2016 +1000 >> >> >> >> Merge branch 'xfs-4.7-misc-fixes' into for-next >> >> >> >> commit a7792aad644a259375002db8c9d9e03fd50bf509 >> >> Merge: 5b911354 3ab3ffc >> >> Author: Dave Chinner >> >> Date: Fri May 20 10:32:35 2016 +1000 >> >> >> >> Is this correct? >> >> If so, let me build and test. >> >> Building it already as we speak, but it would be nice if you could >> >> confirm I'm actually testing the right thing. >> >> Though, wouldn't it be good to repro and get a core file as well? >> >> Or would the test of this commit narrow down the possibilities as well? >> >> Thanks, >> >> >> >> Reinoud. >> >> >> > >> > Ouch, forgive me for not responding inline previously. >> > For what it's worth, i've compiled the kernel and are running it as we speak. >> > Will do testing and let you know. >> >> Ok, going back to commit 555b67e4e729ca544bb4028ab12e532c68b70ddb >> brings the kernel back to 4.6-rc1. >> With that kernel I crash all over the place, so that's something I cannot run. >> Is there a way to get the 4.7-rc1 or rc2 without the commits for XFS? > > In your Linus git tree: > > $ git remote add xfsdev git://git.kernel.org/git/dgc/linux-xfs.git > $ git remote update > $ git checkout -b xfsdev-merge v4.6 > $ git merge xfsdev/xfs-for-linus-4.7-rc1 Tried to do this: reinoud@router-dev:~/Downloads/kernel_current$ git remote add xfsdev git://git.kernel.org/git/dgc/linux-xfs.git reinoud@router-dev:~/Downloads/kernel_current$ git remote update Fetching origin Fetching xfsdev fatal: remote error: access denied or repository not exported: /git/dgc/linux-xfs.git error: Could not fetch xfsdev I don't think I have access to git.kernel.org in terms of pushing. :) Or am I doing something else wrong. Forgive the trivial question. Btw, I started in the most current linus git tree.... or should I git 4.6.y and then do your suggestions? Thanks, Reinoud. > > And that should give you the XFS changes for 4.7-rc1 in a vanilla 4.6 > tree. This merge is one of the things I test (i.e. send to my test > machiens for a round of xfstests and other stress) before sending a > pull request to Linus, so it should work just fine. > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com From sandeen@sandeen.net Wed Jun 8 21:56:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id AB5157CB1 for ; Wed, 8 Jun 2016 21:56:25 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 43685AC002 for ; Wed, 8 Jun 2016 19:56:24 -0700 (PDT) X-ASG-Debug-ID: 1465440982-04bdf05ad7c0c8f0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id GlQN6WA4RrsZGVsO for ; Wed, 08 Jun 2016 19:56:22 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id AB83F1F1C; Wed, 8 Jun 2016 21:56:21 -0500 (CDT) Subject: Re: crash in xfs in current To: Reinoud Koornstra , Dave Chinner X-ASG-Orig-Subj: Re: crash in xfs in current References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> <20160609022238.GY26977@dastard> Cc: Christoph Hellwig , Daniel Wagner , viro@zeniv.linux.org.uk, xfs@oss.sgi.com From: Eric Sandeen Message-ID: <00bbe658-a891-3771-ca1d-5661a8b6ab61@sandeen.net> Date: Wed, 8 Jun 2016 21:56:21 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465440982 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1403 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30291 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 6/8/16 9:53 PM, Reinoud Koornstra wrote: >> In your Linus git tree: >> >> $ git remote add xfsdev git://git.kernel.org/git/dgc/linux-xfs.git >> $ git remote update >> $ git checkout -b xfsdev-merge v4.6 >> $ git merge xfsdev/xfs-for-linus-4.7-rc1 > > Tried to do this: > > reinoud@router-dev:~/Downloads/kernel_current$ git remote add xfsdev > git://git.kernel.org/git/dgc/linux-xfs.git I think that should be: git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git -Eric > reinoud@router-dev:~/Downloads/kernel_current$ git remote update > Fetching origin > Fetching xfsdev > fatal: remote error: access denied or repository not exported: > /git/dgc/linux-xfs.git > error: Could not fetch xfsdev > > I don't think I have access to git.kernel.org in terms of pushing. :) > Or am I doing something else wrong. > Forgive the trivial question. > > Btw, I started in the most current linus git tree.... or should I git > 4.6.y and then do your suggestions? > > Thanks, > > Reinoud. > >> >> And that should give you the XFS changes for 4.7-rc1 in a vanilla 4.6 >> tree. This merge is one of the things I test (i.e. send to my test >> machiens for a round of xfstests and other stress) before sending a >> pull request to Linus, so it should work just fine. >> >> Cheers, >> >> Dave. >> -- >> Dave Chinner >> david@fromorbit.com > From reinoudkoornstra@gmail.com Wed Jun 8 22:42:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B48237CB1 for ; Wed, 8 Jun 2016 22:42:32 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 87B7F304043 for ; Wed, 8 Jun 2016 20:42:29 -0700 (PDT) X-ASG-Debug-ID: 1465443747-04cb6c2dbbbfb290001-NocioJ Received: from mail-qg0-f41.google.com (mail-qg0-f41.google.com [209.85.192.41]) by cuda.sgi.com with ESMTP id whwFUYxqpRQt8AzZ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 08 Jun 2016 20:42:27 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qg0-f41.google.com[209.85.192.41] X-Barracuda-Apparent-Source-IP: 209.85.192.41 Received: by mail-qg0-f41.google.com with SMTP id q32so14445703qgq.3 for ; Wed, 08 Jun 2016 20:42:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=/cV44dHpfM8lsSF4a2jRdszdr8RlJHiFF9rufR4ETaI=; b=Wz+8QEb9tupj9+QnOYtV7JeA9psapPXWpCK9iVbOZBjQLw9vNHWIccwjMfq/ql/MSa 5/24/rxBr6qB+Am9E+I6kj3FWT2EUPHnEFaHw6jb6aw/TbBn2SFbb1i3aJjgEgn6TILa Eul6bCELz/5kjRTeLQZ9J6dolvwnsJqnNKiRQcYXgQ5GkSbStxmXDvRZbVQIhqfY0hY2 O4Ch5BNXNwut6IkyyA2DS56bBeZPFGnSOkPSy7O3j1BlhPJD/0RGqs/5fS38Lc4ZrjNz GEKNJYcJ4Eba9vd134Ng0dpazseWDFLx+ingVoXyDx7d3xajow8OPVJFJdSPCcjFynmd fVZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=/cV44dHpfM8lsSF4a2jRdszdr8RlJHiFF9rufR4ETaI=; b=bRhv8igVFjx3gebnlYnycvMxpESqwMRM5eobuVpLCUeQCmEReS86J03fDviO8pKrKG Xv2uBFCoLl8pA6v6TX98qpRuCsMPtAIvrbocnP/CKxQhEgbrmi6tMuV9RWE1VOkV8rab go5bOUzjqtMeMw6IE6vH63Px3N4o/49rEO7fVT+aKzgR/dD3559o6Pvqol1qeEVkqFFF aek+Ng0+Rm/RV3sXotokJoaQ0Hl6g/YWk+KsLKYbtmlYshNwoutXwumvZaGz62y9xe3g 3EdsfLYHLOr24d/b3fetQTs1iz/49IiavWBihxoZs4NmFiFQUFFh5GrRAsS3HHyrsZ7D WrmA== X-Gm-Message-State: ALyK8tLsrALjwWQUBdWYfujcRZyxGoKJRYEraKJWtjpABRCBitDE0Oh2nqm6tYzHj3TNE4VuZk2BxvLqOIJf3g== X-Received: by 10.140.250.213 with SMTP id v204mr7859609qhc.15.1465443747183; Wed, 08 Jun 2016 20:42:27 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.39.13 with HTTP; Wed, 8 Jun 2016 20:42:26 -0700 (PDT) In-Reply-To: <00bbe658-a891-3771-ca1d-5661a8b6ab61@sandeen.net> References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> <20160609022238.GY26977@dastard> <00bbe658-a891-3771-ca1d-5661a8b6ab61@sandeen.net> From: Reinoud Koornstra Date: Wed, 8 Jun 2016 21:42:26 -0600 Message-ID: Subject: Re: crash in xfs in current To: Eric Sandeen X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Dave Chinner , Christoph Hellwig , Daniel Wagner , viro@zeniv.linux.org.uk, xfs@oss.sgi.com Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qg0-f41.google.com[209.85.192.41] X-Barracuda-Start-Time: 1465443747 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2950 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30292 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Wed, Jun 8, 2016 at 8:56 PM, Eric Sandeen wrote: > On 6/8/16 9:53 PM, Reinoud Koornstra wrote: > >>> In your Linus git tree: >>> >>> $ git remote add xfsdev git://git.kernel.org/git/dgc/linux-xfs.git >>> $ git remote update >>> $ git checkout -b xfsdev-merge v4.6 >>> $ git merge xfsdev/xfs-for-linus-4.7-rc1 >> >> Tried to do this: >> >> reinoud@router-dev:~/Downloads/kernel_current$ git remote add xfsdev >> git://git.kernel.org/git/dgc/linux-xfs.git > > I think that should be: > > git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git Ok That worked better indeed. :) reinoud@router-dev:~/Downloads/kernel_current$ git remote add xfsdev git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git reinoud@router-dev:~/Downloads/kernel_current$ git remote update Fetching origin Fetching xfsdev remote: Counting objects: 139, done. [SNIP] reinoud@router-dev:~/Downloads/kernel_current$ git checkout -b xfsdev-merge v4.6 Checking out files: 100% (9437/9437), done. Switched to a new branch 'xfsdev-merge' reinoud@router-dev:~/Downloads/kernel_current$ git merge xfsdev/xfs-for-linus-4.7-rc1 merge: xfsdev/xfs-for-linus-4.7-rc1 - not something we can merge So i tried this: reinoud@router-dev:~/Downloads/kernel_current$ git merge xfs-for-linus-4.7-rc1 Auto-merging fs/xfs/xfs_super.c Auto-merging fs/xfs/xfs_pnfs.c Auto-merging fs/xfs/xfs_mount.h Auto-merging fs/xfs/xfs_mount.c Auto-merging fs/xfs/xfs_file.c Auto-merging fs/xfs/xfs_bmap_util.c Auto-merging fs/xfs/xfs_aops.c Auto-merging fs/xfs/libxfs/xfs_bmap.c Auto-merging fs/namei.c Merge made by the 'recursive' strategy. The terminal did hang .... in 4.6 I killed the git operation and did it again and now it says it's up to date. reinoud@router-dev:~/Downloads/kernel_current$ git merge xfs-for-linus-4.7-rc1 Already up-to-date. reinoud@router-dev:~/Downloads/kernel_current$ git status On branch xfsdev-merge Is this correct, can I now build and test? > > -Eric > >> reinoud@router-dev:~/Downloads/kernel_current$ git remote update >> Fetching origin >> Fetching xfsdev >> fatal: remote error: access denied or repository not exported: >> /git/dgc/linux-xfs.git >> error: Could not fetch xfsdev >> >> I don't think I have access to git.kernel.org in terms of pushing. :) >> Or am I doing something else wrong. >> Forgive the trivial question. >> >> Btw, I started in the most current linus git tree.... or should I git >> 4.6.y and then do your suggestions? >> >> Thanks, >> >> Reinoud. >> >>> >>> And that should give you the XFS changes for 4.7-rc1 in a vanilla 4.6 >>> tree. This merge is one of the things I test (i.e. send to my test >>> machiens for a round of xfstests and other stress) before sending a >>> pull request to Linus, so it should work just fine. >>> >>> Cheers, >>> >>> Dave. >>> -- >>> Dave Chinner >>> david@fromorbit.com >> From prodajbionline@meiloffer.eu Thu Jun 9 06:29:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_MESSAGE,MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A82BC7CA0 for ; Thu, 9 Jun 2016 06:29:22 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6B2E18F8039 for ; Thu, 9 Jun 2016 04:29:19 -0700 (PDT) X-ASG-Debug-ID: 1465471753-04cbb03569c41e70001-NocioJ Received: from meiloffer.eu (meiloffer.eu [94.156.237.41]) by cuda.sgi.com with ESMTP id 1b41krnDhT4ewANG for ; Thu, 09 Jun 2016 04:29:13 -0700 (PDT) X-Barracuda-Envelope-From: prodajbionline@meiloffer.eu X-Barracuda-Effective-Source-IP: meiloffer.eu[94.156.237.41] X-Barracuda-Apparent-Source-IP: 94.156.237.41 Received: from tsmails.eu by meiloffer.eu (MDaemon PRO v9.6.1) with ESMTP id md50010981596.msg for ; Thu, 09 Jun 2016 14:28:01 +0300 To: xfs@oss.sgi.com Subject: =?UTF-8?B?0KHQu9C10LTQstCw0Lkg0L/RgNCw0LLQuNC70L3QuNGC0LUg0YHRgtGK0L/QutC4?= Message-ID: X-ASG-Orig-Subj: =?UTF-8?B?0KHQu9C10LTQstCw0Lkg0L/RgNCw0LLQuNC70L3QuNGC0LUg0YHRgtGK0L/QutC4?= Date: Thu, 09 Jun 2016 11:35:49 +0300 From: "=?UTF-8?B?0J/RgNC+0LTQsNC20LHQuCDQvtC90LvQsNC50L0=?=" Reply-To: prodajbionline@mail.bg MIME-Version: 1.0 X-Mailer-LID: 55 List-Unsubscribe: X-Mailer-RecptId: 2375256 X-Mailer-SID: 120 X-Mailer-Sent-By: 1 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: 8bit X-Authenticated-Sender: prodajbionline@meiloffer.eu X-Lookup-Warning: EHLO lookup on tsmails.eu does not match 94.156.237.44 X-MDRemoteIP: 94.156.237.44 X-Return-Path: prodajbionline@meiloffer.eu X-Envelope-From: prodajbionline@meiloffer.eu X-MDaemon-Deliver-To: xfs@oss.sgi.com X-Barracuda-Connect: meiloffer.eu[94.156.237.41] X-Barracuda-Start-Time: 1465471753 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8432 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.80 X-Barracuda-Spam-Status: No, SCORE=0.80 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC7_SA_HREF_HTTP_MISMATCH, HTML_MESSAGE, MIME_HTML_ONLY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30299 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.80 BSF_SC7_SA_HREF_HTTP_MISMATCH BODY: Custom Phishing Mismatch 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message

Как да извличате максимума от вашите рекламни кампании в интернет?

Покана за тренинг - Продажби онлайн – следвай правилните стъпки

Темата е популярна, но знаете ли, че може да планирате много точно как да използвате своите ограничени ресурси във възможности за увеличение на продажбите?

Важно* Не е необходимо да имате каквито и да е технически умения, за да бъдете на този курс.

Планиране, тактика, действие – работа с готов материал от 12 страници с точни стъпки, които да следвате при изработка на маркетинг стратегия за он-лайн продажби.

Ще разберете, кои са работещите бизнес модели и как да ценообразувате, така че да сте на печалба.

На този тренинг ще научите:

· Как да планирате

· Как да поставяте цели

· Как да правите целеви страници

· За какво да използвате Facebook и Google

· Как да откриете най-подходящите специалисти

· Колко е нормално да струват услугите

· Как да продавате по и-мейл

· Колко и какви хора ще са ви необходими за всичко

· С кое може да се справите сами

· Как да ценообразувате

· Какви бизнес модели можете да изберете

ВАЖНО* По време на тренинга ще работите по готов материал от 12 страници с точни стъпки, които да следвате. Така ще се запознаете и изпробвате механиката на всяка успешна кампания за онлайн продажби.

Вижте пълната програма на сайта от този линк http://igritenauspeha.com/events/prodajbi-on-line-2/

Курсът ще се проведе на 22 юни в гр. София, зала „Лозенец“, ул. Бисер 2 (до НДК)

Стандарта цена 180 лв.

Цена 120 лв. при ранна регистрация направена до 17.06.2016 г. (спестявате 60 лв.)

Обадете се на 0878 161 907 още сега, за да проверите за свободни места и да вземете своята отстъпка от 60 лв.

Програма и подробно описание вижте от този линк http://igritenauspeha.com/events/prodajbi-on-line-2/

Очакваме Ви.

 

Съгласно закона за електронна търговия Чл. 6, ал. 1 Ви уведомяваме, че е възможно това да е непоискано търговско съобщение.
То е еднократно изпратено писмо до Вашия e-mail адрес, който е взет от публичното пространство.
Извиняваме се за причиненото неудобство, ако сме Ви притеснили с нашето предложение.
Ако не желаете да получавате съобщения от "Igrite na uspeha", моля натиснете ТУК за автоматично отписване.

From jtulak@redhat.com Thu Jun 9 07:26:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BFCB27CA0 for ; Thu, 9 Jun 2016 07:26:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 37D1FAC002 for ; Thu, 9 Jun 2016 05:26:42 -0700 (PDT) X-ASG-Debug-ID: 1465475201-04cb6c2dbac06f60001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 4RAApZqmFM1opQMg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 05:26:42 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 365CB4DB08 for ; Thu, 9 Jun 2016 12:26:41 +0000 (UTC) Received: from jtulak.brq.redhat.com (jtulak.brq.redhat.com [10.34.26.85]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u59CQdIu017963; Thu, 9 Jun 2016 08:26:40 -0400 From: Jan Tulak To: xfs@oss.sgi.com Cc: Jan Tulak Subject: [PATCH] mkfs: better error with incorrect b/s value suffix usage Date: Thu, 9 Jun 2016 14:26:35 +0200 X-ASG-Orig-Subj: [PATCH] mkfs: better error with incorrect b/s value suffix usage Message-Id: <1465475195-19149-1-git-send-email-jtulak@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 09 Jun 2016 12:26:41 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465475201 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1940 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 If user writes a value using b or s suffix without explicitly stating the size of blocks or sectors, mkfs ends with a not helpful error about the value being too small. It happens because we read the physical geometry after all options are parsed. So, tell the user exactly what is wrong with the input. Signed-off-by: Jan Tulak --- While adding entries into the mkfs input test, I found this issue, though it may be only a documentation thing. When I give some option block/sector suffix without specifying explicitly its size (for example, -l su=10b without -b size=4096), I get an error that value 10b is too small. Of course it is, because, at the time, mkfs did not read physical geometry yet, so blocksize is 0. And 10*0 = 0. I think that this is not something we need to change, but it should be better documented. Maybe not manpage (where it can be overlooked if not written to every option using the size and it might be that it already is somewhere down there), but an error message should warn the user in case of using b or s suffix incorrectly. I'm open to suggestions for a better solution, though. Cheers, Jan --- mkfs/xfs_mkfs.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 955dcfd..2870f7b 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -3615,9 +3615,21 @@ cvtnum( return -1LL; if (*sp == 'b') - return i * blksize; + if (!blksize) { + fprintf(stderr, +_("Blocksize must be explicitly provided when using 'b' suffix.\n")); + usage(); + } else { + return i * blksize; + } if (*sp == 's') - return i * sectsize; + if (!sectsize) { + fprintf(stderr, +_("Sectorsize must be explicitly provided when using 's' suffix.\n")); + usage(); + } else { + return i * sectsize; + } c = tolower(*sp); switch (c) { -- 2.5.5 From jtulak@redhat.com Thu Jun 9 08:27:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EA7B97CA0 for ; Thu, 9 Jun 2016 08:27:51 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 62A18AC002 for ; Thu, 9 Jun 2016 06:27:48 -0700 (PDT) X-ASG-Debug-ID: 1465478866-04cbb03569c45b40001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id MyXXDvoVKc4jKK3P (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 06:27:46 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 454E88F4F7 for ; Thu, 9 Jun 2016 13:27:46 +0000 (UTC) Received: from jtulak.brq.redhat.com (jtulak.brq.redhat.com [10.34.26.85]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u59DRjLf017308; Thu, 9 Jun 2016 09:27:45 -0400 From: Jan Tulak To: xfs@oss.sgi.com Cc: Jan Tulak Subject: [PATCH v2] mkfs: better error with incorrect b/s value suffix usage Date: Thu, 9 Jun 2016 15:27:41 +0200 X-ASG-Orig-Subj: [PATCH v2] mkfs: better error with incorrect b/s value suffix usage Message-Id: <1465478861-8714-1-git-send-email-jtulak@redhat.com> In-Reply-To: <1465475195-19149-1-git-send-email-jtulak@redhat.com> References: <1465475195-19149-1-git-send-email-jtulak@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Thu, 09 Jun 2016 13:27:46 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465478866 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2095 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 If user writes a value using b or s suffix without explicitly stating the size of blocks or sectors, mkfs ends with a not helpful error about the value being too small. It happens because we read the physical geometry after all options are parsed. So, tell the user exactly what is wrong with the input. Signed-off-by: Jan Tulak --- While adding entries into the mkfs input test, I found this issue, though it may be only a documentation thing. When I give some option block/sector suffix without specifying explicitly its size (for example, -l su=10b without -b size=4096), I get an error that value 10b is too small. Of course it is, because, at the time, mkfs did not read physical geometry yet, so blocksize is 0. And 10*0 = 0. I think that this is not something we need to change, but it should be better documented. Maybe not manpage (where it can be overlooked if not written to every option using the size and it might be that it already is somewhere down there), but an error message should warn the user in case of using b or s suffix incorrectly. I'm open to suggestions for a better solution, though. UPDATE: Add { and } to fix a gcc warning about ambigious else branch. Cheers, Jan --- mkfs/xfs_mkfs.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index ed7800f..455bf11 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -3614,10 +3614,24 @@ cvtnum( if (sp[1] != '\0') return -1LL; - if (*sp == 'b') - return i * blksize; - if (*sp == 's') - return i * sectsize; + if (*sp == 'b') { + if (!blksize) { + fprintf(stderr, +_("Blocksize must be explicitly provided when using 'b' suffix.\n")); + usage(); + } else { + return i * blksize; + } + } + if (*sp == 's') { + if (!sectsize) { + fprintf(stderr, +_("Sectorsize must be explicitly provided when using 's' suffix.\n")); + usage(); + } else { + return i * sectsize; + } + } c = tolower(*sp); switch (c) { -- 2.5.5 From jtulak@redhat.com Thu Jun 9 08:41:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A75E27CA0 for ; Thu, 9 Jun 2016 08:41:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 7A2AE304051 for ; Thu, 9 Jun 2016 06:41:50 -0700 (PDT) X-ASG-Debug-ID: 1465479708-04cbb0356ac462e0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id djk5dXWvjEXQAZgw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 06:41:49 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 97478C003574 for ; Thu, 9 Jun 2016 13:41:48 +0000 (UTC) Received: from jtulak.brq.redhat.com (jtulak.brq.redhat.com [10.34.26.85]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u59DflJw016247; Thu, 9 Jun 2016 09:41:47 -0400 From: Jan Tulak To: xfs@oss.sgi.com Cc: Jan Tulak Subject: [PATCH] mkfs: test that -l su is a multiple of block size Date: Thu, 9 Jun 2016 15:41:40 +0200 X-ASG-Orig-Subj: [PATCH] mkfs: test that -l su is a multiple of block size Message-Id: <1465479700-14111-1-git-send-email-jtulak@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 09 Jun 2016 13:41:48 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465479709 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 847 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 lsunit was already tested, but lsu was not. So a thing like -l su=4097 was possible. This commit adds a check to fix it. Signed-off-by: Jan Tulak --- mkfs/xfs_mkfs.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 455bf11..b9b50fe 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2875,6 +2875,15 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), lsunit = dsunit; } + if (lsu) { + if (lsu % blocksize != 0) { + fprintf(stderr, + _("log stripe unit (%d) must be a multiple of the block size (%d)\n"), + lsu, blocksize); + exit(1); + } + } + if (sb_feat.log_version == 2 && (lsunit * blocksize) > 256 * 1024) { /* Warn only if specified on commandline */ if (lsuflag || lsunitflag) { -- 2.5.5 From sandeen@sandeen.net Thu Jun 9 10:44:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 1CE4F7CA0 for ; Thu, 9 Jun 2016 10:44:57 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D31748F8035 for ; Thu, 9 Jun 2016 08:44:56 -0700 (PDT) X-ASG-Debug-ID: 1465487093-04bdf06581005c0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id Ijf5eFSfM4MyEfzT for ; Thu, 09 Jun 2016 08:44:53 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id E51784A6 for ; Thu, 9 Jun 2016 10:44:52 -0500 (CDT) Subject: Re: [PATCH v2] mkfs: better error with incorrect b/s value suffix usage To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH v2] mkfs: better error with incorrect b/s value suffix usage References: <1465475195-19149-1-git-send-email-jtulak@redhat.com> <1465478861-8714-1-git-send-email-jtulak@redhat.com> From: Eric Sandeen Message-ID: Date: Thu, 9 Jun 2016 10:44:52 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1465478861-8714-1-git-send-email-jtulak@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465487093 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3019 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/9/16 8:27 AM, Jan Tulak wrote: > If user writes a value using b or s suffix without explicitly stating the size > of blocks or sectors, mkfs ends with a not helpful error about the value being > too small. It happens because we read the physical geometry after all options > are parsed. It's probably worth putting an example of the current error in the commitlog, i.e.: # mkfs.xfs -dfile,name=fsfile,size=128m -l su=10b -b Illegal value 10b for -l su option. value is too small ... > So, tell the user exactly what is wrong with the input. > > Signed-off-by: Jan Tulak > --- > > While adding entries into the mkfs input test, I found this issue, though it > may be only a documentation thing. When I give some option block/sector suffix > without specifying explicitly its size (for example, -l su=10b without -b > size=4096), I get an error that value 10b is too small. Of course it is, > because, at the time, mkfs did not read physical geometry yet, so blocksize is > 0. And 10*0 = 0. > > I think that this is not something we need to change, but it should be better > documented. Maybe not manpage (where it can be overlooked if not written to > every option using the size and it might be that it already is somewhere down > there), but an error message should warn the user in case of using b or s > suffix incorrectly. > > I'm open to suggestions for a better solution, though. > > UPDATE: > Add { and } to fix a gcc warning about ambigious else branch. > > Cheers, > Jan > --- > mkfs/xfs_mkfs.c | 22 ++++++++++++++++++---- > 1 file changed, 18 insertions(+), 4 deletions(-) > > diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c > index ed7800f..455bf11 100644 > --- a/mkfs/xfs_mkfs.c > +++ b/mkfs/xfs_mkfs.c > @@ -3614,10 +3614,24 @@ cvtnum( > if (sp[1] != '\0') > return -1LL; > > - if (*sp == 'b') > - return i * blksize; > - if (*sp == 's') > - return i * sectsize; > + if (*sp == 'b') { > + if (!blksize) { > + fprintf(stderr, > +_("Blocksize must be explicitly provided when using 'b' suffix.\n")); I'd fix the warning text a little bit, because: # mkfs.xfs -dfile,name=fsfile,size=128m -l su=10b -b size=4k Blocksize must be explicitly provided when using 'b' suffix. But I *did* provide it! No fair! ;) Perhaps: +_("Blocksize must be specified prior to using the 'b' suffix.\n")); and +_("Sectorsize must be specified prior to using the 's' suffix.\n")); ? (old mkfs said "blocksize not available yet." which is a bit cryptic as well, but at least we clearly have the same behavior now, just different messages.) -Eric > + usage(); > + } else { > + return i * blksize; > + } > + } > + if (*sp == 's') { > + if (!sectsize) { > + fprintf(stderr, > +_("Sectorsize must be explicitly provided when using 's' suffix.\n")); > + usage(); > + } else { > + return i * sectsize; > + } > + } > > c = tolower(*sp); > switch (c) { > From axboe@kernel.dk Thu Jun 9 11:06:12 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 191517CA0 for ; Thu, 9 Jun 2016 11:06:12 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id CEF348F8033 for ; Thu, 9 Jun 2016 09:06:08 -0700 (PDT) X-ASG-Debug-ID: 1465488366-04bdf0658000f80001-NocioJ Received: from mail-io0-f182.google.com (mail-io0-f182.google.com [209.85.223.182]) by cuda.sgi.com with ESMTP id cZYuGEftKC0TCyWc (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 09 Jun 2016 09:06:06 -0700 (PDT) X-Barracuda-Envelope-From: axboe@kernel.dk X-Barracuda-RBL-Trusted-Forwarder: 209.85.223.182 Received: by mail-io0-f182.google.com with SMTP id 5so42025415ioy.1 for ; Thu, 09 Jun 2016 09:06:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel-dk.20150623.gappssmtp.com; s=20150623; h=subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=gEjnzXH80ke3Z0QlPkKEkAYlOSZ2ssT1AlEiKc/dgLk=; b=S2D/NtJKMi78v5rYNGoaGIp6gYOA/77pr43nNpMHO/5xP1PIrDKifkt4cM6OiulSyH hDBzIjLuxuOOWcpBWoH15h0P5x4+Rr/8U6cXbz459tI0fCdSvuw/lA1aDpzfqJlftGCM eEo6XpBAajGm1N55HL0uYPnNybAmkf+mjXH51zWVGW3CkJuzI/zHH6OlswuNL6uxpLQz 3BwPNcSzWcqiyvHqoNhoBRC2UzAzkd1Ow6B8wjeC2/ZGe839xWl5mY4t5BKFa/gKTrjv r3BKeCGf+kqXnrsW8MIcREYNyY1MjqDB4GreP9q0KbJE07vYKxI4/DT8DqHUFNcEjMFT eM5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=gEjnzXH80ke3Z0QlPkKEkAYlOSZ2ssT1AlEiKc/dgLk=; b=QizdQL/PxmWyyg5elE9bAgj+uNQ3bdogK9J25orVb6vHxPTbkBgTZuAgsQ8jPWQleW fF+mnm9Juo5HPQzx34WpgRJ/7ska+Jr+5NJmg4+W5pqDvhSGut/uW/9U4RXNWgKsBo5v TE2VSz1rpy0adfOtOqEUJVnwKxJ/Dcicbc7+5lQGNP8w0kxY+ZPvcC6FEMrE0BMZat0Q xrQ2BKxEZNb1+vX+65D9UnNUi97FaMETI+Efn+vZYxWlRArIGFx2HybFPNAVobdDE774 eEXeHwstaegfhQ1yp47E1YkLqE7chJ7y07CDitkjQQoL6UtV836GsvubTuj7THS23y5b kLBw== X-Gm-Message-State: ALyK8tKAHUIcfYDi8fO7F3Ylzhl8CPuEY/p70FS/lAdqrwzEEmJUgplcBllIMlATMtCZEg== X-Received: by 10.107.153.71 with SMTP id b68mr19393747ioe.105.1465488365885; Thu, 09 Jun 2016 09:06:05 -0700 (PDT) Received: from [192.168.1.130] ([216.160.245.98]) by smtp.gmail.com with ESMTPSA id l123sm13825636ita.1.2016.06.09.09.06.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Jun 2016 09:06:05 -0700 (PDT) Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs X-Barracuda-BBL-IP: 192.168.1.130 To: Ming Lei , Jens Axboe , linux-kernel@vger.kernel.org X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> Cc: linux-block@vger.kernel.org, Christoph Hellwig , Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , Mike Snitzer , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" From: Jens Axboe Message-ID: <575993EA.3010005@kernel.dk> Date: Thu, 9 Jun 2016 10:06:02 -0600 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-io0-f182.google.com[209.85.223.182] X-Barracuda-Start-Time: 1465488366 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 969 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 05/30/2016 07:34 AM, Ming Lei wrote: > Hi, > > Interests[1] have been shown in multipage bvecs, so this patchset > try to prepare for the support and do two things: > > 1) the 1st 4 patches use bvec iterator to implement iterate_bvec(), > then we can drop the non-standard way for iterating bvec, which > can be thought as a good cleanup for lib/iov_iter.c > > 2) remove BIO_MAX_SECTORS and makre BIO_MAX_SIZE as obsolete, and > now there is only one user for each. Once multipage bvecs is introduced, > one bio may hold lots of sectors, and we should always use sort of > BIO_MAX_VECS which should be introduced in future and is similiar > with current BIO_MAX_PAGES. > > The only functional change is iterate_bvec():lib/iov_iter.c > > xfstests(-a auto) over loop aio is run for ext4/xfs to verify > the change and no regression found with this patchset. Added patches 1-7, still waiting for an answer on my reply to #8. -- Jens Axboe From sandeen@sandeen.net Thu Jun 9 11:23:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 241447CA4 for ; Thu, 9 Jun 2016 11:23:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id E8BDA8F8033 for ; Thu, 9 Jun 2016 09:23:15 -0700 (PDT) X-ASG-Debug-ID: 1465489392-04cbb03f52018b0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id pvkRiqyOLKk6NBTa for ; Thu, 09 Jun 2016 09:23:12 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id DEE934A6 for ; Thu, 9 Jun 2016 11:23:11 -0500 (CDT) Subject: Re: [PATCH] mkfs: test that -l su is a multiple of block size To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] mkfs: test that -l su is a multiple of block size References: <1465479700-14111-1-git-send-email-jtulak@redhat.com> From: Eric Sandeen Message-ID: <5f6ee8a0-b704-5aa6-ff67-f7a5f6761732@sandeen.net> Date: Thu, 9 Jun 2016 11:23:11 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1465479700-14111-1-git-send-email-jtulak@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465489392 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3133 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/9/16 8:41 AM, Jan Tulak wrote: > lsunit was already tested, but lsu was not. So a thing like -l su=4097 was > possible. This commit adds a check to fix it. > > Signed-off-by: Jan Tulak > --- > mkfs/xfs_mkfs.c | 9 +++++++++ > 1 file changed, 9 insertions(+) > > diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c > index 455bf11..b9b50fe 100644 > --- a/mkfs/xfs_mkfs.c > +++ b/mkfs/xfs_mkfs.c > @@ -2875,6 +2875,15 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), > lsunit = dsunit; > } > > + if (lsu) { > + if (lsu % blocksize != 0) { > + fprintf(stderr, > + _("log stripe unit (%d) must be a multiple of the block size (%d)\n"), > + lsu, blocksize); > + exit(1); > + } > + } > + Hm, I'm not quite seeing the behavior you say you're fixing; you give the example of -l su=4097, but: # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=4097 Illegal value 4097 for -l su option. value is too small So that's really not the relevant test case. And in these cases it is caught and does fail: # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=63k log stripe unit (64512) must be a multiple of the block size (4096) # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=64512 log stripe unit (64512) must be a multiple of the block size (4096) But in this case it does not: # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=16385 meta-data=fsfile isize=512 agcount=4, agsize=8192 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1, sparse=0 data = bsize=4096 blocks=32768, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal log bsize=4096 blocks=552, version=2 = sectsz=512 sunit=4 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 So what's going on here...? It has something to do with how calc_stripe_factors() operates, and when that happens vs. the checks. lsu and lsunit are really specifying the same thing, just in different units. Your patch does fix it up, but I wonder if these tests are in the wrong place; with your patch we essentially do this: 1) Parse lsu value 2) Convert lsu to lsunit 3) Check lsunit (it's ok) 4) Go back and check lsu (it's not ok) It seems to me that we should recognize either lsu or lsunit as the "one true value" and convert the other to it as soon as possible, rather than carrying around both, and checking both at various times. calc_stripe_factors() does do some validity checks; perhaps it should check against blocksize multiples as well, so it's all in one place? And a comment about what that function is doing (converting su's to sunit's, really) would be helpful. What do you think? Your patch does resolve the problem but I think it adds a little more confusion to already confusing code. -Eric From sandeen@sandeen.net Thu Jun 9 11:36:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 13D9D7CA4 for ; Thu, 9 Jun 2016 11:36:28 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 910F9AC001 for ; Thu, 9 Jun 2016 09:36:24 -0700 (PDT) X-ASG-Debug-ID: 1465490182-04cb6c381604300001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id Q6pr2YTdVKfzUEPD for ; Thu, 09 Jun 2016 09:36:22 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 887814A6 for ; Thu, 9 Jun 2016 11:36:22 -0500 (CDT) To: xfs-oss From: Eric Sandeen Subject: [PATCH 0/4] xfs: online relabeling [RFC] Message-ID: X-ASG-Orig-Subj: [PATCH 0/4] xfs: online relabeling [RFC] Date: Thu, 9 Jun 2016 11:36:21 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465490182 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 680 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Ok, this more or less works; not really up to snuff for submission or merging, just sketching it out, but some questions first: 1) Is there really any point to this? :) We did have one request, and btrfs can do it ... 2) Is using m_growlock horrible? growfs is the only other thing that writes all supers, so I grabbed it. We don't want multiple relabels stepping on each other. 3) Is there some way to actually force the primary to disk? Right now the label change isn't actually visible on the primary until unmount, which defeats the purpose. I'm not sure if there's a straightforward/safe way to make it visible... Thanks, -Eric From sandeen@sandeen.net Thu Jun 9 11:38:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 03BC17CA0 for ; Thu, 9 Jun 2016 11:38:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 72631AC004 for ; Thu, 9 Jun 2016 09:38:43 -0700 (PDT) X-ASG-Debug-ID: 1465490321-04cb6c3816043d0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id qkSOkpu3grjoJPed for ; Thu, 09 Jun 2016 09:38:41 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 5F0504A6 for ; Thu, 9 Jun 2016 11:38:41 -0500 (CDT) Subject: [PATCH 1/4] fs: hoist [GS]ET_FSLABEL to vfs To: xfs@oss.sgi.com X-ASG-Orig-Subj: [PATCH 1/4] fs: hoist [GS]ET_FSLABEL to vfs References: From: Eric Sandeen Message-ID: Date: Thu, 9 Jun 2016 11:38:40 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465490321 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2321 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Move the btrfs label ioctls up to the vfs for general use. Signed-off-by: Eric Sandeen --- diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 053e677..b23be4e 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -5431,6 +5431,10 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_setflags(file, argp); case FS_IOC_GETVERSION: return btrfs_ioctl_getversion(file, argp); + case FS_IOC_GET_FSLABEL: + return btrfs_ioctl_get_fslabel(file, argp); + case FS_IOC_SET_FSLABEL: + return btrfs_ioctl_set_fslabel(file, argp); case FITRIM: return btrfs_ioctl_fitrim(file, argp); case BTRFS_IOC_SNAP_CREATE: @@ -5538,10 +5542,6 @@ long btrfs_ioctl(struct file *file, unsigned int return btrfs_ioctl_quota_rescan_wait(file, argp); case BTRFS_IOC_DEV_REPLACE: return btrfs_ioctl_dev_replace(root, argp); - case BTRFS_IOC_GET_FSLABEL: - return btrfs_ioctl_get_fslabel(file, argp); - case BTRFS_IOC_SET_FSLABEL: - return btrfs_ioctl_set_fslabel(file, argp); case BTRFS_IOC_GET_SUPPORTED_FEATURES: return btrfs_ioctl_get_supported_features(argp); case BTRFS_IOC_GET_FEATURES: diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index a079d50..fca64f2 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -234,6 +234,8 @@ struct fsxattr { #define FICLONERANGE _IOW(0x94, 13, struct file_clone_range) #define FIDEDUPERANGE _IOWR(0x94, 54, struct file_dedupe_range) +#define FSLABEL_MAX 256 /* Max chars for the interface; each fs may differ */ + #define FS_IOC_GETFLAGS _IOR('f', 1, long) #define FS_IOC_SETFLAGS _IOW('f', 2, long) #define FS_IOC_GETVERSION _IOR('v', 1, long) @@ -243,8 +245,10 @@ struct fsxattr { #define FS_IOC32_SETFLAGS _IOW('f', 2, int) #define FS_IOC32_GETVERSION _IOR('v', 1, int) #define FS_IOC32_SETVERSION _IOW('v', 2, int) -#define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) -#define FS_IOC_FSSETXATTR _IOW ('X', 32, struct fsxattr) +#define FS_IOC_FSGETXATTR _IOR('X', 31, struct fsxattr) +#define FS_IOC_FSSETXATTR _IOW('X', 32, struct fsxattr) +#define FS_IOC_GET_FSLABEL _IOR(0x94, 49, char[FSLABEL_MAX]) +#define FS_IOC_SET_FSLABEL _IOW(0x94, 50, char[FSLABEL_MAX]) /* * File system encryption support From sandeen@sandeen.net Thu Jun 9 11:40:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 56CBD7CA6 for ; Thu, 9 Jun 2016 11:40:04 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2ACEB304039 for ; Thu, 9 Jun 2016 09:40:01 -0700 (PDT) X-ASG-Debug-ID: 1465490399-04cb6c381304460001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id XtoMUqgADzzrAlI1 for ; Thu, 09 Jun 2016 09:39:59 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 32D084A6 for ; Thu, 9 Jun 2016 11:39:59 -0500 (CDT) Subject: [PATCH 2/4] xfs: factor out secondary superblock updates To: xfs@oss.sgi.com X-ASG-Orig-Subj: [PATCH 2/4] xfs: factor out secondary superblock updates References: From: Eric Sandeen Message-ID: <35aeba74-5045-a00e-bb62-e7bdcd32fae8@sandeen.net> Date: Thu, 9 Jun 2016 11:39:58 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465490399 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5486 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- growfs rewrites all secondary supers, and relabel must do so as well; factor out the code which does this for use by both operations. Signed-off-by: Eric Sandeen --- fs/xfs/xfs_fsops.c | 131 +++++++++++++++++++++++++++++++--------------------- fs/xfs/xfs_fsops.h | 2 + 2 files changed, 80 insertions(+), 53 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index b4d7582..b49b4e4 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -140,6 +140,79 @@ xfs_growfs_get_hdr_buf( return bp; } +/* + * Copy the contents of the primary super to all backup supers. + * %agcount is current number of ags in the filesystem. + * %nagcount is used during growfs when we may have new secondaries. + * If %nagcount is 0 (no growfs), we use %agcount in its place. + */ +int +xfs_update_secondary_supers( + xfs_mount_t *mp, + xfs_agnumber_t agcount, + xfs_agnumber_t nagcount) +{ + int error, saved_error; + xfs_agnumber_t agno; + xfs_buf_t *bp; + + error = saved_error = 0; + + if (nagcount == 0) + nagcount = agcount; + + for (agno = 1; agno < nagcount; agno++) { + error = 0; + if (agno < agcount) { + error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0, &bp, + &xfs_sb_buf_ops); + } else { + /* + * new secondary superblocks need to be zeroed, not read + * from disk as the contents of the new area we are + * growing into is completely unknown. + */ + bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), + XFS_FSS_TO_BB(mp, 1), 0); + if (bp) { + bp->b_ops = &xfs_sb_buf_ops; + xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); + } else + error = -ENOMEM; + } + + /* + * If we get an error reading or writing alternate superblocks, + * continue. xfs_repair chooses the "best" superblock based + * on most matches; if we break early, we'll leave more + * superblocks un-updated than updated, and xfs_repair may + * pick them over the properly-updated primary. + */ + if (error) { + xfs_warn(mp, + "error %d reading secondary superblock for ag %d", + error, agno); + saved_error = error; + continue; + } + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); + + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) { + xfs_warn(mp, + "write error %d updating secondary superblock for ag %d", + error, agno); + saved_error = error; + continue; + } + } + return saved_error ? saved_error : error; +} + static int xfs_growfs_data_private( xfs_mount_t *mp, /* mount point for filesystem */ @@ -155,7 +228,7 @@ xfs_growfs_data_private( xfs_buf_t *bp; int bucket; int dpct; - int error, saved_error = 0; + int error; xfs_agnumber_t nagcount; xfs_agnumber_t nagimax = 0; xfs_rfsblock_t nb, nb_mod; @@ -502,59 +575,11 @@ xfs_growfs_data_private( mp->m_maxicount = 0; xfs_set_low_space_thresholds(mp); - /* update secondary superblocks. */ - for (agno = 1; agno < nagcount; agno++) { - error = 0; - /* - * new secondary superblocks need to be zeroed, not read from - * disk as the contents of the new area we are growing into is - * completely unknown. - */ - if (agno < oagcount) { - error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), - XFS_FSS_TO_BB(mp, 1), 0, &bp, - &xfs_sb_buf_ops); - } else { - bp = xfs_trans_get_buf(NULL, mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)), - XFS_FSS_TO_BB(mp, 1), 0); - if (bp) { - bp->b_ops = &xfs_sb_buf_ops; - xfs_buf_zero(bp, 0, BBTOB(bp->b_length)); - } else - error = -ENOMEM; - } - - /* - * If we get an error reading or writing alternate superblocks, - * continue. xfs_repair chooses the "best" superblock based - * on most matches; if we break early, we'll leave more - * superblocks un-updated than updated, and xfs_repair may - * pick them over the properly-updated primary. - */ - if (error) { - xfs_warn(mp, - "error %d reading secondary superblock for ag %d", - error, agno); - saved_error = error; - continue; - } - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); - - error = xfs_bwrite(bp); - xfs_buf_relse(bp); - if (error) { - xfs_warn(mp, - "write error %d updating secondary superblock for ag %d", - error, agno); - saved_error = error; - continue; - } - } - return saved_error ? saved_error : error; + /* Copy new geometry to all backup superblocks */ + error = xfs_update_secondary_supers(mp, oagcount, nagcount); + return error; - error0: +error0: xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h index f32713f..82e8dc7 100644 --- a/fs/xfs/xfs_fsops.h +++ b/fs/xfs/xfs_fsops.h @@ -19,6 +19,8 @@ #define __XFS_FSOPS_H__ extern int xfs_fs_geometry(xfs_mount_t *mp, xfs_fsop_geom_t *geo, int nversion); +extern int xfs_update_secondary_supers(xfs_mount_t *mp, xfs_agnumber_t aogcount, + xfs_agnumber_t nagcount); extern int xfs_growfs_data(xfs_mount_t *mp, xfs_growfs_data_t *in); extern int xfs_growfs_log(xfs_mount_t *mp, xfs_growfs_log_t *in); extern int xfs_fs_counts(xfs_mount_t *mp, xfs_fsop_counts_t *cnt); -- 1.7.1 From sandeen@sandeen.net Thu Jun 9 11:41:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EF7907CA2 for ; Thu, 9 Jun 2016 11:41:09 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id C27AE8F8035 for ; Thu, 9 Jun 2016 09:41:09 -0700 (PDT) X-ASG-Debug-ID: 1465490468-04cbb03f5502360001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id iaXhTCgj2aeEiIWb for ; Thu, 09 Jun 2016 09:41:08 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 00FC54A6 for ; Thu, 9 Jun 2016 11:41:08 -0500 (CDT) Subject: [PATCH 3/4] xfs: implement online get/set fs label To: xfs@oss.sgi.com X-ASG-Orig-Subj: [PATCH 3/4] xfs: implement online get/set fs label References: From: Eric Sandeen Message-ID: <67255993-9730-2872-675f-ac5cb518a338@sandeen.net> Date: Thu, 9 Jun 2016 11:41:07 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465490468 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2593 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Wire up label ioctls for XFS. Signed-off-by: Eric Sandeen --- This is where the implementation questions come in; is using growlock an abomination? How can I make the primary super change immediately visible? fs/xfs/xfs_ioctl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 62 insertions(+), 0 deletions(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index dbca737..ab59213 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -41,6 +41,8 @@ #include "xfs_trans.h" #include "xfs_pnfs.h" #include "xfs_acl.h" +#include "xfs_log.h" +#include "xfs_sb.h" #include #include @@ -1603,6 +1605,62 @@ xfs_ioc_swapext( return error; } +static int +xfs_ioc_getlabel( + struct xfs_mount *mp, + char __user *label) +{ + int error = 0; + struct xfs_sb *sbp = &mp->m_sb; + + if (!mutex_trylock(&mp->m_growlock)) + return -EWOULDBLOCK; + if (copy_to_user(label, sbp->sb_fname, sizeof(sbp->sb_fname))) + error = -EFAULT; + mutex_unlock(&mp->m_growlock); + return error; +} + +static int +xfs_ioc_setlabel( + struct file *filp, + struct xfs_mount *mp, + char __user *newlabel) +{ + int error; + struct xfs_sb *sbp = &mp->m_sb; + char sb_fname[12]; + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (copy_from_user(sb_fname, newlabel, sizeof(sb_fname))) + return -EFAULT; + + error = mnt_want_write_file(filp); + if (error) + return error; + + /* growfs & label both muck w/ the super directly... */ + if (!mutex_trylock(&mp->m_growlock)) + return -EWOULDBLOCK; + memset(sbp->sb_fname, 0, sizeof(sbp->sb_fname)); + strncpy(sbp->sb_fname, sb_fname, sizeof(sbp->sb_fname)); + + error = xfs_sync_sb(mp, true); + if (error) + goto out; + /* + * Most kernelspace superblock updates only update sb 0. + * Userspace relabel has always updated all, though, so: + */ + error = xfs_update_secondary_supers(mp, sbp->sb_agcount, 0); +out: + mutex_unlock(&mp->m_growlock); + mnt_drop_write_file(filp); + return error; +} + /* * Note: some of the ioctl's return positive numbers as a * byte count indicating success, such as readlink_by_handle. @@ -1630,6 +1688,10 @@ xfs_file_ioctl( switch (cmd) { case FITRIM: return xfs_ioc_trim(mp, arg); + case FS_IOC_GET_FSLABEL: + return xfs_ioc_getlabel(mp, arg); + case FS_IOC_SET_FSLABEL: + return xfs_ioc_setlabel(filp, mp, arg); case XFS_IOC_ALLOCSP: case XFS_IOC_FREESP: case XFS_IOC_RESVSP: -- 1.7.1 From tibbs@math.uh.edu Thu Jun 9 11:43:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9F6567CA2 for ; Thu, 9 Jun 2016 11:43:15 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 734658F8035 for ; Thu, 9 Jun 2016 09:43:15 -0700 (PDT) X-ASG-Debug-ID: 1465490592-04cb6c3815045a0001-NocioJ Received: from mx2.math.uh.edu (mx2.math.uh.edu [129.7.128.33]) by cuda.sgi.com with ESMTP id mrhk8SBcR83Q8FQF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 09:43:12 -0700 (PDT) X-Barracuda-Envelope-From: tibbs@math.uh.edu X-Barracuda-Effective-Source-IP: mx2.math.uh.edu[129.7.128.33] X-Barracuda-Apparent-Source-IP: 129.7.128.33 Received: from epithumia.math.uh.edu ([129.7.128.2]) by mx2.math.uh.edu with esmtp (Exim 4.86_2) (envelope-from ) id 1bB331-0005fW-JB for xfs@oss.sgi.com; Thu, 09 Jun 2016 11:43:12 -0500 Received: by epithumia.math.uh.edu (Postfix, from userid 7225) id 88D0B6A7; Thu, 9 Jun 2016 11:43:11 -0500 (CDT) From: Jason L Tibbitts III To: xfs@oss.sgi.com Subject: xfsaild 20 wakeups per second Date: Thu, 09 Jun 2016 11:43:11 -0500 X-ASG-Orig-Subj: xfsaild 20 wakeups per second Message-ID: User-Agent: Gnus/5.130014 (Ma Gnus v0.14) Emacs/24.5 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Barracuda-Connect: mx2.math.uh.edu[129.7.128.33] X-Barracuda-Start-Time: 1465490592 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 602 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- I was tuning the power consumption of my new laptop and noticed that each xfsaild process is still waking up 20 times per second. I found http://oss.sgi.com/archives/xfs/2012-03/msg00237.html which I think indicates that this was a workaround for some other issue and wouldn't be permanent. Unfortunately that was 4+ years ago. I wasn't able to locate any other discussion about the topic. Was it determined that the wakeups were going to have to stay permanently? Or was the issue just not revisited? And if the former, is there a way to tune the wakeup frequency in any way? - J< From sandeen@sandeen.net Thu Jun 9 11:44:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5A04F7CA2 for ; Thu, 9 Jun 2016 11:44:39 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id C8BF5AC001 for ; Thu, 9 Jun 2016 09:44:38 -0700 (PDT) X-ASG-Debug-ID: 1465490676-04cbb03f5402510001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id rIGcBhl5ScUZ9k65 for ; Thu, 09 Jun 2016 09:44:36 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id E6C074A6 for ; Thu, 9 Jun 2016 11:44:35 -0500 (CDT) Subject: [PATCH 4/4] xfsprogs: add online relabel commands To: xfs@oss.sgi.com X-ASG-Orig-Subj: [PATCH 4/4] xfsprogs: add online relabel commands References: From: Eric Sandeen Message-ID: <0d905426-649e-278a-1e85-6dca646cb812@sandeen.net> Date: Thu, 9 Jun 2016 11:44:35 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465490676 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5244 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.50 X-Barracuda-Spam-Status: No, SCORE=0.50 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MV0713 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.50 BSF_SC0_MV0713 Custom rule MV0713 This adds a get/set label command to xfs_io, and updates the xfs_admin script to use it rather than xfs_db if the filesystem is mounted. Signed-off-by: Eric Sandeen --- Still needs a man page update. The new xfs_io command is: # xfs_io> label [newlabel] The hack to flush the bdev is maybe not right, I'm not sure xfs has actually gotten the change out to sector 0 yet at this point... diff --git a/db/xfs_admin.sh b/db/xfs_admin.sh index d42446b..02485b0 100755 --- a/db/xfs_admin.sh +++ b/db/xfs_admin.sh @@ -16,7 +16,7 @@ do f) DB_OPTS=$DB_OPTS" -f";; j) DB_OPTS=$DB_OPTS" -c 'version log2'";; l) DB_OPTS=$DB_OPTS" -r -c label";; - L) DB_OPTS=$DB_OPTS" -c 'label "$OPTARG"'";; + L) LABEL_OPT=$OPTARG;; p) DB_OPTS=$DB_OPTS" -c 'version projid32bit'";; u) DB_OPTS=$DB_OPTS" -r -c uuid";; U) DB_OPTS=$DB_OPTS" -c 'uuid "$OPTARG"'";; @@ -32,10 +32,18 @@ done set -- extra $@ shift $OPTIND case $# in - 1) if [ -n "$DB_OPTS" ] + 1) DIR=`grep -w $1 /proc/mounts | awk '{print $2}'` + if [ -n "$LABEL_OPT" -a -n "$DIR" ] then - eval xfs_db -x -p xfs_admin $DB_OPTS $1 + eval io/xfs_io -c "'label $LABEL_OPT'" $DIR status=$? + else + DB_OPTS=$DB_OPTS" -c 'label "$LABEL_OPT"'" + fi + if [ -n "$DB_OPTS" ] + then + eval db/xfs_db -x -p xfs_admin $DB_OPTS $1 + status=`expr $? + $status` fi if [ -n "$REPAIR_OPTS" ] then diff --git a/io/Makefile b/io/Makefile index 0b53f41..8f46340 100644 --- a/io/Makefile +++ b/io/Makefile @@ -9,9 +9,9 @@ LTCOMMAND = xfs_io LSRCFILES = xfs_bmap.sh xfs_freeze.sh xfs_mkfile.sh HFILES = init.h io.h CFILES = init.c \ - attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c link.c \ - mmap.c open.c parent.c pread.c prealloc.c pwrite.c seek.c shutdown.c \ - sync.c truncate.c reflink.c + attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c label.c \ + link.c mmap.c open.c parent.c pread.c prealloc.c pwrite.c seek.c \ + shutdown.c sync.c truncate.c reflink.c LLDLIBS = $(LIBXCMD) $(LIBHANDLE) LTDEPENDENCIES = $(LIBXCMD) $(LIBHANDLE) diff --git a/io/init.c b/io/init.c index 51f1f5c..0c08a57 100644 --- a/io/init.c +++ b/io/init.c @@ -65,6 +65,7 @@ init_commands(void) help_init(); imap_init(); inject_init(); + label_init(); seek_init(); madvise_init(); mincore_init(); diff --git a/io/io.h b/io/io.h index 172b1f8..560ad52 100644 --- a/io/io.h +++ b/io/io.h @@ -102,6 +102,7 @@ extern void getrusage_init(void); extern void help_init(void); extern void imap_init(void); extern void inject_init(void); +extern void label_init(void); extern void mmap_init(void); extern void open_init(void); extern void parent_init(void); diff --git a/io/label.c b/io/label.c new file mode 100644 index 0000000..721f27b --- /dev/null +++ b/io/label.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 Red Hat, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "platform_defs.h" +#include "libxfs.h" +#include "path.h" +#include "command.h" +#include "init.h" +#include "io.h" + +#ifndef FS_IOC_GET_FSLABEL +#define FSLABEL_MAX 256 /* Max chars for the interface; each fs may differ */ +#define FS_IOC_GET_FSLABEL _IOR(0x94, 49, char[FSLABEL_MAX]) +#define FS_IOC_SET_FSLABEL _IOW(0x94, 50, char[FSLABEL_MAX]) +#endif + +static cmdinfo_t label_cmd; + +static int +label_f( + int argc, + char **argv) +{ + int error; + char label[FSLABEL_MAX]; + + if (argc == 1) { + memset(&label, 0, sizeof(label)); + error = ioctl(file->fd, FS_IOC_GET_FSLABEL, &label); + } else { + fs_path_t *fs; /* mount point information */ + int fd; + + strncpy(label, argv[1], sizeof(label)); + error = ioctl(file->fd, FS_IOC_SET_FSLABEL, &label); + /* best effort to flush bdev cache */ + fs_table_initialise(0, NULL, 0, NULL); + fs = fs_table_lookup(file->name, FS_MOUNT_POINT); + if (fs) { + fd = open(fs->fs_name, O_RDONLY); + if (fd >= 0) { + ioctl(fd, BLKFLSBUF, 0); + close(fd); + } + } + } + + if (error) + perror("label:"); + else + printf("label = \"%s\"\n", label); + + return error; + +} + +void +label_init(void) +{ + label_cmd.name = "label"; + label_cmd.cfunc = label_f; + label_cmd.argmin = 0; + label_cmd.argmax = 1; + label_cmd.args = _("[label]"); + label_cmd.flags = CMD_NOMAP_OK | CMD_FOREIGN_OK; + label_cmd.oneline = + _("queries or sets the filesystem label while mounted"); + + add_command(&label_cmd); +} From sandeen@sandeen.net Thu Jun 9 11:51:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8C5EB7CA7 for ; Thu, 9 Jun 2016 11:51:15 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 517D48F8035 for ; Thu, 9 Jun 2016 09:51:15 -0700 (PDT) X-ASG-Debug-ID: 1465491073-04cb6c381404940001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id uLjVndBJqwn3GEN8 for ; Thu, 09 Jun 2016 09:51:13 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 620A84A6 for ; Thu, 9 Jun 2016 11:51:13 -0500 (CDT) Subject: Re: [PATCH 0/4] xfs: online relabeling [RFC] To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH 0/4] xfs: online relabeling [RFC] References: From: Eric Sandeen Message-ID: <2305b486-f336-6d1e-9420-b69dc5bdc572@sandeen.net> Date: Thu, 9 Jun 2016 11:51:12 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465491073 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1428 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/9/16 11:36 AM, Eric Sandeen wrote: > Ok, this more or less works; not really up to snuff > for submission or merging, just sketching it out, but some > questions first: > > 1) Is there really any point to this? :) We did have one > request, and btrfs can do it ... > > 2) Is using m_growlock horrible? growfs is the only other > thing that writes all supers, so I grabbed it. We don't > want multiple relabels stepping on each other. > > 3) Is there some way to actually force the primary to disk? > Right now the label change isn't actually visible on the > primary until unmount, which defeats the purpose. I'm not > sure if there's a straightforward/safe way to make it > visible... Oh, sorry - I guess it is getting written out, but it's only available via an O_DIRECT read from userspace; it's not invalidating the cache. # io/xfs_io -c "label derp" /mnt/test label = "derp" # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C ... 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| ... # dd if=/dev/sdb2 iflag=direct bs=512 count=1 | hexdump -C ... 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 64 65 72 70 |............derp| ... # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C ... 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| ... Guess I need to think about this some more. -Eric From original-tl-headlamp-xfs=oss.sgi.com@christophercouto.com Thu Jun 9 12:08:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_IMAGE_RATIO_02, HTML_MESSAGE,MIME_QP_LONG_LINE,T_DKIM_INVALID,T_REMOTE_IMAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7544C7CA0 for ; Thu, 9 Jun 2016 12:08:32 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 29CA38F8033 for ; Thu, 9 Jun 2016 10:08:29 -0700 (PDT) X-ASG-Debug-ID: 1465492090-04bdf0657f02c70001-NocioJ Received: from mail.christophercouto.com (nat207.web.ntrra.com [94.156.145.207]) by cuda.sgi.com with ESMTP id Ba2aw2BcSlCZtcbK for ; Thu, 09 Jun 2016 10:08:11 -0700 (PDT) X-Barracuda-Envelope-From: original-tl-headlamp-xfs=oss.sgi.com@christophercouto.com X-Barracuda-Effective-Source-IP: nat207.web.ntrra.com[94.156.145.207] X-Barracuda-Apparent-Source-IP: 94.156.145.207 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; s=dkim; d=christophercouto.com; h=Date:From:To:Subject:MIME-Version:Content-Type:List-Unsubscribe:Message-ID; i=original-tl-headlamp@christophercouto.com; bh=UmjnV4zlTs+KfdChJf9yd1cI4t8=; b=cHuFKwGv9nH8CBTUpZ4bZYO+/gnfyt1MpWPxFvSXOnvUdPPlSzsEFPJfY6hhkbP0jQtarHKV/0y5 SHZpy9bcJFix9cCW6Job85WAa7LLHRLiS4J1M7yimuWMldJ3a2nd9vcOFEYULIfB21AFfppEPZ+g m5yBSvvpaGVcmwaktYw= DomainKey-Signature: a=rsa-sha1; c=nofws; q=dns; s=dkim; d=christophercouto.com; b=Y5kBUgc5vkEWG5FdBd414vb8pIEmtCeVz56s4+iC4LJG0U6b/RlZJAkMR0YeyF4ua+hmyeuhBSi4 azSdAoANEP7Fe3wujZlSLLyBEuzAckcPo2xlOQzipkZRsfKgpr0tPOPk2RB2bZvqA52EjjvM1PRI W6mxf+OZuWPC0VRjHZo=; Received: by mail.christophercouto.com id hb6h7o0001g3 for ; Thu, 9 Jun 2016 12:05:48 -0500 (envelope-from ) Date: Thu, 9 Jun 2016 12:05:48 -0500 From: "Original TL Headlamp" To: Subject: Summers Approaching, Are You Equipped? MIME-Version: 1.0 X-ASG-Orig-Subj: Summers Approaching, Are You Equipped? Content-Type: multipart/alternative; boundary="----=_Part_496_1115618197.1465491945951" List-Unsubscribe: Message-ID: <0.0.0.37.1D1C2712B7CCC8E.A487@mail.christophercouto.com> X-Barracuda-Connect: nat207.web.ntrra.com[94.156.145.207] X-Barracuda-Start-Time: 1465492090 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8606 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.37 X-Barracuda-Spam-Status: No, SCORE=1.37 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, HTML_IMAGE_RATIO_02, HTML_MESSAGE, MIME_QP_LONG_LINE, MIME_QP_LONG_LINE_2 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.55 HTML_IMAGE_RATIO_02 BODY: HTML has a low ratio of text to image area 0.00 HTML_MESSAGE BODY: HTML included in message 0.00 MIME_QP_LONG_LINE RAW: Quoted-printable line longer than 76 chars 0.82 MIME_QP_LONG_LINE_2 RAW: Quoted-printable line longer than 76 chars ------=_Part_496_1115618197.1465491945951 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Summers Approaching, Are You Equipped? http://www.christophercouto.com/blue/b5286FC5DbdfZsnFjnn0ntv0Mjh347 Update Preferences- http://www.christophercouto.com/red/b34Uv865bQe4ZsnFjnn0ntv0Mjha6d ------=_Part_496_1115618197.1465491945951 Content-Type: text/html; charset=us-ascii Content-Transfer-Encoding: quoted-printable =20 =20 =20 =20 =20 =20
=20

Summers Approaching, Are You Equipped?

=20
=20 =20 =20 =20 =20 =20 =20
=20 =20 =20 =20 =20 =20 =20
=20 =20 =20 =20 =20 =20 =20

I wanted to quickly inform you something Primitive Surviv= ors is releasing in a few days...

It' s The TL900 Flashlight....

(see the image below)

3D""

Limited supplies ar= e available....Yes Claim My 75% OFF Today!


  <= /td>=20
 
=20 =20 =20 =20 =20 =20 =20
=20 =20 =20 =20 =20 =20 =20 =20
=20
=20

Update Preferences

=20
Primitive Survivors
1863 Pioneer Pkwy E Suite 222 Springfield, OR 97477 -= 1-866-804-5530
 
=20
=20
=20
=20
=20
=20
=20
=20
=20
 =20

=20
3D""/
=20 =20 ------=_Part_496_1115618197.1465491945951-- From bfoster@redhat.com Thu Jun 9 12:19:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D218A7CA3 for ; Thu, 9 Jun 2016 12:19:06 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4CC5AAC001 for ; Thu, 9 Jun 2016 10:19:03 -0700 (PDT) X-ASG-Debug-ID: 1465492741-04cb6c381405390001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id gTLl2rD6hj2HWpEn (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 10:19:02 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 59E9EC04B33C; Thu, 9 Jun 2016 17:19:01 +0000 (UTC) Received: from laptop.bfoster (vpn-59-59.rdu2.redhat.com [10.10.59.59]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u59HIwxZ029342 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 9 Jun 2016 13:19:00 -0400 Date: Thu, 9 Jun 2016 13:18:57 -0400 From: Brian Foster To: Jason L Tibbitts III Cc: xfs@oss.sgi.com Subject: Re: xfsaild 20 wakeups per second Message-ID: <20160609171857.GA9052@laptop.bfoster> X-ASG-Orig-Subj: Re: xfsaild 20 wakeups per second References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 09 Jun 2016 17:19:01 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465492741 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1093 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 09, 2016 at 11:43:11AM -0500, Jason L Tibbitts III wrote: > I was tuning the power consumption of my new laptop and noticed that > each xfsaild process is still waking up 20 times per second. I found > http://oss.sgi.com/archives/xfs/2012-03/msg00237.html which I think > indicates that this was a workaround for some other issue and wouldn't > be permanent. Unfortunately that was 4+ years ago. I wasn't able to > locate any other discussion about the topic. > > Was it determined that the wakeups were going to have to stay > permanently? Or was the issue just not revisited? And if the former, > is there a way to tune the wakeup frequency in any way? > The short answer is that the wakeups are probably going to be around for the immediate future. There was some recent discussion on this here (see the follow up thread to the patch): http://oss.sgi.com/pipermail/xfs/2016-April/048526.html Brian > - J< > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Thu Jun 9 12:46:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BD80F7CA0 for ; Thu, 9 Jun 2016 12:46:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 47D16AC002 for ; Thu, 9 Jun 2016 10:46:02 -0700 (PDT) X-ASG-Debug-ID: 1465494360-04bdf0658203ca0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id J4D8igDfQvuT0CWG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 10:46:00 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u59Hjuh2004284 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 9 Jun 2016 17:45:57 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u59Hjuol010984 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 9 Jun 2016 17:45:56 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u59Hjrfx020507; Thu, 9 Jun 2016 17:45:54 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 09 Jun 2016 10:45:53 -0700 Date: Thu, 9 Jun 2016 10:45:51 -0700 From: "Darrick J. Wong" To: Christoph Hellwig Cc: Dave Chinner , xfs@oss.sgi.com Subject: Re: [RFC] allow enabling reflinks at runtime Message-ID: <20160609174551.GD10371@birch.djwong.org> X-ASG-Orig-Subj: Re: [RFC] allow enabling reflinks at runtime References: <1464877150-20457-1-git-send-email-hch@lst.de> <20160602225415.GP12670@dastard> <20160608071130.GB24663@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160608071130.GB24663@lst.de> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1465494360 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1486 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30300 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Wed, Jun 08, 2016 at 09:11:30AM +0200, Christoph Hellwig wrote: > On Fri, Jun 03, 2016 at 08:54:15AM +1000, Dave Chinner wrote: > > On Thu, Jun 02, 2016 at 04:19:07PM +0200, Christoph Hellwig wrote: > > > I've had some vocal user requests to allow enabling reflinks at run time, > > > which happens to be a mostly trivial feature. The only caveat is that we > > > need a large enough log size to support the reflink requirements, but for > > > typical large file systems that's not an issue. > > > > Hmmm - how does this interact with all the rmap code? I was not > > planning on enabling reflink without rmap and vice versa simply > > because it makes the validation and testing matrix vastly more > > complex. > > Uh. So far I've only been testing pure reflink code, mostly because > rmap really doesn't buy much for the use case I'm working on. So far I've mostly been testing with mkfs.xfs -i sparse=1 -m rmapbt=1,reflink=1 on the assumption that sparse will get turned on soon and that it might help a lot in the post-COW fragmentation world. (Hoping that the cowextsize defaults avoid most of the horrifying fragmentation that we see on the second- and last-letter filesystems.) > Enabling rmap post-mkfs is defintively a different ballpark, and probably > not worth it even if it would be doable. Hughflgrgh. I wasn't even going to consider /that/ possibility. :) (I guess you could flip on the feature bit and run xfs_repair...) --D From tibbs@math.uh.edu Thu Jun 9 13:08:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8A1877CAF for ; Thu, 9 Jun 2016 13:08:30 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 04522AC002 for ; Thu, 9 Jun 2016 11:08:26 -0700 (PDT) X-ASG-Debug-ID: 1465495704-04cb6c381606840001-NocioJ Received: from mx1.math.uh.edu (mx1.math.uh.edu [129.7.128.32]) by cuda.sgi.com with ESMTP id G4xM51c4NzvDe2kU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 09 Jun 2016 11:08:24 -0700 (PDT) X-Barracuda-Envelope-From: tibbs@math.uh.edu X-Barracuda-Effective-Source-IP: mx1.math.uh.edu[129.7.128.32] X-Barracuda-Apparent-Source-IP: 129.7.128.32 Received: from epithumia.math.uh.edu ([129.7.128.2]) by mx1.math.uh.edu with esmtp (Exim 4.86_2) (envelope-from ) id 1bB4NT-0000vx-Fg; Thu, 09 Jun 2016 13:08:24 -0500 Received: by epithumia.math.uh.edu (Postfix, from userid 7225) id 6B50D467; Thu, 9 Jun 2016 13:08:23 -0500 (CDT) From: Jason L Tibbitts III To: Brian Foster Cc: xfs@oss.sgi.com Subject: Re: xfsaild 20 wakeups per second References: <20160609171857.GA9052@laptop.bfoster> X-ASG-Orig-Subj: Re: xfsaild 20 wakeups per second Date: Thu, 09 Jun 2016 13:08:23 -0500 In-Reply-To: <20160609171857.GA9052@laptop.bfoster> (Brian Foster's message of "Thu, 9 Jun 2016 13:18:57 -0400") Message-ID: User-Agent: Gnus/5.130014 (Ma Gnus v0.14) Emacs/24.5 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Barracuda-Connect: mx1.math.uh.edu[129.7.128.32] X-Barracuda-Start-Time: 1465495704 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 351 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30301 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header >>>>> "BF" == Brian Foster writes: BF> There was some recent discussion on this here (see the follow up BF> thread to the patch): Ah. Sorry about bringing that back up; I just joined and I wasn't using the right search terms to find the previous thread in the archives. At least I now know what's happening. - J< From david@fromorbit.com Thu Jun 9 17:58:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 624757CA0 for ; Thu, 9 Jun 2016 17:58:09 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 27FFC304051 for ; Thu, 9 Jun 2016 15:58:05 -0700 (PDT) X-ASG-Debug-ID: 1465513082-04cbb03f540ee20001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id VCqdc3pojoWjmSH0 for ; Thu, 09 Jun 2016 15:58:02 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjgKAJPzWVd5LDgrN2dsb2JhbABegz6BU4J2g3mfWwEBAQEBAQaMMYYEhAmGDQQCAoE7TQEBAQEBAQcBAQEBQkCERgEBBDocMwgDGAklDwUlAwcbEoguvl4xHoVBhRWKGgEEmFWOHY8qj2WCWxyBXSoyiggBAQE Received: from ppp121-44-56-43.lns20.syd4.internode.on.net (HELO dastard) ([121.44.56.43]) by ipmail06.adl2.internode.on.net with ESMTP; 10 Jun 2016 08:28:00 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bB8tS-0004tS-LN; Fri, 10 Jun 2016 08:57:42 +1000 Date: Fri, 10 Jun 2016 08:57:42 +1000 From: Dave Chinner To: xfs@oss.sgi.com, hch@infradead.org Subject: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time Message-ID: <20160609225742.GZ26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: add an option to enable reflinks at mount time References: <1464877150-20457-1-git-send-email-hch@lst.de> <1464877150-20457-4-git-send-email-hch@lst.de> <20160606112342.GB23695@redhat.com> <20160608070459.GC18458@infradead.org> <20160608080703.GA8987@redhat.com> <20160608081007.GB8987@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160608081007.GB8987@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1465513082 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 918 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30310 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On Wed, Jun 08, 2016 at 10:10:07AM +0200, Carlos Maiolino wrote: > On Wed, Jun 08, 2016 at 10:07:03AM +0200, Carlos Maiolino wrote: > > On Wed, Jun 08, 2016 at 12:04:59AM -0700, Christoph Hellwig wrote: > > > Yes, the comment is wrong. Any reason you didn't include me in the > > > reply? Also it seems your reply-to also magically drops you > > > from the reply. Are you using a new mailer? :) > > > > No, no reason, I missed to CC you. Maybe my CTRL-L list-reply in mutt screwed up > > with the destination fields, I should come back to group replies, thanks for the > > heads up :) > > Oh crap, I did it again, ok, no more list-reply for me If you are using mutt, then just use "g" for group reply. I've never used anything else - it just does the right thing. I didn't even know that "list-reply" was something that people used.... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 9 18:33:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2CA237CA0 for ; Thu, 9 Jun 2016 18:33:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 01F6D8F8033 for ; Thu, 9 Jun 2016 16:33:49 -0700 (PDT) X-ASG-Debug-ID: 1465515227-04cbb03f550fe70001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id wdExOUKWcL6TeqB6 for ; Thu, 09 Jun 2016 16:33:47 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjYKAMb7WVd5LDgrN2dsb2JhbABdgz6BU4J2g3mfXQEBAQEBAQaMMYoNhg0EAgKBN00BAQEBAQEHAQEBAUJAhEYBAQQ6HCMQCAMOCgklDwUlAwcaE4guvlABAQEBBgIBJB6FQYUVh2yCLgWYVY4djyqPZYRUKjKIRiuBFwEBAQ Received: from ppp121-44-56-43.lns20.syd4.internode.on.net (HELO dastard) ([121.44.56.43]) by ipmail06.adl2.internode.on.net with ESMTP; 10 Jun 2016 09:03:46 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bB9SK-0004wz-5R; Fri, 10 Jun 2016 09:33:44 +1000 Date: Fri, 10 Jun 2016 09:33:44 +1000 From: Dave Chinner To: Christoph Hellwig Cc: darrick.wong@oracle.com, xfs@oss.sgi.com Subject: Re: [RFC] allow enabling reflinks at runtime Message-ID: <20160609233344.GA26977@dastard> X-ASG-Orig-Subj: Re: [RFC] allow enabling reflinks at runtime References: <1464877150-20457-1-git-send-email-hch@lst.de> <20160602225415.GP12670@dastard> <20160608071130.GB24663@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160608071130.GB24663@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1465515227 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2101 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30311 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 08, 2016 at 09:11:30AM +0200, Christoph Hellwig wrote: > On Fri, Jun 03, 2016 at 08:54:15AM +1000, Dave Chinner wrote: > > On Thu, Jun 02, 2016 at 04:19:07PM +0200, Christoph Hellwig wrote: > > > I've had some vocal user requests to allow enabling reflinks at run time, > > > which happens to be a mostly trivial feature. The only caveat is that we > > > need a large enough log size to support the reflink requirements, but for > > > typical large file systems that's not an issue. > > > > Hmmm - how does this interact with all the rmap code? I was not > > planning on enabling reflink without rmap and vice versa simply > > because it makes the validation and testing matrix vastly more > > complex. > > Uh. So far I've only been testing pure reflink code, mostly because > rmap really doesn't buy much for the use case I'm working on. > Enabling rmap post-mkfs is defintively a different ballpark, and probably > not worth it even if it would be doable. Wasn't expecting rmap to ever be dynamically enabled ;) So ignoring the testing side of things, and looking more at the implementation of the enabling, I'm not sure I really like the idea of doing this via a mount option. Because we've got to make significant additions to the on disk format in each AG, this seems more like a "growfs style" operation than anything. i.e. lock out allocation, add all the structures to the AG headers and allocate all the blocks needed, re-initialise the per-ag structures with all the necessary info, then switch on the feature bit and commit the change. It's probably a little more intricate than doing it at mount time, but it gets around the fact that users have to add a mount option and bounce the filesystem to turn on reflinks. I can see this being much easier than a mount option in some situations, (e.g. for the root filesystem), and I don't think it's much harder to test than the mount option (e.g. the way growfs is tested under stress by xfs/104)... Your thoughts, Christoph? Cheers, Dave. -- Dave Chinner david@fromorbit.com From ming.lei@canonical.com Thu Jun 9 21:44:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A92297CA0 for ; Thu, 9 Jun 2016 21:44:45 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6D9C48F8033 for ; Thu, 9 Jun 2016 19:44:42 -0700 (PDT) X-ASG-Debug-ID: 1465526676-04cb6c381513210001-NocioJ Received: from youngberry.canonical.com (youngberry.canonical.com [91.189.89.112]) by cuda.sgi.com with ESMTP id zPuYDNbusCE4vH2Q (version=TLSv1 cipher=AES256-SHA bits=256 verify=NO) for ; Thu, 09 Jun 2016 19:44:37 -0700 (PDT) X-Barracuda-Envelope-From: ming.lei@canonical.com X-Barracuda-Effective-Source-IP: youngberry.canonical.com[91.189.89.112] X-Barracuda-Apparent-Source-IP: 91.189.89.112 Received: from mail-yw0-f173.google.com ([209.85.161.173]) by youngberry.canonical.com with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1bBCR2-00075J-9V for xfs@oss.sgi.com; Fri, 10 Jun 2016 02:44:36 +0000 Received: by mail-yw0-f173.google.com with SMTP id z186so36952788ywd.2 for ; Thu, 09 Jun 2016 19:44:36 -0700 (PDT) X-Gm-Message-State: ALyK8tJASslx2kbMnnUrzITAGhI1IhIAaYfP3MYDByG6N43t1orLJPOGGDXRV7GFL/FVdxq4WHsS97JTGD8OxA== X-Received: by 10.37.217.3 with SMTP id q3mr7198950ybg.127.1465526675324; Thu, 09 Jun 2016 19:44:35 -0700 (PDT) MIME-Version: 1.0 Received: by 10.37.216.78 with HTTP; Thu, 9 Jun 2016 19:44:34 -0700 (PDT) In-Reply-To: <575993EA.3010005@kernel.dk> References: <1464615294-9946-1-git-send-email-ming.lei@canonical.com> <575993EA.3010005@kernel.dk> From: Ming Lei Date: Fri, 10 Jun 2016 10:44:34 +0800 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: [PATCH v6 0/8] block: prepare for multipage bvecs To: Jens Axboe X-ASG-Orig-Subj: Re: [PATCH v6 0/8] block: prepare for multipage bvecs Cc: Jens Axboe , Linux Kernel Mailing List , linux-block@vger.kernel.org, Christoph Hellwig , Al Viro , "open list:DRBD DRIVER" , Jan Kara , Joe Thornber , Keith Busch , Kent Overstreet , "Kirill A. Shutemov" , "Martin K. Petersen" , Michal Hocko , Mike Snitzer , NeilBrown , Sagi Grimberg , Shaohua Li , Steven Whitehouse , Tejun Heo , "open list:XFS FILESYSTEM" Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: youngberry.canonical.com[91.189.89.112] X-Barracuda-Start-Time: 1465526677 X-Barracuda-Encrypted: AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1508 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30312 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 10, 2016 at 12:06 AM, Jens Axboe wrote: > On 05/30/2016 07:34 AM, Ming Lei wrote: >> >> Hi, >> >> Interests[1] have been shown in multipage bvecs, so this patchset >> try to prepare for the support and do two things: >> >> 1) the 1st 4 patches use bvec iterator to implement iterate_bvec(), >> then we can drop the non-standard way for iterating bvec, which >> can be thought as a good cleanup for lib/iov_iter.c >> >> 2) remove BIO_MAX_SECTORS and makre BIO_MAX_SIZE as obsolete, and >> now there is only one user for each. Once multipage bvecs is introduced, >> one bio may hold lots of sectors, and we should always use sort of >> BIO_MAX_VECS which should be introduced in future and is similiar >> with current BIO_MAX_PAGES. >> >> The only functional change is iterate_bvec():lib/iov_iter.c >> >> xfstests(-a auto) over loop aio is run for ext4/xfs to verify >> the change and no regression found with this patchset. > > > Added patches 1-7, still waiting for an answer on my reply to #8. Thanks for adding patches 1-7, and now I just found the added BIO_MAX_SIZE usage in dm-crypt.c is droped from next, so it is safe to kill it now. I will send a new patch #8 against for-4.8/core. Thanks, Ming > > -- > Jens Axboe > > > -- > To unsubscribe from this list: send the line "unsubscribe linux-block" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html From jtulak@redhat.com Fri Jun 10 03:39:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6B30E7CA0 for ; Fri, 10 Jun 2016 03:39:15 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 400E68F8033 for ; Fri, 10 Jun 2016 01:39:12 -0700 (PDT) X-ASG-Debug-ID: 1465547950-04cb6c381419700001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 9BLDadEoHkJCZceF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 10 Jun 2016 01:39:11 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3DD9F461C1; Fri, 10 Jun 2016 08:39:10 +0000 (UTC) Received: from jtulak.brq.redhat.com (jtulak.brq.redhat.com [10.34.26.85]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5A8d8sx032043; Fri, 10 Jun 2016 04:39:09 -0400 From: Jan Tulak To: xfs@oss.sgi.com Cc: sandeen@sandeen.net, Jan Tulak Subject: [PATCH v3] mkfs: better error with incorrect b/s value suffix usage Date: Fri, 10 Jun 2016 10:39:00 +0200 X-ASG-Orig-Subj: [PATCH v3] mkfs: better error with incorrect b/s value suffix usage Message-Id: <1465547940-22974-1-git-send-email-jtulak@redhat.com> In-Reply-To: <1465478861-8714-1-git-send-email-jtulak@redhat.com> References: <1465478861-8714-1-git-send-email-jtulak@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Fri, 10 Jun 2016 08:39:10 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465547951 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2128 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 If user writes a value using b or s suffix without explicitly stating the size of blocks or sectors, mkfs ends with a not helpful error about the value being too small. It happens because we read the physical geometry after all options are parsed. So, tell the user exactly what is wrong with the input. Signed-off-by: Jan Tulak --- While adding entries into the mkfs input test, I found this issue, though it may be only a documentation thing. When I give some option block/sector suffix without specifying explicitly its size (for example, -l su=10b without -b size=4096), I get an error that value 10b is too small. Of course it is, because, at the time, mkfs did not read physical geometry yet, so blocksize is 0. And 10*0 = 0. I think that this is not something we need to change, but it should be better documented. Maybe not manpage (where it can be overlooked if not written to every option using the size and it might be that it already is somewhere down there), but an error message should warn the user in case of using b or s suffix incorrectly. I'm open to suggestions for a better solution, though. UPDATE: Changed error message. Thanks Eric, this sounds better. :-) Cheers, Jan Signed-off-by: Jan Tulak --- mkfs/xfs_mkfs.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index ed7800f..6059d91 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -3614,10 +3614,24 @@ cvtnum( if (sp[1] != '\0') return -1LL; - if (*sp == 'b') - return i * blksize; - if (*sp == 's') - return i * sectsize; + if (*sp == 'b') { + if (!blksize) { + fprintf(stderr, +_("Blocksize must be provided prior to using 'b' suffix.\n")); + usage(); + } else { + return i * blksize; + } + } + if (*sp == 's') { + if (!sectsize) { + fprintf(stderr, +_("Sectorsize must be specified prior to using 's' suffix.\n")); + usage(); + } else { + return i * sectsize; + } + } c = tolower(*sp); switch (c) { -- 2.5.5 From jtulak@redhat.com Fri Jun 10 04:22:00 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 499A67CA0 for ; Fri, 10 Jun 2016 04:22:00 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C5D91AC002 for ; Fri, 10 Jun 2016 02:21:59 -0700 (PDT) X-ASG-Debug-ID: 1465550517-04bdf0658019ab0001-NocioJ Received: from mail-io0-f169.google.com (mail-io0-f169.google.com [209.85.223.169]) by cuda.sgi.com with ESMTP id XmGcNTCdRHp8edFJ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 10 Jun 2016 02:21:58 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-RBL-Trusted-Forwarder: 209.85.223.169 Received: by mail-io0-f169.google.com with SMTP id o127so14606489iod.2 for ; Fri, 10 Jun 2016 02:21:58 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=xuvf/NiL8vcyYmCFBDOE2Zyj4savZUHMJ+cHmhTmtWM=; b=lSlwrGxuxXE6KapFPfD6Wuz+nti/QKu0plriDeCrbLTPZai0Qoujb86QfBG0Jrej/l Em9yezg4nz6U7FBLQ07k/g4q4PXA//2EMHOvaHtzuuOJrJF7A2MzROZsGQcDeSu5poO/ ULYKLEK0R66pgju0ZUYvjvC0UzSVCgO2RFChwqMtNZKVR7RcrCQ3bqNFuMnUqeyjszo5 AW2ovz7nLOCBVnaAxR3LgkmSpABc7Qk8TL0upbJLOoNDzCEa9oalg34tFOVSMeqqDEFV r3Rza7jiXB203+j/V8SNQn2eTdy2va9hDC9q6K85m802Tq/yj77KYhbzq9hFJvfwDYYT 5Row== X-Gm-Message-State: ALyK8tKBUExgceQNdj3LzZJNze/YtlZ2mBNqk18WDnFY51m6SWinmT/PNK+alMj5r5Qtr/8gvGQ+RkBzKlKi7TW0 X-Received: by 10.107.4.78 with SMTP id 75mr2486815ioe.52.1465550517146; Fri, 10 Jun 2016 02:21:57 -0700 (PDT) MIME-Version: 1.0 Received: by 10.36.72.70 with HTTP; Fri, 10 Jun 2016 02:21:37 -0700 (PDT) In-Reply-To: <5f6ee8a0-b704-5aa6-ff67-f7a5f6761732@sandeen.net> References: <1465479700-14111-1-git-send-email-jtulak@redhat.com> <5f6ee8a0-b704-5aa6-ff67-f7a5f6761732@sandeen.net> From: Jan Tulak Date: Fri, 10 Jun 2016 11:21:37 +0200 Message-ID: Subject: Re: [PATCH] mkfs: test that -l su is a multiple of block size To: Eric Sandeen X-ASG-Orig-Subj: Re: [PATCH] mkfs: test that -l su is a multiple of block size Cc: xfs-oss Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-io0-f169.google.com[209.85.223.169] X-Barracuda-Start-Time: 1465550518 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4078 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30317 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 9, 2016 at 6:23 PM, Eric Sandeen wrote: > > > On 6/9/16 8:41 AM, Jan Tulak wrote: >> lsunit was already tested, but lsu was not. So a thing like -l su=4097 was >> possible. This commit adds a check to fix it. >> >> Signed-off-by: Jan Tulak >> --- >> mkfs/xfs_mkfs.c | 9 +++++++++ >> 1 file changed, 9 insertions(+) >> >> diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c >> index 455bf11..b9b50fe 100644 >> --- a/mkfs/xfs_mkfs.c >> +++ b/mkfs/xfs_mkfs.c >> @@ -2875,6 +2875,15 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), >> lsunit = dsunit; >> } >> >> + if (lsu) { >> + if (lsu % blocksize != 0) { >> + fprintf(stderr, >> + _("log stripe unit (%d) must be a multiple of the block size (%d)\n"), >> + lsu, blocksize); >> + exit(1); >> + } >> + } >> + > > > Hm, I'm not quite seeing the behavior you say you're fixing; > you give the example of -l su=4097, but: > > # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=4097 > Illegal value 4097 for -l su option. value is too small > > So that's really not the relevant test case. > Well, but 4097 is not too small - 4096 should pass and few days ago, I send a patch to fix that ("mkfs: fix -l su minval"). But yeah, I didn't realized that when writing the commit message and didn't told you that. :-) > > And in these cases it is caught and does fail: > > # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=63k > log stripe unit (64512) must be a multiple of the block size (4096) > > # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=64512 > log stripe unit (64512) must be a multiple of the block size (4096) > > But in this case it does not: > > # mkfs/mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=16385 > meta-data=fsfile isize=512 agcount=4, agsize=8192 blks > = sectsz=512 attr=2, projid32bit=1 > = crc=1 finobt=1, sparse=0 > data = bsize=4096 blocks=32768, imaxpct=25 > = sunit=0 swidth=0 blks > naming =version 2 bsize=4096 ascii-ci=0 ftype=1 > log =internal log bsize=4096 blocks=552, version=2 > = sectsz=512 sunit=4 blks, lazy-count=1 > realtime =none extsz=4096 blocks=0, rtextents=0 > > So what's going on here...? It has something to do with how > calc_stripe_factors() operates, and when that happens vs. the checks. > > lsu and lsunit are really specifying the same thing, just in different > units. > > Your patch does fix it up, but I wonder if these tests are in the > wrong place; with your patch we essentially do this: > > 1) Parse lsu value > 2) Convert lsu to lsunit > 3) Check lsunit (it's ok) > 4) Go back and check lsu (it's not ok) > > It seems to me that we should recognize either lsu or lsunit > as the "one true value" and convert the other to it as soon as possible, > rather than carrying around both, and checking both at various times. > > calc_stripe_factors() does do some validity checks; perhaps it should > check against blocksize multiples as well, so it's all in one place? > And a comment about what that function is doing (converting su's to > sunit's, really) would be helpful. > > What do you think? > > Your patch does resolve the problem but I think it adds a little more > confusion to already confusing code. > I moved both the new check and the lsunit check to calc_stripe_factor(). We need to check both, though, because the entire issue stems from how lsunit is computed from lsu: *lsunit = (int)BTOBBT(lsu); So if lsu is incorrectly sized, we still get a valid lsunit. It just might be different from what user thought... Thanks for pointing it out, though. Jan -- Jan Tulak jtulak@redhat.com / jan@tulak.me From jtulak@redhat.com Fri Jun 10 04:27:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5F6F97CA0 for ; Fri, 10 Jun 2016 04:27:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 31B268F8033 for ; Fri, 10 Jun 2016 02:27:16 -0700 (PDT) X-ASG-Debug-ID: 1465550833-04cbb03f521f0e0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id hs71pt1pyxn0hUJy (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 10 Jun 2016 02:27:14 -0700 (PDT) X-Barracuda-Envelope-From: jtulak@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id CD94012B2A; Fri, 10 Jun 2016 09:27:13 +0000 (UTC) Received: from jtulak.brq.redhat.com (jtulak.brq.redhat.com [10.34.26.85]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5A9RCDC017260; Fri, 10 Jun 2016 05:27:12 -0400 From: Jan Tulak To: xfs@oss.sgi.com Cc: sandeen@sandeen.net, Jan Tulak Subject: [PATCH v2] mkfs: test that -l su is a multiple of block size Date: Fri, 10 Jun 2016 11:27:09 +0200 X-ASG-Orig-Subj: [PATCH v2] mkfs: test that -l su is a multiple of block size Message-Id: <1465550829-8066-1-git-send-email-jtulak@redhat.com> In-Reply-To: <1465479700-14111-1-git-send-email-jtulak@redhat.com> References: <1465479700-14111-1-git-send-email-jtulak@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Fri, 10 Jun 2016 09:27:13 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465550834 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1905 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 lsunit was already tested, but lsu was not. So a thing like -l su=4097 was possible. This commit adds a check to catch this, and moves the entire lsu/lsunit block size testing to calc_stripe_factors(), where already is some logic w.r.t. lsu/lsunit. Signed-off-by: Jan Tulak --- UPDATE: Moving the checks to calc_stripe_factors(). An example of previously failing options: mkfs.xfs -f -dfile,name=fsfile,size=128m -l su=16385 --- mkfs/xfs_mkfs.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 6059d91..b8f6b89 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -726,6 +726,9 @@ struct opt_params mopts = { */ #define WHACK_SIZE (128 * 1024) +/* + * Convert lsu to lsunit for 512 bytes blocks and check validity of the values. + */ static void calc_stripe_factors( int dsu, @@ -775,6 +778,20 @@ calc_stripe_factors( if (lsu) *lsunit = (int)BTOBBT(lsu); + + /* verify if lsu/lsunit is a multiple block size */ + if (lsu % blocksize != 0) { + fprintf(stderr, +_("log stripe unit (%d) must be a multiple of the block size (%d)\n"), + lsu, blocksize); + exit(1); + } + if ((BBTOB(*lsunit) % blocksize != 0)) { + fprintf(stderr, +_("log stripe unit (%d) must be a multiple of the block size (%d)\n"), + BBTOB(*lsunit), blocksize); + exit(1); + } } /* @@ -2862,12 +2879,6 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), */ if (lsunit) { - if ((BBTOB(lsunit) % blocksize != 0)) { - fprintf(stderr, - _("log stripe unit (%d) must be a multiple of the block size (%d)\n"), - BBTOB(lsunit), blocksize); - exit(1); - } /* convert from 512 byte blocks to fs blocks */ lsunit = DTOBT(lsunit); } else if (sb_feat.log_version == 2 && loginternal && dsunit) { -- 2.5.5 From bfoster@redhat.com Fri Jun 10 07:19:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 08C617CA0 for ; Fri, 10 Jun 2016 07:19:39 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id A084A304048 for ; Fri, 10 Jun 2016 05:19:38 -0700 (PDT) X-ASG-Debug-ID: 1465561177-04bdf0657f20660001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id nvRHTXCwGouYsD0k (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 10 Jun 2016 05:19:37 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7C72DC03BD54; Fri, 10 Jun 2016 12:19:37 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-12.bos.redhat.com [10.18.41.12]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5ACJaZ7012012; Fri, 10 Jun 2016 08:19:37 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 8C1551230F3; Fri, 10 Jun 2016 08:19:36 -0400 (EDT) Date: Fri, 10 Jun 2016 08:19:36 -0400 From: Brian Foster To: Eric Sandeen Cc: xfs@oss.sgi.com Subject: Re: [PATCH 0/4] xfs: online relabeling [RFC] Message-ID: <20160610121936.GC21568@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 0/4] xfs: online relabeling [RFC] References: <2305b486-f336-6d1e-9420-b69dc5bdc572@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <2305b486-f336-6d1e-9420-b69dc5bdc572@sandeen.net> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 10 Jun 2016 12:19:37 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465561177 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2011 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 09, 2016 at 11:51:12AM -0500, Eric Sandeen wrote: > > > On 6/9/16 11:36 AM, Eric Sandeen wrote: > > Ok, this more or less works; not really up to snuff > > for submission or merging, just sketching it out, but some > > questions first: > > > > 1) Is there really any point to this? :) We did have one > > request, and btrfs can do it ... > > Seems reasonable to me. Any details on the use case for the request? > > 2) Is using m_growlock horrible? growfs is the only other > > thing that writes all supers, so I grabbed it. We don't > > want multiple relabels stepping on each other. > > > > 3) Is there some way to actually force the primary to disk? > > Right now the label change isn't actually visible on the > > primary until unmount, which defeats the purpose. I'm not > > sure if there's a straightforward/safe way to make it > > visible... > > Oh, sorry - I guess it is getting written out, but it's only > available via an O_DIRECT read from userspace; it's not > invalidating the cache. > > # io/xfs_io -c "label derp" /mnt/test > label = "derp" > > # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C > ... > 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| > ... > > # dd if=/dev/sdb2 iflag=direct bs=512 count=1 | hexdump -C > ... > 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 64 65 72 70 |............derp| > ... > > # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C > ... > 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| > ... > > Guess I need to think about this some more. > Isn't this to be expected? You're directly accessing the block device of a mounted filesystem. I would think this is expected behavior, so long as the set/get interfaces through the fs are consistent. Brian > -Eric > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Fri Jun 10 07:19:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2E3A07CA1 for ; Fri, 10 Jun 2016 07:19:39 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id F3F52304053 for ; Fri, 10 Jun 2016 05:19:35 -0700 (PDT) X-ASG-Debug-ID: 1465561173-04cb6c381320530001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id yAlffDgrxOH5VFUF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 10 Jun 2016 05:19:34 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 86A4583F45; Fri, 10 Jun 2016 12:19:33 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-12.bos.redhat.com [10.18.41.12]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5ACJXRt027232; Fri, 10 Jun 2016 08:19:33 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id DAB971230F3; Fri, 10 Jun 2016 08:19:32 -0400 (EDT) Date: Fri, 10 Jun 2016 08:19:32 -0400 From: Brian Foster To: Eric Sandeen Cc: xfs@oss.sgi.com Subject: Re: [PATCH 3/4] xfs: implement online get/set fs label Message-ID: <20160610121931.GB21568@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 3/4] xfs: implement online get/set fs label References: <67255993-9730-2872-675f-ac5cb518a338@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <67255993-9730-2872-675f-ac5cb518a338@sandeen.net> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Fri, 10 Jun 2016 12:19:33 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465561174 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3533 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 09, 2016 at 11:41:07AM -0500, Eric Sandeen wrote: > Wire up label ioctls for XFS. > > Signed-off-by: Eric Sandeen > --- > > This is where the implementation questions come in; > is using growlock an abomination? How can I make the > primary super change immediately visible? > > fs/xfs/xfs_ioctl.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 files changed, 62 insertions(+), 0 deletions(-) > > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c > index dbca737..ab59213 100644 > --- a/fs/xfs/xfs_ioctl.c > +++ b/fs/xfs/xfs_ioctl.c > @@ -41,6 +41,8 @@ > #include "xfs_trans.h" > #include "xfs_pnfs.h" > #include "xfs_acl.h" > +#include "xfs_log.h" > +#include "xfs_sb.h" > > #include > #include > @@ -1603,6 +1605,62 @@ xfs_ioc_swapext( > return error; > } > > +static int > +xfs_ioc_getlabel( > + struct xfs_mount *mp, > + char __user *label) > +{ > + int error = 0; > + struct xfs_sb *sbp = &mp->m_sb; > + > + if (!mutex_trylock(&mp->m_growlock)) > + return -EWOULDBLOCK; > + if (copy_to_user(label, sbp->sb_fname, sizeof(sbp->sb_fname))) > + error = -EFAULT; > + mutex_unlock(&mp->m_growlock); > + return error; > +} > + > +static int > +xfs_ioc_setlabel( > + struct file *filp, > + struct xfs_mount *mp, > + char __user *newlabel) > +{ > + int error; > + struct xfs_sb *sbp = &mp->m_sb; > + char sb_fname[12]; > + > + if (!capable(CAP_SYS_ADMIN)) > + return -EPERM; > + > + if (copy_from_user(sb_fname, newlabel, sizeof(sb_fname))) > + return -EFAULT; > + > + error = mnt_want_write_file(filp); > + if (error) > + return error; > + > + /* growfs & label both muck w/ the super directly... */ > + if (!mutex_trylock(&mp->m_growlock)) > + return -EWOULDBLOCK; Why the trylock here? It seems like we can still block in other places (e.g., mnt_want_write_file() above). > + memset(sbp->sb_fname, 0, sizeof(sbp->sb_fname)); > + strncpy(sbp->sb_fname, sb_fname, sizeof(sbp->sb_fname)); > + So m_growlock excludes grow and nothing else looks like it mucks with sb_fname, but what about any other invocations of xfs_log_sb()? For example, is there a risk here of somebody else logging the superblock buffer based on a transiently zeroed mp->m_sb.sb_fname? (In fact, xfs_log_sb() looks kind of racy to me, but maybe I'm missing something.) Perhaps we need an xfs_trans_getsb() somewhere in here..? Brian > + error = xfs_sync_sb(mp, true); > + if (error) > + goto out; > + /* > + * Most kernelspace superblock updates only update sb 0. > + * Userspace relabel has always updated all, though, so: > + */ > + error = xfs_update_secondary_supers(mp, sbp->sb_agcount, 0); > +out: > + mutex_unlock(&mp->m_growlock); > + mnt_drop_write_file(filp); > + return error; > +} > + > /* > * Note: some of the ioctl's return positive numbers as a > * byte count indicating success, such as readlink_by_handle. > @@ -1630,6 +1688,10 @@ xfs_file_ioctl( > switch (cmd) { > case FITRIM: > return xfs_ioc_trim(mp, arg); > + case FS_IOC_GET_FSLABEL: > + return xfs_ioc_getlabel(mp, arg); > + case FS_IOC_SET_FSLABEL: > + return xfs_ioc_setlabel(filp, mp, arg); > case XFS_IOC_ALLOCSP: > case XFS_IOC_FREESP: > case XFS_IOC_RESVSP: > -- > 1.7.1 > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From info@lotto.com Fri Jun 10 08:37:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.2 required=5.0 tests=FREEMAIL_FORGED_REPLYTO autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0D73D7CA0 for ; Fri, 10 Jun 2016 08:37:42 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id ACF3D8F8035 for ; Fri, 10 Jun 2016 06:37:40 -0700 (PDT) X-ASG-Debug-ID: 1465565853-04bdf0657f22690001-NocioJ Received: from mail-bt.elsaco.com (mail-bt.elsaco.com [92.87.31.148]) by cuda.sgi.com with ESMTP id bX7lzGxrqJr4SQCe (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 10 Jun 2016 06:37:35 -0700 (PDT) X-Barracuda-Envelope-From: info@lotto.com X-Barracuda-Effective-Source-IP: mail-bt.elsaco.com[92.87.31.148] X-Barracuda-Apparent-Source-IP: 92.87.31.148 Received: from webmail.elsaco.com (webmail.elsaco.com [10.11.31.30]) by mail-bt.elsaco.com (8.13.8/8.13.8) with ESMTP id u5ADajvt020095 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 10 Jun 2016 16:36:45 +0300 Received: from localhost (localhost [127.0.0.1]) by webmail.elsaco.com (Postfix) with ESMTP id 5D132BDEC96; Fri, 10 Jun 2016 16:17:05 +0300 (EEST) Received: from webmail.elsaco.com ([127.0.0.1]) by localhost (webmail.elsaco.com [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id QrYme6U1Vkv7; Fri, 10 Jun 2016 16:17:04 +0300 (EEST) Received: from localhost (localhost [127.0.0.1]) by webmail.elsaco.com (Postfix) with ESMTP id 867ADBDEFB1; Fri, 10 Jun 2016 16:17:03 +0300 (EEST) X-Virus-Scanned: amavisd-new at elsaco.com Received: from webmail.elsaco.com ([127.0.0.1]) by localhost (webmail.elsaco.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id ey3dYJIXnCEl; Fri, 10 Jun 2016 16:17:03 +0300 (EEST) Received: from [89.163.154.139] (unknown [89.163.154.139]) by webmail.elsaco.com (Postfix) with ESMTPSA id 6960EBDE91D; Fri, 10 Jun 2016 16:16:41 +0300 (EEST) Content-Type: multipart/mixed; boundary="===============1090232603==" MIME-Version: 1.0 Subject: Powered by Google. To: Recipients X-ASG-Orig-Subj: Powered by Google. From: "Google Incorporation" Date: Fri, 10 Jun 2016 06:18:36 -0700 Reply-To: svp.jonesbradley@yandex.com Message-Id: <20160610131641.6960EBDE91D@webmail.elsaco.com> X-Barracuda-Connect: mail-bt.elsaco.com[92.87.31.148] X-Barracuda-Start-Time: 1465565855 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 52 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_DOMAIN_MATCH X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30321 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient Domain You will not see this in a MIME-aware mail reader. --===============1090232603== Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body Dear Google User, You have been selected as a Google Ambassador for using Google services. Fi= nd attached letter for more details and Processing of your claims. Best Regards, Matt Brittin Chairman of the Board and Managing Director, Google United Kingdom --===============1090232603== Content-Type: application/pdf MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="2016 Google Notification Document.pdf" JVBERi0xLjUNCiW1tbW1DQoxIDAgb2JqDQo8PC9UeXBlL0NhdGFsb2cvUGFnZXMgMiAwIFIvTGFu Zyhlbi1VUykgL1N0cnVjdFRyZWVSb290IDI1IDAgUi9NYXJrSW5mbzw8L01hcmtlZCB0cnVlPj4+ Pg0KZW5kb2JqDQoyIDAgb2JqDQo8PC9UeXBlL1BhZ2VzL0NvdW50IDIvS2lkc1sgMyAwIFIgMTUg MCBSXSA+Pg0KZW5kb2JqDQozIDAgb2JqDQo8PC9UeXBlL1BhZ2UvUGFyZW50IDIgMCBSL1Jlc291 cmNlczw8L1hPYmplY3Q8PC9JbWFnZTUgNSAwIFIvSW1hZ2U4IDggMCBSPj4vRm9udDw8L0YxIDYg MCBSL0YyIDkgMCBSL0YzIDExIDAgUi9GNCAxMyAwIFI+Pi9Qcm9jU2V0Wy9QREYvVGV4dC9JbWFn ZUIvSW1hZ2VDL0ltYWdlSV0gPj4vTWVkaWFCb3hbIDAgMCA2MTIgNzkyXSAvQ29udGVudHMgNCAw IFIvR3JvdXA8PC9UeXBlL0dyb3VwL1MvVHJhbnNwYXJlbmN5L0NTL0RldmljZVJHQj4+L1RhYnMv Uy9TdHJ1Y3RQYXJlbnRzIDA+Pg0KZW5kb2JqDQo0IDAgb2JqDQo8PC9GaWx0ZXIvRmxhdGVEZWNv ZGUvTGVuZ3RoIDM5NTY+Pg0Kc3RyZWFtDQp4nK0b2W7bSPI9QP6hH6WFTbG7eQaDWTgZO5nJxM5k FASDZB9kHTY3ElsjUvbO/s7+6FZVsyUeKkpaLIIoEllVXVfX1Z3R1abMFpNpKX74YXRVlpPp43wm vo7GZv2P0fiv9Xz0cfKQ5ZMyM/no9+19iY/ezSez+ebHH8Xrn96IP1++CMPIC4UPf5SU8E3FXgyf qe+pUExXL1+Mfl5NHuah+MmI316+eD2GJzdSAKwfiPHi5QtJyFLEyvNVIOIg9KJEjAHTFw/48fbl i68DMfyHGP/y8sU14MOqQElcf3gjRowIr01ZmhUvxY0x5U4K5KnFRZDQP8gFu7YYfcRVP7z5+Sfh 7xWifZ9opT4QE5H2a1pIKi108GWNldGNOqAejZzFIlKplyYHGOuQVA2SWkh1SN2RTLw0qNTtexqM 5ntBGIrNQ/vJJzLE22EyMOZhORefh5fh4D38FL8OL9WgnNW4qatUhr4XqfpKRzjXvF0iP/SkI/Ia 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 IDM3MS9IZWlnaHQgMTQxL0NvbG9yU3BhY2UvRGV2aWNlUkdCL0JpdHNQZXJDb21wb25lbnQgOC9J bnRlcnBvbGF0ZSBmYWxzZS9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDE3ODg2Pj4NCnN0cmVh bQ0KeJzsnQl32swOhv//jwv7asD7vmAwm/GmK2nsJO2XtEAIyW2sM4dD05Y48fiZVxqNBNBaa621 1lprrbXWWmuttdZaa6211lprrbXWWmuttdZaa6211lprrbXWWmuttdZaa6211lprrbXWWmuttdZa a6211lprrV1hBVQFwBmKFPIjjewA2R6yHZwTGukGjls4xrCPqiQ6b7/6eltrrbVvbQnsY0jWkLgQ WuDjMMHTwcWhgauAswJrCeayMqSTOkvkeSSfIP/qq26ttda+qYWwdsDzIbLAM8CxiSqIFFsFUwVD AUMGbQHKFBaTShruxuN4qh7Ur77qf8cqgLSCfQHbHOIzxCmNDb/Gp/p9ktE/OEGL8ta+u+F8jgpE imuApYGBwwDbYJ4wTIwVaCtQcSxAnoE0qMaD03AYD+frWQqnM6Rf/RP8X1oJsK8gTME/gH8E7wDe HtznsQMHR/Iy8Cu++Dc7+sfiv+ArfjE8weYMR76VrbX2HWxX7oNjGJwDt3Cs3DRSw8gtrTKYJKhP ECaqREOZwwq1yqia9k/DbtwfesMEkrSlypV2qmCdQnQCnxFhJ2BtwdyAEYMe8+uahvGfYcY06H1M /8vegcWv7gGClCCDnxYcIdhDuINdDsVX/6SttYaWQXqCwxEOO9hHEC9zeQ7LMUg8FjhGMB9Uk146 7Gx7Hb8nhVIK56++6v8bQ+clOtLAB99LaNgxDQtBEb4aQTP8l6Hz0DzQ8esRmGt61UN6tZlIyCVn X2seZAtRa8cjgTAh96q11r7OqpJXuRKqM+TzdDkFCWEypDHD1wFM+/m4c+g/xd2u19MSvWhXxb8Z /oLiHIITiwqUKOjUbAkmeoML5Ibpgx2Cv4F1AvEekuPL2B5hc6CBX0dEuGv695oLutcwJyDC1GIm JvHjsApC1wm/HQ2UMQcizPqAa0drrX2xrXJlRkKFqEJIgSmDZdTZ9Z+iXs8beJn/1df4ra0ESHKI M/BPYKC/swNjQz6OGoDGmsReQ7AldBxRLOaQ5ZCXFCSp/hMqqfjTcsYUvh5zQk2AKiUE3QXVZbwE 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 WMB41EPiCaGnDfm2O/eXWtoGvY6cx9RNugvqR5kYS0hI3B5ZzUwXx4qN3l6Ku9oZ5IVqUAxDrmR3 5JYtt9qEGAm9gzPLzYr6v+MyJyEh8SvsjxAk1Bb5LJskbQ2xirbHZR3JL9XHestmjxdJtwXkOsAn 6FDm4liQZlW2V1ftLVW7JSQkvgrALYbdoXg1cYu6FQ7g8AgLghZcB7L8PuKQ0U1wvODU4QZtWNHA V9vU3oncrGQSJCHxp8DZVZttY6IzJk43Q9zCPXmF5fdBuH47R0Ev0UfF84GWTin+BMfHNjx4xs2W GVZ+OmO1VoYqEhJ/GIIQ4pbCcBokFr640zfFLWYg+kwgetmekGEc+uKQsKT5vTRu0WCIsidDecun Yg7q1KE1587vigod1GVZRULij0RaMsertE2m2w139+Yko20xeuFtsbzLxSS7Vc4w7ontQlonpA4v whGk7Rk1GfZnHJSGlMelCu2GenrRAxEN4mvHr48xCvXL9EdC4s8GJCPwYd/sIHSp1k7zmls0imGE /2l/O2z21V37ICTgNuSXalArL5882tAyabQQVVa27fbQhQm6hMteFQmJvwdAL+GF2UAvdq6amWbX mt3qvPzi4EJdXBF7CBlJIBy8sN4h4VyV9tf0O+auWzu1bhfAJ0HMLgVmRnL0T0LirwXkKVHK9kFr bgvdghSpWNu1btWa1WiQLjkdUM3a7dcWsyfVZiubwpstcFFluoV7qE4x5llZhZRSyRKthIQEBTAQ YJQ1i1MWhO3h1HrHduuVjlfaXmHtC2tX2PvK8Rs3wKKKf2JhjN+cFVg/qRu0KJI9bxISEv8HwDNN h1QDsQd2nsDqcMHXPCDhNCKZREJCQkJCQkJCQkJCQkJCQkJCQkJC4m/A/wB3vg0uDQplbmRzdHJl YW0NCmVuZG9iag0KNiAwIG9iag0KPDwvVHlwZS9Gb250L1N1YnR5cGUvVHJ1ZVR5cGUvTmFtZS9G MS9CYXNlRm9udC9BQkNERUUrQ2FsaWJyaS9FbmNvZGluZy9XaW5BbnNpRW5jb2RpbmcvRm9udERl c2NyaXB0b3IgNyAwIFIvRmlyc3RDaGFyIDMyL0xhc3RDaGFyIDMyL1dpZHRocyAxMDYgMCBSPj4N CmVuZG9iag0KNyAwIG9iag0KPDwvVHlwZS9Gb250RGVzY3JpcHRvci9Gb250TmFtZS9BQkNERUUr Q2FsaWJyaS9GbGFncyAzMi9JdGFsaWNBbmdsZSAwL0FzY2VudCA3NTAvRGVzY2VudCAtMjUwL0Nh cEhlaWdodCA3NTAvQXZnV2lkdGggNTIxL01heFdpZHRoIDE3NDMvRm9udFdlaWdodCA0MDAvWEhl aWdodCAyNTAvU3RlbVYgNTIvRm9udEJCb3hbIC01MDMgLTI1MCAxMjQwIDc1MF0gL0ZvbnRGaWxl MiAxMDcgMCBSPj4NCmVuZG9iag0KOCAwIG9iag0KPDwvVHlwZS9YT2JqZWN0L1N1YnR5cGUvSW1h Z2UvV2lkdGggMzcxL0hlaWdodCAxNDEvQ29sb3JTcGFjZS9EZXZpY2VSR0IvQml0c1BlckNvbXBv bmVudCA4L0ZpbHRlci9EQ1REZWNvZGUvSW50ZXJwb2xhdGUgdHJ1ZS9MZW5ndGggODE1MT4+DQpz dHJlYW0NCv/Y/+AAEEpGSUYAAQEBAGAAYAAA/9sAQwAIBgYHBgUIBwcHCQkICgwUDQwLCwwZEhMP FB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJCQkMCwwYDQ0YMiEc ITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy/8AAEQgA jQFzAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkKC//EALUQAAIBAwMC BAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNicoIJChYXGBkaJSYn KCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SFhoeIiYqSk5SVlpeY mZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn6Onq8fLz9PX29/j5 +v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQEAwQHBQQEAAECdwAB AgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBkaJicoKSo1Njc4OTpD REVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ip 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 igAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKK ACiiigClqemWurWMlndxLJE4wQR+teRa98L9QsZWl0uTzoc5CP1HtmvaqMVvQxNSi/cZE4RlufN3 9na7p0oLWU6up4aM8j6YNa9t4p8X2yhI5b8gf31LfzFe6PbQS/6yJG+oqP8As2yzn7LF/wB812PM 5S+OCZl9XS2Z42Nd8c6gNiz3CBu+Qn8hmrmm/D3VNVuBcarPI+TklyefqTya9cS2giHyRIv0Wpaw ljqjVoJR9EWqMVvqZei6DZ6LbrHboNwGN2Mfl6Vq0UVxttu7NQooooAKKKKACiiigAooooAKKKKA CiiigD//2Q0KZW5kc3RyZWFtDQplbmRvYmoNCjkgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBl L1RydWVUeXBlL05hbWUvRjIvQmFzZUZvbnQvVGltZXMjMjBOZXcjMjBSb21hbi9FbmNvZGluZy9X aW5BbnNpRW5jb2RpbmcvRm9udERlc2NyaXB0b3IgMTAgMCBSL0ZpcnN0Q2hhciAzMi9MYXN0Q2hh ciAxNjMvV2lkdGhzIDExMSAwIFI+Pg0KZW5kb2JqDQoxMCAwIG9iag0KPDwvVHlwZS9Gb250RGVz Y3JpcHRvci9Gb250TmFtZS9UaW1lcyMyME5ldyMyMFJvbWFuL0ZsYWdzIDMyL0l0YWxpY0FuZ2xl IDAvQXNjZW50IDg5MS9EZXNjZW50IC0yMTYvQ2FwSGVpZ2h0IDY5My9BdmdXaWR0aCA0MDEvTWF4 V2lkdGggMjU2OC9Gb250V2VpZ2h0IDQwMC9YSGVpZ2h0IDI1MC9MZWFkaW5nIDQyL1N0ZW1WIDQw L0ZvbnRCQm94WyAtNTY4IC0yMTYgMjAwMCA2OTNdID4+DQplbmRvYmoNCjExIDAgb2JqDQo8PC9U eXBlL0ZvbnQvU3VidHlwZS9UcnVlVHlwZS9OYW1lL0YzL0Jhc2VGb250L1RpbWVzIzIwTmV3IzIw Um9tYW4sQm9sZC9FbmNvZGluZy9XaW5BbnNpRW5jb2RpbmcvRm9udERlc2NyaXB0b3IgMTIgMCBS L0ZpcnN0Q2hhciAzMi9MYXN0Q2hhciAxMTgvV2lkdGhzIDExMiAwIFI+Pg0KZW5kb2JqDQoxMiAw IG9iag0KPDwvVHlwZS9Gb250RGVzY3JpcHRvci9Gb250TmFtZS9UaW1lcyMyME5ldyMyMFJvbWFu LEJvbGQvRmxhZ3MgMzIvSXRhbGljQW5nbGUgMC9Bc2NlbnQgODkxL0Rlc2NlbnQgLTIxNi9DYXBI ZWlnaHQgNjc3L0F2Z1dpZHRoIDQyNy9NYXhXaWR0aCAyNTU4L0ZvbnRXZWlnaHQgNzAwL1hIZWln aHQgMjUwL0xlYWRpbmcgNDIvU3RlbVYgNDIvRm9udEJCb3hbIC01NTggLTIxNiAyMDAwIDY3N10g Pj4NCmVuZG9iag0KMTMgMCBvYmoNCjw8L1R5cGUvRm9udC9TdWJ0eXBlL1RydWVUeXBlL05hbWUv RjQvQmFzZUZvbnQvQXJpYWwvRW5jb2RpbmcvV2luQW5zaUVuY29kaW5nL0ZvbnREZXNjcmlwdG9y IDE0IDAgUi9GaXJzdENoYXIgMzIvTGFzdENoYXIgMzIvV2lkdGhzIDExMyAwIFI+Pg0KZW5kb2Jq DQoxNCAwIG9iag0KPDwvVHlwZS9Gb250RGVzY3JpcHRvci9Gb250TmFtZS9BcmlhbC9GbGFncyAz Mi9JdGFsaWNBbmdsZSAwL0FzY2VudCA5MDUvRGVzY2VudCAtMjEwL0NhcEhlaWdodCA3MjgvQXZn V2lkdGggNDQxL01heFdpZHRoIDI2NjUvRm9udFdlaWdodCA0MDAvWEhlaWdodCAyNTAvTGVhZGlu ZyAzMy9TdGVtViA0NC9Gb250QkJveFsgLTY2NSAtMjEwIDIwMDAgNzI4XSA+Pg0KZW5kb2JqDQox NSAwIG9iag0KPDwvVHlwZS9QYWdlL1BhcmVudCAyIDAgUi9SZXNvdXJjZXM8PC9YT2JqZWN0PDwv SW1hZ2UxNyAxNyAwIFIvSW1hZ2UyMyAyMyAwIFI+Pi9Gb250PDwvRjEgNiAwIFIvRjIgOSAwIFIv RjQgMTMgMCBSL0Y1IDE4IDAgUi9GMyAxMSAwIFI+Pi9Qcm9jU2V0Wy9QREYvVGV4dC9JbWFnZUIv SW1hZ2VDL0ltYWdlSV0gPj4vTWVkaWFCb3hbIDAgMCA2MTIgNzkyXSAvQ29udGVudHMgMTYgMCBS L0dyb3VwPDwvVHlwZS9Hcm91cC9TL1RyYW5zcGFyZW5jeS9DUy9EZXZpY2VSR0I+Pi9UYWJzL1Mv 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 PBfkWKQfNe/hXAZKdAExZLSA69/ehksG6db5vs34fKFDrT2ie3APEiFjnFS1j+whvA+XDJNA78Pl wbjz9/8R1sNShI+uthTr3Y3zj2i3GfTT40uMoJ2uXfVadU/riQ9Cjyy+RU8PSg+3dr0/1c6GIba7 3r32XStoWEWKrpvgTISnNvXg21RQZkDS4gFO5ANoat2khNaiQEf2Nm1wa4AHwk4YCMic0AIrad++ ggZJbTBKppogbk0iRlqRTXSCqMLPUMIXYUsa2Oj4Fg17lj0Mp8iL4wsNLzqMswpONuD20l/BEIG7 z9pFok4ifHXPq5cq9B+rG53IBtqOcjY4D9fOBsQj/33rXoPEZzyVoGJJQjvI6iyY3AHjNa2+k3o0 czSBleiPorAS37EkIojcmETXn+3Ske4Mn9LjzXbpCGeGT+n3Zd9qnytXLB3ryZbyoxzZUne0H/vU 4RR8nEqcKe3SicN4uFIchEfue5Yplf0XjvpdYA0KZW5kc3RyZWFtDQplbmRvYmoNCjE3IDAgb2Jq DQo8PC9UeXBlL1hPYmplY3QvU3VidHlwZS9JbWFnZS9XaWR0aCAzNzEvSGVpZ2h0IDE0MS9Db2xv clNwYWNlL0RldmljZVJHQi9CaXRzUGVyQ29tcG9uZW50IDgvSW50ZXJwb2xhdGUgZmFsc2UvRmls dGVyL0ZsYXRlRGVjb2RlL0xlbmd0aCAxNzg4Nj4+DQpzdHJlYW0NCnic7J0Jd9rMDob//48L+2rA +75gMJvxpitp7CTtl7RACMltrDOHQ9OWOPH4mVcajQTQWmuttdZaa6211lprrbXWWmuttdZaa621 1lprrbXWWmuttdZaa6211lprrbXWWmuttdZaa6211lprrbXWWmuttdZaa61dYQVUBcAZihTyI43s ANkesh2cExrpBo5bOMawj6okOm+/+npba621b20J7GNI1pC4EFrg4zDB08HFoYGrgLMCawnmsjKk kzpL5HkknyD/6qturbXWvqmFsHbA8yGywDPAsYkqiBRbBVMFQwFDBm0ByhQWk0oa7sbjeKoe1K++ 6n/HKoC0gn0B2xziM8QpjQ2/xqf6fZLRPzhBi/LWvrvhfI4KRIprgKWBgcMA22CeMEyMFWgrUHEs QJ6BNKjGg9NwGA/n61kKpzOkX/0T/F9aCbCvIEzBP4B/BO8A3h7c57EDB0fyMvArvvg3O/rH4r/g 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 IeFclfbX9Dvmrls7tW4XwCdBzC4FZkZy9E9C4q8F5ClRyvZBa24L3YIUqVjbtW7VmtVokC45HVDN 2u3XFrMn1WYrm8KbLXBRZbqFe6hOMeZZWYWUUskSrYSEBAUwEGCUNYtTFoTt4dR6x3brlY5X2l5h 7QtrV9j7yvEbN8Ciin9iYYzfnBVYP6kbtCiSPW8SEhL/B8AzTYdUA7EHdp7A6nDB1zwg4TQimURC QkJCQkJCQkJCQkJCQkJCQkJCQuJvwP8Ad74NLg0KZW5kc3RyZWFtDQplbmRvYmoNCjE4IDAgb2Jq DQo8PC9UeXBlL0ZvbnQvU3VidHlwZS9UeXBlMC9CYXNlRm9udC9UaW1lcyMyME5ldyMyMFJvbWFu L0VuY29kaW5nL0lkZW50aXR5LUgvRGVzY2VuZGFudEZvbnRzIDE5IDAgUi9Ub1VuaWNvZGUgMTA4 IDAgUj4+DQplbmRvYmoNCjE5IDAgb2JqDQpbIDIwIDAgUl0gDQplbmRvYmoNCjIwIDAgb2JqDQo8 PC9CYXNlRm9udC9UaW1lcyMyME5ldyMyMFJvbWFuL1N1YnR5cGUvQ0lERm9udFR5cGUyL1R5cGUv Rm9udC9DSURUb0dJRE1hcC9JZGVudGl0eS9EVyAxMDAwL0NJRFN5c3RlbUluZm8gMjEgMCBSL0Zv bnREZXNjcmlwdG9yIDIyIDAgUi9XIDExMCAwIFI+Pg0KZW5kb2JqDQoyMSAwIG9iag0KPDwvT3Jk ZXJpbmcoSWRlbnRpdHkpIC9SZWdpc3RyeShBZG9iZSkgL1N1cHBsZW1lbnQgMD4+DQplbmRvYmoN CjIyIDAgb2JqDQo8PC9UeXBlL0ZvbnREZXNjcmlwdG9yL0ZvbnROYW1lL1RpbWVzIzIwTmV3IzIw Um9tYW4vRmxhZ3MgMzIvSXRhbGljQW5nbGUgMC9Bc2NlbnQgODkxL0Rlc2NlbnQgLTIxNi9DYXBI ZWlnaHQgNjkzL0F2Z1dpZHRoIDQwMS9NYXhXaWR0aCAyNTY4L0ZvbnRXZWlnaHQgNDAwL1hIZWln aHQgMjUwL0xlYWRpbmcgNDIvU3RlbVYgNDAvRm9udEJCb3hbIC01NjggLTIxNiAyMDAwIDY5M10g L0ZvbnRGaWxlMiAxMDkgMCBSPj4NCmVuZG9iag0KMjMgMCBvYmoNCjw8L1R5cGUvWE9iamVjdC9T dWJ0eXBlL0ltYWdlL1dpZHRoIDExMTUvSGVpZ2h0IDMwOS9Db2xvclNwYWNlL0RldmljZVJHQi9C aXRzUGVyQ29tcG9uZW50IDgvRmlsdGVyL0RDVERlY29kZS9JbnRlcnBvbGF0ZSB0cnVlL0xlbmd0 aCA1MDA0Nz4+DQpzdHJlYW0NCv/Y/+AAEEpGSUYAAQEBAGAAYAAA/9sAQwAIBgYHBgUIBwcHCQkI CgwUDQwLCwwZEhMPFB0aHx4dGhwcICQuJyAiLCMcHCg3KSwwMTQ0NB8nOT04MjwuMzQy/9sAQwEJ CQkMCwwYDQ0YMiEcITIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy MjIyMjIy/8AAEQgBNQRbAwEiAAIRAQMRAf/EAB8AAAEFAQEBAQEBAAAAAAAAAAABAgMEBQYHCAkK C//EALUQAAIBAwMCBAMFBQQEAAABfQECAwAEEQUSITFBBhNRYQcicRQygZGhCCNCscEVUtHwJDNi coIJChYXGBkaJSYnKCkqNDU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6g4SF hoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2drh4uPk5ebn 6Onq8fLz9PX29/j5+v/EAB8BAAMBAQEBAQEBAQEAAAAAAAABAgMEBQYHCAkKC//EALURAAIBAgQE AwQHBQQEAAECdwABAgMRBAUhMQYSQVEHYXETIjKBCBRCkaGxwQkjM1LwFWJy0QoWJDThJfEXGBka JicoKSo1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoKDhIWGh4iJipKTlJWW l5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uLj5OXm5+jp6vLz9PX29/j5 +v/aAAwDAQACEQMRAD8A9/ooopAFFFFABRRRQAUUUUAFFGaM0AFFFGaACiiigAoozRQAUUUUAFFF FABRSZpc0AFFFFABSYpaKACiiigAooopgFFFFABRRRSAKKM0UAFFITgUZoACOlLTPMXfs3DfjO3P OKdmgBaKTdSBgRkcj2oAdRSE0A0ALRRRTAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiig 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 bgMHGKrmVrjuc1oJl8L/ABJFv4gnRPtmkQQ2tzK2FZolQOgY9ywZsZ9PUVl6ksZt/iLqlrKq6TdF IYXyAs8yj94UPfDbunXJ9K9jvNPs9Rg8i9tYLmLOfLmjDrn1wRSSadZy26W8lrA8EeNkbRgquBjg Y44yKSqa3FzHmep6vZ2fwk0h3srS+jeKyhHnpvhhbYDvkA5wpB47k47mo9G1Swi+LkTnXH1Q3OkC BLraGEspmHyxiNcbRtJ4yBtfcchjXpcOj2SW725tYTC5OYwgCsD1yBwanjsbWJ0eO2iRo08tCqAF U/uj0HA4oc0HMeT+E9VsLf4feJdLmuES9Q3zSQt95BjHzf3ckgDPU5Azg1nm5Nr4T+HusMRJpem3 G29I+YRMxUKzY6bfm/EjuRXs7abZOJd1pAwlYNJmMfOR0J45NLHYWkMMkMVtCkUmd8axgK3GOQBz xxRzoLnneq3EGq/FDw5dabNC/wBitppbyeJwyJCwIQMw45JbH1z71zWlXls3wr8YD7TAd99clf3g +bITGOec4OK9gt9C060ga3trSGGB87oYolVGz1yoGDTm0XTGUqbC1x1/1K9fXp9aftEPmRzfhfxH pVj4c8K6fc3saXN9Zwx2yYLb2WJNwyBgHJxzjniuyBzVKLSLGGSJ47WFWhLNGREo2EjBK8cE98da vAYrJ2epLFooooEFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFGKACiiikAUUUUAFFFFABRRRTAK KKKACiiigAooooAKKKKACiiigAooopAFFFFMAooooAKKKKACiiigAooooAKKKKACiiigAooooAKK KKQBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAUUU UAFFFFABRRRTAKKKKACiiigAooooAKTNFFJiCloopoYUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAU UUUAFFFFABRRRSAKKKKACgjNFFACY96AKKKAFpGOFJoooAAcgGloooAKKKKACg0UUAJjikAwaKKA HUUUUAFFFFABSZoooAWjNFFACZozRRQAtFFFMAooooAKKKKACiiigAooooAKKKKACiiigAooooAK KKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiikAUG iigAzRmiigAzRmiigAooopgf/9kNCmVuZHN0cmVhbQ0KZW5kb2JqDQoyNCAwIG9iag0KPDwvQXV0 aG9yKE1hcm8pIC9DcmVhdG9yKP7/AE0AaQBjAHIAbwBzAG8AZgB0AK4AIABXAG8AcgBkACAAMgAw ADEAMykgL0NyZWF0aW9uRGF0ZShEOjIwMTYwNjA4MDcyNDQ4KzAxJzAwJykgL01vZERhdGUoRDoy MDE2MDYwODA3MjQ0OCswMScwMCcpIC9Qcm9kdWNlcij+/wBNAGkAYwByAG8AcwBvAGYAdACuACAA VwBvAHIAZAAgADIAMAAxADMpID4+DQplbmRvYmoNCjMyIDAgb2JqDQo8PC9UeXBlL09ialN0bS9O IDgwL0ZpcnN0IDYyNi9GaWx0ZXIvRmxhdGVEZWNvZGUvTGVuZ3RoIDEyNDQ+Pg0Kc3RyZWFtDQp4 nMVYTU8bSRC9R8p/qOPuITv9/RFFkbIh0UYEhDCrPcQ5ODBrvBiPNQxS+Pf72tWAQ2Y8uC+REOXp 6feqq+r112hBgrQmqSypSNI70oaUjqRTA96lBknak46KdCBjNH6SiYaMIGss4bWNjowiZzzhtYt4 b8hbSXgdhCbjKFj09BQFugSKNlGQFBJgAes0WUVSSgtOWOfJpmEptDvYAF+WpMZ4bICNaPckDUgc 8FagHXzWYRTgcRLtEtZbjApxabSDz4dADnwBA3Pgi0KSA18EKVwqITFuAevRHklJ5ckr2IB2SUql mJONaNekDMbngTPwg9wpqyXihg2RfCDlUuTo72JAIkh5BOfBG6SiAN4AJwE8UUmCC9BqZIq0QD0C Ui9AHpB7ieJg6FqCDNRaoUqpOgovI8qjMa5Un5QX/GkDv6iQNihFBJ9FclEj7YQlDF07xIshaY/8 SwEin7KEZOggwQgPAcxSgDKmOqQaCuRYilT2lGmRCi9TCLAuhYxiI1sKSnASoac6I1okxASE4g0S Bwdv3lQnSWqCTqtJ9Wm1XKzqyeVsXVfvlt1vB/XNebtYd4tm9Zrev55O/76p25vp9GjWNtMp3l51 zXo6nTfNfFm/ur16tWzmzR//ree/U3V2B5JJ196edx+W9XV1+IXEV6pO5qSTt7dvX7740flkPVv9 hLrvXh2SfISEDDnp86LTJDpN0wim1+NOuNofoveHmP0hdn+I2x/i94eE/SFxf4jsV89ujCzAFAhA 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 b9Rxo/5Al0hmzs16TXWxLp2Omw27du0yW7jZ9ljXY1034LkUzzY8FgO3IIIMoedGQ3SfqGfh3BIP QTEsIobFyi32fUjXe6/3Xqw92/FYjdxq1uv1ke1nnXXW9ohJz03xMF1WrlgNfXG69HpuNe5Astq4 1bGvZl8Nou66SL1I7cZzFh6bkYv/6uEbg9m4YpPB4tFsWjSbg9uS92Xuy9yVtytvx+wds0V3zjaf bd5itpu43aIgTSnfglQ+xaznZmM8YJedK3Zj17Eh7SYR0p7E7c4Dgw8M/mjaSwWvNb3W9Mz85557 YvvT2/fb99sdZu6w6pCmNuwXqWGqNpCvHdhHyaEoDuO+vsT27TMYucP8nEjxVW9lNyhVTBfYEG5i aQ3h4Fo2pckfacFt18p45dJZKsvESdKrrXYjc7C0eI6z/yLuTMCjqu7+f2buZGaSmUQIWwIoDpts AgKKBVlUVDZDRKEUW00Rl0Gl7AQwEA3iLi6IuNQFKVK0aJlq69JpxIghLAbMJDFDCUkYJow3IQm5 N2Oknvdzb4YQ0D61/+f5v+9zns/cucs5c37f7+8sN/K0DpEkOpnXW65YyZ4LRGeKMik9faLoPX3a jReLobdMn3Kxkf/mM8a80050Mc8UfqF9a+s24RLJIjV2FifczE7k6R0LFi8QW8zP7ebn++bnh+bn p+bnrnvZrIh88/OA+VlkfpaZn0fNz+Pmp2qsm6LB+LTYzc+u5udg8/Ma83Om+Tnv/nvvv9ey2vxc Z34+bX5uND9fMz+3mp87WmeP//Rp+ZmfTpRU0MCOwk5h/LXn/+6aFR8S/+tjkrjIfO823sweEs+J zWKn2CUOiUrRYLGKeDNSZyxaVRh/81Ko19H8f31jbrGMajk+uq7l+PtomzrkW+3mc84t7tPnnif1 Pfe8ffK55x1ePve8zw/nnvc77/6Arueejxgq4q1tzxvb3LcLyw1XnXs+9XGOCeR0P5Fu/J2QOszx 1qHWdLHGusVaIt5Qfq/8XhTZltjeFIG4r+2PWpSEmxN+a/ko4RGXxZLvbue+znqt+1b3a9YViXMT 51n/nrgm8UlrXpI1yWk9lNSU1GT9hqVVN7SxFyd++JOlkFKWeKxNicRK4U+UxqSeraUfZRRlAmWe WTadXxILkzYn/aXdxlh5o03ZbpT24idLQvv01vJ4+w2tRW8pyd1/ogymjOj4cpuypaWYd84rHXd2 zG8tBzodpRw3SmfbT5XkwZ2TO/fr8nibssEsu36yFHZpPlNSOqZ0bS0TYmXyT5Z0s8yMHc8t2bFP 47ndZilqLS21j6TUpQ5InZv6Wuo2o5zfeuqOnyotraf+LbUyVhrPFuNXUpvN38o2uHBqr1GtZWqv 6a1lbqzMo2T3mtd7GGV8n8F9JvSax+fgPrv65l9SbJbGfrMpC/r3pQzqX9k/CpX9fxiQP/A1o/Sv HPjpwMjAyCDboKRBHQd9TCkaPJaSPnj2kFdjxX9Z9vC+w6tHPHfFCMrYkSkjZ4/MvHJnrHx65e4r i0YNoFw5at3ow2PsZnlmzC6znB57xdh3Y+XDMac5f3dsnXlWN846zjr23XGDxj89/tOrB183i3Lk hnvGPNPyNMe6lqcmjTWemzR1cs/JQyePnbxtSl+zpE+ZZ5bMKeumvMpn5pQCytGpK6dmTz1y4wLK xrQMnkpPO5B2YEoBn4eNb5TKNDWteVq2WbZO22eWI9NUODJNT7dN07mvps9OP5xeedMSynPTL+a5 rdP0ljvTV07Tpx+bXjsjfebuWbN+k/yb7r/pe7ft7tl3l97dfOZ4zyDKzvnt5vdckLngoQW5CyoX qAv0hbaFwxZOWHjXwgULVy58dOHGhe8u/HBh3sJDixYsem7RtkUNi8Xi5MUTF89Z/Oni4iUjlsxZ 8urSmUsfXepf2rjMvmzQsuuXvbvs+PIJy5szu2den5mRuSjz1cwdmaUreq749YoPV5SuaF7pXtl5 5ZUrr1k5d+XWlaWrBqyasOq2VZtWbV91eJX+wPgHVj7waZY9a3zWoqz3s3ZnnV7ddfU9q7euVteM WpO5Zkd2+r+Zqz48fz46d7bJXna2GPNI9htnS8sM8m/G3uTzR9y546Ql039y1jkz87Qp584d2bvP FmN2yC46W1rmBWMObbc9ZXeXDczDZWPrmDXNOdg8Mt+2T2d+3ZS0ud3GxMLWOZNn2+u95hp1Ez9M 2nR27mxRidl5gjn/tjzVM2nzGfWMq8ZcbD5bZtw3n48pSLsfJh5jJt9MjTKztUJ6t5FjmVnOrg6R 81aFCW3WgbMrwWaj3z+a/bf/aPZPiM35j5vzvTnLm+1QO2kC3zedmQnxY1vML+amlvmnZX6L+cic yAxouDa3dXY84yhzXMrk7EqjxlmPe03PrsyupDXjqUbupadW9pr+45xgHixqM6P+xDzbdl798Zwa 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 VtS7eiKuwyRcj8lg22q2rf4J7O9q+7va/q62v6uNs9o4q42z2jirjbPaOKuNs9o4q42z2jirjbHa GKuNsdoYq42x2hirjbHaGLMnRr17VSGD6uJfNUkssVPWikbFT8XfHulffq1oli39dYEU0qhE8a8o ZlCNbOkX7LOiWZYCKFAABQqgQAEUKIACBVCgAAoUQIECKFAABQqgIPIdJPIdRAm0UgKtlEArJdBK CbRSAq2UQCsl0EoJtFICrZRAqyh5hSh5hSh5RfSvIY5GYCR+gFEYjR/iR7gSY3AVrg4jRNQrRdQr RdQrRdQrRdQrRdPhoulw0XS4aDpcNB0ummZE04xomhFNM6JpRjTNiKYZ0TQjmmZE04y82yTvNsm7 TfJuk7zbJO82ybtNUfH7jjl4DI/j+WiAyDtA/o3l31j+jeXfWP6N5d9Y/o3l31j+jeXfWP6N5d9Y /o1F6zGi9RjReky0US27CS1oxWa0YQtitGMrOrAtTBPZZ4vss0X22SL7bJF9tqg+XlQfL6qPF9XH i+rjafo8TZ+n6fM0fZ6mz9P0eZo+T9Pnafo8TZ+n6fM0fZ6mz9P0eZo+T9Pnafo8TZ+n6fM0fZ6m z9P0eZo+T9Pnafo8TZ+n6fM0fZ6mz9P0eZo+T9Pnafo8TZ+n6fM0fZ6mz9P0eZo+T9Pny74S9Ss7 H1/F1/B13B9yMlFOJsrJRDmZKCcT5WSinEyUk4lyMlFOJsrJRDmZKCcT5WSinEyUk4lyMlFOJsrJ RDmZKCcT5WSinEyUk4lyMlFOLTFfLbFQLbFQLbFQLbFQLbFQLTFfLTFfLTFfLTFfLTG/7C9RpqwW i7EkyshiWVksK4tly4cW/4+q4+cczw6TZbPzZLPzStns4tBWfjlGyG7vy2rlo0ObzHamzDZSZjtT ZhupFr8tcXV4MrEgvJp4MeqVeEX2W6Ker1enN0T9ZblWWS6RWKG+fy/TVch0g0u/Mdnq+maZZ2yU leWyslxWlsvKcllZLivLZWW5rCyXleWyslxWlstS0q2UdCsl3UpJt1LSrZR0KyXdSkm3UtKtlHQr Jd1KSbdS0q3JaSFOTsd9uB8z8ABm4td4MAyXOYfLnMPVXfPVXfPVXfNl0YwsmpFFM7JoRhbNyKIZ WTQji2Zk0YwsmpFFM7Johs6M6cyYzozpzJjOjOnMmM6M6cyYzozpzJjOjOnMmM6MkztCW3InurAL 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 VamdRtaW2O24V6/7eOZ7b+7Ta7fqtNOI25KVjhmjqHb9vZb2mcEOXjdKXdsVlWmlXSvdWgla2FTq OxWVebvd293eDt7c1DOG44t26r7dGNZ4+2hvN3p7Z2KPHVsc/T5+vJ/HddMJIew3ljVaO1prjVrb mawKudKsqq1zNjpApdyq5f3G9GQxi4ZyLe4yjlWJ7qjcW7v0vSpZ4/NxYVDxie4lntiov6KlCp7Y qM2ilQra2Mq6/7BeVr9nnbz9n6xP6dnSunj2P1kPc/wfroN4+l+0vyjzv2x3c/wP7F268+/aOeqV 7BtVJQ82vkOiTHKg1g71zmE0wwd8Pty9I9w7yr3Bzo9xb4h7x8oHyWQ/PRzq7pGOx1iTbLKvMzVE sr/+B+rhUD0V2zrc9SNcH+T6YNePcV07VqH4dLHnQ3ueKPZUbKuPcZW7uz7Zz5X+OCQ63Pj6eHK9 Ng83vnLjK/fW+uSR7g/CUa4P9swxrg3x+djiXyXXyipjLc6wPDnAWAdGFT2tFN9eZfzFGZYnj3Zv sHvvvV1uvn1xMN/rZ8yHaHeguRxq9Q/T1weK83L/CPePdP8o9we7doz7Q9w/1vzMwtocrN1+rvbH IWG5MXSzzprkYdbyA+Z8uGeO8MyR7g/CUZ452jODPTPEM8fKbMV1ypbsekjU1ziKFttlHH2No9o4 siXbHuV8cMmCu4yhrzFUF1clSpTmPrDHzu+Nvmi9RGne773R3jPq8qj3f9cn7NqY/f7BL+z2j0Q1 /1Xf8NZJUfo/8g93j4kO+t/yEa190Kz/m37i7eOiA/+nvqKV04sz+t/xFyvx59I6/rd8ppQbav6r flOK6scldna3iKSXiTiHiWrnJvZ0t4tqn0/s624VfS4X1Y4U1YYmK7pbRNTLRKPDRLVzk1Xd7aLa 55PV3a0i0+Wi2pGi2tBk3+6dLPIhFjmeRY5PHuJ8QPggi/QyqpNZZQirHJM83PUjPHekZwb9H+q+ A76KYvv/zMzuzN6b2SQkAZLQixRBBaQoRcGu6EOfHUSwYgH1ISIiRUAFBKUpoCCgYAF82EFBwQIi FlCRItKR3ntn/t+ZexMTEwjt6e+/+9nJ7OyZcnfPfOd7ZnZPcJTFeTnIlYfcGZCrALmK0JoILDcN m+tCYf+vz9eUCrabBqZbHqziPHCFGWB7Se5/C01mt1M91pIuY3dQH3Yn/t4Fy/1GM1zcBFvkZjMZ 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 bkHTg1t56h8i65UqD+X9J6k7QQm9PhX6p46Fqcg/dSxKxf6Jo6VX0n+M/9gnll7B/zHm+FNYVl9t JOlVfwzNoEW0lnbScUq1bCvWKmJVsGpYDa02VpI10BpjzbAWWWutndZxK1XYoqCoI3qL4WK8mCOW ik1inzgr0jjM+bkUV+ba3IQ7cm8ezuN5jp6Dpq0oP2a5brbzVtnOR2Q7H3nLuZ2tPKSn+R6S1i3n 4Qq3n3vTb6+vrt+uP7bJ7ee56Xb9uWOznRfLJl8z23mzbOfZ+pN73+3neUpkO6+f7bzX7fYXmHp7 +d3Lbz8ven+289K3nOv5VzQ+W/kAnAudH3L6PSxe3z+W8Htu65jLo3NVsYC7PTjuC47Hg+PlP5Iu tTA4Lg+OycFxx+1W3Kdu7+V9S28/LzPgdvkyB24/L7v59vNy32Y7X3L7efmG2c6fz3beJdt512zn Y2+JMk1UHJftfOnt8hWzjdLflW/Ndr492/mO20fx4a0alfZMa+sjamdNRLZtpf9Iz9QxZDkxzh1Y K3JSyKulkr2aaq1apVZrTsi6YF3Qcpety2RZKVYKCeuadY1YVVPVyFZPqCf0umniQfCTXNO0J3KK 3JpjfkGkjD0c0TVL6/M8+m6kK02kZDpMaVastiFKWxXrNSDh1fQSNNbyntNYW1sfo3NynL5biNf3 PFXUaWIRo206g2Oy0ndaIrc+P4djstpFQp/t0Zis9mncoPtqIjQ/FVKHta2rdOkRHJPVUX1crc+P 4Zh8i+TxQPJEIHkykDwVSP7F3mdgbx3Y+yzs/UtJXZTUQ0n9W0vUJli4GRZuhYV/KdmOkh0o2YkS QVLoPz3NXGHe3I4RMdqrubVX2XvKe1p7fZVaRSFt02rtKdYS5mmkv+rrqaXrt8R4EUbKstKsND1q WVaW9pYj9HUP9DrQG4JeKfKL/BQlColCFC1KiBIU5pp6NF2nldOKPKeN04YiTjunHSmnvdOecjhd na4U4yQ5SXSH08PpQTlVnIqjXKqQKqT7VEQVodyqmCpGeVQJpe/5VClVivKq+9X9lE+VVqUpv4pX 8fgud3kqoB5UD9Ld6iH1EBVUD6uH6R71iHqE4tSj6lG6Vz2mHtOjY+KtMOKtiHpaPU1FVXPVnIqp 1qo1FVdtVVsqoV5Rr1BJlagSqZTqrDrrRNFFdaH7VZJKogdUD9WDSqteqheVUX1VX4pX/VV/KqsG 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 ncOOsc1+l6371k+bYOoI+1G7Knl2NbsaKV1WkfLyLJ7N8/gLXsvrOJnX8wbeyJv4R97MW/7I42a3 jGfyTK3xM/O7Zp7Lc7W/F7DOo9pza3R7R/ncX7XP1FJzdelSXsbLeQWv5O95Ff/Aq3nNH40xtM/i WVr7bJ5t3sjkeVr7F6yzs7Zwi9Zu+mG0l6bYP9T6B/2Az44GPjP1/mR0oZ6JBl3P6SwW0Ts0kAbR YBpCQ2mYntfv0gj8d9H3aRR9oGf5aBpDH9FY+pjG0Sd6zk+giTSJJtMUmkrTdAb4lGbQTJpFn9Fs +lzng7k0j+bTAvqCvqSvdHb4mhbRN/QtLaYl9J3OFctoOa2glfQ9raIfdOZYQ2tpHSXTetpAG3Ue +ZE20xbaSttoO/2ks8rPtJN+oV20m/bQXp1j9tMB+pUO0iE6TEd0xjlGx+kEnaRTdJrO6Pxzjs7T BbpIl+gyXdHZ6Cql0jW6Tr/RDfqd0ugmpVMGZVKWDmhLNBAJ4jnRUDQSz4sXRGPxomgimopmorlo IV4SL4uWopVoLdqItqKdeEW0Fx1ER/GqSBSdRGfxmugiXhdTxR6xV+wT+8UB8as4KA6Jw+KIOCqO iePihDgpTonT4ow4K86J8xwWF8RFdsUlcVlcESniqkgV18R18Zu4IX4XaeKmSBcZIlNk6RRk3rZn ttnhEEuO4mhuwAn8HDfkZtycX+aW3Ilf54E8iAfzEB7Nn/BE/pK/4q95ES/h73grb+Pt/BPv4J95 J//Cu3g37+G9vI/38wH+lQ/yIT7MR+xH7Crm/7baO+1f7F32bnuPvdfeZ++3D9i/2gftQ/Zh+4h9 1D5mH7dP2CftU/Zp+4x91j5nn7cv2BftS/Zl+4qdYl+1U+1r9nX7N/uG/budZt+00+0MO9POciJO TllNVpdPyBrySfmUfFrWlLVkbfmMrCOflXVlPVlfNpAJ8jnZUDaSz8sXZGP5omwim8pmsrlsIV+S L8uWspVsrf/a6r9X9F8H2VG+KhNlJ9lZvia7yNdlV9lNJsnusofsKXvJN2Rv/ddHviX7yn6yv3xb DpDvyIFykBwsh8ihcpgcLt+VI+R7cqR8X46SH8gP5Wg5Rn4kx8qP5Tj5iRwvJ8iJcpKcLKfIqXKa nC4/lTPkXDlPzpcL5BfyS/mVXCi/lovkN/Jb879f5XdyqVwml8sVcqX8Xq6SP8jVco1cK9fJZLle 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 vMeEhicqrNq2TOfIfPq3Sz5Hy0xydtzf+KhlW/3DmkZFAZ2+g25+usqn76x4n6l9g8LWpYV1Hqoc cr98p5onu3wLleeATMMiL10/c1/RjQ/UUm5dDhkWrPPqjnHbpN+3btDwRtpRUnncoghZOEhN7n1w YodPne7khWud5rdOasJrNmYGxtRCt0pe3s64NoEVG1x/Ks2QaUmek6w76xJfqlQ5zUFHvleOXLbD NufJGUNPiwVT7/ZOXTF9nLXnuE2HktBexGLwcgL1EWvdhXqF12WtY3aPGHLmmKu5SO6Cc+ENG8cS tJnHGhoET28m1qitLXdPuhvhH/3vfepWQQ0KZW5kc3RyZWFtDQplbmRvYmoNCjExMCAwIG9iag0K WyAwWyA3NzhdICAzWyAyNTBdICA1WyA0MDhdICA5WyA3NzhdICAxMVsgMzMzIDMzM10gIDE0WyA1 NjQgMjUwIDMzMyAyNTAgMjc4IDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUw MCAyNzhdICAzNFsgNDQ0IDkyMSA3MjIgNjY3IDY2NyA3MjIgNjExIDU1NiA3MjIgNzIyIDMzMyAz ODkgNzIyIDYxMSA4ODkgNzIyIDcyMiA1NTZdICA1M1sgNjY3IDU1NiA2MTEgNzIyIDcyMiA5NDRd ICA2MFsgNzIyXSAgNjhbIDQ0NCA1MDAgNDQ0IDUwMCA0NDQgMzMzIDUwMCA1MDAgMjc4IDI3OCA1 MDAgMjc4IDc3OCA1MDAgNTAwIDUwMCA1MDAgMzMzIDM4OSAyNzggNTAwIDUwMCA3MjIgNTAwIDUw MCA0NDRdICAxMzNbIDUwMF0gIDE4MFsgNDQ0XSAgMTgyWyAzMzNdIF0gDQplbmRvYmoNCjExMSAw IG9iag0KWyAyNTAgMCA0MDggMCAwIDAgNzc4IDAgMzMzIDMzMyAwIDU2NCAyNTAgMzMzIDI1MCAy NzggNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDUwMCA1MDAgNTAwIDI3OCAwIDAgMCAwIDQ0 NCA5MjEgNzIyIDY2NyA2NjcgNzIyIDYxMSA1NTYgNzIyIDcyMiAzMzMgMzg5IDcyMiA2MTEgODg5 IDcyMiA3MjIgNTU2IDAgNjY3IDU1NiA2MTEgNzIyIDcyMiA5NDQgMCA3MjIgMCAwIDAgMCAwIDAg MCA0NDQgNTAwIDQ0NCA1MDAgNDQ0IDMzMyA1MDAgNTAwIDI3OCAyNzggNTAwIDI3OCA3NzggNTAw IDUwMCA1MDAgNTAwIDMzMyAzODkgMjc4IDUwMCA1MDAgNzIyIDUwMCA1MDAgNDQ0IDAgMCAwIDAg MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw IDAgMCAwIDAgMCAwIDAgNTAwXSANCmVuZG9iag0KMTEyIDAgb2JqDQpbIDI1MCAzMzMgMCAwIDAg MCAwIDAgMCAwIDAgMCAyNTAgMCAyNTAgMjc4IDUwMCA1MDAgNTAwIDUwMCAwIDUwMCA1MDAgNTAw IDAgNTAwIDMzMyAwIDAgMCAwIDAgMCA3MjIgNjY3IDAgNzIyIDY2NyAwIDc3OCA3NzggMCAwIDc3 OCA2NjcgMCA3MjIgNzc4IDYxMSA3NzggNzIyIDU1NiA2NjcgNzIyIDAgMTAwMCAwIDAgMCAwIDAg MCAwIDAgMCA1MDAgMCA0NDQgNTU2IDQ0NCAzMzMgNTAwIDU1NiAyNzggMCA1NTYgMjc4IDgzMyA1 NTYgNTAwIDAgMCA0NDQgMzg5IDMzMyA1NTYgNTAwXSANCmVuZG9iag0KMTEzIDAgb2JqDQpbIDI3 OF0gDQplbmRvYmoNCjExNCAwIG9iag0KPDwvVHlwZS9YUmVmL1NpemUgMTE0L1dbIDEgNCAyXSAv Um9vdCAxIDAgUi9JbmZvIDI0IDAgUi9JRFs8RDE1ODk4OUE5MDY0MDc0MEEyNENBRjU2QTczNUJB Mjc+PEQxNTg5ODlBOTA2NDA3NDBBMjRDQUY1NkE3MzVCQTI3Pl0gL0ZpbHRlci9GbGF0ZURlY29k ZS9MZW5ndGggMjkzPj4NCnN0cmVhbQ0KeJw10rkzQ1EUx/H73rMEsbzY10Ts+07EGvuuFfkL8heY QVAoVQozNFLQ6ZjR+BcMMyh0Go1MUlLGfefLLc5nzsw5c0/xU0q/dNrQ1VbKIQYPgvEp2FfCVgA+ hPCzsBsW9lzwI+zfCLG4cBASDv3CUUQ42RFe3HAGd8LrNvDt27WDcf6ulKkv86lVWIN1WAET/iY3 9N7F7X9ngAUZkAlZkA0uyIFcyAM35EMBFEIR2OCBYmiDEiiDUqiAcqiCSqiBaqiDWvCBF/xQD43Q AM3QBK3QAu2wCV3QCR3QDX3QCz3QDwMwCEMwDCMQgFEIwhiMwwRMwhRMQwhmYB5mYQ4WYBGWYFmn 4PJbQhT3OJiPx8KT18H6kmBaiXshGRVSp0r9AlW2PAUNCmVuZHN0cmVhbQ0KZW5kb2JqDQp4cmVm DQowIDExNQ0KMDAwMDAwMDAyNSA2NTUzNSBmDQowMDAwMDAwMDE3IDAwMDAwIG4NCjAwMDAwMDAx MjUgMDAwMDAgbg0KMDAwMDAwMDE4OCAwMDAwMCBuDQowMDAwMDAwNDg1IDAwMDAwIG4NCjAwMDAw MDQ1MTYgMDAwMDAgbg0KMDAwMDAyMjU4NCAwMDAwMCBuDQowMDAwMDIyNzUyIDAwMDAwIG4NCjAw MDAwMjI5OTIgMDAwMDAgbg0KMDAwMDAzMTMyMSAwMDAwMCBuDQowMDAwMDMxNDk2IDAwMDAwIG4N CjAwMDAwMzE3MzUgMDAwMDAgbg0KMDAwMDAzMTkxNiAwMDAwMCBuDQowMDAwMDMyMTYwIDAwMDAw IG4NCjAwMDAwMzIzMjEgMDAwMDAgbg0KMDAwMDAzMjU0NiAwMDAwMCBuDQowMDAwMDMyODU5IDAw MDAwIG4NCjAwMDAwMzU5NTkgMDAwMDAgbg0KMDAwMDA1NDAyOCAwMDAwMCBuDQowMDAwMDU0MTY2 IDAwMDAwIG4NCjAwMDAwNTQxOTYgMDAwMDAgbg0KMDAwMDA1NDM2MiAwMDAwMCBuDQowMDAwMDU0 NDM2IDAwMDAwIG4NCjAwMDAwNTQ2OTMgMDAwMDAgbg0KMDAwMDEwNDkyMSAwMDAwMCBuDQowMDAw MDAwMDI2IDY1NTM1IGYNCjAwMDAwMDAwMjcgNjU1MzUgZg0KMDAwMDAwMDAyOCA2NTUzNSBmDQow MDAwMDAwMDI5IDY1NTM1IGYNCjAwMDAwMDAwMzAgNjU1MzUgZg0KMDAwMDAwMDAzMSA2NTUzNSBm DQowMDAwMDAwMDMyIDY1NTM1IGYNCjAwMDAwMDAwMzMgNjU1MzUgZg0KMDAwMDAwMDAzNCA2NTUz NSBmDQowMDAwMDAwMDM1IDY1NTM1IGYNCjAwMDAwMDAwMzYgNjU1MzUgZg0KMDAwMDAwMDAzNyA2 NTUzNSBmDQowMDAwMDAwMDM4IDY1NTM1IGYNCjAwMDAwMDAwMzkgNjU1MzUgZg0KMDAwMDAwMDA0 MCA2NTUzNSBmDQowMDAwMDAwMDQxIDY1NTM1IGYNCjAwMDAwMDAwNDIgNjU1MzUgZg0KMDAwMDAw MDA0MyA2NTUzNSBmDQowMDAwMDAwMDQ0IDY1NTM1IGYNCjAwMDAwMDAwNDUgNjU1MzUgZg0KMDAw MDAwMDA0NiA2NTUzNSBmDQowMDAwMDAwMDQ3IDY1NTM1IGYNCjAwMDAwMDAwNDggNjU1MzUgZg0K MDAwMDAwMDA0OSA2NTUzNSBmDQowMDAwMDAwMDUwIDY1NTM1IGYNCjAwMDAwMDAwNTEgNjU1MzUg Zg0KMDAwMDAwMDA1MiA2NTUzNSBmDQowMDAwMDAwMDUzIDY1NTM1IGYNCjAwMDAwMDAwNTQgNjU1 MzUgZg0KMDAwMDAwMDA1NSA2NTUzNSBmDQowMDAwMDAwMDU2IDY1NTM1IGYNCjAwMDAwMDAwNTcg NjU1MzUgZg0KMDAwMDAwMDA1OCA2NTUzNSBmDQowMDAwMDAwMDU5IDY1NTM1IGYNCjAwMDAwMDAw NjAgNjU1MzUgZg0KMDAwMDAwMDA2MSA2NTUzNSBmDQowMDAwMDAwMDYyIDY1NTM1IGYNCjAwMDAw MDAwNjMgNjU1MzUgZg0KMDAwMDAwMDA2NCA2NTUzNSBmDQowMDAwMDAwMDY1IDY1NTM1IGYNCjAw MDAwMDAwNjYgNjU1MzUgZg0KMDAwMDAwMDA2NyA2NTUzNSBmDQowMDAwMDAwMDY4IDY1NTM1IGYN CjAwMDAwMDAwNjkgNjU1MzUgZg0KMDAwMDAwMDA3MCA2NTUzNSBmDQowMDAwMDAwMDcxIDY1NTM1 IGYNCjAwMDAwMDAwNzIgNjU1MzUgZg0KMDAwMDAwMDA3MyA2NTUzNSBmDQowMDAwMDAwMDc0IDY1 NTM1IGYNCjAwMDAwMDAwNzUgNjU1MzUgZg0KMDAwMDAwMDA3NiA2NTUzNSBmDQowMDAwMDAwMDc3 IDY1NTM1IGYNCjAwMDAwMDAwNzggNjU1MzUgZg0KMDAwMDAwMDA3OSA2NTUzNSBmDQowMDAwMDAw MDgwIDY1NTM1IGYNCjAwMDAwMDAwODEgNjU1MzUgZg0KMDAwMDAwMDA4MiA2NTUzNSBmDQowMDAw MDAwMDgzIDY1NTM1IGYNCjAwMDAwMDAwODQgNjU1MzUgZg0KMDAwMDAwMDA4NSA2NTUzNSBmDQow MDAwMDAwMDg2IDY1NTM1IGYNCjAwMDAwMDAwODcgNjU1MzUgZg0KMDAwMDAwMDA4OCA2NTUzNSBm DQowMDAwMDAwMDg5IDY1NTM1IGYNCjAwMDAwMDAwOTAgNjU1MzUgZg0KMDAwMDAwMDA5MSA2NTUz NSBmDQowMDAwMDAwMDkyIDY1NTM1IGYNCjAwMDAwMDAwOTMgNjU1MzUgZg0KMDAwMDAwMDA5NCA2 NTUzNSBmDQowMDAwMDAwMDk1IDY1NTM1IGYNCjAwMDAwMDAwOTYgNjU1MzUgZg0KMDAwMDAwMDA5 NyA2NTUzNSBmDQowMDAwMDAwMDk4IDY1NTM1IGYNCjAwMDAwMDAwOTkgNjU1MzUgZg0KMDAwMDAw MDEwMCA2NTUzNSBmDQowMDAwMDAwMTAxIDY1NTM1IGYNCjAwMDAwMDAxMDIgNjU1MzUgZg0KMDAw MDAwMDEwMyA2NTUzNSBmDQowMDAwMDAwMTA0IDY1NTM1IGYNCjAwMDAwMDAxMDUgNjU1MzUgZg0K MDAwMDAwMDAwMCA2NTUzNSBmDQowMDAwMTA2NDg2IDAwMDAwIG4NCjAwMDAxMDY1MTQgMDAwMDAg bg0KMDAwMDE4MzY4NCAwMDAwMCBuDQowMDAwMTg0MDk1IDAwMDAwIG4NCjAwMDAyNTY1NDYgMDAw MDAgbg0KMDAwMDI1Njk1MSAwMDAwMCBuDQowMDAwMjU3Mzg1IDAwMDAwIG4NCjAwMDAyNTc2ODIg MDAwMDAgbg0KMDAwMDI1NzcxMCAwMDAwMCBuDQp0cmFpbGVyDQo8PC9TaXplIDExNS9Sb290IDEg MCBSL0luZm8gMjQgMCBSL0lEWzxEMTU4OTg5QTkwNjQwNzQwQTI0Q0FGNTZBNzM1QkEyNz48RDE1 ODk4OUE5MDY0MDc0MEEyNENBRjU2QTczNUJBMjc+XSA+Pg0Kc3RhcnR4cmVmDQoyNTgyMDYNCiUl RU9GDQp4cmVmDQowIDANCnRyYWlsZXINCjw8L1NpemUgMTE1L1Jvb3QgMSAwIFIvSW5mbyAyNCAw IFIvSURbPEQxNTg5ODlBOTA2NDA3NDBBMjRDQUY1NkE3MzVCQTI3PjxEMTU4OTg5QTkwNjQwNzQw QTI0Q0FGNTZBNzM1QkEyNz5dIC9QcmV2IDI1ODIwNi9YUmVmU3RtIDI1NzcxMD4+DQpzdGFydHhy ZWYNCjI2MDY2Ng0KJSVFT0Y= --===============1090232603==-- From darrick.wong@oracle.com Fri Jun 10 11:42:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A654B7CA0 for ; Fri, 10 Jun 2016 11:42:07 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 20C1DAC004 for ; Fri, 10 Jun 2016 09:42:03 -0700 (PDT) X-ASG-Debug-ID: 1465576921-04cb6c381528fd0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id x1CJCJuGqAKUDKN8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 10 Jun 2016 09:42:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5AGfxC8016738 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 10 Jun 2016 16:42:00 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5AGfxUp014255 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 10 Jun 2016 16:41:59 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5AGfwhl032309; Fri, 10 Jun 2016 16:41:58 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 10 Jun 2016 09:41:58 -0700 Date: Fri, 10 Jun 2016 09:41:57 -0700 From: "Darrick J. Wong" To: Brian Foster Cc: Eric Sandeen , xfs@oss.sgi.com Subject: Re: [PATCH 0/4] xfs: online relabeling [RFC] Message-ID: <20160610164157.GA11810@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 0/4] xfs: online relabeling [RFC] References: <2305b486-f336-6d1e-9420-b69dc5bdc572@sandeen.net> <20160610121936.GC21568@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160610121936.GC21568@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1465576921 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2514 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30324 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 10, 2016 at 08:19:36AM -0400, Brian Foster wrote: > On Thu, Jun 09, 2016 at 11:51:12AM -0500, Eric Sandeen wrote: > > > > > > On 6/9/16 11:36 AM, Eric Sandeen wrote: > > > Ok, this more or less works; not really up to snuff > > > for submission or merging, just sketching it out, but some > > > questions first: > > > > > > 1) Is there really any point to this? :) We did have one > > > request, and btrfs can do it ... > > > > > Seems reasonable to me. Any details on the use case for the request? > > > > 2) Is using m_growlock horrible? growfs is the only other > > > thing that writes all supers, so I grabbed it. We don't > > > want multiple relabels stepping on each other. > > > > > > 3) Is there some way to actually force the primary to disk? > > > Right now the label change isn't actually visible on the > > > primary until unmount, which defeats the purpose. I'm not > > > sure if there's a straightforward/safe way to make it > > > visible... > > > > > Oh, sorry - I guess it is getting written out, but it's only > > available via an O_DIRECT read from userspace; it's not > > invalidating the cache. > > > > # io/xfs_io -c "label derp" /mnt/test > > label = "derp" > > > > # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C > > ... > > 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| > > ... > > > > # dd if=/dev/sdb2 iflag=direct bs=512 count=1 | hexdump -C > > ... > > 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 64 65 72 70 |............derp| > > ... > > > > # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C > > ... > > 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| > > ... > > > > Guess I need to think about this some more. > > > > Isn't this to be expected? You're directly accessing the block device of > a mounted filesystem. I would think this is expected behavior, so long > as the set/get interfaces through the fs are consistent. Trouble is, I bet blkid prints LABEL=foo here and not LABEL=derp as the admin is probably expecting. /me wonders if invalidate_inode_pages2_range here would help? --D > > Brian > > > -Eric > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From sandeen@sandeen.net Fri Jun 10 13:12:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C1AF27CA0 for ; Fri, 10 Jun 2016 13:12:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 962C0304051 for ; Fri, 10 Jun 2016 11:12:43 -0700 (PDT) X-ASG-Debug-ID: 1465582359-04cb6c38142bc40001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id ahrjQLOJhmLAr74N for ; Fri, 10 Jun 2016 11:12:39 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 5B78422C5; Fri, 10 Jun 2016 13:12:39 -0500 (CDT) Subject: Re: [PATCH 0/4] xfs: online relabeling [RFC] To: "Darrick J. Wong" , Brian Foster X-ASG-Orig-Subj: Re: [PATCH 0/4] xfs: online relabeling [RFC] References: <2305b486-f336-6d1e-9420-b69dc5bdc572@sandeen.net> <20160610121936.GC21568@bfoster.bfoster> <20160610164157.GA11810@birch.djwong.org> Cc: xfs@oss.sgi.com From: Eric Sandeen Message-ID: <7bb93415-d08c-29e8-df68-1665d7f39581@sandeen.net> Date: Fri, 10 Jun 2016 13:12:39 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160610164157.GA11810@birch.djwong.org> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465582359 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2381 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30325 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 6/10/16 11:41 AM, Darrick J. Wong wrote: > On Fri, Jun 10, 2016 at 08:19:36AM -0400, Brian Foster wrote: >> On Thu, Jun 09, 2016 at 11:51:12AM -0500, Eric Sandeen wrote: >>> >>> >>> On 6/9/16 11:36 AM, Eric Sandeen wrote: >>>> Ok, this more or less works; not really up to snuff >>>> for submission or merging, just sketching it out, but some >>>> questions first: >>>> >>>> 1) Is there really any point to this? :) We did have one >>>> request, and btrfs can do it ... >>>> >> >> Seems reasonable to me. Any details on the use case for the request? >> >>>> 2) Is using m_growlock horrible? growfs is the only other >>>> thing that writes all supers, so I grabbed it. We don't >>>> want multiple relabels stepping on each other. >>>> >>>> 3) Is there some way to actually force the primary to disk? >>>> Right now the label change isn't actually visible on the >>>> primary until unmount, which defeats the purpose. I'm not >>>> sure if there's a straightforward/safe way to make it >>>> visible... >>> >> >>> Oh, sorry - I guess it is getting written out, but it's only >>> available via an O_DIRECT read from userspace; it's not >>> invalidating the cache. >>> >>> # io/xfs_io -c "label derp" /mnt/test >>> label = "derp" >>> >>> # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C >>> ... >>> 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| >>> ... >>> >>> # dd if=/dev/sdb2 iflag=direct bs=512 count=1 | hexdump -C >>> ... >>> 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 64 65 72 70 |............derp| >>> ... >>> >>> # dd if=/dev/sdb2 bs=512 count=1 | hexdump -C >>> ... >>> 00000060 00 00 0a 00 b4 e5 02 00 02 00 00 08 66 6f 6f 00 |............foo.| >>> ... >>> >>> Guess I need to think about this some more. >>> >> >> Isn't this to be expected? You're directly accessing the block device of >> a mounted filesystem. I would think this is expected behavior, so long >> as the set/get interfaces through the fs are consistent. > > Trouble is, I bet blkid prints LABEL=foo here and not LABEL=derp as > the admin is probably expecting. exactly. And FWIW, when btrfs does it, it *is* visible. > /me wonders if invalidate_inode_pages2_range here would help? Um, not sure. Calling that against metadata from xfs feels a bit bizarre... -Eric From sales84@plasticproducts.com Fri Jun 10 19:48:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: **** X-Spam-Status: No, score=4.9 required=5.0 tests=DEAR_FRIEND,HTML_MESSAGE, MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C5B387CA0 for ; Fri, 10 Jun 2016 19:48:25 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9895F8F8037 for ; Fri, 10 Jun 2016 17:48:22 -0700 (PDT) X-ASG-Debug-ID: 1465606094-04cb6c381334290001-NocioJ Received: from plasticproducts.com ([58.218.7.193]) by cuda.sgi.com with SMTP id B7FnC5aGao4EeFCv for ; Fri, 10 Jun 2016 17:48:14 -0700 (PDT) X-Barracuda-Envelope-From: sales84@plasticproducts.com X-Barracuda-Effective-Source-IP: UNKNOWN[58.218.7.193] X-Barracuda-Apparent-Source-IP: 58.218.7.193 Received: from PC-201606051013[127.0.0.1] by PC-201606051013[127.0.0.1] (SMTPD32); Wed, 8 Jun 2016 15:36:21 +0800 From: "marco_acrylic@126.com" Subject: Re:acrylic shirts display To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re:acrylic shirts display MIME-Version: 1.0 Sender: sales84@plasticproducts.com Reply-To: marco_acrylic@126.com Date: Wed, 8 Jun 2016 15:36:21 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline X-Barracuda-Connect: UNKNOWN[58.218.7.193] X-Barracuda-Start-Time: 1465606094 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12141 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.94 X-Barracuda-Spam-Status: No, SCORE=1.94 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_SA038b, BSF_SC5_MJ1963, DEAR_FRIEND, HTML_MESSAGE, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30335 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 1.00 DEAR_FRIEND BODY: Dear Friend? That's not very dear! 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.20 BSF_SC0_SA038b Custom Rule SA038b 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160611004822.67DC21296080@cuda.sgi.com> PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MIHhtbG5zOm8gPSAidXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6 b2ZmaWNlIj48SEVBRD4NCjxNRVRBIGNvbnRlbnQ9InRleHQvaHRtbDsgY2hhcnNldD1VVEYtOCIg aHR0cC1lcXVpdj1jb250ZW50LXR5cGU+DQo8TUVUQSBuYW1lPUdFTkVSQVRPUiBjb250ZW50PSJN U0hUTUwgMTAuMDAuOTIwMC4xNzQ5MiI+PC9IRUFEPg0KPEJPRFk+DQo8UCBjbGFzcz1Nc29Ob3Jt YWw+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiDlrovkvZM7 IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7IENPTE9SOiByZ2IoMTAyLDEwMiwxMDIpOyBt c28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1hc2NpaS1mb250LWZhbWlseTogQXJpYWw7 IG1zby1oYW5zaS1mb250LWZhbWlseTogQXJpYWw7IG1zby1iaWRpLWZvbnQtZmFtaWx5OiBBcmlh bDsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwy NTUpIj48bzpwPjxTVFJPTkc+RGVhciANCkZyaWVuZDwvU1RST05HPiZuYnNwOzwvbzpwPjwvU1BB Tj48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEwLjVwdDsgRk9OVC1GQU1JTFk6IOWui+S9kzsg QkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7IG1z by1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWFzY2lpLWZvbnQtZmFtaWx5OiBBcmlhbDsg bXNvLWhhbnNpLWZvbnQtZmFtaWx5OiBBcmlhbDsgbXNvLWJpZGktZm9udC1mYW1pbHk6IEFyaWFs OyBtc28tZm9udC1rZXJuaW5nOiAxLjAwMDBwdDsgbXNvLXNoYWRpbmc6IHJnYigyNTUsMjU1LDI1 NSkiPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbD48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEw LjVwdDsgRk9OVC1GQU1JTFk6IEFyaWFsOyBCQUNLR1JPVU5EOiByZ2IoMjU1LDI1NSwyNTUpOyBD T0xPUjogcmdiKDEwMiwxMDIsMTAyKTsgbXNvLXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28t Zm9udC1rZXJuaW5nOiAxLjAwMDBwdDsgbXNvLXNoYWRpbmc6IHJnYigyNTUsMjU1LDI1NSkiPldl Jm5ic3A7YXJlJm5ic3A7c3BlY2lhbGl6ZWQmbmJzcDtpbiZuYnNwO2FjcnlsaWMmbmJzcDtzaGly dHMmbmJzcDtkaXNwbGF5IA0KYWxtb3N0Jm5ic3A7MTAmbmJzcDt5ZWFyczwvU1BBTj48L1A+DQo8 UCBjbGFzcz1Nc29Ob3JtYWw+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQt RkFNSUxZOiBBcmlhbDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigx MDIsMTAyLDEwMik7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2Vybmlu ZzogMS4wMDAwcHQ7IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj4mbmJzcDtPdXImbmJz cDtwcm9kdWN0Jm5ic3A7aGF2ZSZuYnNwO1NHUyZuYnNwO3JlcG9ydDwvU1BBTj48U1BBTiANCnN0 eWxlPSJGT05ULVNJWkU6IDEwLjVwdDsgRk9OVC1GQU1JTFk6IEFyaWFsOyBCQUNLR1JPVU5EOiBy Z2IoMjU1LDI1NSwyNTUpOyBDT0xPUjogcmdiKDEwMiwxMDIsMTAyKTsgbXNvLXNwYWNlcnVuOiAm IzM5O3llcyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAxLjAwMDBwdDsgbXNvLXNoYWRpbmc6IHJn YigyNTUsMjU1LDI1NSkiPjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1h bCBzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246IHdpZG93LW9ycGhhbiI+ PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsgQkFD S0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7IG1zby1z cGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7IG1zby1z aGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj48bzpwPjwvbzpwPjwvU1BBTj48L1A+DQo8UCBjbGFz cz1Nc29Ob3JtYWwgc3R5bGU9IlRFWFQtQUxJR046IGxlZnQ7IG1zby1wYWdpbmF0aW9uOiB3aWRv dy1vcnBoYW4iPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0OyBGT05ULUZBTUlMWTog QXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7IENPTE9SOiByZ2IoMTAyLDEwMiwx MDIpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDEuMDAw MHB0OyBtc28tc2hhZGluZzogcmdiKDI1NSwyNTUsMjU1KSI+R2xhZCZuYnNwO3RvJm5ic3A7aGVh ciZuYnNwO3RoYXQmbmJzcDt5b3UmIzM5O3JlJm5ic3A7b24mbmJzcDt0aGUmbmJzcDttYXJrZXQm bmJzcDtvZiANCml0PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0OyBGT05U LUZBTUlMWTogQXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7IENPTE9SOiByZ2Io MTAyLDEwMiwxMDIpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5p bmc6IDEuMDAwMHB0OyBtc28tc2hhZGluZzogcmdiKDI1NSwyNTUsMjU1KSI+LiZuYnNwOzwvU1BB Tj48L1A+DQo8UCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9IlRFWFQtQUxJR046IGxlZnQ7IG1zby1w YWdpbmF0aW9uOiB3aWRvdy1vcnBoYW4iPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0 OyBGT05ULUZBTUlMWTogQXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7IENPTE9S OiByZ2IoMTAyLDEwMiwxMDIpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250 LWtlcm5pbmc6IDEuMDAwMHB0OyBtc28tc2hhZGluZzogcmdiKDI1NSwyNTUsMjU1KSI+SSANCndp c2ggPC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0OyBGT05ULUZBTUlMWTog QXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7IENPTE9SOiByZ2IoMTAyLDEwMiwx MDIpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDEuMDAw MHB0OyBtc28tc2hhZGluZzogcmdiKDI1NSwyNTUsMjU1KSI+d2UgDQpoYXZlJm5ic3A7Y2hhbmNl IHRvIGNvb3BlcmF0ZSB3aXRoIGVhY2ggb3RoZXIuPC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05v cm1hbCBzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246IHdpZG93LW9ycGhh biI+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsg QkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7IG1z by1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7IG1z by1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj48L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1T SVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUs MjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5 OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwy NTUpIj5PZiANCmNhdXNlIHdlJm5ic3A7d2lsbCZuYnNwO3Byb3ZpZGUmbmJzcDs8L1NQQU4+PFNQ QU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsgQkFDS0dS T1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7IG1zby1zcGFj ZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7IG1zby1zaGFk aW5nOiByZ2IoMjU1LDI1NSwyNTUpIj55b3UmbmJzcDt0aGUmbmJzcDtoaWdoJm5ic3A7cXVhbGl0 eSZuYnNwO3Byb2RkdWN0cyANCndpdGgmbmJzcDtjb21wZXRpdGl2ZSZuYnNwO3ByaWNlLjwvU1BB Tj48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEwLjVwdDsgRk9OVC1GQU1JTFk6IEFyaWFsOyBC QUNLR1JPVU5EOiByZ2IoMjU1LDI1NSwyNTUpOyBDT0xPUjogcmdiKDEwMiwxMDIsMTAyKTsgbXNv LXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAxLjAwMDBwdDsgbXNv LXNoYWRpbmc6IHJnYigyNTUsMjU1LDI1NSkiPjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIGNs YXNzPU1zb05vcm1hbCBzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246IHdp ZG93LW9ycGhhbiI+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZ OiBBcmlhbDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAy LDEwMik7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4w MDAwcHQ7IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj48bzpwPjwvbzpwPjwvU1BBTj48 L1A+DQo8UCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9IlRFWFQtQUxJR046IGxlZnQ7IG1zby1wYWdp bmF0aW9uOiB3aWRvdy1vcnBoYW4iPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0OyBG T05ULUZBTUlMWTogQXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7IENPTE9SOiBy Z2IoMTAyLDEwMiwxMDIpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtl cm5pbmc6IDEuMDAwMHB0OyBtc28tc2hhZGluZzogcmdiKDI1NSwyNTUsMjU1KSI+U2hvdWxkJm5i c3A7eW91Jm5ic3A7aGF2ZSZuYnNwO2FueSZuYnNwO3F1ZXN0aW9uLCZuYnNwO2ZlZWwmbmJzcDtm cmVlJm5ic3A7dG8mbmJzcDtjb250YWN0Jm5ic3A7dXMuPC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1z b05vcm1hbCBzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246IHdpZG93LW9y cGhhbiI+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBBcmlh bDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7 IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7 IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj5HZXQmbmJzcDttb3JlJm5ic3A7aW5mb3Jt YXRpb24sPC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0OyBGT05ULUZBTUlM WTogQXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7IENPTE9SOiByZ2IoMTAyLDEw MiwxMDIpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDEu MDAwMHB0OyBtc28tc2hhZGluZzogcmdiKDI1NSwyNTUsMjU1KSI+cGxlYXNlJm5ic3A7dmlzaXQm bmJzcDtvdXImbmJzcDt3ZWJzaXRlOnd3dy5jbnlqaWUuY29tPC9TUEFOPjxTUEFOIA0Kc3R5bGU9 IkZPTlQtU0laRTogMTAuNXB0OyBGT05ULUZBTUlMWTogQXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigy NTUsMjU1LDI1NSk7IENPTE9SOiByZ2IoMTAyLDEwMiwxMDIpOyBtc28tc3BhY2VydW46ICYjMzk7 eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDEuMDAwMHB0OyBtc28tc2hhZGluZzogcmdiKDI1 NSwyNTUsMjU1KSI+PG86cD48L286cD48L1NQQU4+PC9QPg0KPFAgY2xhc3M9TXNvTm9ybWFsIHN0 eWxlPSJURVhULUFMSUdOOiBsZWZ0OyBtc28tcGFnaW5hdGlvbjogd2lkb3ctb3JwaGFuIj48U1BB TiANCnN0eWxlPSJGT05ULVNJWkU6IDEwLjVwdDsgRk9OVC1GQU1JTFk6IEFyaWFsOyBCQUNLR1JP VU5EOiByZ2IoMjU1LDI1NSwyNTUpOyBDT0xPUjogcmdiKDEwMiwxMDIsMTAyKTsgbXNvLXNwYWNl cnVuOiAmIzM5O3llcyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAxLjAwMDBwdDsgbXNvLXNoYWRp bmc6IHJnYigyNTUsMjU1LDI1NSkiPjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1z b05vcm1hbCBzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246IHdpZG93LW9y cGhhbiI+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBBcmlh bDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7 IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7 IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj5BbnkmbmJzcDtuZXcmbmJzcDtlbnF1aXJ5 Jm5ic3A7YXJlJm5ic3A7d2VsY29tZWQuPC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTog MTAuNXB0OyBGT05ULUZBTUlMWTogQXJpYWw7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1NSk7 IENPTE9SOiByZ2IoMTAyLDEwMiwxMDIpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1z by1mb250LWtlcm5pbmc6IDEuMDAwMHB0OyBtc28tc2hhZGluZzogcmdiKDI1NSwyNTUsMjU1KSI+ PG86cD48L286cD48L1NQQU4+PC9QPg0KPFAgY2xhc3M9TXNvTm9ybWFsIHN0eWxlPSJURVhULUFM SUdOOiBsZWZ0OyBtc28tcGFnaW5hdGlvbjogd2lkb3ctb3JwaGFuIj48U1BBTiANCnN0eWxlPSJG T05ULVNJWkU6IDEwLjVwdDsgRk9OVC1GQU1JTFk6IEFyaWFsOyBCQUNLR1JPVU5EOiByZ2IoMjU1 LDI1NSwyNTUpOyBDT0xPUjogcmdiKDEwMiwxMDIsMTAyKTsgbXNvLXNwYWNlcnVuOiAmIzM5O3ll cyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAxLjAwMDBwdDsgbXNvLXNoYWRpbmc6IHJnYigyNTUs MjU1LDI1NSkiPg0KPERJVj48QSBocmVmPSJhYm91dDpibGFuayMiIA0KeGZzJm5ic3A7MjAxNi0w Ni0wOCAxNTozNjoyMTs4NkYwMkIwQi0wOTg5LTQ0QTktQTRFMi04RkQzNjkzREJDMEM7ODZGMDJC MEItMDk4OS00NEE5LUE0RTItOEZEMzY5M0RCQzBDOzg2RjAyQjBCLTA5ODktNDRBOS1BNEUyLThG RDM2OTNEQkMwQzs4NkYwMkIwQi0wOTg5LTQ0QTktQTRFMi04RkQzNjkzREJDMEM7ODZGMDJCMEIt MDk4OS00NEE5LUE0RTItOEZEMzY5M0RCQzBDOzg2RjAyQjBCLTA5ODktNDRBOS1BNEUyLThGRDM2 OTNEQkMwQz48U1BBTiANCnN0eWxlPSJWSVNJQklMSVRZOiBoaWRkZW4iPjwvU1BBTj48L0E+PC9E SVY+DQo8RElWPjxBIGhyZWY9ImFib3V0OmJsYW5rIyIgDQp4ZnMmbmJzcDsyMDE2LTA2LTA4IDE1 OjM2OjIxOzg2RjAyQjBCLTA5ODktNDRBOS1BNEUyLThGRDM2OTNEQkMwQzs4NkYwMkIwQi0wOTg5 LTQ0QTktQTRFMi04RkQzNjkzREJDMEM7ODZGMDJCMEItMDk4OS00NEE5LUE0RTItOEZEMzY5M0RC QzBDOzg2RjAyQjBCLTA5ODktNDRBOS1BNEUyLThGRDM2OTNEQkMwQzs4NkYwMkIwQi0wOTg5LTQ0 QTktQTRFMi04RkQzNjkzREJDMEM7ODZGMDJCMEItMDk4OS00NEE5LUE0RTItOEZEMzY5M0RCQzBD PjxTUEFOIA0Kc3R5bGU9IlZJU0lCSUxJVFk6IGhpZGRlbiI+PC9TUEFOPjwvQT48L0RJVj4NCjxQ PjxCUj48L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZ OiBBcmlhbDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAy LDEwMik7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4w MDAwcHQ7IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj5LaW5kJm5ic3A7cmVnYXJkcyw8 L1NQQU4+PC9QPg0KPFA+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFN SUxZOiBBcmlhbDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIs MTAyLDEwMik7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzog MS4wMDAwcHQ7IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj48L1NQQU4+PFNQQU4gDQpz dHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsgQkFDS0dST1VORDog cmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEwMik7IG1zby1zcGFjZXJ1bjog JiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQ7IG1zby1zaGFkaW5nOiBy Z2IoMjU1LDI1NSwyNTUpIj48bzpwPjwvbzpwPjwvU1BBTj4mbmJzcDs8L1A+DQo8RElWPjxBIGhy ZWY9ImFib3V0OmJsYW5rIyIgDQp4ZnMmbmJzcDsyMDE2LTA2LTA4IDE1OjM2OjIxOzg2RjAyQjBC LTA5ODktNDRBOS1BNEUyLThGRDM2OTNEQkMwQzs4NkYwMkIwQi0wOTg5LTQ0QTktQTRFMi04RkQz NjkzREJDMEM7ODZGMDJCMEItMDk4OS00NEE5LUE0RTItOEZEMzY5M0RCQzBDOzg2RjAyQjBCLTA5 ODktNDRBOS1BNEUyLThGRDM2OTNEQkMwQzs4NkYwMkIwQi0wOTg5LTQ0QTktQTRFMi04RkQzNjkz REJDMEM7ODZGMDJCMEItMDk4OS00NEE5LUE0RTItOEZEMzY5M0RCQzBDPjxTUEFOIA0Kc3R5bGU9 IlZJU0lCSUxJVFk6IGhpZGRlbiI+PC9TUEFOPjwvQT48L0RJVj4NCjxQPjwvUD4NCjxQIGNsYXNz PU1zb05vcm1hbCBzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246IHdpZG93 LW9ycGhhbiI+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBB cmlhbDsgQkFDS0dST1VORDogcmdiKDI1NSwyNTUsMjU1KTsgQ09MT1I6IHJnYigxMDIsMTAyLDEw Mik7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAw cHQ7IG1zby1zaGFkaW5nOiByZ2IoMjU1LDI1NSwyNTUpIj48L1NQQU4+PC9QPg0KPFAgY2xhc3M9 TXNvTm9ybWFsPjwhLS1FbmRGcmFnbWVudC0tPjwvU1BBTj48U1BBTiANCnN0eWxlPSJGT05ULVNJ WkU6IDI0cHQ7IEZPTlQtRkFNSUxZOiDlrovkvZM7IEJBQ0tHUk9VTkQ6IHJnYigyNTUsMjU1LDI1 NSk7IEZPTlQtV0VJR0hUOiBib2xkOyBDT0xPUjogcmdiKDEwMiwxMDIsMTAyKTsgbXNvLXNwYWNl cnVuOiAmIzM5O3llcyYjMzk7OyBtc28tYXNjaWktZm9udC1mYW1pbHk6IEFyaWFsOyBtc28taGFu c2ktZm9udC1mYW1pbHk6IEFyaWFsOyBtc28tYmlkaS1mb250LWZhbWlseTogQXJpYWw7IG1zby1m b250LWtlcm5pbmc6IDIyLjAwMDBwdDsgbXNvLXNoYWRpbmc6IHJnYigyNTUsMjU1LDI1NSkiPjxv OnA+TWFyY28gDQombmJzcDs8L286cD48L1NQQU4+PC9QPg0KPFAgY2xhc3M9TXNvTm9ybWFsIA0K c3R5bGU9IlRFWFQtQUxJR046IGxlZnQ7IG1zby1wYWdpbmF0aW9uOiB3aWRvdy1vcnBoYW47IG1z by1sYXlvdXQtZ3JpZC1hbGlnbjogbm9uZSI+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxM3B0 OyBGT05ULUZBTUlMWTogQXJpYWw7IEZPTlQtV0VJR0hUOiBib2xkOyBDT0xPUjogcmdiKDExLDEw MiwyNTUpOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDAu MDAwMHB0Ij5UQUlaSE9VJm5ic3A7WUpJRSZuYnNwO1BMQVNUSUMmbmJzcDtJTlRFUk5BVElPTkFM Jm5ic3A7TElNSVRFRDwvU1BBTj48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEzcHQ7IEZPTlQt RkFNSUxZOiBBcmlhbDsgRk9OVC1XRUlHSFQ6IGJvbGQ7IENPTE9SOiByZ2IoMTEsMTAyLDI1NSk7 IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMC4wMDAwcHQi PjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCANCnN0eWxlPSJURVhU LUFMSUdOOiBsZWZ0OyBtc28tcGFnaW5hdGlvbjogd2lkb3ctb3JwaGFuOyBtc28tbGF5b3V0LWdy aWQtYWxpZ246IG5vbmUiPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTNwdDsgRk9OVC1GQU1J TFk6IEFyaWFsOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6 IDAuMDAwMHB0Ij5BZGQ6Um9vbSZuYnNwOzQwOCxOby4yMTUsJm5ic3A7TGFvZG9uZyZuYnNwO1Nv dXRoJm5ic3A7Um9hZCwmbmJzcDtIdWFueWFuLCZuYnNwO1RhaXpob3UsJm5ic3A7Wmhlamlhbmcs Jm5ic3A7Q2hpbmEmbmJzcDszMTgwMjA8L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAx NHB0OyBGT05ULUZBTUlMWTogSGVsdmV0aWNhOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7 IG1zby1mb250LWtlcm5pbmc6IDAuMDAwMHB0Ij48bzpwPjwvbzpwPjwvU1BBTj48L1A+DQo8UCBj bGFzcz1Nc29Ob3JtYWwgDQpzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246 IHdpZG93LW9ycGhhbjsgbXNvLWxheW91dC1ncmlkLWFsaWduOiBub25lIj48U1BBTiANCnN0eWxl PSJGT05ULVNJWkU6IDEzcHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsgbXNvLXNwYWNlcnVuOiAmIzM5 O3llcyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAwLjAwMDBwdCI+V2ViOkh0dHA6Ly88L1NQQU4+ PFNQQU4+PEEgDQpocmVmPSJodHRwOi8vd3d3LmNueWppZS5jb20vIj48U1BBTiANCnN0eWxlPSJG T05ULVNJWkU6IDEzcHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsgQ09MT1I6IHJnYig1NiwxMTAsMjU1 KTsgVEVYVC1ERUNPUkFUSU9OOiB1bmRlcmxpbmU7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5 OzsgbXNvLWZvbnQta2VybmluZzogMC4wMDAwcHQ7IHRleHQtdW5kZXJsaW5lOiByZ2IoNTYsMTEw LDI1NSkgc2luZ2xlIj53d3cuY255amllLmNvbTwvU1BBTj48L0E+PC9TUEFOPjxTUEFOIA0Kc3R5 bGU9IkZPTlQtU0laRTogMTNwdDsgRk9OVC1GQU1JTFk6IEFyaWFsOyBtc28tc3BhY2VydW46ICYj Mzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDAuMDAwMHB0Ij4mbmJzcDsmbmJzcDs8L1NQ QU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMC41cHQ7IEZPTlQtRkFNSUxZOiBIZWx2ZXRp Y2E7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMC4wMDAw cHQiPjxvOnA+PC9vOnA+PC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCANCnN0eWxlPSJU RVhULUFMSUdOOiBsZWZ0OyBtc28tcGFnaW5hdGlvbjogd2lkb3ctb3JwaGFuOyBtc28tbGF5b3V0 LWdyaWQtYWxpZ246IG5vbmUiPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTNwdDsgRk9OVC1G QU1JTFk6IEFyaWFsOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5p bmc6IDAuMDAwMHB0Ij5UZWwuOiZuYnNwOyZuYnNwOzg2LTU3Ni04NDE5NjYxOShleHQuNjA4PC9T UEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTNwdDsgRk9OVC1GQU1JTFk6IEFyaWFsOyBt c28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDAuMDAwMHB0Ij4p Jm5ic3A7Jm5ic3A7PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTNwdDsgRk9OVC1G QU1JTFk6IEFyaWFsOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5p bmc6IDAuMDAwMHB0Ij48bzpwPjwvbzpwPjwvU1BBTj48L1A+DQo8UCBjbGFzcz1Nc29Ob3JtYWwg DQpzdHlsZT0iVEVYVC1BTElHTjogbGVmdDsgbXNvLXBhZ2luYXRpb246IHdpZG93LW9ycGhhbjsg bXNvLWxheW91dC1ncmlkLWFsaWduOiBub25lIj48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEz cHQ7IEZPTlQtRkFNSUxZOiBBcmlhbDsgbXNvLXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28t Zm9udC1rZXJuaW5nOiAwLjAwMDBwdCI+TW9iOiZuYnNwOzg2Jm5ic3A7KDApJm5ic3A7MTM4IA0K MjMzNyA2MDgyPC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCANCnN0eWxlPSJURVhULUFM SUdOOiBsZWZ0OyBtc28tcGFnaW5hdGlvbjogd2lkb3ctb3JwaGFuOyBtc28tbGF5b3V0LWdyaWQt YWxpZ246IG5vbmUiPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTNwdDsgRk9OVC1GQU1JTFk6 IEFyaWFsOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDAu MDAwMHB0Ij48L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxM3B0OyBGT05ULUZBTUlM WTogQXJpYWw7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzog MC4wMDAwcHQiPkUtbWFpbDombmJzcDsmbmJzcDs8QSANCmhyZWY9Im1haWx0bzptYXJjb0Bjbnlq aWUuY29tIj5tYXJjb0BjbnlqaWUuY29tPC9BPjwvU1BBTj48L1A+PC9CT0RZPjwvSFRNTD4NCg0K From mina.shinndy68@gmail.com Sun Jun 12 15:31:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_MESSAGE,T_DKIM_INVALID autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 462C37CA0 for ; Sun, 12 Jun 2016 15:31:39 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id ED3BF304032 for ; Sun, 12 Jun 2016 13:31:38 -0700 (PDT) X-ASG-Debug-ID: 1465763495-04bdf0657f828d0001-NocioJ Received: from mail-wm0-f65.google.com (mail-wm0-f65.google.com [74.125.82.65]) by cuda.sgi.com with ESMTP id UVBSUp2VmxE9XKAH (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Sun, 12 Jun 2016 13:31:36 -0700 (PDT) X-Barracuda-Envelope-From: mina.shinndy68@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f65.google.com[74.125.82.65] X-Barracuda-Apparent-Source-IP: 74.125.82.65 Received: by mail-wm0-f65.google.com with SMTP id r5so10451272wmr.0 for ; Sun, 12 Jun 2016 13:31:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=6Uf+iHoIJysIy9vMnrwZb1gqQqgEoCwZz+CSo2MCpv8=; b=YTHjDBxoDUtOCRl3pX8Dlaa5WyBzTBdJXIKEECKGv/Y+aTFUE2EQrIflwWMldV6ZDQ k7x1nB3Wdt5wIPbMbcwA/uwvEe8lETCnG5oPN7Re3j7myIPOysZdgJpoLtEbXFihXPW5 Fm9dO9+4GIqiZqJM0XJtIWq6LjHheIg6vJPhQiTxjhxlerHi9pvwRj44Nkif1yGcss/l ko+i623OlRAWI7P+6xaHj8Yg8RoalKkXHFknuJDACTb4w0JH21hMinQYKES3tiH3WMHp Tcbt6edgBMzI3aj17iR6JMKXt1jamyyy6aa+dlknOf6OZhOxwUO2EJfgZr6f0s1JglY/ xF6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=6Uf+iHoIJysIy9vMnrwZb1gqQqgEoCwZz+CSo2MCpv8=; b=LkuLeT4GwNERTn4EETdIy5OGyuRUCegVlr/CR4YrSLnp3saFIoeyZyqd4iJ2L+hcyN 7DWghS0AQzYDtNcUPesly2m259BX4hYcUFJEHpDFKddLan0v7OzeT2XUcHo4IFrCIl3O KeXBLOgSNe/Iio7IBgW7f8gYhrygdC3wZW1lWXBWZUIeNslzrfK8+SsWhycP52pyC/V2 M/ZQz+vbDHVHDaIK26dv5Ujz7fWW2Yw/L54hMVsRNqtOAmPiacepyI8MMPH+intbZws4 7XfI+a4JSuNmutkmUNHz69r6Y08vQrgqKTb4kTCmc5p7dXtTbi01isp2weVjN8Oui6UI VZrg== X-Gm-Message-State: ALyK8tJzKsL51p6ofOVUIA+BSCJv70AahqOjat9AWW++X+9P0vs2Pw2+KQwmDmKphchHQTfMF5kd5TNnoKgo1g== X-Received: by 10.28.134.199 with SMTP id i190mr8682072wmd.26.1465763494983; Sun, 12 Jun 2016 13:31:34 -0700 (PDT) MIME-Version: 1.0 Received: by 10.28.3.132 with HTTP; Sun, 12 Jun 2016 13:31:33 -0700 (PDT) From: Juan Fang Date: Sun, 12 Jun 2016 21:31:33 +0100 Message-ID: Subject: New Order ( Shanzy Trading Co., Ltd ) To: undisclosed-recipients:; X-ASG-Orig-Subj: New Order ( Shanzy Trading Co., Ltd ) Content-Type: multipart/alternative; boundary=001a11442338717ec105351aa8cd X-Barracuda-Connect: mail-wm0-f65.google.com[74.125.82.65] X-Barracuda-Start-Time: 1465763496 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1613 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30379 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --001a11442338717ec105351aa8cd Content-Type: text/plain; charset=UTF-8 Hello, Good Morning, We currently have a requirement for your product. Please advise your MOQ and payment terms for first time buyer so we can inform our customer accordingly. Please kindly send all the necessary details. Looking forward to hear from you. Juan Fang Shanzy Trading Co., Ltd (TRADING) 19A Fung Chi Tsuen, Kwoloon, Hong Kong (CHINA) TEL: +852 - 94587345 FAX: +852 - 94596617 www.shanzzytrading.com --001a11442338717ec105351aa8cd Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hello,

Good Morning,

We currently have a requirement for your product. Please = advise your MOQ and payment terms for first time buyer so we can inform our= customer accordingly.

Please kindly send all the = necessary details.


Looking forward = to hear from you.

Juan Fang

=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0=C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0

<= /div>

Shanzy Trading Co., Ltd
=C2=A0 =C2=A0 =C2=A0(TRADING)=
19A Fung Chi Tsuen, Kwoloon, =C2=A0 =C2= =A0=C2=A0
=C2=A0 =C2=A0 =C2=A0Hong= Kong (CHINA)
TEL: +852 - 94587345= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0
FAX: +852 - 94596617
--001a11442338717ec105351aa8cd-- From martin.aleksov@gmail.com Mon Jun 13 01:28:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 978E77CA0 for ; Mon, 13 Jun 2016 01:28:23 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 23A7EAC001 for ; Sun, 12 Jun 2016 23:28:20 -0700 (PDT) X-ASG-Debug-ID: 1465799293-04bdf065808f920001-NocioJ Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by cuda.sgi.com with ESMTP id YFTcobuIflLpVb4l (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Sun, 12 Jun 2016 23:28:14 -0700 (PDT) X-Barracuda-Envelope-From: martin.aleksov@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Apparent-Source-IP: 74.125.82.67 Received: by mail-wm0-f67.google.com with SMTP id k184so12196768wme.2 for ; Sun, 12 Jun 2016 23:28:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=to:from:subject:message-id:date:user-agent:mime-version :content-transfer-encoding; bh=1J0h2mBB/rDTd1gUffMOCcuLEx9Gc7ePad1meWxx6KY=; b=rY9BA+WiFxLXjc+XCS3JyaRhs4abdfjx4LPap3a0TbQgCfW9Jl27Xpaq76+h298TK4 kbKqLsu8NP3Gh62FTnAO7KnFW8UYIrrJyFI7RHK5y6Yei1YTBG7GZyXwk+qhhpqVsYgs grWC69DvHIeouSy0yhCpkPVfYW9CEg5xDJ0ypFNMF1ZyFHkL8ncQKv/VqmBVuT8wjNlw uaGEyDZVALUYeuTuIQebvPB3+5SwykaZCX9XGvD99YUNGTm3L4TGl7dYJCE9D0ECVIgW unVEnpALX+rFPZ4/elKYSL6uwDZC/WazgeDtB8FXKn/k0hjQoqI7n7UynTlGvFAnVslN uiNw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-transfer-encoding; bh=1J0h2mBB/rDTd1gUffMOCcuLEx9Gc7ePad1meWxx6KY=; b=ZSbgSgf0+7aafgRyKfQ53nxIGy2EzxGV656Yok3BySft6kBIKnAvQorxQv1t1DyfSC uhYFagBGWeStc+J9Du04VHFgnzUJNSG/1UtpB5080ip/7iIgcdNGrRo64oJatgR4foIF wuWAXXkJhszlHgPY9JnRg5l96lXILDplaapdgz8TjMhW6lQsnvWd2JjHo67e464V80eF 7C6Cl61PCkjOP3Z7k2+tohilJWjdcw+1AvQmoRUQoIMxN4B6w5rkuvtAmc1uVSrczoqS jreJ2h1zx86ci59He7TAsXm3VEo5H1RcYYEHQPPq08kgKZlcPXVcb26giHU/0hQ/9Kie 450g== X-Gm-Message-State: ALyK8tKjx+0qppca7ACIOYfQWHb8YEqHF1UcP6zcaBHby86HW/yrlOVhTEfKxe3hjBVyiQ== X-Received: by 10.194.134.230 with SMTP id pn6mr749246wjb.165.1465799292693; Sun, 12 Jun 2016 23:28:12 -0700 (PDT) Received: from [10.101.4.32] ([195.170.178.154]) by smtp.gmail.com with ESMTPSA id d137sm5623294wmd.12.2016.06.12.23.28.11 for (version=TLSv1/SSLv3 cipher=OTHER); Sun, 12 Jun 2016 23:28:12 -0700 (PDT) To: xfs@oss.sgi.com From: Martin Aleksov Subject: Metadata corruption Message-ID: <7494383b-a153-7a79-b872-42ac6506ac9e@gmail.com> X-ASG-Orig-Subj: Metadata corruption Date: Mon, 13 Jun 2016 09:27:57 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Start-Time: 1465799294 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11734 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30390 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature HiThere, I'm using XFS on Arch linux.Each 2 days I'm receiving this error: Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 while doing this: [martin@marto ~]$ sudo xfs_db -c frag -r /dev/sda2 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 xfs_db: out of memory Here is the needed information: Linux marto 4.6.2-1-ARCH #1 SMP PREEMPT Wed Jun 8 08:40:59 CEST 2016 x86_64 GNU/Linux ================================================ xfs_repair version 4.5.0 ================================================== lscpu Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 2 Core(s) per socket: 2 Socket(s): 1 NUMA node(s): 1 Vendor ID: GenuineIntel CPU family: 6 Model: 58 Model name: Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz Stepping: 9 CPU MHz: 1213.964 CPU max MHz: 3100.0000 CPU min MHz: 1200.0000 BogoMIPS: 4990.55 Virtualization: VT-x L1d cache: 32K L1i cache: 32K L2 cache: 256K L3 cache: 3072K NUMA node0 CPU(s): 0-3 Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm epb tpr_shadow vnmi flexpriority ept vpid fsgsbase smep erms xsaveopt dtherm ida arat pln pts ============================================================================== cat /proc/meminfo MemTotal: 16025984 kB MemFree: 13078108 kB MemAvailable: 14024292 kB Buffers: 5740 kB Cached: 1373716 kB SwapCached: 0 kB Active: 1656728 kB Inactive: 997388 kB Active(anon): 1346700 kB Inactive(anon): 158028 kB Active(file): 310028 kB Inactive(file): 839360 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 2047996 kB SwapFree: 2047996 kB Dirty: 0 kB Writeback: 0 kB AnonPages: 1128564 kB Mapped: 403056 kB Shmem: 230068 kB Slab: 131908 kB SReclaimable: 97016 kB SUnreclaim: 34892 kB KernelStack: 7040 kB PageTables: 17108 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 10060988 kB Committed_AS: 3812328 kB VmallocTotal: 34359738367 kB VmallocUsed: 0 kB VmallocChunk: 0 kB HardwareCorrupted: 0 kB AnonHugePages: 317440 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 82280 kB DirectMap2M: 16279552 kB ============================================== cat /proc/mounts proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 sys /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 dev /dev devtmpfs rw,nosuid,relatime,size=8009624k,nr_inodes=2002406,mode=755 0 0 run /run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0 /dev/sda2 / xfs rw,relatime,attr2,inode64,noquota 0 0 securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0 tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0 devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,mode=755 0 0 cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0 pstore /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0 cgroup /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0 cgroup /sys/fs/cgroup/net_cls cgroup rw,nosuid,nodev,noexec,relatime,net_cls 0 0 cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0 cgroup /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0 cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0 cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpu,cpuacct 0 0 cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0 cgroup /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatime,devices 0 0 systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=26,pgrp=1,timeout=0,minproto=5,maxproto=5,direct 0 0 mqueue /dev/mqueue mqueue rw,relatime 0 0 debugfs /sys/kernel/debug debugfs rw,relatime 0 0 hugetlbfs /dev/hugepages hugetlbfs rw,relatime 0 0 configfs /sys/kernel/config configfs rw,relatime 0 0 tmpfs /tmp tmpfs rw 0 0 /dev/sda4 /home xfs rw,relatime,attr2,inode64,noquota 0 0 /dev/sda1 /boot ext4 rw,relatime,data=ordered 0 0 /dev/sdb1 /var xfs rw,relatime,attr2,inode64,noquota 0 0 /dev/sdb2 /data xfs rw,relatime,attr2,inode64,noquota 0 0 tmpfs /run/user/1000 tmpfs rw,nosuid,nodev,relatime,size=1602600k,mode=700,uid=1000,gid=100 0 0 gvfsd-fuse /run/user/1000/gvfs fuse.gvfsd-fuse rw,nosuid,nodev,relatime,user_id=1000,group_id=100 0 0 fusectl /sys/fs/fuse/connections fusectl rw,relatime 0 0 ================================================================= cat /proc/partitions major minor #blocks name 8 0 244198584 sda 8 1 307200 sda1 8 2 20480000 sda2 8 3 2048000 sda3 8 4 221362176 sda4 8 16 488386584 sdb 8 17 20971520 sdb1 8 18 467414016 sdb2 ====================================================== I'm Using Samsumng 850 Evo SSD and normal HDD. ================================================= sudo hdparm -I /dev/sda |grep -i "write ca" [sudo] password for martin: * Write cache ================================================= [martin@marto ~]$ sudo hdparm -I /dev/sdb |grep -i "write ca" * Write cache ======================================================== xfs_info /dev/sda2 meta-data=/dev/sda2 isize=512 agcount=4, agsize=1280000 blks = sectsz=512 attr=2, projid32bit=1 = crc=1 finobt=1 spinodes=0 data = bsize=4096 blocks=5120000, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=1 log =internal bsize=4096 blocks=2560, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 ========================================================================== [martin@marto ~]$ dmesg |grep -i xfs [ 3.659623] SGI XFS with ACLs, security attributes, realtime, no debug enabled [ 3.662257] XFS (sda2): Mounting V5 Filesystem [ 3.676309] XFS (sda2): Ending clean mount [ 4.064618] XFS (sda4): Mounting V5 Filesystem [ 4.068012] XFS (sdb2): Mounting V5 Filesystem [ 4.074383] XFS (sdb1): Mounting V5 Filesystem [ 4.082505] XFS (sda4): Ending clean mount [ 4.299465] XFS (sdb1): Ending clean mount [ 4.300056] XFS (sdb2): Ending clean mount After reboot the error is gone.Any advise what is causing this error and how to fix the issue permenantly? From martin.aleksov@gmail.com Mon Jun 13 01:41:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 238307CA0 for ; Mon, 13 Jun 2016 01:41:50 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id A04A9AC002 for ; Sun, 12 Jun 2016 23:41:49 -0700 (PDT) X-ASG-Debug-ID: 1465800105-04bdf065818fe10001-NocioJ Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by cuda.sgi.com with ESMTP id ojQ7SDEKk2jbD93w (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Sun, 12 Jun 2016 23:41:46 -0700 (PDT) X-Barracuda-Envelope-From: martin.aleksov@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Apparent-Source-IP: 74.125.82.67 Received: by mail-wm0-f67.google.com with SMTP id n184so12274925wmn.1 for ; Sun, 12 Jun 2016 23:41:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=subject:to:references:from:message-id:date:user-agent:mime-version :in-reply-to:content-transfer-encoding; bh=mCvDpMDJaxbKB3pe9pA+xi8FwvzsXMB4tg+VVMSUQak=; b=U5d4VGSjOW84V3xk+HFBSPzNLqs0dSIUsBrbToWBfni3Ui2lH0AsGVirgr5JFw9465 RiUOS9uCkDcNt+zBFLipTJhJxlmkIMPdDfi3rDhp0vLOd3xfW/miupIHVGR1YJKusEh5 uwenTqmEM52whhJikknfrKI5CZdN6lbfkHE6sDVQfd75lPJPyxzGKUiyi8PGDmNNSH5x lUepq3Zfvd7ATuV7qOIK+tLdSONHISn52erCO+HKdEXUdF+qqDIadRDgFpTuoyxlo4Xz gzdEdcaEwsHXwXA7p/rlIfc4CPKneSlYZ2kTx4QFhrMFmwE+FAxngDN0ALMAXJrTmgLD VbgQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=mCvDpMDJaxbKB3pe9pA+xi8FwvzsXMB4tg+VVMSUQak=; b=TMSof2yiYK9Dm7KFh8LsMJJV6QzLl52cMNOJQv/3pLAk9pNvdUPFMRZPPKlOsfMPjO bVM9pbMe6fKhiKSzRmKgeWjqF/UXAwYbg5qt221JdsBZLrAp6pn2qOJHJvyqrzRzzyI9 dGY1ZvkI+bgtLdSiIGeCexhsh60YS99Xj+GjEcveUxy2/QppFrPN3tqCSwxhVhkGLjBh zN+R+lpq63OY1brknKx2pXE1KOXTtRxJkPo+rNLkVj1Yj1ylZViYZVerwX1kCnz1IE1e GRM6djT14Noe5x+6C44f9GtbuiPfxectLsKpDq+9SA2AJtBnfDINZjlRTazcE5wX64d4 LSIA== X-Gm-Message-State: ALyK8tKSB6t+bf4M9VW+xFRIDEK5aOfnFq1P0IYMTe5iq6nKggz1fMAN/mEveLtKY/zRrg== X-Received: by 10.28.157.199 with SMTP id g190mr5336721wme.2.1465800104980; Sun, 12 Jun 2016 23:41:44 -0700 (PDT) Received: from [10.101.4.32] ([195.170.178.154]) by smtp.gmail.com with ESMTPSA id hf7sm6875226wjc.48.2016.06.12.23.41.44 for (version=TLSv1/SSLv3 cipher=OTHER); Sun, 12 Jun 2016 23:41:44 -0700 (PDT) Subject: Re: Metadata corruption To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: Metadata corruption References: <7494383b-a153-7a79-b872-42ac6506ac9e@gmail.com> From: Martin Aleksov Message-ID: <52b9dc9e-ae36-4f66-454a-b8f2d4b0c6d6@gmail.com> Date: Mon, 13 Jun 2016 09:41:29 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <7494383b-a153-7a79-b872-42ac6506ac9e@gmail.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Start-Time: 1465800106 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13043 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30390 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature Please note that after executing: [martin@marto ~]$ sudo xfs_db -c blockget -r /dev/sda2 ERROR: The filesystem has valuable metadata changes in a log which needs to be replayed. Mount the filesystem to replay the log, and unmount it before re-running xfs_db. If you are unable to mount the filesystem, then use the xfs_repair -L option to destroy the log and attempt a repair. Note that destroying the log may cause corruption -- please attempt a mount of the filesystem before doing this. and after that [martin@marto ~]$ sudo xfs_db -c frag -r /dev/sda2 actual 124994, ideal 124469, fragmentation factor 0.42% the error is gone.Any ideas about that and what cause it? On 06/13/2016 09:27 AM, Martin Aleksov wrote: > HiThere, > > I'm using XFS on Arch linux.Each 2 days I'm receiving this error: > > > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > > while doing this: > > > [martin@marto ~]$ sudo xfs_db -c frag -r /dev/sda2 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > xfs_db: out of memory > > > > Here is the needed information: > > > Linux marto 4.6.2-1-ARCH #1 SMP PREEMPT Wed Jun 8 08:40:59 CEST 2016 > x86_64 GNU/Linux > ================================================ > > xfs_repair version 4.5.0 > ================================================== > > lscpu > Architecture: x86_64 > CPU op-mode(s): 32-bit, 64-bit > Byte Order: Little Endian > CPU(s): 4 > On-line CPU(s) list: 0-3 > Thread(s) per core: 2 > Core(s) per socket: 2 > Socket(s): 1 > NUMA node(s): 1 > Vendor ID: GenuineIntel > CPU family: 6 > Model: 58 > Model name: Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz > Stepping: 9 > CPU MHz: 1213.964 > CPU max MHz: 3100.0000 > CPU min MHz: 1200.0000 > BogoMIPS: 4990.55 > Virtualization: VT-x > L1d cache: 32K > L1i cache: 32K > L2 cache: 256K > L3 cache: 3072K > NUMA node0 CPU(s): 0-3 > Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr > pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe > syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl > xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor > ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt > tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm epb tpr_shadow vnmi > flexpriority ept vpid fsgsbase smep erms xsaveopt dtherm ida arat pln pts > ============================================================================== > > cat /proc/meminfo > MemTotal: 16025984 kB > MemFree: 13078108 kB > MemAvailable: 14024292 kB > Buffers: 5740 kB > Cached: 1373716 kB > SwapCached: 0 kB > Active: 1656728 kB > Inactive: 997388 kB > Active(anon): 1346700 kB > Inactive(anon): 158028 kB > Active(file): 310028 kB > Inactive(file): 839360 kB > Unevictable: 0 kB > Mlocked: 0 kB > SwapTotal: 2047996 kB > SwapFree: 2047996 kB > Dirty: 0 kB > Writeback: 0 kB > AnonPages: 1128564 kB > Mapped: 403056 kB > Shmem: 230068 kB > Slab: 131908 kB > SReclaimable: 97016 kB > SUnreclaim: 34892 kB > KernelStack: 7040 kB > PageTables: 17108 kB > NFS_Unstable: 0 kB > Bounce: 0 kB > WritebackTmp: 0 kB > CommitLimit: 10060988 kB > Committed_AS: 3812328 kB > VmallocTotal: 34359738367 kB > VmallocUsed: 0 kB > VmallocChunk: 0 kB > HardwareCorrupted: 0 kB > AnonHugePages: 317440 kB > HugePages_Total: 0 > HugePages_Free: 0 > HugePages_Rsvd: 0 > HugePages_Surp: 0 > Hugepagesize: 2048 kB > DirectMap4k: 82280 kB > DirectMap2M: 16279552 kB > ============================================== > cat /proc/mounts > proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 > sys /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 > dev /dev devtmpfs > rw,nosuid,relatime,size=8009624k,nr_inodes=2002406,mode=755 0 0 > run /run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0 > /dev/sda2 / xfs rw,relatime,attr2,inode64,noquota 0 0 > securityfs /sys/kernel/security securityfs > rw,nosuid,nodev,noexec,relatime 0 0 > tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0 > devpts /dev/pts devpts > rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 > tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,mode=755 0 0 > cgroup /sys/fs/cgroup/systemd cgroup > rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd > 0 0 > pstore /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0 > cgroup /sys/fs/cgroup/memory cgroup > rw,nosuid,nodev,noexec,relatime,memory 0 0 > cgroup /sys/fs/cgroup/net_cls cgroup > rw,nosuid,nodev,noexec,relatime,net_cls 0 0 > cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0 > cgroup /sys/fs/cgroup/cpuset cgroup > rw,nosuid,nodev,noexec,relatime,cpuset 0 0 > cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0 > cgroup /sys/fs/cgroup/cpu,cpuacct cgroup > rw,nosuid,nodev,noexec,relatime,cpu,cpuacct 0 0 > cgroup /sys/fs/cgroup/freezer cgroup > rw,nosuid,nodev,noexec,relatime,freezer 0 0 > cgroup /sys/fs/cgroup/devices cgroup > rw,nosuid,nodev,noexec,relatime,devices 0 0 > systemd-1 /proc/sys/fs/binfmt_misc autofs > rw,relatime,fd=26,pgrp=1,timeout=0,minproto=5,maxproto=5,direct 0 0 > mqueue /dev/mqueue mqueue rw,relatime 0 0 > debugfs /sys/kernel/debug debugfs rw,relatime 0 0 > hugetlbfs /dev/hugepages hugetlbfs rw,relatime 0 0 > configfs /sys/kernel/config configfs rw,relatime 0 0 > tmpfs /tmp tmpfs rw 0 0 > /dev/sda4 /home xfs rw,relatime,attr2,inode64,noquota 0 0 > /dev/sda1 /boot ext4 rw,relatime,data=ordered 0 0 > /dev/sdb1 /var xfs rw,relatime,attr2,inode64,noquota 0 0 > /dev/sdb2 /data xfs rw,relatime,attr2,inode64,noquota 0 0 > tmpfs /run/user/1000 tmpfs > rw,nosuid,nodev,relatime,size=1602600k,mode=700,uid=1000,gid=100 0 0 > gvfsd-fuse /run/user/1000/gvfs fuse.gvfsd-fuse > rw,nosuid,nodev,relatime,user_id=1000,group_id=100 0 0 > fusectl /sys/fs/fuse/connections fusectl rw,relatime 0 0 > ================================================================= > > cat /proc/partitions > major minor #blocks name > > 8 0 244198584 sda > 8 1 307200 sda1 > 8 2 20480000 sda2 > 8 3 2048000 sda3 > 8 4 221362176 sda4 > 8 16 488386584 sdb > 8 17 20971520 sdb1 > 8 18 467414016 sdb2 > > ====================================================== > > > I'm Using Samsumng 850 Evo SSD and normal HDD. > > ================================================= > > sudo hdparm -I /dev/sda |grep -i "write ca" > [sudo] password for martin: > * Write cache > > ================================================= > > [martin@marto ~]$ sudo hdparm -I /dev/sdb |grep -i "write ca" > * Write cache > > ======================================================== > > > > xfs_info /dev/sda2 > meta-data=/dev/sda2 isize=512 agcount=4, agsize=1280000 blks > = sectsz=512 attr=2, projid32bit=1 > = crc=1 finobt=1 spinodes=0 > data = bsize=4096 blocks=5120000, imaxpct=25 > = sunit=0 swidth=0 blks > naming =version 2 bsize=4096 ascii-ci=0 ftype=1 > log =internal bsize=4096 blocks=2560, version=2 > = sectsz=512 sunit=0 blks, lazy-count=1 > realtime =none extsz=4096 blocks=0, rtextents=0 > > ========================================================================== > [martin@marto ~]$ dmesg |grep -i xfs > [ 3.659623] SGI XFS with ACLs, security attributes, realtime, no > debug enabled > [ 3.662257] XFS (sda2): Mounting V5 Filesystem > [ 3.676309] XFS (sda2): Ending clean mount > [ 4.064618] XFS (sda4): Mounting V5 Filesystem > [ 4.068012] XFS (sdb2): Mounting V5 Filesystem > [ 4.074383] XFS (sdb1): Mounting V5 Filesystem > [ 4.082505] XFS (sda4): Ending clean mount > [ 4.299465] XFS (sdb1): Ending clean mount > [ 4.300056] XFS (sdb2): Ending clean mount > > After reboot the error is gone.Any advise what is causing this error and > how to fix the issue permenantly? > > > From stefanrin@gmail.com Mon Jun 13 01:45:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5E50E7CA2 for ; Mon, 13 Jun 2016 01:45:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id C740FAC001 for ; Sun, 12 Jun 2016 23:45:49 -0700 (PDT) X-ASG-Debug-ID: 1465800347-04cb6c381673980001-NocioJ Received: from mail-wm0-f51.google.com (mail-wm0-f51.google.com [74.125.82.51]) by cuda.sgi.com with ESMTP id PBp2xejQRNbPtWNY (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Sun, 12 Jun 2016 23:45:47 -0700 (PDT) X-Barracuda-Envelope-From: stefanrin@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f51.google.com[74.125.82.51] X-Barracuda-Apparent-Source-IP: 74.125.82.51 Received: by mail-wm0-f51.google.com with SMTP id k204so64778790wmk.0 for ; Sun, 12 Jun 2016 23:45:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=qyUWhoptEpLkESGDae33CAdCIvPGeZ7Zn5x7KOcIGZw=; b=WjYfpP+P0e462u2Lf+aUzhMJhEVNERelpAMuoQD2pGumh0n852K2OOhcwN5nJFqynE lD9tZtqtJ2yTcFBszli2autZnkPid6KWew/acMUj70gpAUXVgVlhKENhPsnmYligQQeF AB92znrAN8DLelkL4i9aBUCjpMlsVUzGQQZE020ZUWdOWIlHLarEe8QaUjnX2yFP9KCs M4c8N6AwOBRyc59C30cKNdjP8TmRquBJOI9geDYRliDEexcOFlhGFLxKcx7v/NOGubcP fvIAbB1bUcfsbm9Bw5gdoWyS2UDIdFkhPIqd6/uSTR6lzz5aDpSQCIgx4DCUapmdwnXj Cxlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=qyUWhoptEpLkESGDae33CAdCIvPGeZ7Zn5x7KOcIGZw=; b=jA4jplTJ51u0GixSc00x26/68k65DQmWdMpYtojdkDOfUJJyjg73icEvkNWc4UceIL bKAWgjB/rIOXf3lVWQpOceZu9hE29wTQHeUzNcwiEe/xcqaX2a2qY717YzC9RiZx1FX8 /98LTKWTCgDj/uzZMejG5j/BTa+OYSBCmIYzg0Gjriq8hWbDEkwKf7dOkK/F1BINF1xf c6ATVs49vKT0lIRsRapKO6ZeLXF3bjzo1904MoGi1/0C7kFMeKMH7e+jfmCU8MGyloC5 qL8IDIPoCjFJCo3tbhv5NQ/Vnmorgga7ob7kKo+pjo2VrJ3l7yhcwtdfpG9/ES2Mx12H Qukg== X-Gm-Message-State: ALyK8tLWZhFE6Bz9soOCQ8ENUUaEWpYTESr3+JAD31fMrMvxKgRwxNZjObaEUGNCRY9Foq6GQmGtWIJdzvsFzg== X-Received: by 10.194.103.4 with SMTP id fs4mr13999827wjb.10.1465800346684; Sun, 12 Jun 2016 23:45:46 -0700 (PDT) MIME-Version: 1.0 Received: by 10.194.17.129 with HTTP; Sun, 12 Jun 2016 23:45:45 -0700 (PDT) In-Reply-To: <52b9dc9e-ae36-4f66-454a-b8f2d4b0c6d6@gmail.com> References: <7494383b-a153-7a79-b872-42ac6506ac9e@gmail.com> <52b9dc9e-ae36-4f66-454a-b8f2d4b0c6d6@gmail.com> From: Stefan Ring Date: Mon, 13 Jun 2016 08:45:45 +0200 Message-ID: Subject: Re: Metadata corruption To: Martin Aleksov X-ASG-Orig-Subj: Re: Metadata corruption Cc: Linux fs XFS Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-wm0-f51.google.com[74.125.82.51] X-Barracuda-Start-Time: 1465800347 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 669 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_DOMAIN_MATCH, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30390 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient Domain On Mon, Jun 13, 2016 at 8:41 AM, Martin Aleksov wrote: > Please note that after executing: > > [martin@marto ~]$ sudo xfs_db -c blockget -r /dev/sda2 > > > ERROR: The filesystem has valuable metadata changes in a log which needs to > be replayed. Mount the filesystem to replay the log, and unmount it before > re-running xfs_db. If you are unable to mount the filesystem, then use > the xfs_repair -L option to destroy the log and attempt a repair. > Note that destroying the log may cause corruption -- please attempt a mount > of the filesystem before doing this. > > and after that > the error is gone. After what? From bfoster@redhat.com Mon Jun 13 06:27:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C2D827CA0 for ; Mon, 13 Jun 2016 06:27:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 950578F8035 for ; Mon, 13 Jun 2016 04:27:43 -0700 (PDT) X-ASG-Debug-ID: 1465817261-04cb6c381379130001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 8SlurXCE0XEwEnvH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 13 Jun 2016 04:27:42 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DE29063E11; Mon, 13 Jun 2016 11:27:40 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-81.bos.redhat.com [10.18.41.81]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5DBRepw002988; Mon, 13 Jun 2016 07:27:40 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 02B30122ECF; Mon, 13 Jun 2016 07:27:39 -0400 (EDT) Date: Mon, 13 Jun 2016 07:27:39 -0400 From: Brian Foster To: Martin Aleksov Cc: xfs@oss.sgi.com Subject: Re: Metadata corruption Message-ID: <20160613112738.GA4730@bfoster.bfoster> X-ASG-Orig-Subj: Re: Metadata corruption References: <7494383b-a153-7a79-b872-42ac6506ac9e@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <7494383b-a153-7a79-b872-42ac6506ac9e@gmail.com> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 13 Jun 2016 11:27:40 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465817261 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12799 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 13, 2016 at 09:27:57AM +0300, Martin Aleksov wrote: > HiThere, > > I'm using XFS on Arch linux.Each 2 days I'm receiving this error: > > > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > > while doing this: > > > [martin@marto ~]$ sudo xfs_db -c frag -r /dev/sda2 sda2 is your root filesystem.. so I assume the filesystem is mounted when you run this? If so, this type of thing could be expected. Do you see errors in the logs otherwise? If not, I'd suggest to repeat this from a ramdisk or boot/recovery disk where the filesystem isn't mounted to confirm. Brian > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 > xfs_db: out of memory > > > > Here is the needed information: > > > Linux marto 4.6.2-1-ARCH #1 SMP PREEMPT Wed Jun 8 08:40:59 CEST 2016 > x86_64 GNU/Linux > ================================================ > > xfs_repair version 4.5.0 > ================================================== > > lscpu > Architecture: x86_64 > CPU op-mode(s): 32-bit, 64-bit > Byte Order: Little Endian > CPU(s): 4 > On-line CPU(s) list: 0-3 > Thread(s) per core: 2 > Core(s) per socket: 2 > Socket(s): 1 > NUMA node(s): 1 > Vendor ID: GenuineIntel > CPU family: 6 > Model: 58 > Model name: Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz > Stepping: 9 > CPU MHz: 1213.964 > CPU max MHz: 3100.0000 > CPU min MHz: 1200.0000 > BogoMIPS: 4990.55 > Virtualization: VT-x > L1d cache: 32K > L1i cache: 32K > L2 cache: 256K > L3 cache: 3072K > NUMA node0 CPU(s): 0-3 > Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr > pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe > syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good nopl > xtopology nonstop_tsc aperfmperf eagerfpu pni pclmulqdq dtes64 monitor > ds_cpl vmx est tm2 ssse3 cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic popcnt > tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm epb tpr_shadow vnmi > flexpriority ept vpid fsgsbase smep erms xsaveopt dtherm ida arat pln pts > ============================================================================== > > cat /proc/meminfo > MemTotal: 16025984 kB > MemFree: 13078108 kB > MemAvailable: 14024292 kB > Buffers: 5740 kB > Cached: 1373716 kB > SwapCached: 0 kB > Active: 1656728 kB > Inactive: 997388 kB > Active(anon): 1346700 kB > Inactive(anon): 158028 kB > Active(file): 310028 kB > Inactive(file): 839360 kB > Unevictable: 0 kB > Mlocked: 0 kB > SwapTotal: 2047996 kB > SwapFree: 2047996 kB > Dirty: 0 kB > Writeback: 0 kB > AnonPages: 1128564 kB > Mapped: 403056 kB > Shmem: 230068 kB > Slab: 131908 kB > SReclaimable: 97016 kB > SUnreclaim: 34892 kB > KernelStack: 7040 kB > PageTables: 17108 kB > NFS_Unstable: 0 kB > Bounce: 0 kB > WritebackTmp: 0 kB > CommitLimit: 10060988 kB > Committed_AS: 3812328 kB > VmallocTotal: 34359738367 kB > VmallocUsed: 0 kB > VmallocChunk: 0 kB > HardwareCorrupted: 0 kB > AnonHugePages: 317440 kB > HugePages_Total: 0 > HugePages_Free: 0 > HugePages_Rsvd: 0 > HugePages_Surp: 0 > Hugepagesize: 2048 kB > DirectMap4k: 82280 kB > DirectMap2M: 16279552 kB > ============================================== > cat /proc/mounts > proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 > sys /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 > dev /dev devtmpfs > rw,nosuid,relatime,size=8009624k,nr_inodes=2002406,mode=755 0 0 > run /run tmpfs rw,nosuid,nodev,relatime,mode=755 0 0 > /dev/sda2 / xfs rw,relatime,attr2,inode64,noquota 0 0 > securityfs /sys/kernel/security securityfs > rw,nosuid,nodev,noexec,relatime 0 0 > tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0 > devpts /dev/pts devpts > rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 > tmpfs /sys/fs/cgroup tmpfs ro,nosuid,nodev,noexec,mode=755 0 0 > cgroup /sys/fs/cgroup/systemd cgroup > rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd > 0 0 > pstore /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0 > cgroup /sys/fs/cgroup/memory cgroup > rw,nosuid,nodev,noexec,relatime,memory 0 0 > cgroup /sys/fs/cgroup/net_cls cgroup > rw,nosuid,nodev,noexec,relatime,net_cls 0 0 > cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0 > cgroup /sys/fs/cgroup/cpuset cgroup > rw,nosuid,nodev,noexec,relatime,cpuset 0 0 > cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0 > cgroup /sys/fs/cgroup/cpu,cpuacct cgroup > rw,nosuid,nodev,noexec,relatime,cpu,cpuacct 0 0 > cgroup /sys/fs/cgroup/freezer cgroup > rw,nosuid,nodev,noexec,relatime,freezer 0 0 > cgroup /sys/fs/cgroup/devices cgroup > rw,nosuid,nodev,noexec,relatime,devices 0 0 > systemd-1 /proc/sys/fs/binfmt_misc autofs > rw,relatime,fd=26,pgrp=1,timeout=0,minproto=5,maxproto=5,direct 0 0 > mqueue /dev/mqueue mqueue rw,relatime 0 0 > debugfs /sys/kernel/debug debugfs rw,relatime 0 0 > hugetlbfs /dev/hugepages hugetlbfs rw,relatime 0 0 > configfs /sys/kernel/config configfs rw,relatime 0 0 > tmpfs /tmp tmpfs rw 0 0 > /dev/sda4 /home xfs rw,relatime,attr2,inode64,noquota 0 0 > /dev/sda1 /boot ext4 rw,relatime,data=ordered 0 0 > /dev/sdb1 /var xfs rw,relatime,attr2,inode64,noquota 0 0 > /dev/sdb2 /data xfs rw,relatime,attr2,inode64,noquota 0 0 > tmpfs /run/user/1000 tmpfs > rw,nosuid,nodev,relatime,size=1602600k,mode=700,uid=1000,gid=100 0 0 > gvfsd-fuse /run/user/1000/gvfs fuse.gvfsd-fuse > rw,nosuid,nodev,relatime,user_id=1000,group_id=100 0 0 > fusectl /sys/fs/fuse/connections fusectl rw,relatime 0 0 > ================================================================= > > cat /proc/partitions > major minor #blocks name > > 8 0 244198584 sda > 8 1 307200 sda1 > 8 2 20480000 sda2 > 8 3 2048000 sda3 > 8 4 221362176 sda4 > 8 16 488386584 sdb > 8 17 20971520 sdb1 > 8 18 467414016 sdb2 > > ====================================================== > > > I'm Using Samsumng 850 Evo SSD and normal HDD. > > ================================================= > > sudo hdparm -I /dev/sda |grep -i "write ca" > [sudo] password for martin: > * Write cache > > ================================================= > > [martin@marto ~]$ sudo hdparm -I /dev/sdb |grep -i "write ca" > * Write cache > > ======================================================== > > > > xfs_info /dev/sda2 > meta-data=/dev/sda2 isize=512 agcount=4, agsize=1280000 blks > = sectsz=512 attr=2, projid32bit=1 > = crc=1 finobt=1 spinodes=0 > data = bsize=4096 blocks=5120000, imaxpct=25 > = sunit=0 swidth=0 blks > naming =version 2 bsize=4096 ascii-ci=0 ftype=1 > log =internal bsize=4096 blocks=2560, version=2 > = sectsz=512 sunit=0 blks, lazy-count=1 > realtime =none extsz=4096 blocks=0, rtextents=0 > > ========================================================================== > [martin@marto ~]$ dmesg |grep -i xfs > [ 3.659623] SGI XFS with ACLs, security attributes, realtime, no > debug enabled > [ 3.662257] XFS (sda2): Mounting V5 Filesystem > [ 3.676309] XFS (sda2): Ending clean mount > [ 4.064618] XFS (sda4): Mounting V5 Filesystem > [ 4.068012] XFS (sdb2): Mounting V5 Filesystem > [ 4.074383] XFS (sdb1): Mounting V5 Filesystem > [ 4.082505] XFS (sda4): Ending clean mount > [ 4.299465] XFS (sdb1): Ending clean mount > [ 4.300056] XFS (sdb2): Ending clean mount > > After reboot the error is gone.Any advise what is causing this error and > how to fix the issue permenantly? > > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From sandeen@sandeen.net Mon Jun 13 10:49:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C849E7CA0 for ; Mon, 13 Jun 2016 10:49:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 9B817304032 for ; Mon, 13 Jun 2016 08:49:10 -0700 (PDT) X-ASG-Debug-ID: 1465832943-04cb6c3814806f0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id kMKF5L7FgnVW1XNp for ; Mon, 13 Jun 2016 08:49:03 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 74890B55 for ; Mon, 13 Jun 2016 10:49:03 -0500 (CDT) Subject: Re: Metadata corruption To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: Metadata corruption References: <7494383b-a153-7a79-b872-42ac6506ac9e@gmail.com> <20160613112738.GA4730@bfoster.bfoster> From: Eric Sandeen Message-ID: Date: Mon, 13 Jun 2016 10:49:02 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160613112738.GA4730@bfoster.bfoster> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465832943 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 901 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.10 X-Barracuda-Spam-Status: No, SCORE=1.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MV0613, BSF_SC0_SA085 X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30399 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 1.00 BSF_SC0_MV0613 BSF_SC0_MV0613 0.10 BSF_SC0_SA085 Custom Rule SA085 On 6/13/16 6:27 AM, Brian Foster wrote: > On Mon, Jun 13, 2016 at 09:27:57AM +0300, Martin Aleksov wrote: >> HiThere, >> >> I'm using XFS on Arch linux.Each 2 days I'm receiving this error: >> >> >> Metadata corruption detected at xfs_inode block 0x5bd20/0x8000 >> >> while doing this: >> >> >> [martin@marto ~]$ sudo xfs_db -c frag -r /dev/sda2 > > sda2 is your root filesystem.. so I assume the filesystem is mounted > when you run this? If so, this type of thing could be expected. Do you > see errors in the logs otherwise? If not, I'd suggest to repeat this > from a ramdisk or boot/recovery disk where the filesystem isn't mounted > to confirm. That's probably it. In addition, I would suggest not running the frag command, as it is largely useless: http://xfs.org/index.php/XFS_FAQ#Q:_The_xfs_db_.22frag.22_command_says_I.27m_over_50.25._Is_that_bad.3F -Eric From ben@decadent.org.uk Mon Jun 13 13:37:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D1E4F7CA0 for ; Mon, 13 Jun 2016 13:37:36 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4DC65AC003 for ; Mon, 13 Jun 2016 11:37:36 -0700 (PDT) X-ASG-Debug-ID: 1465843054-04cbb03f54ac6f0001-NocioJ Received: from shadbolt.e.decadent.org.uk (shadbolt.e.decadent.org.uk [88.96.1.126]) by cuda.sgi.com with ESMTP id CuOxzZnAeJ42PQoo (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 13 Jun 2016 11:37:34 -0700 (PDT) X-Barracuda-Envelope-From: ben@decadent.org.uk X-Barracuda-Effective-Source-IP: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Apparent-Source-IP: 88.96.1.126 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bCWjo-0007Ua-Li; Mon, 13 Jun 2016 19:37:28 +0100 Received: from ben by deadeye with local (Exim 4.87) (envelope-from ) id 1bCWjn-0005FO-Hj; Mon, 13 Jun 2016 19:37:27 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Brian Foster" , "Dave Chinner" , "Dave Chinner" , xfs@oss.sgi.com, "Jan Kara" Date: Mon, 13 Jun 2016 19:36:37 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 097/114] xfs: mmap lock needs to be inside freeze protection In-Reply-To: X-ASG-Orig-Subj: [PATCH 3.16 097/114] xfs: mmap lock needs to be inside freeze protection X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false X-Barracuda-Connect: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Start-Time: 1465843054 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1707 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30403 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 3.16.36-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Dave Chinner commit ec56b1f1fdc69599963574ce94cc5693d535dd64 upstream. Lock ordering for the new mmap lock needs to be: mmap_sem sb_start_pagefault i_mmap_lock page lock Right now xfs_vm_page_mkwrite gets this the wrong way around, While technically it cannot deadlock due to the current freeze ordering, it's still a landmine that might explode if we change anything in future. Hence we need to nest the locks correctly. Signed-off-by: Dave Chinner Reviewed-by: Jan Kara Reviewed-by: Brian Foster Signed-off-by: Dave Chinner Signed-off-by: Ben Hutchings Cc: Jan Kara Cc: xfs@oss.sgi.com --- fs/xfs/xfs_file.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1441,15 +1441,20 @@ xfs_filemap_page_mkwrite( struct vm_fault *vmf) { struct xfs_inode *ip = XFS_I(vma->vm_file->f_mapping->host); - int error; + int ret; trace_xfs_filemap_page_mkwrite(ip); + sb_start_pagefault(VFS_I(ip)->i_sb); + file_update_time(vma->vm_file); xfs_ilock(ip, XFS_MMAPLOCK_SHARED); - error = block_page_mkwrite(vma, vmf, xfs_get_blocks); + + ret = __block_page_mkwrite(vma, vmf, xfs_get_blocks); + xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); + sb_end_pagefault(VFS_I(ip)->i_sb); - return error; + return block_page_mkwrite_return(ret); } const struct file_operations xfs_file_operations = { From ben@decadent.org.uk Mon Jun 13 13:37:37 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id AE60C7CA1 for ; Mon, 13 Jun 2016 13:37:37 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6E9BF304032 for ; Mon, 13 Jun 2016 11:37:37 -0700 (PDT) X-ASG-Debug-ID: 1465843051-04bdf01e1307450001-NocioJ Received: from shadbolt.e.decadent.org.uk (shadbolt.e.decadent.org.uk [88.96.1.126]) by cuda.sgi.com with ESMTP id bvA8AukHDni882Zt (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 13 Jun 2016 11:37:32 -0700 (PDT) X-Barracuda-Envelope-From: ben@decadent.org.uk X-Barracuda-Effective-Source-IP: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Apparent-Source-IP: 88.96.1.126 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bCWjo-0007UV-PE; Mon, 13 Jun 2016 19:37:29 +0100 Received: from ben by deadeye with local (Exim 4.87) (envelope-from ) id 1bCWjn-0005F5-An; Mon, 13 Jun 2016 19:37:27 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Dave Chinner" , xfs@oss.sgi.com, "Jan Kara" , "Brian Foster" , "Dave Chinner" Date: Mon, 13 Jun 2016 19:36:37 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 093/114] xfs: use i_mmaplock on write faults In-Reply-To: X-ASG-Orig-Subj: [PATCH 3.16 093/114] xfs: use i_mmaplock on write faults X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false X-Barracuda-Connect: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Start-Time: 1465843052 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3213 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30403 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 3.16.36-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Dave Chinner commit 075a924d45cc69c75a35f20b4912b85aa98b180a upstream. Take the i_mmaplock over write page faults. These come through the ->page_mkwrite callout, so we need to wrap that calls with the i_mmaplock. This gives us a lock order of mmap_sem -> i_mmaplock -> page_lock -> i_lock. Also, move the page_mkwrite wrapper to the same region of xfs_file.c as the read fault wrappers and add a tracepoint. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Signed-off-by: Dave Chinner [bwh: Backported to 3.16: adjust context] Signed-off-by: Ben Hutchings Cc: Jan Kara Cc: xfs@oss.sgi.com --- fs/xfs/xfs_file.c | 39 ++++++++++++++++++++++++--------------- fs/xfs/xfs_trace.h | 1 + 2 files changed, 25 insertions(+), 15 deletions(-) --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -957,20 +957,6 @@ xfs_file_mmap( } /* - * mmap()d file has taken write protection fault and is being made - * writable. We can set the page state up correctly for a writable - * page, which means we can do correct delalloc accounting (ENOSPC - * checking!) and unwritten extent mapping. - */ -STATIC int -xfs_vm_page_mkwrite( - struct vm_area_struct *vma, - struct vm_fault *vmf) -{ - return block_page_mkwrite(vma, vmf, xfs_get_blocks); -} - -/* * This type is designed to indicate the type of offset we would like * to search from page cache for either xfs_seek_data() or xfs_seek_hole(). */ @@ -1443,6 +1429,29 @@ xfs_filemap_fault( return error; } +/* + * mmap()d file has taken write protection fault and is being made writable. We + * can set the page state up correctly for a writable page, which means we can + * do correct delalloc accounting (ENOSPC checking!) and unwritten extent + * mapping. + */ +STATIC int +xfs_filemap_page_mkwrite( + struct vm_area_struct *vma, + struct vm_fault *vmf) +{ + struct xfs_inode *ip = XFS_I(vma->vm_file->f_mapping->host); + int error; + + trace_xfs_filemap_page_mkwrite(ip); + + xfs_ilock(ip, XFS_MMAPLOCK_SHARED); + error = block_page_mkwrite(vma, vmf, xfs_get_blocks); + xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); + + return error; +} + const struct file_operations xfs_file_operations = { .llseek = xfs_file_llseek, .read = new_sync_read, @@ -1477,6 +1486,6 @@ const struct file_operations xfs_dir_fil static const struct vm_operations_struct xfs_file_vm_ops = { .fault = xfs_filemap_fault, .map_pages = filemap_map_pages, - .page_mkwrite = xfs_vm_page_mkwrite, + .page_mkwrite = xfs_filemap_page_mkwrite, .remap_pages = generic_file_remap_pages, }; --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -685,6 +685,7 @@ DEFINE_INODE_EVENT(xfs_inode_clear_eofbl DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); DEFINE_INODE_EVENT(xfs_filemap_fault); +DEFINE_INODE_EVENT(xfs_filemap_page_mkwrite); DECLARE_EVENT_CLASS(xfs_iref_class, TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), From ben@decadent.org.uk Mon Jun 13 13:37:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0FAEC7CA2 for ; Mon, 13 Jun 2016 13:37:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id C94BA304048 for ; Mon, 13 Jun 2016 11:37:34 -0700 (PDT) X-ASG-Debug-ID: 1465843051-04cbb03f52ac6c0001-NocioJ Received: from shadbolt.e.decadent.org.uk (shadbolt.e.decadent.org.uk [88.96.1.126]) by cuda.sgi.com with ESMTP id Zx1FQ4vcNpm6RR51 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 13 Jun 2016 11:37:32 -0700 (PDT) X-Barracuda-Envelope-From: ben@decadent.org.uk X-Barracuda-Effective-Source-IP: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Apparent-Source-IP: 88.96.1.126 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bCWjo-0007UW-Pb; Mon, 13 Jun 2016 19:37:29 +0100 Received: from ben by deadeye with local (Exim 4.87) (envelope-from ) id 1bCWjn-0005Ez-A6; Mon, 13 Jun 2016 19:37:27 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Jan Kara" , "Dave Chinner" , xfs@oss.sgi.com, "Dave Chinner" , "Brian Foster" Date: Mon, 13 Jun 2016 19:36:37 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 092/114] xfs: use i_mmaplock on read faults In-Reply-To: X-ASG-Orig-Subj: [PATCH 3.16 092/114] xfs: use i_mmaplock on read faults X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false X-Barracuda-Connect: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Start-Time: 1465843052 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2453 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30403 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 3.16.36-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Dave Chinner commit de0e8c20ba3a65b0f15040aabbefdc1999876e6b upstream. Take the i_mmaplock over read page faults. These come through the ->fault callout, so we need to wrap the generic implementation with the i_mmaplock. While there, add tracepoints for the read fault as it passes through XFS. This gives us a lock order of mmap_sem -> i_mmaplock -> page_lock -> i_lock. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Signed-off-by: Dave Chinner Signed-off-by: Ben Hutchings Cc: Jan Kara Cc: xfs@oss.sgi.com --- fs/xfs/xfs_file.c | 28 +++++++++++++++++++++++++++- fs/xfs/xfs_trace.h | 2 ++ 2 files changed, 29 insertions(+), 1 deletion(-) --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1417,6 +1417,32 @@ xfs_file_llseek( } } +/* + * Locking for serialisation of IO during page faults. This results in a lock + * ordering of: + * + * mmap_sem (MM) + * i_mmap_lock (XFS - truncate serialisation) + * page_lock (MM) + * i_lock (XFS - extent map serialisation) + */ +STATIC int +xfs_filemap_fault( + struct vm_area_struct *vma, + struct vm_fault *vmf) +{ + struct xfs_inode *ip = XFS_I(vma->vm_file->f_mapping->host); + int error; + + trace_xfs_filemap_fault(ip); + + xfs_ilock(ip, XFS_MMAPLOCK_SHARED); + error = filemap_fault(vma, vmf); + xfs_iunlock(ip, XFS_MMAPLOCK_SHARED); + + return error; +} + const struct file_operations xfs_file_operations = { .llseek = xfs_file_llseek, .read = new_sync_read, @@ -1449,7 +1475,7 @@ const struct file_operations xfs_dir_fil }; static const struct vm_operations_struct xfs_file_vm_ops = { - .fault = filemap_fault, + .fault = xfs_filemap_fault, .map_pages = filemap_map_pages, .page_mkwrite = xfs_vm_page_mkwrite, .remap_pages = generic_file_remap_pages, --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -684,6 +684,8 @@ DEFINE_INODE_EVENT(xfs_inode_set_eofbloc DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag); DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); +DEFINE_INODE_EVENT(xfs_filemap_fault); + DECLARE_EVENT_CLASS(xfs_iref_class, TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), TP_ARGS(ip, caller_ip), From ben@decadent.org.uk Mon Jun 13 13:37:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 016607CA0 for ; Mon, 13 Jun 2016 13:37:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id C8CFD304039 for ; Mon, 13 Jun 2016 11:37:34 -0700 (PDT) X-ASG-Debug-ID: 1465843050-04cbb03f55ac6c0001-NocioJ Received: from shadbolt.e.decadent.org.uk (shadbolt.e.decadent.org.uk [88.96.1.126]) by cuda.sgi.com with ESMTP id LF5tEsxHs9IKlfqH (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 13 Jun 2016 11:37:31 -0700 (PDT) X-Barracuda-Envelope-From: ben@decadent.org.uk X-Barracuda-Effective-Source-IP: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Apparent-Source-IP: 88.96.1.126 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bCWjo-0007UR-Pa; Mon, 13 Jun 2016 19:37:29 +0100 Received: from ben by deadeye with local (Exim 4.87) (envelope-from ) id 1bCWjn-0005FA-CG; Mon, 13 Jun 2016 19:37:27 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, xfs@oss.sgi.com, "Dave Chinner" , "Jan Kara" , "Brian Foster" , "Dave Chinner" Date: Mon, 13 Jun 2016 19:36:37 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 094/114] xfs: take i_mmap_lock on extent manipulation operations In-Reply-To: X-ASG-Orig-Subj: [PATCH 3.16 094/114] xfs: take i_mmap_lock on extent manipulation operations X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false X-Barracuda-Connect: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Start-Time: 1465843051 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3132 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30403 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 3.16.36-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Dave Chinner commit e8e9ad42c1f1e1bfbe0e8c32c8cac02e9ebfb7ef upstream. Now we have the i_mmap_lock being held across the page fault IO path, we now add extent manipulation operation exclusion by adding the lock to the paths that directly modify extent maps. This includes truncate, hole punching and other fallocate based operations. The operations will now take both the i_iolock and the i_mmaplock in exclusive mode, thereby ensuring that all IO and page faults block without holding any page locks while the extent manipulation is in progress. This gives us the lock order during truncate of i_iolock -> i_mmaplock -> page_lock -> i_lock, hence providing the same lock order as the iolock provides the normal IO path without involving the mmap_sem. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Signed-off-by: Dave Chinner [bwh: Backported to 3.16: - We never need to break layouts, so take both i_iolock and i_mmaplock at the same time - Adjust context] Signed-off-by: Ben Hutchings Cc: Jan Kara Cc: xfs@oss.sgi.com --- --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -786,7 +786,7 @@ xfs_file_fallocate( FALLOC_FL_COLLAPSE_RANGE | FALLOC_FL_ZERO_RANGE)) return -EOPNOTSUPP; - xfs_ilock(ip, XFS_IOLOCK_EXCL); + xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); if (mode & FALLOC_FL_PUNCH_HOLE) { error = xfs_free_file_space(ip, offset, len); if (error) @@ -866,7 +866,7 @@ xfs_file_fallocate( } out_unlock: - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); return -error; } --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -640,7 +640,7 @@ xfs_ioc_space( if (error) return error; - xfs_ilock(ip, XFS_IOLOCK_EXCL); + xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); switch (bf->l_whence) { case 0: /*SEEK_SET*/ @@ -757,7 +757,7 @@ xfs_ioc_space( error = xfs_trans_commit(tp, 0); out_unlock: - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); mnt_drop_write_file(filp); return -error; } --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -759,6 +759,7 @@ xfs_setattr_size( return XFS_ERROR(error); ASSERT(xfs_isilocked(ip, XFS_IOLOCK_EXCL)); + ASSERT(xfs_isilocked(ip, XFS_MMAPLOCK_EXCL)); ASSERT(S_ISREG(ip->i_d.di_mode)); ASSERT((iattr->ia_valid & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); @@ -935,9 +936,9 @@ xfs_vn_setattr( int error; if (iattr->ia_valid & ATTR_SIZE) { - xfs_ilock(ip, XFS_IOLOCK_EXCL); + xfs_ilock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); error = xfs_setattr_size(ip, iattr); - xfs_iunlock(ip, XFS_IOLOCK_EXCL); + xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL); } else { error = xfs_setattr_nonsize(ip, iattr, 0); } From ben@decadent.org.uk Mon Jun 13 13:37:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 917137CAF for ; Mon, 13 Jun 2016 13:37:40 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 645118F8033 for ; Mon, 13 Jun 2016 11:37:37 -0700 (PDT) X-ASG-Debug-ID: 1465843053-04cbb03f53ac6e0001-NocioJ Received: from shadbolt.e.decadent.org.uk (shadbolt.e.decadent.org.uk [88.96.1.126]) by cuda.sgi.com with ESMTP id 9AfKmmGJyGSHPM91 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 13 Jun 2016 11:37:34 -0700 (PDT) X-Barracuda-Envelope-From: ben@decadent.org.uk X-Barracuda-Effective-Source-IP: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Apparent-Source-IP: 88.96.1.126 Received: from [2a02:8011:400e:2:6f00:88c8:c921:d332] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bCWjp-0007VR-Ts; Mon, 13 Jun 2016 19:37:30 +0100 Received: from ben by deadeye with local (Exim 4.87) (envelope-from ) id 1bCWjn-0005Ev-9N; Mon, 13 Jun 2016 19:37:27 +0100 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Jan Kara" , xfs@oss.sgi.com, "Dave Chinner" , "Dave Chinner" , "Brian Foster" Date: Mon, 13 Jun 2016 19:36:37 +0100 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 091/114] xfs: introduce mmap/truncate lock In-Reply-To: X-ASG-Orig-Subj: [PATCH 3.16 091/114] xfs: introduce mmap/truncate lock X-SA-Exim-Connect-IP: 2a02:8011:400e:2:6f00:88c8:c921:d332 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false X-Barracuda-Connect: shadbolt.e.decadent.org.uk[88.96.1.126] X-Barracuda-Start-Time: 1465843053 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13807 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30403 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 3.16.36-rc1 review patch. If anyone has any objections, please let me know. ------------------ From: Dave Chinner commit 653c60b633a9019a54a80d64b5ed33ecb214823c upstream. Right now we cannot serialise mmap against truncate or hole punch sanely. ->page_mkwrite is not able to take locks that the read IO path normally takes (i.e. the inode iolock) because that could result in lock inversions (read - iolock - page fault - page_mkwrite - iolock) and so we cannot use an IO path lock to serialise page write faults against truncate operations. Instead, introduce a new lock that is used *only* in the ->page_mkwrite path that is the equivalent of the iolock. The lock ordering in a page fault is i_mmaplock -> page lock -> i_ilock, and so in truncate we can i_iolock -> i_mmaplock and so lock out new write faults during the process of truncation. Because i_mmap_lock is outside the page lock, we can hold it across all the same operations we hold the i_iolock for. The only difference is that we never hold the i_mmaplock in the normal IO path and so do not ever have the possibility that we can page fault inside it. Hence there are no recursion issues on the i_mmap_lock and so we can use it to serialise page fault IO against inode modification operations that affect the IO path. This patch introduces the i_mmaplock infrastructure, lockdep annotations and initialisation/destruction code. Use of the new lock will be in subsequent patches. Signed-off-by: Dave Chinner Reviewed-by: Brian Foster Signed-off-by: Dave Chinner Signed-off-by: Ben Hutchings Cc: Jan Kara Cc: xfs@oss.sgi.com --- fs/xfs/xfs_inode.c | 128 ++++++++++++++++++++++++++++++++++++++++------------- fs/xfs/xfs_inode.h | 29 +++++++++--- fs/xfs/xfs_super.c | 2 + 3 files changed, 121 insertions(+), 38 deletions(-) --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -119,24 +119,34 @@ xfs_ilock_attr_map_shared( } /* - * The xfs inode contains 2 locks: a multi-reader lock called the - * i_iolock and a multi-reader lock called the i_lock. This routine - * allows either or both of the locks to be obtained. + * The xfs inode contains 3 multi-reader locks: the i_iolock the i_mmap_lock and + * the i_lock. This routine allows various combinations of the locks to be + * obtained. * - * The 2 locks should always be ordered so that the IO lock is - * obtained first in order to prevent deadlock. + * The 3 locks should always be ordered so that the IO lock is obtained first, + * the mmap lock second and the ilock last in order to prevent deadlock. * - * ip -- the inode being locked - * lock_flags -- this parameter indicates the inode's locks - * to be locked. It can be: - * XFS_IOLOCK_SHARED, - * XFS_IOLOCK_EXCL, - * XFS_ILOCK_SHARED, - * XFS_ILOCK_EXCL, - * XFS_IOLOCK_SHARED | XFS_ILOCK_SHARED, - * XFS_IOLOCK_SHARED | XFS_ILOCK_EXCL, - * XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED, - * XFS_IOLOCK_EXCL | XFS_ILOCK_EXCL + * Basic locking order: + * + * i_iolock -> i_mmap_lock -> page_lock -> i_ilock + * + * mmap_sem locking order: + * + * i_iolock -> page lock -> mmap_sem + * mmap_sem -> i_mmap_lock -> page_lock + * + * The difference in mmap_sem locking order mean that we cannot hold the + * i_mmap_lock over syscall based read(2)/write(2) based IO. These IO paths can + * fault in pages during copy in/out (for buffered IO) or require the mmap_sem + * in get_user_pages() to map the user pages into the kernel address space for + * direct IO. Similarly the i_iolock cannot be taken inside a page fault because + * page faults already hold the mmap_sem. + * + * Hence to serialise fully against both syscall and mmap based IO, we need to + * take both the i_iolock and the i_mmap_lock. These locks should *only* be both + * taken in places where we need to invalidate the page cache in a race + * free manner (e.g. truncate, hole punch and other extent manipulation + * functions). */ void xfs_ilock( @@ -152,6 +162,8 @@ xfs_ilock( */ ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) != (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); + ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) != + (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); @@ -161,6 +173,11 @@ xfs_ilock( else if (lock_flags & XFS_IOLOCK_SHARED) mraccess_nested(&ip->i_iolock, XFS_IOLOCK_DEP(lock_flags)); + if (lock_flags & XFS_MMAPLOCK_EXCL) + mrupdate_nested(&ip->i_mmaplock, XFS_MMAPLOCK_DEP(lock_flags)); + else if (lock_flags & XFS_MMAPLOCK_SHARED) + mraccess_nested(&ip->i_mmaplock, XFS_MMAPLOCK_DEP(lock_flags)); + if (lock_flags & XFS_ILOCK_EXCL) mrupdate_nested(&ip->i_lock, XFS_ILOCK_DEP(lock_flags)); else if (lock_flags & XFS_ILOCK_SHARED) @@ -193,6 +210,8 @@ xfs_ilock_nowait( */ ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) != (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); + ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) != + (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); @@ -204,21 +223,35 @@ xfs_ilock_nowait( if (!mrtryaccess(&ip->i_iolock)) goto out; } + + if (lock_flags & XFS_MMAPLOCK_EXCL) { + if (!mrtryupdate(&ip->i_mmaplock)) + goto out_undo_iolock; + } else if (lock_flags & XFS_MMAPLOCK_SHARED) { + if (!mrtryaccess(&ip->i_mmaplock)) + goto out_undo_iolock; + } + if (lock_flags & XFS_ILOCK_EXCL) { if (!mrtryupdate(&ip->i_lock)) - goto out_undo_iolock; + goto out_undo_mmaplock; } else if (lock_flags & XFS_ILOCK_SHARED) { if (!mrtryaccess(&ip->i_lock)) - goto out_undo_iolock; + goto out_undo_mmaplock; } return 1; - out_undo_iolock: +out_undo_mmaplock: + if (lock_flags & XFS_MMAPLOCK_EXCL) + mrunlock_excl(&ip->i_mmaplock); + else if (lock_flags & XFS_MMAPLOCK_SHARED) + mrunlock_shared(&ip->i_mmaplock); +out_undo_iolock: if (lock_flags & XFS_IOLOCK_EXCL) mrunlock_excl(&ip->i_iolock); else if (lock_flags & XFS_IOLOCK_SHARED) mrunlock_shared(&ip->i_iolock); - out: +out: return 0; } @@ -246,6 +279,8 @@ xfs_iunlock( */ ASSERT((lock_flags & (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)) != (XFS_IOLOCK_SHARED | XFS_IOLOCK_EXCL)); + ASSERT((lock_flags & (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)) != + (XFS_MMAPLOCK_SHARED | XFS_MMAPLOCK_EXCL)); ASSERT((lock_flags & (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)) != (XFS_ILOCK_SHARED | XFS_ILOCK_EXCL)); ASSERT((lock_flags & ~(XFS_LOCK_MASK | XFS_LOCK_DEP_MASK)) == 0); @@ -256,6 +291,11 @@ xfs_iunlock( else if (lock_flags & XFS_IOLOCK_SHARED) mrunlock_shared(&ip->i_iolock); + if (lock_flags & XFS_MMAPLOCK_EXCL) + mrunlock_excl(&ip->i_mmaplock); + else if (lock_flags & XFS_MMAPLOCK_SHARED) + mrunlock_shared(&ip->i_mmaplock); + if (lock_flags & XFS_ILOCK_EXCL) mrunlock_excl(&ip->i_lock); else if (lock_flags & XFS_ILOCK_SHARED) @@ -273,11 +313,14 @@ xfs_ilock_demote( xfs_inode_t *ip, uint lock_flags) { - ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)); - ASSERT((lock_flags & ~(XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL)) == 0); + ASSERT(lock_flags & (XFS_IOLOCK_EXCL|XFS_MMAPLOCK_EXCL|XFS_ILOCK_EXCL)); + ASSERT((lock_flags & + ~(XFS_IOLOCK_EXCL|XFS_MMAPLOCK_EXCL|XFS_ILOCK_EXCL)) == 0); if (lock_flags & XFS_ILOCK_EXCL) mrdemote(&ip->i_lock); + if (lock_flags & XFS_MMAPLOCK_EXCL) + mrdemote(&ip->i_mmaplock); if (lock_flags & XFS_IOLOCK_EXCL) mrdemote(&ip->i_iolock); @@ -296,6 +339,12 @@ xfs_isilocked( return rwsem_is_locked(&ip->i_lock.mr_lock); } + if (lock_flags & (XFS_MMAPLOCK_EXCL|XFS_MMAPLOCK_SHARED)) { + if (!(lock_flags & XFS_MMAPLOCK_SHARED)) + return !!ip->i_mmaplock.mr_writer; + return rwsem_is_locked(&ip->i_mmaplock.mr_lock); + } + if (lock_flags & (XFS_IOLOCK_EXCL|XFS_IOLOCK_SHARED)) { if (!(lock_flags & XFS_IOLOCK_SHARED)) return !!ip->i_iolock.mr_writer; @@ -316,14 +365,27 @@ int xfs_lock_delays; #endif /* - * Bump the subclass so xfs_lock_inodes() acquires each lock with - * a different value + * Bump the subclass so xfs_lock_inodes() acquires each lock with a different + * value. This shouldn't be called for page fault locking, but we also need to + * ensure we don't overrun the number of lockdep subclasses for the iolock or + * mmaplock as that is limited to 12 by the mmap lock lockdep annotations. */ static inline int xfs_lock_inumorder(int lock_mode, int subclass) { - if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) + if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) { + ASSERT(subclass + XFS_LOCK_INUMORDER < + (1 << (XFS_MMAPLOCK_SHIFT - XFS_IOLOCK_SHIFT))); lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_IOLOCK_SHIFT; + } + + if (lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) { + ASSERT(subclass + XFS_LOCK_INUMORDER < + (1 << (XFS_ILOCK_SHIFT - XFS_MMAPLOCK_SHIFT))); + lock_mode |= (subclass + XFS_LOCK_INUMORDER) << + XFS_MMAPLOCK_SHIFT; + } + if (lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) lock_mode |= (subclass + XFS_LOCK_INUMORDER) << XFS_ILOCK_SHIFT; @@ -442,10 +504,10 @@ again: } /* - * xfs_lock_two_inodes() can only be used to lock one type of lock - * at a time - the iolock or the ilock, but not both at once. If - * we lock both at once, lockdep will report false positives saying - * we have violated locking orders. + * xfs_lock_two_inodes() can only be used to lock one type of lock at a time - + * the iolock, the mmaplock or the ilock, but not more than one at a time. If we + * lock more than one at a time, lockdep will report false positives saying we + * have violated locking orders. */ void xfs_lock_two_inodes( @@ -457,8 +519,12 @@ xfs_lock_two_inodes( int attempts = 0; xfs_log_item_t *lp; - if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) - ASSERT((lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)) == 0); + if (lock_mode & (XFS_IOLOCK_SHARED|XFS_IOLOCK_EXCL)) { + ASSERT(!(lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL))); + ASSERT(!(lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))); + } else if (lock_mode & (XFS_MMAPLOCK_SHARED|XFS_MMAPLOCK_EXCL)) + ASSERT(!(lock_mode & (XFS_ILOCK_SHARED|XFS_ILOCK_EXCL))); + ASSERT(ip0->i_ino != ip1->i_ino); if (ip0->i_ino > ip1->i_ino) { --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -57,6 +57,7 @@ typedef struct xfs_inode { struct xfs_inode_log_item *i_itemp; /* logging information */ mrlock_t i_lock; /* inode lock */ mrlock_t i_iolock; /* inode IO lock */ + mrlock_t i_mmaplock; /* inode mmap IO lock */ atomic_t i_pincount; /* inode pin count */ spinlock_t i_flags_lock; /* inode i_flags lock */ /* Miscellaneous state. */ @@ -264,15 +265,20 @@ static inline int xfs_isiflocked(struct #define XFS_IOLOCK_SHARED (1<<1) #define XFS_ILOCK_EXCL (1<<2) #define XFS_ILOCK_SHARED (1<<3) +#define XFS_MMAPLOCK_EXCL (1<<4) +#define XFS_MMAPLOCK_SHARED (1<<5) #define XFS_LOCK_MASK (XFS_IOLOCK_EXCL | XFS_IOLOCK_SHARED \ - | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED) + | XFS_ILOCK_EXCL | XFS_ILOCK_SHARED \ + | XFS_MMAPLOCK_EXCL | XFS_MMAPLOCK_SHARED) #define XFS_LOCK_FLAGS \ { XFS_IOLOCK_EXCL, "IOLOCK_EXCL" }, \ { XFS_IOLOCK_SHARED, "IOLOCK_SHARED" }, \ { XFS_ILOCK_EXCL, "ILOCK_EXCL" }, \ - { XFS_ILOCK_SHARED, "ILOCK_SHARED" } + { XFS_ILOCK_SHARED, "ILOCK_SHARED" }, \ + { XFS_MMAPLOCK_EXCL, "MMAPLOCK_EXCL" }, \ + { XFS_MMAPLOCK_SHARED, "MMAPLOCK_SHARED" } /* @@ -303,17 +309,26 @@ static inline int xfs_isiflocked(struct #define XFS_IOLOCK_SHIFT 16 #define XFS_IOLOCK_PARENT (XFS_LOCK_PARENT << XFS_IOLOCK_SHIFT) +#define XFS_MMAPLOCK_SHIFT 20 + #define XFS_ILOCK_SHIFT 24 #define XFS_ILOCK_PARENT (XFS_LOCK_PARENT << XFS_ILOCK_SHIFT) #define XFS_ILOCK_RTBITMAP (XFS_LOCK_RTBITMAP << XFS_ILOCK_SHIFT) #define XFS_ILOCK_RTSUM (XFS_LOCK_RTSUM << XFS_ILOCK_SHIFT) -#define XFS_IOLOCK_DEP_MASK 0x00ff0000 +#define XFS_IOLOCK_DEP_MASK 0x000f0000 +#define XFS_MMAPLOCK_DEP_MASK 0x00f00000 #define XFS_ILOCK_DEP_MASK 0xff000000 -#define XFS_LOCK_DEP_MASK (XFS_IOLOCK_DEP_MASK | XFS_ILOCK_DEP_MASK) - -#define XFS_IOLOCK_DEP(flags) (((flags) & XFS_IOLOCK_DEP_MASK) >> XFS_IOLOCK_SHIFT) -#define XFS_ILOCK_DEP(flags) (((flags) & XFS_ILOCK_DEP_MASK) >> XFS_ILOCK_SHIFT) +#define XFS_LOCK_DEP_MASK (XFS_IOLOCK_DEP_MASK | \ + XFS_MMAPLOCK_DEP_MASK | \ + XFS_ILOCK_DEP_MASK) + +#define XFS_IOLOCK_DEP(flags) (((flags) & XFS_IOLOCK_DEP_MASK) \ + >> XFS_IOLOCK_SHIFT) +#define XFS_MMAPLOCK_DEP(flags) (((flags) & XFS_MMAPLOCK_DEP_MASK) \ + >> XFS_MMAPLOCK_SHIFT) +#define XFS_ILOCK_DEP(flags) (((flags) & XFS_ILOCK_DEP_MASK) \ + >> XFS_ILOCK_SHIFT) /* * For multiple groups support: if S_ISGID bit is set in the parent --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -982,6 +982,8 @@ xfs_fs_inode_init_once( atomic_set(&ip->i_pincount, 0); spin_lock_init(&ip->i_flags_lock); + mrlock_init(&ip->i_mmaplock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, + "xfsino", ip->i_ino); mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, "xfsino", ip->i_ino); } From sandeen@sandeen.net Mon Jun 13 16:32:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 00FC37CA0 for ; Mon, 13 Jun 2016 16:32:39 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5D71CAC001 for ; Mon, 13 Jun 2016 14:32:31 -0700 (PDT) X-ASG-Debug-ID: 1465853542-04cbb03f55c3fb0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id jom1uKYxaD3U24IY for ; Mon, 13 Jun 2016 14:32:22 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 9F10DB55 for ; Mon, 13 Jun 2016 16:32:22 -0500 (CDT) Subject: Re: [PATCH] xfs: hide unused variable To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] xfs: hide unused variable References: <1460838665-1249242-1-git-send-email-arnd@arndb.de> From: Eric Sandeen Message-ID: <24741415-3bd6-18cd-6ba7-cd86b1d4149d@sandeen.net> Date: Mon, 13 Jun 2016 16:32:22 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1460838665-1249242-1-git-send-email-arnd@arndb.de> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1465853542 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1419 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30408 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 4/16/16 3:30 PM, Arnd Bergmann wrote: > The newly added xfs_finish_page_writeback() function causes > a harmless gcc warning when debugging is disabled: > > fs/xfs/xfs_aops.c: In function 'xfs_finish_page_writeback': > fs/xfs/xfs_aops.c:97:16: error: unused variable 'blockmask' [-Werror=unused-variable] > unsigned int blockmask = (1 << inode->i_blkbits) - 1; > ^~~~~~~~~ > > This adds an #ifdef around the variable declaration to hide > it whenever the ASSERT macro is defined as a stub, following > the same style as used elsewhere in xfs. Thanks Arnd - This got fixed by hch's patch, 690a787 xfs: fix warning in xfs_finish_page_writeback for non-debug builds -Eric > Signed-off-by: Arnd Bergmann > Fixes: 37992c18bba3 ("xfs: don't release bios on completion immediately") > --- > fs/xfs/xfs_aops.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c > index e5c3a457c191..737d028914a2 100644 > --- a/fs/xfs/xfs_aops.c > +++ b/fs/xfs/xfs_aops.c > @@ -94,7 +94,9 @@ xfs_finish_page_writeback( > struct bio_vec *bvec, > int error) > { > +#if defined(DEBUG) || defined(XFS_WARN) > unsigned int blockmask = (1 << inode->i_blkbits) - 1; > +#endif > unsigned int end = bvec->bv_offset + bvec->bv_len - 1; > struct buffer_head *head, *bh; > unsigned int off = 0; > From whissi@whissi.de Mon Jun 13 16:58:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 605A97CA0 for ; Mon, 13 Jun 2016 16:58:06 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id DEE12AC004 for ; Mon, 13 Jun 2016 14:58:03 -0700 (PDT) X-ASG-Debug-ID: 1465855075-04cb6c381389690001-NocioJ Received: from yamato.tf-network.de (yamato.tf-network.de [93.186.202.221]) by cuda.sgi.com with ESMTP id AQ6GjxI9rUSpWHMB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 13 Jun 2016 14:57:56 -0700 (PDT) X-Barracuda-Envelope-From: whissi@whissi.de X-Barracuda-Effective-Source-IP: yamato.tf-network.de[93.186.202.221] X-Barracuda-Apparent-Source-IP: 93.186.202.221 Received: from amavis3.tf-network.de ([IPv6:2001:4ba0:ffa0:1b::d1:221]) by yamato.tf-network.de (Postfix) with ESMTP id 3rT68f6m53z45m1 for ; Mon, 13 Jun 2016 23:57:54 +0200 (CEST) X-Virus-Scanned: amavisd-new at amavis3.tf-network.de Received: from smtp.tf-network.de ([93.186.202.221]) by amavis3.tf-network.de ([IPv6:2001:4ba0:ffa0:1b::d1:221]) (amavisd-new, port 10024) with LMTP id JeBIUkEnd1eZ for ; Mon, 13 Jun 2016 23:57:54 +0200 (CEST) Received: from [192.168.2.10] (pD9F15652.dip0.t-ipconnect.de [217.241.86.82]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.tf-network.de (Postfix) with ESMTPSA id 3rT68f18LTz45ls for ; Mon, 13 Jun 2016 23:57:54 +0200 (CEST) To: xfs@oss.sgi.com From: "Thomas D." Subject: Something badly broken with the latest XFS changeset in all stable kernels? Message-ID: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> X-ASG-Orig-Subj: Something badly broken with the latest XFS changeset in all stable kernels? Date: Mon, 13 Jun 2016 23:57:53 +0200 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: yamato.tf-network.de[93.186.202.221] X-Barracuda-Start-Time: 1465855076 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1574 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30408 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Hi, can anybody confirm if there's something broken with the latest XFS change set which is now applied on all stable kernels? I found https://forums.grsecurity.net/viewtopic.php?t=4489&p=16355 and grsec changelog says > commit 1f621dc42acbabb71bd69f6ba606cee56e7ad3bc > Author: Brad Spengler > Date: Sat Jun 11 08:14:32 2016 -0400 > > Fix Greg KH's broken XFS backport, caused a benign case to be detected > as disk corruption > Problem was due to a tree-wide conversion of error codes to their negative > counterparts, which would likely never be backported to older kernels, but > the backports didn't account for the change > > fs/xfs/xfs_inode.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) This is the change grsec applied: > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c > index fb8579d..af807d8 100644 > --- a/fs/xfs/xfs_inode.c > +++ b/fs/xfs/xfs_inode.c > @@ -3098,7 +3111,7 @@ xfs_iflush( > */ > error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK, > 0); > - if (error == -EAGAIN) { > + if (error == EAGAIN) { > xfs_ifunlock(ip); > return error; > } The bad commit according to grsec's statement is > From b1438f477934f5a4d5a44df26f3079a7575d5946 Mon Sep 17 00:00:00 2001 > From: Dave Chinner > Date: Wed, 18 May 2016 13:53:42 +1000 > Subject: [PATCH] xfs: xfs_iflush_cluster fails to abort on error Would be nice to get some clarification. Thanks. -- Regards, Thomas From ning_wang@asdc.com.cn Mon Jun 13 20:51:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=HTML_MESSAGE, HTML_OBFUSCATE_05_10 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1ABD07CA2 for ; Mon, 13 Jun 2016 20:51:25 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 63B66AC003 for ; Mon, 13 Jun 2016 18:51:20 -0700 (PDT) X-ASG-Debug-ID: 1465869072-04cb6c38148df30001-NocioJ Received: from regular2.263xmail.com (regular2.263xmail.com [211.157.152.3]) by cuda.sgi.com with ESMTP id K1efuh4bINl5QFoG (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 13 Jun 2016 18:51:15 -0700 (PDT) X-Barracuda-Envelope-From: ning_wang@asdc.com.cn X-Barracuda-Effective-Source-IP: regular2.263xmail.com[211.157.152.3] X-Barracuda-Apparent-Source-IP: 211.157.152.3 Received: from regular1.263xmail.com (unknown [192.168.165.185]) by regular2.263xmail.com (Postfix) with ESMTP id 13F6B1EA47 for ; Tue, 14 Jun 2016 09:51:06 +0800 (CST) Received: from ning_wang?asdc.com.cn (unknown [192.168.167.87]) by regular1.263xmail.com (Postfix) with SMTP id 2DDB04CA7 for ; Tue, 14 Jun 2016 09:50:57 +0800 (CST) X-263anti-spam:KSV:0;BIG:0;ABS:1;DNS:0;ATT:0;SPF:S; X-MAIL-GRAY:0 X-MAIL-DELIVERY:1 X-KSVirus-check:0 X-ABS-CHECKED:1 X-SKE-CHECKED:1 X-ADDR-CHECKED:0 Received: from smtp.263.net (va-smtp01.263.net [54.88.144.211]) by smtp.263.net (Postfix) with ESMTP id 2ADC6735B for ; Tue, 14 Jun 2016 09:50:57 +0800 (CST) Received: from MchiaelPC (localhost.localdomain [127.0.0.1]) by smtp.263.net (Postfix) with ESMTP id E33CA9F615 for ; Tue, 14 Jun 2016 09:50:49 +0800 (CST) X-RL-SENDER:ning_wang@asdc.com.cn X-FST-TO:xfs@oss.sgi.com X-SENDER-IP:111.203.254.28 X-LOGIN-NAME:ning_wang@asdc.com.cn X-UNIQUE-TAG: X-ATTACHMENT-NUM:0 X-SENDER:ning_wang@asdc.com.cn X-DNS-TYPE:0 Received: from MchiaelPC (unknown [111.203.254.28]) by smtp.263.net (Postfix) whith ESMTP id 6816BC8F8T; Tue, 14 Jun 2016 09:50:51 +0800 (CST) From: "Michael" To: Subject: questions about flush data to disk. Date: Tue, 14 Jun 2016 09:50:45 +0800 X-ASG-Orig-Subj: questions about flush data to disk. Message-ID: <00ba01d1c5df$2d254090$876fc1b0$@asdc.com.cn> MIME-Version: 1.0 Content-Type: multipart/related; boundary="----=_NextPart_000_00BB_01D1C622.3B4BDBF0" X-Mailer: Microsoft Outlook 14.0 Thread-Index: AdHF3hk2A2oykOBeSEC+HnLZD3Y5DQ== Content-Language: zh-cn X-Barracuda-Connect: regular2.263xmail.com[211.157.152.3] X-Barracuda-Start-Time: 1465869074 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7768 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.41 X-Barracuda-Spam-Status: No, SCORE=0.41 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_SA090h, HTML_MESSAGE, HTML_OBFUSCATE_05_10, THREAD_INDEX X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30416 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.00 HTML_OBFUSCATE_05_10 BODY: Message is 5% to 10% HTML obfuscation 0.00 HTML_MESSAGE BODY: HTML included in message 0.40 BSF_SC0_SA090h Custom Rule SA090h This is a multipart message in MIME format. ------=_NextPart_000_00BB_01D1C622.3B4BDBF0 Content-Type: multipart/alternative; boundary="----=_NextPart_001_00BC_01D1C622.3B4BDBF0" ------=_NextPart_001_00BC_01D1C622.3B4BDBF0 Content-Type: text/plain; charset="gb2312" Content-Transfer-Encoding: quoted-printable Dear SGI, =20 I=A1=AFm trying to backup XFS partition SUSE 12 with XFS_PROGS 3.2.1, = when we do snapshot of the partition. The created snapshot always have problem by = run =A1=B0xfs_repair =A8Cn /dev/VG/snapshot=A1=B1. I have tried = =A1=B0sync=A1=B1 didn=A1=AFt flush cache to disk. Then tried to umount and mount the XFS partition the = snapshot looks fine. Can you tell me another way to force XFS flush cached data = to disk?=20 =20 Best Regards Michael(Ning)Wang -------------------------------------------------------------------------= --- ------------------------------------------- =CB=B5=C3=F7: cid:_Foxmail.1@95d58f00-9e62-93f7-6199-b1696cc80320 ADVANCED SYSTEMS DEVELOPMENT CO.,LTD. 3/F DASCOM Mansion, 9# East Road Shangdi, Haidian, Beijing, 100085 Tel=A3=BA010-62981691-1234, 010-62980000, 010-82780000 Fax=A3=BA010-62981258 E-mail=A3=BA ning_wang@asdc.com.cn Http=A3=BA www.asdc.com.cn =CB=B5=C3=F7: cid:_Foxmail.1@e1a38f84-0fa5-04a6-9e7c-c5842b6ca2fa =20 ------=_NextPart_001_00BC_01D1C622.3B4BDBF0 Content-Type: text/html; charset="gb2312" Content-Transfer-Encoding: quoted-printable

Dear SGI,

 

I=A1=AFm trying to backup XFS = partition SUSE 12 with XFS_PROGS 3.2.1, when we do snapshot of the = partition. The created snapshot always have problem by run = =A1=B0xfs_repair =A8Cn /dev/VG/snapshot=A1=B1. I have tried = =A1=B0sync=A1=B1 didn=A1=AFt flush cache to disk. Then tried to umount = and mount the XFS partition the snapshot looks fine. Can you tell me = another way to force XFS flush cached data to disk? =

 

Best = Regards

Michael(Ning)Wang

---------------------------------= -------------------------------------------------------------------------= -------------

3D"=CB=B5=C3=F7:

ADVANCED SYSTEMS DEVELOPMENT = CO.,LTD.

3/F DASCOM Mansion, 9# East Road Shangdi, Haidian, = Beijing, 100085

Tel=A3=BA010-62981691-1234, = 010-62980000, 010-82780000

Fax=A3=BA010-62981258

E-mail=A3=BAning_wang@asdc.com.cn

Http=A3=BAwww.asdc.com.cn

3D"=CB=B5=C3=F7:

 

------=_NextPart_001_00BC_01D1C622.3B4BDBF0-- ------=_NextPart_000_00BB_01D1C622.3B4BDBF0 Content-Type: image/png; name="image001.png" Content-Transfer-Encoding: base64 Content-ID: iVBORw0KGgoAAAANSUhEUgAAAN4AAAAZCAYAAABeipC7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ bWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdp bj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6 eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEz NDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJo dHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlw dGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAv IiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RS ZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpD cmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlE PSJ4bXAuaWlkOjlEM0E1Mzc0QzAwMTExRTVBMkU5REQ1QTQ4MkQ5QzJGIiB4bXBNTTpEb2N1bWVu dElEPSJ4bXAuZGlkOjlEM0E1Mzc1QzAwMTExRTVBMkU5REQ1QTQ4MkQ5QzJGIj4gPHhtcE1NOkRl cml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OUQzQTUzNzJDMDAxMTFFNUEyRTlE RDVBNDgyRDlDMkYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OUQzQTUzNzNDMDAxMTFFNUEy RTlERDVBNDgyRDlDMkYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1l dGE+IDw/eHBhY2tldCBlbmQ9InIiPz5bFwtCAAAJeElEQVR42uxcvW7jRhCmDu5PySFAkCY0UgRI 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 fwIMAE8YLTUlD+5LAAAAAElFTkSuQmCC ------=_NextPart_000_00BB_01D1C622.3B4BDBF0 Content-Type: image/gif; name="image002.gif" Content-Transfer-Encoding: base64 Content-ID: R0lGODlhkAFaAPcAAAAAAP////Ly8pK92iAfIGRjZOvr7Ofn6OXl5gA8hUZHSABXqQBIjAFVoQFN kgVTmBBPjBpbliZjmgBcrAJgsQJgrwRcpgVhrglfqApgqA1krBRqsRhmqR5injR3rzFrnUyEskh6 pmSOsHOXtJ660tPg63ehwYOtzX6guouuyImnvprB3KbH3rLO4b7T4sTZ57PF0uLp7uzv8ZK+2pWx wqC5ya3AzMnW3trl7JLA2cDN1N/h4pLC2MLR2MTT2pLD15LF1pTG1pLI1JbK1eDl5p7N1tLf4ajS 17DW2LXY2Mne3s7g4Nbh4czR0SgpKeXn59fY2NHS0sPExL2+vrKzs7CxsamqqpydnZWWlo+QkIiJ ibjZ2L3b2sbe3bra2Mzf3sDc2tvk4+Xn5dPV0/Hy8d3e3eHj4Lq7ube4teLj4N7f3MXGwzk5OOjo 5ubm5OHh3+Hh4IuLipqXkYSDgbm4toqHgrWxq317eH57d4B9eTg1Mjs4NeDb1snIx66ppUhFQyom JBYUEywqKXt5eMG/viUiIRQSEjEvL97d3fHx8e/v7+3t7ezs7Ovr6+np6efn5+Xl5ePj497e3tzc 3Nvb29nZ2dbW1tTU1NLS0tHR0dDQ0M/Pz8zMzMrKysjIyMbGxsTExMLCwsHBwb6+vry8vLu7u7m5 ubi4uLe3t7a2trS0tK6urq2traurq6mpqaampqWlpaOjo6KioqCgoJ6enpubm5mZmZaWlpWVlZKS kpGRkY6OjoyMjIeHh4SEhIODg4KCgn9/f319fXt7e3l5eXd3d3R0dHFxcW9vb21tbWtra2lpaWZm ZmVlZWNjY2BgYF9fX11dXVpaWllZWVhYWFdXV1RUVFJSUlFRUU5OTkxMTEtLS0lJSUdHR0VFRUJC Qj8/Pz09PTs7Ozc3NzU1NTMzMzExMS8vLywsLCoqKicnJyUlJSMjIyAgIB4eHhwcHBsbGxkZGRcX FxUVFRISEhAQEA4ODg0NDQoKCgkJCQYGBgUFBQQEBAICAgEBAf///yH5BAEAAP8ALAAAAACQAVoA AAj/AAUIHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX MGPKnEmzps2bOHPq3Mmzp8+fQIMKHUq0qNGjSJMqXcq0qdOnUKNKnUq1qtWrWLOCTOSQq9avYKdW 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 ------=_NextPart_000_00BB_01D1C622.3B4BDBF0-- From tdm@sgi.com Mon Jun 13 21:26:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,RP_MATCHES_RCVD autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D0B0C7CA2 for ; Mon, 13 Jun 2016 21:26:48 -0500 (CDT) Received: from xmail.sgi.com (pv-excas3-dc21.corp.sgi.com [137.38.106.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 26050AC001; Mon, 13 Jun 2016 19:26:43 -0700 (PDT) Received: from P-EXMB4-DC21.corp.sgi.com ([169.254.6.189]) by pv-excas3-dc21.corp.sgi.com ([137.38.106.11]) with mapi id 14.03.0224.002; Mon, 13 Jun 2016 21:26:43 -0500 From: Troy McCorkell To: Michael , "xfs@oss.sgi.com" Subject: RE: questions about flush data to disk. Thread-Topic: questions about flush data to disk. Thread-Index: AdHF3hk2A2oykOBeSEC+HnLZD3Y5DQABDJ5Q Date: Tue, 14 Jun 2016 02:26:42 +0000 Message-ID: References: <00ba01d1c5df$2d254090$876fc1b0$@asdc.com.cn> In-Reply-To: <00ba01d1c5df$2d254090$876fc1b0$@asdc.com.cn> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: yes X-MS-TNEF-Correlator: x-originating-ip: [134.15.1.211] Content-Type: multipart/related; boundary="_005_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_"; type="multipart/alternative" MIME-Version: 1.0 --_005_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_ Content-Type: multipart/alternative; boundary="_000_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_" --_000_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_ Content-Type: text/plain; charset="big5" Content-Transfer-Encoding: base64 TWljaGFlbCwNCg0KU0dJIGlzIG5vIGxvbmdlciB0aGUgbWFpbnRhaW5lciBmb3IgWEZTIGluIHRo ZSBvcGVuIHNvdXJjZSBjb21tdW5pdHkuICBYRlMgaXMgbWFpbnRhaW5lZCBieSBEYXZlIENoaW5u ZXINCmFuZCBkZXZlbG9wZWQgYW5kIGVuaGFuY2VkIGJ5IGEgbGFyZ2UgY29tbXVuaXR5IG9mIGNv bnRyaWJ1dG9ycy4NCg0KUmVmZXJlbmNlIHRoZSBtYW5wYWdlIGZvciB0aGUgeGZzX2ZyZWV6ZSBj b21tYW5kIHRvIGhlbHAgc3RhYmlsaXppbmcgeW91ciBmaWxlc3lzdGVtIGJlZm9yZQ0KZ2VuZXJh dGluZyBhIHNuYXBzaG90LiAgIFF1b3RpbmcgdGhlIG1hbnBhZ2UsICJ4ZnNfZnJlZXplIGlzIGlu dGVuZGVkIHRvIGJlDQp1c2VkIHdpdGggdm9sdW1lIG1hbmFnZXJzIGFuZCBoYXJkd2FyZSBSQUlE IGRldmljZXMgdGhhdCBzdXBwb3J0IHRoZSBjcmVhdGlvbiBvZiBzbmFwc2hvdHMuIg0KDQpUaGFu a3MsDQpUcm95IE1jQ29ya2VsbA0KDQpfX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fXw0K RnJvbTogeGZzLWJvdW5jZXNAb3NzLnNnaS5jb20gW3hmcy1ib3VuY2VzQG9zcy5zZ2kuY29tXSBv biBiZWhhbGYgb2YgTWljaGFlbCBbbmluZ193YW5nQGFzZGMuY29tLmNuXQ0KU2VudDogTW9uZGF5 LCBKdW5lIDEzLCAyMDE2IDg6NTAgUE0NClRvOiB4ZnNAb3NzLnNnaS5jb20NClN1YmplY3Q6IHF1 ZXN0aW9ucyBhYm91dCBmbHVzaCBkYXRhIHRvIGRpc2suDQoNCkRlYXIgU0dJLA0KDQpJoaZtIHRy eWluZyB0byBiYWNrdXAgWEZTIHBhcnRpdGlvbiBTVVNFIDEyIHdpdGggWEZTX1BST0dTIDMuMi4x LCB3aGVuIHdlIGRvIHNuYXBzaG90IG9mIHRoZSBwYXJ0aXRpb24uIFRoZSBjcmVhdGVkIHNuYXBz aG90IGFsd2F5cyBoYXZlIHByb2JsZW0gYnkgcnVuIKGneGZzX3JlcGFpciChVm4gL2Rldi9WRy9z bmFwc2hvdKGoLiBJIGhhdmUgdHJpZWQgoadzeW5joaggZGlkbqGmdCBmbHVzaCBjYWNoZSB0byBk aXNrLiBUaGVuIHRyaWVkIHRvIHVtb3VudCBhbmQgbW91bnQgdGhlIFhGUyBwYXJ0aXRpb24gdGhl IHNuYXBzaG90IGxvb2tzIGZpbmUuIENhbiB5b3UgdGVsbCBtZSBhbm90aGVyIHdheSB0byBmb3Jj ZSBYRlMgZmx1c2ggY2FjaGVkIGRhdGEgdG8gZGlzaz8NCg0KQmVzdCBSZWdhcmRzDQpNaWNoYWVs KE5pbmcpV2FuZw0KLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0NCls/qfo6IGNpZDpfRm94bWFpbC4xQDk1ZDU4ZjAwLTllNjItOTNm Ny02MTk5LWIxNjk2Y2M4MDMyMF0NCkFEVkFOQ0VEIFNZU1RFTVMgREVWRUxPUE1FTlQgQ08uLExU RC4NCjMvRiBEQVNDT00gTWFuc2lvbiwgOSMgRWFzdCBSb2FkIFNoYW5nZGksIEhhaWRpYW4sIEJl aWppbmcsIDEwMDA4NQ0KVGVsoUcwMTAtNjI5ODE2OTEtMTIzNCwgMDEwLTYyOTgwMDAwLCAwMTAt ODI3ODAwMDANCkZheKFHMDEwLTYyOTgxMjU4DQpFLW1haWyhR25pbmdfd2FuZ0Bhc2RjLmNvbS5j bjxtYWlsdG86bmluZ193YW5nQGFzZGMuY29tLmNuPg0KSHR0cKFHd3d3LmFzZGMuY29tLmNuPGh0 dHA6Ly93d3cuYXNkYy5jb20uY24vPg0KWz+p+jogY2lkOl9Gb3htYWlsLjFAZTFhMzhmODQtMGZh NS0wNGE2LTllN2MtYzU4NDJiNmNhMmZhXQ0KDQo= --_000_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_ Content-Type: text/html; charset="big5" Content-Transfer-Encoding: quoted-printable
Michael,

SGI is no longer the maintainer for XFS in the open source community. = XFS is maintained by Dave Chinner
and developed and enhanced by a large community of contributors.

Reference the manpage for the xfs_freeze command to help stabilizing your f= ilesystem before
generating a snapshot.   Quoting the manpage, "xfs_freeze is= intended to be
used with volume managers and hardware RAID devices that support the creati= on of snapshots."

Thanks,
Troy McCorkell

From: xfs-bounces@oss.sgi.com [xfs-bounce= s@oss.sgi.com] on behalf of Michael [ning_wang@asdc.com.cn]
Sent: Monday, June 13, 2016 8:50 PM
To: xfs@oss.sgi.com
Subject: questions about flush data to disk.

Dear SGI,

 

I=A1=A6m trying to backup XFS partition SUSE 12 with XFS_PROGS 3= .2.1, when we do snapshot of the partition. The created snapshot always hav= e problem by run =A1=A7xfs_repair =A1Vn /dev/VG/snapshot=A1=A8. I have tried =A1=A7sync=A1=A8 didn=A1=A6t flush cache to disk. Then tried = to umount and mount the XFS partition the snapshot looks fine. Can you tell= me another way to force XFS flush cached data to disk?

 

Best Regards

Michael(Ning)Wang

------------------------------------= ---------------------------------------------------------------------------= --------

3D"说=A9=FA:

ADVANCED SYSTEMS DEVELOPMENT CO.,L= TD.

3/F DASCOM Mansion, 9# East Road Shangd= i, Haidian, Beijing, 100085=

Tel=A1G010-62981691-1234, 010-62980000, 010-82780000=

Fax=A1G010-62981258

E-mail=A1G<= span lang=3D"EN-US">ning_wang@asdc.com.cn

Http=A1Gwww.asdc.com.cn

=3D"说=A9=FA:

 

--_000_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_-- --_005_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_ Content-Type: image/png; name="image001.png" Content-Description: image001.png Content-Disposition: inline; filename="image001.png"; size=3330; creation-date="Tue, 14 Jun 2016 01:51:29 GMT"; modification-date="Tue, 14 Jun 2016 01:51:29 GMT" Content-ID: Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAAN4AAAAZCAYAAABeipC7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJ bWFnZVJlYWR5ccllPAAAAyBpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdp bj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6 eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEz NDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJo dHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlw dGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAv IiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RS ZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpD cmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBXaW5kb3dzIiB4bXBNTTpJbnN0YW5jZUlE PSJ4bXAuaWlkOjlEM0E1Mzc0QzAwMTExRTVBMkU5REQ1QTQ4MkQ5QzJGIiB4bXBNTTpEb2N1bWVu dElEPSJ4bXAuZGlkOjlEM0E1Mzc1QzAwMTExRTVBMkU5REQ1QTQ4MkQ5QzJGIj4gPHhtcE1NOkRl cml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OUQzQTUzNzJDMDAxMTFFNUEyRTlE RDVBNDgyRDlDMkYiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6OUQzQTUzNzNDMDAxMTFFNUEy RTlERDVBNDgyRDlDMkYiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1l dGE+IDw/eHBhY2tldCBlbmQ9InIiPz5bFwtCAAAJeElEQVR42uxcvW7jRhCmDu5PySFAkCY0UgRI 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 fwIMAE8YLTUlD+5LAAAAAElFTkSuQmCC --_005_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_ Content-Type: image/gif; name="image002.gif" Content-Description: image002.gif Content-Disposition: inline; filename="image002.gif"; size=9216; creation-date="Tue, 14 Jun 2016 01:51:29 GMT"; modification-date="Tue, 14 Jun 2016 01:51:29 GMT" Content-ID: Content-Transfer-Encoding: base64 R0lGODlhkAFaAPcAAAAAAP////Ly8pK92iAfIGRjZOvr7Ofn6OXl5gA8hUZHSABXqQBIjAFVoQFN kgVTmBBPjBpbliZjmgBcrAJgsQJgrwRcpgVhrglfqApgqA1krBRqsRhmqR5injR3rzFrnUyEskh6 pmSOsHOXtJ660tPg63ehwYOtzX6guouuyImnvprB3KbH3rLO4b7T4sTZ57PF0uLp7uzv8ZK+2pWx wqC5ya3AzMnW3trl7JLA2cDN1N/h4pLC2MLR2MTT2pLD15LF1pTG1pLI1JbK1eDl5p7N1tLf4ajS 17DW2LXY2Mne3s7g4Nbh4czR0SgpKeXn59fY2NHS0sPExL2+vrKzs7CxsamqqpydnZWWlo+QkIiJ ibjZ2L3b2sbe3bra2Mzf3sDc2tvk4+Xn5dPV0/Hy8d3e3eHj4Lq7ube4teLj4N7f3MXGwzk5OOjo 5ubm5OHh3+Hh4IuLipqXkYSDgbm4toqHgrWxq317eH57d4B9eTg1Mjs4NeDb1snIx66ppUhFQyom JBYUEywqKXt5eMG/viUiIRQSEjEvL97d3fHx8e/v7+3t7ezs7Ovr6+np6efn5+Xl5ePj497e3tzc 3Nvb29nZ2dbW1tTU1NLS0tHR0dDQ0M/Pz8zMzMrKysjIyMbGxsTExMLCwsHBwb6+vry8vLu7u7m5 ubi4uLe3t7a2trS0tK6urq2traurq6mpqaampqWlpaOjo6KioqCgoJ6enpubm5mZmZaWlpWVlZKS kpGRkY6OjoyMjIeHh4SEhIODg4KCgn9/f319fXt7e3l5eXd3d3R0dHFxcW9vb21tbWtra2lpaWZm ZmVlZWNjY2BgYF9fX11dXVpaWllZWVhYWFdXV1RUVFJSUlFRUU5OTkxMTEtLS0lJSUdHR0VFRUJC Qj8/Pz09PTs7Ozc3NzU1NTMzMzExMS8vLywsLCoqKicnJyUlJSMjIyAgIB4eHhwcHBsbGxkZGRcX FxUVFRISEhAQEA4ODg0NDQoKCgkJCQYGBgUFBQQEBAICAgEBAf///yH5BAEAAP8ALAAAAACQAVoA AAj/AAUIHEiwoMGDCBMqXMiwocOHECNKnEixosWLGDNq3Mixo8ePIEOKHEmypMmTKFOqXMmypcuX MGPKnEmzps2bOHPq3Mmzp8+fQIMKHUq0qNGjSJMqXcq0qdOnUKNKnUq1qtWrWLOCTOSQq9avYKdW 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 --_005_DF733A1EC32F124D86BC1188068FECB101A72C20A9PEXMB4DC21cor_-- From jpoimboe@redhat.com Mon Jun 13 23:29:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BC1447CA2 for ; Mon, 13 Jun 2016 23:29:19 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 90D158F8033 for ; Mon, 13 Jun 2016 21:29:16 -0700 (PDT) X-ASG-Debug-ID: 1465878554-04cb6c381692260001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id a7LJz7ToBxJRcD63 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 13 Jun 2016 21:29:14 -0700 (PDT) X-Barracuda-Envelope-From: jpoimboe@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2AF117D0C2; Tue, 14 Jun 2016 04:29:14 +0000 (UTC) Received: from treble (ovpn-116-88.phx2.redhat.com [10.3.116.88]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with SMTP id u5E4TCMc028119; Tue, 14 Jun 2016 00:29:13 -0400 Date: Mon, 13 Jun 2016 23:29:12 -0500 From: Josh Poimboeuf To: Daniel Wagner Cc: Dave Chinner , linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" , xfs@oss.sgi.com Subject: Re: Internal error xfs_trans_cancel Message-ID: <20160614042912.k4xifnftaik4rnar@treble> X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.6.0.1 (2016-04-01) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Tue, 14 Jun 2016 04:29:14 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465878554 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14502 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 01, 2016 at 07:52:31AM +0200, Daniel Wagner wrote: > Hi, > > I got the error message below while compiling a kernel > on that system. I can't really say if I did something > which made the file system unhappy before the crash. > > > [Jun 1 07:41] XFS (sde1): Internal error xfs_trans_cancel at line 984 of file fs/xfs/xfs_trans.c. Caller xfs_rename+0x453/0x960 [xfs] > [ +0.000095] CPU: 22 PID: 8640 Comm: gcc Not tainted 4.7.0-rc1 #16 > [ +0.000035] Hardware name: Dell Inc. PowerEdge R820/066N7P, BIOS 2.0.20 01/16/2014 > [ +0.000048] 0000000000000286 00000000c8be6bc3 ffff885fa9473cb0 ffffffff813d146e > [ +0.000056] ffff885fa9ac5ed0 0000000000000001 ffff885fa9473cc8 ffffffffa0213cdc > [ +0.000053] ffffffffa02257b3 ffff885fa9473cf0 ffffffffa022eb36 ffff883faa502d00 > [ +0.000053] Call Trace: > [ +0.000028] [] dump_stack+0x63/0x85 > [ +0.000069] [] xfs_error_report+0x3c/0x40 [xfs] > [ +0.000065] [] ? xfs_rename+0x453/0x960 [xfs] > [ +0.000064] [] xfs_trans_cancel+0xb6/0xe0 [xfs] > [ +0.000065] [] xfs_rename+0x453/0x960 [xfs] > [ +0.000062] [] xfs_vn_rename+0xb3/0xf0 [xfs] > [ +0.000040] [] vfs_rename+0x58c/0x8d0 > [ +0.000032] [] SyS_rename+0x371/0x390 > [ +0.000036] [] entry_SYSCALL_64_fastpath+0x1a/0xa4 > [ +0.000040] XFS (sde1): xfs_do_force_shutdown(0x8) called from line 985 of file fs/xfs/xfs_trans.c. Return address = 0xffffffffa022eb4f > [ +0.027680] XFS (sde1): Corruption of in-memory data detected. Shutting down filesystem > [ +0.000057] XFS (sde1): Please umount the filesystem and rectify the problem(s) > [Jun 1 07:42] XFS (sde1): xfs_log_force: error -5 returned. > [ +30.081016] XFS (sde1): xfs_log_force: error -5 returned. I saw this today. I was just building/installing kernels, rebooting, running kexec, running perf. [ 1359.005573] ------------[ cut here ]------------ [ 1359.010191] WARNING: CPU: 4 PID: 6031 at fs/inode.c:280 drop_nlink+0x3e/0x50 [ 1359.017231] Modules linked in: rpcrdma ib_isert iscsi_target_mod ib_iser libiscsi scsi_transport_iscsi ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm ib_cm iw_cm intel_powerclamp coretemp kvm_intel kvm nfsd ipmi_ssif ipmi_devintf ipmi_si iTCO_wdt irqbypass iTCO_vendor_support ipmi_msghandler i7core_edac shpchp sg edac_core pcspkr wmi lpc_ich dcdbas mfd_core acpi_power_meter auth_rpcgss acpi_cpufreq nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c sd_mod sr_mod cdrom iw_cxgb3 ib_core mgag200 ata_generic pata_acpi i2c_algo_bit drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops ttm drm mptsas scsi_transport_sas ata_piix mptscsih libata cxgb3 crc32c_intel i2c_core serio_raw mptbase bnx2 fjes mdio dm_mirror dm_region_hash dm_log dm_mod [ 1359.088447] CPU: 4 PID: 6031 Comm: depmod Tainted: G I 4.7.0-rc3+ #4 [ 1359.095911] Hardware name: Dell Inc. PowerEdge R410/0N051F, BIOS 1.11.0 07/20/2012 [ 1359.103461] 0000000000000286 00000000a0bc39d9 ffff8802143dfd18 ffffffff8134bb7f [ 1359.110871] 0000000000000000 0000000000000000 ffff8802143dfd58 ffffffff8108b671 [ 1359.118280] 00000118575f7d13 ffff880222c9a6e8 ffff8803ec3874d8 ffff880428827000 [ 1359.125693] Call Trace: [ 1359.128133] [] dump_stack+0x63/0x84 [ 1359.133259] [] __warn+0xd1/0xf0 [ 1359.138037] [] warn_slowpath_null+0x1d/0x20 [ 1359.143855] [] drop_nlink+0x3e/0x50 [ 1359.149017] [] xfs_droplink+0x28/0x60 [xfs] [ 1359.154864] [] xfs_remove+0x231/0x350 [xfs] [ 1359.160682] [] ? security_inode_permission+0x3a/0x60 [ 1359.167309] [] xfs_vn_unlink+0x58/0xa0 [xfs] [ 1359.173213] [] ? selinux_inode_unlink+0x13/0x20 [ 1359.179379] [] vfs_unlink+0xda/0x190 [ 1359.184590] [] do_unlinkat+0x263/0x2a0 [ 1359.189974] [] SyS_unlinkat+0x1b/0x30 [ 1359.195272] [] do_syscall_64+0x62/0x110 [ 1359.200743] [] entry_SYSCALL64_slow_path+0x25/0x25 [ 1359.207178] ---[ end trace 0d397afdaff9f340 ]--- [ 1359.211830] XFS (dm-0): Internal error xfs_trans_cancel at line 984 of file fs/xfs/xfs_trans.c. Caller xfs_remove+0x1d1/0x350 [xfs] [ 1359.223723] CPU: 4 PID: 6031 Comm: depmod Tainted: G W I 4.7.0-rc3+ #4 [ 1359.231185] Hardware name: Dell Inc. PowerEdge R410/0N051F, BIOS 1.11.0 07/20/2012 [ 1359.238736] 0000000000000286 00000000a0bc39d9 ffff8802143dfd60 ffffffff8134bb7f [ 1359.246147] ffff8803ec3874d8 0000000000000001 ffff8802143dfd78 ffffffffa03176bb [ 1359.253559] ffffffffa0328c21 ffff8802143dfda0 ffffffffa03327a6 ffff880222e7e180 [ 1359.260969] Call Trace: [ 1359.263407] [] dump_stack+0x63/0x84 [ 1359.268560] [] xfs_error_report+0x3b/0x40 [xfs] [ 1359.274755] [] ? xfs_remove+0x1d1/0x350 [xfs] [ 1359.280778] [] xfs_trans_cancel+0xb6/0xe0 [xfs] [ 1359.286973] [] xfs_remove+0x1d1/0x350 [xfs] [ 1359.292820] [] xfs_vn_unlink+0x58/0xa0 [xfs] [ 1359.298724] [] ? selinux_inode_unlink+0x13/0x20 [ 1359.304890] [] vfs_unlink+0xda/0x190 [ 1359.310100] [] do_unlinkat+0x263/0x2a0 [ 1359.315486] [] SyS_unlinkat+0x1b/0x30 [ 1359.320784] [] do_syscall_64+0x62/0x110 [ 1359.326256] [] entry_SYSCALL64_slow_path+0x25/0x25 [ 1359.332692] XFS (dm-0): xfs_do_force_shutdown(0x8) called from line 985 of file fs/xfs/xfs_trans.c. Return address = 0xffffffffa03327bf [ 1360.461638] XFS (dm-0): Corruption of in-memory data detected. Shutting down filesystem [ 1360.469729] XFS (dm-0): Please umount the filesystem and rectify the problem(s) [ 1360.595843] XFS (dm-0): xfs_log_force: error -5 returned. # uname -a Linux dell-per410-01.khw.lab.eng.bos.redhat.com 4.7.0-rc3+ #5 SMP Mon Jun 13 23:35:14 EDT 2016 x86_64 x86_64 x86_64 GNU/Linux # xfs_repair -V xfs_repair version 3.2.2 # cat /proc/cpuinfo | grep CPU | wc -l 16 # cat /proc/meminfo MemTotal: 16415296 kB MemFree: 15723380 kB MemAvailable: 15796192 kB Buffers: 964 kB Cached: 350700 kB SwapCached: 0 kB Active: 248992 kB Inactive: 223000 kB Active(anon): 121176 kB Inactive(anon): 8116 kB Active(file): 127816 kB Inactive(file): 214884 kB Unevictable: 0 kB Mlocked: 0 kB SwapTotal: 8257532 kB SwapFree: 8257532 kB Dirty: 0 kB Writeback: 0 kB AnonPages: 120340 kB Mapped: 40136 kB Shmem: 8964 kB Slab: 80092 kB SReclaimable: 25208 kB SUnreclaim: 54884 kB KernelStack: 5872 kB PageTables: 5468 kB NFS_Unstable: 0 kB Bounce: 0 kB WritebackTmp: 0 kB CommitLimit: 16465180 kB Committed_AS: 355084 kB VmallocTotal: 34359738367 kB VmallocUsed: 0 kB VmallocChunk: 0 kB HardwareCorrupted: 0 kB AnonHugePages: 51200 kB CmaTotal: 0 kB CmaFree: 0 kB HugePages_Total: 0 HugePages_Free: 0 HugePages_Rsvd: 0 HugePages_Surp: 0 Hugepagesize: 2048 kB DirectMap4k: 177572 kB DirectMap2M: 16586752 kB # cat /proc/mounts sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 devtmpfs /dev devtmpfs rw,seclabel,nosuid,size=8161852k,nr_inodes=2040463,mode=755 0 0 securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0 tmpfs /dev/shm tmpfs rw,seclabel,nosuid,nodev 0 0 devpts /dev/pts devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0 tmpfs /run tmpfs rw,seclabel,nosuid,nodev,mode=755 0 0 tmpfs /sys/fs/cgroup tmpfs ro,seclabel,nosuid,nodev,noexec,mode=755 0 0 cgroup /sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0 pstore /sys/fs/pstore pstore rw,seclabel,nosuid,nodev,noexec,relatime 0 0 cgroup /sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpu,cpuacct 0 0 cgroup /sys/fs/cgroup/net_cls cgroup rw,nosuid,nodev,noexec,relatime,net_cls 0 0 cgroup /sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0 cgroup /sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0 cgroup /sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatime,devices 0 0 cgroup /sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatime,perf_event 0 0 cgroup /sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatime,hugetlb 0 0 cgroup /sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0 cgroup /sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0 cgroup /sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0 configfs /sys/kernel/config configfs rw,relatime 0 0 /dev/mapper/rhel_dell--per410--01-root / xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0 selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0 systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=28,pgrp=1,timeout=300,minproto=5,maxproto=5,direct 0 0 debugfs /sys/kernel/debug debugfs rw,seclabel,relatime 0 0 mqueue /dev/mqueue mqueue rw,seclabel,relatime 0 0 hugetlbfs /dev/hugepages hugetlbfs rw,seclabel,relatime 0 0 sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime 0 0 /dev/mapper/rhel_dell--per410--01-home /home xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0 nfsd /proc/fs/nfsd nfsd rw,relatime 0 0 /dev/sda1 /boot xfs rw,seclabel,relatime,attr2,inode64,noquota 0 0 tmpfs /run/user/0 tmpfs rw,seclabel,nosuid,nodev,relatime,size=1641532k,mode=700 0 0 tracefs /sys/kernel/debug/tracing tracefs rw,relatime 0 0 # cat /proc/partitions major minor #blocks name 11 0 1048575 sr0 8 16 143374740 sdb 8 17 143373312 sdb1 8 0 143374740 sda 8 1 512000 sda1 8 2 142861312 sda2 253 0 52428800 dm-0 253 1 8257536 dm-1 253 2 225480704 dm-2 # pvdisplay --- Physical volume --- PV Name /dev/sda2 VG Name rhel_dell-per410-01 PV Size 136.24 GiB / not usable 0 Allocatable yes PE Size 4.00 MiB Total PE 34878 Free PE 16 Allocated PE 34862 PV UUID cTa6X3-dz3E-HmdE-bY1J-XEoo-USwY-dl2lRm --- Physical volume --- PV Name /dev/sdb1 VG Name rhel_dell-per410-01 PV Size 136.73 GiB / not usable 0 Allocatable yes (but full) PE Size 4.00 MiB Total PE 35003 Free PE 0 Allocated PE 35003 PV UUID ZzXTQx-9CN1-TaMu-UfrN-Usuz-aFvl-A6PKJS # lvdisplay --- Logical volume --- LV Path /dev/rhel_dell-per410-01/swap LV Name swap VG Name rhel_dell-per410-01 LV UUID E6Y5qQ-URKt-9wc6-3fRc-2wbZ-ev2n-IliB7s LV Write Access read/write LV Creation host, time dell-per410-01.khw.lab.eng.bos.redhat.com, 2016-06-13 12:55:31 -0400 LV Status available # open 2 LV Size 7.88 GiB Current LE 2016 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:1 --- Logical volume --- LV Path /dev/rhel_dell-per410-01/home LV Name home VG Name rhel_dell-per410-01 LV UUID Zq6BIP-0Yem-3NAp-gJ5K-2c6Q-Zc67-mdp51k LV Write Access read/write LV Creation host, time dell-per410-01.khw.lab.eng.bos.redhat.com, 2016-06-13 12:55:31 -0400 LV Status available # open 1 LV Size 215.04 GiB Current LE 55049 Segments 2 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:2 --- Logical volume --- LV Path /dev/rhel_dell-per410-01/root LV Name root VG Name rhel_dell-per410-01 LV UUID T4rKVg-cuiW-jc6c-grNW-DJQQ-mCt8-N8Ig5l LV Write Access read/write LV Creation host, time dell-per410-01.khw.lab.eng.bos.redhat.com, 2016-06-13 12:55:35 -0400 LV Status available # open 1 LV Size 50.00 GiB Current LE 12800 Segments 1 Allocation inherit Read ahead sectors auto - currently set to 8192 Block device 253:0 # hdparm -i /dev/sda /dev/sda: SG_IO: bad/missing sense data, sb[]: 70 00 05 00 00 00 00 28 00 00 00 00 20 00 00 00 00 00 00 85 55 06 01 00 00 00 00 00 00 00 00 00 HDIO_GET_IDENTITY failed: Invalid argument # hdparm -i /dev/sdb /dev/sdb: SG_IO: bad/missing sense data, sb[]: 70 00 05 00 00 00 00 28 00 00 00 00 20 00 00 00 00 00 00 85 55 06 01 00 00 00 00 00 00 00 00 00 HDIO_GET_IDENTITY failed: Invalid argument (I don't know anything about the disks, but I can try to find out if you need it.) # xfs_info /dev/mapper/rhel_dell--per410--01-root meta-data=/dev/mapper/rhel_dell--per410--01-root isize=256 agcount=4, agsize=3276800 blks = sectsz=512 attr=2, projid32bit=1 = crc=0 finobt=0 data = bsize=4096 blocks=13107200, imaxpct=25 = sunit=0 swidth=0 blks naming =version 2 bsize=4096 ascii-ci=0 ftype=0 log =internal bsize=4096 blocks=6400, version=2 = sectsz=512 sunit=0 blks, lazy-count=1 realtime =none extsz=4096 blocks=0, rtextents=0 -- Josh From angelawillians223@hotmail.com Tue Jun 14 05:18:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: *** X-Spam-Status: No, score=3.3 required=5.0 tests=FORGED_HOTMAIL_RCVD2, FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM,FREEMAIL_REPLYTO,HTML_MESSAGE, LOTS_OF_MONEY,MONEY_FROM_41 autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 68CB17CA2 for ; Tue, 14 Jun 2016 05:18:03 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 39F6A30404E for ; Tue, 14 Jun 2016 03:18:00 -0700 (PDT) X-ASG-Debug-ID: 1465899474-04cb6c38159b1b0001-NocioJ Received: from ns601-vm10.bullet.mail.ssk.yahoo.co.jp (ns601-vm10.bullet.mail.ssk.yahoo.co.jp [182.22.91.59]) by cuda.sgi.com with SMTP id ihQTufVAQHYh03EH for ; Tue, 14 Jun 2016 03:17:55 -0700 (PDT) X-Barracuda-Envelope-From: angelawillians223@hotmail.com X-Barracuda-Effective-Source-IP: ns601-vm10.bullet.mail.ssk.yahoo.co.jp[182.22.91.59] X-Barracuda-Apparent-Source-IP: 182.22.91.59 Received: from [182.22.66.105] by ns601.bullet.mail.ssk.yahoo.co.jp with NNFMP; 14 Jun 2016 10:17:51 -0000 Received: from [182.22.91.131] by t603.bullet.mail.ssk.yahoo.co.jp with NNFMP; 14 Jun 2016 10:17:50 -0000 Received: from [127.0.0.1] by omp604.mail.ssk.yahoo.co.jp with NNFMP; 14 Jun 2016 10:17:50 -0000 X-Yahoo-Newman-Property: ymail-5 X-Yahoo-Newman-Id: 895141.11257.bm@omp604.mail.ssk.yahoo.co.jp Received: (qmail 99617 invoked by uid 60001); 14 Jun 2016 10:17:50 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=yj20050223; d=yahoo.co.jp; h=Message-ID:X-YMail-OSG:Received:X-RocketYMMF:X-Mailer:X-YMail-JAS:Sender:References:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type; b=nyd2hrOfQXkDJJy4s6DMIaS+qfXNC2fQeQBur5cekKX4Uu8JL98e9M3a7e6Ck0Stfw7eLk//E0x6dG3UOjhWP+U03muw/cF1lfHimii9naoonM7KsFKtwy+tJcQUZDsp ; Message-ID: <501188.92835.qm@web101903.mail.ssk.yahoo.co.jp> X-YMail-OSG: G4JLttYVM1kCDJ7NAQTyV0yxNUhQZT2o66a_VtnMyBpFCxrN7oiWiT7KCAEzSzNiyUMBPvx5MR2stXfA5nsAJZx7.olU5lJVtX4gq5j8CuufAcDYPVbwJ_9iqd599MXrtZixB5d4aolitzTjxXSeRirdNg9dWiL.BLFVlCD79lS.HFzYq4mD0qSshhgFbijmGERK6EFgRUCTL2Nz8xjFLgVivNB9J1cguqkfhGik04js9gVLYzYJEG82nfsiMg8FC.rbMlcegWfQvPELw2tqFWgKsv0rNn3i1XJ3o9fFpNLjA1rxE5oJpCzNur2k_Ir.MJmGm3yyrK0C1TJQ2bBYTx_TMeILHfZENWUaYau7QloUF.aavY41yFzb11wo9gvlEqQVbMKCT2AOY3Y7usPSZ7K_px178tBjULLAGXFt.cm.cWx982qFE8pQ8On69eTxwhsIgNcoDtgbWVFTRC8CCwFVZPxAXiSOgKJwJOozm3a2SW8F.BKR89A7K2hPX_9vwPPNuS1Bqzw_ZySV3HRzzKHM9CbEXfkTMWHrjtcb2RO32McBU_jQcMttgeeBngRmkl4CWVMk4MW5tXPeMXX2qSc7FRVtyRDMyoUI.n8saUzz3OIpGpL8sxRz3wNlMd1LIrwlw.N4WKle2uL1DWM8IMUipsFW.pGz7KOTYv0BT3UJ6Gt8p7v4q572T93OOA-- Received: from [41.189.33.60] by web101903.mail.ssk.yahoo.co.jp via HTTP; Tue, 14 Jun 2016 19:17:48 JST X-RocketYMMF: jtwwgp482 X-Mailer: YahooMailWebService/0.8.111_69 X-YMail-JAS: yLxSr_4VM1ks6zNywEGtkXwbebjweg3mE5Jz_OeqPoQYfeVAl23j7FP4tFR0TGm1N5_pDo95BR..hVnE8lMy8YZIW._dTDYw9YQkdCPMn7Aj8KHpDSQwKGmdbG8BzblHT3u0 Sender: jtwwgp482@yahoo.co.jp References: Date: Tue, 14 Jun 2016 19:17:48 +0900 (JST) From: Angela Williams Reply-To: Angela Williams Subject: Ich bitte um Ihre Unterstuetzung!! To: undisclosed recipients: ; X-ASG-Orig-Subj: Ich bitte um Ihre Unterstuetzung!! MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="-488044274-1704054557-1465899468=:92835" X-Barracuda-Connect: ns601-vm10.bullet.mail.ssk.yahoo.co.jp[182.22.91.59] X-Barracuda-Start-Time: 1465899474 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3365 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.62 X-Barracuda-Spam-Status: No, SCORE=2.62 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=ADVANCE_FEE_1, BSF_SC0_MISMATCH_TO, BSF_SC0_SA083, DKIM_SIGNED, DKIM_VERIFIED, FORGED_HOTMAIL_RCVD2, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30424 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 1.12 FORGED_HOTMAIL_RCVD2 hotmail.com 'From' address, but no 'Received:' -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message 0.00 ADVANCE_FEE_1 Appears to be advance fee fraud (Nigerian 419) 1.50 BSF_SC0_SA083 Custom Rule SA083 ---488044274-1704054557-1465899468=:92835 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable Sehr geehrter Damen und Herren,=0A=A0=0AVorname/ =A0Williams=0AName/ =A0 An= gela=0ANationalitaet/ =A0Sierra Leonean=0A=A0=0AIch habe die Summe von USD = 3.7millionen von meinen verstorbenen Eltern geebrt. Meine Eltern wurden Dia= manten Haendler.=0A=A0=0ADas Geld wurde von meinen Eltern in der Sicherheit= sfirma fuer sicheres Behalten deponiert.=0A=A0=0AMomentan lebe ich in Bouak= e in Elfenbeinkueste und zwar gibt es Buergerkrieg bei uns, deswegen moecht= e ich das Geld in Ihrem Land per Ihre Hilfe investieren.=0A=A0=0AIch moecht= e in den gunstigen Branchen investieren wenn Sie mich unterstuetzen koennen= .=0A=A0=0AKoennen Sie mich unterstuetzen?=0A=A0=0AIch warte auf Ihre baldig= e Antwort!=0A=A0=0AMit freundlichen Gruessen,=0AFr=E4ulein Angela Williams ---488044274-1704054557-1465899468=:92835 Content-Type: text/html; charset=iso-8859-1 Content-Transfer-Encoding: quoted-printable
<= div style=3D"font-family:MS PGothic, sans-serif;font-size:12pt;">
Sehr geehrter Damen und Herren,
&nb= sp;
Vorname/  Williams
Name/   Angela
Nationalitaet/  Sierra Leonean
 
Ich habe = die Summe von USD 3.7millionen von meinen verstorbenen Eltern geebrt. Meine= Eltern wurden Diamanten Haendler.
 
Das Geld wurde von = meinen Eltern in der Sicherheitsfirma fuer sicheres Behalten deponiert.
 
Momentan lebe ich in Bouake in Elfenbeinkueste und zwar= gibt es Buergerkrieg bei uns, deswegen moechte ich das Geld in Ihrem Land = per Ihre Hilfe investieren.
 
Ich moechte in den gunstigen Branchen investieren= wenn Sie mich unterstuetzen koennen.
 
Koennen Sie m= ich unterstuetzen?
 
Ich warte auf Ihre baldige Antwort!=
 
Mit freundlichen Gruessen,
Fr=E4ulein Angela W= illiams
---488044274-1704054557-1465899468=:92835-- From alisowska@swiezabazylia.pl Tue Jun 14 07:09:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EBFED7CA0 for ; Tue, 14 Jun 2016 07:09:47 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8469FAC001 for ; Tue, 14 Jun 2016 05:09:44 -0700 (PDT) X-ASG-Debug-ID: 1465906181-04bdf01e1329720001-NocioJ Received: from cloudserver099139.home.net.pl (cloudserver099139.home.net.pl [79.96.190.79]) by cuda.sgi.com with SMTP id BNwxwOdXJZR4ADDB for ; Tue, 14 Jun 2016 05:09:41 -0700 (PDT) X-Barracuda-Envelope-From: alisowska@swiezabazylia.pl X-Barracuda-Effective-Source-IP: cloudserver099139.home.net.pl[79.96.190.79] X-Barracuda-Apparent-Source-IP: 79.96.190.79 Received: from ip-11-55.dataclub.biz (185.29.11.55) (HELO IP-11-55.dataclub.biz) by swiezabazylia1.home.pl (79.96.190.79) with SMTP (IdeaSmtpServer v0.80.2) id 19d0de4d6ed61a64; Tue, 14 Jun 2016 14:09:41 +0200 Content-Type: multipart/mixed; boundary="===============1880848174==" MIME-Version: 1.0 Subject: Google Celebrates! Ref Number GAAP/6168/657 To: Recipients X-ASG-Orig-Subj: Google Celebrates! Ref Number GAAP/6168/657 From: "Google Incorporation" Date: Tue, 14 Jun 2016 14:09:38 +0200 Reply-To: validating.department@webname.com X-Barracuda-Connect: cloudserver099139.home.net.pl[79.96.190.79] X-Barracuda-Start-Time: 1465906181 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 52 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.15 X-Barracuda-Spam-Status: No, SCORE=0.15 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_DOMAIN_MATCH, HTML_MESSAGE, MISSING_MID X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30425 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message 0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient Domain Message-Id: <20160614120944.28FB2A420A0@cuda.sgi.com> You will not see this in a MIME-aware mail reader. --===============1880848174== Content-Type: multipart/alternative; boundary="===============1058128587==" MIME-Version: 1.0 --===============1058128587== Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body Dear Google User. Attached to this email is your official Sweepstakes notification for being= an active user of Google Products. Best Regards, Larry Page. Ceo/CO-Founder, GOOGLE INC. =20 --===============1058128587== Content-Type: text/html; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body

Dear Google User.

Attached to this email is your official Sweepstakes notification for bei= ng an active user of Google Products.

Best Regards,
Larry Page.
Ceo/CO-Founder,
GOOGLE INC.

 

--===============1058128587==-- --===============1880848174== Content-Type: application/octet-stream MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Google Inc.docx" UEsDBBQABgAIAAAAIQATrM+BiAEAAAsGAAATAAgCW0NvbnRlbnRfVHlwZXNdLnhtbCCiBAIooAAC AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0 VMlOwzAQvSPxD5GvKHHLASHUtAeWI1SifIBrT1KDN9nu9vdM0jYqkKYSbS+R4vFb5nnswWilVbIA H6Q1OelnPZKA4VZIU+bkY/KS3pMkRGYEU9ZATtYQyGh4fTWYrB2EBNEm5GQWo3ugNPAZaBYy68Bg pbBes4i/vqSO8S9WAr3t9e4otyaCiWmsOMhw8AQFm6uYPK9weePEmZIkj5t9lVROpK7w1TptRXw6 aIfUhXaMBxV+yTDnlOQsYh50YcSvXtJtHxki6z1hJl24wWYPuKoqP/vYF9ji3vAAvBSQjJmPr0xj t3RpvaDC8rnGpLJumhaftigkhwZfsTlvOYSAJ6tV1lQ0k2bn/6APM9dT8Ig8v5GG+qiJENcKwvkd bHi75DGssbcuUDy7k/WhGnIBIsXzcOCjhGZ+DuYfIEZM/xLNb5m72q9HMeLVBlp/+ydnUNMclSzw +k/YVMHJen/Gv6E+amIJ0/eLpb9H3mWkmT9u/T/C2L1ZFbpl6mj9lA+/AQAA//8DAFBLAwQUAAYA CAAAACEAHpEat/MAAABOAgAACwAIAl9yZWxzLy5yZWxzIKIEAiigAAIAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIyS20oDQQyG7wXfYch9N9sK ItLZ3kihdyLrA4SZ7AF3Dsyk2r69oyC6UNte5vTny0/Wm4Ob1DunPAavYVnVoNibYEffa3htt4sH UFnIW5qCZw1HzrBpbm/WLzyRlKE8jDGrouKzhkEkPiJmM7CjXIXIvlS6kBxJCVOPkcwb9Yyrur7H 9FcDmpmm2lkNaWfvQLXHWDZf1g5dNxp+Cmbv2MuJFcgHYW/ZLmIqbEnGco1qKfUsGmwwzyWdkWKs CjbgaaLV9UT/X4uOhSwJoQmJz/N8dZwDWl4PdNmiecevOx8hWSwWfXv7Q4OzL2g+AQAA//8DAFBL AwQUAAYACAAAACEA+GkgzygBAAC/BAAAHAAIAXdvcmQvX3JlbHMvZG9jdW1lbnQueG1sLnJlbHMg ogQBKKAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8lE1OwzAQhfdI3CHynjgJUBCq0w1C 6hbCAdxkkhjiH9kukNszatUkFW26sVjOs/zep5mxl6sf2UVfYJ3QipE0TkgEqtSVUA0j78XLzSOJ nOeq4p1WwEgPjqzy66vlK3Tc4yXXCuMidFGOkdZ780SpK1uQ3MXagMKTWlvJPZa2oYaXn7wBmiXJ gtqpB8mPPKN1xYhdV5hf9AaTL3vruhYlPOtyK0H5ExHUIxegIbcNeEZ25V5MYwQl9DTDbUgGB95j d92IcVDmEB5CItRa+YJvukkrBmkOIgsJ4Xzf4TINw9jXc/FpyHi1lRuwOIiRYJDmIBYhIYTEtzAC SKgEpzsxiw2indnH+/9hSOMPA2ch7kJCfMPm7c+7mIiHidCjbyf/BQAA//8DAFBLAwQUAAYACAAA ACEARq+ZLtgTAAAFqAAAEQAAAHdvcmQvZG9jdW1lbnQueG1s7F3bcuJImr7fiH2HHCJ2Y2a2bIQN xtaO3YM5uB3jslmXuyv2MpESoy5JqUlJYHru5lnmZl5jH2WfZL4/JWGEwQUYqkSbiiijYyoP//mU f/rhyXPZUKjQkf55qXJolJjwLWk7/uN56aeHzsFpiYUR923uSl+cl8YiLP1w8e//9qeRaUsr9oQf MTThh+YQdwdRFJjlcmgNhMfDQxkIHzf7Unk8wql6LHtcfYmDA0t6AY+cnuM60bh8ZBgnpbQZeV6K lW+mTRx4jqVkKPsRvWLKft+xRPqTvaGW+W7yZivtsv5iWQkXfZB+OHCCMGvNW7c1DHGQNTJ8bRBD z82eGwXLfM1WfIT18Nyk2yOp7EBJS4QhrraSm5MWK8Zr304nkJqYvLFMF/LfzHriccefNEPQMbP+ k8U7xOKVk2+XqanngWAuLgBLPWmP6TdgIxOwaN+flwyjcVIzms1Sdqkl+jx2o5d3ulOXdCNdRT8q /elIPwrRCA8txzkvPfCB9Di1Omj4Ye6CFU5ul3Wv9N/wVzw75O556cgopVea1ODUtXL6OfwG6Wen uuDLrpKyj3ez54A9ybrhqcB0fNfxBbOdMHrAWEr66HJydDM5ommh+QpM8RQR6llP6FWlelw5qpWY NQYGV+qVWr2m+4mn+n1hRe3kWQygcmbU0DzNYYkBb85q9F6PTmlgAeF0VzHHxqMl5nMPa9p1rChW glXSR6zb4ZXiwcCxOgoP0Gi5+Th15UZaX8IUm/kLmJhDE2bgO4EqXzYH3H8UjTDAEKg/evoC87Xv v/WrU0Np8YizWAE+ZoD66wMIkhnDQuHIxP+0Wzh6c2v+sOtgiZKmMRXpamE556wWfZ6eSd7g1JVk cV5OLptcUkqOBoLbwIVkzvOtlOk014ue6wQdx3Vp8uiYKVN4PQEYUte2hkRuhsq6xzJiCXEcKRFZ Azrs47X0ennqhv7Gc7P0xRBoxXqjj9IGSPI4kphdbj71lUe/IC0MmIBZAApoWOaEIa+iBz6YvR6o MLoS0mN0gG6jp7p5PrwJqc94NHuEvuZLGq4ei+uzUYpGM3c8JxKKuQ74yalB/wh+uUkz2/ZtfRxx x02O8QHXx3eykaaHONUfT7GLQHL6HMcT4kHHzzSFyIy+EhAVeo2odkEFDKN1XKkcHa1NaYNP0dgV GUW8lZ8CboE1aYIxIcO5Zz7FvcgVbS8Y8NAJ0wdnCPWltKXvsI8P7NLl1pcpij17B7MJFqL/WtKV KutJpVM9q7foxQgCiWjSvfNSBMg4ok9mxBi/GdHGo5r95KaFWs+YSXFHgUFeXEn5iIW49q1DGl2U jHEPCaX3BgnEcUAzuQVqGSgRCjUUpYtL4YKUDAX7UcahYPUTtoeSd00vLmPrCwj1gHusy0FkBbuX 3N4DxbsGihvpg/GyT58rn9nZw/+sDA2r6ml76aEAMhAJCz/5kFlt9hdQBFt6q0sQ73ThSXxcTsw2 zmrHZ7B0pULmVuarcEJ0OuhpIXqmj1C91KMzbZKZukI2mex0Ss7vNcOV5f2RuYophzDiXvSFgj1U sNsYKq3K0UKsYraSC9WFnRmpya4ajW75pHJyWj6p1XMDXR7Aq61a66yxNoCPHFuOmjDXKeliarV9 LTW5kcpPaqVotRfeuZ29Y/8Sh9G98ziIrn175iYJxyB0uMr70NS18WBkkh0OFrUqLAnJyX3sZgYH DW+ZHrj0wuq3puCumii74a9TJkR9DbOsG6fZJgPPu5v16ll+0sUThx2mgLO+Kt1+BawlXC99V466 sW9FMxD6bUH+eCHI/2JlHetJuDjWWxA0QZS8oRzuJk3MpeCGUenUOhmKZN89SolADmn0tVmkeUGT 6yfVZvUY1rwUu/CzNOpuuc/EYFqCK5ZabX6Clv67lQnvHhgntrmiLOzqFPyNguGewGjh8bsQmA2I t9siikRgPsMs74QDFklmSR/WvyiG01uwsYwZ/PKsJ0gICoULnwd0Px4yzjz+C+5YkJ2kBx+G7DOY zzMqBduyVIFEQ/CcH7IGfCbSk3SyMulKpOY97CeC7i4wV6y17LcV6T3ROIBgDIDyPkVcZXIabkz5 TwqOG/A95WAWgve88cFFlwo9uzS6+R6AFN+DOGKOzwJt8iUywF2XQdp24BuAZ0CFM0gfQkyxBogM eqQ4BUQDMUiCIA2p5IJps2MLQRagMhQ9FCv+iMdcNze9yyg0e2mmsNLMAuyYxv6iStkapHOwuGAw z6he0KHMx+rD1f14e0QrLKItQycT0SlVbjO2tF/Twq4pxKKCUhTSEBT3wdSZTMIQ2weIwHMhKUT8 YIZokuA3Jd8V3LgSiTBifagn7CPitSjQl8SaVGZJxJwRwhgHpAwplg6b2zbiJUJmIbaRxUGiESH8 1hfqMHvXCREuN9JaUc95fKTP5CUkxLi6NrTyRFaCpIXZRSymVFEiIoUUUBkNOKSwiCnESjvoGylZ nkRb9KI7zk398jRheyb4va3SzEWXvd1WOVfdmBaodgrdgFH50JGvClm7NLz5klce77fvMn/F0vdN 3QWV+oy7oLDOmkRS2h5V3E/73GSN92Pbq1bzbksCiMRe5GinsyL/MwWBJxd32ptWbIPefBIN+ZZs VaI3JoO3B6vUGLYvOtRGcC2FkTU8jC1KqerH9EDAQ3AzLZIp8dfYgYyGdJvwA3PFI3chsj1f0+aw EObwsA8LmlRj3IV9PJU8ybCWytVaHIURnkxlZGoHdNB3BxSQ2xMCQuKIKzv9ahh7JKz+/9//cVYz PiB94NAw2NVll/3tlkxwP8Y+xNSkkY7Tj8bsYYCYXmrzSgnIlZfKQY8GrCvxZMg+IcQBsQ2Ph+yz E6UCL5IvIPpPIlx8HeFi5k0JEPd3iUlfLA5ieTGSYsPyxQfAhOuIIblnNIyOJgtH2ghdDpTza+LJ GUG/If9O5PgxwF3i3cyci0jOKe9NXk1ZaMhdXZDZ0/sR0vgoyGiH6f1ey5xItRQE9h0Y+9rRYrtG 3hqwciRUrDkAMxVlxweL8rVXGQzWEipy+g44XI/7XxgyRPtkFwGVA2VzwjDGHZhVtOGGEh8ZuHtq 2Olm/mjWIH7KHgT3PrAR/OBgiZo46kRkxCGBz/vwXPfHmg9rNzcsO5oLa+4MOsrtoYNMGeLTiQc9 Ao/XBBW6e5qBDT5NWenM8TxhO3Cuo904AN1dGC5KKXedk3qnclbYwCRhCSeIEjcgJsWDZEQ+PYhN ObvUjoHdfAmR6h8A2CwNfB8ooCFbWWKQYgjJLwZMBnysyx2k8RC8B4NYyoMBGwCRdbnmb0Q5PTKO 85pQYW0CG3SUfFP1f5NxyZBUlomX6nSy3OXloudHZoyWdeQ2VadwBWm9kCtyoc043aY3ZKN9piCq n6foQ478FUFg2lkIXFvWeXezvjOR8ds2tsJGkVRXcdzhbIYI7l2T/qVpT1otxJy8EPFeSDQHv9kz uEf8KpCIS68m9RkAWdmDxfF2LU5GSRROV/RhX6QRYDRUMwV0dzKikbnTBsdUNNomt1jXjQdQmS9O /i95kzswI7JbaCbhjEVtGeK1QflkggB7jCEg+u1jTP242oEgvnsYQ3l/pFw3kgCMNdAm4T7pBIAW 6kiVPS4RKPAtpELucek5M5k4b1JNLstVxpVl9KvtcJ8mvD6RGpdvU3saiiyujU/bs068S950jIJ7 81OLf/v4VGxp7kILbg9IhQoGqHVa/ihRnnRR5n9B+evF78M/5CwULwy0xV6D+RL1nnYVJEd8T7uK ivd3lhVTRWXpm7P4X9Auz0f1fPjJMsry3uY0KY2yuQIoeylltzToxqMoXwnfFmptXonaVO0k5GGv N1M1IO2eWF9vfs8YlIJSQRnPRcNNQ03gv6fcG0p9RtIyyqk7fQR+5DNvtuyr3Lj+vwb+701kBKl7 VEd5vKmiZMvVV9pFdbKNeB/2GQFaDZ/dJTmPNzICTRj/sLr4uUeePfKkkQwrI0/B+eRnnaAaJlGW 2MFFR7/d+VOBlrrqxw85hXN5le1dZK8vbTHRMLRLvvrlF3p7HoRvGvtUqUyiw5OqoIWNb0xMIp3L 47Mz3eVNK3TFiY05xTZFr3lTZpIx1qvemsv6rtSPT2oL9hRBV5Br44lPA07b1Fy+LGRZTdTKnKCl rwGbZkMk0dpUrYV0NbepU71taKnGnBtaTobE5GQblCBGKxYpY9FLRNH1SGcacmv8O6b9MEmKnrZo IuCfVQzjP5BsbaFwQpL1liUDUNY5E0+WG4eoXoXQe4SoJwH6McrUIXY/H9ePXLzxO4/TrtbzOFNY MrZB0fqbMorvEKa9rhmBmPi7LDa9yTVaO5D5hXO24AV1HiTTScNEYpHvghqhLneQXIVjxlHRJk2L Rt60rjaqw7nosZ+569gg5chZtUWAapFak6BWfm7cXLcaD9d3t0SndZtpXhg2WETCK3K8HkbIvxkf IOMVKVxS0X41zObjtEQhWEOWSKZzudIsHspz1ullVFYH6dDUO9xnYDzUE7CMfOtsbvPzWtZNwVaA XC82lE7CjBxfN/zeGcuuFHDftstwZ7nNWyjZViXTdvW03sxkZwjGQLdltmMlkfOPG/23sq1jL8TM rc2tIW3BFgB1ozlRJpZf60yUecFU201sI3yyMX/u5nu+MJOA8gdm/DkY3aYQbSsDufgI9g6u/SNy tT3u59BlJ1fmYl2mvj3z5s6yFyDzbEz05oFwMR2o1dsnR9+EDszbxATJ/nqw0waS5Fpm+1lIB/Je qRdo9N18cDs9pPlZwm8YUptCCV6S68yMR0Uf6sdGpaVNllOWvfTi9yLrS434IlWcoHwdPqtwfx6J HlXfOIRzKEfpCQdpPF/febrWrLfaTTJIbdpIvbNUMiGJ+m/O8gzw2axglM79WoC36U6SpD4JvTfZ f1WrB3Xj+KByVjmo1qpHe+gChtDmdJvZj663FegqCiAtiCxmz/9y4PSCnxYNLzr8KcMI46B2ahwY x2fvfIfGGbdfYV0Ye0vTgp1dNQFaZ1tMYOtadGaO7jF3C9ndtTT9pmCtcrorxuS9gW+ugW8ecr3V S/mCU383zffrO5KSQIuSBtmOe3r3Cb0XBVVjRY3/fj9k/8m94L/ZR0FbS0/vTdGA6woxqiFHMeHn IoZrG6IuTxrVy72K5eTS9WcNUduA12XU4F0lH8f10wVhJFMGuClO7UsU5pR98P1ncxfKesLF+oin AlRmIfWG2U4YPejNuOnocnJ0Mzm6pyP9iniK4Bpm1tN5qWIcndapApI1Jr+QYRzVtLUtMLHtCra2 bCePwmlUOTNqeA4Vk/A32fa7R8ckkASmLa2uYo59XkItQzJtnJe6jhXRdi1HJTivQwuvXHtUChO7 xMQuqnzDi+1yBUwNcDVtxrodXikeYHOZDjZIFBRhwU2QgsmVG2l9CUlP8UOTn5cGURSY5XJoIXqM h4cyED7uoWmPRzhVj+V0qjy3jNGdlGnHGHRQNqnek2iEAcaIsdHnyxjGa99/61enhtLiEWexAmKt PIAgmVUsJI5M/E+7haM3t+YPuw6WMWkaU5GuKNZ7zRWlLlI7Saucupss4MsFeF4TpeRoILiN6mLJ uuRbKdNprqc91wk6cJvQBNMxUyZxBsCiurZPaGm5GSrrHkudHEdKRNaALiMqw02vl/FQdkN/47lZ +mKIcB/WG32UFKBIJjKsADef+sqjX1SyZcAmzBTQSOMEN4Flr6EYvpe9HagwQvkTD5F8IaBRoaO6 dT68CanLeDR7hD7mSxqtHorrs9F56awGrJ2546FmLxDM8WgHhawUJTdpYtu+rV+OYHZNjvEB18d3 soGmhzjVH08RkKB2+hzHE/pDx+aELBGl0leWNGamnsZdN2YuJu2Yj6T+3vKbqGOJ4PWRLshk6rY3 jEuj89LBu0poLLW5ck+W1AAXCKmnmrTnU6T0tWd2tqAeHPuK+2bD/un5gszcKV9mTBc3mrl1wdw+ EHJEGiHeI1rM1oN/s9Fpo1iBpXlfVOro+CQvgGpupsnN9kjDXDSa0LKVE8C+H+p/tc+LndGMNdt3 5ebdQefup9tW+z5PFl7o6BhjtbE5t/sK5O0NY8xRunlD2mRE0YaHdHF1d3d102bXt83D3DiWJxG1 03qrpZNcdtsruzKJeHBQsZXdihG7lwhfIgKT1vWbvbN5uWb55VksZ7Zr1eNmg7pNC9eFEG80ThD+ 1oRcnYb6j8yibCK4egz+7CJ8y+XBlL4idjYUNhSZApfJ+aydScPNgsDHedylojU/Kr7/zF2Sa4CX lNEtFDyfPZ5rHuXoBwCITDhtpTDv0TiABgmVypu3YekU4KWweJ+4J77O8SYzlyLe5PybzOTF//2z KYNxkpR2ZFROsmzna9+SSChTOiMtT1cXzAt00kRnoOnSdLTIs/IvAQAAAP//bFFLbsIwEL1K5AMU U4FLIxIJpXRXKYJF1yZ2QiQnTu0Jbjl9xx8qJLqJMs/zPjNjr5XNXH7hqiBLRhblduFyU5ty63LI vgeV24k3siCTkVaaiyRltlMqM313BpslUDx5GkRy+E5eYEJlY3txKAile8reK0ZuUG08uGNrWlV/ 4Jts+azgsb2+a8aMLreygdrcxB4Jh//0j0gKrRW6MhIidscrqjicfvlKqU9y9pvYrKhfBs7QfXDv A3pCfBM6wvAFYbE6aQA94GN4U7JFj5fnKCW5kDhoKlut4a7sZghlcmq08qdI+04U+TVz9dkLwFQ0 JMa2FJiuMXC8mOf6tKPej2JElwjHLYWDnLT4CT9CN/MgRyh/AQAA//8DAFBLAwQUAAYACAAAACEA lrWt4pYGAABQGwAAFQAAAHdvcmQvdGhlbWUvdGhlbWUxLnhtbOxZT2/bNhS/D9h3IHRvYyd2Ggd1 itixmy1NG8Ruhx5piZbYUKJA0kl9G9rjgAHDumGHFdhth2FbgRbYpfs02TpsHdCvsEdSksVYXpI2 2IqtPiQS+eP7/x4fqavX7scMHRIhKU/aXv1yzUMk8XlAk7Dt3R72L615SCqcBJjxhLS9KZHetY33 37uK11VEYoJgfSLXcduLlErXl5akD8NYXuYpSWBuzEWMFbyKcCkQ+AjoxmxpuVZbXYoxTTyU4BjI 3hqPqU/QUJP0NnLiPQaviZJ6wGdioEkTZ4XBBgd1jZBT2WUCHWLW9oBPwI+G5L7yEMNSwUTbq5mf t7RxdQmvZ4uYWrC2tK5vftm6bEFwsGx4inBUMK33G60rWwV9A2BqHtfr9bq9ekHPALDvg6ZWljLN Rn+t3slplkD2cZ52t9asNVx8if7KnMytTqfTbGWyWKIGZB8bc/i12mpjc9nBG5DFN+fwjc5mt7vq 4A3I4lfn8P0rrdWGizegiNHkYA6tHdrvZ9QLyJiz7Ur4GsDXahl8hoJoKKJLsxjzRC2KtRjf46IP AA1kWNEEqWlKxtiHKO7ieCQo1gzwOsGlGTvky7khzQtJX9BUtb0PUwwZMaP36vn3r54/RccPnh0/ +On44cPjBz9aQs6qbZyE5VUvv/3sz8cfoz+efvPy0RfVeFnG//rDJ7/8/Hk1ENJnJs6LL5/89uzJ i68+/f27RxXwTYFHZfiQxkSim+QI7fMYFDNWcSUnI3G+FcMI0/KKzSSUOMGaSwX9nooc9M0pZpl3 HDk6xLXgHQHlowp4fXLPEXgQiYmiFZx3otgB7nLOOlxUWmFH8yqZeThJwmrmYlLG7WN8WMW7ixPH v71JCnUzD0tH8W5EHDH3GE4UDklCFNJz/ICQCu3uUurYdZf6gks+VuguRR1MK00ypCMnmmaLtmkM fplW6Qz+dmyzewd1OKvSeoscukjICswqhB8S5pjxOp4oHFeRHOKYlQ1+A6uoSsjBVPhlXE8q8HRI GEe9gEhZteaWAH1LTt/BULEq3b7LprGLFIoeVNG8gTkvI7f4QTfCcVqFHdAkKmM/kAcQohjtcVUF 3+Vuhuh38ANOFrr7DiWOu0+vBrdp6Ig0CxA9MxHal1CqnQoc0+TvyjGjUI9tDFxcOYYC+OLrxxWR 9bYW4k3Yk6oyYftE+V2EO1l0u1wE9O2vuVt4kuwRCPP5jeddyX1Xcr3/fMldlM9nLbSz2gplV/cN tik2LXK8sEMeU8YGasrIDWmaZAn7RNCHQb3OnA5JcWJKI3jM6rqDCwU2a5Dg6iOqokGEU2iw654m EsqMdChRyiUc7MxwJW2NhyZd2WNhUx8YbD2QWO3ywA6v6OH8XFCQMbtNaA6fOaMVTeCszFauZERB 7ddhVtdCnZlb3YhmSp3DrVAZfDivGgwW1oQGBEHbAlZehfO5Zg0HE8xIoO1u997cLcYLF+kiGeGA ZD7Ses/7qG6clMeKuQmA2KnwkT7knWK1EreWJvsG3M7ipDK7xgJ2uffexEt5BM+8pPP2RDqypJyc LEFHba/VXG56yMdp2xvDmRYe4xS8LnXPh1kIF0O+EjbsT01mk+Uzb7ZyxdwkqMM1hbX7nMJOHUiF VFtYRjY0zFQWAizRnKz8y00w60UpYCP9NaRYWYNg+NekADu6riXjMfFV2dmlEW07+5qVUj5RRAyi 4AiN2ETsY3C/DlXQJ6ASriZMRdAvcI+mrW2m3OKcJV359srg7DhmaYSzcqtTNM9kCzd5XMhg3kri gW6Vshvlzq+KSfkLUqUcxv8zVfR+AjcFK4H2gA/XuAIjna9tjwsVcahCaUT9voDGwdQOiBa4i4Vp CCq4TDb/BTnU/23OWRomreHAp/ZpiASF/UhFgpA9KEsm+k4hVs/2LkuSZYRMRJXElakVe0QOCRvq Griq93YPRRDqpppkZcDgTsaf+55l0CjUTU4535waUuy9Ngf+6c7HJjMo5dZh09Dk9i9ErNhV7Xqz PN97y4roiVmb1cizApiVtoJWlvavKcI5t1pbseY0Xm7mwoEX5zWGwaIhSuG+B+k/sP9R4TP7ZUJv qEO+D7UVwYcGTQzCBqL6km08kC6QdnAEjZMdtMGkSVnTZq2Ttlq+WV9wp1vwPWFsLdlZ/H1OYxfN mcvOycWLNHZmYcfWdmyhqcGzJ1MUhsb5QcY4xnzSKn914qN74OgtuN+fMCVNMME3JYGh9RyYPIDk txzN0o2/AAAA//8DAFBLAwQKAAAAAAAAACEAzfSFrLwhAAC8IQAAFgAAAHdvcmQvbWVkaWEvaW1h Z2UxLmpwZWf/2P/gABBKRklGAAEBAQ7EDsQAAP/bAEMAAwICAwICAwMDAwQDAwQFCAUFBAQFCgcH BggMCgwMCwoLCw0OEhANDhEOCwsQFhARExQVFRUMDxcYFhQYEhQVFP/bAEMBAwQEBQQFCQUFCRQN Cw0UFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFP/AABEI AH0BOQMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMD AgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUm JygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaX mJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4 +fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncA AQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6 Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeo qaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2gAMAwEAAhED EQA/AP1TooooAZxigAdhRkY61w3j/wCMvhD4a27Sa/rdtYsv/LIvmRv+A1dOjUrS5aUeaREpxgua R3WQKNwr498S/wDBSPwZYXMttoWh6pr0i/deNNiNXOXP/BSySz+af4danDF/fd69qGRY+av7P8Uc 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 AAAOAA4AiAMAAN1gAAAAAA== --===============1880848174==-- From bfoster@redhat.com Tue Jun 14 07:59:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A45BF7CA0 for ; Tue, 14 Jun 2016 07:59:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 651F08F8035 for ; Tue, 14 Jun 2016 05:59:03 -0700 (PDT) X-ASG-Debug-ID: 1465909141-04cbb03f53f7e30001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id cEYrGe09zXof7lI7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 05:59:01 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0908F1393C0 for ; Tue, 14 Jun 2016 12:59:01 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-81.bos.redhat.com [10.18.41.81]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5ECx0lr006933 for ; Tue, 14 Jun 2016 08:59:00 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id A4C2A12673F; Tue, 14 Jun 2016 08:58:59 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly Date: Tue, 14 Jun 2016 08:58:59 -0400 X-ASG-Orig-Subj: [PATCH] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly Message-Id: <1465909139-36329-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 14 Jun 2016 12:59:01 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465909141 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7269 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 xfs_reserve_blocks() is responsible to update the XFS reserved block pool count at mount time or based on user request. When the caller requests to increase the reserve pool, blocks must be allocated from the global counters such that they are no longer available for general purpose use. If the requested reserve pool size is too large, XFS reserves what blocks are available. The implementation requires looking at the percpu counters and making an educated guess as to how many blocks to try and allocate from xfs_mod_fdblocks(), which can return -ENOSPC if the guess was not accurate due to counters being modified in parallel. xfs_reserve_blocks() retries the guess in this scenario until the allocation succeeds or it is determined that there is no space available in the fs. While not easily reproducible in the current form, the retry code doesn't actually work correctly if xfs_mod_fdblocks() actually fails. The problem is that the percpu calculations use the m_resblks counter to determine how many blocks to allocate, but unconditionally update m_resblks before the block allocation has actually succeeded. Therefore, if xfs_mod_fdblocks() fails, the code jumps to the retry label and uses the already updated m_resblks value to determine how many blocks to try and allocate. If the percpu counters previously suggested that the entire request was available, fdblocks_delta could end up set to 0. In that case, m_resblks is updated to the requested value, yet no blocks have been reserved at all. Refactor xfs_reserve_blocks() to use an explicit loop and make the code easier to follow. Since we have to drop the spinlock across the xfs_mod_fdblocks() call, use a delta value for m_resblks as well and only apply the delta once allocation succeeds. Signed-off-by: Brian Foster --- This is something I had laying around from the thin block device reservation stuff. That work introduced a more common xfs_mod_fdblocks() failure scenario that isn't as much of a problem with the current code, but the current xfs_reserve_blocks() retry code is clearly broken and so should probably be fixed up. Brian fs/xfs/xfs_fsops.c | 105 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index b4d7582..003d180 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -667,8 +667,11 @@ xfs_reserve_blocks( __uint64_t *inval, xfs_fsop_resblks_t *outval) { - __int64_t lcounter, delta, fdblks_delta; + __int64_t lcounter, delta; + __int64_t fdblks_delta = 0; __uint64_t request; + __int64_t free; + int error = 0; /* If inval is null, report current values and return */ if (inval == (__uint64_t *)NULL) { @@ -682,24 +685,23 @@ xfs_reserve_blocks( request = *inval; /* - * With per-cpu counters, this becomes an interesting - * problem. we needto work out if we are freeing or allocation - * blocks first, then we can do the modification as necessary. + * With per-cpu counters, this becomes an interesting problem. we need + * to work out if we are freeing or allocation blocks first, then we can + * do the modification as necessary. * - * We do this under the m_sb_lock so that if we are near - * ENOSPC, we will hold out any changes while we work out - * what to do. This means that the amount of free space can - * change while we do this, so we need to retry if we end up - * trying to reserve more space than is available. + * We do this under the m_sb_lock so that if we are near ENOSPC, we will + * hold out any changes while we work out what to do. This means that + * the amount of free space can change while we do this, so we need to + * retry if we end up trying to reserve more space than is available. */ -retry: spin_lock(&mp->m_sb_lock); /* * If our previous reservation was larger than the current value, - * then move any unused blocks back to the free pool. + * then move any unused blocks back to the free pool. Modify the resblks + * counters directly since we shouldn't have any problems unreserving + * space. */ - fdblks_delta = 0; if (mp->m_resblks > request) { lcounter = mp->m_resblks_avail - request; if (lcounter > 0) { /* release unused blocks */ @@ -707,54 +709,67 @@ retry: mp->m_resblks_avail -= lcounter; } mp->m_resblks = request; - } else { - __int64_t free; + if (fdblks_delta) { + spin_unlock(&mp->m_sb_lock); + error = xfs_mod_fdblocks(mp, fdblks_delta, 0); + spin_lock(&mp->m_sb_lock); + } + + goto out; + } + /* + * If the request is larger than the current reservation, reserve the + * blocks before we update the reserve counters. Sample m_fdblocks and + * perform a partial reservation if the request exceeds free space. + */ + error = -ENOSPC; + while (error == -ENOSPC) { free = percpu_counter_sum(&mp->m_fdblocks) - XFS_ALLOC_SET_ASIDE(mp); if (!free) - goto out; /* ENOSPC and fdblks_delta = 0 */ + break; delta = request - mp->m_resblks; lcounter = free - delta; - if (lcounter < 0) { + if (lcounter < 0) /* We can't satisfy the request, just get what we can */ - mp->m_resblks += free; - mp->m_resblks_avail += free; - fdblks_delta = -free; - } else { - fdblks_delta = -delta; - mp->m_resblks = request; - mp->m_resblks_avail += delta; - } - } -out: - if (outval) { - outval->resblks = mp->m_resblks; - outval->resblks_avail = mp->m_resblks_avail; - } - spin_unlock(&mp->m_sb_lock); + fdblks_delta = free; + else + fdblks_delta = delta; - if (fdblks_delta) { /* - * If we are putting blocks back here, m_resblks_avail is - * already at its max so this will put it in the free pool. - * - * If we need space, we'll either succeed in getting it - * from the free block count or we'll get an enospc. If - * we get a ENOSPC, it means things changed while we were - * calculating fdblks_delta and so we should try again to - * see if there is anything left to reserve. + * We'll either succeed in getting space from the free block + * count or we'll get an ENOSPC. If we get a ENOSPC, it means + * things changed while we were calculating fdblks_delta and so + * we should try again to see if there is anything left to + * reserve. * * Don't set the reserved flag here - we don't want to reserve * the extra reserve blocks from the reserve..... */ - int error; - error = xfs_mod_fdblocks(mp, fdblks_delta, 0); - if (error == -ENOSPC) - goto retry; + spin_unlock(&mp->m_sb_lock); + error = xfs_mod_fdblocks(mp, -fdblks_delta, 0); + spin_lock(&mp->m_sb_lock); } - return 0; + + /* + * Update the reserve counters if blocks have been successfully + * allocated. + */ + if (!error && fdblks_delta) { + mp->m_resblks += fdblks_delta; + mp->m_resblks_avail += fdblks_delta; + } + +out: + if (outval) { + outval->resblks = mp->m_resblks; + outval->resblks_avail = mp->m_resblks_avail; + } + + spin_unlock(&mp->m_sb_lock); + return error; } int -- 2.5.5 From pcacjr@zytor.com Tue Jun 14 08:33:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 930A37CA2 for ; Tue, 14 Jun 2016 08:33:15 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 51A5D8F8033 for ; Tue, 14 Jun 2016 06:33:12 -0700 (PDT) X-ASG-Debug-ID: 1465911189-04bdf01e132ded0001-NocioJ Received: from mail.zytor.com ([198.137.202.10]) by cuda.sgi.com with ESMTP id iddkrtZpyJl4JSKt (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 06:33:09 -0700 (PDT) X-Barracuda-Envelope-From: pcacjr@zytor.com X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.10] X-Barracuda-Apparent-Source-IP: 198.137.202.10 Received: from [10.10.1.56] ([15.219.162.32]) (authenticated bits=0) by mail.zytor.com (8.15.2/8.14.5) with ESMTPSA id u5EDX5Ct027128 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO); Tue, 14 Jun 2016 06:33:08 -0700 User-Agent: K-9 Mail for Android In-Reply-To: <1465909139-36329-1-git-send-email-bfoster@redhat.com> References: <1465909139-36329-1-git-send-email-bfoster@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Subject: Re: [PATCH] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly From: Paulo Alcantara X-ASG-Orig-Subj: Re: [PATCH] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly Date: Tue, 14 Jun 2016 10:32:57 -0300 To: Brian Foster , xfs@oss.sgi.com Message-ID: X-Barracuda-Connect: UNKNOWN[198.137.202.10] X-Barracuda-Start-Time: 1465911189 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5416 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30426 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On June 14, 2016 9:58:59 AM GMT-03:00, Brian Foster wrote: >xfs_reserve_blocks() is responsible to update the XFS reserved block >pool count at mount time or based on user request. When the caller >requests to increase the reserve pool, blocks must be allocated from >the >global counters such that they are no longer available for general >purpose use. If the requested reserve pool size is too large, XFS >reserves what blocks are available. The implementation requires looking >at the percpu counters and making an educated guess as to how many >blocks to try and allocate from xfs_mod_fdblocks(), which can return >-ENOSPC if the guess was not accurate due to counters being modified in >parallel. > >xfs_reserve_blocks() retries the guess in this scenario until the >allocation succeeds or it is determined that there is no space >available >in the fs. While not easily reproducible in the current form, the retry >code doesn't actually work correctly if xfs_mod_fdblocks() actually >fails. The problem is that the percpu calculations use the m_resblks >counter to determine how many blocks to allocate, but unconditionally >update m_resblks before the block allocation has actually succeeded. >Therefore, if xfs_mod_fdblocks() fails, the code jumps to the retry >label and uses the already updated m_resblks value to determine how >many >blocks to try and allocate. If the percpu counters previously suggested >that the entire request was available, fdblocks_delta could end up set >to 0. In that case, m_resblks is updated to the requested value, yet no >blocks have been reserved at all. > >Refactor xfs_reserve_blocks() to use an explicit loop and make the code >easier to follow. Since we have to drop the spinlock across the >xfs_mod_fdblocks() call, use a delta value for m_resblks as well and >only apply the delta once allocation succeeds. > >Signed-off-by: Brian Foster >--- > >This is something I had laying around from the thin block device >reservation stuff. That work introduced a more common >xfs_mod_fdblocks() >failure scenario that isn't as much of a problem with the current code, >but the current xfs_reserve_blocks() retry code is clearly broken and >so >should probably be fixed up. > >Brian > >fs/xfs/xfs_fsops.c | 105 >++++++++++++++++++++++++++++++----------------------- > 1 file changed, 60 insertions(+), 45 deletions(-) > >diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c >index b4d7582..003d180 100644 >--- a/fs/xfs/xfs_fsops.c >+++ b/fs/xfs/xfs_fsops.c >@@ -667,8 +667,11 @@ xfs_reserve_blocks( > __uint64_t *inval, > xfs_fsop_resblks_t *outval) > { >- __int64_t lcounter, delta, fdblks_delta; >+ __int64_t lcounter, delta; >+ __int64_t fdblks_delta = 0; > __uint64_t request; >+ __int64_t free; >+ int error = 0; > > /* If inval is null, report current values and return */ > if (inval == (__uint64_t *)NULL) { >@@ -682,24 +685,23 @@ xfs_reserve_blocks( > request = *inval; > > /* >- * With per-cpu counters, this becomes an interesting >- * problem. we needto work out if we are freeing or allocation >- * blocks first, then we can do the modification as necessary. >+ * With per-cpu counters, this becomes an interesting problem. we >need >+ * to work out if we are freeing or allocation blocks first, then we >can >+ * do the modification as necessary. > * >- * We do this under the m_sb_lock so that if we are near >- * ENOSPC, we will hold out any changes while we work out >- * what to do. This means that the amount of free space can >- * change while we do this, so we need to retry if we end up >- * trying to reserve more space than is available. >+ * We do this under the m_sb_lock so that if we are near ENOSPC, we >will >+ * hold out any changes while we work out what to do. This means that >+ * the amount of free space can change while we do this, so we need >to >+ * retry if we end up trying to reserve more space than is available. > */ >-retry: > spin_lock(&mp->m_sb_lock); > > /* > * If our previous reservation was larger than the current value, >- * then move any unused blocks back to the free pool. >+ * then move any unused blocks back to the free pool. Modify the >resblks >+ * counters directly since we shouldn't have any problems unreserving >+ * space. > */ >- fdblks_delta = 0; > if (mp->m_resblks > request) { > lcounter = mp->m_resblks_avail - request; > if (lcounter > 0) { /* release unused blocks */ >@@ -707,54 +709,67 @@ retry: > mp->m_resblks_avail -= lcounter; > } > mp->m_resblks = request; >- } else { >- __int64_t free; >+ if (fdblks_delta) { >+ spin_unlock(&mp->m_sb_lock); >+ error = xfs_mod_fdblocks(mp, fdblks_delta, 0); >+ spin_lock(&mp->m_sb_lock); >+ } >+ >+ goto out; >+ } > >+ /* >+ * If the request is larger than the current reservation, reserve the >+ * blocks before we update the reserve counters. Sample m_fdblocks >and >+ * perform a partial reservation if the request exceeds free space. >+ */ >+ error = -ENOSPC; >+ while (error == -ENOSPC) { Why don't you make this a "do { } while (error == -ENOSPC)"? xfs_mod_fdblocks() will already set the error at the end of that loop. Paulo -- Paulo Alcantara, HP Speaking for myself only. From bfoster@redhat.com Tue Jun 14 08:37:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 61B767CA0 for ; Tue, 14 Jun 2016 08:37:29 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id D0F3DAC003 for ; Tue, 14 Jun 2016 06:37:25 -0700 (PDT) X-ASG-Debug-ID: 1465911443-04cb6c38149fa80001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 9VDCwE8mGrimHaak (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 06:37:24 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 7FD8085543; Tue, 14 Jun 2016 13:37:23 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-81.bos.redhat.com [10.18.41.81]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5EDbN9P013707; Tue, 14 Jun 2016 09:37:23 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 1D98212673F; Tue, 14 Jun 2016 09:37:22 -0400 (EDT) Date: Tue, 14 Jun 2016 09:37:22 -0400 From: Brian Foster To: Paulo Alcantara Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly Message-ID: <20160614133721.GD32443@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly References: <1465909139-36329-1-git-send-email-bfoster@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 14 Jun 2016 13:37:23 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465911444 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1954 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Tue, Jun 14, 2016 at 10:32:57AM -0300, Paulo Alcantara wrote: > > > On June 14, 2016 9:58:59 AM GMT-03:00, Brian Foster wrote: ... > > > >Signed-off-by: Brian Foster > >--- > > > >This is something I had laying around from the thin block device > >reservation stuff. That work introduced a more common > >xfs_mod_fdblocks() > >failure scenario that isn't as much of a problem with the current code, > >but the current xfs_reserve_blocks() retry code is clearly broken and > >so > >should probably be fixed up. > > > >Brian > > > >fs/xfs/xfs_fsops.c | 105 > >++++++++++++++++++++++++++++++----------------------- > > 1 file changed, 60 insertions(+), 45 deletions(-) > > > >diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c > >index b4d7582..003d180 100644 > >--- a/fs/xfs/xfs_fsops.c > >+++ b/fs/xfs/xfs_fsops.c ... > >@@ -707,54 +709,67 @@ retry: > > mp->m_resblks_avail -= lcounter; > > } > > mp->m_resblks = request; > >- } else { > >- __int64_t free; > >+ if (fdblks_delta) { > >+ spin_unlock(&mp->m_sb_lock); > >+ error = xfs_mod_fdblocks(mp, fdblks_delta, 0); > >+ spin_lock(&mp->m_sb_lock); > >+ } > >+ > >+ goto out; > >+ } > > > >+ /* > >+ * If the request is larger than the current reservation, reserve the > >+ * blocks before we update the reserve counters. Sample m_fdblocks > >and > >+ * perform a partial reservation if the request exceeds free space. > >+ */ > >+ error = -ENOSPC; > >+ while (error == -ENOSPC) { > > Why don't you make this a "do { } while (error == -ENOSPC)"? xfs_mod_fdblocks() will already set the error at the end of that loop. > Sure, I can clean that up. Thanks. Brian > Paulo > > -- > Paulo Alcantara, HP > Speaking for myself only. > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From Waiman.Long@hpe.com Tue Jun 14 13:13:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 3BBB27CA0 for ; Tue, 14 Jun 2016 13:13:23 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0F2F38F8050 for ; Tue, 14 Jun 2016 11:13:23 -0700 (PDT) X-ASG-Debug-ID: 1465928000-04cbb03f55101a10001-NocioJ Received: from g9t5009.houston.hpe.com (g9t5009.houston.hpe.com [15.241.48.73]) by cuda.sgi.com with ESMTP id DSTG36VKwMrSLcti (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:13:20 -0700 (PDT) X-Barracuda-Envelope-From: Waiman.Long@hpe.com X-Barracuda-Effective-Source-IP: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Apparent-Source-IP: 15.241.48.73 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g9t5009.houston.hpe.com (Postfix) with ESMTP id E634258; Tue, 14 Jun 2016 18:13:19 +0000 (UTC) Received: from RHEL65.localdomain (unknown [16.214.227.42]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 87F0C53; Tue, 14 Jun 2016 18:13:18 +0000 (UTC) From: Waiman Long To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch , Waiman Long Subject: [RFC PATCH-tip 1/6] locking/rwsem: Stop active read lock ASAP Date: Tue, 14 Jun 2016 14:12:34 -0400 X-ASG-Orig-Subj: [RFC PATCH-tip 1/6] locking/rwsem: Stop active read lock ASAP Message-Id: <1465927959-39719-2-git-send-email-Waiman.Long@hpe.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> X-Barracuda-Connect: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Start-Time: 1465928000 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3212 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30432 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Currently, when down_read() fails, the active read locking isn't undone until the rwsem_down_read_failed() function grabs the wait_lock. If the wait_lock is contended, it may takes a while to get the lock. During that period, writer lock stealing will be disabled because of the active read lock. This patch will release the active read lock ASAP so that writer lock stealing can happen sooner. The only downside is when the reader is the first one in the wait queue as it has to issue another atomic operation to update the count. On a 4-socket Haswell machine running on a 4.7-rc1 tip-based kernel, the fio test with multithreaded randrw and randwrite tests on the same file on a XFS partition on top of a NVDIMM with DAX were run, the aggregated bandwidths before and after the patch were as follows: Test BW before patch BW after patch % change ---- --------------- -------------- -------- randrw 1210 MB/s 1352 MB/s +12% randwrite 1622 MB/s 1710 MB/s +5.4% The write-only microbench also showed improvement because some read locking was done by the XFS code. Signed-off-by: Waiman Long --- kernel/locking/rwsem-xadd.c | 19 ++++++++++++++----- 1 files changed, 14 insertions(+), 5 deletions(-) diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 2031281..29027c6 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -230,11 +230,18 @@ __rwsem_mark_wake(struct rw_semaphore *sem, __visible struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) { - long count, adjustment = -RWSEM_ACTIVE_READ_BIAS; + long count, adjustment = 0; struct rwsem_waiter waiter; struct task_struct *tsk = current; WAKE_Q(wake_q); + /* + * Undo read bias from down_read operation, stop active locking. + * Doing that after taking the wait_lock may block writer lock + * stealing for too long. + */ + atomic_long_add(-RWSEM_ACTIVE_READ_BIAS, &sem->count); + /* set up my own style of waitqueue */ waiter.task = tsk; waiter.type = RWSEM_WAITING_FOR_READ; @@ -244,8 +251,11 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) adjustment += RWSEM_WAITING_BIAS; list_add_tail(&waiter.list, &sem->wait_list); - /* we're now waiting on the lock, but no longer actively locking */ - count = atomic_long_add_return(adjustment, &sem->count); + /* we're now waiting on the lock */ + if (adjustment) + count = atomic_long_add_return(adjustment, &sem->count); + else + count = atomic_long_read(&sem->count); /* If there are no active locks, wake the front queued process(es). * @@ -253,8 +263,7 @@ struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) * wake our own waiter to join the existing active readers ! */ if (count == RWSEM_WAITING_BIAS || - (count > RWSEM_WAITING_BIAS && - adjustment != -RWSEM_ACTIVE_READ_BIAS)) + (count > RWSEM_WAITING_BIAS && adjustment)) sem = __rwsem_mark_wake(sem, RWSEM_WAKE_ANY, &wake_q); raw_spin_unlock_irq(&sem->wait_lock); -- 1.7.1 From Waiman.Long@hpe.com Tue Jun 14 13:13:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id F29437CA4 for ; Tue, 14 Jun 2016 13:13:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id C45C98F8052 for ; Tue, 14 Jun 2016 11:13:22 -0700 (PDT) X-ASG-Debug-ID: 1465927999-04cbb03f52101a00001-NocioJ Received: from g9t5009.houston.hpe.com (g9t5009.houston.hpe.com [15.241.48.73]) by cuda.sgi.com with ESMTP id RZzunPrPUdV1sb64 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:13:19 -0700 (PDT) X-Barracuda-Envelope-From: Waiman.Long@hpe.com X-Barracuda-Effective-Source-IP: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Apparent-Source-IP: 15.241.48.73 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g9t5009.houston.hpe.com (Postfix) with ESMTP id 65F8E4D; Tue, 14 Jun 2016 18:13:18 +0000 (UTC) Received: from RHEL65.localdomain (unknown [16.214.227.42]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 35CF84D; Tue, 14 Jun 2016 18:13:16 +0000 (UTC) From: Waiman Long To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch , Waiman Long Subject: [RFC PATCH-tip 0/6] locking/rwsem: Enable reader optimistic spinning Date: Tue, 14 Jun 2016 14:12:33 -0400 X-ASG-Orig-Subj: [RFC PATCH-tip 0/6] locking/rwsem: Enable reader optimistic spinning Message-Id: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> X-Mailer: git-send-email 1.7.1 X-Barracuda-Connect: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Start-Time: 1465927999 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1940 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30432 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header This patchset adds an option to enable more aggressive optimistic spinning on both readers and writers waiting on a writer or reader owned lock. Spinning on writer is done by looking at the on_cpu flag of the lock owner. Spinning on readers, on the other hand, is count-based as there is no easy way to figure out if all the readers are running. The spinner will stop spinning once the count goes to 0. Because of that, spinning on readers may hurt performance in some cases. So this feature is optional and has to explicitly enabled for those rwsems where the readers are unlikely to go to sleep. Patch 1 reduces the length of the blocking window after a read locking attempt where writer lock stealing is disabled because of the active read lock. It can improve rwsem performance for contended lock. It is independent of the rest of the patchset. Patches 2-5 lays the groundwork for enabling reader optimistic spinning. Patch 6 enables reader optimistic spinning in XFS for inodes that comes from a DAX-enabled mount point on top of persistent memory as the CPUs can do I/O directly without waiting or sleeping. Waiman Long (6): locking/rwsem: Stop active read lock ASAP locking/rwsem: Enable optional count-based spinning on reader locking/rwsem: move down rwsem_down_read_failed function locking/rwsem: Change RWSEM_WAITING_BIAS for better disambiguation locking/rwsem: Enable spinning readers xfs: Enable reader optimistic spinning for DAX inodes arch/alpha/include/asm/rwsem.h | 7 +- arch/ia64/include/asm/rwsem.h | 6 +- arch/s390/include/asm/rwsem.h | 6 +- arch/x86/include/asm/rwsem.h | 13 ++- fs/xfs/xfs_icache.c | 9 ++ include/asm-generic/rwsem.h | 9 +- include/linux/rwsem.h | 21 ++++- kernel/locking/rwsem-xadd.c | 212 ++++++++++++++++++++++++++-------------- 8 files changed, 192 insertions(+), 91 deletions(-) From Waiman.Long@hpe.com Tue Jun 14 13:13:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 26E657CAF for ; Tue, 14 Jun 2016 13:13:28 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id B30CDAC001 for ; Tue, 14 Jun 2016 11:13:24 -0700 (PDT) X-ASG-Debug-ID: 1465928001-04bdf01e10369e0001-NocioJ Received: from g9t5009.houston.hpe.com (g9t5009.houston.hpe.com [15.241.48.73]) by cuda.sgi.com with ESMTP id KohJehRlqmcFrB3P (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:13:22 -0700 (PDT) X-Barracuda-Envelope-From: Waiman.Long@hpe.com X-Barracuda-Effective-Source-IP: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Apparent-Source-IP: 15.241.48.73 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g9t5009.houston.hpe.com (Postfix) with ESMTP id 7E8D159; Tue, 14 Jun 2016 18:13:21 +0000 (UTC) Received: from RHEL65.localdomain (unknown [16.214.227.42]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 1DEB64D; Tue, 14 Jun 2016 18:13:20 +0000 (UTC) From: Waiman Long To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch , Waiman Long Subject: [RFC PATCH-tip 2/6] locking/rwsem: Enable optional count-based spinning on reader Date: Tue, 14 Jun 2016 14:12:35 -0400 X-ASG-Orig-Subj: [RFC PATCH-tip 2/6] locking/rwsem: Enable optional count-based spinning on reader Message-Id: <1465927959-39719-3-git-send-email-Waiman.Long@hpe.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> X-Barracuda-Connect: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Start-Time: 1465928001 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5141 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30433 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header When the rwsem is owned by reader, writers stop optimistic spinning simply because there is no easy way to figure out if all the readers are actively running or not. However, there are scenarios where the readers are unlikely to sleep and optimistic spinning can help performance. This patch provides a way for the kernel code to designate specific rwsems to be more aggressive in term of optimistic spinning that the writers will continue to spin for some additional count-based time to see if it can get the lock before sleeping. This aggressive spinning mode should only be used on rwsems where the readers are unlikely to go to sleep. One can use the following function to designate rwsems that can be benefited from more aggressive spinning: void __rwsem_set_rspin_threshold_shift(struct rw_semaphore *sem, int shift) A shift value of 0 will use the default 4K (shift = 12) iteration count. Signed-off-by: Waiman Long --- include/linux/rwsem.h | 21 ++++++++++++++++++++- kernel/locking/rwsem-xadd.c | 28 +++++++++++++++++++--------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index dd1d142..1c5f6ff 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -32,6 +32,8 @@ struct rw_semaphore { raw_spinlock_t wait_lock; #ifdef CONFIG_RWSEM_SPIN_ON_OWNER struct optimistic_spin_queue osq; /* spinner MCS lock */ + int rspin_threshold_shift; /* reader spinning threshold shift */ + /* * Write owner. Used as a speculative check to see * if the owner is running on the cpu. @@ -70,9 +72,26 @@ static inline int rwsem_is_locked(struct rw_semaphore *sem) #endif #ifdef CONFIG_RWSEM_SPIN_ON_OWNER -#define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED, .owner = NULL +#define __RWSEM_OPT_INIT(lockname) , .osq = OSQ_LOCK_UNLOCKED, .owner = NULL, \ + .rspin_threshold_shift = 0 + +#define RWSEM_RSPIN_THRESHOLD_SHIFT_DEFAULT 12 +static inline void +__rwsem_set_rspin_threshold(struct rw_semaphore *sem, int shift) +{ + sem->rspin_threshold_shift = shift; +} + +static inline void rwsem_set_rspin_threshold(struct rw_semaphore *sem) +{ + __rwsem_set_rspin_threshold(sem, RWSEM_RSPIN_THRESHOLD_SHIFT_DEFAULT); +} #else #define __RWSEM_OPT_INIT(lockname) + +static inline void +__rwsem_set_rspin_threshold(struct rw_semaphore *sem, int shift) {} +static inline void rwsem_set_rspin_threshold(struct rw_semaphore *sem) {} #endif #define __RWSEM_INITIALIZER(name) \ diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 29027c6..9703f4a 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -85,6 +85,7 @@ void __init_rwsem(struct rw_semaphore *sem, const char *name, INIT_LIST_HEAD(&sem->wait_list); #ifdef CONFIG_RWSEM_SPIN_ON_OWNER sem->owner = NULL; + sem->rspin_threshold_shift = 0; osq_lock_init(&sem->osq); #endif } @@ -347,9 +348,11 @@ static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) owner = READ_ONCE(sem->owner); if (!rwsem_owner_is_writer(owner)) { /* - * Don't spin if the rwsem is readers owned. + * Don't spin if the rwsem is readers owned and the + * reader spinning threshold isn't set. */ - ret = !rwsem_owner_is_reader(owner); + ret = !rwsem_owner_is_reader(owner) || + sem->rspin_threshold_shift; goto done; } @@ -398,7 +401,8 @@ out: static bool rwsem_optimistic_spin(struct rw_semaphore *sem) { - bool taken = false; + bool taken = false, can_spin; + int loopcnt; preempt_disable(); @@ -409,6 +413,9 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem) if (!osq_lock(&sem->osq)) goto done; + loopcnt = sem->rspin_threshold_shift + ? (1 << sem->rspin_threshold_shift) : 0; + /* * Optimistically spin on the owner field and attempt to acquire the * lock whenever the owner changes. Spinning will be stopped when: @@ -416,7 +423,7 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem) * 2) readers own the lock as we can't determine if they are * actively running or not. */ - while (rwsem_spin_on_owner(sem)) { + while ((can_spin = rwsem_spin_on_owner(sem)) || loopcnt) { /* * Try to acquire the lock */ @@ -425,13 +432,16 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem) break; } + if (!can_spin && loopcnt) + loopcnt--; + /* - * When there's no owner, we might have preempted between the - * owner acquiring the lock and setting the owner field. If - * we're an RT task that will live-lock because we won't let - * the owner complete. + * The need_resched() check in rwsem_spin_on_owner() won't + * break the loop anymore. So we need to check this in + * the outer loop. If we're an RT task that will live-lock + * because we won't let the owner complete. */ - if (!sem->owner && (need_resched() || rt_task(current))) + if (need_resched() || rt_task(current)) break; /* -- 1.7.1 From Waiman.Long@hpe.com Tue Jun 14 13:13:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B4A3D7CAF for ; Tue, 14 Jun 2016 13:13:28 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8778730405F for ; Tue, 14 Jun 2016 11:13:25 -0700 (PDT) X-ASG-Debug-ID: 1465928003-04cbb03f54101a10001-NocioJ Received: from g9t5009.houston.hpe.com (g9t5009.houston.hpe.com [15.241.48.73]) by cuda.sgi.com with ESMTP id 6XOLNC9AhlP0TpFB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:13:23 -0700 (PDT) X-Barracuda-Envelope-From: Waiman.Long@hpe.com X-Barracuda-Effective-Source-IP: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Apparent-Source-IP: 15.241.48.73 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g9t5009.houston.hpe.com (Postfix) with ESMTP id 06A1A54; Tue, 14 Jun 2016 18:13:23 +0000 (UTC) Received: from RHEL65.localdomain (unknown [16.214.227.42]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 9C5524C; Tue, 14 Jun 2016 18:13:21 +0000 (UTC) From: Waiman Long To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch , Waiman Long Subject: [RFC PATCH-tip 3/6] locking/rwsem: move down rwsem_down_read_failed function Date: Tue, 14 Jun 2016 14:12:36 -0400 X-ASG-Orig-Subj: [RFC PATCH-tip 3/6] locking/rwsem: move down rwsem_down_read_failed function Message-Id: <1465927959-39719-4-git-send-email-Waiman.Long@hpe.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> X-Barracuda-Connect: g9t5009.houston.hpe.com[15.241.48.73] X-Barracuda-Start-Time: 1465928003 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4293 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30432 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Move the rwsem_down_read_failed() function down to below the optimistic spinning section before enabling optimistic spinning for the readers. There is no change in code. Signed-off-by: Waiman Long --- kernel/locking/rwsem-xadd.c | 116 +++++++++++++++++++++--------------------- 1 files changed, 58 insertions(+), 58 deletions(-) diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 9703f4a..400e594 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -226,64 +226,6 @@ __rwsem_mark_wake(struct rw_semaphore *sem, } /* - * Wait for the read lock to be granted - */ -__visible -struct rw_semaphore __sched *rwsem_down_read_failed(struct rw_semaphore *sem) -{ - long count, adjustment = 0; - struct rwsem_waiter waiter; - struct task_struct *tsk = current; - WAKE_Q(wake_q); - - /* - * Undo read bias from down_read operation, stop active locking. - * Doing that after taking the wait_lock may block writer lock - * stealing for too long. - */ - atomic_long_add(-RWSEM_ACTIVE_READ_BIAS, &sem->count); - - /* set up my own style of waitqueue */ - waiter.task = tsk; - waiter.type = RWSEM_WAITING_FOR_READ; - - raw_spin_lock_irq(&sem->wait_lock); - if (list_empty(&sem->wait_list)) - adjustment += RWSEM_WAITING_BIAS; - list_add_tail(&waiter.list, &sem->wait_list); - - /* we're now waiting on the lock */ - if (adjustment) - count = atomic_long_add_return(adjustment, &sem->count); - else - count = atomic_long_read(&sem->count); - - /* If there are no active locks, wake the front queued process(es). - * - * If there are no writers and we are first in the queue, - * wake our own waiter to join the existing active readers ! - */ - if (count == RWSEM_WAITING_BIAS || - (count > RWSEM_WAITING_BIAS && adjustment)) - sem = __rwsem_mark_wake(sem, RWSEM_WAKE_ANY, &wake_q); - - raw_spin_unlock_irq(&sem->wait_lock); - wake_up_q(&wake_q); - - /* wait to be given the lock */ - while (true) { - set_task_state(tsk, TASK_UNINTERRUPTIBLE); - if (!waiter.task) - break; - schedule(); - } - - __set_task_state(tsk, TASK_RUNNING); - return sem; -} -EXPORT_SYMBOL(rwsem_down_read_failed); - -/* * This function must be called with the sem->wait_lock held to prevent * race conditions between checking the rwsem wait list and setting the * sem->count accordingly. @@ -479,6 +421,64 @@ static inline bool rwsem_has_spinner(struct rw_semaphore *sem) #endif /* + * Wait for the read lock to be granted + */ +__visible +struct rw_semaphore __sched * rwsem_down_read_failed(struct rw_semaphore *sem) +{ + long count, adjustment = 0; + struct rwsem_waiter waiter; + struct task_struct *tsk = current; + WAKE_Q(wake_q); + + /* + * Undo read bias from down_read operation, stop active locking. + * Doing that after taking the wait_lock may block writer lock + * stealing for too long. + */ + atomic_long_add(-RWSEM_ACTIVE_READ_BIAS, &sem->count); + + /* set up my own style of waitqueue */ + waiter.task = tsk; + waiter.type = RWSEM_WAITING_FOR_READ; + + raw_spin_lock_irq(&sem->wait_lock); + if (list_empty(&sem->wait_list)) + adjustment += RWSEM_WAITING_BIAS; + list_add_tail(&waiter.list, &sem->wait_list); + + /* we're now waiting on the lock */ + if (adjustment) + count = atomic_long_add_return(adjustment, &sem->count); + else + count = atomic_long_read(&sem->count); + + /* If there are no active locks, wake the front queued process(es). + * + * If there are no writers and we are first in the queue, + * wake our own waiter to join the existing active readers ! + */ + if (count == RWSEM_WAITING_BIAS || + (count > RWSEM_WAITING_BIAS && adjustment)) + sem = __rwsem_mark_wake(sem, RWSEM_WAKE_ANY, &wake_q); + + raw_spin_unlock_irq(&sem->wait_lock); + wake_up_q(&wake_q); + + /* wait to be given the lock */ + while (true) { + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + if (!waiter.task) + break; + schedule(); + } + + __set_task_state(tsk, TASK_RUNNING); + return sem; +} +EXPORT_SYMBOL(rwsem_down_read_failed); + +/* * Wait until we successfully acquire the write lock */ static inline struct rw_semaphore * -- 1.7.1 From Waiman.Long@hpe.com Tue Jun 14 13:13:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 930927CAF for ; Tue, 14 Jun 2016 13:13:29 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5B6B78F8050 for ; Tue, 14 Jun 2016 11:13:29 -0700 (PDT) X-ASG-Debug-ID: 1465928006-04cbb03f55101a20001-NocioJ Received: from g9t5008.houston.hpe.com (g9t5008.houston.hpe.com [15.241.48.72]) by cuda.sgi.com with ESMTP id kx8HiZLNfsV4EOpx (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:13:26 -0700 (PDT) X-Barracuda-Envelope-From: Waiman.Long@hpe.com X-Barracuda-Effective-Source-IP: g9t5008.houston.hpe.com[15.241.48.72] X-Barracuda-Apparent-Source-IP: 15.241.48.72 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g9t5008.houston.hpe.com (Postfix) with ESMTP id A31FA59; Tue, 14 Jun 2016 18:13:24 +0000 (UTC) Received: from RHEL65.localdomain (unknown [16.214.227.42]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 2C5A14F; Tue, 14 Jun 2016 18:13:23 +0000 (UTC) From: Waiman Long To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch , Waiman Long Subject: [RFC PATCH-tip 4/6] locking/rwsem: Change RWSEM_WAITING_BIAS for better disambiguation Date: Tue, 14 Jun 2016 14:12:37 -0400 X-ASG-Orig-Subj: [RFC PATCH-tip 4/6] locking/rwsem: Change RWSEM_WAITING_BIAS for better disambiguation Message-Id: <1465927959-39719-5-git-send-email-Waiman.Long@hpe.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> X-Barracuda-Connect: g9t5008.houston.hpe.com[15.241.48.72] X-Barracuda-Start-Time: 1465928006 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10095 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30432 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header When the count value is in between 0 and RWSEM_WAITING_BIAS, there are 2 possibilities. Either a writer is present and there is no waiter or there are waiters and readers. There is no easy way to know which is true unless the wait_lock is taken. This patch changes the RWSEM_WAITING_BIAS from 0xffff (32-bit) or 0xffffffff (64-bit) to 0xc0000000 (32-bit) or 0xc000000000000000 (64-bit). By doing so, we will be able to determine if writers are present by looking at the count value alone without taking the wait_lock. This patch has the effect of halving the maximum number of writers that can attempt to take the write lock simultaneously. However, even the reduced maximum of about 16k (32-bit) or 1G (64-bit) should be more than enough for the foreseeable future. With that change, the following identity is now no longer true: RWSEM_ACTIVE_WRITE_BIAS = RWSEM_WAITING_BIAS + RWSEM_ACTIVE_READ_BIAS Signed-off-by: Waiman Long --- arch/alpha/include/asm/rwsem.h | 7 ++++--- arch/ia64/include/asm/rwsem.h | 6 +++--- arch/s390/include/asm/rwsem.h | 6 +++--- arch/x86/include/asm/rwsem.h | 13 ++++++++----- include/asm-generic/rwsem.h | 9 +++++---- kernel/locking/rwsem-xadd.c | 32 ++++++++++++++++++++++++-------- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/arch/alpha/include/asm/rwsem.h b/arch/alpha/include/asm/rwsem.h index 77873d0..0f08fad 100644 --- a/arch/alpha/include/asm/rwsem.h +++ b/arch/alpha/include/asm/rwsem.h @@ -17,9 +17,9 @@ #define RWSEM_UNLOCKED_VALUE 0x0000000000000000L #define RWSEM_ACTIVE_BIAS 0x0000000000000001L #define RWSEM_ACTIVE_MASK 0x00000000ffffffffL -#define RWSEM_WAITING_BIAS (-0x0000000100000000L) +#define RWSEM_WAITING_BIAS 0xc000000000000000L #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) +#define RWSEM_ACTIVE_WRITE_BIAS (-RWSEM_ACTIVE_MASK) static inline void __down_read(struct rw_semaphore *sem) { @@ -185,7 +185,8 @@ static inline void __downgrade_write(struct rw_semaphore *sem) "2: br 1b\n" ".previous" :"=&r" (oldcount), "=m" (sem->count), "=&r" (temp) - :"Ir" (-RWSEM_WAITING_BIAS), "m" (sem->count) : "memory"); + :"Ir" (-RWSEM_ACTIVE_WRITE_BIAS + RWSEM_ACTIVE_READ_BIAS), + "m" (sem->count) : "memory"); #endif if (unlikely(oldcount < 0)) rwsem_downgrade_wake(sem); diff --git a/arch/ia64/include/asm/rwsem.h b/arch/ia64/include/asm/rwsem.h index 8fa98dd..db3693b 100644 --- a/arch/ia64/include/asm/rwsem.h +++ b/arch/ia64/include/asm/rwsem.h @@ -30,9 +30,9 @@ #define RWSEM_UNLOCKED_VALUE __IA64_UL_CONST(0x0000000000000000) #define RWSEM_ACTIVE_BIAS (1L) #define RWSEM_ACTIVE_MASK (0xffffffffL) -#define RWSEM_WAITING_BIAS (-0x100000000L) +#define RWSEM_WAITING_BIAS (-(1L << 62)) #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) +#define RWSEM_ACTIVE_WRITE_BIAS (-RWSEM_ACTIVE_MASK) /* * lock for reading @@ -144,7 +144,7 @@ __downgrade_write (struct rw_semaphore *sem) do { old = atomic_long_read(&sem->count); - new = old - RWSEM_WAITING_BIAS; + new = old - RWSEM_ACTIVE_WRITE_BIAS + RWSEM_ACTIVE_READ_BIAS; } while (atomic_long_cmpxchg_release(&sem->count, old, new) != old); if (old < 0) diff --git a/arch/s390/include/asm/rwsem.h b/arch/s390/include/asm/rwsem.h index 597e7e9..e7f50f5 100644 --- a/arch/s390/include/asm/rwsem.h +++ b/arch/s390/include/asm/rwsem.h @@ -42,9 +42,9 @@ #define RWSEM_UNLOCKED_VALUE 0x0000000000000000L #define RWSEM_ACTIVE_BIAS 0x0000000000000001L #define RWSEM_ACTIVE_MASK 0x00000000ffffffffL -#define RWSEM_WAITING_BIAS (-0x0000000100000000L) +#define RWSEM_WAITING_BIAS 0xc000000000000000L #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) +#define RWSEM_ACTIVE_WRITE_BIAS (-RWSEM_ACTIVE_MASK) /* * lock for reading @@ -193,7 +193,7 @@ static inline void __downgrade_write(struct rw_semaphore *sem) { signed long old, new, tmp; - tmp = -RWSEM_WAITING_BIAS; + tmp = -RWSEM_ACTIVE_WRITE_BIAS + RWSEM_ACTIVE_READ_BIAS; asm volatile( " lg %0,%2\n" "0: lgr %1,%0\n" diff --git a/arch/x86/include/asm/rwsem.h b/arch/x86/include/asm/rwsem.h index 089ced4..f1fb09f 100644 --- a/arch/x86/include/asm/rwsem.h +++ b/arch/x86/include/asm/rwsem.h @@ -41,21 +41,23 @@ /* * The bias values and the counter type limits the number of - * potential readers/writers to 32767 for 32 bits and 2147483647 - * for 64 bits. + * potential writers to 16383 for 32 bits and 1073741823 for 64 bits. + * The combined readers and writers can go up to 65534 for 32-bits and + * 4294967294 for 64-bits. */ #ifdef CONFIG_X86_64 # define RWSEM_ACTIVE_MASK 0xffffffffL +# define RWSEM_WAITING_BIAS (-(1L << 62)) #else # define RWSEM_ACTIVE_MASK 0x0000ffffL +# define RWSEM_WAITING_BIAS (-(1L << 30)) #endif #define RWSEM_UNLOCKED_VALUE 0x00000000L #define RWSEM_ACTIVE_BIAS 0x00000001L -#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1) #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) +#define RWSEM_ACTIVE_WRITE_BIAS (-RWSEM_ACTIVE_MASK) /* * lock for reading @@ -209,7 +211,8 @@ static inline void __downgrade_write(struct rw_semaphore *sem) "1:\n\t" "# ending __downgrade_write\n" : "+m" (sem->count) - : "a" (sem), "er" (-RWSEM_WAITING_BIAS) + : "a" (sem), "er" (-RWSEM_ACTIVE_WRITE_BIAS + + RWSEM_ACTIVE_READ_BIAS) : "memory", "cc"); } diff --git a/include/asm-generic/rwsem.h b/include/asm-generic/rwsem.h index 5be122e..655e405 100644 --- a/include/asm-generic/rwsem.h +++ b/include/asm-generic/rwsem.h @@ -18,15 +18,16 @@ */ #ifdef CONFIG_64BIT # define RWSEM_ACTIVE_MASK 0xffffffffL +# define RWSEM_WAITING_BIAS (-(1L << 62)) #else # define RWSEM_ACTIVE_MASK 0x0000ffffL +# define RWSEM_WAITING_BIAS (-(1L << 30)) #endif #define RWSEM_UNLOCKED_VALUE 0x00000000L #define RWSEM_ACTIVE_BIAS 0x00000001L -#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1) #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS -#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) +#define RWSEM_ACTIVE_WRITE_BIAS (-RWSEM_ACTIVE_MASK) /* * lock for reading @@ -120,8 +121,8 @@ static inline void __downgrade_write(struct rw_semaphore *sem) * read-locked region is ok to be re-ordered into the * write side. As such, rely on RELEASE semantics. */ - tmp = atomic_long_add_return_release(-RWSEM_WAITING_BIAS, - (atomic_long_t *)&sem->count); + tmp = atomic_long_add_return_release(-RWSEM_ACTIVE_WRITE_BIAS + + RWSEM_ACTIVE_READ_BIAS, (atomic_long_t *)&sem->count); if (tmp < 0) rwsem_downgrade_wake(sem); } diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 400e594..689a138 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -29,28 +29,30 @@ * 0x00000000 rwsem is unlocked, and no one is waiting for the lock or * attempting to read lock or write lock. * - * 0xffff000X (1) X readers active or attempting lock, with waiters for lock + * 0xc000000X (1) X readers active or attempting lock, with waiters for lock * X = #active readers + # readers attempting lock * (X*ACTIVE_BIAS + WAITING_BIAS) - * (2) 1 writer attempting lock, no waiters for lock + * + * 0xffff000X (1) 1 writer attempting lock, no waiters for lock * X-1 = #active readers + #readers attempting lock * ((X-1)*ACTIVE_BIAS + ACTIVE_WRITE_BIAS) - * (3) 1 writer active, no waiters for lock + * (2) 1 writer active, no waiters for lock * X-1 = #active readers + #readers attempting lock * ((X-1)*ACTIVE_BIAS + ACTIVE_WRITE_BIAS) * - * 0xffff0001 (1) 1 reader active or attempting lock, waiters for lock + * 0xc0000001 (1) 1 reader active or attempting lock, waiters for lock * (WAITING_BIAS + ACTIVE_BIAS) - * (2) 1 writer active or attempting lock, no waiters for lock + * + * 0xffff0001 (1) 1 writer active or attempting lock, no waiters for lock * (ACTIVE_WRITE_BIAS) * - * 0xffff0000 (1) There are writers or readers queued but none active + * 0xc0000000 (1) There are writers or readers queued but none active * or in the process of attempting lock. * (WAITING_BIAS) * Note: writer can attempt to steal lock for this count by adding * ACTIVE_WRITE_BIAS in cmpxchg and checking the old count * - * 0xfffe0001 (1) 1 writer active, or attempting lock. Waiters on queue. + * 0xbfff0001 (1) 1 writer active, or attempting lock. Waiters on queue. * (ACTIVE_WRITE_BIAS + WAITING_BIAS) * * Note: Readers attempt to lock by adding ACTIVE_BIAS in down_read and checking @@ -62,9 +64,23 @@ * checking the count becomes ACTIVE_WRITE_BIAS for successful lock * acquisition (i.e. nobody else has lock or attempts lock). If * unsuccessful, in rwsem_down_write_failed, we'll check to see if there - * are only waiters but none active (5th case above), and attempt to + * are only waiters but none active (7th case above), and attempt to * steal the lock. * + * We can infer the reader/writer/waiter state of the lock by looking + * at the count value: + * (1) count > 0 + * Only readers are present. + * (2) WAITING_BIAS - ACTIVE_WRITE_BIAS < count < 0 + * Have writers, maybe readers, but no waiter + * (3) WAITING_BIAS < count <= WAITING_BIAS - ACTIVE_WRITE_BIAS + * Have readers and waiters, but no writer + * (4) count < WAITING_BIAS + * Have writers and waiters, maybe readers + * + * IOW, writers are present when + * (1) count < WAITING_BIAS, or + * (2) WAITING_BIAS - ACTIVE_WRITE_BIAS < count < 0 */ /* -- 1.7.1 From Waiman.Long@hpe.com Tue Jun 14 13:13:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 069A27CBE for ; Tue, 14 Jun 2016 13:13:33 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id BE46830405F for ; Tue, 14 Jun 2016 11:13:32 -0700 (PDT) X-ASG-Debug-ID: 1465928010-04cbb03f55101a30001-NocioJ Received: from g4t3425.houston.hpe.com (g4t3425.houston.hpe.com [15.241.140.78]) by cuda.sgi.com with ESMTP id Jc9VWdbRTBl7iAQr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:13:30 -0700 (PDT) X-Barracuda-Envelope-From: Waiman.Long@hpe.com X-Barracuda-Effective-Source-IP: g4t3425.houston.hpe.com[15.241.140.78] X-Barracuda-Apparent-Source-IP: 15.241.140.78 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g4t3425.houston.hpe.com (Postfix) with ESMTP id 54A1250; Tue, 14 Jun 2016 18:13:30 +0000 (UTC) Received: from RHEL65.localdomain (unknown [16.214.227.42]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id 9D66C4B; Tue, 14 Jun 2016 18:13:28 +0000 (UTC) From: Waiman Long To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch , Waiman Long Subject: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes Date: Tue, 14 Jun 2016 14:12:39 -0400 X-ASG-Orig-Subj: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes Message-Id: <1465927959-39719-7-git-send-email-Waiman.Long@hpe.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> X-Barracuda-Connect: g4t3425.houston.hpe.com[15.241.140.78] X-Barracuda-Start-Time: 1465928010 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1366 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30432 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header This patch enables reader optimistic spinning for inodes that are under a DAX-based mount point. On a 4-socket Haswell machine running on a 4.7-rc1 tip-based kernel, the fio test with multithreaded randrw and randwrite tests on the same file on a XFS partition on top of a NVDIMM with DAX were run, the aggregated bandwidths before and after the patch were as follows: Test BW before patch BW after patch % change ---- --------------- -------------- -------- randrw 1352 MB/s 2164 MB/s +60% randwrite 1710 MB/s 2550 MB/s +49% Signed-off-by: Waiman Long --- fs/xfs/xfs_icache.c | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 99ee6ee..09f284f 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -71,6 +71,15 @@ xfs_inode_alloc( mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); + /* + * Enable reader spinning for DAX nount point + */ + if (mp->m_flags & XFS_MOUNT_DAX) { + rwsem_set_rspin_threshold(&ip->i_iolock.mr_lock); + rwsem_set_rspin_threshold(&ip->i_mmaplock.mr_lock); + rwsem_set_rspin_threshold(&ip->i_lock.mr_lock); + } + /* initialise the xfs inode */ ip->i_ino = ino; ip->i_mount = mp; -- 1.7.1 From Waiman.Long@hpe.com Tue Jun 14 13:13:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 097FA7CC5 for ; Tue, 14 Jun 2016 13:13:33 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 78FF2AC004 for ; Tue, 14 Jun 2016 11:13:32 -0700 (PDT) X-ASG-Debug-ID: 1465928008-04cb6c3813a7290001-NocioJ Received: from g4t3425.houston.hpe.com (g4t3425.houston.hpe.com [15.241.140.78]) by cuda.sgi.com with ESMTP id 1uFZovizJ6Zc4pXu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:13:29 -0700 (PDT) X-Barracuda-Envelope-From: Waiman.Long@hpe.com X-Barracuda-Effective-Source-IP: g4t3425.houston.hpe.com[15.241.140.78] X-Barracuda-Apparent-Source-IP: 15.241.140.78 Received: from g9t2301.houston.hpecorp.net (g9t2301.houston.hpecorp.net [16.220.97.129]) by g4t3425.houston.hpe.com (Postfix) with ESMTP id 816DF4B; Tue, 14 Jun 2016 18:13:28 +0000 (UTC) Received: from RHEL65.localdomain (unknown [16.214.227.42]) by g9t2301.houston.hpecorp.net (Postfix) with ESMTP id D1A534C; Tue, 14 Jun 2016 18:13:24 +0000 (UTC) From: Waiman Long To: Peter Zijlstra , Ingo Molnar Cc: linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch , Waiman Long Subject: [RFC PATCH-tip 5/6] locking/rwsem: Enable spinning readers Date: Tue, 14 Jun 2016 14:12:38 -0400 X-ASG-Orig-Subj: [RFC PATCH-tip 5/6] locking/rwsem: Enable spinning readers Message-Id: <1465927959-39719-6-git-send-email-Waiman.Long@hpe.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> X-Barracuda-Connect: g4t3425.houston.hpe.com[15.241.140.78] X-Barracuda-Start-Time: 1465928009 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3493 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30432 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header This patch enables readers to optimistically spin when the rspin_threshold is non-zero. That threshold value should only be set when the lock owners of the rwsem are unlikely to go to sleep. Otherwise enabling reader spinning may make the performance worse in some cases. Signed-off-by: Waiman Long --- kernel/locking/rwsem-xadd.c | 45 +++++++++++++++++++++++++++++++++++++----- 1 files changed, 39 insertions(+), 6 deletions(-) diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c index 689a138..be2a327 100644 --- a/kernel/locking/rwsem-xadd.c +++ b/kernel/locking/rwsem-xadd.c @@ -83,6 +83,12 @@ * (2) WAITING_BIAS - ACTIVE_WRITE_BIAS < count < 0 */ +static inline bool count_has_writer(long count) +{ + return (count < RWSEM_WAITING_BIAS) || ((count < 0) && + (count > RWSEM_WAITING_BIAS - RWSEM_ACTIVE_WRITE_BIAS)); +} + /* * Initialize an rwsem: */ @@ -294,6 +300,25 @@ static inline bool rwsem_try_write_lock_unqueued(struct rw_semaphore *sem) } } +/* + * Try to acquire read lock before the reader is put on wait queue + */ +static inline bool rwsem_try_read_lock_unqueued(struct rw_semaphore *sem) +{ + long count = atomic_long_read(&sem->count); + + if (count_has_writer(count)) + return false; + count = atomic_long_add_return_acquire(RWSEM_ACTIVE_READ_BIAS, + &sem->count); + if (!count_has_writer(count)) + return true; + + /* Back out the change */ + atomic_long_add(-RWSEM_ACTIVE_READ_BIAS, &sem->count); + return false; +} + static inline bool rwsem_can_spin_on_owner(struct rw_semaphore *sem) { struct task_struct *owner; @@ -357,7 +382,8 @@ out: return !rwsem_owner_is_reader(READ_ONCE(sem->owner)); } -static bool rwsem_optimistic_spin(struct rw_semaphore *sem) +static bool rwsem_optimistic_spin(struct rw_semaphore *sem, + enum rwsem_waiter_type type) { bool taken = false, can_spin; int loopcnt; @@ -385,10 +411,11 @@ static bool rwsem_optimistic_spin(struct rw_semaphore *sem) /* * Try to acquire the lock */ - if (rwsem_try_write_lock_unqueued(sem)) { - taken = true; + taken = (type == RWSEM_WAITING_FOR_WRITE) + ? rwsem_try_write_lock_unqueued(sem) + : rwsem_try_read_lock_unqueued(sem); + if (taken) break; - } if (!can_spin && loopcnt) loopcnt--; @@ -425,7 +452,8 @@ static inline bool rwsem_has_spinner(struct rw_semaphore *sem) } #else -static bool rwsem_optimistic_spin(struct rw_semaphore *sem) +static bool rwsem_optimistic_spin(struct rw_semaphore *sem, + enum rwsem_waiter_type type) { return false; } @@ -454,6 +482,11 @@ struct rw_semaphore __sched * rwsem_down_read_failed(struct rw_semaphore *sem) */ atomic_long_add(-RWSEM_ACTIVE_READ_BIAS, &sem->count); + /* do optimistic spinning and steal lock if possible */ + if (sem->rspin_threshold_shift && + rwsem_optimistic_spin(sem, RWSEM_WAITING_FOR_READ)) + return sem; + /* set up my own style of waitqueue */ waiter.task = tsk; waiter.type = RWSEM_WAITING_FOR_READ; @@ -510,7 +543,7 @@ __rwsem_down_write_failed_common(struct rw_semaphore *sem, int state) count = atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS, &sem->count); /* do optimistic spinning and steal lock if possible */ - if (rwsem_optimistic_spin(sem)) + if (rwsem_optimistic_spin(sem, RWSEM_WAITING_FOR_WRITE)) return sem; /* -- 1.7.1 From BATV+1815987b1c14acf14571+4678+infradead.org+hch@bombadil.srs.infradead.org Tue Jun 14 13:24:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 4E5687CA0 for ; Tue, 14 Jun 2016 13:24:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0E06C8F8035 for ; Tue, 14 Jun 2016 11:24:30 -0700 (PDT) X-ASG-Debug-ID: 1465928668-04cb6c3816a7790001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id YtFxgUms7mKweRDp (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 14 Jun 2016 11:24:29 -0700 (PDT) X-Barracuda-Envelope-From: BATV+1815987b1c14acf14571+4678+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bCt0h-0002Ce-RD; Tue, 14 Jun 2016 18:24:23 +0000 Date: Tue, 14 Jun 2016 11:24:23 -0700 From: Christoph Hellwig To: Waiman Long Cc: Peter Zijlstra , Ingo Molnar , linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch Subject: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes Message-ID: <20160614182423.GA6330@infradead.org> X-ASG-Orig-Subj: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> <1465927959-39719-7-git-send-email-Waiman.Long@hpe.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1465927959-39719-7-git-send-email-Waiman.Long@hpe.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1465928668 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 622 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30433 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Tue, Jun 14, 2016 at 02:12:39PM -0400, Waiman Long wrote: > This patch enables reader optimistic spinning for inodes that are > under a DAX-based mount point. > > On a 4-socket Haswell machine running on a 4.7-rc1 tip-based kernel, > the fio test with multithreaded randrw and randwrite tests on the > same file on a XFS partition on top of a NVDIMM with DAX were run, > the aggregated bandwidths before and after the patch were as follows: And why is this specific to DAX? Many I/O operations already never got out to disk, and ilock is mostly held for operations that have nothing to do with disk I/O. From dave@stgolabs.net Tue Jun 14 13:28:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2A2DF7CA1 for ; Tue, 14 Jun 2016 13:28:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id DCB988F8035 for ; Tue, 14 Jun 2016 11:28:12 -0700 (PDT) X-ASG-Debug-ID: 1465928889-04bdf01e15371e0001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id DgmcX5jD76eN0XbC (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Tue, 14 Jun 2016 11:28:10 -0700 (PDT) X-Barracuda-Envelope-From: dave@stgolabs.net X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 70D6AADAE; Tue, 14 Jun 2016 18:28:08 +0000 (UTC) Date: Tue, 14 Jun 2016 11:27:57 -0700 From: Davidlohr Bueso To: Waiman Long Cc: Peter Zijlstra , Ingo Molnar , linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch Subject: Re: [RFC PATCH-tip 2/6] locking/rwsem: Enable optional count-based spinning on reader Message-ID: <20160614182757.GA15903@linux-80c1.suse> X-ASG-Orig-Subj: Re: [RFC PATCH-tip 2/6] locking/rwsem: Enable optional count-based spinning on reader References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> <1465927959-39719-3-git-send-email-Waiman.Long@hpe.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline In-Reply-To: <1465927959-39719-3-git-send-email-Waiman.Long@hpe.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1465928890 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 651 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30433 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, 14 Jun 2016, Waiman Long wrote: >This patch provides a way for the kernel code to designate specific >rwsems to be more aggressive in term of optimistic spinning that the >writers will continue to spin for some additional count-based time to >see if it can get the lock before sleeping. This aggressive spinning >mode should only be used on rwsems where the readers are unlikely to >go to sleep. Yikes, exposing this sort of thing makes me _very_ uneasy, not to mention the ad-hoc nature and its easiness to mess up. I'm not really for this, even if it shows extraordinary performance boosts on benchmarks. Thanks, Davidlohr From waiman.long@hpe.com Tue Jun 14 14:09:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0D3C57CA0 for ; Tue, 14 Jun 2016 14:09:15 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id AF9268F8049 for ; Tue, 14 Jun 2016 12:09:11 -0700 (PDT) X-ASG-Debug-ID: 1465931348-04bdf01e1338350001-NocioJ Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1on0146.outbound.protection.outlook.com [157.56.110.146]) by cuda.sgi.com with ESMTP id D2sfCJKEh1WTZ17c (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 12:09:09 -0700 (PDT) X-Barracuda-Envelope-From: waiman.long@hpe.com X-Barracuda-Effective-Source-IP: mail-bn1on0146.outbound.protection.outlook.com[157.56.110.146] X-Barracuda-Apparent-Source-IP: 157.56.110.146 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=waiman.long@hpe.com; Received: from [192.168.142.153] (72.71.243.198) by DF4PR84MB0313.NAMPRD84.PROD.OUTLOOK.COM (10.162.193.27) with Microsoft SMTP Server (TLS) id 15.1.511.8; Tue, 14 Jun 2016 19:09:06 +0000 Message-ID: <57605648.6060705@hpe.com> Date: Tue, 14 Jun 2016 15:08:56 -0400 From: Waiman Long User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Thunderbird/10.0.12 MIME-Version: 1.0 To: Christoph Hellwig CC: Peter Zijlstra , Ingo Molnar , , , , , , , , Davidlohr Bueso , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch Subject: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> <1465927959-39719-7-git-send-email-Waiman.Long@hpe.com> <20160614182423.GA6330@infradead.org> X-ASG-Orig-Subj: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes In-Reply-To: <20160614182423.GA6330@infradead.org> Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [72.71.243.198] X-ClientProxiedBy: SN1PR15CA0021.namprd15.prod.outlook.com (10.163.200.31) To DF4PR84MB0313.NAMPRD84.PROD.OUTLOOK.COM (10.162.193.27) X-MS-Office365-Filtering-Correlation-Id: 2c3f758f-6597-4781-b9a4-08d394875bf6 X-Microsoft-Exchange-Diagnostics: 1;DF4PR84MB0313;2:K2REQA9eis6w+GduPZbs6AUOHkv/sUCro2wZ4khcNgVMa8Y6qw0LkIwch7dVeVvKiLti9UvbyJdSiV2KR2ehFZp7H5jG5kVsnw23sEFcD+B3scZtJhHBqmNWu7RpFKLdGmbae8ktuuFxFpaIqJZOktKmPdlzDi4OpRrKkU0vcpdWBY0FkH3naryhymPRM3JO;3:xXOVdIoqAd1l7y3YWGqFIfP0lhG3+XpP/1ei/wc6KCusALg25iWN/h0E+u/ZFyP9JueW5VcY7IVmzzHwZmQOwYHZv7O/Mioylnx6ZpXC33UemQHORXdC1Rs64kKY1kJD;25:AWPx5S2UvFFVTau0ullBxHuV8EjsrWbgxWF7DTEt5EfBSn3hDQ8oPXizCzlMXm5quqjFKfcAf3upQC8hpqA1AWYA87/Pyd7yJsp7cyU2RvzrmpGZoDJVhDvHPcFoE+PppuErbrvpnhkTZZRU8EPxMnJi9nqoetX3s0LlFg5iW8opybH/QSFm7iFcY6AbKt2smqy+TwDtl3KMGC/XVtJq61qedSGUwNZe63Z7e/uhQW9zYgtuK+lotYKnDPOU5PXKqKfmRN0v0nPI4kHfIkk++DMjmEx4tOvnJNXXJ5yNoF6KeIOF8kaWI7hZOrIszkDE+8L8dL0FvI/HGVY7G0fuP3/71hWTTbvjC6lTnH1E47UwBEfro8OTtvtcKsVcslzCNZdbCAZsRUQ3LTbiPIIMgHeRP4I9wIdij9fLn9Ckc8o= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DF4PR84MB0313; X-Microsoft-Exchange-Diagnostics: 1;DF4PR84MB0313;20:n84O0zh0O5uVMoqMWe5NYlI7DvRMOEWrgyQR+Taqgn9EVoc7wq9SyPU1jtPAh3vNKH5PLibY2Ee8mshP9U94XUWkQzUz2zMLvFzwcyXZ/7H7WPOFbAYRbvq8yg0RRAMlL5BLIn66gG7pEB/dHWfTjECaNhhvZgNtPb0O9p8fbHEJovWcCKVHdUdZwq9DdkVUhhCOfvMBXfgNskra2O8YK0jL800qB9oKpbQDT8rMHCqQ/SThIHZrEi1mW4cjEIe6YpAfeYH/R7a7aopmHl0Y5GAVK8TmwQ0oY+EwQZGzrmpBkvshT+SIiObRBkzdJpjI52IVileUQ015w1W4dU8I/ASwG/Ul+EsgTLVmW98erh8J2Zmfgxyt1ZXFy64pTiXZ28lbhr+P7xSBfwrIbu8kEEJs/yP0GgiCDQpTqOMLkV47AzQu4ElhCdY5OnF9VILRsBGoko0w5vodNxsNsgzA5y3d8jwZ3CGAYz8yqyTnPEU0bYpFIW0ojlH9rTKm2AH5;4:cYvGzdfCzFOFoS47odZvNkSgY8QAZ2jBCKaWrExecmnTOmbwF0kDiMxnifjh19P4S/Rr3P/SMqDnKsW4z7+wu20OK8BxwV3eYlQDeo2JH0rbEpH6Rts/HbJlYUo5X59nWrI9rIrnwudcieE7fxW4TmFTPzETuV4gCyjRMSuIn6DzqQkNRHgjVBEKAcb+V+IVGxIsJB6O0rsmKDiwjKU3VD1MR4mItA6Nsd37NlE4Q8PuQMnVcXzpnwXABVGnEHzBjDmwp96XRYWUcSH22NQE5wKSgSUEQyxf36aYeGF/FYqFWUuB6iPd2ufemRbrmiIb7J02wSqhFp3FXzdFBxB1B1pEXyxvYA6/itc6Owh82a2uxsAeXbe4zCSxjEOJ8oCZ X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001);SRVR:DF4PR84MB0313;BCL:0;PCL:0;RULEID:;SRVR:DF4PR84MB0313; X-Forefront-PRVS: 09730BD177 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(6049001)(7916002)(199003)(24454002)(189002)(377454003)(5008740100001)(64126003)(83506001)(5004730100002)(189998001)(42186005)(2906002)(23756003)(4326007)(110136002)(2950100001)(86362001)(92566002)(66066001)(65806001)(65956001)(99136001)(105586002)(117636001)(106356001)(36756003)(54356999)(8676002)(81166006)(81156014)(101416001)(87266999)(76176999)(50986999)(65816999)(47776003)(68736007)(117156001)(4001350100001)(50466002)(122286003)(77096005)(8666004)(59896002)(6116002)(3846002)(97736004)(230700001)(586003)(7059030)(62816006);DIR:OUT;SFP:1102;SCL:1;SRVR:DF4PR84MB0313;H:[192.168.142.153];FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; Received-SPF: None (protection.outlook.com: hpe.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?iso-8859-1?Q?1;DF4PR84MB0313;23:cULFODliudbGqYSkAyapikZWe7vei5Cq7wlqdBr?= =?iso-8859-1?Q?PpcCxiP0wyiiro1POZyA3oBifgV/ZLokn8n74lBJSX/bsSS8zZK9zHmfIw?= =?iso-8859-1?Q?dFY3rhoIbOcKynJC6ukGh7bvU8kJToSVJu0MAKeLjjiWzYRtIsyRSLa5j5?= =?iso-8859-1?Q?SCmz7kcTA54js7VpfXdBPeUuRNyZaXqRk9g5iKRPfCFBjaCsybtTVJAYj6?= =?iso-8859-1?Q?6CkNkm6PPGiZsBg5gy4XmTe+9K+dG8aVzXqa6PRmL/aPxboszR2WRK+UUe?= =?iso-8859-1?Q?TzWsWMscltx0Wsy7bbAz0rVvmUO8JriQgIjpLmwMEH0kQjhqbGoy6nfT83?= =?iso-8859-1?Q?AiLpbOdkMxh4e/AluXvn0tlakuRFQyD/z/TOo3a6Wq6F+VienX347YuaMK?= =?iso-8859-1?Q?/Swk9jsp1W007D2F2bgGa1Y+w97CoHpCUbi5eK13C5Xk1dasTtjlggHTHV?= =?iso-8859-1?Q?eNuytZs7yG0Eqzxm04YlQgCXfGE6Xfym93QVuvqmUGxvC82TMutGftupYE?= =?iso-8859-1?Q?MK2O1Xr4iFzRIorfx9wATzA2kGunQrErAgut0o35bOEgP3/48of+GS2YU5?= =?iso-8859-1?Q?Z2Ol0dinBo9FUXhgrOQQz2hWXHMcStrS0TR2vfLssQhaJMpsKFtzDbhvv0?= =?iso-8859-1?Q?5KkyF2MM0Gi9uHzRTj6wzMMxsvCZukeYcxyTkISiy3xetuaUXHb8iM0OrA?= =?iso-8859-1?Q?WdsxJVqbVRGLx5osbBpbPiLOAY7JUwPor490UceGS7x57RIhLlW1ZVIorF?= =?iso-8859-1?Q?3KhkYy0S31p+RocfxdwtPTtSRb8TujzEKe/uj9xKX1Br15Ld5cwo/bao/s?= =?iso-8859-1?Q?LmK/u4plBtHtZawTOh1V0KLhVpv+XfTKxpQb4mlgDLZ0SUSo4TwXXjUejI?= =?iso-8859-1?Q?R/BmIHvsyDa3Wi44nfu+IyWukEb28DQTM/n4b/nB+O+y4wnICf1IisOiuk?= =?iso-8859-1?Q?Dp4GmQdSXN9IrGZaaZZLFq50GyPcMesmnXxG5jR6MVDfa48MXS/wV93eaC?= =?iso-8859-1?Q?vj6MUu2C4QQahQr+1Qa9bPrl3YXb0lU0CNi4Ru5Lth7/jIrXXRBF20eBpS?= =?iso-8859-1?Q?1YI/ZPxVjQydkbs0Q3nnif+Cubl8vFRdGQ9u7Ecif6nnQHk+lZH/JnpdV/?= =?iso-8859-1?Q?IRmGJ8FTxymLbhil83V4qDhsWd/c3LrbdtLgsaPuLUhxCX3gaIGn1YeCeT?= =?iso-8859-1?Q?0zJ3qCclQX1FQej3ZSjozl7upKvGytHqg0KGxe3IKTKw8Zwo3UMWb9Ga4P?= =?iso-8859-1?Q?e+UR4Vcei1GBUPyfzUhFGWDcq7DpuPyzlRBcJG34yGkreJ6UZcLLxHXYnk?= =?iso-8859-1?Q?V3LnTTtXFe47Xsm6N7ylhrSAxLdydaUK3T5rcAYvYiVeq1iYo/RL9wyR4e?= =?iso-8859-1?Q?1N+LwK1pYlkLArxAefpk/rI/kpxuc?= X-Microsoft-Exchange-Diagnostics: 1;DF4PR84MB0313;5:4xsdWoM3GS7hq8VWgIawENsfME1FefW9ih55ss0FBO75wpJdyfvexdQ8aQKgKHNic8SeuEjC0lyqfvTIMEQLgajAP1mq8pTr4kzKKRTGD88AizMC9EXDiqJ5GA7ePn6R+DRankrcx+mQGjwJPmxvOg==;24:rkZhk9MvkSdgH4fKtuMadQxkIbD8XzVe9HO+I7ryPefPTz0rnBGNJIm3arRWdr+v4dxWAtQFjX+LQ30wKK0E9hK/TPEjI41oe08l0Ugf1+Q=;7:K8uL4AM4uAjLIbwiZ8ZEwiL5rhQt8TULF/DwMyGavSJYBGrlATOTYbEeJLowCTSUjsmHT0xo3305+GmhSBl1ZN3ww8sBUeZ9L0yW08DLpwbXtJiqWl11+cSUdO26UgipIzwkjfAaj2tQyMFUHHyE1QElR5kvfUS7ar8ZPtroMal9rowps/dl3THY7naviX26M/oXck7aYKBNeiuA1XUijAuJyN4yuBpw3kUa+6vXfuc= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: hpe.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 14 Jun 2016 19:09:06.0637 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DF4PR84MB0313 X-Barracuda-Connect: mail-bn1on0146.outbound.protection.outlook.com[157.56.110.146] X-Barracuda-Start-Time: 1465931348 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 791 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30435 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/14/2016 02:24 PM, Christoph Hellwig wrote: > On Tue, Jun 14, 2016 at 02:12:39PM -0400, Waiman Long wrote: >> This patch enables reader optimistic spinning for inodes that are >> under a DAX-based mount point. >> >> On a 4-socket Haswell machine running on a 4.7-rc1 tip-based kernel, >> the fio test with multithreaded randrw and randwrite tests on the >> same file on a XFS partition on top of a NVDIMM with DAX were run, >> the aggregated bandwidths before and after the patch were as follows: > And why is this specific to DAX? Many I/O operations already never > got out to disk, and ilock is mostly held for operations that have > nothing to do with disk I/O. It is just a showcase for the rwsem change. We can certainly have more use cases. Cheers, Longman From waiman.long@hpe.com Tue Jun 14 14:11:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 474167CA3 for ; Tue, 14 Jun 2016 14:11:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 92D91AC005 for ; Tue, 14 Jun 2016 12:11:34 -0700 (PDT) X-ASG-Debug-ID: 1465931491-04cbb01fec00c80001-NocioJ Received: from na01-by2-obe.outbound.protection.outlook.com (mail-by2on0130.outbound.protection.outlook.com [207.46.100.130]) by cuda.sgi.com with ESMTP id IRSCI9F6UNcU3Qff (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 12:11:32 -0700 (PDT) X-Barracuda-Envelope-From: waiman.long@hpe.com X-Barracuda-Effective-Source-IP: mail-by2on0130.outbound.protection.outlook.com[207.46.100.130] X-Barracuda-Apparent-Source-IP: 207.46.100.130 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=waiman.long@hpe.com; Received: from [192.168.142.153] (72.71.243.198) by AT5PR84MB0307.NAMPRD84.PROD.OUTLOOK.COM (10.162.138.29) with Microsoft SMTP Server (TLS) id 15.1.523.12; Tue, 14 Jun 2016 19:11:27 +0000 Message-ID: <576056DB.5050701@hpe.com> Date: Tue, 14 Jun 2016 15:11:23 -0400 From: Waiman Long User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Thunderbird/10.0.12 MIME-Version: 1.0 To: Davidlohr Bueso CC: Peter Zijlstra , Ingo Molnar , , , , , , , , Jason Low , Dave Chinner , Scott J Norton , Douglas Hatch Subject: Re: [RFC PATCH-tip 2/6] locking/rwsem: Enable optional count-based spinning on reader References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> <1465927959-39719-3-git-send-email-Waiman.Long@hpe.com> <20160614182757.GA15903@linux-80c1.suse> X-ASG-Orig-Subj: Re: [RFC PATCH-tip 2/6] locking/rwsem: Enable optional count-based spinning on reader In-Reply-To: <20160614182757.GA15903@linux-80c1.suse> Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [72.71.243.198] X-ClientProxiedBy: SN1PR15CA0004.namprd15.prod.outlook.com (10.163.200.14) To AT5PR84MB0307.NAMPRD84.PROD.OUTLOOK.COM (10.162.138.29) X-MS-Office365-Filtering-Correlation-Id: 7956dbe4-ecc3-435f-c4d0-08d39487b064 X-Microsoft-Exchange-Diagnostics: 1;AT5PR84MB0307;2:WlJ6eB+PDvn+OO8V0W3cxUxiBYx9MtGZIB+zmngq3fnsYsMqQSKeCNjtbxkPYtJxRgCWVXQ2+I4xeq7DSzlxqadvIBthkjnpnck877Mot6Ic+p+hoqYFP/32oDz3g71h0TYFjkC/kREgLWYb5NHFQ6Ia/gb1FdEe+3SU2udqe8uWlGNcBcGcvEot3OvNDRkj;3:XLWW8d9fnqsJDHs1yNjbaTKiIvOK8a0NzUOG1p7gj8ITsb+My/8gHvS+9RVUr0a3/KpfMkOSVn/BNPddQsh6Lk0vf763XGAmA/ely73QjYntVbnkWwfvFp5q5+fBXX/E X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:AT5PR84MB0307; X-Microsoft-Exchange-Diagnostics: 1;AT5PR84MB0307;25:SYndGAwZeVj70JSYNedpLpp9NxqaTxBOcqqRWJ/856LnhXvnxef9lfEEOjjKgleNachMmliX9zjy/ykypR/qm3LBH29WCLfXibSTD/ruxZIatdWSkrrGAvcoqDNW2OOUWaHVCE5HyNAQRjfLtq7MUQN0iM0FunJkC927FoDn2D0DyWG8h8ZLGi/+2omQzELmWUUDg424Ka0T1FbpugzCcWCBBopqW058xSViBMH2N07tTBEBG872vqfJ2UWxa1j8/aN9xZ8at36J3uxPpN6Dh09iYgKjkqjLxRgRPv2hkEzB4bcTExUeLiDh/F6YLmIDDe+XZpl9jg1HF+BHbxWukg29DoE/+kl4Yaiv6TgRxnJ5lkil0Ka8sNCiQqEVleDGaIYSf7Z3gK2dW0ayompgZjS2w4CQIJZhPBcL34YcNRDVeKG6UO+pWwUdxjO8EwKa1BSS9mR4oAdEiec8aHPTC7GvQfZf2QGecpIXt/XpWplvFLwUbu99jIHH6D2ptedBzqKuOfzlDKng77pvWNF5CQYOl2E9i/KioAoG7shfX83GLBTkWCWkzPfGKkA3KqjaNThK7vb/mhVsRZM6it4ZqE97ou9jckdznLNR3KJLI/E1Sa7JQmS34kmg9mD7MtKqZgCEdUZXcHXctTBNEeG4BWa/OOVhCzhc9jl6jeArpwDIxR3GtYpRpU1JtUb+er6elntHhhZeSXyy2HowEgay0w== X-Microsoft-Exchange-Diagnostics: 1;AT5PR84MB0307;20:cDGJA7jM5A2vVkH0f7sXSZltfZVkzMbvxDkMpHa9zLvXLEY/iQu8i7e+SvKLX6aR20w7xQr9ABqS6lt7JEFyJw19135ssXmzjurrUSh3ojoG/euoZGbnC5lh+EhSpuK3TM4ubHybCP0+quzul4TQfLMhSuCh+EEE8Y4aWgPb3D+5ttxSGoR6hQnnGpVWpiXckKztTRNYTkSdfVyB82U0BG8FotztAgZAm6R0V+fhjURYAA8oDXfwOmrtm1B+1i6SJ+GWJA9ZroJr5XAtGUwFaPbM3j4QztdE4YIEFj6/jReBznXuJ4aOeNUY8+OBLC0fCaVMnqCxGQ8MtvqXRkQV2saxnCm4E4FZuPh4N6wOX2ILl9szAK1Nw8b3VirqVm2+3QojhgySV1dOio9m0GagfHXX0kumPYfMJ9XVE3QJXOFBswSpJkHGz7rLzNz+3RnpTTgPj3WL1auW6R14hkWSFYazfgWFXz9xyM5rKtrBV1dZ2+BYuCzV5uLn5heCA7ft;4:Ie4F1lbig+U5dgdk+XkatlyyMWDt8eXmZNskwx1UH3jxzLp+BwmW4evxceYnHLXfqlAxbmt7bK+u4jgv/H4FJfq6lDrD6d9igC9g1nrQvaag+dFtOAD8cAQW6fsx7ky+jiocDLSGmK/phmufrYqc4oxp7kfEf5ne4bPdqeqQ8r2kEpRQV/qitwiFeZsZkPGt04uzxC5P8W6nzyFuibog1Has3709AQMOavnuOwFRzlsPpMIwr8Wmr5YVjsBfgZ48nYfA6nipHtQQeb3DiLw/2cDyZA369T7hitZggoRKnJgfkd05uEUc6lAHoBAu0GNWDbf0rm8J67l51WUlC/Wf9LBDj2bZRIhIVEpSd60/Qn6SLZgYGZ01kaCsfR0Z9dnI X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046);SRVR:AT5PR84MB0307;BCL:0;PCL:0;RULEID:;SRVR:AT5PR84MB0307; X-Forefront-PRVS: 09730BD177 X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6009001)(6049001)(7916002)(189002)(377454003)(24454002)(199003)(2950100001)(83506001)(86362001)(80316001)(47776003)(77096005)(5004730100002)(65956001)(65816999)(65806001)(66066001)(50986999)(87266999)(54356999)(76176999)(4001350100001)(92566002)(189998001)(97736004)(110136002)(33656002)(117156001)(59896002)(64126003)(42186005)(50466002)(23756003)(105586002)(106356001)(101416001)(99136001)(3846002)(2906002)(230700001)(4326007)(6116002)(68736007)(36756003)(8676002)(81156014)(81166006)(5008740100001)(8666004)(586003)(7059030);DIR:OUT;SFP:1102;SCL:1;SRVR:AT5PR84MB0307;H:[192.168.142.153];FPR:;SPF:None;PTR:InfoNoRecords;MX:1;A:1;CAT:NONE;LANG:en;CAT:NONE; Received-SPF: None (protection.outlook.com: hpe.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?iso-8859-1?Q?1;AT5PR84MB0307;23:k7oEU+lWH8BkoIfkRv9hvrom9oW/cwY/KPs2td4?= =?iso-8859-1?Q?k5TDgzLKy4sWfGvuN/Oux47dGRUkaOLpK5Eed43nllLCh7SBq7uXvSlESq?= =?iso-8859-1?Q?mg5ExTn2jfO+ALwN9zml3gdDPfXYr/p2/anivZDwoFcDbByxJg5pbPolRD?= =?iso-8859-1?Q?HJs+DTAPBOi2nOzDeokW2swIul+RDNrM7EsRzExfZKvRNxJuCrULq6jgSV?= =?iso-8859-1?Q?AnDepNtt2zUNmusVSebaMkLQ3VSRbgjp9lrA8PPUE/Ox76rK/JXn0OMnUm?= =?iso-8859-1?Q?D9c3x7GjdRQ3bRAQGDcwArLJSAanHd33uw9jJPnW8bqtdrhfkZHqIZl6DD?= =?iso-8859-1?Q?abS1/sf310w0HOx6w2kGuZ9DeajhNsr+GUAqD8IUhVMihpe0cdG+CEuFbj?= =?iso-8859-1?Q?RH8FTe4G0o5Q8AEV5k0moaZ7fT3KWEfVE5bx7dwdrbFn2p70oNzlywQE4C?= =?iso-8859-1?Q?pEOeyWcAvQlx9j9pM5CcCfnuBjQl6LuaASRZWPTH459P/Qy7AIRRp9QrRI?= =?iso-8859-1?Q?63O1r79CuhkIukCk7ZtVwTC5gv7B8sd771AMQdhN1+SkVa10jVuwPlwmtY?= =?iso-8859-1?Q?JdEjkCQlRMLivJmM/o6A/8mRcG2heLrE1M+aX8h+kNBSRVFvDyZsNGPcCd?= =?iso-8859-1?Q?bTZeQ54nqKg73eKheJu8ZXjGmt8gRJlyD68eu4icYhlwKy7ul8Z6r96I9m?= =?iso-8859-1?Q?JJXOM/Tkam1/5bQUtq8aknr9HmDEWS6L3HJQh906GskQ6vmq6sW1K+iFbt?= =?iso-8859-1?Q?ekD+ZzE9kigcJZylCnzx3R7RtbM35+SkI4bcmaQLDBs7pHDPN/j7kmmf6B?= =?iso-8859-1?Q?V5Wd8Xib8uCZXHWswrB3u3nIzIBMQ4A/borLn6gZORkrV3xZ0h0Li4pLuF?= =?iso-8859-1?Q?oG9ZvGsrRCWfdnRaJn7Pbxx8TdpJo5Cd62mHvZnvqjyQ+tDf9SM/ISHhuO?= =?iso-8859-1?Q?wCuToYXyuVrdSf7RQQNb30DrqMr8FIQDiDds5ClXP5TYjwNb8DL8r69o1f?= =?iso-8859-1?Q?iX0AIEkrjqsG7ItwamKo1ugw4iBFxD5gHtEVnogk3VERkUsTT5U59GwlSx?= =?iso-8859-1?Q?TbuYcKWElvH83cQEM4vJOOliwVMlE/TNxlFO5UnSEbC6tq44rvtx346192?= =?iso-8859-1?Q?5755t1O0RDsqXhk6lfbZ6KEGogqEby5JJCwulTp9Tlkp5HJJpj3wdyAe60?= =?iso-8859-1?Q?ternPVL99V6MBSrx3slR60UQrR3TSATccA55jhl+L4oRpVfXvemjCTGa+G?= =?iso-8859-1?Q?/IVhh55K/Vv/wuQeSKE9PDP4rRif2wUjStxarIOjVwN3oUBl/WCNpm1YX3?= =?iso-8859-1?Q?xXxQBLipstFW0j7D/NcsPgQ3uX5Iq4jXuTQaMd9fyv9i+eMD5KYO/FkOw9?= =?iso-8859-1?Q?RcU1bgeY=3D?= X-Microsoft-Exchange-Diagnostics: 1;AT5PR84MB0307;6:JuI7ZaARSfg+bQqSKEqqgPY3CGs3ACAYayiH4yVD0UbfOkQQgjldNIIpSMP+CrlBpbWbsZcwkIk8QRZ/0Vc+EnJpVGvw56CQBhyl7zknYmyWnvdJYUIV69cQ3sIRn9M/Yo86tJ40UN4YQxIrhOYMWg8dQqVmz7j8cvS40/S4nmSyp2Xm4z7KRQsvjzHC055+MWKdewhcn3ci86SKNL7G62EI2YzYtmUAN3mYm4I5lwa7UnRqXurQZVgopDuQGUzDP0LwgO5u6XERVR025SYuJTfNsE7xG8jhWd3VQS4UhtY=;5:uHKXE2R80DIasfCvZYtryp6ORgB4dje75PRO6hESQSGHgafTUWXJovjR/3cNrgwe4ss2xTqykgqFtDmqvzV/bUGiijvGdRsO/4iwFvMx3tToxDuJxaC7yxnBay8d0VRM1jvjkYnzmFYNXFtgAoYmCQ==;24:g5YRT19Xd3kc+NpGUhnxSKEV2MGZ7lprwnZkPLA+STt0Gh9XIe9eDK/wEdwyRrLFaV2/fWZypQ0Td1TgdVqrIAw/imdU9S4Cu88BuaA/jfc=;7:4VmzOBcAqtmXqwxdzDHs4WGSCadiXODBeIHnz9RwTMsv06Hid8dVQbcNhjf8KdSDTFnuDiCppcWXPvxLTeyErrn0fhvl+zmQ9+L6YPVrf0B0X0Grp2DIXBjbPb7g34rgq+EeL25mrSEYcXab4YquV9Tt27oifeOcDLJtKsgHMRw7KZ32uTH4I+ffqQ7ETIJyznwIzBo0nzJM7z1ONGDMS4Bb66BkycLWUW8jc54oCQ4= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: hpe.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 14 Jun 2016 19:11:27.6389 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: AT5PR84MB0307 X-Barracuda-Connect: mail-by2on0130.outbound.protection.outlook.com[207.46.100.130] X-Barracuda-Start-Time: 1465931491 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 861 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30434 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/14/2016 02:27 PM, Davidlohr Bueso wrote: > On Tue, 14 Jun 2016, Waiman Long wrote: > >> This patch provides a way for the kernel code to designate specific >> rwsems to be more aggressive in term of optimistic spinning that the >> writers will continue to spin for some additional count-based time to >> see if it can get the lock before sleeping. This aggressive spinning >> mode should only be used on rwsems where the readers are unlikely to >> go to sleep. > > Yikes, exposing this sort of thing makes me _very_ uneasy, not to mention > the ad-hoc nature and its easiness to mess up. I'm not really for > this, even > if it shows extraordinary performance boosts on benchmarks. > > Thanks, > Davidlohr I understand your concern. I will see if there is a way to autotune instead of using explicit enablement. Cheers, Longman From thomas@fjellstrom.ca Tue Jun 14 15:51:37 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 4D0247CA0 for ; Tue, 14 Jun 2016 15:51:37 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1E7FC30405F for ; Tue, 14 Jun 2016 13:51:33 -0700 (PDT) X-ASG-Debug-ID: 1465937488-04cbb01fee034c0001-NocioJ Received: from s18564588.onlinehome-server.info (s18564588.onlinehome-server.info [212.227.86.227]) by cuda.sgi.com with ESMTP id YTm6Blmk9lsSY1hS (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 13:51:30 -0700 (PDT) X-Barracuda-Envelope-From: thomas@fjellstrom.ca X-Barracuda-Effective-Source-IP: s18564588.onlinehome-server.info[212.227.86.227] X-Barracuda-Apparent-Source-IP: 212.227.86.227 Received: from lhwhgu.com (unknown [138.204.37.172]) by s18564588.onlinehome-server.info (Postfix) with ESMTPSA id 281E912D27; Tue, 14 Jun 2016 21:09:45 +0100 (BST) From: To: "xemul" , "xen-devel" , "xfs" , "xiakaixu" , "xiaofeng.yan" Subject: recent photos Date: Tue, 14 Jun 2016 23:09:42 +0300 X-ASG-Orig-Subj: recent photos Message-ID: <00006044b145$8783a721$bdcb090a$@fjellstrom.ca> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_0001_1DBC46AE.52935B68" X-Mailer: Microsoft Outlook 15.0 Thread-Index: AdHOBc8aLvQTjF7iu1fSwaxEBvz2Vw== Content-Language: en-us X-Barracuda-Connect: s18564588.onlinehome-server.info[212.227.86.227] X-Barracuda-Start-Time: 1465937489 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2375 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE, NO_REAL_NAME, THREAD_INDEX X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30437 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.00 NO_REAL_NAME From: does not include a real name 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message This is a multipart message in MIME format. ------=_NextPart_000_0001_1DBC46AE.52935B68 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Hi, I've got those photos from our last meeting, just take a look Kind regards, thomas@fjellstrom.ca ------=_NextPart_000_0001_1DBC46AE.52935B68 Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

<= span lang=3DEN-US>Hi,

 

I've got those photos from our last meeting, just take a lo= ok http= ://hislechypo.cincoranchhomevalue.com/aevzzepz

 

=

Kind regards, thomas@fjellstro= m.ca

------=_NextPart_000_0001_1DBC46AE.52935B68-- From david@fromorbit.com Tue Jun 14 18:06:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 7964D7CA0 for ; Tue, 14 Jun 2016 18:06:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 4B8A7304039 for ; Tue, 14 Jun 2016 16:06:35 -0700 (PDT) X-ASG-Debug-ID: 1465945589-04cbb01fee07490001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id y1ktwrMwP6v0vY57 for ; Tue, 14 Jun 2016 16:06:29 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DQCgD7jGBXN5gMLHldgz6BU4Zvn3ABAQEBAQEGjDiGBoQIhhECAgEBAoEzTQEBAQEBAQcBAQEBQkCETAEBBCcTHBYKAxAIAxgJJQ8FJQMHGhOIL71tAQEBAQYBAQEBIx6FQYUVh2yCLwWIDZBWjh+PLI90hFQqMooIAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 15 Jun 2016 08:36:13 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bCxPR-0008NF-8Z; Wed, 15 Jun 2016 09:06:13 +1000 Date: Wed, 15 Jun 2016 09:06:13 +1000 From: Dave Chinner To: Waiman Long Cc: Peter Zijlstra , Ingo Molnar , linux-kernel@vger.kernel.org, x86@kernel.org, linux-alpha@vger.kernel.org, linux-ia64@vger.kernel.org, linux-s390@vger.kernel.org, linux-arch@vger.kernel.org, xfs@oss.sgi.com, Davidlohr Bueso , Jason Low , Scott J Norton , Douglas Hatch Subject: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes Message-ID: <20160614230613.GB26977@dastard> X-ASG-Orig-Subj: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> <1465927959-39719-7-git-send-email-Waiman.Long@hpe.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1465927959-39719-7-git-send-email-Waiman.Long@hpe.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1465945589 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2246 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30440 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 14, 2016 at 02:12:39PM -0400, Waiman Long wrote: > This patch enables reader optimistic spinning for inodes that are > under a DAX-based mount point. > > On a 4-socket Haswell machine running on a 4.7-rc1 tip-based kernel, > the fio test with multithreaded randrw and randwrite tests on the > same file on a XFS partition on top of a NVDIMM with DAX were run, > the aggregated bandwidths before and after the patch were as follows: > > Test BW before patch BW after patch % change > ---- --------------- -------------- -------- > randrw 1352 MB/s 2164 MB/s +60% > randwrite 1710 MB/s 2550 MB/s +49% > > Signed-off-by: Waiman Long > --- > fs/xfs/xfs_icache.c | 9 +++++++++ > 1 files changed, 9 insertions(+), 0 deletions(-) > > diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c > index 99ee6ee..09f284f 100644 > --- a/fs/xfs/xfs_icache.c > +++ b/fs/xfs/xfs_icache.c > @@ -71,6 +71,15 @@ xfs_inode_alloc( > > mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); > > + /* > + * Enable reader spinning for DAX nount point > + */ > + if (mp->m_flags & XFS_MOUNT_DAX) { > + rwsem_set_rspin_threshold(&ip->i_iolock.mr_lock); > + rwsem_set_rspin_threshold(&ip->i_mmaplock.mr_lock); > + rwsem_set_rspin_threshold(&ip->i_lock.mr_lock); > + } That's wrong. DAX is a per-inode flag, not a mount wide flag. This needs to be done once the inode has been fully initialised and IS_DAX(inode) can be run. Also, the benchmark doesn't show that all these locks are being tested by this benchmark. e.g. the i_mmaplock isn't involved in the benchmark's IO paths at all. It's only taken in page faults and truncate paths.... I'd also like to see how much of the gain comes from the iolock vs the ilock, as the ilock is nested inside the iolock and so contention is much rarer.... As it is, I'm *extremely* paranoid when it comes to changes to core locking like this. Performance is secondary to correctness, and we need much more than just a few benchmarks to verify there aren't locking bugs being introduced.... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Tue Jun 14 19:07:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7B6047CA0 for ; Tue, 14 Jun 2016 19:07:45 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3E6768F8037 for ; Tue, 14 Jun 2016 17:07:42 -0700 (PDT) X-ASG-Debug-ID: 1465949253-04bdf01e1740520001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id 1WwDMyjkDIk6NlDZ for ; Tue, 14 Jun 2016 17:07:34 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DWEAADm2BXKJgMLHlDGoM+Vn2mXwEBAQEBAQaMOIoOIoVvAgIBAQKBNE0BAQEBAQEHAQEBAQEBQECESwEBAQMBJxMcIwULCAMRAwECAQkMGQ8FJQMHDA4TiCgHDy29OwEBAQEBAQEDAQEBAQEBHAUehUGFFYQQb4Jtgi8FiAaHHIlBhgWIGoFzhFKIZ490hFQqMgGIQ4FEAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 15 Jun 2016 09:32:43 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bCyI5-0008S0-M9; Wed, 15 Jun 2016 10:02:41 +1000 Date: Wed, 15 Jun 2016 10:02:41 +1000 From: Dave Chinner To: "Thomas D." Cc: xfs@oss.sgi.com, stable@vger.kernel.org, spender@grsecurity.net Subject: Re: Something badly broken with the latest XFS changeset in all stable kernels? Message-ID: <20160615000241.GC26977@dastard> X-ASG-Orig-Subj: Re: Something badly broken with the latest XFS changeset in all stable kernels? References: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1465949253 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2822 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30442 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Mon, Jun 13, 2016 at 11:57:53PM +0200, Thomas D. wrote: > Hi, > > can anybody confirm if there's something broken with the latest XFS > change set which is now applied on all stable kernels? > > I found https://forums.grsecurity.net/viewtopic.php?t=4489&p=16355 and > grsec changelog says > > > commit 1f621dc42acbabb71bd69f6ba606cee56e7ad3bc > > Author: Brad Spengler > > Date: Sat Jun 11 08:14:32 2016 -0400 > > > > Fix Greg KH's broken XFS backport, caused a benign case to be detected > > as disk corruption > > Problem was due to a tree-wide conversion of error codes to their negative > > counterparts, which would likely never be backported to older kernels, but > > the backports didn't account for the change > > > > fs/xfs/xfs_inode.c | 2 +- > > 1 file changed, 1 insertion(+), 1 deletion(-) Yes, the backport is busted, and needs this fix. The error sign change occurred in 3.17. xfstests would have picked up this regression in a couple of minutes, so I'm guessing that none of these stable releases have had any significant regression testing done.... > This is the change grsec applied: > > > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c > > index fb8579d..af807d8 100644 > > --- a/fs/xfs/xfs_inode.c > > +++ b/fs/xfs/xfs_inode.c > > @@ -3098,7 +3111,7 @@ xfs_iflush( > > */ > > error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK, > > 0); > > - if (error == -EAGAIN) { > > + if (error == EAGAIN) { > > xfs_ifunlock(ip); > > return error; > > } Yes, that is the fix that is needed. Thank you for reporting it to us. Mr Spender: it would be appreciated if you reported stable kernel regressions to the relevant upstream maintainers so they can be fixed quickly for everyone, rather than having one of your users decide it needs to be reported. Stable kernel maintainers: the above error sign change is needed for stable kernels 3.16 and earlier, as a matter of critical importance. And as a further matter of critical importance: in future, please take the time to regression test the changes you backport. > The bad commit according to grsec's statement is > > > From b1438f477934f5a4d5a44df26f3079a7575d5946 Mon Sep 17 00:00:00 2001 > > From: Dave Chinner > > Date: Wed, 18 May 2016 13:53:42 +1000 > > Subject: [PATCH] xfs: xfs_iflush_cluster fails to abort on error > > Would be nice to get some clarification. There's nothing wrong with that commit in the upstream kernel, it's the backport that has a bug in it because it failed to take into account changes outside the context of the upstream commit that the older kernels don't have. Cheers, Dave. -- Dave Chinner david@fromorbit.com From greg@kroah.com Tue Jun 14 20:31:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 335317CA0 for ; Tue, 14 Jun 2016 20:31:04 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id B0F63AC001 for ; Tue, 14 Jun 2016 18:31:00 -0700 (PDT) X-ASG-Debug-ID: 1465954257-04cbb01fee0b180001-NocioJ Received: from out3-smtp.messagingengine.com (out3-smtp.messagingengine.com [66.111.4.27]) by cuda.sgi.com with ESMTP id Ibv2bddN0Cdc58RD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 14 Jun 2016 18:30:57 -0700 (PDT) X-Barracuda-Envelope-From: greg@kroah.com X-Barracuda-Effective-Source-IP: out3-smtp.messagingengine.com[66.111.4.27] X-Barracuda-Apparent-Source-IP: 66.111.4.27 Received: from compute4.internal (compute4.nyi.internal [10.202.2.44]) by mailout.nyi.internal (Postfix) with ESMTP id C767F21CA3; Tue, 14 Jun 2016 21:30:56 -0400 (EDT) Received: from frontend1 ([10.202.2.160]) by compute4.internal (MEProxy); Tue, 14 Jun 2016 21:30:56 -0400 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to:x-sasl-enc :x-sasl-enc; s=smtpout; bh=9ps7cPraNl39AN9dpUMV+EKNBb0=; b=L//fF yS+qsrVgire9MYfLP7fx8Mzm44aQJvyESH4oOLctkRsXYJGaOQE6L4dbgXKF3ubg wOQvnupdD0gPuz9aASXqqA31sUDuUxBi70BEoS5ga2m9bThBkpQL21AxUr5Nc2Ca IWjTAJh2UWk9vsCBoScpcZQDM6iTgfBqV/kwi8= X-Sasl-enc: JiMCPKk/GKbvHD/wZSnE/s6Jj9LPPNh1PJlLJLw2ldgC 1465954256 Received: from localhost (c-50-170-35-168.hsd1.wa.comcast.net [50.170.35.168]) by mail.messagingengine.com (Postfix) with ESMTPA id 36D74F29F7; Tue, 14 Jun 2016 21:30:56 -0400 (EDT) Date: Tue, 14 Jun 2016 18:30:56 -0700 From: Greg KH To: Dave Chinner Cc: "Thomas D." , xfs@oss.sgi.com, stable@vger.kernel.org, spender@grsecurity.net Subject: Re: Something badly broken with the latest XFS changeset in all stable kernels? Message-ID: <20160615013056.GA23074@kroah.com> X-ASG-Orig-Subj: Re: Something badly broken with the latest XFS changeset in all stable kernels? References: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> <20160615000241.GC26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160615000241.GC26977@dastard> User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: out3-smtp.messagingengine.com[66.111.4.27] X-Barracuda-Start-Time: 1465954257 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3285 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30443 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Wed, Jun 15, 2016 at 10:02:41AM +1000, Dave Chinner wrote: > On Mon, Jun 13, 2016 at 11:57:53PM +0200, Thomas D. wrote: > > Hi, > > > > can anybody confirm if there's something broken with the latest XFS > > change set which is now applied on all stable kernels? > > > > I found https://forums.grsecurity.net/viewtopic.php?t=4489&p=16355 and > > grsec changelog says > > > > > commit 1f621dc42acbabb71bd69f6ba606cee56e7ad3bc > > > Author: Brad Spengler > > > Date: Sat Jun 11 08:14:32 2016 -0400 > > > > > > Fix Greg KH's broken XFS backport, caused a benign case to be detected > > > as disk corruption > > > Problem was due to a tree-wide conversion of error codes to their negative > > > counterparts, which would likely never be backported to older kernels, but > > > the backports didn't account for the change > > > > > > fs/xfs/xfs_inode.c | 2 +- > > > 1 file changed, 1 insertion(+), 1 deletion(-) > > Yes, the backport is busted, and needs this fix. The error sign > change occurred in 3.17. xfstests would have picked up this > regression in a couple of minutes, so I'm guessing that none of > these stable releases have had any significant regression testing > done.... > > > This is the change grsec applied: > > > > > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c > > > index fb8579d..af807d8 100644 > > > --- a/fs/xfs/xfs_inode.c > > > +++ b/fs/xfs/xfs_inode.c > > > @@ -3098,7 +3111,7 @@ xfs_iflush( > > > */ > > > error = xfs_imap_to_bp(mp, NULL, &ip->i_imap, &dip, &bp, XBF_TRYLOCK, > > > 0); > > > - if (error == -EAGAIN) { > > > + if (error == EAGAIN) { > > > xfs_ifunlock(ip); > > > return error; > > > } > > Yes, that is the fix that is needed. Thank you for reporting it to > us. > > Mr Spender: it would be appreciated if you reported stable kernel > regressions to the relevant upstream maintainers so they can be > fixed quickly for everyone, rather than having one of your users > decide it needs to be reported. > > Stable kernel maintainers: the above error sign change is needed for > stable kernels 3.16 and earlier, as a matter of critical importance. > And as a further matter of critical importance: in future, please > take the time to regression test the changes you backport. > > > The bad commit according to grsec's statement is > > > > > From b1438f477934f5a4d5a44df26f3079a7575d5946 Mon Sep 17 00:00:00 2001 > > > From: Dave Chinner > > > Date: Wed, 18 May 2016 13:53:42 +1000 > > > Subject: [PATCH] xfs: xfs_iflush_cluster fails to abort on error > > > > Would be nice to get some clarification. > > There's nothing wrong with that commit in the upstream kernel, > it's the backport that has a bug in it because it failed to take > into account changes outside the context of the upstream commit that > the older kernels don't have. Thanks for letting me know about this. As the patch was tagged with 3.10+, I assumed that it was safe to be merged to those older kernels, otherwise I would never have done so. We do have ways to mark external things like this for stable patches, it's a great help when doing backports. thanks, greg k-h From w@1wt.eu Wed Jun 15 00:28:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8C8067CA0 for ; Wed, 15 Jun 2016 00:28:45 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id EE8EEAC002 for ; Tue, 14 Jun 2016 22:28:41 -0700 (PDT) X-ASG-Debug-ID: 1465968518-04cbb01fec11f60001-NocioJ Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by cuda.sgi.com with ESMTP id qAs5nM5C3E32IDNi for ; Tue, 14 Jun 2016 22:28:38 -0700 (PDT) X-Barracuda-Envelope-From: w@1wt.eu X-Barracuda-Effective-Source-IP: wtarreau.pck.nerim.net[62.212.114.60] X-Barracuda-Apparent-Source-IP: 62.212.114.60 Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id u5F5SVLD003642; Wed, 15 Jun 2016 07:28:31 +0200 Date: Wed, 15 Jun 2016 07:28:31 +0200 From: Willy Tarreau To: Greg KH Cc: Dave Chinner , "Thomas D." , xfs@oss.sgi.com, stable@vger.kernel.org, spender@grsecurity.net Subject: Re: Something badly broken with the latest XFS changeset in all stable kernels? Message-ID: <20160615052831.GA3452@1wt.eu> X-ASG-Orig-Subj: Re: Something badly broken with the latest XFS changeset in all stable kernels? References: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> <20160615000241.GC26977@dastard> <20160615013056.GA23074@kroah.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160615013056.GA23074@kroah.com> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: wtarreau.pck.nerim.net[62.212.114.60] X-Barracuda-Start-Time: 1465968518 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 998 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30447 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 14, 2016 at 06:30:56PM -0700, Greg KH wrote: > As the patch was tagged with 3.10+, I assumed that it was safe to be > merged to those older kernels, otherwise I would never have done so. We > do have ways to mark external things like this for stable patches, it's > a great help when doing backports. I guess only 3.14.72 was affected in the end. 3.18.35 has the fix but my understanding is that after 3.17 it's OK. Apparently it's not yet queued for 3.16. Jiri has queued it for 3.12 but not yet released it. For 3.10 I only pick patches that are already in a 3.14 release so I didn't have the time to backport it to 3.10 yet as the preview started before the release. Overall the regression lived only 8 days in a single branch, I guess it shows that our process works rather well and limits the exposure to regressions. Brad, it would have been nice to report it to the stable team especially since you rely on these kernels for yours as well. Regards, Willy From reinoudkoornstra@gmail.com Wed Jun 15 00:40:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A998F7CA0 for ; Wed, 15 Jun 2016 00:40:30 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7BA8A8F8035 for ; Tue, 14 Jun 2016 22:40:27 -0700 (PDT) X-ASG-Debug-ID: 1465969224-04cb6c54250f340001-NocioJ Received: from mail-qg0-f43.google.com (mail-qg0-f43.google.com [209.85.192.43]) by cuda.sgi.com with ESMTP id 4BfCP7XeCOc3rKEQ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 14 Jun 2016 22:40:24 -0700 (PDT) X-Barracuda-Envelope-From: reinoudkoornstra@gmail.com X-Barracuda-Effective-Source-IP: mail-qg0-f43.google.com[209.85.192.43] X-Barracuda-Apparent-Source-IP: 209.85.192.43 Received: by mail-qg0-f43.google.com with SMTP id v48so6305853qgd.2 for ; Tue, 14 Jun 2016 22:40:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=1e8BzOoTmSVuCXe9TVRmrCJdQkyP/js5YQ2I5SgY5Zo=; b=xNWv49O7bOU4KH0B4IDLHwazm38BTpdFce1wJfO9i3CmOpWyAmK+rj+1KdBenAK+a8 p4qVtU9UxfhEiXi3YtGqfOR9p+jTo0Yi8XOsGo/fRPmJ1jYMRhtLN5pk5WVKRYfznH+n Q/9yDOA7GF5Vx6YnK8b3XVtm0OyCciK1i5IUMBV0QvipR8CT3UIpa02YrNj/JGpdKfLv EEpAL1Vb/NfzYfBwAOXqyuBkxQmbY8BcKs1vIsLc4VIaDkHYP9HW8ZpKETAXyqTbj9vI 8AtMxHeGqGvTrisGwpp1lV//kf5649NbLoY7yuHMIY6xsWHD142BS0abbJgzS4NcW9Ht 67Dw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=1e8BzOoTmSVuCXe9TVRmrCJdQkyP/js5YQ2I5SgY5Zo=; b=YUWJGAFOrVsmTO/M9+97HD+o7M9jhEVmhRY3TI4ulii9w027U7wuDCDgBuAt84VQwV AO3ecehIJLYDdB3PGsZHDOiFSjQOEo2WEMG0CAkO7IFtXPNr5JricbF001OJOmR2ydhF rfNrakmG6/8/lqQ7fXhGF12i7nNF51Q9iW8/Ad9DTCjkleU6hagFemezfJk33n392r8L YciYnKJkjuMQr3a1Pqc07Vq/TGdFhgVwwI1Nscok0IQtrJYYKSsK22VZPCQSQSUER51U sQGbijBIRsqXVBCUr+4ggejxTJTxyMBvj/vIXe2zSGDO5ZCrwLzjOPiPRf969k7oOwKZ DObQ== X-Gm-Message-State: ALyK8tItHcjF01//uuCtN2heJW67XnRpPAaAo82TY0ZMf2yd4VUB1TAhbepxQxWOGKzXKGg5h/7sEVigyU73oA== X-Received: by 10.140.250.213 with SMTP id v204mr23600892qhc.15.1465969223747; Tue, 14 Jun 2016 22:40:23 -0700 (PDT) MIME-Version: 1.0 Received: by 10.55.39.13 with HTTP; Tue, 14 Jun 2016 22:40:23 -0700 (PDT) In-Reply-To: References: <79c8e051-24a9-2e2b-553a-bcab17d03e83@sandeen.net> <20160607062717.GA30022@infradead.org> <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> <20160609022238.GY26977@dastard> <00bbe658-a891-3771-ca1d-5661a8b6ab61@sandeen.net> From: Reinoud Koornstra Date: Tue, 14 Jun 2016 23:40:23 -0600 Message-ID: Subject: Re: crash in xfs in current To: Eric Sandeen X-ASG-Orig-Subj: Re: crash in xfs in current Cc: Dave Chinner , Christoph Hellwig , Daniel Wagner , viro@zeniv.linux.org.uk, xfs@oss.sgi.com Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-qg0-f43.google.com[209.85.192.43] X-Barracuda-Start-Time: 1465969224 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5207 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30447 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Wed, Jun 8, 2016 at 9:42 PM, Reinoud Koornstra wrote: > On Wed, Jun 8, 2016 at 8:56 PM, Eric Sandeen wrote: >> On 6/8/16 9:53 PM, Reinoud Koornstra wrote: >> >>>> In your Linus git tree: >>>> >>>> $ git remote add xfsdev git://git.kernel.org/git/dgc/linux-xfs.git >>>> $ git remote update >>>> $ git checkout -b xfsdev-merge v4.6 >>>> $ git merge xfsdev/xfs-for-linus-4.7-rc1 >>> >>> Tried to do this: >>> >>> reinoud@router-dev:~/Downloads/kernel_current$ git remote add xfsdev >>> git://git.kernel.org/git/dgc/linux-xfs.git >> >> I think that should be: >> >> git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git > > Ok That worked better indeed. :) I've tested the way you and Dave described. Indeed, I do not see the issues appearing in that xfsdev tree. So it works good there. For verification, I tried when I was upon this state (so this is a good state): reinoud@router-dev:~/Downloads/kernel_current$ git log | more commit f56c2f323f026bd9cf942f34f8a634ccd88b6ed7 Merge: 2dcd0af 555b67e Author: Reinoud Koornstra Date: Wed Jun 8 21:31:32 2016 -0600 Merge tag 'xfs-for-linus-4.7-rc1' into xfsdev-merge xfs: update for 4.7-rc1 Merge local tree Changes in this update: o fixes for mount line parsing, sparse warnings, read-only compat feature remount behaviour o allow fast path symlink lookups for inline symlinks. o attribute listing cleanups o writeback goes direct to bios rather than indirecting through bufferheads o transaction allocation cleanup o optimised kmem_realloc o added configurable error handling for metadata write errors, changed default error handling behaviour from "retry forever" to "retry until unmount then fail" o fixed several inode cluster writeback lookup vs reclaim race conditions o fixed inode cluster writeback checking wrong inode after lookup o fixed bugs where struct xfs_inode freeing wasn't actually RCU safe o cleaned up inode reclaim tagging commit 555b67e4e729ca544bb4028ab12e532c68b70ddb Merge: 544ad71 ad438c4 Author: Dave Chinner Date: Fri May 20 10:34:00 2016 +1000 Merge branch 'xfs-4.7-inode-reclaim' into for-next commit 544ad71fc8e20fb3a6f50f00d487751492cd8409 Merge: 2a4ad58 e6b3bb7 Author: Dave Chinner Date: Fri May 20 10:33:38 2016 +1000 Merge branch 'xfs-4.7-error-cfg' into for-next commit 2a4ad5894c819978dca5595396d54d51c3aca694 Merge: a7792aa 6e3e6d5 Author: Dave Chinner Date: Fri May 20 10:33:17 2016 +1000 Merge branch 'xfs-4.7-misc-fixes' into for-next Thanks, Reinoud. > > reinoud@router-dev:~/Downloads/kernel_current$ git remote add xfsdev > git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git > reinoud@router-dev:~/Downloads/kernel_current$ git remote update > Fetching origin > Fetching xfsdev > remote: Counting objects: 139, done. > [SNIP] > reinoud@router-dev:~/Downloads/kernel_current$ git checkout -b xfsdev-merge v4.6 > Checking out files: 100% (9437/9437), done. > Switched to a new branch 'xfsdev-merge' > reinoud@router-dev:~/Downloads/kernel_current$ git merge > xfsdev/xfs-for-linus-4.7-rc1 > merge: xfsdev/xfs-for-linus-4.7-rc1 - not something we can merge > So i tried this: > > reinoud@router-dev:~/Downloads/kernel_current$ git merge xfs-for-linus-4.7-rc1 > Auto-merging fs/xfs/xfs_super.c > Auto-merging fs/xfs/xfs_pnfs.c > Auto-merging fs/xfs/xfs_mount.h > Auto-merging fs/xfs/xfs_mount.c > Auto-merging fs/xfs/xfs_file.c > Auto-merging fs/xfs/xfs_bmap_util.c > Auto-merging fs/xfs/xfs_aops.c > Auto-merging fs/xfs/libxfs/xfs_bmap.c > Auto-merging fs/namei.c > Merge made by the 'recursive' strategy. > The terminal did hang .... in 4.6 > I killed the git operation and did it again and now it says it's up to date. > > reinoud@router-dev:~/Downloads/kernel_current$ git merge xfs-for-linus-4.7-rc1 > Already up-to-date. > reinoud@router-dev:~/Downloads/kernel_current$ git status > On branch xfsdev-merge > > Is this correct, can I now build and test? > >> >> -Eric >> >>> reinoud@router-dev:~/Downloads/kernel_current$ git remote update >>> Fetching origin >>> Fetching xfsdev >>> fatal: remote error: access denied or repository not exported: >>> /git/dgc/linux-xfs.git >>> error: Could not fetch xfsdev >>> >>> I don't think I have access to git.kernel.org in terms of pushing. :) >>> Or am I doing something else wrong. >>> Forgive the trivial question. >>> >>> Btw, I started in the most current linus git tree.... or should I git >>> 4.6.y and then do your suggestions? >>> >>> Thanks, >>> >>> Reinoud. >>> >>>> >>>> And that should give you the XFS changes for 4.7-rc1 in a vanilla 4.6 >>>> tree. This merge is one of the things I test (i.e. send to my test >>>> machiens for a round of xfstests and other stress) before sending a >>>> pull request to Linus, so it should work just fine. >>>> >>>> Cheers, >>>> >>>> Dave. >>>> -- >>>> Dave Chinner >>>> david@fromorbit.com >>> From david@fromorbit.com Wed Jun 15 01:40:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 40EFC7CA0 for ; Wed, 15 Jun 2016 01:40:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id AF2A0AC002 for ; Tue, 14 Jun 2016 23:40:27 -0700 (PDT) X-ASG-Debug-ID: 1465972823-04cb6c5425100f0001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id DrgHLIm54Dz3XHWG for ; Tue, 14 Jun 2016 23:40:24 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Aq0NAB73YFd5LAyYKGdsb2JhbABdgz6BU4Zvn3IBBQaMOIoOhhECAgEBAoE3TQEBAQEBAQcBAQEBAQE/AUCESwEBAQQ6HCMQCAMRAwECAQkMGQ8FJQMHDA4TiC++CQEBAQEBAQQBAQEBASIehUGFFYR/gm2CLwWIB4cciUaOH48sj3SEVSoyiggBAQE Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl2.internode.on.net with ESMTP; 15 Jun 2016 16:10:22 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bD4Uw-0000hQ-7r; Wed, 15 Jun 2016 16:40:22 +1000 Date: Wed, 15 Jun 2016 16:40:22 +1000 From: Dave Chinner To: Greg KH Cc: "Thomas D." , xfs@oss.sgi.com, stable@vger.kernel.org, spender@grsecurity.net Subject: Re: Something badly broken with the latest XFS changeset in all stable kernels? Message-ID: <20160615064022.GD26977@dastard> X-ASG-Orig-Subj: Re: Something badly broken with the latest XFS changeset in all stable kernels? References: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> <20160615000241.GC26977@dastard> <20160615013056.GA23074@kroah.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160615013056.GA23074@kroah.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1465972823 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1575 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30448 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 14, 2016 at 06:30:56PM -0700, Greg KH wrote: > On Wed, Jun 15, 2016 at 10:02:41AM +1000, Dave Chinner wrote: > > On Mon, Jun 13, 2016 at 11:57:53PM +0200, Thomas D. wrote: > > > The bad commit according to grsec's statement is > > > > > > > From b1438f477934f5a4d5a44df26f3079a7575d5946 Mon Sep 17 00:00:00 2001 > > > > From: Dave Chinner > > > > Date: Wed, 18 May 2016 13:53:42 +1000 > > > > Subject: [PATCH] xfs: xfs_iflush_cluster fails to abort on error > > > > > > Would be nice to get some clarification. > > > > There's nothing wrong with that commit in the upstream kernel, > > it's the backport that has a bug in it because it failed to take > > into account changes outside the context of the upstream commit that > > the older kernels don't have. > > Thanks for letting me know about this. > > As the patch was tagged with 3.10+, I assumed that it was safe to be > merged to those older kernels, otherwise I would never have done so. We > do have ways to mark external things like this for stable patches, it's > a great help when doing backports. Little things like this are very easy to forget about - those error sign changes are ancient history as far as upstream development is concerned. This is why we have regression tests - the zero-day kernel robot can run xfstests - perhaps stable kernels should be submitted to a full round of testing before release to catch subtle "patch applies but ends up wrong" issues like this... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Wed Jun 15 01:51:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2E9227CA0 for ; Wed, 15 Jun 2016 01:51:59 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D746E8F8040 for ; Tue, 14 Jun 2016 23:51:58 -0700 (PDT) X-ASG-Debug-ID: 1465973515-04bdf01e134f1a0001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id OlFkaDRLvdAVzJkv for ; Tue, 14 Jun 2016 23:51:55 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AkkfAKv6YFd5LAyYKGdsb2JhbABdgz6BU4Zvn3IBBQaMOIoOglCDQQQCAoE3TQEBAQEBAQcBAQEBAQE/AUCESwEBAQMBOhwjBQsIAw4KCSUPBSUDBxoTiCgHvgEBAQEHAgEkHoVBhRWHbIIvAQSTRIUljh+PLI90glscgV4qMooIAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl2.internode.on.net with ESMTP; 15 Jun 2016 16:21:22 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bD4fZ-0000iv-BA; Wed, 15 Jun 2016 16:51:21 +1000 Date: Wed, 15 Jun 2016 16:51:21 +1000 From: Dave Chinner To: Willy Tarreau Cc: Greg KH , "Thomas D." , xfs@oss.sgi.com, stable@vger.kernel.org, spender@grsecurity.net Subject: Re: Something badly broken with the latest XFS changeset in all stable kernels? Message-ID: <20160615065121.GE26977@dastard> X-ASG-Orig-Subj: Re: Something badly broken with the latest XFS changeset in all stable kernels? References: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> <20160615000241.GC26977@dastard> <20160615013056.GA23074@kroah.com> <20160615052831.GA3452@1wt.eu> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160615052831.GA3452@1wt.eu> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1465973515 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1429 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30449 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 15, 2016 at 07:28:31AM +0200, Willy Tarreau wrote: > On Tue, Jun 14, 2016 at 06:30:56PM -0700, Greg KH wrote: > > As the patch was tagged with 3.10+, I assumed that it was safe to be > > merged to those older kernels, otherwise I would never have done so. We > > do have ways to mark external things like this for stable patches, it's > > a great help when doing backports. > > I guess only 3.14.72 was affected in the end. 3.18.35 has the fix but my > understanding is that after 3.17 it's OK. Correct. > Apparently it's not yet queued > for 3.16. The queue for 3.16 has a different bunch of XFS stuff that I've previous said is pretty risky and not advisable to back port (the mmaplock stuff). I'm waiting for that to get to users and a new bunch of whacky problems to be reported... > Jiri has queued it for 3.12 but not yet released it. For 3.10 > I only pick patches that are already in a 3.14 release so I didn't have > the time to backport it to 3.10 yet as the preview started before the > release. Just lucky, eh? > Overall the regression lived only 8 days in a single branch, I > guess it shows that our process works rather well and limits the exposure > to regressions. That it got as far as release and it took so long to get to the upstream maintainers shows the process could do with being improved. Cheers, Dave. -- Dave Chinner david@fromorbit.com From jirislaby@gmail.com Wed Jun 15 02:00:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E6BC57CA0 for ; Wed, 15 Jun 2016 02:00:12 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6E14AAC003 for ; Wed, 15 Jun 2016 00:00:12 -0700 (PDT) X-ASG-Debug-ID: 1465974008-04bdf01e134f500001-NocioJ Received: from mail-wm0-f45.google.com (mail-wm0-f45.google.com [74.125.82.45]) by cuda.sgi.com with ESMTP id 0GPClhMDIkEb8hMa (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 15 Jun 2016 00:00:09 -0700 (PDT) X-Barracuda-Envelope-From: jirislaby@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f45.google.com[74.125.82.45] X-Barracuda-Apparent-Source-IP: 74.125.82.45 Received: by mail-wm0-f45.google.com with SMTP id v199so149439857wmv.0 for ; Wed, 15 Jun 2016 00:00:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=c/hZyQGCUKda1hW0/v4zEq98JBk6xGqf5bnaxC63fwU=; b=KDpZ4wgb4kD0Hfdjf8854tAiNq8Mk0SCFQFx/u/OtraGJlSV1odcdZJrxP9L16LRUb qIS+2XdPShuP/li76OvKduEPH/gl9EwhsXpZ7+BfJkH8tPTu/R+ij62PhGPqOv680F6k hNQh+WUllrU3h2ZluUwf5wLdjenSWHh6dKMmZzOwcNXBL0rL2f8vY9swydy+wpnr9A5v 6mTFbkQn7t0qdla/ADXnxbd96xRSO81FH8U5vCSDT4aRFHmI8FvEvOJ3YMTDvsXeW/oF 2cr2z9LCtigKYpzXlnsyo9S2uwb8O6nxsvDc7ZDukNWhPO2+Si9Geex2ab/woZ2hl2ZN VweQ== X-Gm-Message-State: ALyK8tLOZgYYbL4tpD9xirDKUZ+uVWYl9P1I9+hUq33U8OXARaNHw5uSPWhKgxEVegXoxQ== X-Received: by 10.194.192.193 with SMTP id hi1mr9515137wjc.4.1465974008283; Wed, 15 Jun 2016 00:00:08 -0700 (PDT) Received: from ?IPv6:2a01:4240:2e27:ad85:aaaa::19f? (f.9.1.0.0.0.0.0.0.0.0.0.a.a.a.a.5.8.d.a.7.2.e.2.0.4.2.4.1.0.a.2.v6.cust.nbox.cz. [2a01:4240:2e27:ad85:aaaa::19f]) by smtp.gmail.com with ESMTPSA id w81sm2500777wmg.20.2016.06.15.00.00.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Jun 2016 00:00:07 -0700 (PDT) Subject: Re: Something badly broken with the latest XFS changeset in all stable kernels? To: Willy Tarreau , Greg KH X-ASG-Orig-Subj: Re: Something badly broken with the latest XFS changeset in all stable kernels? References: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> <20160615000241.GC26977@dastard> <20160615013056.GA23074@kroah.com> <20160615052831.GA3452@1wt.eu> Cc: Dave Chinner , "Thomas D." , xfs@oss.sgi.com, stable@vger.kernel.org, spender@grsecurity.net From: Jiri Slaby Message-ID: Date: Wed, 15 Jun 2016 09:00:06 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160615052831.GA3452@1wt.eu> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f45.google.com[74.125.82.45] X-Barracuda-Start-Time: 1465974009 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 147 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30449 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/15/2016, 07:28 AM, Willy Tarreau wrote: > Jiri has queued it for 3.12 but not yet released it. Fixed now, thanks! -- js suse labs From w@1wt.eu Wed Jun 15 02:14:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D5EA87CA0 for ; Wed, 15 Jun 2016 02:14:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id A6DD5304032 for ; Wed, 15 Jun 2016 00:14:47 -0700 (PDT) X-ASG-Debug-ID: 1465974884-04cb6c542510cc0001-NocioJ Received: from 1wt.eu (wtarreau.pck.nerim.net [62.212.114.60]) by cuda.sgi.com with ESMTP id aes6DpLmkVTSlz4k for ; Wed, 15 Jun 2016 00:14:44 -0700 (PDT) X-Barracuda-Envelope-From: w@1wt.eu X-Barracuda-Effective-Source-IP: wtarreau.pck.nerim.net[62.212.114.60] X-Barracuda-Apparent-Source-IP: 62.212.114.60 Received: (from willy@localhost) by pcw.home.local (8.15.2/8.15.2/Submit) id u5F7Eca0005328; Wed, 15 Jun 2016 09:14:38 +0200 Date: Wed, 15 Jun 2016 09:14:38 +0200 From: Willy Tarreau To: Dave Chinner Cc: Greg KH , "Thomas D." , xfs@oss.sgi.com, stable@vger.kernel.org, spender@grsecurity.net Subject: Re: Something badly broken with the latest XFS changeset in all stable kernels? Message-ID: <20160615071438.GA5294@1wt.eu> X-ASG-Orig-Subj: Re: Something badly broken with the latest XFS changeset in all stable kernels? References: <75808782-835f-4bc9-5243-b25cab00d6f3@whissi.de> <20160615000241.GC26977@dastard> <20160615013056.GA23074@kroah.com> <20160615052831.GA3452@1wt.eu> <20160615065121.GE26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160615065121.GE26977@dastard> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: wtarreau.pck.nerim.net[62.212.114.60] X-Barracuda-Start-Time: 1465974884 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1577 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30449 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 15, 2016 at 04:51:21PM +1000, Dave Chinner wrote: > > Overall the regression lived only 8 days in a single branch, I > > guess it shows that our process works rather well and limits the exposure > > to regressions. > > That it got as far as release and it took so long to get to the > upstream maintainers shows the process could do with being improved. Yep but users relying on oldest LTS usually run on servers that cannot reboot without prior planning, so in practice we know that users tend to be late by 1 week or more and often one or two versions. I'm pretty sure this is the reason why a single user reported the issue. I'm not saying this to dismiss the importance of a regression, just the fact that the zero-risk never exists and that if an issue can only be discovered in field (since the commit was backported according to the tags and that the need to adapt it was not detected during the review process), it will need one first victim to save all other users. In the end the quick enough report ensured that most 3.14 users will not have the time to upgrade to the broken version and 3.10/3.12 users will not even have the opportunity to see the issue at all. That's what I'm saying is not that bad. We could imagine some automated tests depending on the affected files and/or subsystems but it's not even certain that an automated test would have detected this one :-/ We need to thank the initial reporter here, and to encourage Brad to pass the information back ASAP next time this happens via his channel. Willy From david@fromorbit.com Wed Jun 15 02:22:17 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 61ABA7CA0 for ; Wed, 15 Jun 2016 02:22:17 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D44EA8F8035 for ; Wed, 15 Jun 2016 00:22:13 -0700 (PDT) X-ASG-Debug-ID: 1465975330-04bdf01e104fea0001-NocioJ Received: from ipmail06.adl2.internode.on.net (ipmail06.adl2.internode.on.net [150.101.137.129]) by cuda.sgi.com with ESMTP id RqIv1eCqjnFYcQGY for ; Wed, 15 Jun 2016 00:22:10 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Apparent-Source-IP: 150.101.137.129 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AicNALoBYVd5LAyYKGdsb2JhbABdgz6BU4Zvn3IBBQaMOIoOhhEEAgKBN00BAQEBAQEHAQEBAQEBPwFAhEsBAQEDATocIwULCAMOCgklDwUlAwcaE4goB74NAQEBAQEFAQEBASMehUGFFYdsgi8FmGmOH4Fzh3+FOo90hFUqMooIAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl2.internode.on.net with ESMTP; 15 Jun 2016 16:51:54 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bD598-0000mu-3m; Wed, 15 Jun 2016 17:21:54 +1000 Date: Wed, 15 Jun 2016 17:21:54 +1000 From: Dave Chinner To: Michal Hocko Cc: Peter Zijlstra , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160615072154.GF26977@dastard> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160517223549.GV26977@dastard> <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> <20160602232254.GR12670@dastard> <20160606122022.GH11895@dhcp22.suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160606122022.GH11895@dhcp22.suse.cz> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl2.internode.on.net[150.101.137.129] X-Barracuda-Start-Time: 1465975330 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4653 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30449 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header [sorry for the slow repsonse - been on holidays] On Mon, Jun 06, 2016 at 02:20:22PM +0200, Michal Hocko wrote: > On Fri 03-06-16 09:22:54, Dave Chinner wrote: > > On Thu, Jun 02, 2016 at 05:46:19PM +0200, Michal Hocko wrote: > > > On Thu 02-06-16 17:11:16, Peter Zijlstra wrote: > > > > With scope I mostly meant the fact that you have two calls that you need > > > > to pair up. That's not really nice as you can 'annotate' a _lot_ of code > > > > in between. I prefer the narrower annotations where you annotate a > > > > single specific site. > > > > > > Yes, I can see you point. What I meant to say is that we would most > > > probably end up with the following pattern > > > lockdep_trace_alloc_enable() > > > some_foo_with_alloc(gfp_mask); > > > lockdep_trace_alloc_disable() > > > > > > and some_foo_with_alloc might be a lot of code. > > > > That's the problem I see with this - the only way to make it > > maintainable is to precede each enable/disable() pair with a comment > > explaining *exactly* what those calls are protecting. And that, in > > itself, becomes a maintenance problem, because then code several > > layers deep has no idea what context it is being called from and we > > are likely to disable warnings in contexts where we probably > > shouldn't be. > > I am not sure I understand what you mean here. I thought the problem is > that: > > func_A (!trans. context) func_B (trans. context) > foo1() foo2() > bar(inode, GFP_KERNEL) bar(inode, GFP_NOFS) > > so bar(inode, gfp) can be called from two different contexts which > would confuse the lockdep. Yes, that's the core of the problem. What I think you are missing is the scale of the problem. > And the workaround would be annotating bar > depending on the context it is called from - either pass a special gfp > flag or do disable/enable thing. In both cases that anotation should be > global for the whole func_A, no? Or is it possible that something in > that path would really need a reclaim lockdep detection? The problem is that there are cases where the call stack that leads to bar() has many different entry points. See, for example, the xfs_bmapi*() interfaces. They all end up in the same low level btree traversal code (and hence memory allocation points). xfs_bmapi_read() can be called from both inside and outside transaction context and there's ~30 callers we'd have to audit and annotate. Then there's ~10 callers of xfs_bmapi_write which are all within transaction context. And then there's xfs_bmapi_delay(), which can end up in the same low level code outside transaction context. Then there's 10 callers of xfs_bunmapi(), which runs both inside and outside transaction context, too. Add to that all the miscellenous points that can read extents off disk, and you get another ~12 entry points. Hopefully you can see the complexity of the issue - for an allocation in the bmap btree code that could occur outside both inside and outside of a transaction context, we've got to work out which of those ~60 high level entry points would need to be annotated. And then we have to ensure that in future we don't miss adding or removing an annotation as we change the code deep inside the btree implementation. It's the latter that is the long term maintainence problem the hihg-level annotation approach introduces. > > I think such an annotation approach really requires per-alloc site > > annotation, the reason for it should be more obvious from the > > context. e.g. any function that does memory alloc and takes an > > optional transaction context needs annotation. Hence, from an XFS > > perspective, I think it makes more sense to add a new KM_ flag to > > indicate this call site requirement, then jump through whatever > > lockdep hoop is required within the kmem_* allocation wrappers. > > e.g, we can ignore the new KM_* flag if we are in a transaction > > context and so the flag is only activated in the situations were > > we currently enforce an external GFP_NOFS context from the call > > site..... > > Hmm, I thought we would achive this by using the scope GFP_NOFS usage > which would mark those transaction related conctexts and no lockdep > specific workarounds would be needed... There are allocations outside transaction context which need to be GFP_NOFS - this is what KM_NOFS was originally intended for. We need to disambiguate the two cases where we use KM_NOFS to shut up lockdep vs the cases where it is necessary to prevent reclaim deadlocks. Cheers, Dave. -- Dave Chinner david@fromorbit.com From bfoster@redhat.com Wed Jun 15 08:26:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A42E67CA3 for ; Wed, 15 Jun 2016 08:26:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 772618F8040 for ; Wed, 15 Jun 2016 06:26:47 -0700 (PDT) X-ASG-Debug-ID: 1465997205-04cb6c542519fe0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id MIsAHLRAddTm2VXO (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 15 Jun 2016 06:26:46 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4AFD4B5396 for ; Wed, 15 Jun 2016 13:26:45 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-81.bos.redhat.com [10.18.41.81]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5FDQiOB009553 for ; Wed, 15 Jun 2016 09:26:45 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id C1F8412673F; Wed, 15 Jun 2016 09:26:43 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH v2] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly Date: Wed, 15 Jun 2016 09:26:43 -0400 X-ASG-Orig-Subj: [PATCH v2] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correctly Message-Id: <1465997203-55379-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 15 Jun 2016 13:26:45 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1465997206 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7034 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 xfs_reserve_blocks() is responsible to update the XFS reserved block pool count at mount time or based on user request. When the caller requests to increase the reserve pool, blocks must be allocated from the global counters such that they are no longer available for general purpose use. If the requested reserve pool size is too large, XFS reserves what blocks are available. The implementation requires looking at the percpu counters and making an educated guess as to how many blocks to try and allocate from xfs_mod_fdblocks(), which can return -ENOSPC if the guess was not accurate due to counters being modified in parallel. xfs_reserve_blocks() retries the guess in this scenario until the allocation succeeds or it is determined that there is no space available in the fs. While not easily reproducible in the current form, the retry code doesn't actually work correctly if xfs_mod_fdblocks() actually fails. The problem is that the percpu calculations use the m_resblks counter to determine how many blocks to allocate, but unconditionally update m_resblks before the block allocation has actually succeeded. Therefore, if xfs_mod_fdblocks() fails, the code jumps to the retry label and uses the already updated m_resblks value to determine how many blocks to try and allocate. If the percpu counters previously suggested that the entire request was available, fdblocks_delta could end up set to 0. In that case, m_resblks is updated to the requested value, yet no blocks have been reserved at all. Refactor xfs_reserve_blocks() to use an explicit loop and make the code easier to follow. Since we have to drop the spinlock across the xfs_mod_fdblocks() call, use a delta value for m_resblks as well and only apply the delta once allocation succeeds. Signed-off-by: Brian Foster --- v2: - Convert while() loop to do {} while(). v1: http://oss.sgi.com/pipermail/xfs/2016-June/049391.html fs/xfs/xfs_fsops.c | 104 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 45 deletions(-) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index b4d7582..d5c1044 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -667,8 +667,11 @@ xfs_reserve_blocks( __uint64_t *inval, xfs_fsop_resblks_t *outval) { - __int64_t lcounter, delta, fdblks_delta; + __int64_t lcounter, delta; + __int64_t fdblks_delta = 0; __uint64_t request; + __int64_t free; + int error = 0; /* If inval is null, report current values and return */ if (inval == (__uint64_t *)NULL) { @@ -682,24 +685,23 @@ xfs_reserve_blocks( request = *inval; /* - * With per-cpu counters, this becomes an interesting - * problem. we needto work out if we are freeing or allocation - * blocks first, then we can do the modification as necessary. + * With per-cpu counters, this becomes an interesting problem. we need + * to work out if we are freeing or allocation blocks first, then we can + * do the modification as necessary. * - * We do this under the m_sb_lock so that if we are near - * ENOSPC, we will hold out any changes while we work out - * what to do. This means that the amount of free space can - * change while we do this, so we need to retry if we end up - * trying to reserve more space than is available. + * We do this under the m_sb_lock so that if we are near ENOSPC, we will + * hold out any changes while we work out what to do. This means that + * the amount of free space can change while we do this, so we need to + * retry if we end up trying to reserve more space than is available. */ -retry: spin_lock(&mp->m_sb_lock); /* * If our previous reservation was larger than the current value, - * then move any unused blocks back to the free pool. + * then move any unused blocks back to the free pool. Modify the resblks + * counters directly since we shouldn't have any problems unreserving + * space. */ - fdblks_delta = 0; if (mp->m_resblks > request) { lcounter = mp->m_resblks_avail - request; if (lcounter > 0) { /* release unused blocks */ @@ -707,54 +709,66 @@ retry: mp->m_resblks_avail -= lcounter; } mp->m_resblks = request; - } else { - __int64_t free; + if (fdblks_delta) { + spin_unlock(&mp->m_sb_lock); + error = xfs_mod_fdblocks(mp, fdblks_delta, 0); + spin_lock(&mp->m_sb_lock); + } + + goto out; + } + /* + * If the request is larger than the current reservation, reserve the + * blocks before we update the reserve counters. Sample m_fdblocks and + * perform a partial reservation if the request exceeds free space. + */ + do { free = percpu_counter_sum(&mp->m_fdblocks) - XFS_ALLOC_SET_ASIDE(mp); if (!free) - goto out; /* ENOSPC and fdblks_delta = 0 */ + break; delta = request - mp->m_resblks; lcounter = free - delta; - if (lcounter < 0) { + if (lcounter < 0) /* We can't satisfy the request, just get what we can */ - mp->m_resblks += free; - mp->m_resblks_avail += free; - fdblks_delta = -free; - } else { - fdblks_delta = -delta; - mp->m_resblks = request; - mp->m_resblks_avail += delta; - } - } -out: - if (outval) { - outval->resblks = mp->m_resblks; - outval->resblks_avail = mp->m_resblks_avail; - } - spin_unlock(&mp->m_sb_lock); + fdblks_delta = free; + else + fdblks_delta = delta; - if (fdblks_delta) { /* - * If we are putting blocks back here, m_resblks_avail is - * already at its max so this will put it in the free pool. - * - * If we need space, we'll either succeed in getting it - * from the free block count or we'll get an enospc. If - * we get a ENOSPC, it means things changed while we were - * calculating fdblks_delta and so we should try again to - * see if there is anything left to reserve. + * We'll either succeed in getting space from the free block + * count or we'll get an ENOSPC. If we get a ENOSPC, it means + * things changed while we were calculating fdblks_delta and so + * we should try again to see if there is anything left to + * reserve. * * Don't set the reserved flag here - we don't want to reserve * the extra reserve blocks from the reserve..... */ - int error; - error = xfs_mod_fdblocks(mp, fdblks_delta, 0); - if (error == -ENOSPC) - goto retry; + spin_unlock(&mp->m_sb_lock); + error = xfs_mod_fdblocks(mp, -fdblks_delta, 0); + spin_lock(&mp->m_sb_lock); + } while (error == -ENOSPC); + + /* + * Update the reserve counters if blocks have been successfully + * allocated. + */ + if (!error && fdblks_delta) { + mp->m_resblks += fdblks_delta; + mp->m_resblks_avail += fdblks_delta; } - return 0; + +out: + if (outval) { + outval->resblks = mp->m_resblks; + outval->resblks_avail = mp->m_resblks_avail; + } + + spin_unlock(&mp->m_sb_lock); + return error; } int -- 2.5.5 From BATV+aeca86be1910f2be2f7c+4679+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 15 09:48:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8AC1B7CA2 for ; Wed, 15 Jun 2016 09:48:09 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 16AC0AC002 for ; Wed, 15 Jun 2016 07:48:05 -0700 (PDT) X-ASG-Debug-ID: 1466002083-04bdf01e1061c70001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id J8S95Gu914820GTo (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 15 Jun 2016 07:48:03 -0700 (PDT) X-Barracuda-Envelope-From: BATV+aeca86be1910f2be2f7c+4679+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDC6r-0001E9-Dj; Wed, 15 Jun 2016 14:48:01 +0000 Date: Wed, 15 Jun 2016 07:48:01 -0700 From: Christoph Hellwig To: Trond Myklebust Cc: Christoph Hellwig , "linux-nfs@vger.kernel.org" , xfs@oss.sgi.com Subject: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Message-ID: <20160615144801.GB18524@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes References: <1465931115-30784-3-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-4-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-5-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-6-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-7-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-8-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-9-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-10-git-send-email-trond.myklebust@primarydata.com> <20160615071343.GC4318@infradead.org> <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466002083 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1579 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30456 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 15, 2016 at 02:29:42PM +0000, Trond Myklebust wrote: > The locking is actually simpler than XFS. It looks way more complicated. And totally undocumented. > We have 2 I/O modes: buffered I/O and direct I/O. The write lock is there to ensure safe transitions between those 2 modes, but once the mode is set, > we _only_ use shared locks in order to allow parallelism. >From reading the patch that's not what actually happens - I think you're still taking i_rwsem exclusive for buffered writes, aren't you? Doing that is absolutely mandatory for Posix atomicy requirements, or you'll break tons of of applications. But XFS allows full parallelism for direct reads and writes as long as there is no more pagecache to flush. But if you have pages in the pagecache you need the exclusive lock to prevent against new pagecache pages being added. > >The nice thing is than in 4.7-rc i_mutex has been replaced with a > >rw_mutex so you can just use that in shared mode for direct I/O > >as-is without needing any new lock. > > We would end up serialising reads and writes, since the latter grab an > exclusive lock in generic_file_write(). Why do that if we don???t have to? Looks at the XFS code - no serialization between direct reads and writes as long as no buffered I/O came in inbetween. And don't use generic_file_{read,write}_iter if you want to do direct I/O, unfortunately locking in mm/filemap.c is totally screwed for direct I/O, take a look at XFS which is where direct I/O came from and where we get the locking right. From trondmy@primarydata.com Wed Jun 15 09:52:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 668E27CA2 for ; Wed, 15 Jun 2016 09:52:51 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id E4F02AC002 for ; Wed, 15 Jun 2016 07:52:50 -0700 (PDT) X-ASG-Debug-ID: 1466002350-04bdf01e1361e30001-NocioJ Received: from us-smtp-delivery-194.mimecast.com (us-smtp-delivery-194.mimecast.com [63.128.21.194]) by cuda.sgi.com with ESMTP id hBcz4gCySPB9AEJC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 15 Jun 2016 07:52:31 -0700 (PDT) X-Barracuda-Envelope-From: trondmy@primarydata.com X-Barracuda-Effective-Source-IP: us-smtp-delivery-194.mimecast.com[63.128.21.194] X-Barracuda-Apparent-Source-IP: 63.128.21.194 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=PrimaryData.onmicrosoft.com; s=selector1-primarydata-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=uslqjn0x5ds6qO+DDlKBMSRczqDOP2EHl/E+WuZv7jI=; b=g1oQ53PjsCTlRflR17f0xLBnaHWjgo9Er3xoVp3pO0qKbTwa5vqfTA5Z+avkPOp+ktMESRUWAzjqbhRsFjnQt4vJAgGqVS0lMF6Z5EiEiCpEJM4O/I69VUpAjdv/ht3f8m5d5kT0YgTFTh8TmUhEPa6w4KYgV4Bck2+RO5AcePM= Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1blp0189.outbound.protection.outlook.com [207.46.163.189]) (Using TLS) by us-smtp-1.mimecast.com with ESMTP id us-mta-14-A9dgmNClPIm7_QIohkpnpQ-1; Wed, 15 Jun 2016 10:52:26 -0400 Received: from CY1PR11MB0316.namprd11.prod.outlook.com (10.161.164.26) by CY1PR11MB0314.namprd11.prod.outlook.com (10.161.164.24) with Microsoft SMTP Server (TLS) id 15.1.517.8; Wed, 15 Jun 2016 14:52:24 +0000 Received: from CY1PR11MB0316.namprd11.prod.outlook.com ([10.161.164.26]) by CY1PR11MB0316.namprd11.prod.outlook.com ([10.161.164.26]) with mapi id 15.01.0517.014; Wed, 15 Jun 2016 14:52:24 +0000 From: Trond Myklebust To: Christoph Hellwig CC: "linux-nfs@vger.kernel.org" , "xfs@oss.sgi.com" Subject: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Thread-Topic: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes X-ASG-Orig-Subj: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Thread-Index: AQHRxm/Hou68eOWUIUa7yE29WUzNT5/qHgaAgAA2wYCAAEgtgP//viqA Date: Wed, 15 Jun 2016 14:52:24 +0000 Message-ID: References: <1465931115-30784-3-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-4-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-5-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-6-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-7-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-8-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-9-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-10-git-send-email-trond.myklebust@primarydata.com> <20160615071343.GC4318@infradead.org> <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> <20160615144801.GB18524@infradead.org> In-Reply-To: <20160615144801.GB18524@infradead.org> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [68.49.162.121] x-ms-office365-filtering-correlation-id: 24e5e1d3-dd2d-4ee3-d63a-08d3952ca9c6 x-microsoft-exchange-diagnostics: 1;CY1PR11MB0314;6:aanf6dAo4NrLXky3vGK87VE748WUbNvpekGdxCcKdwh9eC8syIFjf7OEjxTcnTJsDwpO/fsj7rPafOO6dMwSpawN4PRf/PTnHgP3nZ3X/qlN2nnBpqlwSNAfIN4E3xAlEBgZPoz11ycDOopA5P2rFGDt+Qe1usSFfLkOqGvgnBVNAHoIcVvJF3UxlBh8LMo+kPTxgdrt8rdV5YbIef/b+G2ucsr421BF+vW92PelhLn1qTICIhhC59yu5zkpM4KDGtWPk3oyM8tBT/ZzRa66U1YLrIcII98kSy4EeeXaQoE=;5:Jxo1Z5tQMNKiSWA3kyeu18AlkaMldviDL/G+S1qvV4bxV007kgtQH2Xtr5Uvaz+x/2zHXnuDk80sOKNfMiGEIge0JO8m8BNPWiHYmD/79klAmCPkFYM0YBAqbPWzZzUC0rLJ7jAAvlvmmEqOIyvuHQ==;24:YctuDc2Vz32LNDx01FGiA8Xs7LPWPUcKseYcmFV2r7V92a3A2VQySxApWA4vqYRAA7394pevaPW6ocm/W55wikdF1BcGuwZJ96xHNXL5HoA=;7:lznK4//ryK2D/mCuPWm7WQVx3WtUK16cqFETXlhZa+HLKcuz2ZUShFMIlu+mfM34Ai/emLSycOVw08/C7PGNAE8a91sYvb91KoG0tu5YjBUaA/OViU+N65cWGICuw37DHgtEB4y7VVuPgQ4NijxwvXGBg+IwC0ajt1C17dfbMPcxMHLOPoIxoUnWBSSfQsunUvBll8DQO6VRYSVLRgXpAQ==;20:m+E9MPZV9AzCJ2orlPxJITPF4uwFGfD7Q/5cOXMIWhcwik0twgvvyntVyVVhC07JhKnTQrwx0OjWlx/id3Q0dddTe8+LFdy9+F0KCTcqv8EX9WV6FnzRPPoggVXWGZIXXGyyyIHzIeFc/2uqB56lqp9XoaArpAcPG1WrWFfXODs= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR11MB0314; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(6040130)(601004)(2401047)(8121501046)(5005006)(3002001)(10201501046)(6041072)(6043046);SRVR:CY1PR11MB0314;BCL:0;PCL:0;RULEID:;SRVR:CY1PR11MB0314; x-forefront-prvs: 09749A275C x-forefront-antispam-report: SFV:NSPM;SFS:(10019020)(6009001)(7916002)(199003)(24454002)(189002)(19580405001)(19580395003)(33656002)(87936001)(97736004)(81156014)(68736007)(3846002)(102836003)(6116002)(93886004)(92566002)(586003)(5002640100001)(110136002)(36756003)(66066001)(11100500001)(106116001)(106356001)(83716003)(50986999)(54356999)(76176999)(122556002)(105586002)(82746002)(3660700001)(189998001)(86362001)(10400500002)(101416001)(2900100001)(2950100001)(99286002)(5008740100001)(77096005)(8676002)(5004730100002)(3280700002)(81166006)(2906002)(8936002)(4326007)(104396002);DIR:OUT;SFP:1102;SCL:1;SRVR:CY1PR11MB0314;H:CY1PR11MB0316.namprd11.prod.outlook.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;CAT:NONE;LANG:en;CAT:NONE; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: <03C34F082829B84FB19C8F422DED8E81@namprd11.prod.outlook.com> MIME-Version: 1.0 X-OriginatorOrg: primarydata.com X-MS-Exchange-CrossTenant-originalarrivaltime: 15 Jun 2016 14:52:24.6400 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 03193ed6-8726-4bb3-a832-18ab0d28adb7 X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR11MB0314 X-MC-Unique: A9dgmNClPIm7_QIohkpnpQ-1 Content-Type: multipart/alternative; boundary="MCBoundary=_11606151052282941" X-Barracuda-Connect: us-smtp-delivery-194.mimecast.com[63.128.21.194] X-Barracuda-Start-Time: 1466002351 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4971 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30457 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --MCBoundary=_11606151052282941 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: base64 T24gNi8xNS8xNiwgMTA6NDgsICJDaHJpc3RvcGggSGVsbHdpZyIgPGhjaEBpbmZyYWRlYWQub3Jn PiB3cm90ZToNCg0KPk9uIFdlZCwgSnVuIDE1LCAyMDE2IGF0IDAyOjI5OjQyUE0gKzAwMDAsIFRy b25kIE15a2xlYnVzdCB3cm90ZToNCj4+IFRoZSBsb2NraW5nIGlzIGFjdHVhbGx5IHNpbXBsZXIg dGhhbiBYRlMuDQo+DQo+SXQgbG9va3Mgd2F5IG1vcmUgY29tcGxpY2F0ZWQuICBBbmQgdG90YWxs eSB1bmRvY3VtZW50ZWQuDQo+DQo+PiBXZSBoYXZlIDIgSS9PIG1vZGVzOiBidWZmZXJlZCBJL08g YW5kIGRpcmVjdCBJL08uIFRoZSB3cml0ZSBsb2NrIGlzIHRoZXJlIHRvIGVuc3VyZSBzYWZlIHRy YW5zaXRpb25zIGJldHdlZW4gdGhvc2UgMiBtb2RlcywgYnV0IG9uY2UgdGhlIG1vZGUgaXMgc2V0 LA0KPj4gd2UgX29ubHlfIHVzZSBzaGFyZWQgbG9ja3MgaW4gb3JkZXIgdG8gYWxsb3cgcGFyYWxs ZWxpc20uDQo+DQo+RnJvbSByZWFkaW5nIHRoZSBwYXRjaCB0aGF0J3Mgbm90IHdoYXQgYWN0dWFs bHkgaGFwcGVucyAtIEkgdGhpbmsgeW91J3JlDQo+c3RpbGwgdGFraW5nIGlfcndzZW0gZXhjbHVz aXZlIGZvciBidWZmZXJlZCB3cml0ZXMsIGFyZW4ndCB5b3U/DQo+DQo+RG9pbmcgdGhhdCBpcyBh YnNvbHV0ZWx5IG1hbmRhdG9yeSBmb3IgUG9zaXggYXRvbWljeSByZXF1aXJlbWVudHMsIG9yDQo+ eW91J2xsIGJyZWFrIHRvbnMgb2Ygb2YgYXBwbGljYXRpb25zLg0KDQpZZXMuIFdlIGNvbnRpbnVl IHRvIGxldCB0aGUgVkZTIG1hbmFnZSBzZXJpYWxpc2F0aW9uIG9mIHdyaXRlcy4NCg0KPkJ1dCBY RlMgYWxsb3dzIGZ1bGwgcGFyYWxsZWxpc20gZm9yIGRpcmVjdCByZWFkcyBhbmQgd3JpdGVzIGFz IGxvbmcNCj5hcyB0aGVyZSBpcyBubyBtb3JlIHBhZ2VjYWNoZSB0byBmbHVzaC4gIEJ1dCBpZiB5 b3UgaGF2ZSBwYWdlcyBpbg0KPnRoZSBwYWdlY2FjaGUgeW91IG5lZWQgdGhlIGV4Y2x1c2l2ZSBs b2NrIHRvIHByZXZlbnQgYWdhaW5zdCBuZXcNCj5wYWdlY2FjaGUgcGFnZXMgYmVpbmcgYWRkZWQu DQoNCkV4YWN0bHkuIFNvIGRvZXMgdGhpcy4NCg0KPj4gPlRoZSBuaWNlIHRoaW5nIGlzIHRoYW4g aW4gNC43LXJjIGlfbXV0ZXggaGFzIGJlZW4gcmVwbGFjZWQgd2l0aCBhDQo+PiA+cndfbXV0ZXgg c28geW91IGNhbiBqdXN0IHVzZSB0aGF0IGluIHNoYXJlZCBtb2RlIGZvciBkaXJlY3QgSS9PDQo+ PiA+YXMtaXMgd2l0aG91dCBuZWVkaW5nIGFueSBuZXcgbG9jay4NCj4+IA0KPj4gV2Ugd291bGQg ZW5kIHVwIHNlcmlhbGlzaW5nIHJlYWRzIGFuZCB3cml0ZXMsIHNpbmNlIHRoZSBsYXR0ZXIgZ3Jh YiBhbg0KPj4gZXhjbHVzaXZlIGxvY2sgaW4gZ2VuZXJpY19maWxlX3dyaXRlKCkuIFdoeSBkbyB0 aGF0IGlmIHdlIGRvbj8/P3QgaGF2ZSB0bz8NCj4NCj5Mb29rcyBhdCB0aGUgWEZTIGNvZGUgLSBu byBzZXJpYWxpemF0aW9uIGJldHdlZW4gZGlyZWN0IHJlYWRzIGFuZCB3cml0ZXMNCj5hcyBsb25n IGFzIG5vIGJ1ZmZlcmVkIEkvTyBjYW1lIGluIGluYmV0d2Vlbi4NCj4NCj5BbmQgZG9uJ3QgdXNl IGdlbmVyaWNfZmlsZV97cmVhZCx3cml0ZX1faXRlciBpZiB5b3Ugd2FudCB0byBkbyBkaXJlY3Qg SS9PLA0KPnVuZm9ydHVuYXRlbHkgbG9ja2luZyBpbiBtbS9maWxlbWFwLmMgaXMgdG90YWxseSBz Y3Jld2VkIGZvciBkaXJlY3QgSS9PLA0KPnRha2UgYSBsb29rIGF0IFhGUyB3aGljaCBpcyB3aGVy ZSBkaXJlY3QgSS9PIGNhbWUgZnJvbSBhbmQgd2hlcmUgd2UgZ2V0DQo+dGhlIGxvY2tpbmcgcmln aHQuDQoNCldlIGRvbuKAmXQgdXNlIGdlbmVyaWNfZmlsZV8qIGZvciBPX0RJUkVDVDsgd2Ugb25s eSB1c2UgaXQgZm9yIGJ1ZmZlcmVkIEkvTy4NCg0KRGlzY2xhaW1lcg0KDQpUaGUgaW5mb3JtYXRp b24gY29udGFpbmVkIGluIHRoaXMgY29tbXVuaWNhdGlvbiBmcm9tIHRoZSBzZW5kZXIgaXMgY29u ZmlkZW50aWFsLiBJdCBpcyBpbnRlbmRlZCBzb2xlbHkgZm9yIHVzZSBieSB0aGUgcmVjaXBpZW50 IGFuZCBvdGhlcnMgYXV0aG9yaXplZCB0byByZWNlaXZlIGl0LiBJZiB5b3UgYXJlIG5vdCB0aGUg cmVjaXBpZW50LCB5b3UgYXJlIGhlcmVieSBub3RpZmllZCB0aGF0IGFueSBkaXNjbG9zdXJlLCBj b3B5aW5nLCBkaXN0cmlidXRpb24gb3IgdGFraW5nIGFjdGlvbiBpbiByZWxhdGlvbiBvZiB0aGUg Y29udGVudHMgb2YgdGhpcyBpbmZvcm1hdGlvbiBpcyBzdHJpY3RseSBwcm9oaWJpdGVkIGFuZCBt YXkgYmUgdW5sYXdmdWwuDQo= --MCBoundary=_11606151052282941 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=UTF-8 On 6/15/16, 10:48, "Christoph Hellwig" <hch@infrad= ead.org> wrote:

>On Wed, Jun 15, 2016 at 02:29:42PM +0000, Trond Myklebust wrote:
>> The locking is actually simpler than XFS.
>
>It looks way more complicated. And totally undocumented.
>
>> We have 2 I/O modes: buffered I/O and direct I/O. The write lock i= s there to ensure safe transitions between those 2 modes, but once the mode= is set,
>> we _only_ use shared locks in order to allow parallelism.
>
>From reading the patch that's not what actually happens - I think you'r= e
>still taking i_rwsem exclusive for buffered writes, aren't you?
>
>Doing that is absolutely mandatory for Posix atomicy requirements, or >you'll break tons of of applications.

Yes. We continue to let the VFS manage serialisation of writes.

>But XFS allows full parallelism for direct reads and writes as long
>as there is no more pagecache to flush. But if you have pages in
>the pagecache you need the exclusive lock to prevent against new
>pagecache pages being added.

Exactly. So does this.

>> >The nice thing is than in 4.7-rc i_mutex has been replaced wit= h a
>> >rw_mutex so you can just use that in shared mode for direct I/= O
>> >as-is without needing any new lock.
>>
>> We would end up serialising reads and writes, since the latter gra= b an
>> exclusive lock in generic_file_write(). Why do that if we don???t = have to?
>
>Looks at the XFS code - no serialization between direct reads and write= s
>as long as no buffered I/O came in inbetween.
>
>And don't use generic_file_{read,write}_iter if you want to do direct I= /O,
>unfortunately locking in mm/filemap.c is totally screwed for direct I/O= ,
>take a look at XFS which is where direct I/O came from and where we get=
>the locking right.

We don=E2=80=99t use generic_file_* for O_DIRECT; we only use it for buffer= ed I/O.


Disclaimer

The information contained in this communication from the send= er is confidential. It is intended solely for use by the recipient and othe= rs authorized to receive it. If you are not the recipient, you are hereby n= otified that any disclosure, copying, distribution or taking action in rela= tion of the contents of this information is strictly prohibited and may be = unlawful.

--MCBoundary=_11606151052282941-- From BATV+aeca86be1910f2be2f7c+4679+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 15 09:56:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 07BE47CA2 for ; Wed, 15 Jun 2016 09:56:43 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 75101AC002 for ; Wed, 15 Jun 2016 07:56:42 -0700 (PDT) X-ASG-Debug-ID: 1466002600-04cb6c54271c0e0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id pkhbDMQGGqJ5mIeI (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 15 Jun 2016 07:56:40 -0700 (PDT) X-Barracuda-Envelope-From: BATV+aeca86be1910f2be2f7c+4679+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDCFC-0007iZ-5z; Wed, 15 Jun 2016 14:56:38 +0000 Date: Wed, 15 Jun 2016 07:56:38 -0700 From: Christoph Hellwig To: Trond Myklebust Cc: Christoph Hellwig , "linux-nfs@vger.kernel.org" , "xfs@oss.sgi.com" Subject: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Message-ID: <20160615145638.GC5297@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes References: <1465931115-30784-5-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-6-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-7-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-8-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-9-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-10-git-send-email-trond.myklebust@primarydata.com> <20160615071343.GC4318@infradead.org> <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> <20160615144801.GB18524@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466002600 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 629 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30457 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 15, 2016 at 02:52:24PM +0000, Trond Myklebust wrote: > >But XFS allows full parallelism for direct reads and writes as long > >as there is no more pagecache to flush. But if you have pages in > >the pagecache you need the exclusive lock to prevent against new > >pagecache pages being added. > > Exactly. So does this. So let's avoid bloating the inode with another rw_semaphore, and make everyones life easier by using the existing lock. > We don???t use generic_file_* for O_DIRECT; we only use it for buffered I/O. I know - this was just an answer to your reference to the generic_file_* code. From trondmy@primarydata.com Wed Jun 15 10:09:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C77957CA4 for ; Wed, 15 Jun 2016 10:09:35 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5BE14AC005 for ; Wed, 15 Jun 2016 08:09:35 -0700 (PDT) X-ASG-Debug-ID: 1466003368-04bdf01e1562700001-NocioJ Received: from us-smtp-delivery-194.mimecast.com (us-smtp-delivery-194.mimecast.com [216.205.24.194]) by cuda.sgi.com with ESMTP id Ky4aWV5f6Cov9fKw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 15 Jun 2016 08:09:30 -0700 (PDT) X-Barracuda-Envelope-From: trondmy@primarydata.com X-Barracuda-Effective-Source-IP: us-smtp-delivery-194.mimecast.com[216.205.24.194] X-Barracuda-Apparent-Source-IP: 216.205.24.194 Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1blp0181.outbound.protection.outlook.com [207.46.163.181]) (Using TLS) by us-smtp-1.mimecast.com with ESMTP id us-mta-23-XgC81i4JSBKyk8155NqDkA-1; Wed, 15 Jun 2016 11:09:25 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=PrimaryData.onmicrosoft.com; s=selector1-primarydata-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=q1DsR1urGFijXRejw1Dkr7sZsnjgSTPBE3XUmrTCo3U=; b=FSTmMkJT4bA3l8Qpc1HzezQolymWsTJoX9DNmhbqBAeDJscOPtR2+Pq7HfkWpzLqCkXeo1QRYMyuQGb2dbIHp6E3s4R9lt3j9l9DALOalssDx8KBWe9vgiwo1THvlQMpu/xDiGjyDdmd9oxNmXM1LK+iPVbqnqhc6dcTWvNzECE= Received: from CY1PR11MB0316.namprd11.prod.outlook.com (10.161.164.26) by CY1PR11MB0316.namprd11.prod.outlook.com (10.161.164.26) with Microsoft SMTP Server (TLS) id 15.1.517.8; Wed, 15 Jun 2016 15:09:23 +0000 Received: from CY1PR11MB0316.namprd11.prod.outlook.com ([10.161.164.26]) by CY1PR11MB0316.namprd11.prod.outlook.com ([10.161.164.26]) with mapi id 15.01.0517.014; Wed, 15 Jun 2016 15:09:23 +0000 From: Trond Myklebust To: Christoph Hellwig CC: "linux-nfs@vger.kernel.org" , "xfs@oss.sgi.com" Subject: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Thread-Topic: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes X-ASG-Orig-Subj: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Thread-Index: AQHRxm/Hou68eOWUIUa7yE29WUzNT5/qHgaAgAA2wYCAAEgtgP//viqAgABEPgD//8CAgA== Date: Wed, 15 Jun 2016 15:09:23 +0000 Message-ID: <02DCF6B5-AFDF-4E33-A8F2-DBFE67A87E91@primarydata.com> References: <1465931115-30784-5-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-6-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-7-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-8-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-9-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-10-git-send-email-trond.myklebust@primarydata.com> <20160615071343.GC4318@infradead.org> <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> <20160615144801.GB18524@infradead.org> <20160615145638.GC5297@infradead.org> In-Reply-To: <20160615145638.GC5297@infradead.org> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [68.49.162.121] x-ms-office365-filtering-correlation-id: f5947814-4be4-49e8-04cc-08d3952f08d1 x-microsoft-exchange-diagnostics: 1;CY1PR11MB0316;6:1EqJMSrcrB5x4of3Y8lPqTrZOi349LzEg7BdS9PYNfDyi2B8TB8PcA+fQvYAeHYlCiP+cNHprRBpuKp/i6JqVInUg4DRQ1v3v85uJjY5qRYJuvvNs/qcGbwHww3RvcTVDlKcbZ0SosR+bMMhGa2K3ITTtKnCIzXcVCeaYIV6d8XmviJZtHqD1fWk5ug1FkBP+ECKuWWyLuJ3TkA4L8C0Eu7cAxq6wD3o6HFKny3Lbfw3gCLRUNb+DqQlAxqq9pQtM8aw6wPIHAVHnfXlIN8nJc1Esp4cbL71m1ngPJhoPYg=;5:RKFVVraNFrEZC04+/P7Jel+sejmHcPq4rvhu1jZ6eBHFwdnFptkJ4rd4FhQBQEqZm9GaGZVGcaSJFyh+6dCF6uA7bYQYs/ShhEwBZ2Pq3jyCbVqNMgoFYGnMDQzvYvd6WJ5kCb9b8Qd2D54u2CEtCQ==;24:W7EmNmd5UuhZ0naoCoYvsVGXDzLHOzdPCuYH8s4JHW1bP4JIRfaby4ljFNhOa49HiSQ/nUNHbWd6NJVgXuXsT2m6+MfwuugveggzLjchXCQ=;7:PL3kHyDCMd3BB4fJWOzCH5AomPvW6F+2G390fcE2CplQRrb8WMtgNxrQtGbtzZfM1pplN4Vpou9RVuo10Aa0Kd4NlrTakXgbK1McQM1b/Oe912rTQ+h4eQIj6AuN+6TG67NeiRekbWHYxudmltcPfcgljQ5DJGGqLUyPHESFfig8D1w8U5ShdOwEyT5Dgjqr5RwPBBRKqosn+xicGJ8gDw==;20:wGqtopYQqPFe7yhug5nSRUO7z7HRqLj982io5pzhKJei1EbZc6AISYgBsilQ44WX5wSQ6Uag41IkyBdQVbV0a8I5+iYYc7SvPBESU1VM5oTiRZwK8YlJ2eeE3S1MrFVg1Unf2VSv91pKkGdJng2q6xoFIIoYXp/rEHXNLSUq0Z4= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR11MB0316; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(6040130)(601004)(2401047)(5005006)(8121501046)(10201501046)(3002001)(6041072)(6043046);SRVR:CY1PR11MB0316;BCL:0;PCL:0;RULEID:;SRVR:CY1PR11MB0316; x-forefront-prvs: 09749A275C x-forefront-antispam-report: SFV:NSPM;SFS:(10019020)(6009001)(7916002)(199003)(24454002)(189002)(19580405001)(19580395003)(33656002)(87936001)(81156014)(97736004)(68736007)(3846002)(102836003)(6116002)(93886004)(92566002)(586003)(5002640100001)(110136002)(36756003)(66066001)(11100500001)(106116001)(106356001)(83716003)(50986999)(54356999)(76176999)(122556002)(105586002)(82746002)(3660700001)(189998001)(86362001)(10400500002)(101416001)(2900100001)(2950100001)(99286002)(5008740100001)(77096005)(8676002)(5004730100002)(3280700002)(81166006)(2906002)(8936002)(4326007)(104396002);DIR:OUT;SFP:1102;SCL:1;SRVR:CY1PR11MB0316;H:CY1PR11MB0316.namprd11.prod.outlook.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;CAT:NONE;LANG:en;CAT:NONE; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: <5594A498DF247448A4B9742EF574217F@namprd11.prod.outlook.com> MIME-Version: 1.0 X-OriginatorOrg: primarydata.com X-MS-Exchange-CrossTenant-originalarrivaltime: 15 Jun 2016 15:09:23.1258 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 03193ed6-8726-4bb3-a832-18ab0d28adb7 X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR11MB0316 X-MC-Unique: XgC81i4JSBKyk8155NqDkA-1 Content-Type: multipart/alternative; boundary="MCBoundary=_11606151109270731" X-Barracuda-Connect: us-smtp-delivery-194.mimecast.com[216.205.24.194] X-Barracuda-Start-Time: 1466003369 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3100 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30457 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --MCBoundary=_11606151109270731 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: base64 DQoNCk9uIDYvMTUvMTYsIDEwOjU2LCAiQ2hyaXN0b3BoIEhlbGx3aWciIDxoY2hAaW5mcmFkZWFk Lm9yZz4gd3JvdGU6DQoNCj5PbiBXZWQsIEp1biAxNSwgMjAxNiBhdCAwMjo1MjoyNFBNICswMDAw LCBUcm9uZCBNeWtsZWJ1c3Qgd3JvdGU6DQo+PiA+QnV0IFhGUyBhbGxvd3MgZnVsbCBwYXJhbGxl bGlzbSBmb3IgZGlyZWN0IHJlYWRzIGFuZCB3cml0ZXMgYXMgbG9uZw0KPj4gPmFzIHRoZXJlIGlz IG5vIG1vcmUgcGFnZWNhY2hlIHRvIGZsdXNoLiAgQnV0IGlmIHlvdSBoYXZlIHBhZ2VzIGluDQo+ PiA+dGhlIHBhZ2VjYWNoZSB5b3UgbmVlZCB0aGUgZXhjbHVzaXZlIGxvY2sgdG8gcHJldmVudCBh Z2FpbnN0IG5ldw0KPj4gPnBhZ2VjYWNoZSBwYWdlcyBiZWluZyBhZGRlZC4NCj4+IA0KPj4gRXhh Y3RseS4gU28gZG9lcyB0aGlzLg0KPg0KPlNvIGxldCdzIGF2b2lkIGJsb2F0aW5nIHRoZSBpbm9k ZSB3aXRoIGFub3RoZXIgcndfc2VtYXBob3JlLCBhbmQgbWFrZQ0KPmV2ZXJ5b25lcyBsaWZlIGVh c2llciBieSB1c2luZyB0aGUgZXhpc3RpbmcgbG9jay4NCg0KQXMgSSBzYWlkIGVhcmxpZXIsIHRo ZSBwcm9ibGVtIHdpdGggdGhhdCBpcyB5b3UgZW5kIHVwIGFydGlmaWNpYWxseSBzZXJpYWxpc2lu ZyBidWZmZXJlZCByZWFkcyBhbmQgYnVmZmVyZWQgd3JpdGVzLg0KDQrigKIgVGhlIHJlYWRzIG9u bHkgbmVlZCBhIHNoYXJlZCBsb2NrIGluIG9yZGVyIHRvIHByb3RlY3QgdGhlIEkvTyBtb2RlIGZy b20gZmxpcHBpbmcgdG8gT19ESVJFQ1QgKGFuZCByZWx5aW5nIG9uIHBhZ2UgbG9ja3MgdG8gcHJv dGVjdCBhZ2FpbnN0IGJ1ZmZlcmVkIHdyaXRlcykuDQrigKIgVGhlIHdyaXRlcyBuZWVkIHByb3Rl Y3Rpb24gYWdhaW5zdCBPX0RJUkVDVCwgdGhleSBkb27igJl0IG5lZWQgc2VyaWFsaXNhdGlvbiB3 aXRoIG90aGVyIHJlYWRzLCBidXQgdGhleSBkbyBuZWVkIHRvIGJlIHNlcmlhbGlzZWQgYWdhaW5z dCBvdGhlciBidWZmZXJlZCB3cml0ZXMuDQoNCkRpc2NsYWltZXINCg0KVGhlIGluZm9ybWF0aW9u IGNvbnRhaW5lZCBpbiB0aGlzIGNvbW11bmljYXRpb24gZnJvbSB0aGUgc2VuZGVyIGlzIGNvbmZp ZGVudGlhbC4gSXQgaXMgaW50ZW5kZWQgc29sZWx5IGZvciB1c2UgYnkgdGhlIHJlY2lwaWVudCBh bmQgb3RoZXJzIGF1dGhvcml6ZWQgdG8gcmVjZWl2ZSBpdC4gSWYgeW91IGFyZSBub3QgdGhlIHJl Y2lwaWVudCwgeW91IGFyZSBoZXJlYnkgbm90aWZpZWQgdGhhdCBhbnkgZGlzY2xvc3VyZSwgY29w eWluZywgZGlzdHJpYnV0aW9uIG9yIHRha2luZyBhY3Rpb24gaW4gcmVsYXRpb24gb2YgdGhlIGNv bnRlbnRzIG9mIHRoaXMgaW5mb3JtYXRpb24gaXMgc3RyaWN0bHkgcHJvaGliaXRlZCBhbmQgbWF5 IGJlIHVubGF3ZnVsLg0K --MCBoundary=_11606151109270731 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

On 6/15/16, 10:56, "Christoph Hellwig" <hch@infradead.org> = wrote:

>On Wed, Jun 15, 2016 at 02:52:24PM +0000, Trond Myklebust wrote:
>> >But XFS allows full parallelism for direct reads and writes as= long
>> >as there is no more pagecache to flush. But if you have pages= in
>> >the pagecache you need the exclusive lock to prevent against n= ew
>> >pagecache pages being added.
>>
>> Exactly. So does this.
>
>So let's avoid bloating the inode with another rw_semaphore, and make >everyones life easier by using the existing lock.

As I said earlier, the problem with that is you end up artificially seriali= sing buffered reads and buffered writes.

=E2=80=A2 The reads only need a shared lock in order to protect the I/O mod= e from flipping to O_DIRECT (and relying on page locks to protect against b= uffered writes).
=E2=80=A2 The writes need protection against O_DIRECT, they don=E2=80=99t n= eed serialisation with other reads, but they do need to be serialised again= st other buffered writes.


Disclaimer

The information contained in this communication from the send= er is confidential. It is intended solely for use by the recipient and othe= rs authorized to receive it. If you are not the recipient, you are hereby n= otified that any disclosure, copying, distribution or taking action in rela= tion of the contents of this information is strictly prohibited and may be = unlawful.

--MCBoundary=_11606151109270731-- From BATV+aeca86be1910f2be2f7c+4679+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 15 10:14:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 097737CA6 for ; Wed, 15 Jun 2016 10:14:29 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id D023F30404E for ; Wed, 15 Jun 2016 08:14:25 -0700 (PDT) X-ASG-Debug-ID: 1466003663-04cbb01fec23fc0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id yS5Y8cqSRosJBcxs (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 15 Jun 2016 08:14:24 -0700 (PDT) X-Barracuda-Envelope-From: BATV+aeca86be1910f2be2f7c+4679+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDCWM-0000IO-4i; Wed, 15 Jun 2016 15:14:22 +0000 Date: Wed, 15 Jun 2016 08:14:22 -0700 From: Christoph Hellwig To: Trond Myklebust Cc: Christoph Hellwig , "linux-nfs@vger.kernel.org" , "xfs@oss.sgi.com" Subject: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Message-ID: <20160615151422.GA28557@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes References: <1465931115-30784-7-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-8-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-9-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-10-git-send-email-trond.myklebust@primarydata.com> <20160615071343.GC4318@infradead.org> <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> <20160615144801.GB18524@infradead.org> <20160615145638.GC5297@infradead.org> <02DCF6B5-AFDF-4E33-A8F2-DBFE67A87E91@primarydata.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <02DCF6B5-AFDF-4E33-A8F2-DBFE67A87E91@primarydata.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466003664 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 752 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30457 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 15, 2016 at 03:09:23PM +0000, Trond Myklebust wrote: > As I said earlier, the problem with that is you end up artificially serialising buffered reads and buffered writes. If you actually want to be Posix compiant you need to serialize buffered reads against buffererd writes - it's just that most Linux file systems happen to get this wrong. > ??? The reads only need a shared lock in order to protect the I/O mode from flipping to O_DIRECT (and relying on page locks to protect against buffered writes). Which strictly speaking is not enough, although as said above most Linux filesystems get this wrong. If you indeed want to keep that (incorrect) behavior you need another lock. It's defintively not "simpler", though. From trondmy@primarydata.com Wed Jun 15 10:45:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EF4D67CA3 for ; Wed, 15 Jun 2016 10:45:46 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id C1C1F8F804B for ; Wed, 15 Jun 2016 08:45:46 -0700 (PDT) X-ASG-Debug-ID: 1466005543-04cbb01fed25220001-NocioJ Received: from us-smtp-delivery-194.mimecast.com (us-smtp-delivery-194.mimecast.com [63.128.21.194]) by cuda.sgi.com with ESMTP id U7O9pKTBIs7hRWq0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 15 Jun 2016 08:45:43 -0700 (PDT) X-Barracuda-Envelope-From: trondmy@primarydata.com X-Barracuda-Effective-Source-IP: us-smtp-delivery-194.mimecast.com[63.128.21.194] X-Barracuda-Apparent-Source-IP: 63.128.21.194 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=PrimaryData.onmicrosoft.com; s=selector1-primarydata-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=pLCB0xZKEBgSGrG/bvRNoN4hB+ziNFNfCFBA3bF0gso=; b=GO6D9JH8F8whWWpGw1oNwGXBjVqKdZ550Fbx11+eJPg9UoQHsE1UtlF/j11GRE+1XYwM1HfpLnv3raOpeqMwfWqPz/yV80yHt9aiuttsyGjlX/pf5j2nM5dTGvPoXOLJu+8dVm19R5Ke5IfMJirqoprkLOnWy8dzdKvoFkimw7M= Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1blp0183.outbound.protection.outlook.com [207.46.163.183]) (Using TLS) by us-smtp-1.mimecast.com with ESMTP id us-mta-14-1XnrxGcNP9mBbn6bUAF7UQ-1; Wed, 15 Jun 2016 11:45:40 -0400 Received: from CY1PR11MB0316.namprd11.prod.outlook.com (10.161.164.26) by CY1PR11MB0315.namprd11.prod.outlook.com (10.161.164.25) with Microsoft SMTP Server (TLS) id 15.1.517.8; Wed, 15 Jun 2016 15:45:37 +0000 Received: from CY1PR11MB0316.namprd11.prod.outlook.com ([10.161.164.26]) by CY1PR11MB0316.namprd11.prod.outlook.com ([10.161.164.26]) with mapi id 15.01.0517.014; Wed, 15 Jun 2016 15:45:37 +0000 From: Trond Myklebust To: Christoph Hellwig CC: "linux-nfs@vger.kernel.org" , "xfs@oss.sgi.com" Subject: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Thread-Topic: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes X-ASG-Orig-Subj: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Thread-Index: AQHRxm/Hou68eOWUIUa7yE29WUzNT5/qHgaAgAA2wYCAAEgtgP//viqAgABEPgD//8CAgIAARHUA///FrAA= Date: Wed, 15 Jun 2016 15:45:37 +0000 Message-ID: References: <1465931115-30784-7-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-8-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-9-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-10-git-send-email-trond.myklebust@primarydata.com> <20160615071343.GC4318@infradead.org> <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> <20160615144801.GB18524@infradead.org> <20160615145638.GC5297@infradead.org> <02DCF6B5-AFDF-4E33-A8F2-DBFE67A87E91@primarydata.com> <20160615151422.GA28557@infradead.org> In-Reply-To: <20160615151422.GA28557@infradead.org> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-exchange-messagesentrepresentingtype: 1 x-originating-ip: [68.49.162.121] x-ms-office365-filtering-correlation-id: 0f3ed250-0660-46ce-9692-08d3953418f7 x-microsoft-exchange-diagnostics: 1;CY1PR11MB0315;6:8hqhPv/9o6x4813dSvVS7Rco/cVSQOlejMaGMkTbttQWllDwGXDJR+0n8OUZPqePIFvljAyeiN8/3s5h8VhPGfi6MPingtNJQsiTH4Kl5FfVS0JcA20KddF1os1JceCKRjyw8J4yFjP7PsGDyXY5TpoOnalGcatqUiuMyPJ0tBRn1ywA4KxTaIecPY4sZH5+NOMgiKsONHRoRTs3Y9KtGbL+VHnLpH63KsSxlvjC9Trdj9CbiLxsYBD0u2J7mx4PXv/1BCqj72EJoHlhcgP2AIOFaXDn9CCsN1R4kUmrO8Q=;5:XwiMExYpvtAxFH4r3pRPm1oGQLlu4WvPtvr4umcMQO+v0THRooB+OtbXKsOsr6X6bj7OYrHFbzQbt8h0DO6ABUrFyarDUTUS2fYTO8OW2pRXfFB8E8Zk0/GS1uDYR7oVepRYfbqABCzNSSPE91BMVw==;24:ejHADV/oblmM5DiFM/Xoi7NdYF3rC4bycovz7ZDFpK3l26AvU2osqM4KgowJXYxndsxs0kkBT0h7b0la+wB07ew4HKwVYJgoY6eDjJL9Mx0=;7:8kET+OeEXj7LtOw2ZEgKwJPxxnp8FjG9jP5rk2CleCzwsITZp+4Ygb5HNE60TJgAFpZL6EByRyHZKrSrCtlAeIHDbzvF+PIvjNfSg+sO0Zve1S0k/pmpYbYisxFYpZo9keDj2uzO73icAMzKe+Dzor6PVeTQxnoxUF7aCcSs10G6sSUx8ukrv9Rw9kXCbT8+NaD2ul2h5YlSQdENlmu/AA==;20:Cej9UotQ2w8moEkb0Jn1dkzn2d1Ps7y3qHJTJ86lq1TxlCiqVDxq+Np6a6jGThcDJUlfeuMixvoNcqP4VwhsgBIyG0/ZcOK/GcbKefCRE5FGCMNtmPPFoP7I+C6FReSKbikOEEYyooP9pkNuFM+sMdUbcLIXIJJwblz9N8drzPA= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR11MB0315; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(6040130)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6041072)(6043046);SRVR:CY1PR11MB0315;BCL:0;PCL:0;RULEID:;SRVR:CY1PR11MB0315; x-forefront-prvs: 09749A275C x-forefront-antispam-report: SFV:NSPM;SFS:(10019020)(6009001)(7916002)(24454002)(199003)(189002)(99286002)(66066001)(82746002)(4326007)(122556002)(86362001)(83716003)(2906002)(106116001)(105586002)(19300405004)(586003)(106356001)(11100500001)(102836003)(3846002)(10400500002)(8936002)(19580405001)(36756003)(77096005)(5002640100001)(19580395003)(76176999)(54356999)(2950100001)(189998001)(87936001)(15975445007)(33656002)(5004730100002)(3280700002)(93886004)(101416001)(5008740100001)(92566002)(81166006)(110136002)(2900100001)(6116002)(3660700001)(50986999)(97736004)(8676002)(81156014)(68736007)(562404015)(104396002);DIR:OUT;SFP:1102;SCL:1;SRVR:CY1PR11MB0315;H:CY1PR11MB0316.namprd11.prod.outlook.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;CAT:NONE;LANG:en;CAT:NONE; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: MIME-Version: 1.0 X-OriginatorOrg: primarydata.com X-MS-Exchange-CrossTenant-originalarrivaltime: 15 Jun 2016 15:45:37.7057 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 03193ed6-8726-4bb3-a832-18ab0d28adb7 X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR11MB0315 X-MC-Unique: 1XnrxGcNP9mBbn6bUAF7UQ-1 Content-Type: multipart/alternative; boundary="MCBoundary=_11606151145415551" X-Barracuda-Connect: us-smtp-delivery-194.mimecast.com[63.128.21.194] X-Barracuda-Start-Time: 1466005543 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4255 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30457 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --MCBoundary=_11606151145415551 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: base64 DQoNCk9uIDYvMTUvMTYsIDExOjE0LCAiQ2hyaXN0b3BoIEhlbGx3aWciIDxoY2hAaW5mcmFkZWFk Lm9yZz4gd3JvdGU6DQoNCj5PbiBXZWQsIEp1biAxNSwgMjAxNiBhdCAwMzowOToyM1BNICswMDAw LCBUcm9uZCBNeWtsZWJ1c3Qgd3JvdGU6DQo+PiBBcyBJIHNhaWQgZWFybGllciwgdGhlIHByb2Js ZW0gd2l0aCB0aGF0IGlzIHlvdSBlbmQgdXAgYXJ0aWZpY2lhbGx5IHNlcmlhbGlzaW5nIGJ1ZmZl cmVkIHJlYWRzIGFuZCBidWZmZXJlZCB3cml0ZXMuDQo+DQo+SWYgeW91IGFjdHVhbGx5IHdhbnQg dG8gYmUgUG9zaXggY29tcGlhbnQgeW91IG5lZWQgdG8gc2VyaWFsaXplIGJ1ZmZlcmVkDQo+cmVh ZHMgYWdhaW5zdCBidWZmZXJlcmQgd3JpdGVzIC0gaXQncyBqdXN0IHRoYXQgbW9zdCBMaW51eCBm aWxlIHN5c3RlbXMNCj5oYXBwZW4gdG8gZ2V0IHRoaXMgd3JvbmcuDQo+DQo+PiA/Pz8gVGhlIHJl YWRzIG9ubHkgbmVlZCBhIHNoYXJlZCBsb2NrIGluIG9yZGVyIHRvIHByb3RlY3QgdGhlIEkvTyBt b2RlIGZyb20gZmxpcHBpbmcgdG8gT19ESVJFQ1QgKGFuZCByZWx5aW5nIG9uIHBhZ2UgbG9ja3Mg dG8gcHJvdGVjdCBhZ2FpbnN0IGJ1ZmZlcmVkIHdyaXRlcykuDQo+DQo+V2hpY2ggc3RyaWN0bHkg c3BlYWtpbmcgaXMgbm90IGVub3VnaCwgYWx0aG91Z2ggYXMgc2FpZCBhYm92ZSBtb3N0DQo+TGlu dXggZmlsZXN5c3RlbXMgZ2V0IHRoaXMgd3JvbmcuICBJZiB5b3UgaW5kZWVkIHdhbnQgdG8ga2Vl cCB0aGF0DQo+KGluY29ycmVjdCkgYmVoYXZpb3IgeW91IG5lZWQgYW5vdGhlciBsb2NrLiAgSXQn cyBkZWZpbnRpdmVseSBub3QNCj4ic2ltcGxlciIsIHRob3VnaC4NCj4NCg0KU2VyaWFsaXNhdGlv biBpcyBub3QgbWFuZGF0b3J5IGluIFBPU0lYOg0KDQpodHRwOi8vcHVicy5vcGVuZ3JvdXAub3Jn L29ubGluZXB1YnMvOTY5OTkxOTc5OS9mdW5jdGlvbnMvd3JpdGUuaHRtbA0KDQrigJxXcml0ZXMg Y2FuIGJlIHNlcmlhbGl6ZWQgd2l0aCByZXNwZWN0IHRvIG90aGVyIHJlYWRzIGFuZCB3cml0ZXMu IElmIGEgcmVhZCgpIG9mIGZpbGUgZGF0YSBjYW4gYmUgcHJvdmVuIChieSBhbnkgbWVhbnMpIHRv IG9jY3VyIGFmdGVyIGEgd3JpdGUoKSBvZiB0aGUgZGF0YSwgaXQgbXVzdCByZWZsZWN0IHRoYXQg d3JpdGUoKSwgZXZlbiBpZiB0aGUgY2FsbHMgYXJlIG1hZGUgYnkgZGlmZmVyZW50IHByb2Nlc3Nl cy4gQSBzaW1pbGFyIHJlcXVpcmVtZW50IGFwcGxpZXMgdG8gbXVsdGlwbGUgd3JpdGUgb3BlcmF0 aW9ucyB0byB0aGUgc2FtZSBmaWxlIHBvc2l0aW9uLiBUaGlzIGlzIG5lZWRlZCB0byBndWFyYW50 ZWUgdGhlIHByb3BhZ2F0aW9uIG9mIGRhdGEgZnJvbSB3cml0ZSgpIGNhbGxzIHRvIHN1YnNlcXVl bnQgcmVhZCgpIGNhbGxzLiBUaGlzIHJlcXVpcmVtZW50IGlzIHBhcnRpY3VsYXJseSBzaWduaWZp Y2FudCBmb3IgbmV0d29ya2VkIGZpbGUgc3lzdGVtcywgd2hlcmUgc29tZSBjYWNoaW5nIHNjaGVt ZXMgdmlvbGF0ZSB0aGVzZSBzZW1hbnRpY3Mu4oCdDQoNCkRpc2NsYWltZXINCg0KVGhlIGluZm9y bWF0aW9uIGNvbnRhaW5lZCBpbiB0aGlzIGNvbW11bmljYXRpb24gZnJvbSB0aGUgc2VuZGVyIGlz IGNvbmZpZGVudGlhbC4gSXQgaXMgaW50ZW5kZWQgc29sZWx5IGZvciB1c2UgYnkgdGhlIHJlY2lw aWVudCBhbmQgb3RoZXJzIGF1dGhvcml6ZWQgdG8gcmVjZWl2ZSBpdC4gSWYgeW91IGFyZSBub3Qg dGhlIHJlY2lwaWVudCwgeW91IGFyZSBoZXJlYnkgbm90aWZpZWQgdGhhdCBhbnkgZGlzY2xvc3Vy ZSwgY29weWluZywgZGlzdHJpYnV0aW9uIG9yIHRha2luZyBhY3Rpb24gaW4gcmVsYXRpb24gb2Yg dGhlIGNvbnRlbnRzIG9mIHRoaXMgaW5mb3JtYXRpb24gaXMgc3RyaWN0bHkgcHJvaGliaXRlZCBh bmQgbWF5IGJlIHVubGF3ZnVsLg0K --MCBoundary=_11606151145415551 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=UTF-8

On 6/15/16, 11:14, "Christoph Hellwig" <hch@infradead.org> = wrote:

>On Wed, Jun 15, 2016 at 03:09:23PM +0000, Trond Myklebust wrote:
>> As I said earlier, the problem with that is you end up artificiall= y serialising buffered reads and buffered writes.
>
>If you actually want to be Posix compiant you need to serialize buffere= d
>reads against buffererd writes - it's just that most Linux file systems=
>happen to get this wrong.
>
>> ??? The reads only need a shared lock in order to protect the I/O = mode from flipping to O_DIRECT (and relying on page locks to protect agains= t buffered writes).
>
>Which strictly speaking is not enough, although as said above most
>Linux filesystems get this wrong. If you indeed want to keep that
>(incorrect) behavior you need another lock. It's defintively not
>"simpler", though.
>

Serialisation is not mandatory in POSIX:

http://pubs.opengroup.org/onlinepubs/9699919799/fun= ctions/write.html

=E2=80=9CWrites can be serialized with respect to other reads and writes. I= f a read() of file data can be proven (by any means) to occur after a write= () of the data, it must reflect that write(), even if the calls are made by= different processes. A similar requirement applies to multiple write opera= tions to the same file position. This is needed to guarantee the propagatio= n of data from write() calls to subsequent read() calls. This requirement i= s particularly significant for networked file systems, where some caching s= chemes violate these semantics.=E2=80=9D


Disclaimer

The information contained in this communication from the send= er is confidential. It is intended solely for use by the recipient and othe= rs authorized to receive it. If you are not the recipient, you are hereby n= otified that any disclosure, copying, distribution or taking action in rela= tion of the contents of this information is strictly prohibited and may be = unlawful.

--MCBoundary=_11606151145415551-- From waiman.long@hpe.com Wed Jun 15 13:55:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8E99B7CA2 for ; Wed, 15 Jun 2016 13:55:44 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id EEAD6AC002 for ; Wed, 15 Jun 2016 11:55:43 -0700 (PDT) X-ASG-Debug-ID: 1466016936-04cbb01fec2ad90001-NocioJ Received: from na01-bl2-obe.outbound.protection.outlook.com (mail-bl2on0146.outbound.protection.outlook.com [65.55.169.146]) by cuda.sgi.com with ESMTP id Fo4YBGNJm2jr3wgE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for ; Wed, 15 Jun 2016 11:55:37 -0700 (PDT) X-Barracuda-Envelope-From: waiman.long@hpe.com X-Barracuda-Effective-Source-IP: mail-bl2on0146.outbound.protection.outlook.com[65.55.169.146] X-Barracuda-Apparent-Source-IP: 65.55.169.146 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=waiman.long@hpe.com; Received: from [192.168.142.154] (71.168.64.62) by CS1PR84MB0312.NAMPRD84.PROD.OUTLOOK.COM (10.162.190.30) with Microsoft SMTP Server (TLS) id 15.1.511.8; Wed, 15 Jun 2016 18:55:21 +0000 Message-ID: <5761A48F.1040304@hpe.com> Date: Wed, 15 Jun 2016 14:55:11 -0400 From: Waiman Long User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:10.0.12) Gecko/20130109 Thunderbird/10.0.12 MIME-Version: 1.0 To: Dave Chinner CC: Peter Zijlstra , Ingo Molnar , , , , , , , , Davidlohr Bueso , Jason Low , Scott J Norton , Douglas Hatch Subject: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes References: <1465927959-39719-1-git-send-email-Waiman.Long@hpe.com> <1465927959-39719-7-git-send-email-Waiman.Long@hpe.com> <20160614230613.GB26977@dastard> X-ASG-Orig-Subj: Re: [RFC PATCH-tip 6/6] xfs: Enable reader optimistic spinning for DAX inodes In-Reply-To: <20160614230613.GB26977@dastard> Content-Type: text/plain; charset="ISO-8859-1"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [71.168.64.62] X-ClientProxiedBy: CY1PR13CA0017.namprd13.prod.outlook.com (10.162.30.155) To CS1PR84MB0312.NAMPRD84.PROD.OUTLOOK.COM (10.162.190.30) X-MS-Office365-Filtering-Correlation-Id: 4170719c-4d97-4954-1dd1-08d3954e9e1d X-Microsoft-Exchange-Diagnostics: 1;CS1PR84MB0312;2:7dhYYKCIvnXQJtANH/VfmrmevCPrIqjzVG2l4wXtNOunkOhiSfJe7upikgvP88OqI0A/AUie/aTmZq2tZgrH2AMcmMoka6Az8WfeA6TC+XJWp6YCF73qZf+1lj1uAwl2oEfbOxO5I88OT8OiWMRIS1Qm9UtmQi3fDcEVCtJGJetlOL7SLQjNBwuXT0ShhWhc;3:n7j3liX9p9FxNKKCzFRPd8gtTf0bFo0IBp2LcqnGVZaY4dN9hbrmjbC+FC6c4A4JAVPM6kWG2nVSSbTgeW35UmytjCQSuKA1aHttyPCJqHqY55d3kLss9LHeSLVYIvYd X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CS1PR84MB0312; X-Microsoft-Exchange-Diagnostics: 1;CS1PR84MB0312;25:TFMTD87Z8HTSfzzNNsZZ/hb8ITblGUvuQxIG7Uu9TTJL3ZD1m5Vg63HEhnyqikse1ULu0iiZ/YTKvqQ3XEiyK+drBmbo4jj0Iy+iaeywrNbE4BT9z+yspUq7FnodlDVeWv9TJUjk5xmrWIAybUL/XSrpxv9/CmEqSG5u2YcPm5HqjJ7Q9evlDmm3pFBFebEy/HfHq9/+JETkK9rTWCThP2N/KOLU8we69ADxnFF598tmvjx/w2uZk8o9SMERPsMSy1GclPSxJGHesRgB+158yHXGQ6/UCklS7g8u6gTq9K260QkfN2GPN0soCMhoguZ5ENVH5PiyZ6j1wb1AWMybGZRxF1Z/rf7ffbHoLWJADu7IponKI83noBCtA1uMUt21n7nxAfayBI4E3+SERwTUxsYLyLhWD+9s36uj7Rp3Bh76zu4qVxkE+QJWLJaCfuxwNhAmmL8Et22uqff4e4nt4oj1ofR2NXNVtIwYSxO8140e5FLc5CMIOnxzLm3dSeH7mtitVWYFWBPpeVb2ru5E+py8+XDMgJql71pwGCBkK9ybF2SGeiMPwX3H4816pdAB133xc88J/lRdNZdgsj8DDpeoWT4y0j7JndfdR5zoUI/U1JvqjZZIflPwCV40ZwXLPsP7FPT/9yXFDQztAwCZRMS1fObIQ3YWy1pA0++nHfqhQLWXXC+BMT+SYmhj81+J1/HhCWi9tF6dNy+3wCsrtFUtubfIAprmSFoirfytgtZa/XWupm5sitIg8MwNnqr2 X-Microsoft-Exchange-Diagnostics: 1;CS1PR84MB0312;20:QTU0mk5Fn+SzjtUYBu29Cs0jKoeh+eXmtD8jJK30C6FJEXVsbFzHGsQsCmU1g6iskhzZV0SVmIZR4/5+Ct/A0Pb9RPJTmPCRA0d9eN7FukJH/7JmQ5D5kIW73B/CzVEs0jqfTIyD/JGO7Nrf/rF3R/vBG/RY4tYj3SmIH+8BMuz22AQDkIDJVi6YlZuX5Tc8A6cUKmSwBCbjkL6rwXEL4vLqECNjCkPASA5HIK325T8+dUppDsy7QouDOMXImoZaIsR+VOMuAp1u6/FrWrezf4j85PsCjv4JXm33dOPZ95k2kznIDcVq9pDB9p4xOVJqOmX81G3538Fcw9EXQwIwvafTdrNZVYr0DT0ZxkuESqOSZNhUqC5B/wBqwcYlCVTw/nwb+laFVZJGtprC191S32bQzSwdAbl2hUASIMPDOqXfdUBYnKIoSTtaoniitJpQC91B+mfa5kXIJpaEHexNUI5wDx+bu5EL66XteGEZQ/wivj6gge7decI1kD3QrxW1 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(227479698468861)(17755550239193); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(601004)(2401047)(5005006)(8121501046)(3002001)(10201501046);SRVR:CS1PR84MB0312;BCL:0;PCL:0;RULEID:;SRVR:CS1PR84MB0312; X-Microsoft-Exchange-Diagnostics: 1;CS1PR84MB0312;4:XSzoqwZvRtYioPxq4+DCKyLrC+Ua4o4bnosGaq8ccdgTICFpWZQahurl/yMUFH5GNzPTNuAyzV3QEM9YlrRnAyGmlmX4y/UO6waRZOOM/+XaS2Qn73KSwYI87pQNg8RO1BbxZ0X2dyoAxjPEIG0uR8+qODwbTTTUHH30EV9yVo+7659/bY1v/oFguYfjSjKFdcphlHy4odT35/QbWD4mfSwGTf+yKYHuiFk4pbxToYmRHDXBWVW9OQ3fwYHavwh5Bwg65oXwG0rnyAXbRLkmPtV+cnAkg5mnyToBIs25IR6EgvZl0UjcbX0wF9yDfttmBrRhcPGrp7q09Vfu0so9VDexHFE8g+buUvhgHtiSvbnn6++3O8WmO9ZNM8ZNfH+df5iseiRLyWaIIbWdGWC6JcCw00VG8sGLwDGys860jSS7RQ6ddUV5CEhbGTvFMiS4P1K3M5EWylX9PMRnjThTvA== X-Forefront-PRVS: 09749A275C X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10019020)(4630300001)(6049001)(6009001)(7916002)(24454002)(377454003)(199003)(189002)(106356001)(59896002)(189998001)(101416001)(5008740100001)(92566002)(5004730100002)(86362001)(19580395003)(117156001)(65956001)(19580405001)(80316001)(2950100001)(47776003)(77096005)(42186005)(33656002)(83506001)(23756003)(105586002)(50466002)(64126003)(65816999)(87266999)(65806001)(2906002)(36756003)(4326007)(230700001)(3846002)(586003)(110136002)(81156014)(81166006)(66066001)(6116002)(8676002)(76176999)(8666005)(68736007)(4001350100001)(50986999)(54356999)(97736004)(7059030);DIR:OUT;SFP:1102;SCL:1;SRVR:CS1PR84MB0312;H:[192.168.142.154];FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; Received-SPF: None (protection.outlook.com: hpe.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?iso-8859-1?Q?1;CS1PR84MB0312;23:htHS4A9Og3HZxly1nezkl8L4/WJ26kcDI0G4TxQ?= =?iso-8859-1?Q?cU9Kx8sI3omy4MczEFkolpyruGJryndSpN2wAmJmzSJ7oRSIfxHB70UBMS?= =?iso-8859-1?Q?evYVtDhv6MaO6apBsbg66vw1VxSBD5Xz2hOS8y82HaitCSK9dD54bbYixx?= =?iso-8859-1?Q?TSTH4AqdfKtzuSt4crDY+SJi+wPZc9m4Y79rWhFHVwVv52YtwPEfryq9U2?= =?iso-8859-1?Q?vr9dgdCBI3QbYz2OmtYji+/eSzu+heXEOkjAxWGUMVuhy7Yif8Th2PuW0b?= =?iso-8859-1?Q?QkBjvd2nkY8OvwmIz6OiEYkL+Dgn95N7rDAUHo2Pt6v/BFworYCsDAUbFE?= =?iso-8859-1?Q?FqsUiJf+4kHj5bjmS+7PGoJ/1mqklnlZn6vg2u+839xNvXMH3LRZn0qqTi?= =?iso-8859-1?Q?aYIw6zTeGOrHaUFQsPy7WomUmvon+q0ThpVuJYBGw7CvNi4hWAx3yordG2?= =?iso-8859-1?Q?zXLBtB63UG3Gm/eryKlqQiosf15VLIHso5cXI0xU0I2JzGbr9eVVfJPx6C?= =?iso-8859-1?Q?qgAfMZxDRDSCUOfycs3MgmQD3GXTVNqe74qeheNeZkVz9PvKwiK4hDu8mp?= =?iso-8859-1?Q?/RWBGBBNfH8WVWlqbm91YYtP4xITl8t+SOrQb7vYm1O0qPd3pU+oF5ldrn?= =?iso-8859-1?Q?O3WMVxKKebNvTPWOmlP0m/Kz5isoTPNKnQBlh4JFsv1VOPrGiifNpLwWIx?= =?iso-8859-1?Q?R1uoV69jdFb1VnOz2tB3lfNxYISLa9NS7KKPuly60LhPGxqJevtlhDdsY+?= =?iso-8859-1?Q?W9DSXS7xSMFskqcR+uzo2UcK3/5ojMseMd38l/lCB1TzebWgh1y+L7vtFq?= =?iso-8859-1?Q?2mCyuCPt2cQFd91M2D0YWurNeBlZlTLf7zWPXjpOEfBNEz29fDHi/C9U9q?= =?iso-8859-1?Q?/GwRlOHwGy7E3HWriTco32x4WPYRNvMxHcWcanLB/951dTYUvSupObuOeE?= =?iso-8859-1?Q?SbwBIm2q3DjNsMmyDXID2FmzgclYwNrlI0mbzX4T701ADTqJkMbQj6xdhi?= =?iso-8859-1?Q?y2SAo9vVLprxGrMgNLX+0Ln9slD+9L17eKkj112W//RDpDi/d79UDyYBoO?= =?iso-8859-1?Q?S4uFD91WAr1CCKmEoyQBu+Ut4NpOmjqTgrmL2WwMT1/F9zu1mDqzjjutE1?= =?iso-8859-1?Q?mfFSJqe7BQvJln7mGqbfMQD1GM4ALYFN8r4V60Oi/uVMfbf14XGMCH0QEC?= =?iso-8859-1?Q?NmlZDnZGfDCmCdN1RY3VCNljaVynkWYynpn3UIvJOIhCmoEyZdRmXIySse?= =?iso-8859-1?Q?OB57V7zXDVDoEBy0J0fcHp7cmBENUQN08LU/5kedEYl92lHU5U8roOPsuO?= =?iso-8859-1?Q?NAPBrpC1yP0ZsTyNl+pv5KECBSWMCYl34jrnubWEHblMWoUds6UMalmR5x?= =?iso-8859-1?Q?Vc+nco4/XHiXDFu/mn3alzz/mDPF9+aNcJPwdjlGqT8jkGtG9Fg=3D=3D?= X-Microsoft-Exchange-Diagnostics: 1;CS1PR84MB0312;5:WpM1b+6OStF7ytnKQ3blIAz3TsmBGBq8eoM6X7Quo5M/eWe4FV3CHpuSqRESdSbtzM6xWCQZHn4odZsqRxjXINclwYeCrBh//5I06f9BlXzMbs8VNep0hLwYd07Ony8BVkXAAI6K7K1/3Dy3fGJ2pQ==;24:Av3fMJzQRzdHJYMg3O20QpdEzPW1joCBqXCSx3Gct7jbuDSHFzW2lX2LLxNMu2KYH/zFk9hQa57KfugWOR13OxTn1j84AvaAHGtRWo7+quM=;7:Ev6WVPmnQrAly1j6wa7hGsdJ/4bcbaDDOaVe4OCF5syOqBOUwfdVZafbTlZ8jo9ryK25kY2jnBZA+szMEFCnvKq+Sd5lFj3EDACyx+fnlLeB+O2EoOShYQZl3rGKD/lXfmzydf6ni+sF6yutoe9tX16K1c5e56rGxLyxygaUTn/VyD/pMEGxskkPZkOAE7nS7+d4m1/b7+xeDRUYQNJ0w21P4eIoLDA6N98yEgROEFE= SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: hpe.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 Jun 2016 18:55:21.1909 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: CS1PR84MB0312 X-Barracuda-Connect: mail-bl2on0146.outbound.protection.outlook.com[65.55.169.146] X-Barracuda-Start-Time: 1466016937 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2748 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30462 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/14/2016 07:06 PM, Dave Chinner wrote: > On Tue, Jun 14, 2016 at 02:12:39PM -0400, Waiman Long wrote: >> This patch enables reader optimistic spinning for inodes that are >> under a DAX-based mount point. >> >> On a 4-socket Haswell machine running on a 4.7-rc1 tip-based kernel, >> the fio test with multithreaded randrw and randwrite tests on the >> same file on a XFS partition on top of a NVDIMM with DAX were run, >> the aggregated bandwidths before and after the patch were as follows: >> >> Test BW before patch BW after patch % change >> ---- --------------- -------------- -------- >> randrw 1352 MB/s 2164 MB/s +60% >> randwrite 1710 MB/s 2550 MB/s +49% >> >> Signed-off-by: Waiman Long >> --- >> fs/xfs/xfs_icache.c | 9 +++++++++ >> 1 files changed, 9 insertions(+), 0 deletions(-) >> >> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c >> index 99ee6ee..09f284f 100644 >> --- a/fs/xfs/xfs_icache.c >> +++ b/fs/xfs/xfs_icache.c >> @@ -71,6 +71,15 @@ xfs_inode_alloc( >> >> mrlock_init(&ip->i_iolock, MRLOCK_BARRIER, "xfsio", ip->i_ino); >> >> + /* >> + * Enable reader spinning for DAX nount point >> + */ >> + if (mp->m_flags& XFS_MOUNT_DAX) { >> + rwsem_set_rspin_threshold(&ip->i_iolock.mr_lock); >> + rwsem_set_rspin_threshold(&ip->i_mmaplock.mr_lock); >> + rwsem_set_rspin_threshold(&ip->i_lock.mr_lock); >> + } > That's wrong. DAX is a per-inode flag, not a mount wide flag. This > needs to be done once the inode has been fully initialised and > IS_DAX(inode) can be run. > > Also, the benchmark doesn't show that all these locks are being > tested by this benchmark. e.g. the i_mmaplock isn't involved in > the benchmark's IO paths at all. It's only taken in page faults and > truncate paths.... > > I'd also like to see how much of the gain comes from the iolock vs > the ilock, as the ilock is nested inside the iolock and so > contention is much rarer.... This patch has now been superseded by a second one where changes to the xfs code is no longer needed. The new patch will enable reader spinning for all rwsem and dynamically disable it depending on past history. > As it is, I'm *extremely* paranoid when it comes to changes to core > locking like this. Performance is secondary to correctness, and we > need much more than just a few benchmarks to verify there aren't > locking bugs being introduced.... The core rwsem locking logic hasn't been changed. There are some minor changes, however, on what RWSEM_WAITING_BIAS value to use that requires more eyeballs to make sure that it hasn't introduced any new bug. Cheers, Longman From BATV+d68c80116f0bf241093e+4680+infradead.org+hch@bombadil.srs.infradead.org Thu Jun 16 04:12:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id F32C87CA2 for ; Thu, 16 Jun 2016 04:12:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id C65BD8F804B for ; Thu, 16 Jun 2016 02:12:47 -0700 (PDT) X-ASG-Debug-ID: 1466068364-04cb6c5424392e0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id Tg1wNV6NITmBzMue (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 16 Jun 2016 02:12:44 -0700 (PDT) X-Barracuda-Envelope-From: BATV+d68c80116f0bf241093e+4680+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDTLu-0002sl-11; Thu, 16 Jun 2016 09:12:42 +0000 Date: Thu, 16 Jun 2016 02:12:41 -0700 From: Christoph Hellwig To: Trond Myklebust Cc: Christoph Hellwig , "linux-nfs@vger.kernel.org" , "xfs@oss.sgi.com" Subject: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes Message-ID: <20160616091241.GA15953@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 10/12] NFS: Do not serialise O_DIRECT reads and writes References: <1465931115-30784-9-git-send-email-trond.myklebust@primarydata.com> <1465931115-30784-10-git-send-email-trond.myklebust@primarydata.com> <20160615071343.GC4318@infradead.org> <755A2A14-C6A9-4737-8335-0A6785490F6D@primarydata.com> <20160615144801.GB18524@infradead.org> <20160615145638.GC5297@infradead.org> <02DCF6B5-AFDF-4E33-A8F2-DBFE67A87E91@primarydata.com> <20160615151422.GA28557@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466068364 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2636 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30484 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 15, 2016 at 03:45:37PM +0000, Trond Myklebust wrote: > Serialisation is not mandatory in POSIX: > > http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html > > ???Writes can be serialized with respect to other reads and writes. If a read() of file data can be proven (by any means) to occur after a write() of the data, it must reflect that write(), even if the calls are made by different processes. A similar requirement applies to multiple write operations to the same file position. This is needed to guarantee the propagation of data from write() calls to subsequent read() calls. This requirement is particularly significant for networked file systems, where some caching schemes violate these semantics.??? That is the basic defintion, but once O_DSYNC and friends come into play it gets more complicated: >From http://pubs.opengroup.org/onlinepubs/9699919799/functions/read.html: [SIO] [Option Start] If the O_DSYNC and O_RSYNC bits have been set, read I/O operations on the file descriptor shall complete as defined by synchronized I/O data integrity completion. If the O_SYNC and O_RSYNC bits have been set, read I/O operations on the file descriptor shall complete as defined by synchronized I/O file integrity completion. [Option End] Which directs to: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html: 3.378 Synchronized I/O Data Integrity Completion For read, when the operation has been completed or diagnosed if unsuccessful. The read is complete only when an image of the data has been successfully transferred to the requesting process. If there were any pending write requests affecting the data to be read at the time that the synchronized read operation was requested, these write requests are successfully transferred prior to reading the data. For write, when the operation has been completed or diagnosed if unsuccessful. The write is complete only when the data specified in the write request is successfully transferred and all file system information required to retrieve the data is successfully transferred. File attributes that are not necessary for data retrieval (access time, modification time, status change time) need not be successfully transferred prior to returning to the calling process. While we'll never see O_RSYNC in the kernel glibc treats it as just O_SYNC. Either way - I'd be much happier if we could come up with less different ways to do read/write exclusion rather than more.. From zbvesa@gmail.com Thu Jun 16 05:14:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,HTML_MESSAGE, T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3EA727CA2 for ; Thu, 16 Jun 2016 05:14:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 106F9304032 for ; Thu, 16 Jun 2016 03:13:58 -0700 (PDT) X-ASG-Debug-ID: 1466072036-04cbb01fec484a0001-NocioJ Received: from mail-vk0-f67.google.com (mail-vk0-f67.google.com [209.85.213.67]) by cuda.sgi.com with ESMTP id kfjZc4TRBWAickTd (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Thu, 16 Jun 2016 03:13:56 -0700 (PDT) X-Barracuda-Envelope-From: zbvesa@gmail.com X-Barracuda-Effective-Source-IP: mail-vk0-f67.google.com[209.85.213.67] X-Barracuda-Apparent-Source-IP: 209.85.213.67 Received: by mail-vk0-f67.google.com with SMTP id k2so7437313vkb.0 for ; Thu, 16 Jun 2016 03:13:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=HhV2+wgjYKWMUNP12Gqmw73RhmH8a5xVqOHs7szTakI=; b=K4LZvHjTVFs1s4D9TMWKXDU+wEYdrIN/0ckUf5V11kqEPHTRYFrBWU0UwcLZtF/cAU BAfG8G+YViAPAJJyYMLh5NGA2qnqvmh0ugrtJ64n9OFjN97N2jI/BXo82ZmBxsPPJLUh /7/n1F+7aI3o3Cb6qgiIQ1vB2kbmAvH6lqUxzMO9HNKxl98NJUR+iuj/xm9zRVHKX1w/ aCoGmNOky6Ujc2vqlooJiSLiY0mQ/+b8mYEXnfcqW1bNC3D+ks2zDWqt8QCc2dKlIGgE pEO6wOkPqU+jnFmN9UUVeiXxb1OEtomnKCEBoQjDGKnOvf5wvM+5UPXCL80YeXiU2p+f 0K+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=HhV2+wgjYKWMUNP12Gqmw73RhmH8a5xVqOHs7szTakI=; b=hUsQhpwW6cBnNCEM1tUbdtSbtdX+lKJv4JqIMpOh8slHeVVkQgdjFVbUD3A9hQJC0x 3HMSN649TZT93PX/zRxod4fG8Huzuwsjd+TBasl3ahTbLiLBh9RySFP+yEAy1zMzHjfL ql69WGSiQmYaNuQ5GCuex+jfcpVN5+yNPjs5RroaRhYhKaRHxiNIsxh6iRsWXfYqAcQc D9ysWNk2pRAYi1NrI3HMlrFimyqeBJixPU+RkI8TOovi41hnHBnP0vVpmIqDTr5cXpp6 ZlSnrXK3QJtoxuAlsokweASb6BUgLAHYSDedLe9n3rvHRvwvY8UDyzE1mHNimCOquY+h rXtQ== X-Gm-Message-State: ALyK8tJ9RVsiMldYf0WUUr3wK93IlT4o8wFnKMTg4mLt5tO9mdmI4yj6Kl+83CcpzMF+za9YoPMU3mDgHMPKYg== X-Received: by 10.159.35.72 with SMTP id 66mr1717332uae.55.1466072035749; Thu, 16 Jun 2016 03:13:55 -0700 (PDT) MIME-Version: 1.0 Received: by 10.31.16.36 with HTTP; Thu, 16 Jun 2016 03:13:55 -0700 (PDT) From: Shi Summer Date: Thu, 16 Jun 2016 18:13:55 +0800 Message-ID: Subject: Premium Grade A 11 Oz. White Sublimation Mugs To: zubaidahsabran@gmail.com, zonerouge@montrealalouettes.com, zapatayavonne@gmail.com, zamzamimpex@hotmail.com, zakup@poltronic.eu, zahran2371@yahoo.com.tq, zafikeloanfirm88@gmail.com, yolandaanimo225@hotmail.com, Yolanda926@outlook.com, Yolanda@hai-di.com, yevmar@gmail.com, yanielncc@gmail.com, yanie_lncc88@gmail.com, yahyayavas@hotmail.com, xytota14@yahoo.com, xytota@yahoo.com, xytota@gmail.com, xuan@ipcgifts.com, xtarantulz@mail.ru, xfs@oss.sgi.com, xcopyfullerton@gmail.com, wzincker@hotmail.com, wwisewin@gmail.com, wuc4371@gmail.com X-ASG-Orig-Subj: Premium Grade A 11 Oz. White Sublimation Mugs Content-Type: multipart/alternative; boundary=001a11353092e7f6200535627ebe X-Barracuda-Connect: mail-vk0-f67.google.com[209.85.213.67] X-Barracuda-Start-Time: 1466072036 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 564 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_DOMAIN_MATCH, DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30485 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message 0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient Domain --001a11353092e7f6200535627ebe Content-Type: text/plain; charset=UTF-8 Dear friends, Glad to hear that you are on the market for sublimation mugs and sublimation printing. We are the manufacturer of the items, we can supply high quality and competitive price. kindly contact me if any questions. Best regards, Summer --001a11353092e7f6200535627ebe Content-Type: text/html; charset=UTF-8

Dear friends,
Glad to hear that you are on the market for sublimation mugs and sublimation printing.
We are the manufacturer of the items, we can supply high quality and competitive price.
kindly contact me if any questions.

Best regards,

Summer

--001a11353092e7f6200535627ebe-- From jack@suse.cz Thu Jun 16 11:12:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D9DD17CA2 for ; Thu, 16 Jun 2016 11:12:51 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 9B8E9304032 for ; Thu, 16 Jun 2016 09:12:48 -0700 (PDT) X-ASG-Debug-ID: 1466093564-04bdf01e1587f10001-NocioJ Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by cuda.sgi.com with ESMTP id TnPQilSQ6Twb7D0a (version=TLSv1 cipher=ECDHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 16 Jun 2016 09:12:45 -0700 (PDT) X-Barracuda-Envelope-From: jack@suse.cz X-Barracuda-Effective-Source-IP: mx2.suse.de[195.135.220.15] X-Barracuda-Apparent-Source-IP: 195.135.220.15 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id 851E8AC1B; Thu, 16 Jun 2016 16:12:43 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id 019481E0DE6; Thu, 16 Jun 2016 18:12:42 +0200 (CEST) Date: Thu, 16 Jun 2016 18:12:42 +0200 From: Jan Kara To: Christoph Hellwig Cc: xfs@oss.sgi.com, rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: [PATCH 02/14] fs: introduce iomap infrastructure Message-ID: <20160616161242.GB2106@quack2.suse.cz> X-ASG-Orig-Subj: Re: [PATCH 02/14] fs: introduce iomap infrastructure References: <1464792297-13185-1-git-send-email-hch@lst.de> <1464792297-13185-3-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1464792297-13185-3-git-send-email-hch@lst.de> User-Agent: Mutt/1.5.24 (2015-08-30) X-Barracuda-Connect: mx2.suse.de[195.135.220.15] X-Barracuda-Start-Time: 1466093565 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1778 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30491 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed 01-06-16 16:44:45, Christoph Hellwig wrote: > Add infrastructure for multipage buffered writes. This is implemented > using an main iterator that applies an actor function to a range that > can be written. > > This infrastucture is used to implement a buffered write helper, one > to zero file ranges and one to implement the ->page_mkwrite VM > operations. All of them borrow a fair amount of code from fs/buffers. > for now by using an internal version of __block_write_begin that > gets passed an iomap and builds the corresponding buffer head. > > The file system is gets a set of paired ->iomap_begin and ->iomap_end > calls which allow it to map/reserve a range and get a notification > once the write code is finished with it. > > Based on earlier code from Dave Chinner. > > Signed-off-by: Christoph Hellwig > Reviewed-by: Bob Peterson When reading through the patch I've noticed two minor errors in the comments: ... > +static loff_t > +iomap_apply(struct inode *inode, loff_t pos, loff_t length, unsigned flags, > + struct iomap_ops *ops, void *data, iomap_actor_t actor) > +{ > + struct iomap iomap = { 0 }; > + loff_t written = 0, ret; > + > + /* > + * Need to map a range from start position for count bytes. This can ^^^^ length ... > struct iomap { > - sector_t blkno; /* first sector of mapping */ > - loff_t offset; /* file offset of mapping, bytes */ > - u64 length; /* length of mapping, bytes */ > - int type; /* type of mapping */ > + sector_t blkno; /* first sector of mapping, fs blocks */ This is actually in 512-byte units, not in fs blocks as the comment suggests, right? Honza -- Jan Kara SUSE Labs, CR From Benjamin.Wirth@winmagic.com Thu Jun 16 14:57:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2B8CA7CA2 for ; Thu, 16 Jun 2016 14:57:45 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id F1B4E30404E for ; Thu, 16 Jun 2016 12:57:41 -0700 (PDT) X-ASG-Debug-ID: 1466107058-04cb6c54244f6d0001-NocioJ Received: from mail1.bemta8.messagelabs.com (mail1.bemta8.messagelabs.com [216.82.243.206]) by cuda.sgi.com with ESMTP id EwGoRCJWqeKL4HY2 for ; Thu, 16 Jun 2016 12:57:39 -0700 (PDT) X-Barracuda-Envelope-From: Benjamin.Wirth@winmagic.com X-Barracuda-Effective-Source-IP: mail1.bemta8.messagelabs.com[216.82.243.206] X-Barracuda-Apparent-Source-IP: 216.82.243.206 Received: from [216.82.241.211] by server-14.bemta-8.messagelabs.com id 41/C9-11656-2B403675; Thu, 16 Jun 2016 19:57:38 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprCKsWRWlGSWpSXmKPExsWSocJ5SXcTS3K 4wfkXIhZbjt1jtFjUd4vRgcnj1CIJj9UXtjIGMEWxZuYl5VcksGb0nehnLljKU/F83VK2BsaZ XF2MXBxCAtMZJc4//c0M4axjlNg4u5Wpi5GTg03ASKLl0Hl2EFtEQE1i0qQdzCA2s4C6xISpW 1hAbGEBO4k9jxazQtTYS7zfPZMFwnaTmPv2D9gcFgFVia4zp8F6eQWCJDZs28MEseweo8T3s6 vZQBKcAroSZ2ZDNDAKiEl8P7WGCWKZuMStJ/PBbAkBAYkle84zQ9iiEi8f/2OFsOUlGtuvs0P U60gs2P2JDcLWlli28DXUYkGJkzOfgB0nJKAhsW7LIajeYInVp5cyTmAUm4Vk3Swko2YhGTUL yagFjCyrGNWLU4vKUot0LfSSijLTM0pyEzNzdA0NLPRyU4uLE9NTcxKTivWS83M3MQJjiwEId jAebnY+xCjJwaQkyvvza1K4EF9SfkplRmJxRnxRaU5q8SFGGQ4OJQleT+bkcCHBotT01Iq0zB xglMOkJTh4lER4K0HSvMUFibnFmekQqVOMilLivGEgCQGQREZpHlwbLLFcYpSVEuZlBDpEiKc gtSg3swRV/hWjOAejkjDvdpApPJl5JXDTXwEtZgJabDM9HmRxSSJCSqqB0Vpveqt5yYQZya8M xEQl39oH7lMotjq0fOPt75YhZe8tZRr+SemHO1VzfZXgs3FaVa0Sqb9jifMq7U5my8fxV+UrL ORzbopr/WkT1xevEzO1TckpnGn4OeD4otdmHudviio/iJ6welZ3oOTDkOI9/+vC5s7e4T8v9+ 2dl/s2Z7y+fGGuX8JiJZbijERDLeai4kQAKK7AyicDAAA= X-Env-Sender: Benjamin.Wirth@winmagic.com X-Msg-Ref: server-6.tower-85.messagelabs.com!1466107058!33918083!1 X-Originating-IP: [104.36.9.210] X-StarScan-Received: X-StarScan-Version: 8.46; banners=-,-,- X-VirusChecked: Checked Received: (qmail 20892 invoked from network); 16 Jun 2016 19:57:38 -0000 Received: from 104-36-9-210.dedicated.allstream.net (HELO mail.winmagic.com) (104.36.9.210) by server-6.tower-85.messagelabs.com with SMTP; 16 Jun 2016 19:57:38 -0000 Received: from WMSEXCHSVR01.winmagic.local ([10.10.2.27]) by mail.winmagic.com with Microsoft SMTPSVC(6.0.3790.4675); Thu, 16 Jun 2016 15:57:37 -0400 Received: from WMSEXCHSVR02.winmagic.local ([fe80::4dad:19a5:fc50:6d9f]) by wmsexchsvr01.winmagic.local ([::1]) with mapi id 14.03.0266.001; Thu, 16 Jun 2016 15:57:37 -0400 From: Benjamin Wirth To: Dave Chinner CC: "xfs@oss.sgi.com" Subject: RE: development APIs for used/free blocks information Thread-Topic: development APIs for used/free blocks information X-ASG-Orig-Subj: RE: development APIs for used/free blocks information Thread-Index: AdGf/VxhHvG/iQ6eTkuDbtQDeeIgSAALiVKAABWxo1AAH2EYAAnB/Hgw Date: Thu, 16 Jun 2016 19:57:36 +0000 Message-ID: <97A4F433DEE099488FE21C1718A641D213A030CE@wmsexchsvr02.winmagic.local> References: <97A4F433DEE099488FE21C1718A641D2139E86F5@wmsexchsvr01.winmagic.local> <20160426222129.GD26977@dastard> <97A4F433DEE099488FE21C1718A641D2139E972E@wmsexchsvr01.winmagic.local> <20160427234108.GK26977@dastard> In-Reply-To: <20160427234108.GK26977@dastard> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.11.3.102] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-OriginalArrivalTime: 16 Jun 2016 19:57:37.0836 (UTC) FILETIME=[55181EC0:01D1C809] X-Barracuda-Connect: mail1.bemta8.messagelabs.com[216.82.243.206] X-Barracuda-Start-Time: 1466107058 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1583 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.62 X-Barracuda-Spam-Status: No, SCORE=0.62 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30498 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Hi David, I proceeded to parse the on-disk free blocks BTree for finding the free blo= cks information. Is there a way I could force a flush of BTree information = to disk, so that in an online filesystem that is being changed I can also h= andle the changes in the BTree? I was looking at XFS_FSOP_GOING_FLAGS_LOGFLUSH flag but it might do more th= en I need to do and actually shutdown the filesystem. Any other options? I = don't mind about performance degradation so interested in any option. Thanks, Ben -----Original Message----- From: Dave Chinner [mailto:david@fromorbit.com]=20 Sent: Wednesday, April 27, 2016 7:41 PM To: Benjamin Wirth Cc: xfs@oss.sgi.com Subject: Re: development APIs for used/free blocks information On Wed, Apr 27, 2016 at 12:54:24PM +0000, Benjamin Wirth wrote: > Hello Dave, >=20 > Thanks for your response. >=20 > And I apologize, reading back my email I wasn't clear about what I was=20 > looking for. >=20 > I want to be able to query which blocks are free or used, not just the=20 > counts. In EXT I was able to use ext2fs_test_block_bitmap() for that.=20 > XFS has a BTree with the free extents ordered by block number which I=20 > was hoping to be able to access from user-space, but couldn't find any=20 > APIs for it (or the headers containing the structure definitions) in=20 > the xfsprogs-devel package. Am I trying to do something impossible=20 > here? There are prototypes that need a bit of polishing to complete: http://oss.sgi.com/archives/xfs/2016-04/msg00633.html Cheers, Dave. -- Dave Chinner david@fromorbit.com From vishal.l.verma@intel.com Thu Jun 16 20:04:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 648C57CA2 for ; Thu, 16 Jun 2016 20:04:24 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 22F4530404E for ; Thu, 16 Jun 2016 18:04:24 -0700 (PDT) X-ASG-Debug-ID: 1466125460-04bdf01e1395270002-NocioJ Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by cuda.sgi.com with ESMTP id MdIuCFcwj52biRbR for ; Thu, 16 Jun 2016 18:04:22 -0700 (PDT) X-Barracuda-Envelope-From: vishal.l.verma@intel.com X-Barracuda-Effective-Source-IP: mga02.intel.com[134.134.136.20] X-Barracuda-Apparent-Source-IP: 134.134.136.20 X-ASG-Whitelist: Client Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 16 Jun 2016 18:04:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,481,1459839600"; d="scan'208";a="989197295" Received: from omniknight.lm.intel.com ([10.232.112.171]) by fmsmga001.fm.intel.com with ESMTP; 16 Jun 2016 18:04:22 -0700 From: Vishal Verma To: , Cc: Dave Chinner , Jan Kara , "Darrick J. Wong" , Vishal Verma Subject: [RFC PATCH 1/2] block, badblocks: add a notifier for badblocks Date: Thu, 16 Jun 2016 19:03:38 -0600 X-ASG-Orig-Subj: [RFC PATCH 1/2] block, badblocks: add a notifier for badblocks Message-Id: <1466125419-17736-2-git-send-email-vishal.l.verma@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> X-Barracuda-Connect: mga02.intel.com[134.134.136.20] X-Barracuda-Start-Time: 1466125460 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6094 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Filesystems with reverse mapping data may wish to do their own badblock checking if they can be more efficient. This lays the groundwork for that by providing a notifier in badblocks that such filesystems may subscribe to. The notification includes information for whether one or more badblocks were added or removed, the start sector of the operation, and the number of sectors affected. Cc: Darrick J. Wong Cc: Dave Chinner Signed-off-by: Vishal Verma --- block/badblocks.c | 79 +++++++++++++++++++++++++++++++++++++++++++++-- include/linux/badblocks.h | 19 ++++++++++++ 2 files changed, 95 insertions(+), 3 deletions(-) diff --git a/block/badblocks.c b/block/badblocks.c index 7be53cb..f7cfece 100644 --- a/block/badblocks.c +++ b/block/badblocks.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -25,6 +26,67 @@ #include /** + * badblocks_notify - call badblocks notifier chain + * @bb: struct badblocks that is changing + * @op: badblocks operation + * @sector: old clk rate + * + * Triggers a notifier call chain on the badblocks change notification + * for 'bb'. Passes a pointer to the struct badblocks and the operation, + * and affected sector. Intended to be called by internal badblocks code + * only. Returns whatever atomic_notifier_call_chain returns. + */ +static int badblocks_notify(struct badblocks *bb, unsigned long op, sector_t sector, + int count) +{ + struct bb_notifier_data bbn_data; + + bbn_data.sector = sector; + bbn_data.count = count; + + return atomic_notifier_call_chain(&bb->notifier, op, &bbn_data); +} + +/** + * bb_notifier_register - add a badblocks change notifier + * @bb: struct badblocks * to watch + * @nb: struct notifier_block * with callback info + * + * Request notification when badblocks are added or cleared. + * This uses a notifier of the 'atomic' type. + * + * Returns -EINVAL if called with null arguments otherwise, passes along + * the return value of atomic_notifier_chain_register(). + */ +int bb_notifier_register(struct badblocks *bb, struct notifier_block *nb) +{ + if (!bb || !nb) + return -EINVAL; + + return atomic_notifier_chain_register(&bb->notifier, nb); +} +EXPORT_SYMBOL_GPL(bb_notifier_register); + +/** + * bb_notifier_unregister - remove a badblocks change notifier + * @bb: struct badblocks * + * @nb: struct notifier_block * with callback info + * + * Request no further notification for changes to the badblocks list. + * + * Returns -EINVAL if called with null arguments; otherwise, passes + * along the return value of atomic_notifier_chain_unregister(). + */ +int bb_notifier_unregister(struct badblocks *bb, struct notifier_block *nb) +{ + if (!bb || !nb) + return -EINVAL; + + return atomic_notifier_chain_unregister(&bb->notifier, nb); +} +EXPORT_SYMBOL_GPL(bb_notifier_unregister); + +/** * badblocks_check() - check a given range for bad sectors * @bb: the badblocks structure that holds all badblock information * @s: sector (start) at which to check for badblocks @@ -152,9 +214,10 @@ int badblocks_set(struct badblocks *bb, sector_t s, int sectors, int acknowledged) { u64 *p; - int lo, hi; - int rv = 0; + int rv = 0, ret; unsigned long flags; + sector_t saved_s = s; + int lo, hi, saved_count = sectors; if (bb->shift < 0) /* badblocks are disabled */ @@ -294,6 +357,11 @@ int badblocks_set(struct badblocks *bb, sector_t s, int sectors, bb->changed = 1; if (!acknowledged) bb->unacked_exist = 1; + + ret = badblocks_notify(bb, BB_ADD, saved_s, saved_count); + if (ret) + WARN(1, "Failure in badblocks notifier chain: %d\n", ret); + write_sequnlock_irqrestore(&bb->lock, flags); return rv; @@ -318,8 +386,9 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors) { u64 *p; int lo, hi; + sector_t saved_s = s; sector_t target = s + sectors; - int rv = 0; + int rv = 0, ret, saved_count = sectors; if (bb->shift > 0) { /* When clearing we round the start up and the end down. @@ -400,6 +469,9 @@ int badblocks_clear(struct badblocks *bb, sector_t s, int sectors) } bb->changed = 1; + ret = badblocks_notify(bb, BB_CLEAR, saved_s, saved_count); + if (ret) + WARN(1, "Failure in badblocks notifier chain: %d\n", ret); out: write_sequnlock_irq(&bb->lock); return rv; @@ -541,6 +613,7 @@ static int __badblocks_init(struct device *dev, struct badblocks *bb, return -ENOMEM; } seqlock_init(&bb->lock); + ATOMIC_INIT_NOTIFIER_HEAD(&bb->notifier); return 0; } diff --git a/include/linux/badblocks.h b/include/linux/badblocks.h index c3bdf8c..67539f0 100644 --- a/include/linux/badblocks.h +++ b/include/linux/badblocks.h @@ -1,6 +1,7 @@ #ifndef _LINUX_BADBLOCKS_H #define _LINUX_BADBLOCKS_H +#include #include #include #include @@ -38,8 +39,26 @@ struct badblocks { seqlock_t lock; sector_t sector; sector_t size; /* in sectors */ + struct atomic_notifier_head notifier; /* notifier for filesystems */ }; +#define BB_ADD 0 +#define BB_CLEAR 1 + +/** + * struct bb_notifier_data - data to pass to the notifier callback + * @bb: struct badblocks * being changed + * @sector: the 512B sector being added/removed + * @count: number of sectors after @sector being added/removed + */ +struct bb_notifier_data { + struct badblocks *bb; + sector_t sector; + int count; +}; + +int bb_notifier_register(struct badblocks *bb, struct notifier_block *nb); +int bb_notifier_unregister(struct badblocks *bb, struct notifier_block *nb); int badblocks_check(struct badblocks *bb, sector_t s, int sectors, sector_t *first_bad, int *bad_sectors); int badblocks_set(struct badblocks *bb, sector_t s, int sectors, -- 2.5.5 From vishal.l.verma@intel.com Thu Jun 16 20:04:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 230BA7CA2 for ; Thu, 16 Jun 2016 20:04:25 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id D429A30404E for ; Thu, 16 Jun 2016 18:04:21 -0700 (PDT) X-ASG-Debug-ID: 1466125460-04bdf01e1395270001-NocioJ Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by cuda.sgi.com with ESMTP id BNSflzmmDnqoFU6u for ; Thu, 16 Jun 2016 18:04:20 -0700 (PDT) X-Barracuda-Envelope-From: vishal.l.verma@intel.com X-Barracuda-Effective-Source-IP: mga02.intel.com[134.134.136.20] X-Barracuda-Apparent-Source-IP: 134.134.136.20 X-ASG-Whitelist: Client Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 16 Jun 2016 18:04:19 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,481,1459839600"; d="scan'208";a="989197278" Received: from omniknight.lm.intel.com ([10.232.112.171]) by fmsmga001.fm.intel.com with ESMTP; 16 Jun 2016 18:04:19 -0700 From: Vishal Verma To: , Cc: Dave Chinner , Jan Kara , "Darrick J. Wong" , Vishal Verma Subject: [RFC PATCH 0/2] Initial support for badblock checking in xfs Date: Thu, 16 Jun 2016 19:03:37 -0600 X-ASG-Orig-Subj: [RFC PATCH 0/2] Initial support for badblock checking in xfs Message-Id: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> X-Mailer: git-send-email 2.5.5 X-Barracuda-Connect: mga02.intel.com[134.134.136.20] X-Barracuda-Start-Time: 1466125460 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2174 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 These are early/RFC patches to add badblock support in xfs. Patch 1 should be relatively straightforward - it adds a notifier chain to badblocks that filesystems can register with. Patch 2 is the beginnings of xfs support. So far, I have the notifier registration and building the initial badblock list happening in xfs_mountfs. The next steps (and I may need some help with this as I'm no (x)fs developer :)) are to add this badblocks info to the reverse mapping tree, and then to check for it before accessing the media. Right now, this just prints the sector numbers/counts/{added, removed} to the kernel log, for both the initial list, and subsequent notifier hits. While I've tested this with a fake pmem device using libnvdimm's nfit_test framework, it should also work using badblock injection with any block device: # mkfs.xfs -f /dev/ # echo 122 1 > /sys/block//badblocks # echo 124 1 > /sys/block//badblocks # mount -t xfs /dev/ /mnt ... in log: [ +8.803776] XFS (pmem7): Mounting V4 Filesystem [ +0.009633] XFS (pmem7): Ending clean mount [ +0.001655] XFS (pmem7): got badblocks: sector 122, count 1 [ +0.002018] XFS (pmem7): got badblocks: sector 124, count 1 # echo 132 5 | > /sys/block//badblocks [Jun16 18:56] XFS (pmem7): xfs badblock added sector 132 (count 5) This is all based on Darrik's rmap work at: https://github.com/djwong/linux/tree/rmap-reflink-devel Since this is based on a v4.5-rc kernel, it lacks pmem support for clearing badblocks on zeroing/writing, so those parts can't easily be tested yet. The clearing work is in 4.7-rs kernels, and once we rebase to that, that should also be available. Vishal Verma (2): block, badblocks: add a notifier for badblocks xfs: initial/partial support for badblocks block/badblocks.c | 79 +++++++++++++++++++++++++++++++++-- fs/xfs/xfs_linux.h | 1 + fs/xfs/xfs_mount.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_mount.h | 1 + include/linux/badblocks.h | 19 +++++++++ 5 files changed, 201 insertions(+), 3 deletions(-) -- 2.5.5 From vishal.l.verma@intel.com Thu Jun 16 20:04:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_FOLLOW1,T_FRT_FOLLOW2 autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A585E7CB1 for ; Thu, 16 Jun 2016 20:04:28 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5426C8F804C for ; Thu, 16 Jun 2016 18:04:25 -0700 (PDT) X-ASG-Debug-ID: 1466125460-04bdf01e1395270003-NocioJ Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by cuda.sgi.com with ESMTP id ogLt1EmUKLWOnKuf for ; Thu, 16 Jun 2016 18:04:23 -0700 (PDT) X-Barracuda-Envelope-From: vishal.l.verma@intel.com X-Barracuda-Effective-Source-IP: mga02.intel.com[134.134.136.20] X-Barracuda-Apparent-Source-IP: 134.134.136.20 X-ASG-Whitelist: Client Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga101.jf.intel.com with ESMTP; 16 Jun 2016 18:04:23 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,481,1459839600"; d="scan'208";a="989197308" Received: from omniknight.lm.intel.com ([10.232.112.171]) by fmsmga001.fm.intel.com with ESMTP; 16 Jun 2016 18:04:23 -0700 From: Vishal Verma To: , Cc: Dave Chinner , Jan Kara , "Darrick J. Wong" , Vishal Verma Subject: [RFC PATCH 2/2] xfs: initial/partial support for badblocks Date: Thu, 16 Jun 2016 19:03:39 -0600 X-ASG-Orig-Subj: [RFC PATCH 2/2] xfs: initial/partial support for badblocks Message-Id: <1466125419-17736-3-git-send-email-vishal.l.verma@intel.com> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> X-Barracuda-Connect: mga02.intel.com[134.134.136.20] X-Barracuda-Start-Time: 1466125463 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5445 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 RFC/WIP commit. This adds the foollowing: 1. In xfs_mountfs(), get an initial badblocks list from gendisk's badblocks infrastructure. 2. Register with the badblocks notifier to get updates for this disk's badblocks TODO: 1. Add badblocks info to the reverse mapping tree (and remove if a badblock was cleared). 2. Before doing file IO, refer the rmap/badblocks to error out early if the IO will attempt wo read a bad sector 3. Figure out interactions with mmap/DAX. Cc: Darrick J. Wong Cc: Dave Chinner Signed-off-by: Vishal Verma --- fs/xfs/xfs_linux.h | 1 + fs/xfs/xfs_mount.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_mount.h | 1 + 3 files changed, 106 insertions(+) diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h index 7e749be..f66d181 100644 --- a/fs/xfs/xfs_linux.h +++ b/fs/xfs/xfs_linux.h @@ -78,6 +78,7 @@ typedef __u32 xfs_nlink_t; #include #include #include +#include #include #include diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 5e68b2c..1a47737 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -618,6 +618,96 @@ xfs_default_resblks(xfs_mount_t *mp) return resblks; } +STATIC int +xfs_notifier_call( + struct notifier_block *nb, + unsigned long action, + void *data) +{ + struct bb_notifier_data *bb_data = data; + struct xfs_mount *mp; + + mp = container_of(nb, struct xfs_mount, m_badblocks_nb); + /* TODO xfs_add_bb_to_rmap(mp, bb_data->sector, bb_data->count); */ + xfs_warn(mp, "xfs badblock %s sector %lu (count %d)\n", + (action == BB_ADD)?"added":"cleared", + bb_data->sector, bb_data->count); + return 0; +} + +STATIC int +xfs_init_badblocks(struct xfs_mount *mp) +{ + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; + int done = 0, error = 0; + ssize_t len, off = 0; + char *p; + + /* + * TODO: get a list of known badblocks so far and process it. + * Can we just parse the sysfs format that badblocks_show() + * returns? That should be the fastest way to get this. + * Something like: (Is this too hacky? Should we just do + * badblocks_check() in a (rather large) loop?) + */ + p = kzalloc(PAGE_SIZE, GFP_KERNEL); + len = badblocks_show(bb, p, 0); + while (len) { + int count, n; + sector_t s; + + /* + * The sysfs badblocks format is multiple lines of: + * " " + */ + n = sscanf(p + off, "%lu %d\n%n", &s, &count, &done); + if (n < 2 || done < 3) { + error = -1; + break; + } + off += done; + len -= done; + xfs_warn(mp, "got badblocks: sector %ld, count %d", s, count); + /* TODO xfs_add_bb_to_rmap(mp, s, count); */ + } + kfree(p); + if (error) + return error; + + mp->m_badblocks_nb.notifier_call = xfs_notifier_call; + error = bb_notifier_register(bb, &mp->m_badblocks_nb); + if (error) + return error; + + /* + * TODO: There is probably a TOCTOU race hiding here - what if the + * badblocks list gets updated before we register for notifications.. + * Can likely be solved by registering for notifications _first_ (the + * above xfs_add_bb_to_rmap function has to be ready to accept new + * blocks), then querying for the initial list (there could be overlap + * here, shich the above function could handle), and then setting the + * mount flag below. + */ + + /* + * TODO: set some flag (mount flag?) in xfs so that xfs knows + * it will be doing error checking, and can possibly, later, + * tell the block layer (possibly using a REQ_ flag in its IO + * requests) not to do further badblock checking for those IOs. + */ + + /* mp->m_flags |= XFS_MOUNT_FS_BADBLOCKS; */ + return 0; +} + +STATIC void +xfs_badblocks_unmount(struct xfs_mount *mp) +{ + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; + + bb_notifier_unregister(bb, &mp->m_badblocks_nb); +} + /* * This function does the following on an initial mount of a file system: * - reads the superblock from disk and init the mount struct @@ -955,6 +1045,19 @@ xfs_mountfs( } /* + * Register with the badblocks notifier chain + */ + error = xfs_init_badblocks(mp); + if (error) { + xfs_warn(mp, "Unable to register to badblocks notifications\n"); + /* + * TODO is this a hard error or can we simply + * warn and continue? + */ + goto out_rtunmount; + } + + /* * Now we are mounted, reserve a small amount of unused space for * privileged transactions. This is needed so that transaction * space required for critical operations can dip into this pool @@ -1085,6 +1188,7 @@ xfs_unmountfs( xfs_log_unmount(mp); xfs_da_unmount(mp); xfs_uuid_unmount(mp); + xfs_badblocks_unmount(mp); #if defined(DEBUG) xfs_errortag_clearall(mp, 0); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 0ca9244..f0d1111 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -139,6 +139,7 @@ typedef struct xfs_mount { /* low free space thresholds */ struct xfs_kobj m_kobj; struct xstats m_stats; /* per-fs stats */ + struct notifier_block m_badblocks_nb; /* disk badblocks notifier */ struct workqueue_struct *m_buf_workqueue; struct workqueue_struct *m_data_workqueue; -- 2.5.5 From darrick.wong@oracle.com Thu Jun 16 20:18:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 78CDD7CA2 for ; Thu, 16 Jun 2016 20:18:02 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id F3799AC001 for ; Thu, 16 Jun 2016 18:18:01 -0700 (PDT) X-ASG-Debug-ID: 1466126280-04cbb01fee69450001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id PASvl6hOWnsGZJh1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:00 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1HV6U023067 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:31 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1HV9e011224 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:31 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1HTxr021967; Fri, 17 Jun 2016 01:17:30 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:17:29 -0700 Subject: [PATCH v9 0/3] fallocate for block devices From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH v9 0/3] fallocate for block devices To: axboe@kernel.dk, darrick.wong@oracle.com Cc: linux-block@vger.kernel.org, tytso@mit.edu, martin.petersen@oracle.com, snitzer@redhat.com, linux-api@vger.kernel.org, bfoster@redhat.com, xfs@oss.sgi.com, hch@infradead.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org Date: Thu, 16 Jun 2016 18:17:27 -0700 Message-ID: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126280 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1476 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Hi, This is a redesign of the patch series that fixes various interface problems with the existing "zero out this part of a block device" code. BLKZEROOUT2 is gone. The first patch is still a fix to the existing BLKZEROOUT ioctl to invalidate the page cache if the zeroing command to the underlying device succeeds. Without this patch we still have the pagecache coherence bug that's been in the kernel forever. The second patch changes the internal block device functions to reject attempts to discard or zeroout that are not aligned to the logical block size. Previously, we only checked that the start/len parameters were 512-byte aligned, which caused kernel BUG_ONs for unaligned IOs to 4k-LBA devices. The third patch creates an fallocate handler for block devices, wires up the FALLOC_FL_PUNCH_HOLE flag to zeroing-discard, and connects FALLOC_FL_ZERO_RANGE to write-same so that we can have a consistent fallocate interface between files and block devices. It also allows the combination of PUNCH_HOLE and NO_HIDE_STALE to invoke non-zeroing discard. Test cases for the new block device fallocate are now in xfstests as generic/349-351. Comments and questions are, as always, welcome. Patches are against 4.7-rc3. v7: Strengthen parameter checking and fix various code issues pointed out by Linus and Christoph. v8: More code rearranging, rebase to 4.6-rc3, and dig into alignment issues. v9: Forward port to 4.7. --D From darrick.wong@oracle.com Thu Jun 16 20:18:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D51517CA2 for ; Thu, 16 Jun 2016 20:18:04 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 69C50AC001 for ; Thu, 16 Jun 2016 18:18:01 -0700 (PDT) X-ASG-Debug-ID: 1466126279-04bdf01e1595750001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id yO4enlNFB0EpBWof (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:17:59 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1HuuB023265 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:57 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Htl8007585 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:56 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1HsXp017777; Fri, 17 Jun 2016 01:17:55 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:17:54 -0700 Subject: [PATCH v6 000/119] xfs: add reverse mapping, reflink, dedupe, and online scrub support From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH v6 000/119] xfs: add reverse mapping, reflink, dedupe, and online scrub support To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:17:53 -0700 Message-ID: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126279 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5811 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Hi all, This is the sixth revision of a patchset that adds to XFS kernel support for tracking reverse-mappings of physical blocks to file and metadata (rmap); support for mapping multiple file logical blocks to the same physical block (reflink); and implements the beginnings of online metadata scrubbing. Given the significant amount of design assumptions that change with block sharing, rmap and reflink are provided together. There shouldn't be any incompatible on-disk format changes, pending a thorough review of the patches within. The reverse mapping implementation features a simple per-AG b+tree containing tuples of (physical block, owner, offset, blockcount) with the key being the first three fields. The large record size will enable us to reconstruct corrupt block mapping btrees (bmbt); the large key size is necessary to identify uniquely each rmap record in the presence of shared physical blocks. In contrast to previous iterations of this patchset, it is no longer a requirement that there be a 1:1 correspondence between bmbt and rmapbt records; each rmapbt record can cover multiple bmbt records. The reflink implementation features a simple per-AG b+tree containing tuples of (physical block, blockcount, refcount) with the key being the physical block. Copy on Write (CoW) is implemented by creating a separate CoW fork and using the existing delayed allocation mechanism to try to allocate as large of a replacement extent as possible before committing the new data to media. A CoW extent size hint allows administrators to influence the size of the replacement extents, and certain writes can be "promoted" to CoW when it would be advantageous to reduce fragmentation. The userspace interface to reflink and dedupe are the VFS FICLONE, FICLONERANGE, and FIDEDUPERANGE ioctls, which were previously private to btrfs. Since the previous posting, I have made some major changes to the underlying XFS common code. First, I have extended the generic b+tree implementation to support overlapping intervals, which is necessary for the rmapbt on a reflink filesystem where there can be a number of rmapbt records representing a physical block. The new b+tree variant introduces the notion of a "high key" for each record; it is the highest key that can be used to identify a record. On disk, an overlapped-interval b+tree looks like a traditional b+tree except that nodes store both the lowest key and the highest key accessible through that subtree pointer. There's a new interval query function that uses both keys to iterate all records overlapping a given range of keys. This change allows us to remove the old requirement that each bmbt record correspond to a matching rmapbt record. The second big change is to the xfs_bmap_free functions. The existing code implements a mechanism to defer metadata (specifically, free space b+tree) updates across a transaction commit by logging redo items that can be replayed during recovery. It is an elegant way to avoid running afoul of AG locking order rules /and/ it can in theory be used to get around running out of transaction reservation. That said, I have refactored it into a generic "deferred operations" mechanism that can defer arbitrary types of work to a subsequent rolled transaction. The framework thus allows me to schedule rmapbt, refcountbt, and bmbt updates while maintaining correct redo in case of failure. Remapping activities for reflink and CoW are now atomic. The third big change is the establishment of a per-AG block reservation mechanism. This "hides" some blocks from the regular block allocator; refcountbt and rmapbt expansions use these blocks to handle the removal of the assumption that file mapping operations always involve block allocation. This gets us into trouble when a file allocates an entire AG, is reflinked by other files, and subsequent CoWs cause record splits in the rmap and reflink btrees. At the very end of the patchset is an initial implementation of a GETFSMAPX ioctl for userland to query the physical block mapping of a filesystem; and metadata scrubbing for XFS. The scrubber iterates the per-AG btrees and does some simple cross-checking when possible; I built it to check the functionality of the new b+tree code. The first few patches fix various vfs/xfs bugs, adds an enhancement to the xfs_buf tracepoints so that we can analyze buffer deadlocks, and merges difference between the kernel and userspace libxfs so that the rest of the patches apply consistently. There are still two functionality gaps: the extent swap ioctl isn't functional when rmap is enabled; and rmap cannot (yet) coexist with realtime devices. These will be addressed in the next sprint. If you're going to start using this mess, you probably ought to just pull from my github trees for kernel[1], xfsprogs[2], and xfstests[3]. There are also updates for xfs-docs[4]. The kernel patches should apply to dchinner's for-next; xfsprogs patches to for-next; and xfstest to master. NOTE however that the kernel git tree already has the five for-next patches included. The patches have been xfstested with x64, i386, and armv7l--arm64, ppc64, and ppc64le no longer boot in qemu. All three architectures pass all 'clone' group tests except xfs/128 (which is the swapext test), and AFAICT don't cause any new failures for the 'auto' group. This is an extraordinary way to eat your data. Enjoy! Comments and questions are, as always, welcome. --D [1] https://github.com/djwong/linux/tree/djwong-devel [2] https://github.com/djwong/xfsprogs/tree/djwong-devel [3] https://github.com/djwong/xfstests/tree/djwong-devel [4] https://github.com/djwong/xfs-documentation/tree/djwong-devel From darrick.wong@oracle.com Thu Jun 16 20:18:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E8A977CB0 for ; Thu, 16 Jun 2016 20:18:08 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id A7A32304048 for ; Thu, 16 Jun 2016 18:18:08 -0700 (PDT) X-ASG-Debug-ID: 1466126286-04bdf01e1095750001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id oHzpJTS1T5lEg6Xl (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1I3hb004168 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:04 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1I3E6012012 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:03 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1I16p005689; Fri, 17 Jun 2016 01:18:02 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:00 -0700 Subject: [PATCH 001/119] vfs: fix return type of ioctl_file_dedupe_range From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 001/119] vfs: fix return type of ioctl_file_dedupe_range To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:17:59 -0700 Message-ID: <146612627940.12839.15145788608361492501.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126286 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 729 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines All the VFS functions in the dedupe ioctl path return int status, so the ioctl handler ought to as well. Found by Coverity, CID 1350952. Signed-off-by: Darrick J. Wong --- fs/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ioctl.c b/fs/ioctl.c index 116a333..db3d033 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -568,7 +568,7 @@ static int ioctl_fsthaw(struct file *filp) return thaw_super(sb); } -static long ioctl_file_dedupe_range(struct file *file, void __user *arg) +static int ioctl_file_dedupe_range(struct file *file, void __user *arg) { struct file_dedupe_range __user *argp = arg; struct file_dedupe_range *same = NULL; From darrick.wong@oracle.com Thu Jun 16 20:18:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7ED837CB8 for ; Thu, 16 Jun 2016 20:18:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 41D828F804C for ; Thu, 16 Jun 2016 18:18:11 -0700 (PDT) X-ASG-Debug-ID: 1466126289-04cbb01fed69460001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id znNmQDuzZfe8jCNR (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1HdYY003785 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:39 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1HbCF006925 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:37 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1HaGC021989; Fri, 17 Jun 2016 01:17:36 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:17:36 -0700 Subject: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. To: axboe@kernel.dk, darrick.wong@oracle.com Cc: linux-block@vger.kernel.org, tytso@mit.edu, martin.petersen@oracle.com, snitzer@redhat.com, linux-api@vger.kernel.org, bfoster@redhat.com, xfs@oss.sgi.com, hch@infradead.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, Christoph Hellwig Date: Thu, 16 Jun 2016 18:17:34 -0700 Message-ID: <146612625412.12764.6647932282740152837.stgit@birch.djwong.org> In-Reply-To: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126290 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1994 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Invalidate the page cache (as a regular O_DIRECT write would do) to avoid returning stale cache contents at a later time. v5: Refactor the 4.4 refactoring of the ioctl code into separate functions. Split the page invalidation and the new ioctl into separate patches. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- block/ioctl.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/block/ioctl.c b/block/ioctl.c index ed2397f..d001f52 100644 --- a/block/ioctl.c +++ b/block/ioctl.c @@ -225,7 +225,9 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, unsigned long arg) { uint64_t range[2]; - uint64_t start, len; + struct address_space *mapping; + uint64_t start, end, len; + int ret; if (!(mode & FMODE_WRITE)) return -EBADF; @@ -235,18 +237,33 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, start = range[0]; len = range[1]; + end = start + len - 1; if (start & 511) return -EINVAL; if (len & 511) return -EINVAL; - start >>= 9; - len >>= 9; - - if (start + len > (i_size_read(bdev->bd_inode) >> 9)) + if (end >= (uint64_t)i_size_read(bdev->bd_inode)) + return -EINVAL; + if (end < start) return -EINVAL; - return blkdev_issue_zeroout(bdev, start, len, GFP_KERNEL, false); + /* Invalidate the page cache, including dirty pages */ + mapping = bdev->bd_inode->i_mapping; + truncate_inode_pages_range(mapping, start, end); + + ret = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, + false); + if (ret) + return ret; + + /* + * Invalidate again; if someone wandered in and dirtied a page, + * the caller will be given -EBUSY. + */ + return invalidate_inode_pages2_range(mapping, + start >> PAGE_SHIFT, + end >> PAGE_SHIFT); } static int put_ushort(unsigned long arg, unsigned short val) From darrick.wong@oracle.com Thu Jun 16 20:18:12 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EB6607CBA for ; Thu, 16 Jun 2016 20:18:11 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 77753AC002 for ; Thu, 16 Jun 2016 18:18:11 -0700 (PDT) X-ASG-Debug-ID: 1466126289-04bdf01e1595760001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id yBOWyFTlpZWJXMX6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1HiDk003843 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:17:44 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1HiE1004405 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:44 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1HhSF021998; Fri, 17 Jun 2016 01:17:43 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:17:42 -0700 Subject: [PATCH 2/3] block: require write_same and discard requests align to logical block size From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 2/3] block: require write_same and discard requests align to logical block size To: axboe@kernel.dk, darrick.wong@oracle.com Cc: linux-block@vger.kernel.org, tytso@mit.edu, martin.petersen@oracle.com, snitzer@redhat.com, linux-api@vger.kernel.org, bfoster@redhat.com, xfs@oss.sgi.com, hch@infradead.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, Christoph Hellwig Date: Thu, 16 Jun 2016 18:17:41 -0700 Message-ID: <146612626092.12764.773833541076937471.stgit@birch.djwong.org> In-Reply-To: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126289 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2164 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Make sure that the offset and length arguments that we're using to construct WRITE SAME and DISCARD requests are actually aligned to the logical block size. Failure to do this causes other errors in other parts of the block layer or the SCSI layer because disks don't support partial logical block writes. Signed-off-by: Darrick J. Wong Reviewed-by: Christoph Hellwig --- block/blk-lib.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/block/blk-lib.c b/block/blk-lib.c index 9e29dc3..012aa98 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -29,6 +29,7 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, struct bio *bio = *biop; unsigned int granularity; int alignment; + sector_t bs_mask; if (!q) return -ENXIO; @@ -37,6 +38,10 @@ int __blkdev_issue_discard(struct block_device *bdev, sector_t sector, if ((type & REQ_SECURE) && !blk_queue_secdiscard(q)) return -EOPNOTSUPP; + bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1; + if ((sector | nr_sects) & bs_mask) + return -EINVAL; + /* Zero-sector (unknown) and one-sector granularities are the same. */ granularity = max(q->limits.discard_granularity >> 9, 1U); alignment = (bdev_discard_alignment(bdev) >> 9) % granularity; @@ -140,10 +145,15 @@ int blkdev_issue_write_same(struct block_device *bdev, sector_t sector, unsigned int max_write_same_sectors; struct bio *bio = NULL; int ret = 0; + sector_t bs_mask; if (!q) return -ENXIO; + bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1; + if ((sector | nr_sects) & bs_mask) + return -EINVAL; + /* Ensure that max_write_same_sectors doesn't overflow bi_size */ max_write_same_sectors = UINT_MAX >> 9; @@ -191,6 +201,11 @@ static int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, int ret; struct bio *bio = NULL; unsigned int sz; + sector_t bs_mask; + + bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1; + if ((sector | nr_sects) & bs_mask) + return -EINVAL; while (nr_sects != 0) { bio = next_bio(bio, WRITE, From darrick.wong@oracle.com Thu Jun 16 20:18:12 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9E8287CBB for ; Thu, 16 Jun 2016 20:18:12 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2904BAC002 for ; Thu, 16 Jun 2016 18:18:12 -0700 (PDT) X-ASG-Debug-ID: 1466126290-04bdf01e1095760001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id myMwgpJEQf7fn6la (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1I89b023561 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:08 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1I87c008063 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:08 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1I7A3026380; Fri, 17 Jun 2016 01:18:07 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:07 -0700 Subject: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:05 -0700 Message-ID: <146612628567.12839.3246258786290141903.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126290 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1331 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Introduce XFLAGs for the new XFS reflink inode flag and the CoW extent size hint, and actually plumb the CoW extent size hint into the fsxattr structure. Signed-off-by: Darrick J. Wong --- include/uapi/linux/fs.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 3b00f7c..fb371a5 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -157,7 +157,8 @@ struct fsxattr { __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ - unsigned char fsx_pad[12]; + __u32 fsx_cowextsize; /* CoW extsize field value (get/set)*/ + unsigned char fsx_pad[8]; }; /* @@ -178,6 +179,8 @@ struct fsxattr { #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ +#define FS_XFLAG_REFLINK 0x00010000 /* file is reflinked */ +#define FS_XFLAG_COWEXTSIZE 0x00020000 /* CoW extent size allocator hint */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ /* the read-only stuff doesn't really belong here, but any other place is From darrick.wong@oracle.com Thu Jun 16 20:18:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0648F7CA2 for ; Thu, 16 Jun 2016 20:18:20 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id BAC6A304039 for ; Thu, 16 Jun 2016 18:18:19 -0700 (PDT) X-ASG-Debug-ID: 1466126297-04bdf01e1095770001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id JwkBUDRDPPsUVnQb (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1IG0s023617 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:16 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IGZQ001793 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:16 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IDJD005735; Fri, 17 Jun 2016 01:18:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:13 -0700 Subject: [PATCH 003/119] xfs: check offsets of variable length structures From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 003/119] xfs: check offsets of variable length structures To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:12 -0700 Message-ID: <146612629195.12839.14090954204243398929.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126298 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3079 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Some of the directory/attr structures contain variable-length objects, so the enclosing structure doesn't have a meaningful fixed size at compile time. We can check the offsets of the members before the variable-length member, so do those. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_ondisk.h | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 184c44e..0272301 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -22,6 +22,11 @@ BUILD_BUG_ON_MSG(sizeof(structname) != (size), "XFS: sizeof(" \ #structname ") is wrong, expected " #size) +#define XFS_CHECK_OFFSET(structname, member, off) \ + BUILD_BUG_ON_MSG(offsetof(structname, member) != (off), \ + "XFS: offsetof(" #structname ", " #member ") is wrong, " \ + "expected " #off) + static inline void __init xfs_check_ondisk_structs(void) { @@ -75,15 +80,28 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_remote_t, 12); */ + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, valuelen, 0); + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, namelen, 2); + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, nameval, 3); + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valueblk, 0); + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valuelen, 4); + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, namelen, 8); + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, name, 9); XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t, 40); - XFS_CHECK_STRUCT_SIZE(xfs_attr_shortform_t, 8); + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.totsize, 0); + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.count, 2); + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].namelen, 4); + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].valuelen, 5); + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].flags, 6); + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].nameval, 7); XFS_CHECK_STRUCT_SIZE(xfs_da_blkinfo_t, 12); XFS_CHECK_STRUCT_SIZE(xfs_da_intnode_t, 16); XFS_CHECK_STRUCT_SIZE(xfs_da_node_entry_t, 8); XFS_CHECK_STRUCT_SIZE(xfs_da_node_hdr_t, 16); XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_free_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_hdr_t, 16); - XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_unused_t, 6); + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, freetag, 0); + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, length, 2); XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_hdr_t, 16); XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_t, 16); XFS_CHECK_STRUCT_SIZE(xfs_dir2_ino4_t, 4); @@ -94,6 +112,9 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_t, 16); XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_tail_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_entry_t, 3); + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, namelen, 0); + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, offset, 1); + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, name, 3); XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_hdr_t, 10); XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_off_t, 2); From darrick.wong@oracle.com Thu Jun 16 20:18:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B889A7CCD for ; Thu, 16 Jun 2016 20:18:21 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 89A12304048 for ; Thu, 16 Jun 2016 18:18:21 -0700 (PDT) X-ASG-Debug-ID: 1466126299-04cbb01fec69480001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id X588apUa8mm3NweV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1HrML023235 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:53 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Hq1C007532 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:17:53 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1HoWS005675; Fri, 17 Jun 2016 01:17:51 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:17:49 -0700 Subject: [PATCH 3/3] block: implement (some of) fallocate for block devices From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 3/3] block: implement (some of) fallocate for block devices To: axboe@kernel.dk, darrick.wong@oracle.com Cc: linux-block@vger.kernel.org, tytso@mit.edu, martin.petersen@oracle.com, snitzer@redhat.com, linux-api@vger.kernel.org, bfoster@redhat.com, xfs@oss.sgi.com, hch@infradead.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org Date: Thu, 16 Jun 2016 18:17:47 -0700 Message-ID: <146612626773.12764.9800994140955661542.stgit@birch.djwong.org> In-Reply-To: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126299 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5028 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines After much discussion, it seems that the fallocate feature flag FALLOC_FL_ZERO_RANGE maps nicely to SCSI WRITE SAME; and the feature FALLOC_FL_PUNCH_HOLE maps nicely to the devices that have been whitelisted for zeroing SCSI UNMAP. Punch still requires that FALLOC_FL_KEEP_SIZE is set. A length that goes past the end of the device will be clamped to the device size if KEEP_SIZE is set; or will return -EINVAL if not. Both start and length must be aligned to the device's logical block size. Since the semantics of fallocate are fairly well established already, wire up the two pieces. The other fallocate variants (collapse range, insert range, and allocate blocks) are not supported. v2: Incorporate feedback from Christoph & Linus. Tentatively add a requirement that the fallocate arguments be aligned to logical block size, and put in a few XXX comments ahead of LSF discussion. v3: Forward port to 4.7. Signed-off-by: Darrick J. Wong --- fs/block_dev.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/open.c | 3 +- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/fs/block_dev.c b/fs/block_dev.c index 71ccab1..a3975c4 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "internal.h" @@ -1802,6 +1803,88 @@ static const struct address_space_operations def_blk_aops = { .is_dirty_writeback = buffer_check_dirty_writeback, }; +#define BLKDEV_FALLOC_FL_SUPPORTED \ + (FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE | \ + FALLOC_FL_ZERO_RANGE | FALLOC_FL_NO_HIDE_STALE) + +static long blkdev_fallocate(struct file *file, int mode, loff_t start, + loff_t len) +{ + struct block_device *bdev = I_BDEV(bdev_file_inode(file)); + struct request_queue *q = bdev_get_queue(bdev); + struct address_space *mapping; + loff_t end = start + len - 1; + loff_t isize; + int error; + + /* Fail if we don't recognize the flags. */ + if (mode & ~BLKDEV_FALLOC_FL_SUPPORTED) + return -EOPNOTSUPP; + + /* Don't go off the end of the device. */ + isize = i_size_read(bdev->bd_inode); + if (start >= isize) + return -EINVAL; + if (end > isize) { + if (mode & FALLOC_FL_KEEP_SIZE) { + len = isize - start; + end = start + len - 1; + } else + return -EINVAL; + } + + /* + * Don't allow IO that isn't aligned to logical block size. + */ + if ((start | len) & (bdev_logical_block_size(bdev) - 1)) + return -EINVAL; + + /* Invalidate the page cache, including dirty pages. */ + mapping = bdev->bd_inode->i_mapping; + truncate_inode_pages_range(mapping, start, end); + + switch (mode) { + case FALLOC_FL_ZERO_RANGE: + case FALLOC_FL_ZERO_RANGE | FALLOC_FL_KEEP_SIZE: + error = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, + GFP_KERNEL, false); + if (error) + return error; + break; + case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE: + /* Only punch if the device can do zeroing discard. */ + if (!blk_queue_discard(q) || !q->limits.discard_zeroes_data) + return -EOPNOTSUPP; + error = blkdev_issue_discard(bdev, start >> 9, len >> 9, + GFP_KERNEL, 0); + if (error) + return error; + break; + case FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE | FALLOC_FL_NO_HIDE_STALE: + /* + * XXX: a well known search engine vendor interprets this + * flag (in other circumstances) to mean "I don't care if + * we can read stale contents later". Is it appropriate + * to wire this up to the non-zeroing discard? + */ + error = blkdev_issue_discard(bdev, start >> 9, len >> 9, + GFP_KERNEL, 0); + if (error) + return error; + break; + default: + return -EOPNOTSUPP; + } + + /* + * Invalidate again; if someone wandered in and dirtied a page, + * the caller will be given -EBUSY; + */ + return invalidate_inode_pages2_range(mapping, + start >> PAGE_SHIFT, + end >> PAGE_SHIFT); +} + const struct file_operations def_blk_fops = { .open = blkdev_open, .release = blkdev_close, @@ -1816,6 +1899,7 @@ const struct file_operations def_blk_fops = { #endif .splice_read = generic_file_splice_read, .splice_write = iter_file_splice_write, + .fallocate = blkdev_fallocate, }; int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) diff --git a/fs/open.c b/fs/open.c index 93ae3cd..b2dbda4 100644 --- a/fs/open.c +++ b/fs/open.c @@ -289,7 +289,8 @@ int vfs_fallocate(struct file *file, int mode, loff_t offset, loff_t len) * Let individual file system decide if it supports preallocation * for directories or not. */ - if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) + if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode) && + !S_ISBLK(inode->i_mode)) return -ENODEV; /* Check for wrap through zero too */ From darrick.wong@oracle.com Thu Jun 16 20:18:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 583487CC5 for ; Thu, 16 Jun 2016 20:18:27 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id E5A34AC002 for ; Thu, 16 Jun 2016 18:18:26 -0700 (PDT) X-ASG-Debug-ID: 1466126305-04bdf01e15957a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id CQjdRXkVHizAMKIN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1INHS004319 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:18:23 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1IMI6005467 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:22 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IK7L005780; Fri, 17 Jun 2016 01:18:21 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:19 -0700 Subject: [PATCH 004/119] xfs: enable buffer deadlock postmortem diagnosis via ftrace From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 004/119] xfs: enable buffer deadlock postmortem diagnosis via ftrace To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:18 -0700 Message-ID: <146612629822.12839.7938642541078923297.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126305 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1217 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a second buf_trylock tracepoint so that we can distinguish between a successful and a failed trylock. With this piece, we can use a script to look at the ftrace output to detect buffer deadlocks. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_buf.c | 3 ++- fs/xfs/xfs_trace.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index efa2a73..2333db7 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -947,7 +947,8 @@ xfs_buf_trylock( if (locked) XB_SET_OWNER(bp); - trace_xfs_buf_trylock(bp, _RET_IP_); + locked ? trace_xfs_buf_trylock(bp, _RET_IP_) : + trace_xfs_buf_trylock_fail(bp, _RET_IP_); return locked; } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index ea94ee0..68f27f7 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -354,6 +354,7 @@ DEFINE_BUF_EVENT(xfs_buf_submit_wait); DEFINE_BUF_EVENT(xfs_buf_bawrite); DEFINE_BUF_EVENT(xfs_buf_lock); DEFINE_BUF_EVENT(xfs_buf_lock_done); +DEFINE_BUF_EVENT(xfs_buf_trylock_fail); DEFINE_BUF_EVENT(xfs_buf_trylock); DEFINE_BUF_EVENT(xfs_buf_unlock); DEFINE_BUF_EVENT(xfs_buf_iowait); From darrick.wong@oracle.com Thu Jun 16 20:18:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 741797CD6 for ; Thu, 16 Jun 2016 20:18:33 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 37D138F804C for ; Thu, 16 Jun 2016 18:18:33 -0700 (PDT) X-ASG-Debug-ID: 1466126311-04cb6c542457050001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id crC8StLsn5BqRc7C (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:31 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1IRtG004348 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:28 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IRou001970 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:27 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IQ1q022206; Fri, 17 Jun 2016 01:18:26 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:26 -0700 Subject: [PATCH 005/119] xfs: check for a valid error_tag in errortag_add From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 005/119] xfs: check for a valid error_tag in errortag_add To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:24 -0700 Message-ID: <146612630452.12839.3528211000490660021.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126311 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 814 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Currently we don't check the error_tag when someone's trying to set up error injection testing. If userspace passes in a value we don't know about, send back an error. This will help xfstests to _notrun a test that uses error injection to test things like log replay. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_error.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 88693a9..355619a 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -61,6 +61,9 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) int len; int64_t fsid; + if (error_tag >= XFS_ERRTAG_MAX) + return -EINVAL; + memcpy(&fsid, mp->m_fixedfsid, sizeof(xfs_fsid_t)); for (i = 0; i < XFS_NUM_INJECT_ERROR; i++) { From darrick.wong@oracle.com Thu Jun 16 20:18:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D5A277CD6 for ; Thu, 16 Jun 2016 20:18:38 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 865A1304039 for ; Thu, 16 Jun 2016 18:18:38 -0700 (PDT) X-ASG-Debug-ID: 1466126315-04bdf01e17957c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 9441FjvpX9WpWhH5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:36 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1IXKU023691 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:18:33 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1IXoY005730 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:18:33 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1IWDJ026497; Fri, 17 Jun 2016 01:18:32 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:32 -0700 Subject: [PATCH 006/119] xfs: port differences from xfsprogs libxfs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 006/119] xfs: port differences from xfsprogs libxfs To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:30 -0700 Message-ID: <146612631079.12839.13685287438216197909.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126315 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13736 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Port various differences between xfsprogs and the kernel. This cleans up both so that we can develop rmap and reflink on the same libxfs code. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 2 ++ fs/xfs/libxfs/xfs_attr_leaf.h | 2 +- fs/xfs/libxfs/xfs_bmap.c | 2 +- fs/xfs/libxfs/xfs_bmap.h | 6 ++++++ fs/xfs/libxfs/xfs_btree.c | 4 ++++ fs/xfs/libxfs/xfs_btree.h | 4 ++-- fs/xfs/libxfs/xfs_dir2.h | 2 ++ fs/xfs/libxfs/xfs_dir2_priv.h | 1 - fs/xfs/libxfs/xfs_dquot_buf.c | 10 ++++++++++ fs/xfs/libxfs/xfs_format.h | 1 - fs/xfs/libxfs/xfs_ialloc.c | 4 ++-- fs/xfs/libxfs/xfs_inode_buf.c | 19 +++++++++++++++---- fs/xfs/libxfs/xfs_inode_buf.h | 6 ++++-- fs/xfs/libxfs/xfs_log_format.h | 4 ++-- fs/xfs/libxfs/xfs_rtbitmap.c | 1 - fs/xfs/libxfs/xfs_sb.c | 4 ++++ fs/xfs/libxfs/xfs_types.h | 3 +++ 17 files changed, 58 insertions(+), 17 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 99b077c..58bdca7 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2415,7 +2415,9 @@ xfs_alloc_read_agf( be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); spin_lock_init(&pag->pagb_lock); pag->pagb_count = 0; +#ifdef __KERNEL__ pag->pagb_tree = RB_ROOT; +#endif pag->pagf_init = 1; } #ifdef DEBUG diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h index 4f2aed0..8ef420a 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.h +++ b/fs/xfs/libxfs/xfs_attr_leaf.h @@ -51,7 +51,7 @@ int xfs_attr_shortform_getvalue(struct xfs_da_args *args); int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); int xfs_attr_shortform_remove(struct xfs_da_args *args); int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); -int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); +int xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes); void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp); /* diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 932381c..499e980 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -1425,7 +1425,7 @@ xfs_bmap_search_multi_extents( * Else, *lastxp will be set to the index of the found * entry; *gotp will contain the entry. */ -STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */ +xfs_bmbt_rec_host_t * /* pointer to found extent entry */ xfs_bmap_search_extents( xfs_inode_t *ip, /* incore inode pointer */ xfs_fileoff_t bno, /* block number searched for */ diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 423a34e..79e3ebe 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -231,4 +231,10 @@ int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, int num_exts); int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); +struct xfs_bmbt_rec_host * + xfs_bmap_search_extents(struct xfs_inode *ip, xfs_fileoff_t bno, + int fork, int *eofp, xfs_extnum_t *lastxp, + struct xfs_bmbt_irec *gotp, + struct xfs_bmbt_irec *prevp); + #endif /* __XFS_BMAP_H__ */ diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 1f88e1c..105979d 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -2532,6 +2532,7 @@ error0: return error; } +#ifdef __KERNEL__ struct xfs_btree_split_args { struct xfs_btree_cur *cur; int level; @@ -2609,6 +2610,9 @@ xfs_btree_split( destroy_work_on_stack(&args.work); return args.result; } +#else /* !KERNEL */ +#define xfs_btree_split __xfs_btree_split +#endif /* diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 2e874be..9a88839 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -95,7 +95,7 @@ do { \ case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ - case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ + case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -115,7 +115,7 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ case XFS_BTNUM_FINO: \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ - case XFS_BTNUM_MAX: ASSERT(0); /* fucking gcc */ ; break; \ + case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index e553536..0a62e73 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -177,6 +177,8 @@ extern struct xfs_dir2_data_free *xfs_dir2_data_freefind( struct xfs_dir2_data_hdr *hdr, struct xfs_dir2_data_free *bf, struct xfs_dir2_data_unused *dup); +extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); + extern const struct xfs_buf_ops xfs_dir3_block_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leafn_buf_ops; extern const struct xfs_buf_ops xfs_dir3_leaf1_buf_ops; diff --git a/fs/xfs/libxfs/xfs_dir2_priv.h b/fs/xfs/libxfs/xfs_dir2_priv.h index ef9f6ea..d04547f 100644 --- a/fs/xfs/libxfs/xfs_dir2_priv.h +++ b/fs/xfs/libxfs/xfs_dir2_priv.h @@ -21,7 +21,6 @@ struct dir_context; /* xfs_dir2.c */ -extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, xfs_dir2_db_t *dbp); extern int xfs_dir_cilookup_result(struct xfs_da_args *args, diff --git a/fs/xfs/libxfs/xfs_dquot_buf.c b/fs/xfs/libxfs/xfs_dquot_buf.c index 3cc3cf7..06b574d 100644 --- a/fs/xfs/libxfs/xfs_dquot_buf.c +++ b/fs/xfs/libxfs/xfs_dquot_buf.c @@ -31,10 +31,16 @@ #include "xfs_cksum.h" #include "xfs_trace.h" +/* + * XXX: kernel implementation causes ndquots calc to go real + * bad. Just leaving the existing userspace calc here right now. + */ int xfs_calc_dquots_per_chunk( unsigned int nbblks) /* basic block units */ { +#ifdef __KERNEL__ + /* kernel code that goes wrong in userspace! */ unsigned int ndquots; ASSERT(nbblks > 0); @@ -42,6 +48,10 @@ xfs_calc_dquots_per_chunk( do_div(ndquots, sizeof(xfs_dqblk_t)); return ndquots; +#else + ASSERT(nbblks > 0); + return BBTOB(nbblks) / sizeof(xfs_dqblk_t); +#endif } /* diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index dc97eb21..ba528b3 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -835,7 +835,6 @@ typedef struct xfs_timestamp { * padding field for v3 inodes. */ #define XFS_DINODE_MAGIC 0x494e /* 'IN' */ -#define XFS_DINODE_GOOD_VERSION(v) ((v) >= 1 && (v) <= 3) typedef struct xfs_dinode { __be16 di_magic; /* inode magic # = XFS_DINODE_MAGIC */ __be16 di_mode; /* mode and type of file */ diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 22297f9..77b5990 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -2340,7 +2340,7 @@ xfs_imap( imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno); imap->im_len = XFS_FSB_TO_BB(mp, 1); - imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog); + imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog); return 0; } @@ -2368,7 +2368,7 @@ out_map: imap->im_blkno = XFS_AGB_TO_DADDR(mp, agno, cluster_agbno); imap->im_len = XFS_FSB_TO_BB(mp, blks_per_cluster); - imap->im_boffset = (ushort)(offset << mp->m_sb.sb_inodelog); + imap->im_boffset = (unsigned short)(offset << mp->m_sb.sb_inodelog); /* * If the inode number maps to a block outside the bounds diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 9d9559e..794fa66 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -56,6 +56,17 @@ xfs_inobp_check( } #endif +bool +xfs_dinode_good_version( + struct xfs_mount *mp, + __u8 version) +{ + if (xfs_sb_version_hascrc(&mp->m_sb)) + return version == 3; + + return version == 1 || version == 2; +} + /* * If we are doing readahead on an inode buffer, we might be in log recovery * reading an inode allocation buffer that hasn't yet been replayed, and hence @@ -90,7 +101,7 @@ xfs_inode_buf_verify( dip = xfs_buf_offset(bp, (i << mp->m_sb.sb_inodelog)); di_ok = dip->di_magic == cpu_to_be16(XFS_DINODE_MAGIC) && - XFS_DINODE_GOOD_VERSION(dip->di_version); + xfs_dinode_good_version(mp, dip->di_version); if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, XFS_RANDOM_ITOBP_INOTOBP))) { @@ -369,7 +380,7 @@ xfs_log_dinode_to_disk( static bool xfs_dinode_verify( struct xfs_mount *mp, - struct xfs_inode *ip, + xfs_ino_t ino, struct xfs_dinode *dip) { if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) @@ -384,7 +395,7 @@ xfs_dinode_verify( if (!xfs_verify_cksum((char *)dip, mp->m_sb.sb_inodesize, XFS_DINODE_CRC_OFF)) return false; - if (be64_to_cpu(dip->di_ino) != ip->i_ino) + if (be64_to_cpu(dip->di_ino) != ino) return false; if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid)) return false; @@ -459,7 +470,7 @@ xfs_iread( return error; /* even unallocated inodes are verified */ - if (!xfs_dinode_verify(mp, ip, dip)) { + if (!xfs_dinode_verify(mp, ip->i_ino, dip)) { xfs_alert(mp, "%s: validation failed for inode %lld failed", __func__, ip->i_ino); diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h index 7c4dd32..958c543 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.h +++ b/fs/xfs/libxfs/xfs_inode_buf.h @@ -57,8 +57,8 @@ struct xfs_icdinode { */ struct xfs_imap { xfs_daddr_t im_blkno; /* starting BB of inode chunk */ - ushort im_len; /* length in BBs of inode chunk */ - ushort im_boffset; /* inode offset in block in bytes */ + unsigned short im_len; /* length in BBs of inode chunk */ + unsigned short im_boffset; /* inode offset in block in bytes */ }; int xfs_imap_to_bp(struct xfs_mount *, struct xfs_trans *, @@ -73,6 +73,8 @@ void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from); void xfs_log_dinode_to_disk(struct xfs_log_dinode *from, struct xfs_dinode *to); +bool xfs_dinode_good_version(struct xfs_mount *mp, __u8 version); + #if defined(DEBUG) void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); #else diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index e8f49c0..e5baba3 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -462,8 +462,8 @@ static inline uint xfs_log_dinode_size(int version) typedef struct xfs_buf_log_format { unsigned short blf_type; /* buf log item type indicator */ unsigned short blf_size; /* size of this item */ - ushort blf_flags; /* misc state */ - ushort blf_len; /* number of blocks in this buf */ + unsigned short blf_flags; /* misc state */ + unsigned short blf_len; /* number of blocks in this buf */ __int64_t blf_blkno; /* starting blkno of this buf */ unsigned int blf_map_size; /* used size of data bitmap in words */ unsigned int blf_data_map[XFS_BLF_DATAMAP_SIZE]; /* dirty bitmap */ diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index e2e1106..ea45584 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -1016,4 +1016,3 @@ xfs_rtfree_extent( } return 0; } - diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 12ca867..09d6fd0 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -261,6 +261,7 @@ xfs_mount_validate_sb( /* * Until this is fixed only page-sized or smaller data blocks work. */ +#ifdef __KERNEL__ if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { xfs_warn(mp, "File system with blocksize %d bytes. " @@ -268,6 +269,7 @@ xfs_mount_validate_sb( sbp->sb_blocksize, PAGE_SIZE); return -ENOSYS; } +#endif /* * Currently only very few inode sizes are supported. @@ -291,10 +293,12 @@ xfs_mount_validate_sb( return -EFBIG; } +#ifdef __KERNEL__ if (check_inprogress && sbp->sb_inprogress) { xfs_warn(mp, "Offline file system operation in progress!"); return -EFSCORRUPTED; } +#endif return 0; } diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h index b79dc66..f0d145a 100644 --- a/fs/xfs/libxfs/xfs_types.h +++ b/fs/xfs/libxfs/xfs_types.h @@ -75,11 +75,14 @@ typedef __int64_t xfs_sfiloff_t; /* signed block number in a file */ * Minimum and maximum blocksize and sectorsize. * The blocksize upper limit is pretty much arbitrary. * The sectorsize upper limit is due to sizeof(sb_sectsize). + * CRC enable filesystems use 512 byte inodes, meaning 512 byte block sizes + * cannot be used. */ #define XFS_MIN_BLOCKSIZE_LOG 9 /* i.e. 512 bytes */ #define XFS_MAX_BLOCKSIZE_LOG 16 /* i.e. 65536 bytes */ #define XFS_MIN_BLOCKSIZE (1 << XFS_MIN_BLOCKSIZE_LOG) #define XFS_MAX_BLOCKSIZE (1 << XFS_MAX_BLOCKSIZE_LOG) +#define XFS_MIN_CRC_BLOCKSIZE (1 << (XFS_MIN_BLOCKSIZE_LOG + 1)) #define XFS_MIN_SECTORSIZE_LOG 9 /* i.e. 512 bytes */ #define XFS_MAX_SECTORSIZE_LOG 15 /* i.e. 32768 bytes */ #define XFS_MIN_SECTORSIZE (1 << XFS_MIN_SECTORSIZE_LOG) From darrick.wong@oracle.com Thu Jun 16 20:18:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C8EE57CA6 for ; Thu, 16 Jun 2016 20:18:45 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8CBC18F804C for ; Thu, 16 Jun 2016 18:18:45 -0700 (PDT) X-ASG-Debug-ID: 1466126323-04cbb01fef694c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id CzYCp1LIm5utKklF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:43 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1IdeO004451 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:40 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IdUL008641 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:39 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Id84026563; Fri, 17 Jun 2016 01:18:39 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:38 -0700 Subject: [PATCH 007/119] xfs: rearrange xfs_bmap_add_free parameters From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 007/119] xfs: rearrange xfs_bmap_add_free parameters To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Christoph Hellwig , Dave Chinner Date: Thu, 16 Jun 2016 18:18:37 -0700 Message-ID: <146612631720.12839.5804944531874278200.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126323 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4285 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines This is already in xfsprogs' libxfs, so port it to the kernel. Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner Reviewed-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_bmap.c | 12 ++++++------ fs/xfs/libxfs/xfs_bmap.h | 4 ++-- fs/xfs/libxfs/xfs_bmap_btree.c | 2 +- fs/xfs/libxfs/xfs_ialloc.c | 9 ++++----- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 499e980..ea7b3df 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -570,10 +570,10 @@ xfs_bmap_validate_ret( */ void xfs_bmap_add_free( + struct xfs_mount *mp, /* mount point structure */ + struct xfs_bmap_free *flist, /* list of extents */ xfs_fsblock_t bno, /* fs block number of extent */ - xfs_filblks_t len, /* length of extent */ - xfs_bmap_free_t *flist, /* list of extents */ - xfs_mount_t *mp) /* mount point structure */ + xfs_filblks_t len) /* length of extent */ { xfs_bmap_free_item_t *cur; /* current (next) element */ xfs_bmap_free_item_t *new; /* new element */ @@ -699,7 +699,7 @@ xfs_bmap_btree_to_extents( cblock = XFS_BUF_TO_BLOCK(cbp); if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) return error; - xfs_bmap_add_free(cbno, 1, cur->bc_private.b.flist, mp); + xfs_bmap_add_free(mp, cur->bc_private.b.flist, cbno, 1); ip->i_d.di_nblocks--; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); @@ -5073,8 +5073,8 @@ xfs_bmap_del_extent( * If we need to, add to list of extents to delete. */ if (do_fx) - xfs_bmap_add_free(del->br_startblock, del->br_blockcount, flist, - mp); + xfs_bmap_add_free(mp, flist, del->br_startblock, + del->br_blockcount); /* * Adjust inode # blocks in the file. */ diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 79e3ebe..0b2f72c 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -191,8 +191,8 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); -void xfs_bmap_add_free(xfs_fsblock_t bno, xfs_filblks_t len, - struct xfs_bmap_free *flist, struct xfs_mount *mp); +void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist, + xfs_fsblock_t bno, xfs_filblks_t len); void xfs_bmap_cancel(struct xfs_bmap_free *flist); int xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist, struct xfs_inode *ip); diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 6282f6e..db0c71e 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -526,7 +526,7 @@ xfs_bmbt_free_block( struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); - xfs_bmap_add_free(fsbno, 1, cur->bc_private.b.flist, mp); + xfs_bmap_add_free(mp, cur->bc_private.b.flist, fsbno, 1); ip->i_d.di_nblocks--; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 77b5990..9d0003c 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -1828,9 +1828,8 @@ xfs_difree_inode_chunk( if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ - xfs_bmap_add_free(XFS_AGB_TO_FSB(mp, agno, - XFS_AGINO_TO_AGBNO(mp, rec->ir_startino)), - mp->m_ialloc_blks, flist, mp); + xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, sagbno), + mp->m_ialloc_blks); return; } @@ -1873,8 +1872,8 @@ xfs_difree_inode_chunk( ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); - xfs_bmap_add_free(XFS_AGB_TO_FSB(mp, agno, agbno), contigblk, - flist, mp); + xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, agbno), + contigblk); /* reset range to current bit and carry on... */ startidx = endidx = nextbit; From darrick.wong@oracle.com Thu Jun 16 20:18:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A4E6A7CC5 for ; Thu, 16 Jun 2016 20:18:51 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2DE07AC001 for ; Thu, 16 Jun 2016 18:18:51 -0700 (PDT) X-ASG-Debug-ID: 1466126328-04bdf01e17957e0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id lZqDiRnaBVZt38uz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:48 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1IkJh004482 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:47 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IkaN012919 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:46 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1IjZ1018032; Fri, 17 Jun 2016 01:18:45 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:45 -0700 Subject: [PATCH 008/119] xfs: separate freelist fixing into a separate helper From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 008/119] xfs: separate freelist fixing into a separate helper To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:43 -0700 Message-ID: <146612632363.12839.15504324533944246285.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126328 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4160 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Break up xfs_free_extent() into a helper that fixes the freelist. This helper will be used subsequently to ensure the freelist during deferred rmap processing. Signed-off-by: Dave Chinner [darrick: refactor to put this at the head of the patchset] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 82 +++++++++++++++++++++++++++++---------------- fs/xfs/libxfs/xfs_alloc.h | 2 + 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 58bdca7..1c76a0e 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2660,55 +2660,79 @@ error0: return error; } -/* - * Free an extent. - * Just break up the extent address and hand off to xfs_free_ag_extent - * after fixing up the freelist. - */ -int /* error */ -xfs_free_extent( - xfs_trans_t *tp, /* transaction pointer */ - xfs_fsblock_t bno, /* starting block number of extent */ - xfs_extlen_t len) /* length of extent */ +/* Ensure that the freelist is at full capacity. */ +int +xfs_free_extent_fix_freelist( + struct xfs_trans *tp, + xfs_agnumber_t agno, + struct xfs_buf **agbp) { - xfs_alloc_arg_t args; - int error; + xfs_alloc_arg_t args; + int error; - ASSERT(len != 0); memset(&args, 0, sizeof(xfs_alloc_arg_t)); args.tp = tp; args.mp = tp->t_mountp; + args.agno = agno; /* * validate that the block number is legal - the enables us to detect * and handle a silent filesystem corruption rather than crashing. */ - args.agno = XFS_FSB_TO_AGNO(args.mp, bno); if (args.agno >= args.mp->m_sb.sb_agcount) return -EFSCORRUPTED; - args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); - if (args.agbno >= args.mp->m_sb.sb_agblocks) - return -EFSCORRUPTED; - args.pag = xfs_perag_get(args.mp, args.agno); ASSERT(args.pag); error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); if (error) - goto error0; + goto out; + + *agbp = args.agbp; +out: + xfs_perag_put(args.pag); + return error; +} + +/* + * Free an extent. + * Just break up the extent address and hand off to xfs_free_ag_extent + * after fixing up the freelist. + */ +int /* error */ +xfs_free_extent( + struct xfs_trans *tp, /* transaction pointer */ + xfs_fsblock_t bno, /* starting block number of extent */ + xfs_extlen_t len) /* length of extent */ +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_buf *agbp; + xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno); + xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); + int error; + + ASSERT(len != 0); + + error = xfs_free_extent_fix_freelist(tp, agno, &agbp); + if (error) + return error; + + XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err); /* validate the extent size is legal now we have the agf locked */ - if (args.agbno + len > - be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) { - error = -EFSCORRUPTED; - goto error0; - } + XFS_WANT_CORRUPTED_GOTO(mp, + agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), + err); - error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); - if (!error) - xfs_extent_busy_insert(tp, args.agno, args.agbno, len, 0); -error0: - xfs_perag_put(args.pag); + error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0); + if (error) + goto err; + + xfs_extent_busy_insert(tp, agno, agbno, len, 0); + return 0; + +err: + xfs_trans_brelse(tp, agbp); return error; } diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 92a66ba..cf268b2 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -229,5 +229,7 @@ xfs_alloc_get_rec( int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); +int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, + struct xfs_buf **agbp); #endif /* __XFS_ALLOC_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:18:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 13BDC7CA6 for ; Thu, 16 Jun 2016 20:18:57 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id DA6058F804C for ; Thu, 16 Jun 2016 18:18:56 -0700 (PDT) X-ASG-Debug-ID: 1466126334-04cb6c5425570c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id KJKxQWyv5Ey3uctG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:18:54 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Iqq2023822 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:52 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Iq6V013023 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:18:52 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1IpQZ026683; Fri, 17 Jun 2016 01:18:51 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:51 -0700 Subject: [PATCH 009/119] xfs: convert list of extents to free into a regular list From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 009/119] xfs: convert list of extents to free into a regular list To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:50 -0700 Message-ID: <146612632997.12839.18026491074892368053.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126334 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7857 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines In struct xfs_bmap_free, convert the open-coded free extent list to a regular list, then use list_sort to sort it prior to processing. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 39 +++++++++++---------------------------- fs/xfs/libxfs/xfs_bmap.h | 14 ++++++++------ fs/xfs/xfs_bmap_util.c | 32 +++++++++++++++++++++++++------- fs/xfs/xfs_bmap_util.h | 1 - fs/xfs/xfs_super.c | 5 +++-- 5 files changed, 47 insertions(+), 44 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index ea7b3df..a5d207a 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -575,9 +575,7 @@ xfs_bmap_add_free( xfs_fsblock_t bno, /* fs block number of extent */ xfs_filblks_t len) /* length of extent */ { - xfs_bmap_free_item_t *cur; /* current (next) element */ - xfs_bmap_free_item_t *new; /* new element */ - xfs_bmap_free_item_t *prev; /* previous element */ + struct xfs_bmap_free_item *new; /* new element */ #ifdef DEBUG xfs_agnumber_t agno; xfs_agblock_t agbno; @@ -597,17 +595,7 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; - for (prev = NULL, cur = flist->xbf_first; - cur != NULL; - prev = cur, cur = cur->xbfi_next) { - if (cur->xbfi_startblock >= bno) - break; - } - if (prev) - prev->xbfi_next = new; - else - flist->xbf_first = new; - new->xbfi_next = cur; + list_add(&new->xbfi_list, &flist->xbf_flist); flist->xbf_count++; } @@ -617,14 +605,10 @@ xfs_bmap_add_free( */ void xfs_bmap_del_free( - xfs_bmap_free_t *flist, /* free item list header */ - xfs_bmap_free_item_t *prev, /* previous item on list, if any */ - xfs_bmap_free_item_t *free) /* list item to be freed */ + struct xfs_bmap_free *flist, /* free item list header */ + struct xfs_bmap_free_item *free) /* list item to be freed */ { - if (prev) - prev->xbfi_next = free->xbfi_next; - else - flist->xbf_first = free->xbfi_next; + list_del(&free->xbfi_list); flist->xbf_count--; kmem_zone_free(xfs_bmap_free_item_zone, free); } @@ -634,17 +618,16 @@ xfs_bmap_del_free( */ void xfs_bmap_cancel( - xfs_bmap_free_t *flist) /* list of bmap_free_items */ + struct xfs_bmap_free *flist) /* list of bmap_free_items */ { - xfs_bmap_free_item_t *free; /* free list item */ - xfs_bmap_free_item_t *next; + struct xfs_bmap_free_item *free; /* free list item */ if (flist->xbf_count == 0) return; - ASSERT(flist->xbf_first != NULL); - for (free = flist->xbf_first; free; free = next) { - next = free->xbfi_next; - xfs_bmap_del_free(flist, NULL, free); + while (!list_empty(&flist->xbf_flist)) { + free = list_first_entry(&flist->xbf_flist, + struct xfs_bmap_free_item, xbfi_list); + xfs_bmap_del_free(flist, free); } ASSERT(flist->xbf_count == 0); } diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 0b2f72c..0ef4c6b 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -62,12 +62,12 @@ struct xfs_bmalloca { * List of extents to be free "later". * The list is kept sorted on xbf_startblock. */ -typedef struct xfs_bmap_free_item +struct xfs_bmap_free_item { xfs_fsblock_t xbfi_startblock;/* starting fs block number */ xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */ - struct xfs_bmap_free_item *xbfi_next; /* link to next entry */ -} xfs_bmap_free_item_t; + struct list_head xbfi_list; +}; /* * Header for free extent list. @@ -85,7 +85,7 @@ typedef struct xfs_bmap_free_item */ typedef struct xfs_bmap_free { - xfs_bmap_free_item_t *xbf_first; /* list of to-be-free extents */ + struct list_head xbf_flist; /* list of to-be-free extents */ int xbf_count; /* count of items on list */ int xbf_low; /* alloc in low mode */ } xfs_bmap_free_t; @@ -141,8 +141,10 @@ static inline int xfs_bmapi_aflag(int w) static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp) { - ((flp)->xbf_first = NULL, (flp)->xbf_count = 0, \ - (flp)->xbf_low = 0, *(fbp) = NULLFSBLOCK); + INIT_LIST_HEAD(&flp->xbf_flist); + flp->xbf_count = 0; + flp->xbf_low = 0; + *fbp = NULLFSBLOCK; } /* diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 28c42fb..1aac0ba 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -79,6 +79,23 @@ xfs_zero_extent( GFP_NOFS, true); } +/* Sort bmap items by AG. */ +static int +xfs_bmap_free_list_cmp( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_mount *mp = priv; + struct xfs_bmap_free_item *ra; + struct xfs_bmap_free_item *rb; + + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); +} + /* * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi * caller. Frees all the extents that need freeing, which must be done @@ -99,14 +116,15 @@ xfs_bmap_finish( int error; /* error return value */ int committed;/* xact committed or not */ struct xfs_bmap_free_item *free; /* free extent item */ - struct xfs_bmap_free_item *next; /* next item on free list */ ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); if (flist->xbf_count == 0) return 0; + list_sort((*tp)->t_mountp, &flist->xbf_flist, xfs_bmap_free_list_cmp); + efi = xfs_trans_get_efi(*tp, flist->xbf_count); - for (free = flist->xbf_first; free; free = free->xbfi_next) + list_for_each_entry(free, &flist->xbf_flist, xbfi_list) xfs_trans_log_efi_extent(*tp, efi, free->xbfi_startblock, free->xbfi_blockcount); @@ -136,15 +154,15 @@ xfs_bmap_finish( * on error. */ efd = xfs_trans_get_efd(*tp, efi, flist->xbf_count); - for (free = flist->xbf_first; free != NULL; free = next) { - next = free->xbfi_next; - + while (!list_empty(&flist->xbf_flist)) { + free = list_first_entry(&flist->xbf_flist, + struct xfs_bmap_free_item, xbfi_list); error = xfs_trans_free_extent(*tp, efd, free->xbfi_startblock, free->xbfi_blockcount); if (error) return error; - xfs_bmap_del_free(flist, NULL, free); + xfs_bmap_del_free(flist, free); } return 0; @@ -797,7 +815,7 @@ xfs_bmap_punch_delalloc_range( if (error) break; - ASSERT(!flist.xbf_count && !flist.xbf_first); + ASSERT(!flist.xbf_count && list_empty(&flist.xbf_flist)); next_block: start_fsb++; remaining--; diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index 1492348..f200714 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h @@ -41,7 +41,6 @@ int xfs_getbmap(struct xfs_inode *ip, struct getbmapx *bmv, /* functions in xfs_bmap.c that are only needed by xfs_bmap_util.c */ void xfs_bmap_del_free(struct xfs_bmap_free *flist, - struct xfs_bmap_free_item *prev, struct xfs_bmap_free_item *free); int xfs_bmap_extsize_align(struct xfs_mount *mp, struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp, xfs_extlen_t extsz, diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 4700f09..09722a7 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1692,8 +1692,9 @@ xfs_init_zones(void) if (!xfs_log_ticket_zone) goto out_free_ioend_bioset; - xfs_bmap_free_item_zone = kmem_zone_init(sizeof(xfs_bmap_free_item_t), - "xfs_bmap_free_item"); + xfs_bmap_free_item_zone = kmem_zone_init( + sizeof(struct xfs_bmap_free_item), + "xfs_bmap_free_item"); if (!xfs_bmap_free_item_zone) goto out_destroy_log_ticket_zone; From darrick.wong@oracle.com Thu Jun 16 20:19:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id CF1A37CB4 for ; Thu, 16 Jun 2016 20:19:02 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 9FD92304051 for ; Thu, 16 Jun 2016 18:19:02 -0700 (PDT) X-ASG-Debug-ID: 1466126340-04cb6c5424570d0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id gwedssGVf0XYlwb7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:00 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1IwhD004570 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:18:58 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Iw72006283 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:18:58 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Iw9N026695; Fri, 17 Jun 2016 01:18:58 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:18:57 -0700 Subject: [PATCH 010/119] xfs: create a standard btree size calculator code From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 010/119] xfs: create a standard btree size calculator code To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:18:56 -0700 Message-ID: <146612633632.12839.13314497569643567486.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126340 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2039 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a helper to generate AG btree height calculator functions. This will be used (much) later when we get to the refcount btree. v2: Use a helper function instead of a macro. v3: We can (theoretically) store more than 2^32 records in a btree, so widen the fields to accept that. v4: Don't modify xfs_bmap_worst_indlen; the purpose of /that/ function is to estimate the worst-case number of blocks needed for a bmbt expansion, not to calculate the space required to store nr records. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_btree.c | 27 +++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_btree.h | 3 +++ 2 files changed, 30 insertions(+) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 105979d..5eb4e40 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -4156,3 +4156,30 @@ xfs_btree_sblock_verify( return true; } + +/* + * Calculate the number of blocks needed to store a given number of records + * in a short-format (per-AG metadata) btree. + */ +xfs_extlen_t +xfs_btree_calc_size( + struct xfs_mount *mp, + uint *limits, + unsigned long long len) +{ + int level; + int maxrecs; + xfs_extlen_t rval; + + maxrecs = limits[0]; + for (level = 0, rval = 0; len > 0; level++) { + len += maxrecs - 1; + do_div(len, maxrecs); + rval += len; + if (len == 1) + return rval; + if (level == 0) + maxrecs = limits[1]; + } + return rval; +} diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 9a88839..b330f19 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -475,4 +475,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block) bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp); bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); +xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, + unsigned long long len); + #endif /* __XFS_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:19:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B41457CEC for ; Thu, 16 Jun 2016 20:19:09 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2EB7FAC004 for ; Thu, 16 Jun 2016 18:19:09 -0700 (PDT) X-ASG-Debug-ID: 1466126346-04cbb01fed69500001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id S4aNIceuijoAJyyU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1J4Kk004879 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:05 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1J42d009198 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:04 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1J49d026740; Fri, 17 Jun 2016 01:19:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:04 -0700 Subject: [PATCH 011/119] xfs: refactor btree maxlevels computation From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 011/119] xfs: refactor btree maxlevels computation To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:02 -0700 Message-ID: <146612634260.12839.10495592169777117935.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126347 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4040 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a common function to calculate the maximum height of a per-AG btree. This will eventually be used by the rmapbt and refcountbt code to calculate appropriate maxlevels values for each. This is important because the verifiers and the transaction block reservations depend on accurate estimates of many blocks are needed to satisfy a btree split. We were mistakenly using the max bnobt height for all the btrees, which creates a dangerous situation since the larger records and keys in an rmapbt make it very possible that the rmapbt will be taller than the bnobt and so we can run out of transaction block reservation. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 15 ++------------- fs/xfs/libxfs/xfs_btree.c | 19 +++++++++++++++++++ fs/xfs/libxfs/xfs_btree.h | 2 ++ fs/xfs/libxfs/xfs_ialloc.c | 19 +++++-------------- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 1c76a0e..c366889 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1839,19 +1839,8 @@ void xfs_alloc_compute_maxlevels( xfs_mount_t *mp) /* file system mount structure */ { - int level; - uint maxblocks; - uint maxleafents; - int minleafrecs; - int minnoderecs; - - maxleafents = (mp->m_sb.sb_agblocks + 1) / 2; - minleafrecs = mp->m_alloc_mnr[0]; - minnoderecs = mp->m_alloc_mnr[1]; - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; - for (level = 1; maxblocks > 1; level++) - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; - mp->m_ag_maxlevels = level; + mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr, + (mp->m_sb.sb_agblocks + 1) / 2); } /* diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 5eb4e40..046fbcf 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -4158,6 +4158,25 @@ xfs_btree_sblock_verify( } /* + * Calculate the number of btree levels needed to store a given number of + * records in a short-format btree. + */ +uint +xfs_btree_compute_maxlevels( + struct xfs_mount *mp, + uint *limits, + unsigned long len) +{ + uint level; + unsigned long maxblocks; + + maxblocks = (len + limits[0] - 1) / limits[0]; + for (level = 1; maxblocks > 1; level++) + maxblocks = (maxblocks + limits[1] - 1) / limits[1]; + return level; +} + +/* * Calculate the number of blocks needed to store a given number of records * in a short-format (per-AG metadata) btree. */ diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index b330f19..b955e5d 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -477,5 +477,7 @@ bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, unsigned long long len); +uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, + unsigned long len); #endif /* __XFS_BTREE_H__ */ diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 9d0003c..cda7269 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -2394,20 +2394,11 @@ void xfs_ialloc_compute_maxlevels( xfs_mount_t *mp) /* file system mount structure */ { - int level; - uint maxblocks; - uint maxleafents; - int minleafrecs; - int minnoderecs; - - maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >> - XFS_INODES_PER_CHUNK_LOG; - minleafrecs = mp->m_inobt_mnr[0]; - minnoderecs = mp->m_inobt_mnr[1]; - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; - for (level = 1; maxblocks > 1; level++) - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; - mp->m_in_maxlevels = level; + uint inodes; + + inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG; + mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr, + inodes); } /* From darrick.wong@oracle.com Thu Jun 16 20:19:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E7F397CBE for ; Thu, 16 Jun 2016 20:19:18 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 99790304039 for ; Thu, 16 Jun 2016 18:19:18 -0700 (PDT) X-ASG-Debug-ID: 1466126355-04bdf01e1795820001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 40WiZfLnMI4AbSlk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:16 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1JDX4005112 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:19:14 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1JDZJ006678 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:13 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JArv006008; Fri, 17 Jun 2016 01:19:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:10 -0700 Subject: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:08 -0700 Message-ID: <146612634887.12839.6210102273046676244.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126356 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10913 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When a btree block has to be split, we pass the new block's ptr from xfs_btree_split() back to xfs_btree_insert() via a pointer parameter; however, we pass the block's key through the cursor's record. It is a little weird to "initialize" a record from a key since the non-key attributes will have garbage values. When we go to add support for interval queries, we have to be able to pass the lowest and highest keys accessible via a pointer. There's no clean way to pass this back through the cursor's record field. Therefore, pass the key directly back to xfs_btree_insert() the same way that we pass the btree_ptr. As a bonus, we no longer need init_rec_from_key and can drop it from the codebase. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc_btree.c | 12 ---------- fs/xfs/libxfs/xfs_bmap_btree.c | 12 ---------- fs/xfs/libxfs/xfs_btree.c | 44 +++++++++++++++++++------------------- fs/xfs/libxfs/xfs_btree.h | 2 -- fs/xfs/libxfs/xfs_ialloc_btree.c | 10 --------- 5 files changed, 22 insertions(+), 58 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c index d9b42425..5ba2dac 100644 --- a/fs/xfs/libxfs/xfs_alloc_btree.c +++ b/fs/xfs/libxfs/xfs_alloc_btree.c @@ -212,17 +212,6 @@ xfs_allocbt_init_key_from_rec( } STATIC void -xfs_allocbt_init_rec_from_key( - union xfs_btree_key *key, - union xfs_btree_rec *rec) -{ - ASSERT(key->alloc.ar_startblock != 0); - - rec->alloc.ar_startblock = key->alloc.ar_startblock; - rec->alloc.ar_blockcount = key->alloc.ar_blockcount; -} - -STATIC void xfs_allocbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -406,7 +395,6 @@ static const struct xfs_btree_ops xfs_allocbt_ops = { .get_minrecs = xfs_allocbt_get_minrecs, .get_maxrecs = xfs_allocbt_get_maxrecs, .init_key_from_rec = xfs_allocbt_init_key_from_rec, - .init_rec_from_key = xfs_allocbt_init_rec_from_key, .init_rec_from_cur = xfs_allocbt_init_rec_from_cur, .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, .key_diff = xfs_allocbt_key_diff, diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index db0c71e..714b387 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -600,17 +600,6 @@ xfs_bmbt_init_key_from_rec( } STATIC void -xfs_bmbt_init_rec_from_key( - union xfs_btree_key *key, - union xfs_btree_rec *rec) -{ - ASSERT(key->bmbt.br_startoff != 0); - - xfs_bmbt_disk_set_allf(&rec->bmbt, be64_to_cpu(key->bmbt.br_startoff), - 0, 0, XFS_EXT_NORM); -} - -STATIC void xfs_bmbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -760,7 +749,6 @@ static const struct xfs_btree_ops xfs_bmbt_ops = { .get_minrecs = xfs_bmbt_get_minrecs, .get_dmaxrecs = xfs_bmbt_get_dmaxrecs, .init_key_from_rec = xfs_bmbt_init_key_from_rec, - .init_rec_from_key = xfs_bmbt_init_rec_from_key, .init_rec_from_cur = xfs_bmbt_init_rec_from_cur, .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, .key_diff = xfs_bmbt_key_diff, diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 046fbcf..a096539 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -2862,10 +2862,9 @@ xfs_btree_make_block_unfull( int *index, /* new tree index */ union xfs_btree_ptr *nptr, /* new btree ptr */ struct xfs_btree_cur **ncur, /* new btree cursor */ - union xfs_btree_rec *nrec, /* new record */ + union xfs_btree_key *key, /* key of new block */ int *stat) { - union xfs_btree_key key; /* new btree key value */ int error = 0; if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && @@ -2910,13 +2909,12 @@ xfs_btree_make_block_unfull( * If this works we have to re-set our variables because we * could be in a different block now. */ - error = xfs_btree_split(cur, level, nptr, &key, ncur, stat); + error = xfs_btree_split(cur, level, nptr, key, ncur, stat); if (error || *stat == 0) return error; *index = cur->bc_ptrs[level]; - cur->bc_ops->init_rec_from_key(&key, nrec); return 0; } @@ -2929,16 +2927,16 @@ xfs_btree_insrec( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level to insert record at */ union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ - union xfs_btree_rec *recp, /* i/o: record data inserted */ + union xfs_btree_key *key, /* i/o: block key for ptrp */ struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ int *stat) /* success/failure */ { struct xfs_btree_block *block; /* btree block */ struct xfs_buf *bp; /* buffer for block */ - union xfs_btree_key key; /* btree key */ union xfs_btree_ptr nptr; /* new block ptr */ struct xfs_btree_cur *ncur; /* new btree cursor */ - union xfs_btree_rec nrec; /* new record count */ + union xfs_btree_key nkey; /* new block key */ + union xfs_btree_rec rec; /* record to insert */ int optr; /* old key/record index */ int ptr; /* key/record index */ int numrecs;/* number of records */ @@ -2947,8 +2945,14 @@ xfs_btree_insrec( int i; #endif + /* Make a key out of the record data to be inserted, and save it. */ + if (level == 0) { + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(key, &rec); + } + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); - XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp); + XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, &rec); ncur = NULL; @@ -2973,9 +2977,6 @@ xfs_btree_insrec( return 0; } - /* Make a key out of the record data to be inserted, and save it. */ - cur->bc_ops->init_key_from_rec(&key, recp); - optr = ptr; XFS_BTREE_STATS_INC(cur, insrec); @@ -2992,10 +2993,10 @@ xfs_btree_insrec( /* Check that the new entry is being inserted in the right place. */ if (ptr <= numrecs) { if (level == 0) { - ASSERT(cur->bc_ops->recs_inorder(cur, recp, + ASSERT(cur->bc_ops->recs_inorder(cur, &rec, xfs_btree_rec_addr(cur, ptr, block))); } else { - ASSERT(cur->bc_ops->keys_inorder(cur, &key, + ASSERT(cur->bc_ops->keys_inorder(cur, key, xfs_btree_key_addr(cur, ptr, block))); } } @@ -3008,7 +3009,7 @@ xfs_btree_insrec( xfs_btree_set_ptr_null(cur, &nptr); if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) { error = xfs_btree_make_block_unfull(cur, level, numrecs, - &optr, &ptr, &nptr, &ncur, &nrec, stat); + &optr, &ptr, &nptr, &ncur, &nkey, stat); if (error || *stat == 0) goto error0; } @@ -3058,7 +3059,7 @@ xfs_btree_insrec( #endif /* Now put the new data in, bump numrecs and log it. */ - xfs_btree_copy_keys(cur, kp, &key, 1); + xfs_btree_copy_keys(cur, kp, key, 1); xfs_btree_copy_ptrs(cur, pp, ptrp, 1); numrecs++; xfs_btree_set_numrecs(block, numrecs); @@ -3079,7 +3080,7 @@ xfs_btree_insrec( xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1); /* Now put the new data in, bump numrecs and log it. */ - xfs_btree_copy_recs(cur, rp, recp, 1); + xfs_btree_copy_recs(cur, rp, &rec, 1); xfs_btree_set_numrecs(block, ++numrecs); xfs_btree_log_recs(cur, bp, ptr, numrecs); #ifdef DEBUG @@ -3095,7 +3096,7 @@ xfs_btree_insrec( /* If we inserted at the start of a block, update the parents' keys. */ if (optr == 1) { - error = xfs_btree_updkey(cur, &key, level + 1); + error = xfs_btree_updkey(cur, key, level + 1); if (error) goto error0; } @@ -3105,7 +3106,7 @@ xfs_btree_insrec( * we are at the far right edge of the tree, update it. */ if (xfs_btree_is_lastrec(cur, block, level)) { - cur->bc_ops->update_lastrec(cur, block, recp, + cur->bc_ops->update_lastrec(cur, block, &rec, ptr, LASTREC_INSREC); } @@ -3115,7 +3116,7 @@ xfs_btree_insrec( */ *ptrp = nptr; if (!xfs_btree_ptr_is_null(cur, &nptr)) { - *recp = nrec; + *key = nkey; *curp = ncur; } @@ -3146,14 +3147,13 @@ xfs_btree_insert( union xfs_btree_ptr nptr; /* new block number (split result) */ struct xfs_btree_cur *ncur; /* new cursor (split result) */ struct xfs_btree_cur *pcur; /* previous level's cursor */ - union xfs_btree_rec rec; /* record to insert */ + union xfs_btree_key key; /* key of block to insert */ level = 0; ncur = NULL; pcur = cur; xfs_btree_set_ptr_null(cur, &nptr); - cur->bc_ops->init_rec_from_cur(cur, &rec); /* * Loop going up the tree, starting at the leaf level. @@ -3165,7 +3165,7 @@ xfs_btree_insert( * Insert nrec/nptr into this level of the tree. * Note if we fail, nptr will be null. */ - error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i); + error = xfs_btree_insrec(pcur, level, &nptr, &key, &ncur, &i); if (error) { if (pcur != cur) xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index b955e5d..b99c018 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -158,8 +158,6 @@ struct xfs_btree_ops { /* init values of btree structures */ void (*init_key_from_rec)(union xfs_btree_key *key, union xfs_btree_rec *rec); - void (*init_rec_from_key)(union xfs_btree_key *key, - union xfs_btree_rec *rec); void (*init_rec_from_cur)(struct xfs_btree_cur *cur, union xfs_btree_rec *rec); void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index 89c21d7..88da2ad 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c @@ -146,14 +146,6 @@ xfs_inobt_init_key_from_rec( } STATIC void -xfs_inobt_init_rec_from_key( - union xfs_btree_key *key, - union xfs_btree_rec *rec) -{ - rec->inobt.ir_startino = key->inobt.ir_startino; -} - -STATIC void xfs_inobt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -314,7 +306,6 @@ static const struct xfs_btree_ops xfs_inobt_ops = { .get_minrecs = xfs_inobt_get_minrecs, .get_maxrecs = xfs_inobt_get_maxrecs, .init_key_from_rec = xfs_inobt_init_key_from_rec, - .init_rec_from_key = xfs_inobt_init_rec_from_key, .init_rec_from_cur = xfs_inobt_init_rec_from_cur, .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, @@ -336,7 +327,6 @@ static const struct xfs_btree_ops xfs_finobt_ops = { .get_minrecs = xfs_inobt_get_minrecs, .get_maxrecs = xfs_inobt_get_maxrecs, .init_key_from_rec = xfs_inobt_init_key_from_rec, - .init_rec_from_key = xfs_inobt_init_rec_from_key, .init_rec_from_cur = xfs_inobt_init_rec_from_cur, .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, From darrick.wong@oracle.com Thu Jun 16 20:19:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 098ED7CF7 for ; Thu, 16 Jun 2016 20:19:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id CC8B3304039 for ; Thu, 16 Jun 2016 18:19:24 -0700 (PDT) X-ASG-Debug-ID: 1466126360-04cbb01fec69520001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id W99Or6Yj2h7iRM9y (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1JISh024372 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:18 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JIqh013647 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:18 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JHUQ018229; Fri, 17 Jun 2016 01:19:17 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:16 -0700 Subject: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:15 -0700 Message-ID: <146612635526.12839.13865365567940815077.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126360 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 26085 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On a filesystem with both reflink and reverse mapping enabled, it's possible to have multiple rmap records referring to the same blocks on disk. When overlapping intervals are possible, querying a classic btree to find all records intersecting a given interval is inefficient because we cannot use the left side of the search interval to filter out non-matching records the same way that we can use the existing btree key to filter out records coming after the right side of the search interval. This will become important once we want to use the rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl. (For the non-overlapping case, we can perform such queries trivially by starting at the left side of the interval and walking the tree until we pass the right side.) Therefore, extend the btree code to come closer to supporting intervals as a first-class record attribute. This involves widening the btree node's key space to store both the lowest key reachable via the node pointer (as the btree does now) and the highest key reachable via the same pointer and teaching the btree modifying functions to keep the highest-key records up to date. This behavior can be turned on via a new btree ops flag so that btrees that cannot store overlapping intervals don't pay the overhead costs in terms of extra code and disk format changes. v2: When we're deleting a record in a btree that supports overlapped interval records and the deletion results in two btree blocks being joined, we defer updating the high/low keys until after all possible joining (at higher levels in the tree) have finished. At this point, the btree pointers at all levels have been updated to remove the empty blocks and we can update the low and high keys. When we're doing this, we must be careful to update the keys of all node pointers up to the root instead of stopping at the first set of keys that don't need updating. This is because it's possible for a single deletion to cause joining of multiple levels of tree, and so we need to update everything going back to the root. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_btree.c | 379 +++++++++++++++++++++++++++++++++++++++++---- fs/xfs/libxfs/xfs_btree.h | 16 ++ fs/xfs/xfs_trace.h | 36 ++++ 3 files changed, 395 insertions(+), 36 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index a096539..afcafd6 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -52,6 +52,11 @@ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] +struct xfs_btree_double_key { + union xfs_btree_key low; + union xfs_btree_key high; +}; + STATIC int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_lblock( struct xfs_btree_cur *cur, /* btree cursor */ @@ -428,6 +433,30 @@ xfs_btree_dup_cursor( * into a btree block (xfs_btree_*_offset) or return a pointer to the given * record, key or pointer (xfs_btree_*_addr). Note that all addressing * inside the btree block is done using indices starting at one, not zero! + * + * If XFS_BTREE_OVERLAPPING is set, then this btree supports keys containing + * overlapping intervals. In such a tree, records are still sorted lowest to + * highest and indexed by the smallest key value that refers to the record. + * However, nodes are different: each pointer has two associated keys -- one + * indexing the lowest key available in the block(s) below (the same behavior + * as the key in a regular btree) and another indexing the highest key + * available in the block(s) below. Because records are /not/ sorted by the + * highest key, all leaf block updates require us to compute the highest key + * that matches any record in the leaf and to recursively update the high keys + * in the nodes going further up in the tree, if necessary. Nodes look like + * this: + * + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ + * Non-Leaf: | header | lo1 | hi1 | lo2 | hi2 | ... | ptr 1 | ptr 2 | ... | + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ + * + * To perform an interval query on an overlapped tree, perform the usual + * depth-first search and use the low and high keys to decide if we can skip + * that particular node. If a leaf node is reached, return the records that + * intersect the interval. Note that an interval query may return numerous + * entries. For a non-overlapped tree, simply search for the record associated + * with the lowest key and iterate forward until a non-matching record is + * found. */ /* @@ -445,6 +474,17 @@ static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur) return XFS_BTREE_SBLOCK_LEN; } +/* Return size of btree block keys for this btree instance. */ +static inline size_t xfs_btree_key_len(struct xfs_btree_cur *cur) +{ + size_t len; + + len = cur->bc_ops->key_len; + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) + len *= 2; + return len; +} + /* * Return size of btree block pointers for this btree instance. */ @@ -475,7 +515,19 @@ xfs_btree_key_offset( int n) { return xfs_btree_block_len(cur) + - (n - 1) * cur->bc_ops->key_len; + (n - 1) * xfs_btree_key_len(cur); +} + +/* + * Calculate offset of the n-th high key in a btree block. + */ +STATIC size_t +xfs_btree_high_key_offset( + struct xfs_btree_cur *cur, + int n) +{ + return xfs_btree_block_len(cur) + + (n - 1) * xfs_btree_key_len(cur) + cur->bc_ops->key_len; } /* @@ -488,7 +540,7 @@ xfs_btree_ptr_offset( int level) { return xfs_btree_block_len(cur) + - cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len + + cur->bc_ops->get_maxrecs(cur, level) * xfs_btree_key_len(cur) + (n - 1) * xfs_btree_ptr_len(cur); } @@ -519,6 +571,19 @@ xfs_btree_key_addr( } /* + * Return a pointer to the n-th high key in the btree block. + */ +STATIC union xfs_btree_key * +xfs_btree_high_key_addr( + struct xfs_btree_cur *cur, + int n, + struct xfs_btree_block *block) +{ + return (union xfs_btree_key *) + ((char *)block + xfs_btree_high_key_offset(cur, n)); +} + +/* * Return a pointer to the n-th block pointer in the btree block. */ STATIC union xfs_btree_ptr * @@ -1217,7 +1282,7 @@ xfs_btree_copy_keys( int numkeys) { ASSERT(numkeys >= 0); - memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len); + memcpy(dst_key, src_key, numkeys * xfs_btree_key_len(cur)); } /* @@ -1263,8 +1328,8 @@ xfs_btree_shift_keys( ASSERT(numkeys >= 0); ASSERT(dir == 1 || dir == -1); - dst_key = (char *)key + (dir * cur->bc_ops->key_len); - memmove(dst_key, key, numkeys * cur->bc_ops->key_len); + dst_key = (char *)key + (dir * xfs_btree_key_len(cur)); + memmove(dst_key, key, numkeys * xfs_btree_key_len(cur)); } /* @@ -1879,6 +1944,180 @@ error0: return error; } +/* Determine the low and high keys of a leaf block */ +STATIC void +xfs_btree_find_leaf_keys( + struct xfs_btree_cur *cur, + struct xfs_btree_block *block, + union xfs_btree_key *low, + union xfs_btree_key *high) +{ + int n; + union xfs_btree_rec *rec; + union xfs_btree_key max_hkey; + union xfs_btree_key hkey; + + rec = xfs_btree_rec_addr(cur, 1, block); + cur->bc_ops->init_key_from_rec(low, rec); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return; + + cur->bc_ops->init_high_key_from_rec(&max_hkey, rec); + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { + rec = xfs_btree_rec_addr(cur, n, block); + cur->bc_ops->init_high_key_from_rec(&hkey, rec); + if (cur->bc_ops->diff_two_keys(cur, &max_hkey, &hkey) > 0) + max_hkey = hkey; + } + + *high = max_hkey; +} + +/* Determine the low and high keys of a node block */ +STATIC void +xfs_btree_find_node_keys( + struct xfs_btree_cur *cur, + struct xfs_btree_block *block, + union xfs_btree_key *low, + union xfs_btree_key *high) +{ + int n; + union xfs_btree_key *hkey; + union xfs_btree_key *max_hkey; + + *low = *xfs_btree_key_addr(cur, 1, block); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return; + + max_hkey = xfs_btree_high_key_addr(cur, 1, block); + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { + hkey = xfs_btree_high_key_addr(cur, n, block); + if (cur->bc_ops->diff_two_keys(cur, max_hkey, hkey) > 0) + max_hkey = hkey; + } + + *high = *max_hkey; +} + +/* + * Update parental low & high keys from some block all the way back to the + * root of the btree. + */ +STATIC int +__xfs_btree_updkeys( + struct xfs_btree_cur *cur, + int level, + struct xfs_btree_block *block, + struct xfs_buf *bp0, + bool force_all) +{ + union xfs_btree_key lkey; /* keys from current level */ + union xfs_btree_key hkey; + union xfs_btree_key *nlkey; /* keys from the next level up */ + union xfs_btree_key *nhkey; + struct xfs_buf *bp; + int ptr = -1; + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return 0; + + if (level + 1 >= cur->bc_nlevels) + return 0; + + trace_xfs_btree_updkeys(cur, level, bp0); + + if (level == 0) + xfs_btree_find_leaf_keys(cur, block, &lkey, &hkey); + else + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); + for (level++; level < cur->bc_nlevels; level++) { + block = xfs_btree_get_block(cur, level, &bp); + trace_xfs_btree_updkeys(cur, level, bp); + ptr = cur->bc_ptrs[level]; + nlkey = xfs_btree_key_addr(cur, ptr, block); + nhkey = xfs_btree_high_key_addr(cur, ptr, block); + if (!(cur->bc_ops->diff_two_keys(cur, nlkey, &lkey) != 0 || + cur->bc_ops->diff_two_keys(cur, nhkey, &hkey) != 0) && + !force_all) + break; + memcpy(nlkey, &lkey, cur->bc_ops->key_len); + memcpy(nhkey, &hkey, cur->bc_ops->key_len); + xfs_btree_log_keys(cur, bp, ptr, ptr); + if (level + 1 >= cur->bc_nlevels) + break; + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); + } + + return 0; +} + +/* + * Update all the keys from a sibling block at some level in the cursor back + * to the root, stopping when we find a key pair that doesn't need updating. + */ +STATIC int +xfs_btree_sibling_updkeys( + struct xfs_btree_cur *cur, + int level, + int ptr, + struct xfs_btree_block *block, + struct xfs_buf *bp0) +{ + struct xfs_btree_cur *ncur; + int stat; + int error; + + error = xfs_btree_dup_cursor(cur, &ncur); + if (error) + return error; + + if (level + 1 >= ncur->bc_nlevels) + error = -EDOM; + else if (ptr == XFS_BB_RIGHTSIB) + error = xfs_btree_increment(ncur, level + 1, &stat); + else if (ptr == XFS_BB_LEFTSIB) + error = xfs_btree_decrement(ncur, level + 1, &stat); + else + error = -EBADE; + if (error || !stat) + return error; + + error = __xfs_btree_updkeys(ncur, level, block, bp0, false); + xfs_btree_del_cursor(ncur, XFS_BTREE_NOERROR); + return error; +} + +/* + * Update all the keys from some level in cursor back to the root, stopping + * when we find a key pair that don't need updating. + */ +STATIC int +xfs_btree_updkeys( + struct xfs_btree_cur *cur, + int level) +{ + struct xfs_buf *bp; + struct xfs_btree_block *block; + + block = xfs_btree_get_block(cur, level, &bp); + return __xfs_btree_updkeys(cur, level, block, bp, false); +} + +/* Update all the keys from some level in cursor back to the root. */ +STATIC int +xfs_btree_updkeys_force( + struct xfs_btree_cur *cur, + int level) +{ + struct xfs_buf *bp; + struct xfs_btree_block *block; + + block = xfs_btree_get_block(cur, level, &bp); + return __xfs_btree_updkeys(cur, level, block, bp, true); +} + /* * Update keys at all levels from here to the root along the cursor's path. */ @@ -1893,6 +2132,9 @@ xfs_btree_updkey( union xfs_btree_key *kp; int ptr; + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) + return 0; + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGIK(cur, level, keyp); @@ -1970,7 +2212,8 @@ xfs_btree_update( ptr, LASTREC_UPDATE); } - /* Updating first rec in leaf. Pass new key value up to our parent. */ + /* Pass new key value up to our parent. */ + xfs_btree_updkeys(cur, 0); if (ptr == 1) { union xfs_btree_key key; @@ -2149,7 +2392,9 @@ xfs_btree_lshift( rkp = &key; } - /* Update the parent key values of right. */ + /* Update the parent key values of left and right. */ + xfs_btree_sibling_updkeys(cur, level, XFS_BB_LEFTSIB, left, lbp); + xfs_btree_updkeys(cur, level); error = xfs_btree_updkey(cur, rkp, level + 1); if (error) goto error0; @@ -2321,6 +2566,9 @@ xfs_btree_rshift( if (error) goto error1; + /* Update left and right parent pointers */ + xfs_btree_updkeys(cur, level); + xfs_btree_updkeys(tcur, level); error = xfs_btree_updkey(tcur, rkp, level + 1); if (error) goto error1; @@ -2356,7 +2604,7 @@ __xfs_btree_split( struct xfs_btree_cur *cur, int level, union xfs_btree_ptr *ptrp, - union xfs_btree_key *key, + struct xfs_btree_double_key *key, struct xfs_btree_cur **curp, int *stat) /* success/failure */ { @@ -2452,9 +2700,6 @@ __xfs_btree_split( xfs_btree_log_keys(cur, rbp, 1, rrecs); xfs_btree_log_ptrs(cur, rbp, 1, rrecs); - - /* Grab the keys to the entries moved to the right block */ - xfs_btree_copy_keys(cur, key, rkp, 1); } else { /* It's a leaf. Move records. */ union xfs_btree_rec *lrp; /* left record pointer */ @@ -2465,12 +2710,8 @@ __xfs_btree_split( xfs_btree_copy_recs(cur, rrp, lrp, rrecs); xfs_btree_log_recs(cur, rbp, 1, rrecs); - - cur->bc_ops->init_key_from_rec(key, - xfs_btree_rec_addr(cur, 1, right)); } - /* * Find the left block number by looking in the buffer. * Adjust numrecs, sibling pointers. @@ -2484,6 +2725,12 @@ __xfs_btree_split( xfs_btree_set_numrecs(left, lrecs); xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs); + /* Find the low & high keys for the new block. */ + if (level > 0) + xfs_btree_find_node_keys(cur, right, &key->low, &key->high); + else + xfs_btree_find_leaf_keys(cur, right, &key->low, &key->high); + xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS); xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); @@ -2499,6 +2746,10 @@ __xfs_btree_split( xfs_btree_set_sibling(cur, rrblock, &rptr, XFS_BB_LEFTSIB); xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB); } + + /* Update the left block's keys... */ + xfs_btree_updkeys(cur, level); + /* * If the cursor is really in the right block, move it there. * If it's just pointing past the last entry in left, then we'll @@ -2537,7 +2788,7 @@ struct xfs_btree_split_args { struct xfs_btree_cur *cur; int level; union xfs_btree_ptr *ptrp; - union xfs_btree_key *key; + struct xfs_btree_double_key *key; struct xfs_btree_cur **curp; int *stat; /* success/failure */ int result; @@ -2586,7 +2837,7 @@ xfs_btree_split( struct xfs_btree_cur *cur, int level, union xfs_btree_ptr *ptrp, - union xfs_btree_key *key, + struct xfs_btree_double_key *key, struct xfs_btree_cur **curp, int *stat) /* success/failure */ { @@ -2806,27 +3057,27 @@ xfs_btree_new_root( bp = lbp; nptr = 2; } + /* Fill in the new block's btree header and log it. */ xfs_btree_init_block_cur(cur, nbp, cur->bc_nlevels, 2); xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS); ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) && !xfs_btree_ptr_is_null(cur, &rptr)); - /* Fill in the key data in the new root. */ if (xfs_btree_get_level(left) > 0) { - xfs_btree_copy_keys(cur, + xfs_btree_find_node_keys(cur, left, xfs_btree_key_addr(cur, 1, new), - xfs_btree_key_addr(cur, 1, left), 1); - xfs_btree_copy_keys(cur, + xfs_btree_high_key_addr(cur, 1, new)); + xfs_btree_find_node_keys(cur, right, xfs_btree_key_addr(cur, 2, new), - xfs_btree_key_addr(cur, 1, right), 1); + xfs_btree_high_key_addr(cur, 2, new)); } else { - cur->bc_ops->init_key_from_rec( - xfs_btree_key_addr(cur, 1, new), - xfs_btree_rec_addr(cur, 1, left)); - cur->bc_ops->init_key_from_rec( - xfs_btree_key_addr(cur, 2, new), - xfs_btree_rec_addr(cur, 1, right)); + xfs_btree_find_leaf_keys(cur, left, + xfs_btree_key_addr(cur, 1, new), + xfs_btree_high_key_addr(cur, 1, new)); + xfs_btree_find_leaf_keys(cur, right, + xfs_btree_key_addr(cur, 2, new), + xfs_btree_high_key_addr(cur, 2, new)); } xfs_btree_log_keys(cur, nbp, 1, 2); @@ -2837,6 +3088,7 @@ xfs_btree_new_root( xfs_btree_ptr_addr(cur, 2, new), &rptr, 1); xfs_btree_log_ptrs(cur, nbp, 1, 2); + /* Fix up the cursor. */ xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); cur->bc_ptrs[cur->bc_nlevels] = nptr; @@ -2862,7 +3114,7 @@ xfs_btree_make_block_unfull( int *index, /* new tree index */ union xfs_btree_ptr *nptr, /* new btree ptr */ struct xfs_btree_cur **ncur, /* new btree cursor */ - union xfs_btree_key *key, /* key of new block */ + struct xfs_btree_double_key *key, /* key of new block */ int *stat) { int error = 0; @@ -2918,6 +3170,22 @@ xfs_btree_make_block_unfull( return 0; } +/* Copy a double key into a btree block. */ +static void +xfs_btree_copy_double_keys( + struct xfs_btree_cur *cur, + int ptr, + struct xfs_btree_block *block, + struct xfs_btree_double_key *key) +{ + memcpy(xfs_btree_key_addr(cur, ptr, block), &key->low, + cur->bc_ops->key_len); + + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) + memcpy(xfs_btree_high_key_addr(cur, ptr, block), &key->high, + cur->bc_ops->key_len); +} + /* * Insert one record/level. Return information to the caller * allowing the next level up to proceed if necessary. @@ -2927,7 +3195,7 @@ xfs_btree_insrec( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level to insert record at */ union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ - union xfs_btree_key *key, /* i/o: block key for ptrp */ + struct xfs_btree_double_key *key, /* i/o: block key for ptrp */ struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ int *stat) /* success/failure */ { @@ -2935,7 +3203,7 @@ xfs_btree_insrec( struct xfs_buf *bp; /* buffer for block */ union xfs_btree_ptr nptr; /* new block ptr */ struct xfs_btree_cur *ncur; /* new btree cursor */ - union xfs_btree_key nkey; /* new block key */ + struct xfs_btree_double_key nkey; /* new block key */ union xfs_btree_rec rec; /* record to insert */ int optr; /* old key/record index */ int ptr; /* key/record index */ @@ -2944,11 +3212,12 @@ xfs_btree_insrec( #ifdef DEBUG int i; #endif + xfs_daddr_t old_bn; /* Make a key out of the record data to be inserted, and save it. */ if (level == 0) { cur->bc_ops->init_rec_from_cur(cur, &rec); - cur->bc_ops->init_key_from_rec(key, &rec); + cur->bc_ops->init_key_from_rec(&key->low, &rec); } XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); @@ -2983,6 +3252,7 @@ xfs_btree_insrec( /* Get pointers to the btree buffer and block. */ block = xfs_btree_get_block(cur, level, &bp); + old_bn = bp ? bp->b_bn : XFS_BUF_DADDR_NULL; numrecs = xfs_btree_get_numrecs(block); #ifdef DEBUG @@ -2996,7 +3266,7 @@ xfs_btree_insrec( ASSERT(cur->bc_ops->recs_inorder(cur, &rec, xfs_btree_rec_addr(cur, ptr, block))); } else { - ASSERT(cur->bc_ops->keys_inorder(cur, key, + ASSERT(cur->bc_ops->keys_inorder(cur, &key->low, xfs_btree_key_addr(cur, ptr, block))); } } @@ -3059,7 +3329,7 @@ xfs_btree_insrec( #endif /* Now put the new data in, bump numrecs and log it. */ - xfs_btree_copy_keys(cur, kp, key, 1); + xfs_btree_copy_double_keys(cur, ptr, block, key); xfs_btree_copy_ptrs(cur, pp, ptrp, 1); numrecs++; xfs_btree_set_numrecs(block, numrecs); @@ -3095,8 +3365,24 @@ xfs_btree_insrec( xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); /* If we inserted at the start of a block, update the parents' keys. */ + if (ncur && bp->b_bn != old_bn) { + /* + * We just inserted into a new tree block, which means that + * the key for the block is in nkey, not the tree. + */ + if (level == 0) + xfs_btree_find_leaf_keys(cur, block, &nkey.low, + &nkey.high); + else + xfs_btree_find_node_keys(cur, block, &nkey.low, + &nkey.high); + } else { + /* Updating the left block, do it the standard way. */ + xfs_btree_updkeys(cur, level); + } + if (optr == 1) { - error = xfs_btree_updkey(cur, key, level + 1); + error = xfs_btree_updkey(cur, &key->low, level + 1); if (error) goto error0; } @@ -3147,7 +3433,7 @@ xfs_btree_insert( union xfs_btree_ptr nptr; /* new block number (split result) */ struct xfs_btree_cur *ncur; /* new cursor (split result) */ struct xfs_btree_cur *pcur; /* previous level's cursor */ - union xfs_btree_key key; /* key of block to insert */ + struct xfs_btree_double_key key; /* key of block to insert */ level = 0; ncur = NULL; @@ -3552,6 +3838,7 @@ xfs_btree_delrec( * If we deleted the leftmost entry in the block, update the * key values above us in the tree. */ + xfs_btree_updkeys(cur, level); if (ptr == 1) { error = xfs_btree_updkey(cur, keyp, level + 1); if (error) @@ -3882,6 +4169,16 @@ xfs_btree_delrec( if (level > 0) cur->bc_ptrs[level]--; + /* + * We combined blocks, so we have to update the parent keys if the + * btree supports overlapped intervals. However, bc_ptrs[level + 1] + * points to the old block so that the caller knows which record to + * delete. Therefore, the caller must be savvy enough to call updkeys + * for us if we return stat == 2. The other exit points from this + * function don't require deletions further up the tree, so they can + * call updkeys directly. + */ + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); /* Return value means the next level up has something to do. */ *stat = 2; @@ -3907,6 +4204,7 @@ xfs_btree_delete( int error; /* error return value */ int level; int i; + bool joined = false; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); @@ -3920,8 +4218,17 @@ xfs_btree_delete( error = xfs_btree_delrec(cur, level, &i); if (error) goto error0; + if (i == 2) + joined = true; } + /* + * If we combined blocks as part of deleting the record, delrec won't + * have updated the parent keys so we have to do that here. + */ + if (joined) + xfs_btree_updkeys_force(cur, 0); + if (i == 0) { for (level = 1; level < cur->bc_nlevels; level++) { if (cur->bc_ptrs[level] == 0) { diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index b99c018..a5ec6c7 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -126,6 +126,9 @@ struct xfs_btree_ops { size_t key_len; size_t rec_len; + /* flags */ + uint flags; + /* cursor operations */ struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); void (*update_cursor)(struct xfs_btree_cur *src, @@ -162,11 +165,21 @@ struct xfs_btree_ops { union xfs_btree_rec *rec); void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr); + void (*init_high_key_from_rec)(union xfs_btree_key *key, + union xfs_btree_rec *rec); /* difference between key value and cursor value */ __int64_t (*key_diff)(struct xfs_btree_cur *cur, union xfs_btree_key *key); + /* + * Difference between key2 and key1 -- positive if key2 > key1, + * negative if key2 < key1, and zero if equal. + */ + __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur, + union xfs_btree_key *key1, + union xfs_btree_key *key2); + const struct xfs_buf_ops *buf_ops; #if defined(DEBUG) || defined(XFS_WARN) @@ -182,6 +195,9 @@ struct xfs_btree_ops { #endif }; +/* btree ops flags */ +#define XFS_BTREE_OPS_OVERLAPPING (1<<0) /* overlapping intervals */ + /* * Reasons for the update_lastrec method to be called. */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 68f27f7..ffea28c 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -38,6 +38,7 @@ struct xlog_recover_item; struct xfs_buf_log_format; struct xfs_inode_log_format; struct xfs_bmbt_irec; +struct xfs_btree_cur; DECLARE_EVENT_CLASS(xfs_attr_list_class, TP_PROTO(struct xfs_attr_list_context *ctx), @@ -2183,6 +2184,41 @@ DEFINE_DISCARD_EVENT(xfs_discard_toosmall); DEFINE_DISCARD_EVENT(xfs_discard_exclude); DEFINE_DISCARD_EVENT(xfs_discard_busy); +/* btree cursor events */ +DECLARE_EVENT_CLASS(xfs_btree_cur_class, + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), + TP_ARGS(cur, level, bp), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_btnum_t, btnum) + __field(int, level) + __field(int, nlevels) + __field(int, ptr) + __field(xfs_daddr_t, daddr) + ), + TP_fast_assign( + __entry->dev = cur->bc_mp->m_super->s_dev; + __entry->btnum = cur->bc_btnum; + __entry->level = level; + __entry->nlevels = cur->bc_nlevels; + __entry->ptr = cur->bc_ptrs[level]; + __entry->daddr = bp->b_bn; + ), + TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->btnum, + __entry->level, + __entry->nlevels, + __entry->ptr, + (unsigned long long)__entry->daddr) +) + +#define DEFINE_BTREE_CUR_EVENT(name) \ +DEFINE_EVENT(xfs_btree_cur_class, name, \ + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ + TP_ARGS(cur, level, bp)) +DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:19:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 63FB17CBE for ; Thu, 16 Jun 2016 20:19:30 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 14A148F804B for ; Thu, 16 Jun 2016 18:19:30 -0700 (PDT) X-ASG-Debug-ID: 1466126367-04bdf01e1595830001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id NFhsQPxmXdhNvjnk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:27 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1JOK1024414 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:19:24 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1JOL0006832 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:24 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JNnP022514; Fri, 17 Jun 2016 01:19:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:23 -0700 Subject: [PATCH 014/119] xfs: introduce interval queries on btrees From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 014/119] xfs: introduce interval queries on btrees To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:21 -0700 Message-ID: <146612636170.12839.675596870201079078.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126367 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10146 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a function to enable querying of btree records mapping to a range of keys. This will be used in subsequent patches to allow querying the reverse mapping btree to find the extents mapped to a range of physical blocks, though the generic code can be used for any range query. v2: add some shortcuts so that we can jump out of processing once we know there won't be any more records to find. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_btree.c | 249 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_btree.h | 22 +++- fs/xfs/xfs_trace.h | 1 3 files changed, 267 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index afcafd6..5f5cf23 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -4509,3 +4509,252 @@ xfs_btree_calc_size( } return rval; } + +/* Query a regular btree for all records overlapping a given interval. */ +STATIC int +xfs_btree_simple_query_range( + struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, + union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, + void *priv) +{ + union xfs_btree_rec *recp; + union xfs_btree_rec rec; + union xfs_btree_key low_key; + union xfs_btree_key high_key; + union xfs_btree_key rec_key; + __int64_t diff; + int stat; + bool firstrec = true; + int error; + + ASSERT(cur->bc_ops->init_high_key_from_rec); + + /* Find the keys of both ends of the interval. */ + cur->bc_rec = *high_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&high_key, &rec); + + cur->bc_rec = *low_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&low_key, &rec); + + /* Find the leftmost record. */ + stat = 0; + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat); + if (error) + goto out; + + while (stat) { + /* Find the record. */ + error = xfs_btree_get_rec(cur, &recp, &stat); + if (error || !stat) + break; + + /* Can we tell if this record is too low? */ + if (firstrec) { + cur->bc_rec = *low_rec; + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); + diff = cur->bc_ops->key_diff(cur, &rec_key); + if (diff < 0) + goto advloop; + } + firstrec = false; + + /* Have we gone past the end? */ + cur->bc_rec = *high_rec; + cur->bc_ops->init_key_from_rec(&rec_key, recp); + diff = cur->bc_ops->key_diff(cur, &rec_key); + if (diff > 0) + break; + + /* Callback */ + error = fn(cur, recp, priv); + if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) + break; + +advloop: + /* Move on to the next record. */ + error = xfs_btree_increment(cur, 0, &stat); + if (error) + break; + } + +out: + return error; +} + +/* + * Query an overlapped interval btree for all records overlapping a given + * interval. + */ +STATIC int +xfs_btree_overlapped_query_range( + struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, + union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, + void *priv) +{ + union xfs_btree_ptr ptr; + union xfs_btree_ptr *pp; + union xfs_btree_key rec_key; + union xfs_btree_key low_key; + union xfs_btree_key high_key; + union xfs_btree_key *lkp; + union xfs_btree_key *hkp; + union xfs_btree_rec rec; + union xfs_btree_rec *recp; + struct xfs_btree_block *block; + __int64_t ldiff; + __int64_t hdiff; + int level; + struct xfs_buf *bp; + int i; + int error; + + /* Find the keys of both ends of the interval. */ + cur->bc_rec = *high_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&high_key, &rec); + + cur->bc_rec = *low_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&low_key, &rec); + + /* Load the root of the btree. */ + level = cur->bc_nlevels - 1; + cur->bc_ops->init_ptr_from_cur(cur, &ptr); + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); + if (error) + return error; + xfs_btree_get_block(cur, level, &bp); + trace_xfs_btree_overlapped_query_range(cur, level, bp); +#ifdef DEBUG + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; +#endif + cur->bc_ptrs[level] = 1; + + while (level < cur->bc_nlevels) { + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); + + if (level == 0) { + /* End of leaf, pop back towards the root. */ + if (cur->bc_ptrs[level] > + be16_to_cpu(block->bb_numrecs)) { +leaf_pop_up: + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); + + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, + &rec_key); + + cur->bc_ops->init_key_from_rec(&rec_key, recp); + hdiff = cur->bc_ops->diff_two_keys(cur, &rec_key, + &high_key); + + /* If the record matches, callback */ + if (ldiff >= 0 && hdiff >= 0) { + error = fn(cur, recp, priv); + if (error < 0 || + error == XFS_BTREE_QUERY_RANGE_ABORT) + break; + } else if (hdiff < 0) { + /* Record is larger than high key; pop. */ + goto leaf_pop_up; + } + cur->bc_ptrs[level]++; + continue; + } + + /* End of node, pop back towards the root. */ + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { +node_pop_up: + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); + hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); + + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, hkp); + hdiff = cur->bc_ops->diff_two_keys(cur, lkp, &high_key); + + /* If the key matches, drill another level deeper. */ + if (ldiff >= 0 && hdiff >= 0) { + level--; + error = xfs_btree_lookup_get_block(cur, level, pp, + &block); + if (error) + goto out; + xfs_btree_get_block(cur, level, &bp); + trace_xfs_btree_overlapped_query_range(cur, level, bp); +#ifdef DEBUG + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; +#endif + cur->bc_ptrs[level] = 1; + continue; + } else if (hdiff < 0) { + /* The low key is larger than the upper range; pop. */ + goto node_pop_up; + } + cur->bc_ptrs[level]++; + } + +out: + /* + * If we don't end this function with the cursor pointing at a record + * block, a subsequent non-error cursor deletion will not release + * node-level buffers, causing a buffer leak. This is quite possible + * with a zero-results range query, so release the buffers if we + * failed to return any results. + */ + if (cur->bc_bufs[0] == NULL) { + for (i = 0; i < cur->bc_nlevels; i++) { + if (cur->bc_bufs[i]) { + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); + cur->bc_bufs[i] = NULL; + cur->bc_ptrs[i] = 0; + cur->bc_ra[i] = 0; + } + } + } + + return error; +} + +/* + * Query a btree for all records overlapping a given interval of keys. The + * supplied function will be called with each record found; return one of the + * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error + * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a + * negative error code. + */ +int +xfs_btree_query_range( + struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, + union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, + void *priv) +{ + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return xfs_btree_simple_query_range(cur, low_rec, + high_rec, fn, priv); + return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, + fn, priv); +} diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index a5ec6c7..898fee5 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -206,6 +206,12 @@ struct xfs_btree_ops { #define LASTREC_DELREC 2 +union xfs_btree_irec { + xfs_alloc_rec_incore_t a; + xfs_bmbt_irec_t b; + xfs_inobt_rec_incore_t i; +}; + /* * Btree cursor structure. * This collects all information needed by the btree code in one place. @@ -216,11 +222,7 @@ typedef struct xfs_btree_cur struct xfs_mount *bc_mp; /* file system mount struct */ const struct xfs_btree_ops *bc_ops; uint bc_flags; /* btree features - below */ - union { - xfs_alloc_rec_incore_t a; - xfs_bmbt_irec_t b; - xfs_inobt_rec_incore_t i; - } bc_rec; /* current insert/search record value */ + union xfs_btree_irec bc_rec; /* current insert/search record value */ struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ @@ -494,4 +496,14 @@ xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, unsigned long len); +/* return codes */ +#define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */ +#define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */ +typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur, + union xfs_btree_rec *rec, void *priv); + +int xfs_btree_query_range(struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, void *priv); + #endif /* __XFS_BTREE_H__ */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index ffea28c..f0ac9c9 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2218,6 +2218,7 @@ DEFINE_EVENT(xfs_btree_cur_class, name, \ TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ TP_ARGS(cur, level, bp)) DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); +DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); #endif /* _TRACE_XFS_H */ From darrick.wong@oracle.com Thu Jun 16 20:19:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id ABFF27CB3 for ; Thu, 16 Jun 2016 20:19:35 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6E288304039 for ; Thu, 16 Jun 2016 18:19:35 -0700 (PDT) X-ASG-Debug-ID: 1466126373-04cb6c542757160001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id prCzzL9bCsAtaGhs (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:33 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1JUgq024450 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:31 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JUSF003318 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:30 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JTCx018270; Fri, 17 Jun 2016 01:19:30 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:29 -0700 Subject: [PATCH 015/119] xfs: refactor btree owner change into a separate visit-blocks function From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 015/119] xfs: refactor btree owner change into a separate visit-blocks function To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:28 -0700 Message-ID: <146612636805.12839.15108503251791000478.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126373 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6170 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Refactor the btree_change_owner function into a more generic apparatus which visits all blocks in a btree. We'll use this in a subsequent patch for counting btree blocks for AG reservations. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_btree.c | 141 +++++++++++++++++++++++++++++---------------- fs/xfs/libxfs/xfs_btree.h | 5 ++ 2 files changed, 96 insertions(+), 50 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 5f5cf23..eac876a 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -4289,6 +4289,81 @@ xfs_btree_get_rec( return 0; } +/* Visit a block in a btree. */ +STATIC int +xfs_btree_visit_block( + struct xfs_btree_cur *cur, + int level, + xfs_btree_visit_blocks_fn fn, + void *data) +{ + struct xfs_btree_block *block; + struct xfs_buf *bp; + union xfs_btree_ptr rptr; + int error; + + /* do right sibling readahead */ + xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); + block = xfs_btree_get_block(cur, level, &bp); + + /* process the block */ + error = fn(cur, level, data); + if (error) + return error; + + /* now read rh sibling block for next iteration */ + xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); + if (xfs_btree_ptr_is_null(cur, &rptr)) + return -ENOENT; + + return xfs_btree_lookup_get_block(cur, level, &rptr, &block); +} + + +/* Visit every block in a btree. */ +int +xfs_btree_visit_blocks( + struct xfs_btree_cur *cur, + xfs_btree_visit_blocks_fn fn, + void *data) +{ + union xfs_btree_ptr lptr; + int level; + struct xfs_btree_block *block = NULL; + int error = 0; + + cur->bc_ops->init_ptr_from_cur(cur, &lptr); + + /* for each level */ + for (level = cur->bc_nlevels - 1; level >= 0; level--) { + /* grab the left hand block */ + error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); + if (error) + return error; + + /* readahead the left most block for the next level down */ + if (level > 0) { + union xfs_btree_ptr *ptr; + + ptr = xfs_btree_ptr_addr(cur, 1, block); + xfs_btree_readahead_ptr(cur, ptr, 1); + + /* save for the next iteration of the loop */ + lptr = *ptr; + } + + /* for each buffer in the level */ + do { + error = xfs_btree_visit_block(cur, level, fn, data); + } while (!error); + + if (error != -ENOENT) + return error; + } + + return 0; +} + /* * Change the owner of a btree. * @@ -4313,26 +4388,27 @@ xfs_btree_get_rec( * just queue the modified buffer as delayed write buffer so the transaction * recovery completion writes the changes to disk. */ +struct xfs_btree_block_change_owner_info { + __uint64_t new_owner; + struct list_head *buffer_list; +}; + static int xfs_btree_block_change_owner( struct xfs_btree_cur *cur, int level, - __uint64_t new_owner, - struct list_head *buffer_list) + void *data) { + struct xfs_btree_block_change_owner_info *bbcoi = data; struct xfs_btree_block *block; struct xfs_buf *bp; - union xfs_btree_ptr rptr; - - /* do right sibling readahead */ - xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); /* modify the owner */ block = xfs_btree_get_block(cur, level, &bp); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) - block->bb_u.l.bb_owner = cpu_to_be64(new_owner); + block->bb_u.l.bb_owner = cpu_to_be64(bbcoi->new_owner); else - block->bb_u.s.bb_owner = cpu_to_be32(new_owner); + block->bb_u.s.bb_owner = cpu_to_be32(bbcoi->new_owner); /* * If the block is a root block hosted in an inode, we might not have a @@ -4346,19 +4422,14 @@ xfs_btree_block_change_owner( xfs_trans_ordered_buf(cur->bc_tp, bp); xfs_btree_log_block(cur, bp, XFS_BB_OWNER); } else { - xfs_buf_delwri_queue(bp, buffer_list); + xfs_buf_delwri_queue(bp, bbcoi->buffer_list); } } else { ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); ASSERT(level == cur->bc_nlevels - 1); } - /* now read rh sibling block for next iteration */ - xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); - if (xfs_btree_ptr_is_null(cur, &rptr)) - return -ENOENT; - - return xfs_btree_lookup_get_block(cur, level, &rptr, &block); + return 0; } int @@ -4367,43 +4438,13 @@ xfs_btree_change_owner( __uint64_t new_owner, struct list_head *buffer_list) { - union xfs_btree_ptr lptr; - int level; - struct xfs_btree_block *block = NULL; - int error = 0; + struct xfs_btree_block_change_owner_info bbcoi; - cur->bc_ops->init_ptr_from_cur(cur, &lptr); + bbcoi.new_owner = new_owner; + bbcoi.buffer_list = buffer_list; - /* for each level */ - for (level = cur->bc_nlevels - 1; level >= 0; level--) { - /* grab the left hand block */ - error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); - if (error) - return error; - - /* readahead the left most block for the next level down */ - if (level > 0) { - union xfs_btree_ptr *ptr; - - ptr = xfs_btree_ptr_addr(cur, 1, block); - xfs_btree_readahead_ptr(cur, ptr, 1); - - /* save for the next iteration of the loop */ - lptr = *ptr; - } - - /* for each buffer in the level */ - do { - error = xfs_btree_block_change_owner(cur, level, - new_owner, - buffer_list); - } while (!error); - - if (error != -ENOENT) - return error; - } - - return 0; + return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner, + &bbcoi); } /** diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 898fee5..0ec3055 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -506,4 +506,9 @@ int xfs_btree_query_range(struct xfs_btree_cur *cur, union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, xfs_btree_query_range_fn fn, void *priv); +typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level, + void *data); +int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, + xfs_btree_visit_blocks_fn fn, void *data); + #endif /* __XFS_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:19:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 57B3C7CDE for ; Thu, 16 Jun 2016 20:19:43 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0A584304048 for ; Thu, 16 Jun 2016 18:19:42 -0700 (PDT) X-ASG-Debug-ID: 1466126378-04cb6c542757170001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id i0NwhvBTNdqE7HTW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Jb4Z005312 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:19:37 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1JaTT007078 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:19:37 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1JaFR026955; Fri, 17 Jun 2016 01:19:36 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:35 -0700 Subject: [PATCH 016/119] xfs: move deferred operations into a separate file From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 016/119] xfs: move deferred operations into a separate file To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:34 -0700 Message-ID: <146612637438.12839.12318902006860455847.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126379 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 23928 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines All the code around struct xfs_bmap_free basically implements a deferred operation framework through which we can roll transactions (to unlock buffers and avoid violating lock order rules) while managing all the necessary log redo items. Previously we only used this code to free extents after some sort of mapping operation, but with the advent of rmap and reflink, we suddenly need to do more than that. With that in mind, xfs_bmap_free really becomes a deferred ops control structure. Rename the structure and move the deferred ops into their own file to avoid further bloating of the bmap code. v2: actually sort the work items by AG to avoid deadlocks Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 2 fs/xfs/libxfs/xfs_defer.c | 471 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_defer.h | 96 +++++++++ fs/xfs/xfs_defer_item.c | 36 +++ fs/xfs/xfs_super.c | 2 5 files changed, 607 insertions(+) create mode 100644 fs/xfs/libxfs/xfs_defer.c create mode 100644 fs/xfs/libxfs/xfs_defer.h create mode 100644 fs/xfs/xfs_defer_item.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 3542d94..ad46a2d 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -39,6 +39,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_btree.o \ xfs_da_btree.o \ xfs_da_format.o \ + xfs_defer.o \ xfs_dir2.o \ xfs_dir2_block.o \ xfs_dir2_data.o \ @@ -66,6 +67,7 @@ xfs-y += xfs_aops.o \ xfs_attr_list.o \ xfs_bmap_util.o \ xfs_buf.o \ + xfs_defer_item.o \ xfs_dir2_readdir.o \ xfs_discard.o \ xfs_error.o \ diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c new file mode 100644 index 0000000..ad14e33e --- /dev/null +++ b/fs/xfs/libxfs/xfs_defer.c @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_trans.h" +#include "xfs_trace.h" + +/* + * Deferred Operations in XFS + * + * Due to the way locking rules work in XFS, certain transactions (block + * mapping and unmapping, typically) have permanent reservations so that + * we can roll the transaction to adhere to AG locking order rules and + * to unlock buffers between metadata updates. Prior to rmap/reflink, + * the mapping code had a mechanism to perform these deferrals for + * extents that were going to be freed; this code makes that facility + * more generic. + * + * When adding the reverse mapping and reflink features, it became + * necessary to perform complex remapping multi-transactions to comply + * with AG locking order rules, and to be able to spread a single + * refcount update operation (an operation on an n-block extent can + * update as many as n records!) among multiple transactions. XFS can + * roll a transaction to facilitate this, but using this facility + * requires us to log "intent" items in case log recovery needs to + * redo the operation, and to log "done" items to indicate that redo + * is not necessary. + * + * The xfs_defer_ops structure tracks incoming deferred work (which is + * work that has not yet had an intent logged) in xfs_defer_intake. + * There is one xfs_defer_intake for each type of deferrable + * operation. Each new deferral is placed in the op's intake list, + * where it waits for the caller to finish the deferred operations. + * + * Finishing a set of deferred operations is an involved process. To + * start, we define "rolling a deferred-op transaction" as follows: + * + * > For each xfs_defer_intake, + * - Sort the items on the intake list in AG order. + * - Create a log intent item for that type. + * - Attach to it the items on the intake list. + * - Stash the intent+items for later in an xfs_defer_pending. + * - Attach the xfs_defer_pending to the xfs_defer_ops work list. + * > Roll the transaction. + * + * NOTE: To avoid exceeding the transaction reservation, we limit the + * number of items that we attach to a given xfs_defer_pending. + * + * The actual finishing process looks like this: + * + * > For each xfs_defer_pending in the xfs_defer_ops work list, + * - Roll the deferred-op transaction as above. + * - Create a log done item for that type, and attach it to the + * intent item. + * - For each work item attached to the intent item, + * * Perform the described action. + * * Attach the work item to the log done item. + * * If the result of doing the work was -EAGAIN, log a fresh + * intent item and attach all remaining work items to it. Put + * the xfs_defer_pending item back on the work list, and repeat + * the loop. This allows us to make partial progress even if + * the transaction is too full to finish the job. + * + * The key here is that we must log an intent item for all pending + * work items every time we roll the transaction, and that we must log + * a done item as soon as the work is completed. With this mechanism + * we can perform complex remapping operations, chaining intent items + * as needed. + * + * This is an example of remapping the extent (E, E+B) into file X at + * offset A and dealing with the extent (C, C+B) already being mapped + * there: + * +-------------------------------------------------+ + * | Unmap file X startblock C offset A length B | t0 + * | Intent to reduce refcount for extent (C, B) | + * | Intent to remove rmap (X, C, A, B) | + * | Intent to free extent (D, 1) (bmbt block) | + * | Intent to map (X, A, B) at startblock E | + * +-------------------------------------------------+ + * | Map file X startblock E offset A length B | t1 + * | Done mapping (X, E, A, B) | + * | Intent to increase refcount for extent (E, B) | + * | Intent to add rmap (X, E, A, B) | + * +-------------------------------------------------+ + * | Reduce refcount for extent (C, B) | t2 + * | Done reducing refcount for extent (C, B) | + * | Increase refcount for extent (E, B) | + * | Done increasing refcount for extent (E, B) | + * | Intent to free extent (C, B) | + * | Intent to free extent (F, 1) (refcountbt block) | + * | Intent to remove rmap (F, 1, REFC) | + * +-------------------------------------------------+ + * | Remove rmap (X, C, A, B) | t3 + * | Done removing rmap (X, C, A, B) | + * | Add rmap (X, E, A, B) | + * | Done adding rmap (X, E, A, B) | + * | Remove rmap (F, 1, REFC) | + * | Done removing rmap (F, 1, REFC) | + * +-------------------------------------------------+ + * | Free extent (C, B) | t4 + * | Done freeing extent (C, B) | + * | Free extent (D, 1) | + * | Done freeing extent (D, 1) | + * | Free extent (F, 1) | + * | Done freeing extent (F, 1) | + * +-------------------------------------------------+ + * + * If we should crash before t2 commits, log recovery replays + * the following intent items: + * + * - Intent to reduce refcount for extent (C, B) + * - Intent to remove rmap (X, C, A, B) + * - Intent to free extent (D, 1) (bmbt block) + * - Intent to increase refcount for extent (E, B) + * - Intent to add rmap (X, E, A, B) + * + * In the process of recovering, it should also generate and take care + * of these intent items: + * + * - Intent to free extent (C, B) + * - Intent to free extent (F, 1) (refcountbt block) + * - Intent to remove rmap (F, 1, REFC) + */ + +static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; + +/* + * For each pending item in the intake list, log its intent item and the + * associated extents, then add the entire intake list to the end of + * the pending list. + */ +STATIC void +xfs_defer_intake_work( + struct xfs_trans *tp, + struct xfs_defer_ops *dop) +{ + struct list_head *li; + struct xfs_defer_pending *dfp; + + list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { + dfp->dfp_intent = dfp->dfp_type->create_intent(tp, + dfp->dfp_count); + list_sort(tp->t_mountp, &dfp->dfp_work, + dfp->dfp_type->diff_items); + list_for_each(li, &dfp->dfp_work) + dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); + } + + list_splice_tail_init(&dop->dop_intake, &dop->dop_pending); +} + +/* Abort all the intents that were committed. */ +STATIC void +xfs_defer_trans_abort( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + int error) +{ + struct xfs_defer_pending *dfp; + + /* + * If the transaction was committed, drop the intent reference + * since we're bailing out of here. The other reference is + * dropped when the intent hits the AIL. If the transaction + * was not committed, the intent is freed by the intent item + * unlock handler on abort. + */ + if (!dop->dop_committed) + return; + + /* Abort intent items. */ + list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { + if (dfp->dfp_committed) + dfp->dfp_type->abort_intent(dfp->dfp_intent); + } + + /* Shut down FS. */ + xfs_force_shutdown(tp->t_mountp, (error == -EFSCORRUPTED) ? + SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR); +} + +/* Roll a transaction so we can do some deferred op processing. */ +STATIC int +xfs_defer_trans_roll( + struct xfs_trans **tp, + struct xfs_defer_ops *dop, + struct xfs_inode *ip) +{ + int i; + int error; + + /* Log all the joined inodes except the one we passed in. */ + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { + if (dop->dop_inodes[i] == ip) + continue; + xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); + } + + /* Roll the transaction. */ + error = xfs_trans_roll(tp, ip); + if (error) { + xfs_defer_trans_abort(*tp, dop, error); + return error; + } + dop->dop_committed = true; + + /* Log all the joined inodes except the one we passed in. */ + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { + if (dop->dop_inodes[i] == ip) + continue; + xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); + } + + return error; +} + +/* Do we have any work items to finish? */ +bool +xfs_defer_has_unfinished_work( + struct xfs_defer_ops *dop) +{ + return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake); +} + +/* + * Add this inode to the deferred op. Each joined inode is relogged + * each time we roll the transaction, in addition to any inode passed + * to xfs_defer_finish(). + */ +int +xfs_defer_join( + struct xfs_defer_ops *dop, + struct xfs_inode *ip) +{ + int i; + + for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) { + if (dop->dop_inodes[i] == ip) + return 0; + else if (dop->dop_inodes[i] == NULL) { + dop->dop_inodes[i] = ip; + return 0; + } + } + + return -EFSCORRUPTED; +} + +/* + * Finish all the pending work. This involves logging intent items for + * any work items that wandered in since the last transaction roll (if + * one has even happened), rolling the transaction, and finishing the + * work items in the first item on the logged-and-pending list. + * + * If an inode is provided, relog it to the new transaction. + */ +int +xfs_defer_finish( + struct xfs_trans **tp, + struct xfs_defer_ops *dop, + struct xfs_inode *ip) +{ + struct xfs_defer_pending *dfp; + struct list_head *li; + struct list_head *n; + void *done_item = NULL; + void *state; + int error = 0; + void (*cleanup_fn)(struct xfs_trans *, void *, int); + + ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); + + /* Until we run out of pending work to finish... */ + while (xfs_defer_has_unfinished_work(dop)) { + /* Log intents for work items sitting in the intake. */ + xfs_defer_intake_work(*tp, dop); + + /* Roll the transaction. */ + error = xfs_defer_trans_roll(tp, dop, ip); + if (error) + goto out; + + /* Mark all pending intents as committed. */ + list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { + if (dfp->dfp_committed) + break; + dfp->dfp_committed = true; + } + + /* Log an intent-done item for the first pending item. */ + dfp = list_first_entry(&dop->dop_pending, + struct xfs_defer_pending, dfp_list); + done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, + dfp->dfp_count); + cleanup_fn = dfp->dfp_type->finish_cleanup; + + /* Finish the work items. */ + state = NULL; + list_for_each_safe(li, n, &dfp->dfp_work) { + list_del(li); + dfp->dfp_count--; + error = dfp->dfp_type->finish_item(*tp, dop, li, + done_item, &state); + if (error == -EAGAIN) { + /* + * If the caller needs to try again, put the + * item back on the pending list and jump out + * for further processing. + */ + list_add(li, &dfp->dfp_work); + dfp->dfp_count++; + break; + } else if (error) { + /* + * Clean up after ourselves and jump out. + * xfs_defer_cancel will take care of freeing + * all these lists and stuff. + */ + if (cleanup_fn) + cleanup_fn(*tp, state, error); + xfs_defer_trans_abort(*tp, dop, error); + goto out; + } + } + if (error == -EAGAIN) { + /* + * Log a new intent, relog all the remaining work + * item to the new intent, attach the new intent to + * the dfp, and leave the dfp at the head of the list + * for further processing. + */ + dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, + dfp->dfp_count); + list_for_each(li, &dfp->dfp_work) + dfp->dfp_type->log_item(*tp, dfp->dfp_intent, + li); + } else { + /* Done with the dfp, free it. */ + list_del(&dfp->dfp_list); + kmem_free(dfp); + } + + if (cleanup_fn) + cleanup_fn(*tp, state, error); + } + +out: + return error; +} + +/* + * Free up any items left in the list. + */ +void +xfs_defer_cancel( + struct xfs_defer_ops *dop) +{ + struct xfs_defer_pending *dfp; + struct xfs_defer_pending *pli; + struct list_head *pwi; + struct list_head *n; + + /* + * Free the pending items. Caller should already have arranged + * for the intent items to be released. + */ + list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { + list_del(&dfp->dfp_list); + list_for_each_safe(pwi, n, &dfp->dfp_work) { + list_del(pwi); + dfp->dfp_count--; + dfp->dfp_type->cancel_item(pwi); + } + ASSERT(dfp->dfp_count == 0); + kmem_free(dfp); + } + list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { + list_del(&dfp->dfp_list); + list_for_each_safe(pwi, n, &dfp->dfp_work) { + list_del(pwi); + dfp->dfp_count--; + dfp->dfp_type->cancel_item(pwi); + } + ASSERT(dfp->dfp_count == 0); + kmem_free(dfp); + } +} + +/* Add an item for later deferred processing. */ +void +xfs_defer_add( + struct xfs_defer_ops *dop, + enum xfs_defer_ops_type type, + struct list_head *li) +{ + struct xfs_defer_pending *dfp = NULL; + + /* + * Add the item to a pending item at the end of the intake list. + * If the last pending item has the same type, reuse it. Else, + * create a new pending item at the end of the intake list. + */ + if (!list_empty(&dop->dop_intake)) { + dfp = list_last_entry(&dop->dop_intake, + struct xfs_defer_pending, dfp_list); + if (dfp->dfp_type->type != type || + (dfp->dfp_type->max_items && + dfp->dfp_count >= dfp->dfp_type->max_items)) + dfp = NULL; + } + if (!dfp) { + dfp = kmem_alloc(sizeof(struct xfs_defer_pending), + KM_SLEEP | KM_NOFS); + dfp->dfp_type = defer_op_types[type]; + dfp->dfp_committed = false; + dfp->dfp_intent = NULL; + dfp->dfp_count = 0; + INIT_LIST_HEAD(&dfp->dfp_work); + list_add_tail(&dfp->dfp_list, &dop->dop_intake); + } + + list_add_tail(li, &dfp->dfp_work); + dfp->dfp_count++; +} + +/* Initialize a deferred operation list. */ +void +xfs_defer_init_op_type( + const struct xfs_defer_op_type *type) +{ + defer_op_types[type->type] = type; +} + +/* Initialize a deferred operation. */ +void +xfs_defer_init( + struct xfs_defer_ops *dop, + xfs_fsblock_t *fbp) +{ + dop->dop_committed = false; + dop->dop_low = false; + memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); + *fbp = NULLFSBLOCK; + INIT_LIST_HEAD(&dop->dop_intake); + INIT_LIST_HEAD(&dop->dop_pending); +} diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h new file mode 100644 index 0000000..85c7a3a --- /dev/null +++ b/fs/xfs/libxfs/xfs_defer.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_DEFER_H__ +#define __XFS_DEFER_H__ + +struct xfs_defer_op_type; + +/* + * Save a log intent item and a list of extents, so that we can replay + * whatever action had to happen to the extent list and file the log done + * item. + */ +struct xfs_defer_pending { + const struct xfs_defer_op_type *dfp_type; /* function pointers */ + struct list_head dfp_list; /* pending items */ + bool dfp_committed; /* committed trans? */ + void *dfp_intent; /* log intent item */ + struct list_head dfp_work; /* work items */ + unsigned int dfp_count; /* # extent items */ +}; + +/* + * Header for deferred operation list. + * + * dop_low is used by the allocator to activate the lowspace algorithm - + * when free space is running low the extent allocator may choose to + * allocate an extent from an AG without leaving sufficient space for + * a btree split when inserting the new extent. In this case the allocator + * will enable the lowspace algorithm which is supposed to allow further + * allocations (such as btree splits and newroots) to allocate from + * sequential AGs. In order to avoid locking AGs out of order the lowspace + * algorithm will start searching for free space from AG 0. If the correct + * transaction reservations have been made then this algorithm will eventually + * find all the space it needs. + */ +enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_MAX, +}; + +#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ + +struct xfs_defer_ops { + bool dop_committed; /* did any trans commit? */ + bool dop_low; /* alloc in low mode */ + struct list_head dop_intake; /* unlogged pending work */ + struct list_head dop_pending; /* logged pending work */ + + /* relog these inodes with each roll */ + struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; +}; + +void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, + struct list_head *h); +int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop, + struct xfs_inode *ip); +void xfs_defer_cancel(struct xfs_defer_ops *dop); +void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); +bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); +int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip); + +/* Description of a deferred type. */ +struct xfs_defer_op_type { + enum xfs_defer_ops_type type; + unsigned int max_items; + void (*abort_intent)(void *); + void *(*create_done)(struct xfs_trans *, void *, unsigned int); + int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, + struct list_head *, void *, void **); + void (*finish_cleanup)(struct xfs_trans *, void *, int); + void (*cancel_item)(struct list_head *); + int (*diff_items)(void *, struct list_head *, struct list_head *); + void *(*create_intent)(struct xfs_trans *, uint); + void (*log_item)(struct xfs_trans *, void *, struct list_head *); +}; + +void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); +void xfs_defer_init_types(void); + +#endif /* __XFS_DEFER_H__ */ diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c new file mode 100644 index 0000000..849088d --- /dev/null +++ b/fs/xfs/xfs_defer_item.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_trans.h" + +/* Initialize the deferred operation types. */ +void +xfs_defer_init_types(void) +{ +} diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 09722a7..bf63f6d 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -46,6 +46,7 @@ #include "xfs_quota.h" #include "xfs_sysfs.h" #include "xfs_ondisk.h" +#include "xfs_defer.h" #include #include @@ -1850,6 +1851,7 @@ init_xfs_fs(void) printk(KERN_INFO XFS_VERSION_STRING " with " XFS_BUILD_OPTIONS " enabled\n"); + xfs_defer_init_types(); xfs_dir_startup(); error = xfs_init_zones(); From darrick.wong@oracle.com Thu Jun 16 20:19:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A0CE17CB5 for ; Thu, 16 Jun 2016 20:19:51 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 71AD28F804B for ; Thu, 16 Jun 2016 18:19:51 -0700 (PDT) X-ASG-Debug-ID: 1466126385-04cbb01fec69550001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id mmedWZcN8Sv6N4wF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:49 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1JhZB005388 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:44 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JhXo003580 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:43 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JgF3018321; Fri, 17 Jun 2016 01:19:43 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:42 -0700 Subject: [PATCH 017/119] xfs: add tracepoints for the deferred ops mechanism From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 017/119] xfs: add tracepoints for the deferred ops mechanism To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:40 -0700 Message-ID: <146612638080.12839.2097094526348177968.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126389 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11202 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add tracepoints for the internals of the deferred ops mechanism and tracepoint classes for clients of the dops, to make debugging easier. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.c | 19 ++++ fs/xfs/xfs_defer_item.c | 1 fs/xfs/xfs_trace.c | 1 fs/xfs/xfs_trace.h | 198 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 219 insertions(+) diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index ad14e33e..b4e7faa 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -163,6 +163,7 @@ xfs_defer_intake_work( struct xfs_defer_pending *dfp; list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { + trace_xfs_defer_intake_work(tp->t_mountp, dfp); dfp->dfp_intent = dfp->dfp_type->create_intent(tp, dfp->dfp_count); list_sort(tp->t_mountp, &dfp->dfp_work, @@ -183,6 +184,7 @@ xfs_defer_trans_abort( { struct xfs_defer_pending *dfp; + trace_xfs_defer_trans_abort(tp->t_mountp, dop); /* * If the transaction was committed, drop the intent reference * since we're bailing out of here. The other reference is @@ -195,6 +197,7 @@ xfs_defer_trans_abort( /* Abort intent items. */ list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { + trace_xfs_defer_pending_abort(tp->t_mountp, dfp); if (dfp->dfp_committed) dfp->dfp_type->abort_intent(dfp->dfp_intent); } @@ -221,9 +224,12 @@ xfs_defer_trans_roll( xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); } + trace_xfs_defer_trans_roll((*tp)->t_mountp, dop); + /* Roll the transaction. */ error = xfs_trans_roll(tp, ip); if (error) { + trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error); xfs_defer_trans_abort(*tp, dop, error); return error; } @@ -295,6 +301,8 @@ xfs_defer_finish( ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); + trace_xfs_defer_finish((*tp)->t_mountp, dop); + /* Until we run out of pending work to finish... */ while (xfs_defer_has_unfinished_work(dop)) { /* Log intents for work items sitting in the intake. */ @@ -309,12 +317,14 @@ xfs_defer_finish( list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { if (dfp->dfp_committed) break; + trace_xfs_defer_pending_commit((*tp)->t_mountp, dfp); dfp->dfp_committed = true; } /* Log an intent-done item for the first pending item. */ dfp = list_first_entry(&dop->dop_pending, struct xfs_defer_pending, dfp_list); + trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, dfp->dfp_count); cleanup_fn = dfp->dfp_type->finish_cleanup; @@ -370,6 +380,10 @@ xfs_defer_finish( } out: + if (error) + trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); + else + trace_xfs_defer_finish_done((*tp)->t_mountp, dop); return error; } @@ -385,11 +399,14 @@ xfs_defer_cancel( struct list_head *pwi; struct list_head *n; + trace_xfs_defer_cancel(NULL, dop); + /* * Free the pending items. Caller should already have arranged * for the intent items to be released. */ list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { + trace_xfs_defer_intake_cancel(NULL, dfp); list_del(&dfp->dfp_list); list_for_each_safe(pwi, n, &dfp->dfp_work) { list_del(pwi); @@ -400,6 +417,7 @@ xfs_defer_cancel( kmem_free(dfp); } list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { + trace_xfs_defer_pending_cancel(NULL, dfp); list_del(&dfp->dfp_list); list_for_each_safe(pwi, n, &dfp->dfp_work) { list_del(pwi); @@ -468,4 +486,5 @@ xfs_defer_init( *fbp = NULLFSBLOCK; INIT_LIST_HEAD(&dop->dop_intake); INIT_LIST_HEAD(&dop->dop_pending); + trace_xfs_defer_init(NULL, dop); } diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c index 849088d..4c2ba28 100644 --- a/fs/xfs/xfs_defer_item.c +++ b/fs/xfs/xfs_defer_item.c @@ -28,6 +28,7 @@ #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_trans.h" +#include "xfs_trace.h" /* Initialize the deferred operation types. */ void diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 13a0298..3971527 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -22,6 +22,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_inode.h" #include "xfs_btree.h" diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index f0ac9c9..5923014 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2220,6 +2220,204 @@ DEFINE_EVENT(xfs_btree_cur_class, name, \ DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); +/* deferred ops */ +struct xfs_defer_pending; +struct xfs_defer_intake; +struct xfs_defer_ops; + +DECLARE_EVENT_CLASS(xfs_defer_class, + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop), + TP_ARGS(mp, dop), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(void *, dop) + __field(bool, committed) + __field(bool, low) + ), + TP_fast_assign( + __entry->dev = mp ? mp->m_super->s_dev : 0; + __entry->dop = dop; + __entry->committed = dop->dop_committed; + __entry->low = dop->dop_low; + ), + TP_printk("dev %d:%d ops %p committed %d low %d\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dop, + __entry->committed, + __entry->low) +) +#define DEFINE_DEFER_EVENT(name) \ +DEFINE_EVENT(xfs_defer_class, name, \ + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop), \ + TP_ARGS(mp, dop)) + +DECLARE_EVENT_CLASS(xfs_defer_error_class, + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), + TP_ARGS(mp, dop, error), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(void *, dop) + __field(bool, committed) + __field(bool, low) + __field(int, error) + ), + TP_fast_assign( + __entry->dev = mp ? mp->m_super->s_dev : 0; + __entry->dop = dop; + __entry->committed = dop->dop_committed; + __entry->low = dop->dop_low; + __entry->error = error; + ), + TP_printk("dev %d:%d ops %p committed %d low %d err %d\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->dop, + __entry->committed, + __entry->low, + __entry->error) +) +#define DEFINE_DEFER_ERROR_EVENT(name) \ +DEFINE_EVENT(xfs_defer_error_class, name, \ + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), \ + TP_ARGS(mp, dop, error)) + +DECLARE_EVENT_CLASS(xfs_defer_pending_class, + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp), + TP_ARGS(mp, dfp), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(int, type) + __field(void *, intent) + __field(bool, committed) + __field(int, nr) + ), + TP_fast_assign( + __entry->dev = mp ? mp->m_super->s_dev : 0; + __entry->type = dfp->dfp_type->type; + __entry->intent = dfp->dfp_intent; + __entry->committed = dfp->dfp_committed; + __entry->nr = dfp->dfp_count; + ), + TP_printk("dev %d:%d optype %d intent %p committed %d nr %d\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->type, + __entry->intent, + __entry->committed, + __entry->nr) +) +#define DEFINE_DEFER_PENDING_EVENT(name) \ +DEFINE_EVENT(xfs_defer_pending_class, name, \ + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp), \ + TP_ARGS(mp, dfp)) + +DECLARE_EVENT_CLASS(xfs_phys_extent_deferred_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + int type, xfs_agblock_t agbno, xfs_extlen_t len), + TP_ARGS(mp, agno, type, agbno, len), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(int, type) + __field(xfs_agblock_t, agbno) + __field(xfs_extlen_t, len) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->type = type; + __entry->agbno = agbno; + __entry->len = len; + ), + TP_printk("dev %d:%d op %d agno %u agbno %u len %u", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->type, + __entry->agno, + __entry->agbno, + __entry->len) +); +#define DEFINE_PHYS_EXTENT_DEFERRED_EVENT(name) \ +DEFINE_EVENT(xfs_phys_extent_deferred_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + int type, \ + xfs_agblock_t bno, \ + xfs_extlen_t len), \ + TP_ARGS(mp, agno, type, bno, len)) + +DECLARE_EVENT_CLASS(xfs_map_extent_deferred_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + int op, + xfs_agblock_t agbno, + xfs_ino_t ino, + int whichfork, + xfs_fileoff_t offset, + xfs_filblks_t len, + xfs_exntst_t state), + TP_ARGS(mp, agno, op, agbno, ino, whichfork, offset, len, state), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_ino_t, ino) + __field(xfs_agblock_t, agbno) + __field(int, whichfork) + __field(xfs_fileoff_t, l_loff) + __field(xfs_filblks_t, l_len) + __field(xfs_exntst_t, l_state) + __field(int, op) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->ino = ino; + __entry->agbno = agbno; + __entry->whichfork = whichfork; + __entry->l_loff = offset; + __entry->l_len = len; + __entry->l_state = state; + __entry->op = op; + ), + TP_printk("dev %d:%d op %d agno %u agbno %u owner %lld %s offset %llu len %llu state %d", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->op, + __entry->agno, + __entry->agbno, + __entry->ino, + __entry->whichfork == XFS_ATTR_FORK ? "attr" : "data", + __entry->l_loff, + __entry->l_len, + __entry->l_state) +); +#define DEFINE_MAP_EXTENT_DEFERRED_EVENT(name) \ +DEFINE_EVENT(xfs_map_extent_deferred_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + int op, \ + xfs_agblock_t agbno, \ + xfs_ino_t ino, \ + int whichfork, \ + xfs_fileoff_t offset, \ + xfs_filblks_t len, \ + xfs_exntst_t state), \ + TP_ARGS(mp, agno, op, agbno, ino, whichfork, offset, len, state)) + +DEFINE_DEFER_EVENT(xfs_defer_init); +DEFINE_DEFER_EVENT(xfs_defer_cancel); +DEFINE_DEFER_EVENT(xfs_defer_trans_roll); +DEFINE_DEFER_EVENT(xfs_defer_trans_abort); +DEFINE_DEFER_EVENT(xfs_defer_finish); +DEFINE_DEFER_EVENT(xfs_defer_finish_done); + +DEFINE_DEFER_ERROR_EVENT(xfs_defer_trans_roll_error); +DEFINE_DEFER_ERROR_EVENT(xfs_defer_finish_error); +DEFINE_DEFER_ERROR_EVENT(xfs_defer_op_finish_error); + +DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_work); +DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_cancel); +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_commit); +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel); +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish); +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort); + +DEFINE_PHYS_EXTENT_DEFERRED_EVENT(xfs_defer_phys_extent); +DEFINE_MAP_EXTENT_DEFERRED_EVENT(xfs_defer_map_extent); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:19:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6206F7D0E for ; Thu, 16 Jun 2016 20:19:55 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id EF8B0AC001 for ; Thu, 16 Jun 2016 18:19:54 -0700 (PDT) X-ASG-Debug-ID: 1466126393-04bdf01e1795870001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id gDkNIcjVSgjofmv2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:19:53 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Jp8G005405 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:52 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Jpdk014310 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:51 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JnWb006275; Fri, 17 Jun 2016 01:19:50 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:48 -0700 Subject: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:47 -0700 Message-ID: <146612638717.12839.11007379793448761871.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126393 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3836 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.60 X-Barracuda-Spam-Status: No, SCORE=2.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_MV0249, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 2.00 BSF_SC0_MV0249 Custom rule MV0249 Connect the xfs_defer mechanism with the pieces that we'll need to handle deferred extent freeing. We'll wire up the existing code to our new deferred mechanism later. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.h | 1 fs/xfs/xfs_defer_item.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 85c7a3a..743fc32 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_FREE, XFS_DEFER_OPS_TYPE_MAX, }; diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c index 4c2ba28..127a54e 100644 --- a/fs/xfs/xfs_defer_item.c +++ b/fs/xfs/xfs_defer_item.c @@ -29,9 +29,117 @@ #include "xfs_defer.h" #include "xfs_trans.h" #include "xfs_trace.h" +#include "xfs_bmap.h" +#include "xfs_extfree_item.h" + +/* Extent Freeing */ + +/* Sort bmap items by AG. */ +static int +xfs_bmap_free_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_mount *mp = priv; + struct xfs_bmap_free_item *ra; + struct xfs_bmap_free_item *rb; + + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); +} + +/* Get an EFI. */ +STATIC void * +xfs_bmap_free_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return xfs_trans_get_efi(tp, count); +} + +/* Log a free extent to the intent item. */ +STATIC void +xfs_bmap_free_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ + struct xfs_bmap_free_item *free; + + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); + xfs_trans_log_efi_extent(tp, intent, free->xbfi_startblock, + free->xbfi_blockcount); +} + +/* Get an EFD so we can process all the free extents. */ +STATIC void * +xfs_bmap_free_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return xfs_trans_get_efd(tp, intent, count); +} + +/* Process a free extent. */ +STATIC int +xfs_bmap_free_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + struct xfs_bmap_free_item *free; + int error; + + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); + error = xfs_trans_free_extent(tp, done_item, + free->xbfi_startblock, + free->xbfi_blockcount); + kmem_free(free); + return error; +} + +/* Abort all pending EFIs. */ +STATIC void +xfs_bmap_free_abort_intent( + void *intent) +{ + xfs_efi_release(intent); +} + +/* Cancel a free extent. */ +STATIC void +xfs_bmap_free_cancel_item( + struct list_head *item) +{ + struct xfs_bmap_free_item *free; + + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); + kmem_free(free); +} + +const struct xfs_defer_op_type xfs_extent_free_defer_type = { + .type = XFS_DEFER_OPS_TYPE_FREE, + .max_items = XFS_EFI_MAX_FAST_EXTENTS, + .diff_items = xfs_bmap_free_diff_items, + .create_intent = xfs_bmap_free_create_intent, + .abort_intent = xfs_bmap_free_abort_intent, + .log_item = xfs_bmap_free_log_item, + .create_done = xfs_bmap_free_create_done, + .finish_item = xfs_bmap_free_finish_item, + .cancel_item = xfs_bmap_free_cancel_item, +}; + +/* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_extent_free_defer_type); } From darrick.wong@oracle.com Thu Jun 16 20:20:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id F2A077CB8 for ; Thu, 16 Jun 2016 20:20:04 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id B617B304048 for ; Thu, 16 Jun 2016 18:20:04 -0700 (PDT) X-ASG-Debug-ID: 1466126401-04cbb01fec69570001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ru6r5M4Wd75QACpa (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1JwWQ024627 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:59 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JvfV010284 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:19:58 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1JtYj006301; Fri, 17 Jun 2016 01:19:56 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:19:55 -0700 Subject: [PATCH 019/119] xfs: rework xfs_bmap_free callers to use xfs_defer_ops From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 019/119] xfs: rework xfs_bmap_free callers to use xfs_defer_ops To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:19:53 -0700 Message-ID: <146612639350.12839.16071552719519511734.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126401 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 20748 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Restructure everything that used xfs_bmap_free to use xfs_defer_ops instead. For now we'll just remove the old symbols and play some cpp magic to make it work; in the next patch we'll actually rename everything. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 1 fs/xfs/libxfs/xfs_attr.c | 1 fs/xfs/libxfs/xfs_attr_remote.c | 1 fs/xfs/libxfs/xfs_bmap.c | 55 +++++------------------ fs/xfs/libxfs/xfs_bmap.h | 32 -------------- fs/xfs/libxfs/xfs_bmap_btree.c | 5 +- fs/xfs/libxfs/xfs_btree.c | 1 fs/xfs/libxfs/xfs_defer.h | 7 +++ fs/xfs/libxfs/xfs_dir2.c | 1 fs/xfs/libxfs/xfs_ialloc.c | 1 fs/xfs/libxfs/xfs_inode_buf.c | 1 fs/xfs/libxfs/xfs_sb.c | 1 fs/xfs/xfs_bmap_util.c | 92 +-------------------------------------- fs/xfs/xfs_bmap_util.h | 2 - fs/xfs/xfs_dquot.c | 1 fs/xfs/xfs_filestream.c | 3 + fs/xfs/xfs_fsops.c | 1 fs/xfs/xfs_inode.c | 1 fs/xfs/xfs_iomap.c | 1 fs/xfs/xfs_log_recover.c | 1 fs/xfs/xfs_mount.c | 1 fs/xfs/xfs_rtalloc.c | 1 fs/xfs/xfs_symlink.c | 1 fs/xfs/xfs_trace.c | 1 24 files changed, 42 insertions(+), 171 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index c366889..c06b463 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_alloc_btree.h" diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 4e126f4..79d3a30 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_attr_sf.h" diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index a572532..93a9ce1 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -24,6 +24,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index a5d207a..64ca97f 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" @@ -595,41 +596,7 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; - list_add(&new->xbfi_list, &flist->xbf_flist); - flist->xbf_count++; -} - -/* - * Remove the entry "free" from the free item list. Prev points to the - * previous entry, unless "free" is the head of the list. - */ -void -xfs_bmap_del_free( - struct xfs_bmap_free *flist, /* free item list header */ - struct xfs_bmap_free_item *free) /* list item to be freed */ -{ - list_del(&free->xbfi_list); - flist->xbf_count--; - kmem_zone_free(xfs_bmap_free_item_zone, free); -} - -/* - * Free up any items left in the list. - */ -void -xfs_bmap_cancel( - struct xfs_bmap_free *flist) /* list of bmap_free_items */ -{ - struct xfs_bmap_free_item *free; /* free list item */ - - if (flist->xbf_count == 0) - return; - while (!list_empty(&flist->xbf_flist)) { - free = list_first_entry(&flist->xbf_flist, - struct xfs_bmap_free_item, xbfi_list); - xfs_bmap_del_free(flist, free); - } - ASSERT(flist->xbf_count == 0); + xfs_defer_add(flist, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); } /* @@ -767,7 +734,7 @@ xfs_bmap_extents_to_btree( if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); - } else if (flist->xbf_low) { + } else if (flist->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = *firstblock; } else { @@ -788,7 +755,7 @@ xfs_bmap_extents_to_btree( ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(*firstblock == NULLFSBLOCK || args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) || - (flist->xbf_low && + (flist->dop_low && args.agno > XFS_FSB_TO_AGNO(mp, *firstblock))); *firstblock = cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; @@ -3708,7 +3675,7 @@ xfs_bmap_btalloc( error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; - } else if (ap->flist->xbf_low) { + } else if (ap->flist->dop_low) { if (xfs_inode_is_filestream(ap->ip)) args.type = XFS_ALLOCTYPE_FIRST_AG; else @@ -3741,7 +3708,7 @@ xfs_bmap_btalloc( * is >= the stripe unit and the allocation offset is * at the end of file. */ - if (!ap->flist->xbf_low && ap->aeof) { + if (!ap->flist->dop_low && ap->aeof) { if (!ap->offset) { args.alignment = stripe_align; atype = args.type; @@ -3834,7 +3801,7 @@ xfs_bmap_btalloc( args.minleft = 0; if ((error = xfs_alloc_vextent(&args))) return error; - ap->flist->xbf_low = 1; + ap->flist->dop_low = true; } if (args.fsbno != NULLFSBLOCK) { /* @@ -3844,7 +3811,7 @@ xfs_bmap_btalloc( ASSERT(*ap->firstblock == NULLFSBLOCK || XFS_FSB_TO_AGNO(mp, *ap->firstblock) == XFS_FSB_TO_AGNO(mp, args.fsbno) || - (ap->flist->xbf_low && + (ap->flist->dop_low && XFS_FSB_TO_AGNO(mp, *ap->firstblock) < XFS_FSB_TO_AGNO(mp, args.fsbno))); @@ -3852,7 +3819,7 @@ xfs_bmap_btalloc( if (*ap->firstblock == NULLFSBLOCK) *ap->firstblock = args.fsbno; ASSERT(nullfb || fb_agno == args.agno || - (ap->flist->xbf_low && fb_agno < args.agno)); + (ap->flist->dop_low && fb_agno < args.agno)); ap->length = args.len; ap->ip->i_d.di_nblocks += args.len; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); @@ -4319,7 +4286,7 @@ xfs_bmapi_allocate( if (error) return error; - if (bma->flist->xbf_low) + if (bma->flist->dop_low) bma->minleft = 0; if (bma->cur) bma->cur->bc_private.b.firstblock = *bma->firstblock; @@ -4684,7 +4651,7 @@ error0: XFS_FSB_TO_AGNO(mp, *firstblock) == XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock) || - (flist->xbf_low && + (flist->dop_low && XFS_FSB_TO_AGNO(mp, *firstblock) < XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock))); diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 0ef4c6b..6681bd9 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -69,27 +69,6 @@ struct xfs_bmap_free_item struct list_head xbfi_list; }; -/* - * Header for free extent list. - * - * xbf_low is used by the allocator to activate the lowspace algorithm - - * when free space is running low the extent allocator may choose to - * allocate an extent from an AG without leaving sufficient space for - * a btree split when inserting the new extent. In this case the allocator - * will enable the lowspace algorithm which is supposed to allow further - * allocations (such as btree splits and newroots) to allocate from - * sequential AGs. In order to avoid locking AGs out of order the lowspace - * algorithm will start searching for free space from AG 0. If the correct - * transaction reservations have been made then this algorithm will eventually - * find all the space it needs. - */ -typedef struct xfs_bmap_free -{ - struct list_head xbf_flist; /* list of to-be-free extents */ - int xbf_count; /* count of items on list */ - int xbf_low; /* alloc in low mode */ -} xfs_bmap_free_t; - #define XFS_BMAP_MAX_NMAP 4 /* @@ -139,14 +118,6 @@ static inline int xfs_bmapi_aflag(int w) #define DELAYSTARTBLOCK ((xfs_fsblock_t)-1LL) #define HOLESTARTBLOCK ((xfs_fsblock_t)-2LL) -static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp) -{ - INIT_LIST_HEAD(&flp->xbf_flist); - flp->xbf_count = 0; - flp->xbf_low = 0; - *fbp = NULLFSBLOCK; -} - /* * Flags for xfs_bmap_add_extent*. */ @@ -195,9 +166,6 @@ int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist, xfs_fsblock_t bno, xfs_filblks_t len); -void xfs_bmap_cancel(struct xfs_bmap_free *flist); -int xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist, - struct xfs_inode *ip); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 714b387..fa5e3a5 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" @@ -462,7 +463,7 @@ xfs_bmbt_alloc_block( * block allocation here and corrupt the filesystem. */ args.minleft = args.tp->t_blk_res; - } else if (cur->bc_private.b.flist->xbf_low) { + } else if (cur->bc_private.b.flist->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; @@ -490,7 +491,7 @@ xfs_bmbt_alloc_block( error = xfs_alloc_vextent(&args); if (error) goto error0; - cur->bc_private.b.flist->xbf_low = 1; + cur->bc_private.b.flist->dop_low = true; } if (args.fsbno == NULLFSBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index eac876a..5b3743a 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_inode_item.h" diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 743fc32..4c05ba6 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -94,4 +94,11 @@ struct xfs_defer_op_type { void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); void xfs_defer_init_types(void); +/* XXX: compatibility shims, will go away in the next patch */ +#define xfs_bmap_finish xfs_defer_finish +#define xfs_bmap_cancel xfs_defer_cancel +#define xfs_bmap_init xfs_defer_init +#define xfs_bmap_free xfs_defer_ops +typedef struct xfs_defer_ops xfs_bmap_free_t; + #endif /* __XFS_DEFER_H__ */ diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index af0f9d1..945c0345 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -21,6 +21,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index cda7269..9ae9a43 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_ialloc.h" diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 794fa66..44f325c 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -22,6 +22,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_error.h" #include "xfs_cksum.h" diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 09d6fd0..a544686 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_ialloc.h" #include "xfs_alloc.h" diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 1aac0ba..972a27a 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -25,6 +25,7 @@ #include "xfs_bit.h" #include "xfs_mount.h" #include "xfs_da_format.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_trans.h" @@ -79,95 +80,6 @@ xfs_zero_extent( GFP_NOFS, true); } -/* Sort bmap items by AG. */ -static int -xfs_bmap_free_list_cmp( - void *priv, - struct list_head *a, - struct list_head *b) -{ - struct xfs_mount *mp = priv; - struct xfs_bmap_free_item *ra; - struct xfs_bmap_free_item *rb; - - ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); - rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); - return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - - XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); -} - -/* - * Routine to be called at transaction's end by xfs_bmapi, xfs_bunmapi - * caller. Frees all the extents that need freeing, which must be done - * last due to locking considerations. We never free any extents in - * the first transaction. - * - * If an inode *ip is provided, rejoin it to the transaction if - * the transaction was committed. - */ -int /* error */ -xfs_bmap_finish( - struct xfs_trans **tp, /* transaction pointer addr */ - struct xfs_bmap_free *flist, /* i/o: list extents to free */ - struct xfs_inode *ip) -{ - struct xfs_efd_log_item *efd; /* extent free data */ - struct xfs_efi_log_item *efi; /* extent free intention */ - int error; /* error return value */ - int committed;/* xact committed or not */ - struct xfs_bmap_free_item *free; /* free extent item */ - - ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); - if (flist->xbf_count == 0) - return 0; - - list_sort((*tp)->t_mountp, &flist->xbf_flist, xfs_bmap_free_list_cmp); - - efi = xfs_trans_get_efi(*tp, flist->xbf_count); - list_for_each_entry(free, &flist->xbf_flist, xbfi_list) - xfs_trans_log_efi_extent(*tp, efi, free->xbfi_startblock, - free->xbfi_blockcount); - - error = __xfs_trans_roll(tp, ip, &committed); - if (error) { - /* - * If the transaction was committed, drop the EFD reference - * since we're bailing out of here. The other reference is - * dropped when the EFI hits the AIL. - * - * If the transaction was not committed, the EFI is freed by the - * EFI item unlock handler on abort. Also, we have a new - * transaction so we should return committed=1 even though we're - * returning an error. - */ - if (committed) { - xfs_efi_release(efi); - xfs_force_shutdown((*tp)->t_mountp, - SHUTDOWN_META_IO_ERROR); - } - return error; - } - - /* - * Get an EFD and free each extent in the list, logging to the EFD in - * the process. The remaining bmap free list is cleaned up by the caller - * on error. - */ - efd = xfs_trans_get_efd(*tp, efi, flist->xbf_count); - while (!list_empty(&flist->xbf_flist)) { - free = list_first_entry(&flist->xbf_flist, - struct xfs_bmap_free_item, xbfi_list); - error = xfs_trans_free_extent(*tp, efd, free->xbfi_startblock, - free->xbfi_blockcount); - if (error) - return error; - - xfs_bmap_del_free(flist, free); - } - - return 0; -} - int xfs_bmap_rtalloc( struct xfs_bmalloca *ap) /* bmap alloc argument struct */ @@ -815,7 +727,7 @@ xfs_bmap_punch_delalloc_range( if (error) break; - ASSERT(!flist.xbf_count && list_empty(&flist.xbf_flist)); + ASSERT(!xfs_defer_has_unfinished_work(&flist)); next_block: start_fsb++; remaining--; diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h index f200714..51aadde 100644 --- a/fs/xfs/xfs_bmap_util.h +++ b/fs/xfs/xfs_bmap_util.h @@ -40,8 +40,6 @@ int xfs_getbmap(struct xfs_inode *ip, struct getbmapx *bmv, xfs_bmap_format_t formatter, void *arg); /* functions in xfs_bmap.c that are only needed by xfs_bmap_util.c */ -void xfs_bmap_del_free(struct xfs_bmap_free *flist, - struct xfs_bmap_free_item *free); int xfs_bmap_extsize_align(struct xfs_mount *mp, struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp, xfs_extlen_t extsz, int rt, int eof, int delay, int convert, diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index e064665..be17f0a 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index a51353a..3e990fb 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -22,6 +22,7 @@ #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" @@ -385,7 +386,7 @@ xfs_filestream_new_ag( } flags = (ap->userdata ? XFS_PICK_USERDATA : 0) | - (ap->flist->xbf_low ? XFS_PICK_LOWSPACE : 0); + (ap->flist->dop_low ? XFS_PICK_LOWSPACE : 0); err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index b4d7582..064fce1 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 8825bcf..d2389bb 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -25,6 +25,7 @@ #include "xfs_trans_resv.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 5839135..b090bc1 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -22,6 +22,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_bmap_btree.h" diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 8359978..080b54b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index e39b023..bf63682 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 3938b37..627f7e6 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_bmap.h" #include "xfs_bmap_util.h" diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 08a46c6..20af47b 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -26,6 +26,7 @@ #include "xfs_mount.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" +#include "xfs_defer.h" #include "xfs_dir2.h" #include "xfs_inode.h" #include "xfs_ialloc.h" diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c index 3971527..7f17ae6 100644 --- a/fs/xfs/xfs_trace.c +++ b/fs/xfs/xfs_trace.c @@ -24,6 +24,7 @@ #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_da_format.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_da_btree.h" From darrick.wong@oracle.com Thu Jun 16 20:20:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B9DF27CAF for ; Thu, 16 Jun 2016 20:20:15 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 769168F8054 for ; Thu, 16 Jun 2016 18:20:15 -0700 (PDT) X-ASG-Debug-ID: 1466126408-04bdf01e1795890001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id SVKNNhSXeRGf6cUu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:09 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1K5aH024940 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:05 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1K4vP010714 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:04 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1K1Cg006340; Fri, 17 Jun 2016 01:20:03 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:01 -0700 Subject: [PATCH 020/119] xfs: change xfs_bmap_{finish, cancel, init, free} -> xfs_defer_* From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 020/119] xfs: change xfs_bmap_{finish, cancel, init, free} -> xfs_defer_* To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:20:00 -0700 Message-ID: <146612639995.12839.12854314786533753722.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126409 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 46660 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.60 X-Barracuda-Spam-Status: No, SCORE=2.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_MV0249, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 2.00 BSF_SC0_MV0249 Custom rule MV0249 Drop the compatibility shims that we were using to integrate the new deferred operation mechanism into the existing code. No new code. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 58 ++++++++++++++++++------------------ fs/xfs/libxfs/xfs_attr_remote.c | 14 ++++----- fs/xfs/libxfs/xfs_bmap.c | 38 ++++++++++++------------ fs/xfs/libxfs/xfs_bmap.h | 10 +++--- fs/xfs/libxfs/xfs_btree.h | 5 ++- fs/xfs/libxfs/xfs_da_btree.h | 4 +-- fs/xfs/libxfs/xfs_defer.h | 7 ---- fs/xfs/libxfs/xfs_dir2.c | 6 ++-- fs/xfs/libxfs/xfs_dir2.h | 8 +++-- fs/xfs/libxfs/xfs_ialloc.c | 6 ++-- fs/xfs/libxfs/xfs_ialloc.h | 2 + fs/xfs/libxfs/xfs_trans_resv.c | 4 +-- fs/xfs/xfs_bmap_util.c | 28 +++++++++--------- fs/xfs/xfs_dquot.c | 10 +++--- fs/xfs/xfs_inode.c | 62 ++++++++++++++++++++------------------- fs/xfs/xfs_inode.h | 4 +-- fs/xfs/xfs_iomap.c | 24 ++++++++------- fs/xfs/xfs_rtalloc.c | 8 +++-- fs/xfs/xfs_symlink.c | 16 +++++----- 19 files changed, 154 insertions(+), 160 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 79d3a30..66baf97 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -204,7 +204,7 @@ xfs_attr_set( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_bmap_free flist; + struct xfs_defer_ops flist; struct xfs_trans_res tres; xfs_fsblock_t firstblock; int rsvd = (flags & ATTR_ROOT) != 0; @@ -317,13 +317,13 @@ xfs_attr_set( * It won't fit in the shortform, transform to a leaf block. * GROT: another possible req'mt for a double-split btree op. */ - xfs_bmap_init(args.flist, args.firstblock); + xfs_defer_init(args.flist, args.firstblock); error = xfs_attr_shortform_to_leaf(&args); if (!error) - error = xfs_bmap_finish(&args.trans, args.flist, dp); + error = xfs_defer_finish(&args.trans, args.flist, dp); if (error) { args.trans = NULL; - xfs_bmap_cancel(&flist); + xfs_defer_cancel(&flist); goto out; } @@ -383,7 +383,7 @@ xfs_attr_remove( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_bmap_free flist; + struct xfs_defer_ops flist; xfs_fsblock_t firstblock; int error; @@ -585,13 +585,13 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit that transaction so that the node_addname() call * can manage its own transactions. */ - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } @@ -675,15 +675,15 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } } @@ -738,14 +738,14 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } } @@ -864,14 +864,14 @@ restart: */ xfs_da_state_free(state); state = NULL; - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } @@ -892,13 +892,13 @@ restart: * in the index/blkno/rmtblkno/rmtblkcnt fields and * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_da3_split(state); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } } else { @@ -991,14 +991,14 @@ restart: * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_da3_join(state); if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } } @@ -1114,13 +1114,13 @@ xfs_attr_node_removename(xfs_da_args_t *args) * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_da3_join(state); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } /* @@ -1147,15 +1147,15 @@ xfs_attr_node_removename(xfs_da_args_t *args) goto out; if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } } else diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index 93a9ce1..aabb516 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -461,16 +461,16 @@ xfs_attr_rmtval_set( * extent and then crash then the block may not contain the * correct metadata after log recovery occurs. */ - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); nmap = 1; error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, args->total, &map, &nmap, args->flist); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } @@ -504,7 +504,7 @@ xfs_attr_rmtval_set( ASSERT(blkcnt > 0); - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); nmap = 1; error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, @@ -604,16 +604,16 @@ xfs_attr_rmtval_remove( blkcnt = args->rmtblkcnt; done = 0; while (!done) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, args->firstblock, args->flist, &done); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, + error = xfs_defer_finish(&args->trans, args->flist, args->dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 64ca97f..45ce7bd 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -572,7 +572,7 @@ xfs_bmap_validate_ret( void xfs_bmap_add_free( struct xfs_mount *mp, /* mount point structure */ - struct xfs_bmap_free *flist, /* list of extents */ + struct xfs_defer_ops *flist, /* list of extents */ xfs_fsblock_t bno, /* fs block number of extent */ xfs_filblks_t len) /* length of extent */ { @@ -672,7 +672,7 @@ xfs_bmap_extents_to_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first-block-allocated */ - xfs_bmap_free_t *flist, /* blocks freed in xaction */ + struct xfs_defer_ops *flist, /* blocks freed in xaction */ xfs_btree_cur_t **curp, /* cursor returned to caller */ int wasdel, /* converting a delayed alloc */ int *logflagsp, /* inode logging flags */ @@ -940,7 +940,7 @@ xfs_bmap_add_attrfork_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - xfs_bmap_free_t *flist, /* blocks to free at commit */ + struct xfs_defer_ops *flist, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -983,7 +983,7 @@ xfs_bmap_add_attrfork_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - xfs_bmap_free_t *flist, /* blocks to free at commit */ + struct xfs_defer_ops *flist, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -1018,7 +1018,7 @@ xfs_bmap_add_attrfork_local( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - xfs_bmap_free_t *flist, /* blocks to free at commit */ + struct xfs_defer_ops *flist, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_da_args_t dargs; /* args for dir/attr code */ @@ -1059,7 +1059,7 @@ xfs_bmap_add_attrfork( int rsvd) /* xact may use reserved blks */ { xfs_fsblock_t firstblock; /* 1st block/ag allocated */ - xfs_bmap_free_t flist; /* freed extent records */ + struct xfs_defer_ops flist; /* freed extent records */ xfs_mount_t *mp; /* mount structure */ xfs_trans_t *tp; /* transaction pointer */ int blks; /* space reservation */ @@ -1125,7 +1125,7 @@ xfs_bmap_add_attrfork( ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); ip->i_afp->if_flags = XFS_IFEXTENTS; logflags = 0; - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); switch (ip->i_d.di_format) { case XFS_DINODE_FMT_LOCAL: error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist, @@ -1165,7 +1165,7 @@ xfs_bmap_add_attrfork( xfs_log_sb(tp); } - error = xfs_bmap_finish(&tp, &flist, NULL); + error = xfs_defer_finish(&tp, &flist, NULL); if (error) goto bmap_cancel; error = xfs_trans_commit(tp); @@ -1173,7 +1173,7 @@ xfs_bmap_add_attrfork( return error; bmap_cancel: - xfs_bmap_cancel(&flist); + xfs_defer_cancel(&flist); trans_cancel: xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -2214,7 +2214,7 @@ xfs_bmap_add_extent_unwritten_real( xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ - xfs_bmap_free_t *flist, /* list of extents to be freed */ + struct xfs_defer_ops *flist, /* list of extents to be freed */ int *logflagsp) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -4447,7 +4447,7 @@ xfs_bmapi_write( xfs_extlen_t total, /* total blocks needed */ struct xfs_bmbt_irec *mval, /* output: map values */ int *nmap, /* i/o: mval size/count */ - struct xfs_bmap_free *flist) /* i/o: list extents to free */ + struct xfs_defer_ops *flist) /* i/o: list extents to free */ { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; @@ -4735,7 +4735,7 @@ xfs_bmap_del_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current transaction pointer */ xfs_extnum_t *idx, /* extent number to update/delete */ - xfs_bmap_free_t *flist, /* list of extents to be freed */ + struct xfs_defer_ops *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ @@ -5064,7 +5064,7 @@ xfs_bunmapi( xfs_extnum_t nexts, /* number of extents max */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ - xfs_bmap_free_t *flist, /* i/o: list extents to free */ + struct xfs_defer_ops *flist, /* i/o: list extents to free */ int *done) /* set if not done yet */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -5678,7 +5678,7 @@ xfs_bmap_shift_extents( int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_bmap_free *flist, + struct xfs_defer_ops *flist, enum shift_direction direction, int num_exts) { @@ -5832,7 +5832,7 @@ xfs_bmap_split_extent_at( struct xfs_inode *ip, xfs_fileoff_t split_fsb, xfs_fsblock_t *firstfsb, - struct xfs_bmap_free *free_list) + struct xfs_defer_ops *free_list) { int whichfork = XFS_DATA_FORK; struct xfs_btree_cur *cur = NULL; @@ -5971,7 +5971,7 @@ xfs_bmap_split_extent( { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; - struct xfs_bmap_free free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t firstfsb; int error; @@ -5983,21 +5983,21 @@ xfs_bmap_split_extent( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_bmap_init(&free_list, &firstfsb); + xfs_defer_init(&free_list, &firstfsb); error = xfs_bmap_split_extent_at(tp, ip, split_fsb, &firstfsb, &free_list); if (error) goto out; - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto out; return xfs_trans_commit(tp); out: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 6681bd9..e2a0425 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -32,7 +32,7 @@ extern kmem_zone_t *xfs_bmap_free_item_zone; */ struct xfs_bmalloca { xfs_fsblock_t *firstblock; /* i/o first block allocated */ - struct xfs_bmap_free *flist; /* bmap freelist */ + struct xfs_defer_ops *flist; /* bmap freelist */ struct xfs_trans *tp; /* transaction pointer */ struct xfs_inode *ip; /* incore inode pointer */ struct xfs_bmbt_irec prev; /* extent before the new one */ @@ -164,7 +164,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); -void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist, +void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *flist, xfs_fsblock_t bno, xfs_filblks_t len); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, @@ -186,18 +186,18 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_fsblock_t *firstblock, xfs_extlen_t total, struct xfs_bmbt_irec *mval, int *nmap, - struct xfs_bmap_free *flist); + struct xfs_defer_ops *flist); int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, - struct xfs_bmap_free *flist, int *done); + struct xfs_defer_ops *flist, int *done); int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, xfs_extnum_t num); uint xfs_default_attroffset(struct xfs_inode *ip); int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_bmap_free *flist, enum shift_direction direction, + struct xfs_defer_ops *flist, enum shift_direction direction, int num_exts); int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 0ec3055..ae714a8 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -19,7 +19,7 @@ #define __XFS_BTREE_H__ struct xfs_buf; -struct xfs_bmap_free; +struct xfs_defer_ops; struct xfs_inode; struct xfs_mount; struct xfs_trans; @@ -234,11 +234,12 @@ typedef struct xfs_btree_cur union { struct { /* needed for BNO, CNT, INO */ struct xfs_buf *agbp; /* agf/agi buffer pointer */ + struct xfs_defer_ops *flist; /* deferred updates */ xfs_agnumber_t agno; /* ag number */ } a; struct { /* needed for BMAP */ struct xfs_inode *ip; /* pointer to our inode */ - struct xfs_bmap_free *flist; /* list to free after */ + struct xfs_defer_ops *flist; /* deferred updates */ xfs_fsblock_t firstblock; /* 1st blk allocated */ int allocated; /* count of alloced */ short forksize; /* fork's inode space */ diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h index 6e153e3..249813a 100644 --- a/fs/xfs/libxfs/xfs_da_btree.h +++ b/fs/xfs/libxfs/xfs_da_btree.h @@ -19,7 +19,7 @@ #ifndef __XFS_DA_BTREE_H__ #define __XFS_DA_BTREE_H__ -struct xfs_bmap_free; +struct xfs_defer_ops; struct xfs_inode; struct xfs_trans; struct zone; @@ -70,7 +70,7 @@ typedef struct xfs_da_args { xfs_ino_t inumber; /* input/output inode number */ struct xfs_inode *dp; /* directory inode to manipulate */ xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */ - struct xfs_bmap_free *flist; /* ptr to freelist for bmap_finish */ + struct xfs_defer_ops *flist; /* ptr to freelist for bmap_finish */ struct xfs_trans *trans; /* current trans (changes over time) */ xfs_extlen_t total; /* total blocks needed, for 1st bmap */ int whichfork; /* data or attribute fork */ diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 4c05ba6..743fc32 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -94,11 +94,4 @@ struct xfs_defer_op_type { void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); void xfs_defer_init_types(void); -/* XXX: compatibility shims, will go away in the next patch */ -#define xfs_bmap_finish xfs_defer_finish -#define xfs_bmap_cancel xfs_defer_cancel -#define xfs_bmap_init xfs_defer_init -#define xfs_bmap_free xfs_defer_ops -typedef struct xfs_defer_ops xfs_bmap_free_t; - #endif /* __XFS_DEFER_H__ */ diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 945c0345..0523100 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -260,7 +260,7 @@ xfs_dir_createname( struct xfs_name *name, xfs_ino_t inum, /* new entry inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - xfs_bmap_free_t *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -437,7 +437,7 @@ xfs_dir_removename( struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, /* bmap's firstblock */ - xfs_bmap_free_t *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -499,7 +499,7 @@ xfs_dir_replace( struct xfs_name *name, /* name of entry to replace */ xfs_ino_t inum, /* new inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - xfs_bmap_free_t *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index 0a62e73..5737d85 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -18,7 +18,7 @@ #ifndef __XFS_DIR2_H__ #define __XFS_DIR2_H__ -struct xfs_bmap_free; +struct xfs_defer_ops; struct xfs_da_args; struct xfs_inode; struct xfs_mount; @@ -129,18 +129,18 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_bmap_free *flist, xfs_extlen_t tot); + struct xfs_defer_ops *flist, xfs_extlen_t tot); extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t *inum, struct xfs_name *ci_name); extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, - struct xfs_bmap_free *flist, xfs_extlen_t tot); + struct xfs_defer_ops *flist, xfs_extlen_t tot); extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_bmap_free *flist, xfs_extlen_t tot); + struct xfs_defer_ops *flist, xfs_extlen_t tot); extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name); diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 9ae9a43..f2e29a1 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -1818,7 +1818,7 @@ xfs_difree_inode_chunk( struct xfs_mount *mp, xfs_agnumber_t agno, struct xfs_inobt_rec_incore *rec, - struct xfs_bmap_free *flist) + struct xfs_defer_ops *flist) { xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); int startidx, endidx; @@ -1890,7 +1890,7 @@ xfs_difree_inobt( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agino_t agino, - struct xfs_bmap_free *flist, + struct xfs_defer_ops *flist, struct xfs_icluster *xic, struct xfs_inobt_rec_incore *orec) { @@ -2122,7 +2122,7 @@ int xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_bmap_free *flist, /* extents to free */ + struct xfs_defer_ops *flist, /* extents to free */ struct xfs_icluster *xic) /* cluster info if deleted */ { /* REFERENCED */ diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h index 6e450df..2e06b67 100644 --- a/fs/xfs/libxfs/xfs_ialloc.h +++ b/fs/xfs/libxfs/xfs_ialloc.h @@ -95,7 +95,7 @@ int /* error */ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_bmap_free *flist, /* extents to free */ + struct xfs_defer_ops *flist, /* extents to free */ struct xfs_icluster *ifree); /* cluster info if deleted */ /* diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index 68cb1e7..4c7eb9d 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -153,9 +153,9 @@ xfs_calc_finobt_res( * item logged to try to account for the overhead of the transaction mechanism. * * Note: Most of the reservations underestimate the number of allocation - * groups into which they could free extents in the xfs_bmap_finish() call. + * groups into which they could free extents in the xfs_defer_finish() call. * This is because the number in the worst case is quite high and quite - * unusual. In order to fix this we need to change xfs_bmap_finish() to free + * unusual. In order to fix this we need to change xfs_defer_finish() to free * extents in only a single AG at a time. This will require changes to the * EFI code as well, however, so that the EFI for the extents not freed is * logged again in each transaction. See SGI PV #261917. diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 972a27a..928dfa4 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -685,7 +685,7 @@ xfs_bmap_punch_delalloc_range( xfs_bmbt_irec_t imap; int nimaps = 1; xfs_fsblock_t firstblock; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; /* * Map the range first and check that it is a delalloc extent @@ -721,7 +721,7 @@ xfs_bmap_punch_delalloc_range( * allocated or freed for a delalloc extent and hence we need * don't cancel or finish them after the xfs_bunmapi() call. */ - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock, &flist, &done); if (error) @@ -884,7 +884,7 @@ xfs_alloc_file_space( int rt; xfs_trans_t *tp; xfs_bmbt_irec_t imaps[1], *imapp; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; uint qblocks, resblks, resrtextents; int error; @@ -975,7 +975,7 @@ xfs_alloc_file_space( xfs_trans_ijoin(tp, ip, 0); - xfs_bmap_init(&free_list, &firstfsb); + xfs_defer_init(&free_list, &firstfsb); error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb, alloc_type, &firstfsb, resblks, imapp, &nimaps, &free_list); @@ -985,7 +985,7 @@ xfs_alloc_file_space( /* * Complete the transaction */ - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto error0; @@ -1008,7 +1008,7 @@ xfs_alloc_file_space( return error; error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag); error1: /* Just cancel transaction */ @@ -1122,7 +1122,7 @@ xfs_free_file_space( xfs_fileoff_t endoffset_fsb; int error; xfs_fsblock_t firstfsb; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_bmbt_irec_t imap; xfs_off_t ioffset; xfs_off_t iendoffset; @@ -1245,7 +1245,7 @@ xfs_free_file_space( /* * issue the bunmapi() call to free the blocks */ - xfs_bmap_init(&free_list, &firstfsb); + xfs_defer_init(&free_list, &firstfsb); error = xfs_bunmapi(tp, ip, startoffset_fsb, endoffset_fsb - startoffset_fsb, 0, 2, &firstfsb, &free_list, &done); @@ -1255,7 +1255,7 @@ xfs_free_file_space( /* * complete the transaction */ - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, ip); if (error) goto error0; @@ -1267,7 +1267,7 @@ xfs_free_file_space( return error; error0: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); error1: xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -1333,7 +1333,7 @@ xfs_shift_file_space( struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; int error; - struct xfs_bmap_free free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; xfs_fileoff_t stop_fsb; xfs_fileoff_t next_fsb; @@ -1411,7 +1411,7 @@ xfs_shift_file_space( xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); /* * We are using the write transaction in which max 2 bmbt @@ -1423,7 +1423,7 @@ xfs_shift_file_space( if (error) goto out_bmap_cancel; - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto out_bmap_cancel; @@ -1433,7 +1433,7 @@ xfs_shift_file_space( return error; out_bmap_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); out_trans_cancel: xfs_trans_cancel(tp); return error; diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index be17f0a..764e1cc 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -307,7 +307,7 @@ xfs_qm_dqalloc( xfs_buf_t **O_bpp) { xfs_fsblock_t firstblock; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; xfs_bmbt_irec_t map; int nmaps, error; xfs_buf_t *bp; @@ -320,7 +320,7 @@ xfs_qm_dqalloc( /* * Initialize the bmap freelist prior to calling bmapi code. */ - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); xfs_ilock(quotip, XFS_ILOCK_EXCL); /* * Return if this type of quotas is turned off while we didn't @@ -368,7 +368,7 @@ xfs_qm_dqalloc( dqp->dq_flags & XFS_DQ_ALLTYPES, bp); /* - * xfs_bmap_finish() may commit the current transaction and + * xfs_defer_finish() may commit the current transaction and * start a second transaction if the freelist is not empty. * * Since we still want to modify this buffer, we need to @@ -382,7 +382,7 @@ xfs_qm_dqalloc( xfs_trans_bhold(tp, bp); - error = xfs_bmap_finish(tpp, &flist, NULL); + error = xfs_defer_finish(tpp, &flist, NULL); if (error) goto error1; @@ -398,7 +398,7 @@ xfs_qm_dqalloc( return 0; error1: - xfs_bmap_cancel(&flist); + xfs_defer_cancel(&flist); error0: xfs_iunlock(quotip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index d2389bb..3ce50da 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1123,7 +1123,7 @@ xfs_create( struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; int error; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; bool unlock_dp_on_error = false; prid_t prid; @@ -1183,7 +1183,7 @@ xfs_create( XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT); unlock_dp_on_error = true; - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); /* * Reserve disk quota and the inode. @@ -1254,7 +1254,7 @@ xfs_create( */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto out_bmap_cancel; @@ -1270,7 +1270,7 @@ xfs_create( return 0; out_bmap_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); out_trans_cancel: xfs_trans_cancel(tp); out_release_inode: @@ -1402,7 +1402,7 @@ xfs_link( xfs_mount_t *mp = tdp->i_mount; xfs_trans_t *tp; int error; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; int resblks; @@ -1453,7 +1453,7 @@ xfs_link( goto error_return; } - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); /* * Handle initial link state of O_TMPFILE inode @@ -1483,9 +1483,9 @@ xfs_link( if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) { - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); goto error_return; } @@ -1527,7 +1527,7 @@ xfs_itruncate_extents( { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp = *tpp; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; xfs_fileoff_t first_unmap_block; xfs_fileoff_t last_block; @@ -1563,7 +1563,7 @@ xfs_itruncate_extents( ASSERT(first_unmap_block < last_block); unmap_len = last_block - first_unmap_block + 1; while (!done) { - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); error = xfs_bunmapi(tp, ip, first_unmap_block, unmap_len, xfs_bmapi_aflag(whichfork), @@ -1577,7 +1577,7 @@ xfs_itruncate_extents( * Duplicate the transaction that has the permanent * reservation and commit the old transaction. */ - error = xfs_bmap_finish(&tp, &free_list, ip); + error = xfs_defer_finish(&tp, &free_list, ip); if (error) goto out_bmap_cancel; @@ -1603,7 +1603,7 @@ out_bmap_cancel: * the transaction can be properly aborted. We just need to make sure * we're not holding any resources that we were not when we came in. */ - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); goto out; } @@ -1744,7 +1744,7 @@ STATIC int xfs_inactive_ifree( struct xfs_inode *ip) { - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; @@ -1781,7 +1781,7 @@ xfs_inactive_ifree( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); error = xfs_ifree(tp, ip, &free_list); if (error) { /* @@ -1808,11 +1808,11 @@ xfs_inactive_ifree( * Just ignore errors at this point. There is nothing we can do except * to try to keep going. Make sure it's not a silent error. */ - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) { - xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", + xfs_notice(mp, "%s: xfs_defer_finish returned error %d", __func__, error); - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); } error = xfs_trans_commit(tp); if (error) @@ -2368,7 +2368,7 @@ int xfs_ifree( xfs_trans_t *tp, xfs_inode_t *ip, - xfs_bmap_free_t *flist) + struct xfs_defer_ops *flist) { int error; struct xfs_icluster xic = { 0 }; @@ -2475,7 +2475,7 @@ xfs_iunpin_wait( * directory entry. * * This is still safe from a transactional point of view - it is not until we - * get to xfs_bmap_finish() that we have the possibility of multiple + * get to xfs_defer_finish() that we have the possibility of multiple * transactions in this operation. Hence as long as we remove the directory * entry and drop the link count in the first transaction of the remove * operation, there are no transactional constraints on the ordering here. @@ -2490,7 +2490,7 @@ xfs_remove( xfs_trans_t *tp = NULL; int is_dir = S_ISDIR(VFS_I(ip)->i_mode); int error = 0; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; uint resblks; @@ -2572,7 +2572,7 @@ xfs_remove( if (error) goto out_trans_cancel; - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); error = xfs_dir_removename(tp, dp, name, ip->i_ino, &first_block, &free_list, resblks); if (error) { @@ -2588,7 +2588,7 @@ xfs_remove( if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto out_bmap_cancel; @@ -2602,7 +2602,7 @@ xfs_remove( return 0; out_bmap_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); out_trans_cancel: xfs_trans_cancel(tp); std_return: @@ -2663,7 +2663,7 @@ xfs_sort_for_rename( static int xfs_finish_rename( struct xfs_trans *tp, - struct xfs_bmap_free *free_list) + struct xfs_defer_ops *free_list) { int error; @@ -2674,9 +2674,9 @@ xfs_finish_rename( if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_bmap_finish(&tp, free_list, NULL); + error = xfs_defer_finish(&tp, free_list, NULL); if (error) { - xfs_bmap_cancel(free_list); + xfs_defer_cancel(free_list); xfs_trans_cancel(tp); return error; } @@ -2698,7 +2698,7 @@ xfs_cross_rename( struct xfs_inode *dp2, struct xfs_name *name2, struct xfs_inode *ip2, - struct xfs_bmap_free *free_list, + struct xfs_defer_ops *free_list, xfs_fsblock_t *first_block, int spaceres) { @@ -2801,7 +2801,7 @@ xfs_cross_rename( return xfs_finish_rename(tp, free_list); out_trans_abort: - xfs_bmap_cancel(free_list); + xfs_defer_cancel(free_list); xfs_trans_cancel(tp); return error; } @@ -2856,7 +2856,7 @@ xfs_rename( { struct xfs_mount *mp = src_dp->i_mount; struct xfs_trans *tp; - struct xfs_bmap_free free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; struct xfs_inode *wip = NULL; /* whiteout inode */ struct xfs_inode *inodes[__XFS_SORT_INODES]; @@ -2945,7 +2945,7 @@ xfs_rename( goto out_trans_cancel; } - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); /* RENAME_EXCHANGE is unique from here on. */ if (flags & RENAME_EXCHANGE) @@ -3131,7 +3131,7 @@ xfs_rename( return error; out_bmap_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); out_trans_cancel: xfs_trans_cancel(tp); out_release_wip: diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 99d7522..633f2af 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -27,7 +27,7 @@ struct xfs_dinode; struct xfs_inode; struct xfs_buf; -struct xfs_bmap_free; +struct xfs_defer_ops; struct xfs_bmbt_irec; struct xfs_inode_log_item; struct xfs_mount; @@ -398,7 +398,7 @@ uint xfs_ilock_attr_map_shared(struct xfs_inode *); uint xfs_ip2xflags(struct xfs_inode *); int xfs_ifree(struct xfs_trans *, xfs_inode_t *, - struct xfs_bmap_free *); + struct xfs_defer_ops *); int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *, int, xfs_fsize_t); void xfs_iext_realloc(xfs_inode_t *, int, int); diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index b090bc1..cb7abe84 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -128,7 +128,7 @@ xfs_iomap_write_direct( int quota_flag; int rt; xfs_trans_t *tp; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; uint qblocks, resblks, resrtextents; int error; int lockmode; @@ -231,7 +231,7 @@ xfs_iomap_write_direct( * From this point onwards we overwrite the imap pointer that the * caller gave to us. */ - xfs_bmap_init(&free_list, &firstfsb); + xfs_defer_init(&free_list, &firstfsb); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flags, &firstfsb, resblks, imap, @@ -242,7 +242,7 @@ xfs_iomap_write_direct( /* * Complete the transaction */ - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto out_bmap_cancel; @@ -266,7 +266,7 @@ out_unlock: return error; out_bmap_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag); out_trans_cancel: xfs_trans_cancel(tp); @@ -685,7 +685,7 @@ xfs_iomap_write_allocate( xfs_fileoff_t offset_fsb, last_block; xfs_fileoff_t end_fsb, map_start_fsb; xfs_fsblock_t first_block; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_filblks_t count_fsb; xfs_trans_t *tp; int nimaps; @@ -727,7 +727,7 @@ xfs_iomap_write_allocate( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); /* * it is possible that the extents have changed since @@ -787,7 +787,7 @@ xfs_iomap_write_allocate( if (error) goto trans_cancel; - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto trans_cancel; @@ -821,7 +821,7 @@ xfs_iomap_write_allocate( } trans_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); xfs_trans_cancel(tp); error0: xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -842,7 +842,7 @@ xfs_iomap_write_unwritten( int nimaps; xfs_trans_t *tp; xfs_bmbt_irec_t imap; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_fsize_t i_size; uint resblks; int error; @@ -886,7 +886,7 @@ xfs_iomap_write_unwritten( /* * Modify the unwritten extent state of the buffer. */ - xfs_bmap_init(&free_list, &firstfsb); + xfs_defer_init(&free_list, &firstfsb); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, XFS_BMAPI_CONVERT, &firstfsb, resblks, @@ -909,7 +909,7 @@ xfs_iomap_write_unwritten( xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto error_on_bmapi_transaction; @@ -936,7 +936,7 @@ xfs_iomap_write_unwritten( return 0; error_on_bmapi_transaction: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); return error; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 627f7e6..c761a6a 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -770,7 +770,7 @@ xfs_growfs_rt_alloc( xfs_daddr_t d; /* disk block address */ int error; /* error return value */ xfs_fsblock_t firstblock;/* first block allocated in xaction */ - struct xfs_bmap_free flist; /* list of freed blocks */ + struct xfs_defer_ops flist; /* list of freed blocks */ xfs_fsblock_t fsbno; /* filesystem block for bno */ struct xfs_bmbt_irec map; /* block map output */ int nmap; /* number of block maps */ @@ -795,7 +795,7 @@ xfs_growfs_rt_alloc( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); /* * Allocate blocks to the bitmap file. */ @@ -810,7 +810,7 @@ xfs_growfs_rt_alloc( /* * Free any blocks freed up in the transaction, then commit. */ - error = xfs_bmap_finish(&tp, &flist, NULL); + error = xfs_defer_finish(&tp, &flist, NULL); if (error) goto out_bmap_cancel; error = xfs_trans_commit(tp); @@ -863,7 +863,7 @@ xfs_growfs_rt_alloc( return 0; out_bmap_cancel: - xfs_bmap_cancel(&flist); + xfs_defer_cancel(&flist); out_trans_cancel: xfs_trans_cancel(tp); return error; diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 20af47b..3b005ec 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -173,7 +173,7 @@ xfs_symlink( struct xfs_inode *ip = NULL; int error = 0; int pathlen; - struct xfs_bmap_free free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t first_block; bool unlock_dp_on_error = false; xfs_fileoff_t first_fsb; @@ -270,7 +270,7 @@ xfs_symlink( * Initialize the bmap freelist prior to calling either * bmapi or the directory create code. */ - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); /* * Allocate an inode for the symlink. @@ -377,7 +377,7 @@ xfs_symlink( xfs_trans_set_sync(tp); } - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto out_bmap_cancel; @@ -393,7 +393,7 @@ xfs_symlink( return 0; out_bmap_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); out_trans_cancel: xfs_trans_cancel(tp); out_release_inode: @@ -427,7 +427,7 @@ xfs_inactive_symlink_rmt( int done; int error; xfs_fsblock_t first_block; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; int i; xfs_mount_t *mp; xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; @@ -466,7 +466,7 @@ xfs_inactive_symlink_rmt( * Find the block(s) so we can inval and unmap them. */ done = 0; - xfs_bmap_init(&free_list, &first_block); + xfs_defer_init(&free_list, &first_block); nmaps = ARRAY_SIZE(mval); error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), mval, &nmaps, 0); @@ -496,7 +496,7 @@ xfs_inactive_symlink_rmt( /* * Commit the first transaction. This logs the EFI and the inode. */ - error = xfs_bmap_finish(&tp, &free_list, ip); + error = xfs_defer_finish(&tp, &free_list, ip); if (error) goto error_bmap_cancel; /* @@ -526,7 +526,7 @@ xfs_inactive_symlink_rmt( return 0; error_bmap_cancel: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); error_trans_cancel: xfs_trans_cancel(tp); error_unlock: From darrick.wong@oracle.com Thu Jun 16 20:20:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 4CFF77D21 for ; Thu, 16 Jun 2016 20:20:20 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 11AF6304048 for ; Thu, 16 Jun 2016 18:20:20 -0700 (PDT) X-ASG-Debug-ID: 1466126418-04cbb01fec69590001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id irKx1wMM0KwyqXP6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1KFH0025102 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:20:16 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1KF4m008114 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:15 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1KEGX022823; Fri, 17 Jun 2016 01:20:15 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:14 -0700 Subject: [PATCH 022/119] xfs: add tracepoints and error injection for deferred extent freeing From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 022/119] xfs: add tracepoints and error injection for deferred extent freeing To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:20:13 -0700 Message-ID: <146612641307.12839.12827584555660167380.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126418 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3053 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add a couple of tracepoints for the deferred extent free operation and a site for injecting errors while finishing the operation. This makes it easier to debug deferred ops and test log redo. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 7 +++++++ fs/xfs/libxfs/xfs_bmap.c | 2 ++ fs/xfs/xfs_error.h | 4 +++- fs/xfs/xfs_trace.h | 5 ++++- 4 files changed, 16 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index c06b463..56c8690 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2704,6 +2704,13 @@ xfs_free_extent( ASSERT(len != 0); + trace_xfs_bmap_free_deferred(mp, agno, 0, agbno, len); + + if (XFS_TEST_ERROR(false, mp, + XFS_ERRTAG_FREE_EXTENT, + XFS_RANDOM_FREE_EXTENT)) + return -EIO; + error = xfs_free_extent_fix_freelist(tp, agno, &agbp); if (error) return error; diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 85061a0..3a6d3e3 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -596,6 +596,8 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; + trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0, + XFS_FSB_TO_AGBNO(mp, bno), len); xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); } diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 4ed3042..ee4680e 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -90,7 +90,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_ERRTAG_STRATCMPL_IOERR 19 #define XFS_ERRTAG_DIOWRITE_IOERR 20 #define XFS_ERRTAG_BMAPIFORMAT 21 -#define XFS_ERRTAG_MAX 22 +#define XFS_ERRTAG_FREE_EXTENT 22 +#define XFS_ERRTAG_MAX 23 /* * Random factors for above tags, 1 means always, 2 means 1/2 time, etc. @@ -117,6 +118,7 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_RANDOM_STRATCMPL_IOERR (XFS_RANDOM_DEFAULT/10) #define XFS_RANDOM_DIOWRITE_IOERR (XFS_RANDOM_DEFAULT/10) #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT +#define XFS_RANDOM_FREE_EXTENT 1 #ifdef DEBUG extern int xfs_error_test_active; diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 5923014..777a89c 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2415,9 +2415,12 @@ DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel); DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish); DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort); -DEFINE_PHYS_EXTENT_DEFERRED_EVENT(xfs_defer_phys_extent); DEFINE_MAP_EXTENT_DEFERRED_EVENT(xfs_defer_map_extent); +#define DEFINE_BMAP_FREE_DEFERRED_EVENT DEFINE_PHYS_EXTENT_DEFERRED_EVENT +DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_defer); +DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_deferred); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:20:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 65B467D25 for ; Thu, 16 Jun 2016 20:20:23 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 36C72304048 for ; Thu, 16 Jun 2016 18:20:23 -0700 (PDT) X-ASG-Debug-ID: 1466126414-04cb6c542657260001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id erGfsI4SoevbL0SE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1KBob025070 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:12 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1KBfb010885 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:11 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1K8V7006365; Fri, 17 Jun 2016 01:20:09 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:08 -0700 Subject: [PATCH 021/119] xfs: rename flist/free_list to dfops From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 021/119] xfs: rename flist/free_list to dfops To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:20:06 -0700 Message-ID: <146612640648.12839.2455186020787957758.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126414 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 68740 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Mechanical change of flist/free_list to dfops, since they're now deferred ops, not just a freeing list. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_attr.c | 62 ++++++++++----------- fs/xfs/libxfs/xfs_attr_leaf.c | 4 + fs/xfs/libxfs/xfs_attr_remote.c | 18 +++--- fs/xfs/libxfs/xfs_bmap.c | 116 ++++++++++++++++++++------------------- fs/xfs/libxfs/xfs_bmap.h | 10 ++- fs/xfs/libxfs/xfs_bmap_btree.c | 14 ++--- fs/xfs/libxfs/xfs_btree.h | 4 + fs/xfs/libxfs/xfs_da_btree.c | 6 +- fs/xfs/libxfs/xfs_da_btree.h | 2 - fs/xfs/libxfs/xfs_dir2.c | 14 ++--- fs/xfs/libxfs/xfs_dir2.h | 6 +- fs/xfs/libxfs/xfs_ialloc.c | 14 ++--- fs/xfs/libxfs/xfs_ialloc.h | 2 - fs/xfs/xfs_bmap_util.c | 40 +++++++------ fs/xfs/xfs_dquot.c | 10 ++- fs/xfs/xfs_filestream.c | 2 - fs/xfs/xfs_inode.c | 94 ++++++++++++++++---------------- fs/xfs/xfs_iomap.c | 30 +++++----- fs/xfs/xfs_rtalloc.c | 10 ++- fs/xfs/xfs_symlink.c | 24 ++++---- 20 files changed, 241 insertions(+), 241 deletions(-) diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 66baf97..af1ecb1 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -204,7 +204,7 @@ xfs_attr_set( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; struct xfs_trans_res tres; xfs_fsblock_t firstblock; int rsvd = (flags & ATTR_ROOT) != 0; @@ -222,7 +222,7 @@ xfs_attr_set( args.value = value; args.valuelen = valuelen; args.firstblock = &firstblock; - args.flist = &flist; + args.dfops = &dfops; args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; args.total = xfs_attr_calc_size(&args, &local); @@ -317,13 +317,13 @@ xfs_attr_set( * It won't fit in the shortform, transform to a leaf block. * GROT: another possible req'mt for a double-split btree op. */ - xfs_defer_init(args.flist, args.firstblock); + xfs_defer_init(args.dfops, args.firstblock); error = xfs_attr_shortform_to_leaf(&args); if (!error) - error = xfs_defer_finish(&args.trans, args.flist, dp); + error = xfs_defer_finish(&args.trans, args.dfops, dp); if (error) { args.trans = NULL; - xfs_defer_cancel(&flist); + xfs_defer_cancel(&dfops); goto out; } @@ -383,7 +383,7 @@ xfs_attr_remove( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; xfs_fsblock_t firstblock; int error; @@ -400,7 +400,7 @@ xfs_attr_remove( return error; args.firstblock = &firstblock; - args.flist = &flist; + args.dfops = &dfops; /* * we have no control over the attribute names that userspace passes us @@ -585,13 +585,13 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit that transaction so that the node_addname() call * can manage its own transactions. */ - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } @@ -675,15 +675,15 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } } @@ -738,14 +738,14 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } } @@ -864,14 +864,14 @@ restart: */ xfs_da_state_free(state); state = NULL; - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } @@ -892,13 +892,13 @@ restart: * in the index/blkno/rmtblkno/rmtblkcnt fields and * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_split(state); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } } else { @@ -991,14 +991,14 @@ restart: * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_join(state); if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } } @@ -1114,13 +1114,13 @@ xfs_attr_node_removename(xfs_da_args_t *args) * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_join(state); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } /* @@ -1147,15 +1147,15 @@ xfs_attr_node_removename(xfs_da_args_t *args) goto out; if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } } else diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 01a5ecf..8ea91f3 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -792,7 +792,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) nargs.dp = dp; nargs.geo = args->geo; nargs.firstblock = args->firstblock; - nargs.flist = args->flist; + nargs.dfops = args->dfops; nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; @@ -922,7 +922,7 @@ xfs_attr3_leaf_to_shortform( nargs.geo = args->geo; nargs.dp = dp; nargs.firstblock = args->firstblock; - nargs.flist = args->flist; + nargs.dfops = args->dfops; nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c index aabb516..d52f525 100644 --- a/fs/xfs/libxfs/xfs_attr_remote.c +++ b/fs/xfs/libxfs/xfs_attr_remote.c @@ -461,16 +461,16 @@ xfs_attr_rmtval_set( * extent and then crash then the block may not contain the * correct metadata after log recovery occurs. */ - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); nmap = 1; error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, - args->total, &map, &nmap, args->flist); + args->total, &map, &nmap, args->dfops); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } @@ -504,7 +504,7 @@ xfs_attr_rmtval_set( ASSERT(blkcnt > 0); - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); nmap = 1; error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, @@ -604,16 +604,16 @@ xfs_attr_rmtval_remove( blkcnt = args->rmtblkcnt; done = 0; while (!done) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, args->firstblock, - args->flist, &done); + args->dfops, &done); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, + error = xfs_defer_finish(&args->trans, args->dfops, args->dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 45ce7bd..85061a0 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -572,7 +572,7 @@ xfs_bmap_validate_ret( void xfs_bmap_add_free( struct xfs_mount *mp, /* mount point structure */ - struct xfs_defer_ops *flist, /* list of extents */ + struct xfs_defer_ops *dfops, /* list of extents */ xfs_fsblock_t bno, /* fs block number of extent */ xfs_filblks_t len) /* length of extent */ { @@ -596,7 +596,7 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; - xfs_defer_add(flist, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); } /* @@ -649,7 +649,7 @@ xfs_bmap_btree_to_extents( cblock = XFS_BUF_TO_BLOCK(cbp); if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) return error; - xfs_bmap_add_free(mp, cur->bc_private.b.flist, cbno, 1); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1); ip->i_d.di_nblocks--; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); @@ -672,7 +672,7 @@ xfs_bmap_extents_to_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first-block-allocated */ - struct xfs_defer_ops *flist, /* blocks freed in xaction */ + struct xfs_defer_ops *dfops, /* blocks freed in xaction */ xfs_btree_cur_t **curp, /* cursor returned to caller */ int wasdel, /* converting a delayed alloc */ int *logflagsp, /* inode logging flags */ @@ -721,7 +721,7 @@ xfs_bmap_extents_to_btree( */ cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0; /* * Convert to a btree with two levels, one record in root. @@ -734,7 +734,7 @@ xfs_bmap_extents_to_btree( if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); - } else if (flist->dop_low) { + } else if (dfops->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = *firstblock; } else { @@ -755,7 +755,7 @@ xfs_bmap_extents_to_btree( ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(*firstblock == NULLFSBLOCK || args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) || - (flist->dop_low && + (dfops->dop_low && args.agno > XFS_FSB_TO_AGNO(mp, *firstblock))); *firstblock = cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; @@ -940,7 +940,7 @@ xfs_bmap_add_attrfork_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - struct xfs_defer_ops *flist, /* blocks to free at commit */ + struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -953,7 +953,7 @@ xfs_bmap_add_attrfork_btree( *flags |= XFS_ILOG_DBROOT; else { cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK); - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.firstblock = *firstblock; if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat))) goto error0; @@ -983,7 +983,7 @@ xfs_bmap_add_attrfork_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - struct xfs_defer_ops *flist, /* blocks to free at commit */ + struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -992,7 +992,7 @@ xfs_bmap_add_attrfork_extents( if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip)) return 0; cur = NULL; - error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0, + error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops, &cur, 0, flags, XFS_DATA_FORK); if (cur) { cur->bc_private.b.allocated = 0; @@ -1018,7 +1018,7 @@ xfs_bmap_add_attrfork_local( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - struct xfs_defer_ops *flist, /* blocks to free at commit */ + struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_da_args_t dargs; /* args for dir/attr code */ @@ -1031,7 +1031,7 @@ xfs_bmap_add_attrfork_local( dargs.geo = ip->i_mount->m_dir_geo; dargs.dp = ip; dargs.firstblock = firstblock; - dargs.flist = flist; + dargs.dfops = dfops; dargs.total = dargs.geo->fsbcount; dargs.whichfork = XFS_DATA_FORK; dargs.trans = tp; @@ -1059,7 +1059,7 @@ xfs_bmap_add_attrfork( int rsvd) /* xact may use reserved blks */ { xfs_fsblock_t firstblock; /* 1st block/ag allocated */ - struct xfs_defer_ops flist; /* freed extent records */ + struct xfs_defer_ops dfops; /* freed extent records */ xfs_mount_t *mp; /* mount structure */ xfs_trans_t *tp; /* transaction pointer */ int blks; /* space reservation */ @@ -1125,18 +1125,18 @@ xfs_bmap_add_attrfork( ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); ip->i_afp->if_flags = XFS_IFEXTENTS; logflags = 0; - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); switch (ip->i_d.di_format) { case XFS_DINODE_FMT_LOCAL: - error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist, + error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &dfops, &logflags); break; case XFS_DINODE_FMT_EXTENTS: error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock, - &flist, &logflags); + &dfops, &logflags); break; case XFS_DINODE_FMT_BTREE: - error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist, + error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &dfops, &logflags); break; default: @@ -1165,7 +1165,7 @@ xfs_bmap_add_attrfork( xfs_log_sb(tp); } - error = xfs_defer_finish(&tp, &flist, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto bmap_cancel; error = xfs_trans_commit(tp); @@ -1173,7 +1173,7 @@ xfs_bmap_add_attrfork( return error; bmap_cancel: - xfs_defer_cancel(&flist); + xfs_defer_cancel(&dfops); trans_cancel: xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -1970,7 +1970,7 @@ xfs_bmap_add_extent_delay_real( if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, + bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) @@ -2054,7 +2054,7 @@ xfs_bmap_add_extent_delay_real( if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, 1, + bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) @@ -2123,7 +2123,7 @@ xfs_bmap_add_extent_delay_real( if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, + bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) @@ -2172,7 +2172,7 @@ xfs_bmap_add_extent_delay_real( ASSERT(bma->cur == NULL); error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, + bma->firstblock, bma->dfops, &bma->cur, da_old > 0, &tmp_logflags, whichfork); bma->logflags |= tmp_logflags; if (error) @@ -2214,7 +2214,7 @@ xfs_bmap_add_extent_unwritten_real( xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ - struct xfs_defer_ops *flist, /* list of extents to be freed */ + struct xfs_defer_ops *dfops, /* list of extents to be freed */ int *logflagsp) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -2707,7 +2707,7 @@ xfs_bmap_add_extent_unwritten_real( int tmp_logflags; /* partial log flag return val */ ASSERT(cur == NULL); - error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur, + error = xfs_bmap_extents_to_btree(tp, ip, first, dfops, &cur, 0, &tmp_logflags, XFS_DATA_FORK); *logflagsp |= tmp_logflags; if (error) @@ -3100,7 +3100,7 @@ xfs_bmap_add_extent_hole_real( ASSERT(bma->cur == NULL); error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, + bma->firstblock, bma->dfops, &bma->cur, 0, &tmp_logflags, whichfork); bma->logflags |= tmp_logflags; if (error) @@ -3675,7 +3675,7 @@ xfs_bmap_btalloc( error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; - } else if (ap->flist->dop_low) { + } else if (ap->dfops->dop_low) { if (xfs_inode_is_filestream(ap->ip)) args.type = XFS_ALLOCTYPE_FIRST_AG; else @@ -3708,7 +3708,7 @@ xfs_bmap_btalloc( * is >= the stripe unit and the allocation offset is * at the end of file. */ - if (!ap->flist->dop_low && ap->aeof) { + if (!ap->dfops->dop_low && ap->aeof) { if (!ap->offset) { args.alignment = stripe_align; atype = args.type; @@ -3801,7 +3801,7 @@ xfs_bmap_btalloc( args.minleft = 0; if ((error = xfs_alloc_vextent(&args))) return error; - ap->flist->dop_low = true; + ap->dfops->dop_low = true; } if (args.fsbno != NULLFSBLOCK) { /* @@ -3811,7 +3811,7 @@ xfs_bmap_btalloc( ASSERT(*ap->firstblock == NULLFSBLOCK || XFS_FSB_TO_AGNO(mp, *ap->firstblock) == XFS_FSB_TO_AGNO(mp, args.fsbno) || - (ap->flist->dop_low && + (ap->dfops->dop_low && XFS_FSB_TO_AGNO(mp, *ap->firstblock) < XFS_FSB_TO_AGNO(mp, args.fsbno))); @@ -3819,7 +3819,7 @@ xfs_bmap_btalloc( if (*ap->firstblock == NULLFSBLOCK) *ap->firstblock = args.fsbno; ASSERT(nullfb || fb_agno == args.agno || - (ap->flist->dop_low && fb_agno < args.agno)); + (ap->dfops->dop_low && fb_agno < args.agno)); ap->length = args.len; ap->ip->i_d.di_nblocks += args.len; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); @@ -4286,7 +4286,7 @@ xfs_bmapi_allocate( if (error) return error; - if (bma->flist->dop_low) + if (bma->dfops->dop_low) bma->minleft = 0; if (bma->cur) bma->cur->bc_private.b.firstblock = *bma->firstblock; @@ -4295,7 +4295,7 @@ xfs_bmapi_allocate( if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork); bma->cur->bc_private.b.firstblock = *bma->firstblock; - bma->cur->bc_private.b.flist = bma->flist; + bma->cur->bc_private.b.dfops = bma->dfops; } /* * Bump the number of extents we've allocated @@ -4376,7 +4376,7 @@ xfs_bmapi_convert_unwritten( bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp, bma->ip, whichfork); bma->cur->bc_private.b.firstblock = *bma->firstblock; - bma->cur->bc_private.b.flist = bma->flist; + bma->cur->bc_private.b.dfops = bma->dfops; } mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; @@ -4393,7 +4393,7 @@ xfs_bmapi_convert_unwritten( } error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx, - &bma->cur, mval, bma->firstblock, bma->flist, + &bma->cur, mval, bma->firstblock, bma->dfops, &tmp_logflags); /* * Log the inode core unconditionally in the unwritten extent conversion @@ -4447,7 +4447,7 @@ xfs_bmapi_write( xfs_extlen_t total, /* total blocks needed */ struct xfs_bmbt_irec *mval, /* output: map values */ int *nmap, /* i/o: mval size/count */ - struct xfs_defer_ops *flist) /* i/o: list extents to free */ + struct xfs_defer_ops *dfops) /* i/o: list extents to free */ { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; @@ -4537,7 +4537,7 @@ xfs_bmapi_write( bma.ip = ip; bma.total = total; bma.userdata = 0; - bma.flist = flist; + bma.dfops = dfops; bma.firstblock = firstblock; while (bno < end && n < *nmap) { @@ -4651,7 +4651,7 @@ error0: XFS_FSB_TO_AGNO(mp, *firstblock) == XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock) || - (flist->dop_low && + (dfops->dop_low && XFS_FSB_TO_AGNO(mp, *firstblock) < XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock))); @@ -4735,7 +4735,7 @@ xfs_bmap_del_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current transaction pointer */ xfs_extnum_t *idx, /* extent number to update/delete */ - struct xfs_defer_ops *flist, /* list of extents to be freed */ + struct xfs_defer_ops *dfops, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ @@ -5023,7 +5023,7 @@ xfs_bmap_del_extent( * If we need to, add to list of extents to delete. */ if (do_fx) - xfs_bmap_add_free(mp, flist, del->br_startblock, + xfs_bmap_add_free(mp, dfops, del->br_startblock, del->br_blockcount); /* * Adjust inode # blocks in the file. @@ -5064,7 +5064,7 @@ xfs_bunmapi( xfs_extnum_t nexts, /* number of extents max */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ - struct xfs_defer_ops *flist, /* i/o: list extents to free */ + struct xfs_defer_ops *dfops, /* i/o: list extents to free */ int *done) /* set if not done yet */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -5137,7 +5137,7 @@ xfs_bunmapi( ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE); cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; } else cur = NULL; @@ -5229,7 +5229,7 @@ xfs_bunmapi( } del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, ip, - &lastx, &cur, &del, firstblock, flist, + &lastx, &cur, &del, firstblock, dfops, &logflags); if (error) goto error0; @@ -5288,7 +5288,7 @@ xfs_bunmapi( lastx--; error = xfs_bmap_add_extent_unwritten_real(tp, ip, &lastx, &cur, &prev, - firstblock, flist, &logflags); + firstblock, dfops, &logflags); if (error) goto error0; goto nodelete; @@ -5297,7 +5297,7 @@ xfs_bunmapi( del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, ip, &lastx, &cur, &del, - firstblock, flist, &logflags); + firstblock, dfops, &logflags); if (error) goto error0; goto nodelete; @@ -5355,7 +5355,7 @@ xfs_bunmapi( } else if (cur) cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL; - error = xfs_bmap_del_extent(ip, tp, &lastx, flist, cur, &del, + error = xfs_bmap_del_extent(ip, tp, &lastx, dfops, cur, &del, &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) @@ -5389,7 +5389,7 @@ nodelete: */ if (xfs_bmap_needs_btree(ip, whichfork)) { ASSERT(cur == NULL); - error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, + error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops, &cur, 0, &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) @@ -5678,7 +5678,7 @@ xfs_bmap_shift_extents( int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *flist, + struct xfs_defer_ops *dfops, enum shift_direction direction, int num_exts) { @@ -5723,7 +5723,7 @@ xfs_bmap_shift_extents( if (ifp->if_flags & XFS_IFBROOT) { cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; } @@ -5832,7 +5832,7 @@ xfs_bmap_split_extent_at( struct xfs_inode *ip, xfs_fileoff_t split_fsb, xfs_fsblock_t *firstfsb, - struct xfs_defer_ops *free_list) + struct xfs_defer_ops *dfops) { int whichfork = XFS_DATA_FORK; struct xfs_btree_cur *cur = NULL; @@ -5894,7 +5894,7 @@ xfs_bmap_split_extent_at( if (ifp->if_flags & XFS_IFBROOT) { cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstfsb; - cur->bc_private.b.flist = free_list; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, @@ -5947,7 +5947,7 @@ xfs_bmap_split_extent_at( int tmp_logflags; /* partial log flag return val */ ASSERT(cur == NULL); - error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, free_list, + error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, dfops, &cur, 0, &tmp_logflags, whichfork); logflags |= tmp_logflags; } @@ -5971,7 +5971,7 @@ xfs_bmap_split_extent( { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t firstfsb; int error; @@ -5983,21 +5983,21 @@ xfs_bmap_split_extent( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(&free_list, &firstfsb); + xfs_defer_init(&dfops, &firstfsb); error = xfs_bmap_split_extent_at(tp, ip, split_fsb, - &firstfsb, &free_list); + &firstfsb, &dfops); if (error) goto out; - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out; return xfs_trans_commit(tp); out: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index e2a0425..8c5f530 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -32,7 +32,7 @@ extern kmem_zone_t *xfs_bmap_free_item_zone; */ struct xfs_bmalloca { xfs_fsblock_t *firstblock; /* i/o first block allocated */ - struct xfs_defer_ops *flist; /* bmap freelist */ + struct xfs_defer_ops *dfops; /* bmap freelist */ struct xfs_trans *tp; /* transaction pointer */ struct xfs_inode *ip; /* incore inode pointer */ struct xfs_bmbt_irec prev; /* extent before the new one */ @@ -164,7 +164,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); -void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *flist, +void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t bno, xfs_filblks_t len); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, @@ -186,18 +186,18 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_fsblock_t *firstblock, xfs_extlen_t total, struct xfs_bmbt_irec *mval, int *nmap, - struct xfs_defer_ops *flist); + struct xfs_defer_ops *dfops); int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *flist, int *done); + struct xfs_defer_ops *dfops, int *done); int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, xfs_extnum_t num); uint xfs_default_attroffset(struct xfs_inode *ip); int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *flist, enum shift_direction direction, + struct xfs_defer_ops *dfops, enum shift_direction direction, int num_exts); int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index fa5e3a5..18b5361 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -407,11 +407,11 @@ xfs_bmbt_dup_cursor( cur->bc_private.b.ip, cur->bc_private.b.whichfork); /* - * Copy the firstblock, flist, and flags values, + * Copy the firstblock, dfops, and flags values, * since init cursor doesn't get them. */ new->bc_private.b.firstblock = cur->bc_private.b.firstblock; - new->bc_private.b.flist = cur->bc_private.b.flist; + new->bc_private.b.dfops = cur->bc_private.b.dfops; new->bc_private.b.flags = cur->bc_private.b.flags; return new; @@ -424,7 +424,7 @@ xfs_bmbt_update_cursor( { ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) || (dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME)); - ASSERT(dst->bc_private.b.flist == src->bc_private.b.flist); + ASSERT(dst->bc_private.b.dfops == src->bc_private.b.dfops); dst->bc_private.b.allocated += src->bc_private.b.allocated; dst->bc_private.b.firstblock = src->bc_private.b.firstblock; @@ -463,7 +463,7 @@ xfs_bmbt_alloc_block( * block allocation here and corrupt the filesystem. */ args.minleft = args.tp->t_blk_res; - } else if (cur->bc_private.b.flist->dop_low) { + } else if (cur->bc_private.b.dfops->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; @@ -491,7 +491,7 @@ xfs_bmbt_alloc_block( error = xfs_alloc_vextent(&args); if (error) goto error0; - cur->bc_private.b.flist->dop_low = true; + cur->bc_private.b.dfops->dop_low = true; } if (args.fsbno == NULLFSBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); @@ -527,7 +527,7 @@ xfs_bmbt_free_block( struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); - xfs_bmap_add_free(mp, cur->bc_private.b.flist, fsbno, 1); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1); ip->i_d.di_nblocks--; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); @@ -789,7 +789,7 @@ xfs_bmbt_init_cursor( cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork); cur->bc_private.b.ip = ip; cur->bc_private.b.firstblock = NULLFSBLOCK; - cur->bc_private.b.flist = NULL; + cur->bc_private.b.dfops = NULL; cur->bc_private.b.allocated = 0; cur->bc_private.b.flags = 0; cur->bc_private.b.whichfork = whichfork; diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index ae714a8..7483cac 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -234,12 +234,12 @@ typedef struct xfs_btree_cur union { struct { /* needed for BNO, CNT, INO */ struct xfs_buf *agbp; /* agf/agi buffer pointer */ - struct xfs_defer_ops *flist; /* deferred updates */ + struct xfs_defer_ops *dfops; /* deferred updates */ xfs_agnumber_t agno; /* ag number */ } a; struct { /* needed for BMAP */ struct xfs_inode *ip; /* pointer to our inode */ - struct xfs_defer_ops *flist; /* deferred updates */ + struct xfs_defer_ops *dfops; /* deferred updates */ xfs_fsblock_t firstblock; /* 1st blk allocated */ int allocated; /* count of alloced */ short forksize; /* fork's inode space */ diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c index 097bf77..68594c7 100644 --- a/fs/xfs/libxfs/xfs_da_btree.c +++ b/fs/xfs/libxfs/xfs_da_btree.c @@ -2030,7 +2030,7 @@ xfs_da_grow_inode_int( error = xfs_bmapi_write(tp, dp, *bno, count, xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, args->firstblock, args->total, &map, &nmap, - args->flist); + args->dfops); if (error) return error; @@ -2053,7 +2053,7 @@ xfs_da_grow_inode_int( error = xfs_bmapi_write(tp, dp, b, c, xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, args->firstblock, args->total, - &mapp[mapi], &nmap, args->flist); + &mapp[mapi], &nmap, args->dfops); if (error) goto out_free_map; if (nmap < 1) @@ -2363,7 +2363,7 @@ xfs_da_shrink_inode( */ error = xfs_bunmapi(tp, dp, dead_blkno, count, xfs_bmapi_aflag(w), 0, args->firstblock, - args->flist, &done); + args->dfops, &done); if (error == -ENOSPC) { if (w != XFS_DATA_FORK) break; diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h index 249813a..98c75cb 100644 --- a/fs/xfs/libxfs/xfs_da_btree.h +++ b/fs/xfs/libxfs/xfs_da_btree.h @@ -70,7 +70,7 @@ typedef struct xfs_da_args { xfs_ino_t inumber; /* input/output inode number */ struct xfs_inode *dp; /* directory inode to manipulate */ xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */ - struct xfs_defer_ops *flist; /* ptr to freelist for bmap_finish */ + struct xfs_defer_ops *dfops; /* ptr to freelist for bmap_finish */ struct xfs_trans *trans; /* current trans (changes over time) */ xfs_extlen_t total; /* total blocks needed, for 1st bmap */ int whichfork; /* data or attribute fork */ diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c index 0523100..20a96dd 100644 --- a/fs/xfs/libxfs/xfs_dir2.c +++ b/fs/xfs/libxfs/xfs_dir2.c @@ -260,7 +260,7 @@ xfs_dir_createname( struct xfs_name *name, xfs_ino_t inum, /* new entry inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - struct xfs_defer_ops *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -287,7 +287,7 @@ xfs_dir_createname( args->inumber = inum; args->dp = dp; args->firstblock = first; - args->flist = flist; + args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; @@ -437,7 +437,7 @@ xfs_dir_removename( struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, /* bmap's firstblock */ - struct xfs_defer_ops *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -459,7 +459,7 @@ xfs_dir_removename( args->inumber = ino; args->dp = dp; args->firstblock = first; - args->flist = flist; + args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; @@ -499,7 +499,7 @@ xfs_dir_replace( struct xfs_name *name, /* name of entry to replace */ xfs_ino_t inum, /* new inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - struct xfs_defer_ops *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -524,7 +524,7 @@ xfs_dir_replace( args->inumber = inum; args->dp = dp; args->firstblock = first; - args->flist = flist; + args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; @@ -681,7 +681,7 @@ xfs_dir2_shrink_inode( /* Unmap the fsblock(s). */ error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, - args->firstblock, args->flist, &done); + args->firstblock, args->dfops, &done); if (error) { /* * ENOSPC actually can happen if we're in a removename with no diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h index 5737d85..a9bab0e 100644 --- a/fs/xfs/libxfs/xfs_dir2.h +++ b/fs/xfs/libxfs/xfs_dir2.h @@ -129,18 +129,18 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_defer_ops *flist, xfs_extlen_t tot); + struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t *inum, struct xfs_name *ci_name); extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, - struct xfs_defer_ops *flist, xfs_extlen_t tot); + struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_defer_ops *flist, xfs_extlen_t tot); + struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name); diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index f2e29a1..dbc3e35 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -1818,7 +1818,7 @@ xfs_difree_inode_chunk( struct xfs_mount *mp, xfs_agnumber_t agno, struct xfs_inobt_rec_incore *rec, - struct xfs_defer_ops *flist) + struct xfs_defer_ops *dfops) { xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); int startidx, endidx; @@ -1829,7 +1829,7 @@ xfs_difree_inode_chunk( if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ - xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, sagbno), + xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno), mp->m_ialloc_blks); return; } @@ -1873,7 +1873,7 @@ xfs_difree_inode_chunk( ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); - xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, agbno), + xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno), contigblk); /* reset range to current bit and carry on... */ @@ -1890,7 +1890,7 @@ xfs_difree_inobt( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agino_t agino, - struct xfs_defer_ops *flist, + struct xfs_defer_ops *dfops, struct xfs_icluster *xic, struct xfs_inobt_rec_incore *orec) { @@ -1977,7 +1977,7 @@ xfs_difree_inobt( goto error0; } - xfs_difree_inode_chunk(mp, agno, &rec, flist); + xfs_difree_inode_chunk(mp, agno, &rec, dfops); } else { xic->deleted = 0; @@ -2122,7 +2122,7 @@ int xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_defer_ops *flist, /* extents to free */ + struct xfs_defer_ops *dfops, /* extents to free */ struct xfs_icluster *xic) /* cluster info if deleted */ { /* REFERENCED */ @@ -2174,7 +2174,7 @@ xfs_difree( /* * Fix up the inode allocation btree. */ - error = xfs_difree_inobt(mp, tp, agbp, agino, flist, xic, &rec); + error = xfs_difree_inobt(mp, tp, agbp, agino, dfops, xic, &rec); if (error) goto error0; diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h index 2e06b67..0bb8966 100644 --- a/fs/xfs/libxfs/xfs_ialloc.h +++ b/fs/xfs/libxfs/xfs_ialloc.h @@ -95,7 +95,7 @@ int /* error */ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_defer_ops *flist, /* extents to free */ + struct xfs_defer_ops *dfops, /* extents to free */ struct xfs_icluster *ifree); /* cluster info if deleted */ /* diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 928dfa4..62d194e 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -685,7 +685,7 @@ xfs_bmap_punch_delalloc_range( xfs_bmbt_irec_t imap; int nimaps = 1; xfs_fsblock_t firstblock; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; /* * Map the range first and check that it is a delalloc extent @@ -716,18 +716,18 @@ xfs_bmap_punch_delalloc_range( WARN_ON(imap.br_blockcount == 0); /* - * Note: while we initialise the firstblock/flist pair, they + * Note: while we initialise the firstblock/dfops pair, they * should never be used because blocks should never be * allocated or freed for a delalloc extent and hence we need * don't cancel or finish them after the xfs_bunmapi() call. */ - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock, - &flist, &done); + &dfops, &done); if (error) break; - ASSERT(!xfs_defer_has_unfinished_work(&flist)); + ASSERT(!xfs_defer_has_unfinished_work(&dfops)); next_block: start_fsb++; remaining--; @@ -884,7 +884,7 @@ xfs_alloc_file_space( int rt; xfs_trans_t *tp; xfs_bmbt_irec_t imaps[1], *imapp; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; uint qblocks, resblks, resrtextents; int error; @@ -975,17 +975,17 @@ xfs_alloc_file_space( xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&free_list, &firstfsb); + xfs_defer_init(&dfops, &firstfsb); error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb, alloc_type, &firstfsb, - resblks, imapp, &nimaps, &free_list); + resblks, imapp, &nimaps, &dfops); if (error) goto error0; /* * Complete the transaction */ - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto error0; @@ -1008,7 +1008,7 @@ xfs_alloc_file_space( return error; error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag); error1: /* Just cancel transaction */ @@ -1122,7 +1122,7 @@ xfs_free_file_space( xfs_fileoff_t endoffset_fsb; int error; xfs_fsblock_t firstfsb; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_bmbt_irec_t imap; xfs_off_t ioffset; xfs_off_t iendoffset; @@ -1245,17 +1245,17 @@ xfs_free_file_space( /* * issue the bunmapi() call to free the blocks */ - xfs_defer_init(&free_list, &firstfsb); + xfs_defer_init(&dfops, &firstfsb); error = xfs_bunmapi(tp, ip, startoffset_fsb, endoffset_fsb - startoffset_fsb, - 0, 2, &firstfsb, &free_list, &done); + 0, 2, &firstfsb, &dfops, &done); if (error) goto error0; /* * complete the transaction */ - error = xfs_defer_finish(&tp, &free_list, ip); + error = xfs_defer_finish(&tp, &dfops, ip); if (error) goto error0; @@ -1267,7 +1267,7 @@ xfs_free_file_space( return error; error0: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); error1: xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -1333,7 +1333,7 @@ xfs_shift_file_space( struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; int error; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; xfs_fileoff_t stop_fsb; xfs_fileoff_t next_fsb; @@ -1411,19 +1411,19 @@ xfs_shift_file_space( xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); /* * We are using the write transaction in which max 2 bmbt * updates are allowed */ error = xfs_bmap_shift_extents(tp, ip, &next_fsb, shift_fsb, - &done, stop_fsb, &first_block, &free_list, + &done, stop_fsb, &first_block, &dfops, direction, XFS_BMAP_MAX_SHIFT_EXTENTS); if (error) goto out_bmap_cancel; - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out_bmap_cancel; @@ -1433,7 +1433,7 @@ xfs_shift_file_space( return error; out_bmap_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); return error; diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 764e1cc..8ca21b8 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -307,7 +307,7 @@ xfs_qm_dqalloc( xfs_buf_t **O_bpp) { xfs_fsblock_t firstblock; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; xfs_bmbt_irec_t map; int nmaps, error; xfs_buf_t *bp; @@ -320,7 +320,7 @@ xfs_qm_dqalloc( /* * Initialize the bmap freelist prior to calling bmapi code. */ - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); xfs_ilock(quotip, XFS_ILOCK_EXCL); /* * Return if this type of quotas is turned off while we didn't @@ -336,7 +336,7 @@ xfs_qm_dqalloc( error = xfs_bmapi_write(tp, quotip, offset_fsb, XFS_DQUOT_CLUSTER_SIZE_FSB, XFS_BMAPI_METADATA, &firstblock, XFS_QM_DQALLOC_SPACE_RES(mp), - &map, &nmaps, &flist); + &map, &nmaps, &dfops); if (error) goto error0; ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); @@ -382,7 +382,7 @@ xfs_qm_dqalloc( xfs_trans_bhold(tp, bp); - error = xfs_defer_finish(tpp, &flist, NULL); + error = xfs_defer_finish(tpp, &dfops, NULL); if (error) goto error1; @@ -398,7 +398,7 @@ xfs_qm_dqalloc( return 0; error1: - xfs_defer_cancel(&flist); + xfs_defer_cancel(&dfops); error0: xfs_iunlock(quotip, XFS_ILOCK_EXCL); diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 3e990fb..4a33a33 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -386,7 +386,7 @@ xfs_filestream_new_ag( } flags = (ap->userdata ? XFS_PICK_USERDATA : 0) | - (ap->flist->dop_low ? XFS_PICK_LOWSPACE : 0); + (ap->dfops->dop_low ? XFS_PICK_LOWSPACE : 0); err = xfs_filestream_pick_ag(pip, startag, agp, flags, minlen); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 3ce50da..e08eaea 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1123,7 +1123,7 @@ xfs_create( struct xfs_inode *ip = NULL; struct xfs_trans *tp = NULL; int error; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; bool unlock_dp_on_error = false; prid_t prid; @@ -1183,7 +1183,7 @@ xfs_create( XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT); unlock_dp_on_error = true; - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); /* * Reserve disk quota and the inode. @@ -1220,7 +1220,7 @@ xfs_create( unlock_dp_on_error = false; error = xfs_dir_createname(tp, dp, name, ip->i_ino, - &first_block, &free_list, resblks ? + &first_block, &dfops, resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); if (error) { ASSERT(error != -ENOSPC); @@ -1254,7 +1254,7 @@ xfs_create( */ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out_bmap_cancel; @@ -1270,7 +1270,7 @@ xfs_create( return 0; out_bmap_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); out_release_inode: @@ -1402,7 +1402,7 @@ xfs_link( xfs_mount_t *mp = tdp->i_mount; xfs_trans_t *tp; int error; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; int resblks; @@ -1453,7 +1453,7 @@ xfs_link( goto error_return; } - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); /* * Handle initial link state of O_TMPFILE inode @@ -1465,7 +1465,7 @@ xfs_link( } error = xfs_dir_createname(tp, tdp, target_name, sip->i_ino, - &first_block, &free_list, resblks); + &first_block, &dfops, resblks); if (error) goto error_return; xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); @@ -1483,9 +1483,9 @@ xfs_link( if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) { - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); goto error_return; } @@ -1527,7 +1527,7 @@ xfs_itruncate_extents( { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp = *tpp; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; xfs_fileoff_t first_unmap_block; xfs_fileoff_t last_block; @@ -1563,12 +1563,12 @@ xfs_itruncate_extents( ASSERT(first_unmap_block < last_block); unmap_len = last_block - first_unmap_block + 1; while (!done) { - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); error = xfs_bunmapi(tp, ip, first_unmap_block, unmap_len, xfs_bmapi_aflag(whichfork), XFS_ITRUNC_MAX_EXTENTS, - &first_block, &free_list, + &first_block, &dfops, &done); if (error) goto out_bmap_cancel; @@ -1577,7 +1577,7 @@ xfs_itruncate_extents( * Duplicate the transaction that has the permanent * reservation and commit the old transaction. */ - error = xfs_defer_finish(&tp, &free_list, ip); + error = xfs_defer_finish(&tp, &dfops, ip); if (error) goto out_bmap_cancel; @@ -1603,7 +1603,7 @@ out_bmap_cancel: * the transaction can be properly aborted. We just need to make sure * we're not holding any resources that we were not when we came in. */ - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); goto out; } @@ -1744,7 +1744,7 @@ STATIC int xfs_inactive_ifree( struct xfs_inode *ip) { - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; @@ -1781,8 +1781,8 @@ xfs_inactive_ifree( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&free_list, &first_block); - error = xfs_ifree(tp, ip, &free_list); + xfs_defer_init(&dfops, &first_block); + error = xfs_ifree(tp, ip, &dfops); if (error) { /* * If we fail to free the inode, shut down. The cancel @@ -1808,11 +1808,11 @@ xfs_inactive_ifree( * Just ignore errors at this point. There is nothing we can do except * to try to keep going. Make sure it's not a silent error. */ - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) { xfs_notice(mp, "%s: xfs_defer_finish returned error %d", __func__, error); - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); } error = xfs_trans_commit(tp); if (error) @@ -2368,7 +2368,7 @@ int xfs_ifree( xfs_trans_t *tp, xfs_inode_t *ip, - struct xfs_defer_ops *flist) + struct xfs_defer_ops *dfops) { int error; struct xfs_icluster xic = { 0 }; @@ -2387,7 +2387,7 @@ xfs_ifree( if (error) return error; - error = xfs_difree(tp, ip->i_ino, flist, &xic); + error = xfs_difree(tp, ip->i_ino, dfops, &xic); if (error) return error; @@ -2490,7 +2490,7 @@ xfs_remove( xfs_trans_t *tp = NULL; int is_dir = S_ISDIR(VFS_I(ip)->i_mode); int error = 0; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; uint resblks; @@ -2572,9 +2572,9 @@ xfs_remove( if (error) goto out_trans_cancel; - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); error = xfs_dir_removename(tp, dp, name, ip->i_ino, - &first_block, &free_list, resblks); + &first_block, &dfops, resblks); if (error) { ASSERT(error != -ENOENT); goto out_bmap_cancel; @@ -2588,7 +2588,7 @@ xfs_remove( if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out_bmap_cancel; @@ -2602,7 +2602,7 @@ xfs_remove( return 0; out_bmap_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); std_return: @@ -2663,7 +2663,7 @@ xfs_sort_for_rename( static int xfs_finish_rename( struct xfs_trans *tp, - struct xfs_defer_ops *free_list) + struct xfs_defer_ops *dfops) { int error; @@ -2674,9 +2674,9 @@ xfs_finish_rename( if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) xfs_trans_set_sync(tp); - error = xfs_defer_finish(&tp, free_list, NULL); + error = xfs_defer_finish(&tp, dfops, NULL); if (error) { - xfs_defer_cancel(free_list); + xfs_defer_cancel(dfops); xfs_trans_cancel(tp); return error; } @@ -2698,7 +2698,7 @@ xfs_cross_rename( struct xfs_inode *dp2, struct xfs_name *name2, struct xfs_inode *ip2, - struct xfs_defer_ops *free_list, + struct xfs_defer_ops *dfops, xfs_fsblock_t *first_block, int spaceres) { @@ -2710,14 +2710,14 @@ xfs_cross_rename( /* Swap inode number for dirent in first parent */ error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, - first_block, free_list, spaceres); + first_block, dfops, spaceres); if (error) goto out_trans_abort; /* Swap inode number for dirent in second parent */ error = xfs_dir_replace(tp, dp2, name2, ip1->i_ino, - first_block, free_list, spaceres); + first_block, dfops, spaceres); if (error) goto out_trans_abort; @@ -2732,7 +2732,7 @@ xfs_cross_rename( if (S_ISDIR(VFS_I(ip2)->i_mode)) { error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot, dp1->i_ino, first_block, - free_list, spaceres); + dfops, spaceres); if (error) goto out_trans_abort; @@ -2759,7 +2759,7 @@ xfs_cross_rename( if (S_ISDIR(VFS_I(ip1)->i_mode)) { error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot, dp2->i_ino, first_block, - free_list, spaceres); + dfops, spaceres); if (error) goto out_trans_abort; @@ -2798,10 +2798,10 @@ xfs_cross_rename( } xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE); - return xfs_finish_rename(tp, free_list); + return xfs_finish_rename(tp, dfops); out_trans_abort: - xfs_defer_cancel(free_list); + xfs_defer_cancel(dfops); xfs_trans_cancel(tp); return error; } @@ -2856,7 +2856,7 @@ xfs_rename( { struct xfs_mount *mp = src_dp->i_mount; struct xfs_trans *tp; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; struct xfs_inode *wip = NULL; /* whiteout inode */ struct xfs_inode *inodes[__XFS_SORT_INODES]; @@ -2945,13 +2945,13 @@ xfs_rename( goto out_trans_cancel; } - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); /* RENAME_EXCHANGE is unique from here on. */ if (flags & RENAME_EXCHANGE) return xfs_cross_rename(tp, src_dp, src_name, src_ip, target_dp, target_name, target_ip, - &free_list, &first_block, spaceres); + &dfops, &first_block, spaceres); /* * Set up the target. @@ -2973,7 +2973,7 @@ xfs_rename( */ error = xfs_dir_createname(tp, target_dp, target_name, src_ip->i_ino, &first_block, - &free_list, spaceres); + &dfops, spaceres); if (error) goto out_bmap_cancel; @@ -3013,7 +3013,7 @@ xfs_rename( */ error = xfs_dir_replace(tp, target_dp, target_name, src_ip->i_ino, - &first_block, &free_list, spaceres); + &first_block, &dfops, spaceres); if (error) goto out_bmap_cancel; @@ -3048,7 +3048,7 @@ xfs_rename( */ error = xfs_dir_replace(tp, src_ip, &xfs_name_dotdot, target_dp->i_ino, - &first_block, &free_list, spaceres); + &first_block, &dfops, spaceres); ASSERT(error != -EEXIST); if (error) goto out_bmap_cancel; @@ -3087,10 +3087,10 @@ xfs_rename( */ if (wip) { error = xfs_dir_replace(tp, src_dp, src_name, wip->i_ino, - &first_block, &free_list, spaceres); + &first_block, &dfops, spaceres); } else error = xfs_dir_removename(tp, src_dp, src_name, src_ip->i_ino, - &first_block, &free_list, spaceres); + &first_block, &dfops, spaceres); if (error) goto out_bmap_cancel; @@ -3125,13 +3125,13 @@ xfs_rename( if (new_parent) xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE); - error = xfs_finish_rename(tp, &free_list); + error = xfs_finish_rename(tp, &dfops); if (wip) IRELE(wip); return error; out_bmap_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); out_release_wip: diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index cb7abe84..61b61f51 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -128,7 +128,7 @@ xfs_iomap_write_direct( int quota_flag; int rt; xfs_trans_t *tp; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; uint qblocks, resblks, resrtextents; int error; int lockmode; @@ -231,18 +231,18 @@ xfs_iomap_write_direct( * From this point onwards we overwrite the imap pointer that the * caller gave to us. */ - xfs_defer_init(&free_list, &firstfsb); + xfs_defer_init(&dfops, &firstfsb); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, bmapi_flags, &firstfsb, resblks, imap, - &nimaps, &free_list); + &nimaps, &dfops); if (error) goto out_bmap_cancel; /* * Complete the transaction */ - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out_bmap_cancel; @@ -266,7 +266,7 @@ out_unlock: return error; out_bmap_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag); out_trans_cancel: xfs_trans_cancel(tp); @@ -685,7 +685,7 @@ xfs_iomap_write_allocate( xfs_fileoff_t offset_fsb, last_block; xfs_fileoff_t end_fsb, map_start_fsb; xfs_fsblock_t first_block; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_filblks_t count_fsb; xfs_trans_t *tp; int nimaps; @@ -727,7 +727,7 @@ xfs_iomap_write_allocate( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); /* * it is possible that the extents have changed since @@ -783,11 +783,11 @@ xfs_iomap_write_allocate( error = xfs_bmapi_write(tp, ip, map_start_fsb, count_fsb, 0, &first_block, nres, imap, &nimaps, - &free_list); + &dfops); if (error) goto trans_cancel; - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto trans_cancel; @@ -821,7 +821,7 @@ xfs_iomap_write_allocate( } trans_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); xfs_trans_cancel(tp); error0: xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -842,7 +842,7 @@ xfs_iomap_write_unwritten( int nimaps; xfs_trans_t *tp; xfs_bmbt_irec_t imap; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsize_t i_size; uint resblks; int error; @@ -886,11 +886,11 @@ xfs_iomap_write_unwritten( /* * Modify the unwritten extent state of the buffer. */ - xfs_defer_init(&free_list, &firstfsb); + xfs_defer_init(&dfops, &firstfsb); nimaps = 1; error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, XFS_BMAPI_CONVERT, &firstfsb, resblks, - &imap, &nimaps, &free_list); + &imap, &nimaps, &dfops); if (error) goto error_on_bmapi_transaction; @@ -909,7 +909,7 @@ xfs_iomap_write_unwritten( xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); } - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto error_on_bmapi_transaction; @@ -936,7 +936,7 @@ xfs_iomap_write_unwritten( return 0; error_on_bmapi_transaction: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); return error; diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index c761a6a..802bcc3 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -770,7 +770,7 @@ xfs_growfs_rt_alloc( xfs_daddr_t d; /* disk block address */ int error; /* error return value */ xfs_fsblock_t firstblock;/* first block allocated in xaction */ - struct xfs_defer_ops flist; /* list of freed blocks */ + struct xfs_defer_ops dfops; /* list of freed blocks */ xfs_fsblock_t fsbno; /* filesystem block for bno */ struct xfs_bmbt_irec map; /* block map output */ int nmap; /* number of block maps */ @@ -795,14 +795,14 @@ xfs_growfs_rt_alloc( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); /* * Allocate blocks to the bitmap file. */ nmap = 1; error = xfs_bmapi_write(tp, ip, oblocks, nblocks - oblocks, XFS_BMAPI_METADATA, &firstblock, - resblks, &map, &nmap, &flist); + resblks, &map, &nmap, &dfops); if (!error && nmap < 1) error = -ENOSPC; if (error) @@ -810,7 +810,7 @@ xfs_growfs_rt_alloc( /* * Free any blocks freed up in the transaction, then commit. */ - error = xfs_defer_finish(&tp, &flist, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out_bmap_cancel; error = xfs_trans_commit(tp); @@ -863,7 +863,7 @@ xfs_growfs_rt_alloc( return 0; out_bmap_cancel: - xfs_defer_cancel(&flist); + xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); return error; diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 3b005ec..58142ae 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c @@ -173,7 +173,7 @@ xfs_symlink( struct xfs_inode *ip = NULL; int error = 0; int pathlen; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t first_block; bool unlock_dp_on_error = false; xfs_fileoff_t first_fsb; @@ -270,7 +270,7 @@ xfs_symlink( * Initialize the bmap freelist prior to calling either * bmapi or the directory create code. */ - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); /* * Allocate an inode for the symlink. @@ -314,7 +314,7 @@ xfs_symlink( error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks, XFS_BMAPI_METADATA, &first_block, resblks, - mval, &nmaps, &free_list); + mval, &nmaps, &dfops); if (error) goto out_bmap_cancel; @@ -362,7 +362,7 @@ xfs_symlink( * Create the directory entry for the symlink. */ error = xfs_dir_createname(tp, dp, link_name, ip->i_ino, - &first_block, &free_list, resblks); + &first_block, &dfops, resblks); if (error) goto out_bmap_cancel; xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); @@ -377,7 +377,7 @@ xfs_symlink( xfs_trans_set_sync(tp); } - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out_bmap_cancel; @@ -393,7 +393,7 @@ xfs_symlink( return 0; out_bmap_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); out_trans_cancel: xfs_trans_cancel(tp); out_release_inode: @@ -427,7 +427,7 @@ xfs_inactive_symlink_rmt( int done; int error; xfs_fsblock_t first_block; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; int i; xfs_mount_t *mp; xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; @@ -466,7 +466,7 @@ xfs_inactive_symlink_rmt( * Find the block(s) so we can inval and unmap them. */ done = 0; - xfs_defer_init(&free_list, &first_block); + xfs_defer_init(&dfops, &first_block); nmaps = ARRAY_SIZE(mval); error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), mval, &nmaps, 0); @@ -486,17 +486,17 @@ xfs_inactive_symlink_rmt( xfs_trans_binval(tp, bp); } /* - * Unmap the dead block(s) to the free_list. + * Unmap the dead block(s) to the dfops. */ error = xfs_bunmapi(tp, ip, 0, size, 0, nmaps, - &first_block, &free_list, &done); + &first_block, &dfops, &done); if (error) goto error_bmap_cancel; ASSERT(done); /* * Commit the first transaction. This logs the EFI and the inode. */ - error = xfs_defer_finish(&tp, &free_list, ip); + error = xfs_defer_finish(&tp, &dfops, ip); if (error) goto error_bmap_cancel; /* @@ -526,7 +526,7 @@ xfs_inactive_symlink_rmt( return 0; error_bmap_cancel: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); error_trans_cancel: xfs_trans_cancel(tp); error_unlock: From darrick.wong@oracle.com Thu Jun 16 20:20:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 827847D20 for ; Thu, 16 Jun 2016 20:20:29 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 41F79304048 for ; Thu, 16 Jun 2016 18:20:29 -0700 (PDT) X-ASG-Debug-ID: 1466126426-04cb6c5425572c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id iEM2PFgt8uLm8Z1y (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:26 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1KOsK005981 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:24 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1KNVA015330 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:23 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1KLAC022840; Fri, 17 Jun 2016 01:20:22 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:21 -0700 Subject: [PATCH 023/119] xfs: introduce rmap btree definitions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 023/119] xfs: introduce rmap btree definitions To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:20:19 -0700 Message-ID: <146612641935.12839.2545862100454514832.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126426 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6489 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Add new per-ag rmap btree definitions to the per-ag structures. The rmap btree will sit in the empty slots on disk after the free space btrees, and hence form a part of the array of space management btrees. This requires the definition of the btree to be contiguous with the free space btrees. Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_alloc.c | 6 ++++++ fs/xfs/libxfs/xfs_btree.c | 4 ++-- fs/xfs/libxfs/xfs_btree.h | 3 +++ fs/xfs/libxfs/xfs_format.h | 22 +++++++++++++++++----- fs/xfs/libxfs/xfs_types.h | 4 ++-- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 56c8690..b61e9c6 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2272,6 +2272,10 @@ xfs_agf_verify( be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS) return false; + if (xfs_sb_version_hasrmapbt(&mp->m_sb) && + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS) + return false; + /* * during growfs operations, the perag is not fully initialised, * so we can't use it for any useful checking. growfs ensures we can't @@ -2403,6 +2407,8 @@ xfs_alloc_read_agf( be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]); pag->pagf_levels[XFS_BTNUM_CNTi] = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); + pag->pagf_levels[XFS_BTNUM_RMAPi] = + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); spin_lock_init(&pag->pagb_lock); pag->pagb_count = 0; #ifdef __KERNEL__ diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 5b3743a..624b572 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -44,9 +44,9 @@ kmem_zone_t *xfs_btree_cur_zone; * Btree magic numbers. */ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { - { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, + { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, XFS_FIBT_MAGIC }, - { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, + { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC, XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC } }; #define xfs_btree_magic(cur) \ diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 7483cac..202fdd3 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -63,6 +63,7 @@ union xfs_btree_rec { #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) +#define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi) /* * For logging record fields. @@ -95,6 +96,7 @@ do { \ case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ + case XFS_BTNUM_RMAP: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -115,6 +117,7 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ case XFS_BTNUM_FINO: \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ + case XFS_BTNUM_RMAP: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index ba528b3..8ca4a3d 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -455,6 +455,7 @@ xfs_sb_has_compat_feature( } #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ +#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL @@ -538,6 +539,12 @@ static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp) (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID); } +static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp) +{ + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && + (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT); +} + /* * end of superblock version macros */ @@ -598,10 +605,10 @@ xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino) #define XFS_AGI_GOOD_VERSION(v) ((v) == XFS_AGI_VERSION) /* - * Btree number 0 is bno, 1 is cnt. This value gives the size of the + * Btree number 0 is bno, 1 is cnt, 2 is rmap. This value gives the size of the * arrays below. */ -#define XFS_BTNUM_AGF ((int)XFS_BTNUM_CNTi + 1) +#define XFS_BTNUM_AGF ((int)XFS_BTNUM_RMAPi + 1) /* * The second word of agf_levels in the first a.g. overlaps the EFS @@ -618,12 +625,10 @@ typedef struct xfs_agf { __be32 agf_seqno; /* sequence # starting from 0 */ __be32 agf_length; /* size in blocks of a.g. */ /* - * Freespace information + * Freespace and rmap information */ __be32 agf_roots[XFS_BTNUM_AGF]; /* root blocks */ - __be32 agf_spare0; /* spare field */ __be32 agf_levels[XFS_BTNUM_AGF]; /* btree levels */ - __be32 agf_spare1; /* spare field */ __be32 agf_flfirst; /* first freelist block's index */ __be32 agf_fllast; /* last freelist block's index */ @@ -1307,6 +1312,13 @@ typedef __be32 xfs_inobt_ptr_t; #define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) /* + * Reverse mapping btree format definitions + * + * There is a btree for the reverse map per allocation group + */ +#define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ + +/* * The first data block of an AG depends on whether the filesystem was formatted * with the finobt feature. If so, account for the finobt reserved root btree * block. diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h index f0d145a..da87796 100644 --- a/fs/xfs/libxfs/xfs_types.h +++ b/fs/xfs/libxfs/xfs_types.h @@ -111,8 +111,8 @@ typedef enum { } xfs_lookup_t; typedef enum { - XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, - XFS_BTNUM_FINOi, XFS_BTNUM_MAX + XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi, + XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_MAX } xfs_btnum_t; struct xfs_name { From darrick.wong@oracle.com Thu Jun 16 20:20:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A1F527CA4 for ; Thu, 16 Jun 2016 20:20:33 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 73AE18F804B for ; Thu, 16 Jun 2016 18:20:33 -0700 (PDT) X-ASG-Debug-ID: 1466126431-04cbb01fec695a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id esIOSnVF9KtDVTMj (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:32 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1KTwe005993 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:29 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1KSGW004823 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:29 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1KSgm027278; Fri, 17 Jun 2016 01:20:28 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:28 -0700 Subject: [PATCH 024/119] xfs: add rmap btree stats infrastructure From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 024/119] xfs: add rmap btree stats infrastructure To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:20:26 -0700 Message-ID: <146612642642.12839.4422813555398236765.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126431 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2993 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner The rmap btree will require the same stats as all the other generic btrees, so add al the code for that now. Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_btree.h | 5 +++-- fs/xfs/xfs_stats.c | 1 + fs/xfs/xfs_stats.h | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 202fdd3..a29067c 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -96,7 +96,7 @@ do { \ case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ - case XFS_BTNUM_RMAP: break; \ + case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -117,7 +117,8 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ case XFS_BTNUM_FINO: \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ - case XFS_BTNUM_RMAP: break; \ + case XFS_BTNUM_RMAP: \ + __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c index 8686df6..f04f547 100644 --- a/fs/xfs/xfs_stats.c +++ b/fs/xfs/xfs_stats.c @@ -61,6 +61,7 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf) { "bmbt2", XFSSTAT_END_BMBT_V2 }, { "ibt2", XFSSTAT_END_IBT_V2 }, { "fibt2", XFSSTAT_END_FIBT_V2 }, + { "rmapbt", XFSSTAT_END_RMAP_V2 }, /* we print both series of quota information together */ { "qm", XFSSTAT_END_QM }, }; diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h index 483b0ef..657865f 100644 --- a/fs/xfs/xfs_stats.h +++ b/fs/xfs/xfs_stats.h @@ -197,7 +197,23 @@ struct xfsstats { __uint32_t xs_fibt_2_alloc; __uint32_t xs_fibt_2_free; __uint32_t xs_fibt_2_moves; -#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_FIBT_V2+6) +#define XFSSTAT_END_RMAP_V2 (XFSSTAT_END_FIBT_V2+15) + __uint32_t xs_rmap_2_lookup; + __uint32_t xs_rmap_2_compare; + __uint32_t xs_rmap_2_insrec; + __uint32_t xs_rmap_2_delrec; + __uint32_t xs_rmap_2_newroot; + __uint32_t xs_rmap_2_killroot; + __uint32_t xs_rmap_2_increment; + __uint32_t xs_rmap_2_decrement; + __uint32_t xs_rmap_2_lshift; + __uint32_t xs_rmap_2_rshift; + __uint32_t xs_rmap_2_split; + __uint32_t xs_rmap_2_join; + __uint32_t xs_rmap_2_alloc; + __uint32_t xs_rmap_2_free; + __uint32_t xs_rmap_2_moves; +#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_RMAP_V2+6) __uint32_t xs_qm_dqreclaims; __uint32_t xs_qm_dqreclaim_misses; __uint32_t xs_qm_dquot_dups; From darrick.wong@oracle.com Thu Jun 16 20:20:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3A1707CB5 for ; Thu, 16 Jun 2016 20:20:43 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id BA8DFAC001 for ; Thu, 16 Jun 2016 18:20:42 -0700 (PDT) X-ASG-Debug-ID: 1466126440-04bdf01e10958b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Spc4CUiB9qiIBhz0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:40 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1KbOU025286 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:20:38 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Kb3J008517 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:37 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1KY9n006462; Fri, 17 Jun 2016 01:20:35 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:34 -0700 Subject: [PATCH 025/119] xfs: rmap btree add more reserved blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 025/119] xfs: rmap btree add more reserved blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:20:32 -0700 Message-ID: <146612643276.12839.2224272649304333643.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126440 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4997 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner XFS reserves a small amount of space in each AG for the minimum number of free blocks needed for operation. Adding the rmap btree increases the number of reserved blocks, but it also increases the complexity of the calculation as the free inode btree is optional (like the rmbt). Rather than calculate the prealloc blocks every time we need to check it, add a function to calculate it at mount time and store it in the struct xfs_mount, and convert the XFS_PREALLOC_BLOCKS macro just to use the xfs-mount variable directly. Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_alloc.c | 11 +++++++++++ fs/xfs/libxfs/xfs_alloc.h | 2 ++ fs/xfs/libxfs/xfs_format.h | 9 +-------- fs/xfs/xfs_fsops.c | 6 +++--- fs/xfs/xfs_mount.c | 2 ++ fs/xfs/xfs_mount.h | 1 + 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index b61e9c6..fb00042 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -50,6 +50,17 @@ STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); +xfs_extlen_t +xfs_prealloc_blocks( + struct xfs_mount *mp) +{ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + return XFS_RMAP_BLOCK(mp) + 1; + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + return XFS_FIBT_BLOCK(mp) + 1; + return XFS_IBT_BLOCK(mp) + 1; +} + /* * Lookup the record equal to [bno, len] in the btree given by cur. */ diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index cf268b2..20b54aa 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -232,4 +232,6 @@ int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **agbp); +xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); + #endif /* __XFS_ALLOC_H__ */ diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 8ca4a3d..b5b0901 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1318,18 +1318,11 @@ typedef __be32 xfs_inobt_ptr_t; */ #define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ -/* - * The first data block of an AG depends on whether the filesystem was formatted - * with the finobt feature. If so, account for the finobt reserved root btree - * block. - */ -#define XFS_PREALLOC_BLOCKS(mp) \ +#define XFS_RMAP_BLOCK(mp) \ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ XFS_FIBT_BLOCK(mp) + 1 : \ XFS_IBT_BLOCK(mp) + 1) - - /* * BMAP Btree format definitions * diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 064fce1..62162d4 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -243,7 +243,7 @@ xfs_growfs_data_private( agf->agf_flfirst = cpu_to_be32(1); agf->agf_fllast = 0; agf->agf_flcount = 0; - tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp); + tmpsize = agsize - mp->m_ag_prealloc_blocks; agf->agf_freeblks = cpu_to_be32(tmpsize); agf->agf_longest = cpu_to_be32(tmpsize); if (xfs_sb_version_hascrc(&mp->m_sb)) @@ -340,7 +340,7 @@ xfs_growfs_data_private( agno, 0); arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); - arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); + arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks); arec->ar_blockcount = cpu_to_be32( agsize - be32_to_cpu(arec->ar_startblock)); @@ -369,7 +369,7 @@ xfs_growfs_data_private( agno, 0); arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); - arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); + arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks); arec->ar_blockcount = cpu_to_be32( agsize - be32_to_cpu(arec->ar_startblock)); nfree += be32_to_cpu(arec->ar_blockcount); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index bf63682..b4153f0 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -231,6 +231,8 @@ xfs_initialize_perag( if (maxagi) *maxagi = index; + + mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp); return 0; out_unwind: diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index c1b798c..0537b1f 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -119,6 +119,7 @@ typedef struct xfs_mount { uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_in_maxlevels; /* max inobt btree levels. */ + xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ struct radix_tree_root m_perag_tree; /* per-ag accounting info */ spinlock_t m_perag_lock; /* lock for m_perag_tree */ struct mutex m_growlock; /* growfs mutex */ From darrick.wong@oracle.com Thu Jun 16 20:20:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3BC537D42 for ; Thu, 16 Jun 2016 20:20:49 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9C635AC002 for ; Thu, 16 Jun 2016 18:20:48 -0700 (PDT) X-ASG-Debug-ID: 1466126444-04cb6c542557310001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id zBbQTc1de3lirVFE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:44 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Kgtt025349 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:42 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Kg9B015748 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:42 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Kfa6018673; Fri, 17 Jun 2016 01:20:41 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:40 -0700 Subject: [PATCH 026/119] xfs: add owner field to extent allocation and freeing From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 026/119] xfs: add owner field to extent allocation and freeing To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:20:39 -0700 Message-ID: <146612643914.12839.17925699349002137545.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126444 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 18919 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines For the rmap btree to work, we have to feed the extent owner information to the the allocation and freeing functions. This information is what will end up in the rmap btree that tracks allocated extents. While we technically don't need the owner information when freeing extents, passing it allows us to validate that the extent we are removing from the rmap btree actually belonged to the owner we expected it to belong to. We also define a special set of owner values for internal metadata that would otherwise have no owner. This allows us to tell the difference between metadata owned by different per-ag btrees, as well as static fs metadata (e.g. AG headers) and internal journal blocks. There are also a couple of special cases we need to take care of - during EFI recovery, we don't actually know who the original owner was, so we need to pass a wildcard to indicate that we aren't checking the owner for validity. We also need special handling in growfs, as we "free" the space in the last AG when extending it, but because it's new space it has no actual owner... While touching the xfs_bmap_add_free() function, re-order the parameters to put the struct xfs_mount first. Extend the owner field to include both the owner type and some sort of index within the owner. The index field will be used to support reverse mappings when reflink is enabled. This is based upon a patch originally from Dave Chinner. It has been extended to add more owner information with the intent of helping recovery operations when things go wrong (e.g. offset of user data block in a file). v2: When we're freeing extents from an EFI, we don't have the owner information available (rmap updates have their own redo items). xfs_free_extent therefore doesn't need to do an rmap update, but the log replay code doesn't signal this correctly. Fix it so that it does. [dchinner: de-shout the xfs_rmap_*_owner helpers] [darrick: minor style fixes suggested by Christoph Hellwig] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_alloc.c | 11 +++++- fs/xfs/libxfs/xfs_alloc.h | 4 ++ fs/xfs/libxfs/xfs_bmap.c | 17 ++++++++-- fs/xfs/libxfs/xfs_bmap.h | 4 ++ fs/xfs/libxfs/xfs_bmap_btree.c | 6 +++- fs/xfs/libxfs/xfs_format.h | 65 ++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_ialloc.c | 7 +++- fs/xfs/libxfs/xfs_ialloc_btree.c | 7 ++++ fs/xfs/xfs_defer_item.c | 3 +- fs/xfs/xfs_fsops.c | 16 +++++++-- fs/xfs/xfs_log_recover.c | 5 ++- fs/xfs/xfs_trans.h | 2 + fs/xfs/xfs_trans_extfree.c | 5 ++- 13 files changed, 131 insertions(+), 21 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index fb00042..eed26f9 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -1596,6 +1596,7 @@ xfs_free_ag_extent( xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t bno, /* starting block number */ xfs_extlen_t len, /* length of extent */ + struct xfs_owner_info *oinfo, /* extent owner */ int isfl) /* set if is freelist blocks - no sb acctg */ { xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ @@ -2005,13 +2006,15 @@ xfs_alloc_fix_freelist( * back on the free list? Maybe we should only do this when space is * getting low or the AGFL is more than half full? */ + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); while (pag->pagf_flcount > need) { struct xfs_buf *bp; error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); if (error) goto out_agbp_relse; - error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1); + error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, + &targs.oinfo, 1); if (error) goto out_agbp_relse; bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); @@ -2021,6 +2024,7 @@ xfs_alloc_fix_freelist( memset(&targs, 0, sizeof(targs)); targs.tp = tp; targs.mp = mp; + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); targs.agbp = agbp; targs.agno = args->agno; targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; @@ -2711,7 +2715,8 @@ int /* error */ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ - xfs_extlen_t len) /* length of extent */ + xfs_extlen_t len, /* length of extent */ + struct xfs_owner_info *oinfo) /* extent owner */ { struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *agbp; @@ -2739,7 +2744,7 @@ xfs_free_extent( agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), err); - error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0); + error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, 0); if (error) goto err; diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 20b54aa..0721a48 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -123,6 +123,7 @@ typedef struct xfs_alloc_arg { char isfl; /* set if is freelist blocks - !acctg */ char userdata; /* mask defining userdata treatment */ xfs_fsblock_t firstblock; /* io first block allocated */ + struct xfs_owner_info oinfo; /* owner of blocks being allocated */ } xfs_alloc_arg_t; /* @@ -210,7 +211,8 @@ int /* error */ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ - xfs_extlen_t len); /* length of extent */ + xfs_extlen_t len, /* length of extent */ + struct xfs_owner_info *oinfo); /* extent owner */ int /* error */ xfs_alloc_lookup_ge( diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 3a6d3e3..2c28f2a 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -574,7 +574,8 @@ xfs_bmap_add_free( struct xfs_mount *mp, /* mount point structure */ struct xfs_defer_ops *dfops, /* list of extents */ xfs_fsblock_t bno, /* fs block number of extent */ - xfs_filblks_t len) /* length of extent */ + xfs_filblks_t len, /* length of extent */ + struct xfs_owner_info *oinfo) /* extent owner */ { struct xfs_bmap_free_item *new; /* new element */ #ifdef DEBUG @@ -593,9 +594,14 @@ xfs_bmap_add_free( ASSERT(agbno + len <= mp->m_sb.sb_agblocks); #endif ASSERT(xfs_bmap_free_item_zone != NULL); + new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; + if (oinfo) + memcpy(&new->xbfi_oinfo, oinfo, sizeof(struct xfs_owner_info)); + else + memset(&new->xbfi_oinfo, 0, sizeof(struct xfs_owner_info)); trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0, XFS_FSB_TO_AGBNO(mp, bno), len); xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); @@ -628,6 +634,7 @@ xfs_bmap_btree_to_extents( xfs_mount_t *mp; /* mount point structure */ __be64 *pp; /* ptr to block address */ struct xfs_btree_block *rblock;/* root btree block */ + struct xfs_owner_info oinfo; mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); @@ -651,7 +658,8 @@ xfs_bmap_btree_to_extents( cblock = XFS_BUF_TO_BLOCK(cbp); if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) return error; - xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1); + xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); @@ -732,6 +740,7 @@ xfs_bmap_extents_to_btree( memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = mp; + xfs_rmap_ino_bmbt_owner(&args.oinfo, ip->i_ino, whichfork); args.firstblock = *firstblock; if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; @@ -878,6 +887,7 @@ xfs_bmap_local_to_extents( memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = ip->i_mount; + xfs_rmap_ino_owner(&args.oinfo, ip->i_ino, whichfork, 0); args.firstblock = *firstblock; /* * Allocate a block. We know we need only one, since the @@ -4839,6 +4849,7 @@ xfs_bmap_del_extent( nblks = 0; do_fx = 0; } + /* * Set flag value to use in switch statement. * Left-contig is 2, right-contig is 1. @@ -5026,7 +5037,7 @@ xfs_bmap_del_extent( */ if (do_fx) xfs_bmap_add_free(mp, dfops, del->br_startblock, - del->br_blockcount); + del->br_blockcount, NULL); /* * Adjust inode # blocks in the file. */ diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 8c5f530..862ea464 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -67,6 +67,7 @@ struct xfs_bmap_free_item xfs_fsblock_t xbfi_startblock;/* starting fs block number */ xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */ struct list_head xbfi_list; + struct xfs_owner_info xbfi_oinfo; /* extent owner */ }; #define XFS_BMAP_MAX_NMAP 4 @@ -165,7 +166,8 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - xfs_fsblock_t bno, xfs_filblks_t len); + xfs_fsblock_t bno, xfs_filblks_t len, + struct xfs_owner_info *oinfo); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 18b5361..3e68f9a 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -447,6 +447,8 @@ xfs_bmbt_alloc_block( args.mp = cur->bc_mp; args.fsbno = cur->bc_private.b.firstblock; args.firstblock = args.fsbno; + xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_private.b.ip->i_ino, + cur->bc_private.b.whichfork); if (args.fsbno == NULLFSBLOCK) { args.fsbno = be64_to_cpu(start->l); @@ -526,8 +528,10 @@ xfs_bmbt_free_block( struct xfs_inode *ip = cur->bc_private.b.ip; struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); + struct xfs_owner_info oinfo; - xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1); + xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index b5b0901..97f354f 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1318,6 +1318,71 @@ typedef __be32 xfs_inobt_ptr_t; */ #define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ +/* + * Ownership info for an extent. This is used to create reverse-mapping + * entries. + */ +#define XFS_OWNER_INFO_ATTR_FORK (1 << 0) +#define XFS_OWNER_INFO_BMBT_BLOCK (1 << 1) +struct xfs_owner_info { + uint64_t oi_owner; + xfs_fileoff_t oi_offset; + unsigned int oi_flags; +}; + +static inline void +xfs_rmap_ag_owner( + struct xfs_owner_info *oi, + uint64_t owner) +{ + oi->oi_owner = owner; + oi->oi_offset = 0; + oi->oi_flags = 0; +} + +static inline void +xfs_rmap_ino_bmbt_owner( + struct xfs_owner_info *oi, + xfs_ino_t ino, + int whichfork) +{ + oi->oi_owner = ino; + oi->oi_offset = 0; + oi->oi_flags = XFS_OWNER_INFO_BMBT_BLOCK; + if (whichfork == XFS_ATTR_FORK) + oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; +} + +static inline void +xfs_rmap_ino_owner( + struct xfs_owner_info *oi, + xfs_ino_t ino, + int whichfork, + xfs_fileoff_t offset) +{ + oi->oi_owner = ino; + oi->oi_offset = offset; + oi->oi_flags = 0; + if (whichfork == XFS_ATTR_FORK) + oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; +} + +/* + * Special owner types. + * + * Seeing as we only support up to 8EB, we have the upper bit of the owner field + * to tell us we have a special owner value. We use these for static metadata + * allocated at mkfs/growfs time, as well as for freespace management metadata. + */ +#define XFS_RMAP_OWN_NULL (-1ULL) /* No owner, for growfs */ +#define XFS_RMAP_OWN_UNKNOWN (-2ULL) /* Unknown owner, for EFI recovery */ +#define XFS_RMAP_OWN_FS (-3ULL) /* static fs metadata */ +#define XFS_RMAP_OWN_LOG (-4ULL) /* static fs metadata */ +#define XFS_RMAP_OWN_AG (-5ULL) /* AG freespace btree blocks */ +#define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */ +#define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ +#define XFS_RMAP_OWN_MIN (-8ULL) /* guard */ + #define XFS_RMAP_BLOCK(mp) \ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ XFS_FIBT_BLOCK(mp) + 1 : \ diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index dbc3e35..1982561 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -615,6 +615,7 @@ xfs_ialloc_ag_alloc( args.tp = tp; args.mp = tp->t_mountp; args.fsbno = NULLFSBLOCK; + xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INODES); #ifdef DEBUG /* randomly do sparse inode allocations */ @@ -1825,12 +1826,14 @@ xfs_difree_inode_chunk( int nextbit; xfs_agblock_t agbno; int contigblk; + struct xfs_owner_info oinfo; DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS); + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno), - mp->m_ialloc_blks); + mp->m_ialloc_blks, &oinfo); return; } @@ -1874,7 +1877,7 @@ xfs_difree_inode_chunk( ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno), - contigblk); + contigblk, &oinfo); /* reset range to current bit and carry on... */ startidx = endidx = nextbit; diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index 88da2ad..f9ea86b 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c @@ -96,6 +96,7 @@ xfs_inobt_alloc_block( memset(&args, 0, sizeof(args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; + xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INOBT); args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); args.minlen = 1; args.maxlen = 1; @@ -125,8 +126,12 @@ xfs_inobt_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { + struct xfs_owner_info oinfo; + + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT); return xfs_free_extent(cur->bc_tp, - XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1); + XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1, + &oinfo); } STATIC int diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c index 127a54e..1c2d556 100644 --- a/fs/xfs/xfs_defer_item.c +++ b/fs/xfs/xfs_defer_item.c @@ -99,7 +99,8 @@ xfs_bmap_free_finish_item( free = container_of(item, struct xfs_bmap_free_item, xbfi_list); error = xfs_trans_free_extent(tp, done_item, free->xbfi_startblock, - free->xbfi_blockcount); + free->xbfi_blockcount, + &free->xbfi_oinfo); kmem_free(free); return error; } diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 62162d4..d60bb97 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -436,6 +436,8 @@ xfs_growfs_data_private( * There are new blocks in the old last a.g. */ if (new) { + struct xfs_owner_info oinfo; + /* * Change the agi length. */ @@ -463,14 +465,20 @@ xfs_growfs_data_private( be32_to_cpu(agi->agi_length)); xfs_alloc_log_agf(tp, bp, XFS_AGF_LENGTH); + /* * Free the new space. + * + * XFS_RMAP_OWN_NULL is used here to tell the rmap btree that + * this doesn't actually exist in the rmap btree. */ - error = xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, agno, - be32_to_cpu(agf->agf_length) - new), new); - if (error) { + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_NULL); + error = xfs_free_extent(tp, + XFS_AGB_TO_FSB(mp, agno, + be32_to_cpu(agf->agf_length) - new), + new, &oinfo); + if (error) goto error0; - } } /* diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 080b54b..0c41bd2 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4180,6 +4180,7 @@ xlog_recover_process_efi( int error = 0; xfs_extent_t *extp; xfs_fsblock_t startblock_fsb; + struct xfs_owner_info oinfo; ASSERT(!test_bit(XFS_EFI_RECOVERED, &efip->efi_flags)); @@ -4211,10 +4212,12 @@ xlog_recover_process_efi( return error; efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); + oinfo.oi_owner = 0; for (i = 0; i < efip->efi_format.efi_nextents; i++) { extp = &(efip->efi_format.efi_extents[i]); error = xfs_trans_free_extent(tp, efdp, extp->ext_start, - extp->ext_len); + extp->ext_len, + &oinfo); if (error) goto abort_error; diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 9a462e8..f8d363f 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -219,7 +219,7 @@ struct xfs_efd_log_item *xfs_trans_get_efd(xfs_trans_t *, uint); int xfs_trans_free_extent(struct xfs_trans *, struct xfs_efd_log_item *, xfs_fsblock_t, - xfs_extlen_t); + xfs_extlen_t, struct xfs_owner_info *); int xfs_trans_commit(struct xfs_trans *); int __xfs_trans_roll(struct xfs_trans **, struct xfs_inode *, int *); int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index a96ae54..d1b8833 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c @@ -118,13 +118,14 @@ xfs_trans_free_extent( struct xfs_trans *tp, struct xfs_efd_log_item *efdp, xfs_fsblock_t start_block, - xfs_extlen_t ext_len) + xfs_extlen_t ext_len, + struct xfs_owner_info *oinfo) { uint next_extent; struct xfs_extent *extp; int error; - error = xfs_free_extent(tp, start_block, ext_len); + error = xfs_free_extent(tp, start_block, ext_len, oinfo); /* * Mark the transaction dirty, even on error. This ensures the From darrick.wong@oracle.com Thu Jun 16 20:20:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8F5B67D5C for ; Thu, 16 Jun 2016 20:20:55 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1C134AC003 for ; Thu, 16 Jun 2016 18:20:54 -0700 (PDT) X-ASG-Debug-ID: 1466126452-04bdf01e15958d0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id eesnPiZZvpbABIrW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:53 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1KoGu006281 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:20:50 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Konc008783 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:50 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1KlNR006558; Fri, 17 Jun 2016 01:20:48 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:47 -0700 Subject: [PATCH 027/119] xfs: introduce rmap extent operation stubs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 027/119] xfs: introduce rmap extent operation stubs To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:20:45 -0700 Message-ID: <146612644563.12839.4763599111875645301.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126453 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8887 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Add the stubs into the extent allocation and freeing paths that the rmap btree implementation will hook into. While doing this, add the trace points that will be used to track rmap btree extent manipulations. [darrick.wong@oracle.com: Extend the stubs to take full owner info.] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_alloc.c | 18 ++++++++ fs/xfs/libxfs/xfs_rmap.c | 90 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 30 +++++++++++++ fs/xfs/xfs_trace.h | 47 +++++++++++++++++++++ 5 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/libxfs/xfs_rmap.c create mode 100644 fs/xfs/libxfs/xfs_rmap_btree.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index ad46a2d..06dd760 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -52,6 +52,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_inode_fork.o \ xfs_inode_buf.o \ xfs_log_rlimit.o \ + xfs_rmap.o \ xfs_sb.o \ xfs_symlink_remote.o \ xfs_trans_resv.o \ diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index eed26f9..570ca17 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -27,6 +27,7 @@ #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" +#include "xfs_rmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_extent_busy.h" @@ -648,6 +649,14 @@ xfs_alloc_ag_vextent( ASSERT(!args->wasfromfl || !args->isfl); ASSERT(args->agbno % args->alignment == 0); + /* if not file data, insert new block into the reverse map btree */ + if (args->oinfo.oi_owner) { + error = xfs_rmap_alloc(args->tp, args->agbp, args->agno, + args->agbno, args->len, &args->oinfo); + if (error) + return error; + } + if (!args->wasfromfl) { error = xfs_alloc_update_counters(args->tp, args->pag, args->agbp, @@ -1614,12 +1623,19 @@ xfs_free_ag_extent( xfs_extlen_t nlen; /* new length of freespace */ xfs_perag_t *pag; /* per allocation group data */ + bno_cur = cnt_cur = NULL; mp = tp->t_mountp; + + if (oinfo->oi_owner) { + error = xfs_rmap_free(tp, agbp, agno, bno, len, oinfo); + if (error) + goto error0; + } + /* * Allocate and initialize a cursor for the by-block btree. */ bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO); - cnt_cur = NULL; /* * Look for a neighboring block on the left (lower block numbers) * that is contiguous with this space. diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c new file mode 100644 index 0000000..d1fd471 --- /dev/null +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -0,0 +1,90 @@ + +/* + * Copyright (c) 2014 Red Hat, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_btree.h" +#include "xfs_trans.h" +#include "xfs_alloc.h" +#include "xfs_rmap_btree.h" +#include "xfs_trans_space.h" +#include "xfs_trace.h" +#include "xfs_error.h" +#include "xfs_extent_busy.h" + +int +xfs_rmap_free( + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = tp->t_mountp; + int error = 0; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + trace_xfs_rmap_free_extent(mp, agno, bno, len, false, oinfo); + if (1) + goto out_error; + trace_xfs_rmap_free_extent_done(mp, agno, bno, len, false, oinfo); + return 0; + +out_error: + trace_xfs_rmap_free_extent_error(mp, agno, bno, len, false, oinfo); + return error; +} + +int +xfs_rmap_alloc( + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = tp->t_mountp; + int error = 0; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + trace_xfs_rmap_alloc_extent(mp, agno, bno, len, false, oinfo); + if (1) + goto out_error; + trace_xfs_rmap_alloc_extent_done(mp, agno, bno, len, false, oinfo); + return 0; + +out_error: + trace_xfs_rmap_alloc_extent_error(mp, agno, bno, len, false, oinfo); + return error; +} diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h new file mode 100644 index 0000000..a3b8f90 --- /dev/null +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __XFS_RMAP_BTREE_H__ +#define __XFS_RMAP_BTREE_H__ + +struct xfs_buf; + +int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + struct xfs_owner_info *oinfo); +int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + struct xfs_owner_info *oinfo); + +#endif /* __XFS_RMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 777a89c..4872fbd 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2421,6 +2421,53 @@ DEFINE_MAP_EXTENT_DEFERRED_EVENT(xfs_defer_map_extent); DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_defer); DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_deferred); +/* rmap tracepoints */ +DECLARE_EVENT_CLASS(xfs_rmap_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, + struct xfs_owner_info *oinfo), + TP_ARGS(mp, agno, agbno, len, unwritten, oinfo), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, agbno) + __field(xfs_extlen_t, len) + __field(uint64_t, owner) + __field(uint64_t, offset) + __field(unsigned long, flags) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->agbno = agbno; + __entry->len = len; + __entry->owner = oinfo->oi_owner; + __entry->offset = oinfo->oi_offset; + __entry->flags = oinfo->oi_flags; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%lx", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->agbno, + __entry->len, + __entry->owner, + __entry->offset, + __entry->flags) +); +#define DEFINE_RMAP_EVENT(name) \ +DEFINE_EVENT(xfs_rmap_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + xfs_agblock_t agbno, xfs_extlen_t len, bool unwritten, \ + struct xfs_owner_info *oinfo), \ + TP_ARGS(mp, agno, agbno, len, unwritten, oinfo)) + +DEFINE_RMAP_EVENT(xfs_rmap_free_extent); +DEFINE_RMAP_EVENT(xfs_rmap_free_extent_done); +DEFINE_RMAP_EVENT(xfs_rmap_free_extent_error); +DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent); +DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_done); +DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_error); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:21:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E651C7D58 for ; Thu, 16 Jun 2016 20:21:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5F8F1AC002 for ; Thu, 16 Jun 2016 18:21:01 -0700 (PDT) X-ASG-Debug-ID: 1466126457-04cbb01fec695c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id SNVyi3ptusUceH6e (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:20:57 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1KtYC025469 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:55 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Kt5r016027 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:20:55 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Ks5U018751; Fri, 17 Jun 2016 01:20:54 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:20:53 -0700 Subject: [PATCH 028/119] xfs: define the on-disk rmap btree format From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 028/119] xfs: define the on-disk rmap btree format To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:20:52 -0700 Message-ID: <146612645206.12839.17008642336898856662.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126457 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19200 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Now we have all the surrounding call infrastructure in place, we can start filling out the rmap btree implementation. Start with the on-disk btree format; add everything needed to read, write and manipulate rmap btree blocks. This prepares the way for adding the btree operations implementation. [darrick: record owner and offset info in rmap btree] [darrick: fork, bmbt and unwritten state in rmap btree] [darrick: flags are a separate field in xfs_rmap_irec] [darrick: calculate maxlevels separately] [darrick: move the 'unwritten' bit into unused parts of rm_offset] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_btree.c | 3 + fs/xfs/libxfs/xfs_btree.h | 18 ++-- fs/xfs/libxfs/xfs_format.h | 140 +++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.c | 180 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 32 +++++++ fs/xfs/libxfs/xfs_sb.c | 6 + fs/xfs/libxfs/xfs_shared.h | 2 fs/xfs/xfs_mount.c | 2 fs/xfs/xfs_mount.h | 3 + fs/xfs/xfs_ondisk.h | 3 + fs/xfs/xfs_trace.h | 2 12 files changed, 384 insertions(+), 8 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_rmap_btree.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 06dd760..2de8c20 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -53,6 +53,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_inode_buf.o \ xfs_log_rlimit.o \ xfs_rmap.o \ + xfs_rmap_btree.o \ xfs_sb.o \ xfs_symlink_remote.o \ xfs_trans_resv.o \ diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 624b572..4b90419 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -1210,6 +1210,9 @@ xfs_btree_set_refs( case XFS_BTNUM_BMAP: xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF); break; + case XFS_BTNUM_RMAP: + xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF); + break; default: ASSERT(0); } diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index a29067c..90ea2a7 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -38,17 +38,19 @@ union xfs_btree_ptr { }; union xfs_btree_key { - xfs_bmbt_key_t bmbt; - xfs_bmdr_key_t bmbr; /* bmbt root block */ - xfs_alloc_key_t alloc; - xfs_inobt_key_t inobt; + struct xfs_bmbt_key bmbt; + xfs_bmdr_key_t bmbr; /* bmbt root block */ + xfs_alloc_key_t alloc; + struct xfs_inobt_key inobt; + struct xfs_rmap_key rmap; }; union xfs_btree_rec { - xfs_bmbt_rec_t bmbt; - xfs_bmdr_rec_t bmbr; /* bmbt root block */ - xfs_alloc_rec_t alloc; - xfs_inobt_rec_t inobt; + struct xfs_bmbt_rec bmbt; + xfs_bmdr_rec_t bmbr; /* bmbt root block */ + struct xfs_alloc_rec alloc; + struct xfs_inobt_rec inobt; + struct xfs_rmap_rec rmap; }; /* diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 97f354f..6efc7a3 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1383,11 +1383,151 @@ xfs_rmap_ino_owner( #define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ #define XFS_RMAP_OWN_MIN (-8ULL) /* guard */ +#define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63))) + +/* + * Data record structure + */ +struct xfs_rmap_rec { + __be32 rm_startblock; /* extent start block */ + __be32 rm_blockcount; /* extent length */ + __be64 rm_owner; /* extent owner */ + __be64 rm_offset; /* offset within the owner */ +}; + +/* + * rmap btree record + * rm_offset:63 is the attribute fork flag + * rm_offset:62 is the bmbt block flag + * rm_offset:61 is the unwritten extent flag (same as l0:63 in bmbt) + * rm_offset:54-60 aren't used and should be zero + * rm_offset:0-53 is the block offset within the inode + */ +#define XFS_RMAP_OFF_ATTR_FORK ((__uint64_t)1ULL << 63) +#define XFS_RMAP_OFF_BMBT_BLOCK ((__uint64_t)1ULL << 62) +#define XFS_RMAP_OFF_UNWRITTEN ((__uint64_t)1ULL << 61) + +#define XFS_RMAP_LEN_MAX ((__uint32_t)~0U) +#define XFS_RMAP_OFF_FLAGS (XFS_RMAP_OFF_ATTR_FORK | \ + XFS_RMAP_OFF_BMBT_BLOCK | \ + XFS_RMAP_OFF_UNWRITTEN) +#define XFS_RMAP_OFF_MASK ((__uint64_t)0x3FFFFFFFFFFFFFULL) + +#define XFS_RMAP_OFF(off) ((off) & XFS_RMAP_OFF_MASK) + +#define XFS_RMAP_IS_BMBT_BLOCK(off) (!!((off) & XFS_RMAP_OFF_BMBT_BLOCK)) +#define XFS_RMAP_IS_ATTR_FORK(off) (!!((off) & XFS_RMAP_OFF_ATTR_FORK)) +#define XFS_RMAP_IS_UNWRITTEN(len) (!!((off) & XFS_RMAP_OFF_UNWRITTEN)) + +#define RMAPBT_STARTBLOCK_BITLEN 32 +#define RMAPBT_BLOCKCOUNT_BITLEN 32 +#define RMAPBT_OWNER_BITLEN 64 +#define RMAPBT_ATTRFLAG_BITLEN 1 +#define RMAPBT_BMBTFLAG_BITLEN 1 +#define RMAPBT_EXNTFLAG_BITLEN 1 +#define RMAPBT_UNUSED_OFFSET_BITLEN 7 +#define RMAPBT_OFFSET_BITLEN 54 + +#define XFS_RMAP_ATTR_FORK (1 << 0) +#define XFS_RMAP_BMBT_BLOCK (1 << 1) +#define XFS_RMAP_UNWRITTEN (1 << 2) +#define XFS_RMAP_KEY_FLAGS (XFS_RMAP_ATTR_FORK | \ + XFS_RMAP_BMBT_BLOCK) +#define XFS_RMAP_REC_FLAGS (XFS_RMAP_UNWRITTEN) +struct xfs_rmap_irec { + xfs_agblock_t rm_startblock; /* extent start block */ + xfs_extlen_t rm_blockcount; /* extent length */ + __uint64_t rm_owner; /* extent owner */ + __uint64_t rm_offset; /* offset within the owner */ + unsigned int rm_flags; /* state flags */ +}; + +static inline __u64 +xfs_rmap_irec_offset_pack( + const struct xfs_rmap_irec *irec) +{ + __u64 x; + + x = XFS_RMAP_OFF(irec->rm_offset); + if (irec->rm_flags & XFS_RMAP_ATTR_FORK) + x |= XFS_RMAP_OFF_ATTR_FORK; + if (irec->rm_flags & XFS_RMAP_BMBT_BLOCK) + x |= XFS_RMAP_OFF_BMBT_BLOCK; + if (irec->rm_flags & XFS_RMAP_UNWRITTEN) + x |= XFS_RMAP_OFF_UNWRITTEN; + return x; +} + +static inline int +xfs_rmap_irec_offset_unpack( + __u64 offset, + struct xfs_rmap_irec *irec) +{ + if (offset & ~(XFS_RMAP_OFF_MASK | XFS_RMAP_OFF_FLAGS)) + return -EFSCORRUPTED; + irec->rm_offset = XFS_RMAP_OFF(offset); + if (offset & XFS_RMAP_OFF_ATTR_FORK) + irec->rm_flags |= XFS_RMAP_ATTR_FORK; + if (offset & XFS_RMAP_OFF_BMBT_BLOCK) + irec->rm_flags |= XFS_RMAP_BMBT_BLOCK; + if (offset & XFS_RMAP_OFF_UNWRITTEN) + irec->rm_flags |= XFS_RMAP_UNWRITTEN; + return 0; +} + +/* + * Key structure + * + * We don't use the length for lookups + */ +struct xfs_rmap_key { + __be32 rm_startblock; /* extent start block */ + __be64 rm_owner; /* extent owner */ + __be64 rm_offset; /* offset within the owner */ +} __attribute__((packed)); + +/* btree pointer type */ +typedef __be32 xfs_rmap_ptr_t; + #define XFS_RMAP_BLOCK(mp) \ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ XFS_FIBT_BLOCK(mp) + 1 : \ XFS_IBT_BLOCK(mp) + 1) +static inline void +xfs_owner_info_unpack( + struct xfs_owner_info *oinfo, + uint64_t *owner, + uint64_t *offset, + unsigned int *flags) +{ + unsigned int r = 0; + + *owner = oinfo->oi_owner; + *offset = oinfo->oi_offset; + if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK) + r |= XFS_RMAP_ATTR_FORK; + if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK) + r |= XFS_RMAP_BMBT_BLOCK; + *flags = r; +} + +static inline void +xfs_owner_info_pack( + struct xfs_owner_info *oinfo, + uint64_t owner, + uint64_t offset, + unsigned int flags) +{ + oinfo->oi_owner = owner; + oinfo->oi_offset = XFS_RMAP_OFF(offset); + oinfo->oi_flags = 0; + if (flags & XFS_RMAP_ATTR_FORK) + oinfo->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; + if (flags & XFS_RMAP_BMBT_BLOCK) + oinfo->oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; +} + /* * BMAP Btree format definitions * diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c new file mode 100644 index 0000000..7a35c78 --- /dev/null +++ b/fs/xfs/libxfs/xfs_rmap_btree.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_inode.h" +#include "xfs_trans.h" +#include "xfs_alloc.h" +#include "xfs_btree.h" +#include "xfs_rmap_btree.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" +#include "xfs_error.h" +#include "xfs_extent_busy.h" + +static struct xfs_btree_cur * +xfs_rmapbt_dup_cursor( + struct xfs_btree_cur *cur) +{ + return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp, + cur->bc_private.a.agbp, cur->bc_private.a.agno); +} + +static bool +xfs_rmapbt_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); + struct xfs_perag *pag = bp->b_pag; + unsigned int level; + + /* + * magic number and level verification + * + * During growfs operations, we can't verify the exact level or owner as + * the perag is not fully initialised and hence not attached to the + * buffer. In this case, check against the maximum tree depth. + * + * Similarly, during log recovery we will have a perag structure + * attached, but the agf information will not yet have been initialised + * from the on disk AGF. Again, we can only check against maximum limits + * in this case. + */ + if (block->bb_magic != cpu_to_be32(XFS_RMAP_CRC_MAGIC)) + return false; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return false; + if (!xfs_btree_sblock_v5hdr_verify(bp)) + return false; + + level = be16_to_cpu(block->bb_level); + if (pag && pag->pagf_init) { + if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi]) + return false; + } else if (level >= mp->m_rmap_maxlevels) + return false; + + return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]); +} + +static void +xfs_rmapbt_read_verify( + struct xfs_buf *bp) +{ + if (!xfs_btree_sblock_verify_crc(bp)) + xfs_buf_ioerror(bp, -EFSBADCRC); + else if (!xfs_rmapbt_verify(bp)) + xfs_buf_ioerror(bp, -EFSCORRUPTED); + + if (bp->b_error) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_verifier_error(bp); + } +} + +static void +xfs_rmapbt_write_verify( + struct xfs_buf *bp) +{ + if (!xfs_rmapbt_verify(bp)) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_buf_ioerror(bp, -EFSCORRUPTED); + xfs_verifier_error(bp); + return; + } + xfs_btree_sblock_calc_crc(bp); + +} + +const struct xfs_buf_ops xfs_rmapbt_buf_ops = { + .name = "xfs_rmapbt", + .verify_read = xfs_rmapbt_read_verify, + .verify_write = xfs_rmapbt_write_verify, +}; + +static const struct xfs_btree_ops xfs_rmapbt_ops = { + .rec_len = sizeof(struct xfs_rmap_rec), + .key_len = sizeof(struct xfs_rmap_key), + + .dup_cursor = xfs_rmapbt_dup_cursor, + .buf_ops = &xfs_rmapbt_buf_ops, +}; + +/* + * Allocate a new allocation btree cursor. + */ +struct xfs_btree_cur * +xfs_rmapbt_init_cursor( + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + struct xfs_btree_cur *cur; + + cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); + cur->bc_tp = tp; + cur->bc_mp = mp; + cur->bc_btnum = XFS_BTNUM_RMAP; + cur->bc_flags = XFS_BTREE_CRC_BLOCKS; + cur->bc_blocklog = mp->m_sb.sb_blocklog; + cur->bc_ops = &xfs_rmapbt_ops; + cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); + + cur->bc_private.a.agbp = agbp; + cur->bc_private.a.agno = agno; + + return cur; +} + +/* + * Calculate number of records in an rmap btree block. + */ +int +xfs_rmapbt_maxrecs( + struct xfs_mount *mp, + int blocklen, + int leaf) +{ + blocklen -= XFS_RMAP_BLOCK_LEN; + + if (leaf) + return blocklen / sizeof(struct xfs_rmap_rec); + return blocklen / + (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); +} + +/* Compute the maximum height of an rmap btree. */ +void +xfs_rmapbt_compute_maxlevels( + struct xfs_mount *mp) +{ + mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, + mp->m_rmap_mnr, mp->m_sb.sb_agblocks); +} diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index a3b8f90..462767f 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -19,6 +19,38 @@ #define __XFS_RMAP_BTREE_H__ struct xfs_buf; +struct xfs_btree_cur; +struct xfs_mount; + +/* rmaps only exist on crc enabled filesystems */ +#define XFS_RMAP_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN + +/* + * Record, key, and pointer address macros for btree blocks. + * + * (note that some of these may appear unused, but they are used in userspace) + */ +#define XFS_RMAP_REC_ADDR(block, index) \ + ((struct xfs_rmap_rec *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + (((index) - 1) * sizeof(struct xfs_rmap_rec)))) + +#define XFS_RMAP_KEY_ADDR(block, index) \ + ((struct xfs_rmap_key *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + ((index) - 1) * sizeof(struct xfs_rmap_key))) + +#define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \ + ((xfs_rmap_ptr_t *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + (maxrecs) * sizeof(struct xfs_rmap_key) + \ + ((index) - 1) * sizeof(xfs_rmap_ptr_t))) + +struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, + struct xfs_trans *tp, struct xfs_buf *bp, + xfs_agnumber_t agno); +int xfs_rmapbt_maxrecs(struct xfs_mount *mp, int blocklen, int leaf); +extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp); int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index a544686..f86226b 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -37,6 +37,7 @@ #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_log.h" +#include "xfs_rmap_btree.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. @@ -734,6 +735,11 @@ xfs_sb_mount_common( mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2; mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2; + mp->m_rmap_mxr[0] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 1); + mp->m_rmap_mxr[1] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 0); + mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2; + mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2; + mp->m_bsize = XFS_FSB_TO_BB(mp, 1); mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK, sbp->sb_inopblock); diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 16002b5..0c5b30b 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -38,6 +38,7 @@ extern const struct xfs_buf_ops xfs_agi_buf_ops; extern const struct xfs_buf_ops xfs_agf_buf_ops; extern const struct xfs_buf_ops xfs_agfl_buf_ops; extern const struct xfs_buf_ops xfs_allocbt_buf_ops; +extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; extern const struct xfs_buf_ops xfs_bmbt_buf_ops; @@ -116,6 +117,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *); #define XFS_INO_BTREE_REF 3 #define XFS_ALLOC_BTREE_REF 2 #define XFS_BMAP_BTREE_REF 2 +#define XFS_RMAP_BTREE_REF 2 #define XFS_DIR_BTREE_REF 2 #define XFS_INO_REF 2 #define XFS_ATTR_BTREE_REF 1 diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index b4153f0..8af1c88 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -42,6 +42,7 @@ #include "xfs_trace.h" #include "xfs_icache.h" #include "xfs_sysfs.h" +#include "xfs_rmap_btree.h" static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -680,6 +681,7 @@ xfs_mountfs( xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); xfs_ialloc_compute_maxlevels(mp); + xfs_rmapbt_compute_maxlevels(mp); xfs_set_maxicount(mp); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 0537b1f..0ed0f29 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -116,9 +116,12 @@ typedef struct xfs_mount { uint m_bmap_dmnr[2]; /* min bmap btree records */ uint m_inobt_mxr[2]; /* max inobt btree records */ uint m_inobt_mnr[2]; /* min inobt btree records */ + uint m_rmap_mxr[2]; /* max rmap btree records */ + uint m_rmap_mnr[2]; /* min rmap btree records */ uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_in_maxlevels; /* max inobt btree levels. */ + uint m_rmap_maxlevels; /* max rmap btree levels */ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ struct radix_tree_root m_perag_tree; /* per-ag accounting info */ spinlock_t m_perag_lock; /* lock for m_perag_tree */ diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 0272301..48d544f 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -47,11 +47,14 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16); + XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_key, 20); + XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_rec, 24); XFS_CHECK_STRUCT_SIZE(struct xfs_timestamp, 8); XFS_CHECK_STRUCT_SIZE(xfs_alloc_key_t, 8); XFS_CHECK_STRUCT_SIZE(xfs_alloc_ptr_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_alloc_rec_t, 8); XFS_CHECK_STRUCT_SIZE(xfs_inobt_ptr_t, 4); + XFS_CHECK_STRUCT_SIZE(xfs_rmap_ptr_t, 4); /* dir/attr trees */ XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr, 80); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 4872fbd..b4ee9c8 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2444,6 +2444,8 @@ DECLARE_EVENT_CLASS(xfs_rmap_class, __entry->owner = oinfo->oi_owner; __entry->offset = oinfo->oi_offset; __entry->flags = oinfo->oi_flags; + if (unwritten) + __entry->flags |= XFS_RMAP_UNWRITTEN; ), TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%lx", MAJOR(__entry->dev), MINOR(__entry->dev), From darrick.wong@oracle.com Thu Jun 16 20:21:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5A9017D6A for ; Thu, 16 Jun 2016 20:21:06 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0DB18304039 for ; Thu, 16 Jun 2016 18:21:05 -0700 (PDT) X-ASG-Debug-ID: 1466126463-04bdf01e13958f0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 5m3vGcvh0CeBvpLB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1L1fq025514 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:21:01 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1L0s6009177 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:21:00 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1L038027488; Fri, 17 Jun 2016 01:21:00 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:00 -0700 Subject: [PATCH 029/119] xfs: add rmap btree growfs support From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 029/119] xfs: add rmap btree growfs support To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:20:58 -0700 Message-ID: <146612645852.12839.9272042349680595884.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126464 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3722 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Now we can read and write rmap btree blocks, we can add support to the growfs code to initialise new rmap btree blocks. [darrick.wong@oracle.com: fill out the rmap offset fields] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/xfs_fsops.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index d60bb97..8a85e49 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -33,6 +33,7 @@ #include "xfs_btree.h" #include "xfs_alloc_btree.h" #include "xfs_alloc.h" +#include "xfs_rmap_btree.h" #include "xfs_ialloc.h" #include "xfs_fsops.h" #include "xfs_itable.h" @@ -240,6 +241,12 @@ xfs_growfs_data_private( agf->agf_roots[XFS_BTNUM_CNTi] = cpu_to_be32(XFS_CNT_BLOCK(mp)); agf->agf_levels[XFS_BTNUM_BNOi] = cpu_to_be32(1); agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + agf->agf_roots[XFS_BTNUM_RMAPi] = + cpu_to_be32(XFS_RMAP_BLOCK(mp)); + agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1); + } + agf->agf_flfirst = cpu_to_be32(1); agf->agf_fllast = 0; agf->agf_flcount = 0; @@ -379,6 +386,72 @@ xfs_growfs_data_private( if (error) goto error0; + /* RMAP btree root block */ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + struct xfs_rmap_rec *rrec; + struct xfs_btree_block *block; + + bp = xfs_growfs_get_hdr_buf(mp, + XFS_AGB_TO_DADDR(mp, agno, XFS_RMAP_BLOCK(mp)), + BTOBB(mp->m_sb.sb_blocksize), 0, + &xfs_rmapbt_buf_ops); + if (!bp) { + error = -ENOMEM; + goto error0; + } + + xfs_btree_init_block(mp, bp, XFS_RMAP_CRC_MAGIC, 0, 0, + agno, XFS_BTREE_CRC_BLOCKS); + block = XFS_BUF_TO_BLOCK(bp); + + + /* + * mark the AG header regions as static metadata The BNO + * btree block is the first block after the headers, so + * it's location defines the size of region the static + * metadata consumes. + * + * Note: unlike mkfs, we never have to account for log + * space when growing the data regions + */ + rrec = XFS_RMAP_REC_ADDR(block, 1); + rrec->rm_startblock = 0; + rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp)); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + /* account freespace btree root blocks */ + rrec = XFS_RMAP_REC_ADDR(block, 2); + rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp)); + rrec->rm_blockcount = cpu_to_be32(2); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + /* account inode btree root blocks */ + rrec = XFS_RMAP_REC_ADDR(block, 3); + rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp)); + rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) - + XFS_IBT_BLOCK(mp)); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + /* account for rmap btree root */ + rrec = XFS_RMAP_REC_ADDR(block, 4); + rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp)); + rrec->rm_blockcount = cpu_to_be32(1); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + } + /* * INO btree root block */ From darrick.wong@oracle.com Thu Jun 16 20:21:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9173B7CD1 for ; Thu, 16 Jun 2016 20:21:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0B048AC004 for ; Thu, 16 Jun 2016 18:21:12 -0700 (PDT) X-ASG-Debug-ID: 1466126470-04cb6c542757370001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id it9cx7bUrswDPPCU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:11 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1L8EN006691 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:08 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1L7ab012394 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:08 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1L61g019135; Fri, 17 Jun 2016 01:21:07 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:06 -0700 Subject: [PATCH 030/119] xfs: rmap btree transaction reservations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 030/119] xfs: rmap btree transaction reservations To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:21:04 -0700 Message-ID: <146612646482.12839.12293815646683700594.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126470 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8432 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines The rmap btrees will use the AGFL as the block allocation source, so we need to ensure that the transaction reservations reflect the fact this tree is modified by allocation and freeing. Hence we need to extend all the extent allocation/free reservations used in transactions to handle this. Note that this also gets rid of the unused XFS_ALLOCFREE_LOG_RES macro, as we now do buffer reservations based on the number of buffers logged via xfs_calc_buf_res(). Hence we only need the buffer count calculation now. [darrick: use rmap_maxlevels when calculating log block resv] Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_trans_resv.c | 58 ++++++++++++++++++++++++++++------------ fs/xfs/libxfs/xfs_trans_resv.h | 10 ------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index 4c7eb9d..301ef2f 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -64,6 +64,30 @@ xfs_calc_buf_res( } /* + * Per-extent log reservation for the btree changes involved in freeing or + * allocating an extent. In classic XFS there were two trees that will be + * modified (bnobt + cntbt). With rmap enabled, there are three trees + * (rmapbt). The number of blocks reserved is based on the formula: + * + * num trees * ((2 blocks/level * max depth) - 1) + * + * Keep in mind that max depth is calculated separately for each type of tree. + */ +static uint +xfs_allocfree_log_count( + struct xfs_mount *mp, + uint num_ops) +{ + uint blocks; + + blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1); + + return blocks; +} + +/* * Logging inodes is really tricksy. They are logged in memory format, * which means that what we write into the log doesn't directly translate into * the amount of space they use on disk. @@ -126,7 +150,7 @@ xfs_calc_inode_res( */ STATIC uint xfs_calc_finobt_res( - struct xfs_mount *mp, + struct xfs_mount *mp, int alloc, int modify) { @@ -137,7 +161,7 @@ xfs_calc_finobt_res( res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)); if (alloc) - res += xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + res += xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); if (modify) res += (uint)XFS_FSB_TO_B(mp, 1); @@ -188,10 +212,10 @@ xfs_calc_write_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } @@ -217,10 +241,10 @@ xfs_calc_itruncate_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(5, 0) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(2 + mp->m_ialloc_blks + mp->m_in_maxlevels, 0))); @@ -247,7 +271,7 @@ xfs_calc_rename_reservation( xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 3), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 3), XFS_FSB_TO_B(mp, 1)))); } @@ -286,7 +310,7 @@ xfs_calc_link_reservation( xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)))); } @@ -324,7 +348,7 @@ xfs_calc_remove_reservation( xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } @@ -371,7 +395,7 @@ xfs_calc_create_resv_alloc( mp->m_sb.sb_sectsize + xfs_calc_buf_res(mp->m_ialloc_blks, XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -399,7 +423,7 @@ xfs_calc_icreate_resv_alloc( return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + mp->m_sb.sb_sectsize + xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_finobt_res(mp, 0, 0); } @@ -483,7 +507,7 @@ xfs_calc_ifree_reservation( xfs_calc_buf_res(1, 0) + xfs_calc_buf_res(2 + mp->m_ialloc_blks + mp->m_in_maxlevels, 0) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_finobt_res(mp, 0, 1); } @@ -513,7 +537,7 @@ xfs_calc_growdata_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -535,7 +559,7 @@ xfs_calc_growrtalloc_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), XFS_FSB_TO_B(mp, 1)) + xfs_calc_inode_res(mp, 1) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -611,7 +635,7 @@ xfs_calc_addafork_reservation( xfs_calc_buf_res(1, mp->m_dir_geo->blksize) + xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1, XFS_FSB_TO_B(mp, 1)) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -634,7 +658,7 @@ xfs_calc_attrinval_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), XFS_FSB_TO_B(mp, 1)))); } @@ -701,7 +725,7 @@ xfs_calc_attrrm_reservation( XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)), (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h index 7978150..0eb46ed 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.h +++ b/fs/xfs/libxfs/xfs_trans_resv.h @@ -68,16 +68,6 @@ struct xfs_trans_resv { #define M_RES(mp) (&(mp)->m_resv) /* - * Per-extent log reservation for the allocation btree changes - * involved in freeing or allocating an extent. - * 2 trees * (2 blocks/level * max depth - 1) * block size - */ -#define XFS_ALLOCFREE_LOG_RES(mp,nx) \ - ((nx) * (2 * XFS_FSB_TO_B((mp), 2 * (mp)->m_ag_maxlevels - 1))) -#define XFS_ALLOCFREE_LOG_COUNT(mp,nx) \ - ((nx) * (2 * (2 * (mp)->m_ag_maxlevels - 1))) - -/* * Per-directory log reservation for any directory change. * dir blocks: (1 btree block per level + data block + free block) * dblock size * bmap btree: (levels + 2) * max depth * block size From darrick.wong@oracle.com Thu Jun 16 20:21:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F328F7D70 for ; Thu, 16 Jun 2016 20:21:21 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 67490AC001 for ; Thu, 16 Jun 2016 18:21:21 -0700 (PDT) X-ASG-Debug-ID: 1466126478-04cbb01fee695e0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id zpNgls7PIDssn3DP (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1LGY7006730 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:16 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1LFxZ012477 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:16 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1LDXJ006953; Fri, 17 Jun 2016 01:21:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:12 -0700 Subject: [PATCH 031/119] xfs: rmap btree requires more reserved free space From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 031/119] xfs: rmap btree requires more reserved free space To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:21:11 -0700 Message-ID: <146612647122.12839.13018596528662402580.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126478 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12686 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner The rmap btree is allocated from the AGFL, which means we have to ensure ENOSPC is reported to userspace before we run out of free space in each AG. The last allocation in an AG can cause a full height rmap btree split, and that means we have to reserve at least this many blocks *in each AG* to be placed on the AGFL at ENOSPC. Update the various space calculation functiosn to handle this. Also, because the macros are now executing conditional code and are called quite frequently, convert them to functions that initialise varaibles in the struct xfs_mount, use the new variables everywhere and document the calculations better. v2: If rmapbt is disabled, it is incorrect to require 1 extra AGFL block for the rmapbt (due to the + 1); the entire clause needs to be gated on the feature flag. v3: Use m_rmap_maxlevels to determine min_free. [darrick.wong@oracle.com: don't reserve blocks if !rmap] [dchinner@redhat.com: update m_ag_max_usable after growfs] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_alloc.c | 71 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_alloc.h | 41 +++----------------------- fs/xfs/libxfs/xfs_bmap.c | 2 + fs/xfs/libxfs/xfs_sb.c | 2 + fs/xfs/xfs_discard.c | 2 + fs/xfs/xfs_fsops.c | 5 ++- fs/xfs/xfs_log_recover.c | 1 + fs/xfs/xfs_mount.c | 2 + fs/xfs/xfs_mount.h | 2 + fs/xfs/xfs_super.c | 2 + 10 files changed, 88 insertions(+), 42 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 570ca17..4c8ffd4 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -63,6 +63,72 @@ xfs_prealloc_blocks( } /* + * In order to avoid ENOSPC-related deadlock caused by out-of-order locking of + * AGF buffer (PV 947395), we place constraints on the relationship among + * actual allocations for data blocks, freelist blocks, and potential file data + * bmap btree blocks. However, these restrictions may result in no actual space + * allocated for a delayed extent, for example, a data block in a certain AG is + * allocated but there is no additional block for the additional bmap btree + * block due to a split of the bmap btree of the file. The result of this may + * lead to an infinite loop when the file gets flushed to disk and all delayed + * extents need to be actually allocated. To get around this, we explicitly set + * aside a few blocks which will not be reserved in delayed allocation. + * + * The minimum number of needed freelist blocks is 4 fsbs _per AG_ when we are + * not using rmap btrees a potential split of file's bmap btree requires 1 fsb, + * so we set the number of set-aside blocks to 4 + 4*agcount when not using + * rmap btrees. + * + * When rmap btrees are active, we have to consider that using the last block + * in the AG can cause a full height rmap btree split and we need enough blocks + * on the AGFL to be able to handle this. That means we have, in addition to + * the above consideration, another (2 * mp->m_rmap_levels) - 1 blocks required + * to be available to the free list. + */ +unsigned int +xfs_alloc_set_aside( + struct xfs_mount *mp) +{ + unsigned int blocks; + + blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE); + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return blocks; + return blocks + (mp->m_sb.sb_agcount * (2 * mp->m_rmap_maxlevels) - 1); +} + +/* + * When deciding how much space to allocate out of an AG, we limit the + * allocation maximum size to the size the AG. However, we cannot use all the + * blocks in the AG - some are permanently used by metadata. These + * blocks are generally: + * - the AG superblock, AGF, AGI and AGFL + * - the AGF (bno and cnt) and AGI btree root blocks, and optionally + * the AGI free inode and rmap btree root blocks. + * - blocks on the AGFL according to xfs_alloc_set_aside() limits + * + * The AG headers are sector sized, so the amount of space they take up is + * dependent on filesystem geometry. The others are all single blocks. + */ +unsigned int +xfs_alloc_ag_max_usable(struct xfs_mount *mp) +{ + unsigned int blocks; + + blocks = XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)); /* ag headers */ + blocks += XFS_ALLOC_AGFL_RESERVE; + blocks += 3; /* AGF, AGI btree root blocks */ + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + blocks++; /* finobt root block */ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + /* rmap root block + full tree split on full AG */ + blocks += 1 + (2 * mp->m_ag_maxlevels) - 1; + } + + return mp->m_sb.sb_agblocks - blocks; +} + +/* * Lookup the record equal to [bno, len] in the btree given by cur. */ STATIC int /* error */ @@ -1904,6 +1970,11 @@ xfs_alloc_min_freelist( /* space needed by-size freespace btree */ min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1, mp->m_ag_maxlevels); + /* space needed reverse mapping used space btree */ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + min_free += min_t(unsigned int, + pag->pagf_levels[XFS_BTNUM_RMAPi] + 1, + mp->m_rmap_maxlevels); return min_free; } diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 0721a48..7b6c66b 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -56,42 +56,6 @@ typedef unsigned int xfs_alloctype_t; #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ /* - * In order to avoid ENOSPC-related deadlock caused by - * out-of-order locking of AGF buffer (PV 947395), we place - * constraints on the relationship among actual allocations for - * data blocks, freelist blocks, and potential file data bmap - * btree blocks. However, these restrictions may result in no - * actual space allocated for a delayed extent, for example, a data - * block in a certain AG is allocated but there is no additional - * block for the additional bmap btree block due to a split of the - * bmap btree of the file. The result of this may lead to an - * infinite loop in xfssyncd when the file gets flushed to disk and - * all delayed extents need to be actually allocated. To get around - * this, we explicitly set aside a few blocks which will not be - * reserved in delayed allocation. Considering the minimum number of - * needed freelist blocks is 4 fsbs _per AG_, a potential split of file's bmap - * btree requires 1 fsb, so we set the number of set-aside blocks - * to 4 + 4*agcount. - */ -#define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) - -/* - * When deciding how much space to allocate out of an AG, we limit the - * allocation maximum size to the size the AG. However, we cannot use all the - * blocks in the AG - some are permanently used by metadata. These - * blocks are generally: - * - the AG superblock, AGF, AGI and AGFL - * - the AGF (bno and cnt) and AGI btree root blocks - * - 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits - * - * The AG headers are sector sized, so the amount of space they take up is - * dependent on filesystem geometry. The others are all single blocks. - */ -#define XFS_ALLOC_AG_MAX_USABLE(mp) \ - ((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7) - - -/* * Argument structure for xfs_alloc routines. * This is turned into a structure to avoid having 20 arguments passed * down several levels of the stack. @@ -133,6 +97,11 @@ typedef struct xfs_alloc_arg { #define XFS_ALLOC_INITIAL_USER_DATA (1 << 1)/* special case start of file */ #define XFS_ALLOC_USERDATA_ZERO (1 << 2)/* zero extent on allocation */ +/* freespace limit calculations */ +#define XFS_ALLOC_AGFL_RESERVE 4 +unsigned int xfs_alloc_set_aside(struct xfs_mount *mp); +unsigned int xfs_alloc_ag_max_usable(struct xfs_mount *mp); + xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp, struct xfs_perag *pag, xfs_extlen_t need); unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp, diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 2c28f2a..61c0231 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3672,7 +3672,7 @@ xfs_bmap_btalloc( args.fsbno = ap->blkno; /* Trim the allocation back to the maximum an AG can fit. */ - args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp)); + args.maxlen = MIN(ap->length, mp->m_ag_max_usable); args.firstblock = *ap->firstblock; blen = 0; if (nullfb) { diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index f86226b..59c9f59 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -749,6 +749,8 @@ xfs_sb_mount_common( mp->m_ialloc_min_blks = sbp->sb_spino_align; else mp->m_ialloc_min_blks = mp->m_ialloc_blks; + mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); + mp->m_ag_max_usable = xfs_alloc_ag_max_usable(mp); } /* diff --git a/fs/xfs/xfs_discard.c b/fs/xfs/xfs_discard.c index 272c3f8..4ff499a 100644 --- a/fs/xfs/xfs_discard.c +++ b/fs/xfs/xfs_discard.c @@ -179,7 +179,7 @@ xfs_ioc_trim( * matter as trimming blocks is an advisory interface. */ if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) || - range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)) || + range.minlen > XFS_FSB_TO_B(mp, mp->m_ag_max_usable) || range.len < mp->m_sb.sb_blocksize) return -EINVAL; diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 8a85e49..3772f6c 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -583,6 +583,7 @@ xfs_growfs_data_private( } else mp->m_maxicount = 0; xfs_set_low_space_thresholds(mp); + mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); /* update secondary superblocks. */ for (agno = 1; agno < nagcount; agno++) { @@ -720,7 +721,7 @@ xfs_fs_counts( cnt->allocino = percpu_counter_read_positive(&mp->m_icount); cnt->freeino = percpu_counter_read_positive(&mp->m_ifree); cnt->freedata = percpu_counter_read_positive(&mp->m_fdblocks) - - XFS_ALLOC_SET_ASIDE(mp); + mp->m_alloc_set_aside; spin_lock(&mp->m_sb_lock); cnt->freertx = mp->m_sb.sb_frextents; @@ -793,7 +794,7 @@ retry: __int64_t free; free = percpu_counter_sum(&mp->m_fdblocks) - - XFS_ALLOC_SET_ASIDE(mp); + mp->m_alloc_set_aside; if (!free) goto out; /* ENOSPC and fdblks_delta = 0 */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 0c41bd2..b33187b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -5027,6 +5027,7 @@ xlog_do_recover( xfs_warn(mp, "Failed post-recovery per-ag init: %d", error); return error; } + mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); xlog_recover_check_summary(log); diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 8af1c88..879f3ef 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1219,7 +1219,7 @@ xfs_mod_fdblocks( batch = XFS_FDBLOCKS_BATCH; __percpu_counter_add(&mp->m_fdblocks, delta, batch); - if (__percpu_counter_compare(&mp->m_fdblocks, XFS_ALLOC_SET_ASIDE(mp), + if (__percpu_counter_compare(&mp->m_fdblocks, mp->m_alloc_set_aside, XFS_FDBLOCKS_BATCH) >= 0) { /* we had space! */ return 0; diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 0ed0f29..b36676c 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -123,6 +123,8 @@ typedef struct xfs_mount { uint m_in_maxlevels; /* max inobt btree levels. */ uint m_rmap_maxlevels; /* max rmap btree levels */ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ + uint m_alloc_set_aside; /* space we can't use */ + uint m_ag_max_usable; /* max space per AG */ struct radix_tree_root m_perag_tree; /* per-ag accounting info */ spinlock_t m_perag_lock; /* lock for m_perag_tree */ struct mutex m_growlock; /* growfs mutex */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index bf63f6d..1575849 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1076,7 +1076,7 @@ xfs_fs_statfs( statp->f_blocks = sbp->sb_dblocks - lsize; spin_unlock(&mp->m_sb_lock); - statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp); + statp->f_bfree = fdblocks - mp->m_alloc_set_aside; statp->f_bavail = statp->f_bfree; fakeinos = statp->f_bfree << sbp->sb_inopblog; From darrick.wong@oracle.com Thu Jun 16 20:21:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 53F237D76 for ; Thu, 16 Jun 2016 20:21:28 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 129188F804C for ; Thu, 16 Jun 2016 18:21:28 -0700 (PDT) X-ASG-Debug-ID: 1466126484-04bdf01e1595920001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id iiDYbkwWL4wjJXxZ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1LMsi006747 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:22 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1LMLe012645 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:22 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1LJN4006963; Fri, 17 Jun 2016 01:21:20 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:19 -0700 Subject: [PATCH 032/119] xfs: add rmap btree operations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 032/119] xfs: add rmap btree operations To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:21:17 -0700 Message-ID: <146612647771.12839.2301418036042118299.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126485 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13620 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Implement the generic btree operations needed to manipulate rmap btree blocks. This is very similar to the per-ag freespace btree implementation, and uses the AGFL for allocation and freeing of blocks. Adapt the rmap btree to store owner offsets within each rmap record, and to handle the primary key being redefined as the tuple [agblk, owner, offset]. The expansion of the primary key is crucial to allowing multiple owners per extent. [darrick: adapt the btree ops to deal with offsets] [darrick: remove init_rec_from_key] [darrick: move unwritten bit to rm_offset] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_btree.h | 1 fs/xfs/libxfs/xfs_rmap.c | 96 ++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.c | 243 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 9 + fs/xfs/xfs_trace.h | 3 5 files changed, 352 insertions(+) diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 90ea2a7..9963c48 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -216,6 +216,7 @@ union xfs_btree_irec { xfs_alloc_rec_incore_t a; xfs_bmbt_irec_t b; xfs_inobt_rec_incore_t i; + struct xfs_rmap_irec r; }; /* diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index d1fd471..c6a5a0b 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -37,6 +37,102 @@ #include "xfs_error.h" #include "xfs_extent_busy.h" +/* + * Lookup the first record less than or equal to [bno, len, owner, offset] + * in the btree given by cur. + */ +int +xfs_rmap_lookup_le( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags, + int *stat) +{ + cur->bc_rec.r.rm_startblock = bno; + cur->bc_rec.r.rm_blockcount = len; + cur->bc_rec.r.rm_owner = owner; + cur->bc_rec.r.rm_offset = offset; + cur->bc_rec.r.rm_flags = flags; + return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); +} + +/* + * Lookup the record exactly matching [bno, len, owner, offset] + * in the btree given by cur. + */ +int +xfs_rmap_lookup_eq( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags, + int *stat) +{ + cur->bc_rec.r.rm_startblock = bno; + cur->bc_rec.r.rm_blockcount = len; + cur->bc_rec.r.rm_owner = owner; + cur->bc_rec.r.rm_offset = offset; + cur->bc_rec.r.rm_flags = flags; + return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); +} + +/* + * Update the record referred to by cur to the value given + * by [bno, len, owner, offset]. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_rmap_update( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *irec) +{ + union xfs_btree_rec rec; + + rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock); + rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount); + rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner); + rec.rmap.rm_offset = cpu_to_be64( + xfs_rmap_irec_offset_pack(irec)); + return xfs_btree_update(cur, &rec); +} + +static int +xfs_rmapbt_btrec_to_irec( + union xfs_btree_rec *rec, + struct xfs_rmap_irec *irec) +{ + irec->rm_flags = 0; + irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock); + irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount); + irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner); + return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset), + irec); +} + +/* + * Get the data from the pointed-to record. + */ +int +xfs_rmap_get_rec( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *irec, + int *stat) +{ + union xfs_btree_rec *rec; + int error; + + error = xfs_btree_get_rec(cur, &rec, stat); + if (error || !*stat) + return error; + + return xfs_rmapbt_btrec_to_irec(rec, irec); +} + int xfs_rmap_free( struct xfs_trans *tp, diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c index 7a35c78..c50c725 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.c +++ b/fs/xfs/libxfs/xfs_rmap_btree.c @@ -35,6 +35,31 @@ #include "xfs_error.h" #include "xfs_extent_busy.h" +/* + * Reverse map btree. + * + * This is a per-ag tree used to track the owner(s) of a given extent. With + * reflink it is possible for there to be multiple owners, which is a departure + * from classic XFS. Owner records for data extents are inserted when the + * extent is mapped and removed when an extent is unmapped. Owner records for + * all other block types (i.e. metadata) are inserted when an extent is + * allocated and removed when an extent is freed. There can only be one owner + * of a metadata extent, usually an inode or some other metadata structure like + * an AG btree. + * + * The rmap btree is part of the free space management, so blocks for the tree + * are sourced from the agfl. Hence we need transaction reservation support for + * this tree so that the freelist is always large enough. This also impacts on + * the minimum space we need to leave free in the AG. + * + * The tree is ordered by [ag block, owner, offset]. This is a large key size, + * but it is the only way to enforce unique keys when a block can be owned by + * multiple files at any offset. There's no need to order/search by extent + * size for online updating/management of the tree. It is intended that most + * reverse lookups will be to find the owner(s) of a particular block, or to + * try to recover tree and file data from corrupt primary metadata. + */ + static struct xfs_btree_cur * xfs_rmapbt_dup_cursor( struct xfs_btree_cur *cur) @@ -43,6 +68,173 @@ xfs_rmapbt_dup_cursor( cur->bc_private.a.agbp, cur->bc_private.a.agno); } +STATIC void +xfs_rmapbt_set_root( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr, + int inc) +{ + struct xfs_buf *agbp = cur->bc_private.a.agbp; + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); + int btnum = cur->bc_btnum; + struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); + + ASSERT(ptr->s != 0); + + agf->agf_roots[btnum] = ptr->s; + be32_add_cpu(&agf->agf_levels[btnum], inc); + pag->pagf_levels[btnum] += inc; + xfs_perag_put(pag); + + xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); +} + +STATIC int +xfs_rmapbt_alloc_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *start, + union xfs_btree_ptr *new, + int *stat) +{ + int error; + xfs_agblock_t bno; + + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); + + /* Allocate the new block from the freelist. If we can't, give up. */ + error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp, + &bno, 1); + if (error) { + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); + return error; + } + + trace_xfs_rmapbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, + bno, 1); + if (bno == NULLAGBLOCK) { + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 0; + return 0; + } + + xfs_extent_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1, + false); + + xfs_trans_agbtree_delta(cur->bc_tp, 1); + new->s = cpu_to_be32(bno); + + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 1; + return 0; +} + +STATIC int +xfs_rmapbt_free_block( + struct xfs_btree_cur *cur, + struct xfs_buf *bp) +{ + struct xfs_buf *agbp = cur->bc_private.a.agbp; + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + xfs_agblock_t bno; + int error; + + bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp)); + trace_xfs_rmapbt_free_block(cur->bc_mp, cur->bc_private.a.agno, + bno, 1); + error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); + if (error) + return error; + + xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, + XFS_EXTENT_BUSY_SKIP_DISCARD); + xfs_trans_agbtree_delta(cur->bc_tp, -1); + + xfs_trans_binval(cur->bc_tp, bp); + return 0; +} + +STATIC int +xfs_rmapbt_get_minrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_rmap_mnr[level != 0]; +} + +STATIC int +xfs_rmapbt_get_maxrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_rmap_mxr[level != 0]; +} + +STATIC void +xfs_rmapbt_init_key_from_rec( + union xfs_btree_key *key, + union xfs_btree_rec *rec) +{ + key->rmap.rm_startblock = rec->rmap.rm_startblock; + key->rmap.rm_owner = rec->rmap.rm_owner; + key->rmap.rm_offset = rec->rmap.rm_offset; +} + +STATIC void +xfs_rmapbt_init_rec_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_rec *rec) +{ + rec->rmap.rm_startblock = cpu_to_be32(cur->bc_rec.r.rm_startblock); + rec->rmap.rm_blockcount = cpu_to_be32(cur->bc_rec.r.rm_blockcount); + rec->rmap.rm_owner = cpu_to_be64(cur->bc_rec.r.rm_owner); + rec->rmap.rm_offset = cpu_to_be64( + xfs_rmap_irec_offset_pack(&cur->bc_rec.r)); +} + +STATIC void +xfs_rmapbt_init_ptr_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); + + ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); + ASSERT(agf->agf_roots[cur->bc_btnum] != 0); + + ptr->s = agf->agf_roots[cur->bc_btnum]; +} + +STATIC __int64_t +xfs_rmapbt_key_diff( + struct xfs_btree_cur *cur, + union xfs_btree_key *key) +{ + struct xfs_rmap_irec *rec = &cur->bc_rec.r; + struct xfs_rmap_key *kp = &key->rmap; + __u64 x, y; + __int64_t d; + + d = (__int64_t)be32_to_cpu(kp->rm_startblock) - rec->rm_startblock; + if (d) + return d; + + x = be64_to_cpu(kp->rm_owner); + y = rec->rm_owner; + if (x > y) + return 1; + else if (y > x) + return -1; + + x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset)); + y = rec->rm_offset; + if (x > y) + return 1; + else if (y > x) + return -1; + return 0; +} + static bool xfs_rmapbt_verify( struct xfs_buf *bp) @@ -117,12 +309,63 @@ const struct xfs_buf_ops xfs_rmapbt_buf_ops = { .verify_write = xfs_rmapbt_write_verify, }; +#if defined(DEBUG) || defined(XFS_WARN) +STATIC int +xfs_rmapbt_keys_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + if (be32_to_cpu(k1->rmap.rm_startblock) < + be32_to_cpu(k2->rmap.rm_startblock)) + return 1; + if (be64_to_cpu(k1->rmap.rm_owner) < + be64_to_cpu(k2->rmap.rm_owner)) + return 1; + if (XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset)) <= + XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset))) + return 1; + return 0; +} + +STATIC int +xfs_rmapbt_recs_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_rec *r1, + union xfs_btree_rec *r2) +{ + if (be32_to_cpu(r1->rmap.rm_startblock) < + be32_to_cpu(r2->rmap.rm_startblock)) + return 1; + if (XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset)) < + XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset))) + return 1; + if (be64_to_cpu(r1->rmap.rm_owner) <= + be64_to_cpu(r2->rmap.rm_owner)) + return 1; + return 0; +} +#endif /* DEBUG */ + static const struct xfs_btree_ops xfs_rmapbt_ops = { .rec_len = sizeof(struct xfs_rmap_rec), .key_len = sizeof(struct xfs_rmap_key), .dup_cursor = xfs_rmapbt_dup_cursor, + .set_root = xfs_rmapbt_set_root, + .alloc_block = xfs_rmapbt_alloc_block, + .free_block = xfs_rmapbt_free_block, + .get_minrecs = xfs_rmapbt_get_minrecs, + .get_maxrecs = xfs_rmapbt_get_maxrecs, + .init_key_from_rec = xfs_rmapbt_init_key_from_rec, + .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur, + .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur, + .key_diff = xfs_rmapbt_key_diff, .buf_ops = &xfs_rmapbt_buf_ops, +#if defined(DEBUG) || defined(XFS_WARN) + .keys_inorder = xfs_rmapbt_keys_inorder, + .recs_inorder = xfs_rmapbt_recs_inorder, +#endif }; /* diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 462767f..17fa383 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -52,6 +52,15 @@ struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, int xfs_rmapbt_maxrecs(struct xfs_mount *mp, int blocklen, int leaf); extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp); +int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, uint64_t owner, uint64_t offset, + unsigned int flags, int *stat); +int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, uint64_t owner, uint64_t offset, + unsigned int flags, int *stat); +int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, + int *stat); + int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index b4ee9c8..28bd991 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2470,6 +2470,9 @@ DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent); DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_done); DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_error); +DEFINE_BUSY_EVENT(xfs_rmapbt_alloc_block); +DEFINE_BUSY_EVENT(xfs_rmapbt_free_block); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:21:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 61F2A7CDB for ; Thu, 16 Jun 2016 20:21:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 250C6304039 for ; Thu, 16 Jun 2016 18:21:31 -0700 (PDT) X-ASG-Debug-ID: 1466126488-04cb6c5425573a0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id i9p0u7OhPN5VYmSH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:29 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1LQ9B025940 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:21:27 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1LQWA009800 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:21:26 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1LQml027577; Fri, 17 Jun 2016 01:21:26 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:25 -0700 Subject: [PATCH 033/119] xfs: support overlapping intervals in the rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 033/119] xfs: support overlapping intervals in the rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:21:24 -0700 Message-ID: <146612648418.12839.17068915263834486145.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126489 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4712 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Now that the generic btree code supports overlapping intervals, plug in the rmap btree to this functionality. We will need it to find potential left neighbors in xfs_rmap_{alloc,free} later in the patch set. v2: Fix bit manipulation bug when generating high key offset. v3: Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rmap_btree.c | 59 +++++++++++++++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_rmap_btree.h | 10 +++++-- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c index c50c725..9adb930 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.c +++ b/fs/xfs/libxfs/xfs_rmap_btree.c @@ -181,6 +181,28 @@ xfs_rmapbt_init_key_from_rec( } STATIC void +xfs_rmapbt_init_high_key_from_rec( + union xfs_btree_key *key, + union xfs_btree_rec *rec) +{ + __uint64_t off; + int adj; + + adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1; + + key->rmap.rm_startblock = rec->rmap.rm_startblock; + be32_add_cpu(&key->rmap.rm_startblock, adj); + key->rmap.rm_owner = rec->rmap.rm_owner; + key->rmap.rm_offset = rec->rmap.rm_offset; + if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rmap.rm_owner)) || + XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rmap.rm_offset))) + return; + off = be64_to_cpu(key->rmap.rm_offset); + off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK); + key->rmap.rm_offset = cpu_to_be64(off); +} + +STATIC void xfs_rmapbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -235,6 +257,38 @@ xfs_rmapbt_key_diff( return 0; } +STATIC __int64_t +xfs_rmapbt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + struct xfs_rmap_key *kp1 = &k1->rmap; + struct xfs_rmap_key *kp2 = &k2->rmap; + __int64_t d; + __u64 x, y; + + d = (__int64_t)be32_to_cpu(kp2->rm_startblock) - + be32_to_cpu(kp1->rm_startblock); + if (d) + return d; + + x = be64_to_cpu(kp2->rm_owner); + y = be64_to_cpu(kp1->rm_owner); + if (x > y) + return 1; + else if (y > x) + return -1; + + x = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset)); + y = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset)); + if (x > y) + return 1; + else if (y > x) + return -1; + return 0; +} + static bool xfs_rmapbt_verify( struct xfs_buf *bp) @@ -350,6 +404,7 @@ xfs_rmapbt_recs_inorder( static const struct xfs_btree_ops xfs_rmapbt_ops = { .rec_len = sizeof(struct xfs_rmap_rec), .key_len = sizeof(struct xfs_rmap_key), + .flags = XFS_BTREE_OPS_OVERLAPPING, .dup_cursor = xfs_rmapbt_dup_cursor, .set_root = xfs_rmapbt_set_root, @@ -358,10 +413,12 @@ static const struct xfs_btree_ops xfs_rmapbt_ops = { .get_minrecs = xfs_rmapbt_get_minrecs, .get_maxrecs = xfs_rmapbt_get_maxrecs, .init_key_from_rec = xfs_rmapbt_init_key_from_rec, + .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec, .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur, .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur, .key_diff = xfs_rmapbt_key_diff, .buf_ops = &xfs_rmapbt_buf_ops, + .diff_two_keys = xfs_rmapbt_diff_two_keys, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_rmapbt_keys_inorder, .recs_inorder = xfs_rmapbt_recs_inorder, @@ -410,7 +467,7 @@ xfs_rmapbt_maxrecs( if (leaf) return blocklen / sizeof(struct xfs_rmap_rec); return blocklen / - (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); + (2 * sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); } /* Compute the maximum height of an rmap btree. */ diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 17fa383..796071c 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -38,12 +38,18 @@ struct xfs_mount; #define XFS_RMAP_KEY_ADDR(block, index) \ ((struct xfs_rmap_key *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ - ((index) - 1) * sizeof(struct xfs_rmap_key))) + ((index) - 1) * 2 * sizeof(struct xfs_rmap_key))) + +#define XFS_RMAP_HIGH_KEY_ADDR(block, index) \ + ((struct xfs_rmap_key *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + sizeof(struct xfs_rmap_key) + \ + ((index) - 1) * 2 * sizeof(struct xfs_rmap_key))) #define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \ ((xfs_rmap_ptr_t *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ - (maxrecs) * sizeof(struct xfs_rmap_key) + \ + (maxrecs) * 2 * sizeof(struct xfs_rmap_key) + \ ((index) - 1) * sizeof(xfs_rmap_ptr_t))) struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, From darrick.wong@oracle.com Thu Jun 16 20:21:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 938767CAF for ; Thu, 16 Jun 2016 20:21:36 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 655A78F804B for ; Thu, 16 Jun 2016 18:21:36 -0700 (PDT) X-ASG-Debug-ID: 1466126494-04cb6c5426573b0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 5tIaNCTevPlrCYoe (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:34 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1LWEE006793 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:21:32 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1LWAV009937 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:21:32 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1LWB2027594; Fri, 17 Jun 2016 01:21:32 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:32 -0700 Subject: [PATCH 034/119] xfs: teach rmapbt to support interval queries From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 034/119] xfs: teach rmapbt to support interval queries To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:21:30 -0700 Message-ID: <146612649050.12839.2803288971604662823.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126494 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2531 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Now that the generic btree code supports querying all records within a range of keys, use that functionality to allow us to ask for all the extents mapped to a range of physical blocks. v2: Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rmap.c | 43 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 9 ++++++++ 2 files changed, 52 insertions(+) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index c6a5a0b..0e1721a 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -184,3 +184,46 @@ out_error: trace_xfs_rmap_alloc_extent_error(mp, agno, bno, len, false, oinfo); return error; } + +struct xfs_rmapbt_query_range_info { + xfs_rmapbt_query_range_fn fn; + void *priv; +}; + +/* Format btree record and pass to our callback. */ +STATIC int +xfs_rmapbt_query_range_helper( + struct xfs_btree_cur *cur, + union xfs_btree_rec *rec, + void *priv) +{ + struct xfs_rmapbt_query_range_info *query = priv; + struct xfs_rmap_irec irec; + int error; + + error = xfs_rmapbt_btrec_to_irec(rec, &irec); + if (error) + return error; + return query->fn(cur, &irec, query->priv); +} + +/* Find all rmaps between two keys. */ +int +xfs_rmapbt_query_range( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *low_rec, + struct xfs_rmap_irec *high_rec, + xfs_rmapbt_query_range_fn fn, + void *priv) +{ + union xfs_btree_irec low_brec; + union xfs_btree_irec high_brec; + struct xfs_rmapbt_query_range_info query; + + low_brec.r = *low_rec; + high_brec.r = *high_rec; + query.priv = priv; + query.fn = fn; + return xfs_btree_query_range(cur, &low_brec, &high_brec, + xfs_rmapbt_query_range_helper, &query); +} diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 796071c..e926c6e 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -74,4 +74,13 @@ int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); +typedef int (*xfs_rmapbt_query_range_fn)( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv); + +int xfs_rmapbt_query_range(struct xfs_btree_cur *cur, + struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec, + xfs_rmapbt_query_range_fn fn, void *priv); + #endif /* __XFS_RMAP_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:21:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6DA787CDB for ; Thu, 16 Jun 2016 20:21:43 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3F212304039 for ; Thu, 16 Jun 2016 18:21:43 -0700 (PDT) X-ASG-Debug-ID: 1466126501-04cbb01fed69600001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id DCuKYqleLMDy5pV2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:41 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Lddv006887 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:39 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Ld0D013033 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:39 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1LcEn027663; Fri, 17 Jun 2016 01:21:38 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:38 -0700 Subject: [PATCH 035/119] xfs: add tracepoints for the rmap functions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 035/119] xfs: add tracepoints for the rmap functions To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:21:36 -0700 Message-ID: <146612649677.12839.16503733724386105697.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126501 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4048 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_trace.h | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 28bd991..6daafaf 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2415,8 +2415,6 @@ DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel); DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish); DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort); -DEFINE_MAP_EXTENT_DEFERRED_EVENT(xfs_defer_map_extent); - #define DEFINE_BMAP_FREE_DEFERRED_EVENT DEFINE_PHYS_EXTENT_DEFERRED_EVENT DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_defer); DEFINE_BMAP_FREE_DEFERRED_EVENT(xfs_bmap_free_deferred); @@ -2463,6 +2461,36 @@ DEFINE_EVENT(xfs_rmap_class, name, \ struct xfs_owner_info *oinfo), \ TP_ARGS(mp, agno, agbno, len, unwritten, oinfo)) +/* simple AG-based error/%ip tracepoint class */ +DECLARE_EVENT_CLASS(xfs_ag_error_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int error, + unsigned long caller_ip), + TP_ARGS(mp, agno, error, caller_ip), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(int, error) + __field(unsigned long, caller_ip) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->error = error; + __entry->caller_ip = caller_ip; + ), + TP_printk("dev %d:%d agno %u error %d caller %ps", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->error, + (char *)__entry->caller_ip) +); + +#define DEFINE_AG_ERROR_EVENT(name) \ +DEFINE_EVENT(xfs_ag_error_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, int error, \ + unsigned long caller_ip), \ + TP_ARGS(mp, agno, error, caller_ip)) + DEFINE_RMAP_EVENT(xfs_rmap_free_extent); DEFINE_RMAP_EVENT(xfs_rmap_free_extent_done); DEFINE_RMAP_EVENT(xfs_rmap_free_extent_error); @@ -2470,8 +2498,57 @@ DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent); DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_done); DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_error); +DECLARE_EVENT_CLASS(xfs_rmapbt_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + xfs_agblock_t agbno, xfs_extlen_t len, + uint64_t owner, uint64_t offset, unsigned int flags), + TP_ARGS(mp, agno, agbno, len, owner, offset, flags), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, agbno) + __field(xfs_extlen_t, len) + __field(uint64_t, owner) + __field(uint64_t, offset) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->agbno = agbno; + __entry->len = len; + __entry->owner = owner; + __entry->offset = offset; + __entry->flags = flags; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset %llu flags 0x%x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->agbno, + __entry->len, + __entry->owner, + __entry->offset, + __entry->flags) +); +#define DEFINE_RMAPBT_EVENT(name) \ +DEFINE_EVENT(xfs_rmapbt_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + xfs_agblock_t agbno, xfs_extlen_t len, \ + uint64_t owner, uint64_t offset, unsigned int flags), \ + TP_ARGS(mp, agno, agbno, len, owner, offset, flags)) + +#define DEFINE_RMAP_DEFERRED_EVENT DEFINE_MAP_EXTENT_DEFERRED_EVENT +DEFINE_RMAP_DEFERRED_EVENT(xfs_rmap_defer); +DEFINE_RMAP_DEFERRED_EVENT(xfs_rmap_deferred); + DEFINE_BUSY_EVENT(xfs_rmapbt_alloc_block); DEFINE_BUSY_EVENT(xfs_rmapbt_free_block); +DEFINE_RMAPBT_EVENT(xfs_rmapbt_update); +DEFINE_RMAPBT_EVENT(xfs_rmapbt_insert); +DEFINE_RMAPBT_EVENT(xfs_rmapbt_delete); +DEFINE_AG_ERROR_EVENT(xfs_rmapbt_insert_error); +DEFINE_AG_ERROR_EVENT(xfs_rmapbt_delete_error); +DEFINE_AG_ERROR_EVENT(xfs_rmapbt_update_error); #endif /* _TRACE_XFS_H */ From darrick.wong@oracle.com Thu Jun 16 20:21:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 47D987CDB for ; Thu, 16 Jun 2016 20:21:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 198D7304048 for ; Thu, 16 Jun 2016 18:21:53 -0700 (PDT) X-ASG-Debug-ID: 1466126510-04cbb01fee69610001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Wi0AVUuCiWRlb7gU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:50 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1LmVN026196 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:21:48 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1LlFi010481 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:47 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1LiQU007130; Fri, 17 Jun 2016 01:21:46 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:44 -0700 Subject: [PATCH 036/119] xfs: add an extent to the rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 036/119] xfs: add an extent to the rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:21:43 -0700 Message-ID: <146612650302.12839.2761171937406229512.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126510 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9734 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Now all the btree, free space and transaction infrastructure is in place, we can finally add the code to insert reverse mappings to the rmap btree. Freeing will be done in a separate patch, so just the addition operation can be focussed on here. v2: Update alloc function to handle non-shared file data. Isolate the part that makes changes from the part that initializes the rmap cursor; this will be useful for deferred updates. [darrick: handle owner offsets when adding rmaps] [dchinner: remove remaining debug printk statements] [darrick: move unwritten bit to rm_offset] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_rmap.c | 225 +++++++++++++++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_rmap_btree.h | 1 fs/xfs/xfs_trace.h | 2 3 files changed, 223 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 0e1721a..196e952 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -159,6 +159,218 @@ out_error: return error; } +/* + * A mergeable rmap should have the same owner, cannot be unwritten, and + * must be a bmbt rmap if we're asking about a bmbt rmap. + */ +static bool +xfs_rmap_is_mergeable( + struct xfs_rmap_irec *irec, + uint64_t owner, + uint64_t offset, + xfs_extlen_t len, + unsigned int flags) +{ + if (irec->rm_owner == XFS_RMAP_OWN_NULL) + return false; + if (irec->rm_owner != owner) + return false; + if ((flags & XFS_RMAP_UNWRITTEN) ^ + (irec->rm_flags & XFS_RMAP_UNWRITTEN)) + return false; + if ((flags & XFS_RMAP_ATTR_FORK) ^ + (irec->rm_flags & XFS_RMAP_ATTR_FORK)) + return false; + if ((flags & XFS_RMAP_BMBT_BLOCK) ^ + (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) + return false; + return true; +} + +/* + * When we allocate a new block, the first thing we do is add a reference to + * the extent in the rmap btree. This takes the form of a [agbno, length, + * owner, offset] record. Flags are encoded in the high bits of the offset + * field. + */ +STATIC int +__xfs_rmap_alloc( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + struct xfs_rmap_irec gtrec; + int have_gt; + int have_lt; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags = 0; + bool ignore_off; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & XFS_RMAP_BMBT_BLOCK); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_alloc_extent(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * For the initial lookup, look for and exact match or the left-adjacent + * record for our insertion point. This will also give us the record for + * start block contiguity tests. + */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, + &have_lt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); + + error = xfs_rmap_get_rec(cur, <rec, &have_lt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + + if (!xfs_rmap_is_mergeable(<rec, owner, offset, len, flags)) + have_lt = 0; + + XFS_WANT_CORRUPTED_GOTO(mp, + have_lt == 0 || + ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error); + + /* + * Increment the cursor to see if we have a right-adjacent record to our + * insertion point. This will give us the record for end block + * contiguity tests. + */ + error = xfs_btree_increment(cur, 0, &have_gt); + if (error) + goto out_error; + if (have_gt) { + error = xfs_rmap_get_rec(cur, >rec, &have_gt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); + XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock, + out_error); + trace_xfs_rmap_map_gtrec(cur->bc_mp, + cur->bc_private.a.agno, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (!xfs_rmap_is_mergeable(>rec, owner, offset, len, flags)) + have_gt = 0; + } + + /* + * Note: cursor currently points one record to the right of ltrec, even + * if there is no record in the tree to the right. + */ + if (have_lt && + ltrec.rm_startblock + ltrec.rm_blockcount == bno && + (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { + /* + * left edge contiguous, merge into left record. + * + * ltbno ltlen + * orig: |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + ltrec.rm_blockcount += len; + if (have_gt && + bno + len == gtrec.rm_startblock && + (ignore_off || offset + len == gtrec.rm_offset) && + (unsigned long)ltrec.rm_blockcount + len + + gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { + /* + * right edge also contiguous, delete right record + * and merge into left record. + * + * ltbno ltlen gtbno gtlen + * orig: |ooooooooo| |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| + */ + ltrec.rm_blockcount += gtrec.rm_blockcount; + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + gtrec.rm_startblock, + gtrec.rm_blockcount, + gtrec.rm_owner, + gtrec.rm_offset, + gtrec.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } + + /* point the cursor back to the left record and update */ + error = xfs_btree_decrement(cur, 0, &have_gt); + if (error) + goto out_error; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else if (have_gt && + bno + len == gtrec.rm_startblock && + (ignore_off || offset + len == gtrec.rm_offset)) { + /* + * right edge contiguous, merge into right record. + * + * gtbno gtlen + * Orig: |ooooooooo| + * adding: |aaaaaaaaa| + * Result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + gtrec.rm_startblock = bno; + gtrec.rm_blockcount += len; + if (!ignore_off) + gtrec.rm_offset = offset; + error = xfs_rmap_update(cur, >rec); + if (error) + goto out_error; + } else { + /* + * no contiguous edge with identical owner, insert + * new record at current cursor position. + */ + cur->bc_rec.r.rm_startblock = bno; + cur->bc_rec.r.rm_blockcount = len; + cur->bc_rec.r.rm_owner = owner; + cur->bc_rec.r.rm_offset = offset; + cur->bc_rec.r.rm_flags = flags; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, len, + owner, offset, flags); + error = xfs_btree_insert(cur, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } + + trace_xfs_rmap_alloc_extent_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_alloc_extent_error(mp, cur->bc_private.a.agno, + bno, len, unwritten, oinfo); + return error; +} + +/* + * Add a reference to an extent in the rmap btree. + */ int xfs_rmap_alloc( struct xfs_trans *tp, @@ -169,19 +381,22 @@ xfs_rmap_alloc( struct xfs_owner_info *oinfo) { struct xfs_mount *mp = tp->t_mountp; - int error = 0; + struct xfs_btree_cur *cur; + int error; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; - trace_xfs_rmap_alloc_extent(mp, agno, bno, len, false, oinfo); - if (1) + cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); + error = __xfs_rmap_alloc(cur, bno, len, false, oinfo); + if (error) goto out_error; - trace_xfs_rmap_alloc_extent_done(mp, agno, bno, len, false, oinfo); + + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; out_error: - trace_xfs_rmap_alloc_extent_error(mp, agno, bno, len, false, oinfo); + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index e926c6e..9d92da5 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -67,6 +67,7 @@ int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat); +/* functions for updating the rmapbt for bmbt blocks and AG btree blocks */ int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 6daafaf..3ebceb0 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2549,6 +2549,8 @@ DEFINE_RMAPBT_EVENT(xfs_rmapbt_delete); DEFINE_AG_ERROR_EVENT(xfs_rmapbt_insert_error); DEFINE_AG_ERROR_EVENT(xfs_rmapbt_delete_error); DEFINE_AG_ERROR_EVENT(xfs_rmapbt_update_error); +DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_result); +DEFINE_RMAPBT_EVENT(xfs_rmap_map_gtrec); #endif /* _TRACE_XFS_H */ From darrick.wong@oracle.com Thu Jun 16 20:21:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EDF097D94 for ; Thu, 16 Jun 2016 20:21:59 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id AF0648F8054 for ; Thu, 16 Jun 2016 18:21:59 -0700 (PDT) X-ASG-Debug-ID: 1466126516-04bdf01e1795950001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id OGnsh2IpGwyPhi2S (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:21:56 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Lsd2026243 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:54 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1LrIE013281 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:54 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1LpMG007159; Fri, 17 Jun 2016 01:21:52 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:51 -0700 Subject: [PATCH 037/119] xfs: remove an extent from the rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 037/119] xfs: remove an extent from the rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:21:49 -0700 Message-ID: <146612650943.12839.11339483902920543336.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126516 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9015 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Now that we have records in the rmap btree, we need to remove them when extents are freed. This needs to find the relevant record in the btree and remove/trim/split it accordingly. v2: Update the free function to deal with non-shared file data, and isolate the part that does the rmap update from the part that deals with cursors. This will be useful for deferred ops. [darrick.wong@oracle.com: make rmap routines handle the enlarged keyspace] [dchinner: remove remaining unused debug printks] [darrick: fix a bug when growfs in an AG with an rmap ending at EOFS] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_rmap.c | 220 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 215 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 196e952..1043c63 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -133,6 +133,212 @@ xfs_rmap_get_rec( return xfs_rmapbt_btrec_to_irec(rec, irec); } +/* + * Find the extent in the rmap btree and remove it. + * + * The record we find should always be an exact match for the extent that we're + * looking for, since we insert them into the btree without modification. + * + * Special Case #1: when growing the filesystem, we "free" an extent when + * growing the last AG. This extent is new space and so it is not tracked as + * used space in the btree. The growfs code will pass in an owner of + * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this + * extent. We verify that - the extent lookup result in a record that does not + * overlap. + * + * Special Case #2: EFIs do not record the owner of the extent, so when + * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap + * btree to ignore the owner (i.e. wildcard match) so we don't trigger + * corruption checks during log recovery. + */ +STATIC int +__xfs_rmap_free( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + uint64_t ltoff; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags; + bool ignore_off; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & XFS_RMAP_BMBT_BLOCK); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_free_extent(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * We should always have a left record because there's a static record + * for the AG headers at rm_startblock == 0 created by mkfs/growfs that + * will not ever be removed from the tree. + */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + error = xfs_rmap_get_rec(cur, <rec, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + ltoff = ltrec.rm_offset; + + /* + * For growfs, the incoming extent must be beyond the left record we + * just found as it is new space and won't be used by anyone. This is + * just a corruption check as we don't actually do anything with this + * extent. Note that we need to use >= instead of > because it might + * be the case that the "left" extent goes all the way to EOFS. + */ + if (owner == XFS_RMAP_OWN_NULL) { + XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock + + ltrec.rm_blockcount, out_error); + goto out_done; + } + + /* Make sure the unwritten flag matches. */ + XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == + (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); + + /* Make sure the extent we found covers the entire freeing range. */ + XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && + ltrec.rm_startblock + ltrec.rm_blockcount >= + bno + len, out_error); + + /* Make sure the owner matches what we expect to find in the tree. */ + XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner || + XFS_RMAP_NON_INODE_OWNER(owner), out_error); + + /* Check the offset, if necessary. */ + if (!XFS_RMAP_NON_INODE_OWNER(owner)) { + if (flags & XFS_RMAP_BMBT_BLOCK) { + XFS_WANT_CORRUPTED_GOTO(mp, + ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK, + out_error); + } else { + XFS_WANT_CORRUPTED_GOTO(mp, + ltrec.rm_offset <= offset, out_error); + XFS_WANT_CORRUPTED_GOTO(mp, + ltoff + ltrec.rm_blockcount >= offset + len, + out_error); + } + } + + if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { + /* exact match, simply remove the record from rmap tree */ + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + ltrec.rm_startblock, ltrec.rm_blockcount, + ltrec.rm_owner, ltrec.rm_offset, + ltrec.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } else if (ltrec.rm_startblock == bno) { + /* + * overlap left hand side of extent: move the start, trim the + * length and update the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + ltrec.rm_startblock += len; + ltrec.rm_blockcount -= len; + if (!ignore_off) + ltrec.rm_offset += len; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { + /* + * overlap right hand side of extent: trim the length and update + * the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + ltrec.rm_blockcount -= len; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else { + + /* + * overlap middle of extent: trim the length of the existing + * record to the length of the new left-extent size, increment + * the insertion position so we can insert a new record + * containing the remaining right-extent space. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrr| |rrrr| + * bno len + */ + xfs_extlen_t orig_len = ltrec.rm_blockcount; + + ltrec.rm_blockcount = bno - ltrec.rm_startblock; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto out_error; + + cur->bc_rec.r.rm_startblock = bno + len; + cur->bc_rec.r.rm_blockcount = orig_len - len - + ltrec.rm_blockcount; + cur->bc_rec.r.rm_owner = ltrec.rm_owner; + if (ignore_off) + cur->bc_rec.r.rm_offset = 0; + else + cur->bc_rec.r.rm_offset = offset + len; + cur->bc_rec.r.rm_flags = flags; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, + cur->bc_rec.r.rm_startblock, + cur->bc_rec.r.rm_blockcount, + cur->bc_rec.r.rm_owner, + cur->bc_rec.r.rm_offset, + cur->bc_rec.r.rm_flags); + error = xfs_btree_insert(cur, &i); + if (error) + goto out_error; + } + +out_done: + trace_xfs_rmap_free_extent_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_free_extent_error(mp, cur->bc_private.a.agno, + bno, len, unwritten, oinfo); + return error; +} + +/* + * Remove a reference to an extent in the rmap btree. + */ int xfs_rmap_free( struct xfs_trans *tp, @@ -143,19 +349,23 @@ xfs_rmap_free( struct xfs_owner_info *oinfo) { struct xfs_mount *mp = tp->t_mountp; - int error = 0; + struct xfs_btree_cur *cur; + int error; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; - trace_xfs_rmap_free_extent(mp, agno, bno, len, false, oinfo); - if (1) + cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); + + error = __xfs_rmap_free(cur, bno, len, false, oinfo); + if (error) goto out_error; - trace_xfs_rmap_free_extent_done(mp, agno, bno, len, false, oinfo); + + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; out_error: - trace_xfs_rmap_free_extent_error(mp, agno, bno, len, false, oinfo); + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } From darrick.wong@oracle.com Thu Jun 16 20:22:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AC4AF7DA0 for ; Thu, 16 Jun 2016 20:22:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6AF6A8F8050 for ; Thu, 16 Jun 2016 18:22:05 -0700 (PDT) X-ASG-Debug-ID: 1466126521-04bdf01e1095950001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id BoiSXwSxFKY1PFLG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:02 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1M0GM007015 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:22:00 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1LxST010818 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:21:59 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Lv2N019357; Fri, 17 Jun 2016 01:21:58 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:21:57 -0700 Subject: [PATCH 038/119] xfs: convert unwritten status of reverse mappings From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 038/119] xfs: convert unwritten status of reverse mappings To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:21:55 -0700 Message-ID: <146612651582.12839.562287367335619574.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126522 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15113 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a function to convert an unwritten extent to a real one and vice versa. v2: Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rmap.c | 442 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_trace.h | 6 + 2 files changed, 448 insertions(+) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 1043c63..53ba14e 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -610,6 +610,448 @@ out_error: return error; } +#define RMAP_LEFT_CONTIG (1 << 0) +#define RMAP_RIGHT_CONTIG (1 << 1) +#define RMAP_LEFT_FILLING (1 << 2) +#define RMAP_RIGHT_FILLING (1 << 3) +#define RMAP_LEFT_VALID (1 << 6) +#define RMAP_RIGHT_VALID (1 << 7) + +#define LEFT r[0] +#define RIGHT r[1] +#define PREV r[2] +#define NEW r[3] + +/* + * Convert an unwritten extent to a real extent or vice versa. + * Does not handle overlapping extents. + */ +STATIC int +__xfs_rmap_convert( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec r[4]; /* neighbor extent entries */ + /* left is 0, right is 1, prev is 2 */ + /* new is 3 */ + uint64_t owner; + uint64_t offset; + uint64_t new_endoff; + unsigned int oldext; + unsigned int newext; + unsigned int flags = 0; + int i; + int state = 0; + int error; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); + oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; + new_endoff = offset + len; + trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * For the initial lookup, look for and exact match or the left-adjacent + * record for our insertion point. This will also give us the record for + * start block contiguity tests. + */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + + error = xfs_rmap_get_rec(cur, &PREV, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, PREV.rm_startblock, + PREV.rm_blockcount, PREV.rm_owner, + PREV.rm_offset, PREV.rm_flags); + + ASSERT(PREV.rm_offset <= offset); + ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); + ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); + newext = ~oldext & XFS_RMAP_UNWRITTEN; + + /* + * Set flags determining what part of the previous oldext allocation + * extent is being replaced by a newext allocation. + */ + if (PREV.rm_offset == offset) + state |= RMAP_LEFT_FILLING; + if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) + state |= RMAP_RIGHT_FILLING; + + /* + * Decrement the cursor to see if we have a left-adjacent record to our + * insertion point. This will give us the record for end block + * contiguity tests. + */ + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + if (i) { + state |= RMAP_LEFT_VALID; + error = xfs_rmap_get_rec(cur, &LEFT, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + XFS_WANT_CORRUPTED_GOTO(mp, + LEFT.rm_startblock + LEFT.rm_blockcount <= bno, + done); + trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, + cur->bc_private.a.agno, LEFT.rm_startblock, + LEFT.rm_blockcount, LEFT.rm_owner, + LEFT.rm_offset, LEFT.rm_flags); + if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && + LEFT.rm_offset + LEFT.rm_blockcount == offset && + xfs_rmap_is_mergeable(&LEFT, owner, offset, len, newext)) + state |= RMAP_LEFT_CONTIG; + } + + /* + * Increment the cursor to see if we have a right-adjacent record to our + * insertion point. This will give us the record for end block + * contiguity tests. + */ + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + if (i) { + state |= RMAP_RIGHT_VALID; + error = xfs_rmap_get_rec(cur, &RIGHT, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, + done); + trace_xfs_rmap_convert_gtrec(cur->bc_mp, + cur->bc_private.a.agno, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (bno + len == RIGHT.rm_startblock && + offset + len == RIGHT.rm_offset && + xfs_rmap_is_mergeable(&RIGHT, owner, offset, len, newext)) + state |= RMAP_RIGHT_CONTIG; + } + + /* check that left + prev + right is not too long */ + if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == + (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && + (unsigned long)LEFT.rm_blockcount + len + + RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) + state &= ~RMAP_RIGHT_CONTIG; + + trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, + _RET_IP_); + + /* reset the cursor back to PREV */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + + /* + * Switch out based on the FILLING and CONTIG state bits. + */ + switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left and right neighbors are both contiguous with new. + */ + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + RIGHT.rm_startblock, RIGHT.rm_blockcount, + RIGHT.rm_owner, RIGHT.rm_offset, + RIGHT.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + PREV.rm_startblock, PREV.rm_blockcount, + PREV.rm_owner, PREV.rm_offset, + PREV.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW = LEFT; + NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left neighbor is contiguous, the right is not. + */ + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + PREV.rm_startblock, PREV.rm_blockcount, + PREV.rm_owner, PREV.rm_offset, + PREV.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW = LEFT; + NEW.rm_blockcount += PREV.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The right neighbor is contiguous, the left is not. + */ + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + RIGHT.rm_startblock, RIGHT.rm_blockcount, + RIGHT.rm_owner, RIGHT.rm_offset, + RIGHT.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_startblock = bno; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_blockcount = len + RIGHT.rm_blockcount; + NEW.rm_flags = newext; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: + /* + * Setting all of a previous oldext extent to newext. + * Neither the left nor right neighbors are contiguous with + * the new one. + */ + NEW = PREV; + NEW.rm_flags = newext; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is contiguous. + */ + NEW = PREV; + NEW.rm_offset += len; + NEW.rm_startblock += len; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + NEW = LEFT; + NEW.rm_blockcount += len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is not contiguous. + */ + NEW = PREV; + NEW.rm_startblock += len; + NEW.rm_offset += len; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + NEW.rm_startblock = bno; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_blockcount = len; + NEW.rm_flags = newext; + cur->bc_rec.r = NEW; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, + len, owner, offset, newext); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + break; + + case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is contiguous with the new allocation. + */ + NEW = PREV; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + NEW = RIGHT; + NEW.rm_offset = offset; + NEW.rm_startblock = bno; + NEW.rm_blockcount += len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_RIGHT_FILLING: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is not contiguous. + */ + NEW = PREV; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, + oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + NEW.rm_startblock = bno; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_blockcount = len; + NEW.rm_flags = newext; + cur->bc_rec.r = NEW; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, + len, owner, offset, newext); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + break; + + case 0: + /* + * Setting the middle part of a previous oldext extent to + * newext. Contiguity is impossible here. + * One extent becomes three extents. + */ + /* new right extent - oldext */ + NEW.rm_startblock = bno + len; + NEW.rm_owner = owner; + NEW.rm_offset = new_endoff; + NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - + new_endoff; + NEW.rm_flags = PREV.rm_flags; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + /* new left extent - oldext */ + NEW = PREV; + NEW.rm_blockcount = offset - PREV.rm_offset; + cur->bc_rec.r = NEW; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, + NEW.rm_startblock, NEW.rm_blockcount, + NEW.rm_owner, NEW.rm_offset, + NEW.rm_flags); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + /* + * Reset the cursor to the position of the new extent + * we are about to insert as we can't trust it after + * the previous insert. + */ + error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, + oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + /* new middle extent - newext */ + cur->bc_rec.b.br_state = newext; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, len, + owner, offset, newext); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_CONTIG: + case RMAP_RIGHT_CONTIG: + /* + * These cases are all impossible. + */ + ASSERT(0); + } + + trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +done: + if (error) + trace_xfs_rmap_convert_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +#undef NEW +#undef LEFT +#undef RIGHT +#undef PREV + struct xfs_rmapbt_query_range_info { xfs_rmapbt_query_range_fn fn; void *priv; diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 3ebceb0..6466adc 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2497,6 +2497,10 @@ DEFINE_RMAP_EVENT(xfs_rmap_free_extent_error); DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent); DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_done); DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_error); +DEFINE_RMAP_EVENT(xfs_rmap_convert); +DEFINE_RMAP_EVENT(xfs_rmap_convert_done); +DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_error); +DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_state); DECLARE_EVENT_CLASS(xfs_rmapbt_class, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, @@ -2551,6 +2555,8 @@ DEFINE_AG_ERROR_EVENT(xfs_rmapbt_delete_error); DEFINE_AG_ERROR_EVENT(xfs_rmapbt_update_error); DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_result); DEFINE_RMAPBT_EVENT(xfs_rmap_map_gtrec); +DEFINE_RMAPBT_EVENT(xfs_rmap_convert_gtrec); +DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result); #endif /* _TRACE_XFS_H */ From darrick.wong@oracle.com Thu Jun 16 20:22:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4C8D07CB5 for ; Thu, 16 Jun 2016 20:22:10 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id C31A1AC001 for ; Thu, 16 Jun 2016 18:22:09 -0700 (PDT) X-ASG-Debug-ID: 1466126527-04cb6c542657410001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id fPcVyIwtI2JfzwdZ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1M5Ph026533 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:05 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1M58t007106 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:05 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1M4F9019406; Fri, 17 Jun 2016 01:22:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:03 -0700 Subject: [PATCH 039/119] xfs: add rmap btree insert and delete helpers From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 039/119] xfs: add rmap btree insert and delete helpers To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:22:02 -0700 Message-ID: <146612652222.12839.8353722216601177344.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126527 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3765 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add a couple of helper functions to encapsulate rmap btree insert and delete operations. Add tracepoints to the update function. Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_rmap.c | 78 +++++++++++++++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_rmap_btree.h | 3 ++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 53ba14e..f92eaa1 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -92,13 +92,89 @@ xfs_rmap_update( struct xfs_rmap_irec *irec) { union xfs_btree_rec rec; + int error; + + trace_xfs_rmapbt_update(cur->bc_mp, cur->bc_private.a.agno, + irec->rm_startblock, irec->rm_blockcount, + irec->rm_owner, irec->rm_offset, irec->rm_flags); rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock); rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount); rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner); rec.rmap.rm_offset = cpu_to_be64( xfs_rmap_irec_offset_pack(irec)); - return xfs_btree_update(cur, &rec); + error = xfs_btree_update(cur, &rec); + if (error) + trace_xfs_rmapbt_update_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +int +xfs_rmapbt_insert( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags) +{ + int i; + int error; + + trace_xfs_rmapbt_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno, + len, owner, offset, flags); + + error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done); + + rcur->bc_rec.r.rm_startblock = agbno; + rcur->bc_rec.r.rm_blockcount = len; + rcur->bc_rec.r.rm_owner = owner; + rcur->bc_rec.r.rm_offset = offset; + rcur->bc_rec.r.rm_flags = flags; + error = xfs_btree_insert(rcur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); +done: + if (error) + trace_xfs_rmapbt_insert_error(rcur->bc_mp, + rcur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +STATIC int +xfs_rmapbt_delete( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags) +{ + int i; + int error; + + trace_xfs_rmapbt_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno, + len, owner, offset, flags); + + error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); + + error = xfs_btree_delete(rcur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); +done: + if (error) + trace_xfs_rmapbt_delete_error(rcur->bc_mp, + rcur->bc_private.a.agno, error, _RET_IP_); + return error; } static int diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 9d92da5..6674340 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -64,6 +64,9 @@ int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags, int *stat); +int xfs_rmapbt_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno, + xfs_extlen_t len, uint64_t owner, uint64_t offset, + unsigned int flags); int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat); From darrick.wong@oracle.com Thu Jun 16 20:22:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 988977DA7 for ; Thu, 16 Jun 2016 20:22:16 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1128EAC002 for ; Thu, 16 Jun 2016 18:22:15 -0700 (PDT) X-ASG-Debug-ID: 1466126533-04cb6c542457420001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id tMFRv4xxAg23v0NO (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:14 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1MB2H007384 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:12 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MBjd007191 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:11 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MADb023656; Fri, 17 Jun 2016 01:22:10 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:10 -0700 Subject: [PATCH 040/119] xfs: create helpers for mapping, unmapping, and converting file fork extents From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 040/119] xfs: create helpers for mapping, unmapping, and converting file fork extents To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:22:08 -0700 Message-ID: <146612652855.12839.8509289990733155675.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126534 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1738 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create two helper functions to assist with mapping, unmapping, and converting flag status of extents in a file's data/attr forks. For non-shared files we can use the _alloc, _free, and _convert functions; when reflink comes these functions will be augmented to deal with shared extents. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rmap.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index f92eaa1..76fc5c2 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -1123,11 +1123,53 @@ done: return error; } +/* + * Convert an unwritten extent to a real extent or vice versa. + */ +STATIC int +xfs_rmap_convert( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + return __xfs_rmap_convert(cur, bno, len, unwritten, oinfo); +} + #undef NEW #undef LEFT #undef RIGHT #undef PREV +/* + * Find an extent in the rmap btree and unmap it. + */ +STATIC int +xfs_rmap_unmap( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + return __xfs_rmap_free(cur, bno, len, unwritten, oinfo); +} + +/* + * Find an extent in the rmap btree and map it. + */ +STATIC int +xfs_rmap_map( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + return __xfs_rmap_alloc(cur, bno, len, unwritten, oinfo); +} + struct xfs_rmapbt_query_range_info { xfs_rmapbt_query_range_fn fn; void *priv; From darrick.wong@oracle.com Thu Jun 16 20:22:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 734E27CD1 for ; Thu, 16 Jun 2016 20:22:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id D92F2AC001 for ; Thu, 16 Jun 2016 18:22:24 -0700 (PDT) X-ASG-Debug-ID: 1466126540-04cbb01fec69630001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 6VKMymQijmMqtc6i (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1MHxe026631 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:22:18 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1MH3K011419 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:17 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MGGr023678; Fri, 17 Jun 2016 01:22:16 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:16 -0700 Subject: [PATCH 041/119] xfs: create rmap update intent log items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 041/119] xfs: create rmap update intent log items To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:22:14 -0700 Message-ID: <146612653482.12839.13343504748508270421.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126540 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 24009 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create rmap update intent/done log items to record redo information in the log. Because we need to roll transactions between updating the bmbt mapping and updating the reverse mapping, we also have to track the status of the metadata updates that will be recorded in the post-roll transactions, just in case we crash before committing the final transaction. This mechanism enables log recovery to finish what was already started. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_log_format.h | 67 ++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 19 ++ fs/xfs/xfs_rmap_item.c | 459 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_rmap_item.h | 100 +++++++++ fs/xfs/xfs_super.c | 21 ++ 6 files changed, 665 insertions(+), 2 deletions(-) create mode 100644 fs/xfs/xfs_rmap_item.c create mode 100644 fs/xfs/xfs_rmap_item.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 2de8c20..8ae0a10 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -104,6 +104,7 @@ xfs-y += xfs_log.o \ xfs_extfree_item.o \ xfs_icreate_item.o \ xfs_inode_item.o \ + xfs_rmap_item.o \ xfs_log_recover.o \ xfs_trans_ail.o \ xfs_trans_buf.o \ diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index e5baba3..b9627b7 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -110,7 +110,9 @@ static inline uint xlog_get_cycle(char *ptr) #define XLOG_REG_TYPE_COMMIT 18 #define XLOG_REG_TYPE_TRANSHDR 19 #define XLOG_REG_TYPE_ICREATE 20 -#define XLOG_REG_TYPE_MAX 20 +#define XLOG_REG_TYPE_RUI_FORMAT 21 +#define XLOG_REG_TYPE_RUD_FORMAT 22 +#define XLOG_REG_TYPE_MAX 22 /* * Flags to log operation header @@ -227,6 +229,8 @@ typedef struct xfs_trans_header { #define XFS_LI_DQUOT 0x123d #define XFS_LI_QUOTAOFF 0x123e #define XFS_LI_ICREATE 0x123f +#define XFS_LI_RUI 0x1240 /* rmap update intent */ +#define XFS_LI_RUD 0x1241 #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ @@ -236,7 +240,9 @@ typedef struct xfs_trans_header { { XFS_LI_BUF, "XFS_LI_BUF" }, \ { XFS_LI_DQUOT, "XFS_LI_DQUOT" }, \ { XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \ - { XFS_LI_ICREATE, "XFS_LI_ICREATE" } + { XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \ + { XFS_LI_RUI, "XFS_LI_RUI" }, \ + { XFS_LI_RUD, "XFS_LI_RUD" } /* * Inode Log Item Format definitions. @@ -604,6 +610,63 @@ typedef struct xfs_efd_log_format_64 { } xfs_efd_log_format_64_t; /* + * RUI/RUD (reverse mapping) log format definitions + */ +struct xfs_map_extent { + __uint64_t me_owner; + __uint64_t me_startblock; + __uint64_t me_startoff; + __uint32_t me_len; + __uint32_t me_flags; +}; + +/* rmap me_flags: upper bits are flags, lower byte is type code */ +#define XFS_RMAP_EXTENT_MAP 1 +#define XFS_RMAP_EXTENT_MAP_SHARED 2 +#define XFS_RMAP_EXTENT_UNMAP 3 +#define XFS_RMAP_EXTENT_UNMAP_SHARED 4 +#define XFS_RMAP_EXTENT_CONVERT 5 +#define XFS_RMAP_EXTENT_CONVERT_SHARED 6 +#define XFS_RMAP_EXTENT_ALLOC 7 +#define XFS_RMAP_EXTENT_FREE 8 +#define XFS_RMAP_EXTENT_TYPE_MASK 0xFF + +#define XFS_RMAP_EXTENT_ATTR_FORK (1U << 31) +#define XFS_RMAP_EXTENT_BMBT_BLOCK (1U << 30) +#define XFS_RMAP_EXTENT_UNWRITTEN (1U << 29) + +#define XFS_RMAP_EXTENT_FLAGS (XFS_RMAP_EXTENT_TYPE_MASK | \ + XFS_RMAP_EXTENT_ATTR_FORK | \ + XFS_RMAP_EXTENT_BMBT_BLOCK | \ + XFS_RMAP_EXTENT_UNWRITTEN) + +/* + * This is the structure used to lay out an rui log item in the + * log. The rui_extents field is a variable size array whose + * size is given by rui_nextents. + */ +struct xfs_rui_log_format { + __uint16_t rui_type; /* rui log item type */ + __uint16_t rui_size; /* size of this item */ + __uint32_t rui_nextents; /* # extents to free */ + __uint64_t rui_id; /* rui identifier */ + struct xfs_map_extent rui_extents[1]; /* array of extents to rmap */ +}; + +/* + * This is the structure used to lay out an rud log item in the + * log. The rud_extents array is a variable size array whose + * size is given by rud_nextents; + */ +struct xfs_rud_log_format { + __uint16_t rud_type; /* rud log item type */ + __uint16_t rud_size; /* size of this item */ + __uint32_t rud_nextents; /* # of extents freed */ + __uint64_t rud_rui_id; /* id of corresponding rui */ + struct xfs_map_extent rud_extents[1]; /* array of extents rmapped */ +}; + +/* * Dquot Log format definitions. * * The first two fields must be the type and size fitting into diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 6674340..aff60dc 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -87,4 +87,23 @@ int xfs_rmapbt_query_range(struct xfs_btree_cur *cur, struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec, xfs_rmapbt_query_range_fn fn, void *priv); +enum xfs_rmap_intent_type { + XFS_RMAP_MAP, + XFS_RMAP_MAP_SHARED, + XFS_RMAP_UNMAP, + XFS_RMAP_UNMAP_SHARED, + XFS_RMAP_CONVERT, + XFS_RMAP_CONVERT_SHARED, + XFS_RMAP_ALLOC, + XFS_RMAP_FREE, +}; + +struct xfs_rmap_intent { + struct list_head ri_list; + enum xfs_rmap_intent_type ri_type; + __uint64_t ri_owner; + int ri_whichfork; + struct xfs_bmbt_irec ri_bmap; +}; + #endif /* __XFS_RMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_rmap_item.c b/fs/xfs/xfs_rmap_item.c new file mode 100644 index 0000000..91a3b2c --- /dev/null +++ b/fs/xfs/xfs_rmap_item.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_buf_item.h" +#include "xfs_rmap_item.h" +#include "xfs_log.h" + + +kmem_zone_t *xfs_rui_zone; +kmem_zone_t *xfs_rud_zone; + +static inline struct xfs_rui_log_item *RUI_ITEM(struct xfs_log_item *lip) +{ + return container_of(lip, struct xfs_rui_log_item, rui_item); +} + +void +xfs_rui_item_free( + struct xfs_rui_log_item *ruip) +{ + if (ruip->rui_format.rui_nextents > XFS_RUI_MAX_FAST_EXTENTS) + kmem_free(ruip); + else + kmem_zone_free(xfs_rui_zone, ruip); +} + +/* + * This returns the number of iovecs needed to log the given rui item. + * We only need 1 iovec for an rui item. It just logs the rui_log_format + * structure. + */ +static inline int +xfs_rui_item_sizeof( + struct xfs_rui_log_item *ruip) +{ + return sizeof(struct xfs_rui_log_format) + + (ruip->rui_format.rui_nextents - 1) * + sizeof(struct xfs_map_extent); +} + +STATIC void +xfs_rui_item_size( + struct xfs_log_item *lip, + int *nvecs, + int *nbytes) +{ + *nvecs += 1; + *nbytes += xfs_rui_item_sizeof(RUI_ITEM(lip)); +} + +/* + * This is called to fill in the vector of log iovecs for the + * given rui log item. We use only 1 iovec, and we point that + * at the rui_log_format structure embedded in the rui item. + * It is at this point that we assert that all of the extent + * slots in the rui item have been filled. + */ +STATIC void +xfs_rui_item_format( + struct xfs_log_item *lip, + struct xfs_log_vec *lv) +{ + struct xfs_rui_log_item *ruip = RUI_ITEM(lip); + struct xfs_log_iovec *vecp = NULL; + + ASSERT(atomic_read(&ruip->rui_next_extent) == + ruip->rui_format.rui_nextents); + + ruip->rui_format.rui_type = XFS_LI_RUI; + ruip->rui_format.rui_size = 1; + + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUI_FORMAT, &ruip->rui_format, + xfs_rui_item_sizeof(ruip)); +} + +/* + * Pinning has no meaning for an rui item, so just return. + */ +STATIC void +xfs_rui_item_pin( + struct xfs_log_item *lip) +{ +} + +/* + * The unpin operation is the last place an RUI is manipulated in the log. It is + * either inserted in the AIL or aborted in the event of a log I/O error. In + * either case, the RUI transaction has been successfully committed to make it + * this far. Therefore, we expect whoever committed the RUI to either construct + * and commit the RUD or drop the RUD's reference in the event of error. Simply + * drop the log's RUI reference now that the log is done with it. + */ +STATIC void +xfs_rui_item_unpin( + struct xfs_log_item *lip, + int remove) +{ + struct xfs_rui_log_item *ruip = RUI_ITEM(lip); + + xfs_rui_release(ruip); +} + +/* + * RUI items have no locking or pushing. However, since RUIs are pulled from + * the AIL when their corresponding RUDs are committed to disk, their situation + * is very similar to being pinned. Return XFS_ITEM_PINNED so that the caller + * will eventually flush the log. This should help in getting the RUI out of + * the AIL. + */ +STATIC uint +xfs_rui_item_push( + struct xfs_log_item *lip, + struct list_head *buffer_list) +{ + return XFS_ITEM_PINNED; +} + +/* + * The RUI has been either committed or aborted if the transaction has been + * cancelled. If the transaction was cancelled, an RUD isn't going to be + * constructed and thus we free the RUI here directly. + */ +STATIC void +xfs_rui_item_unlock( + struct xfs_log_item *lip) +{ + if (lip->li_flags & XFS_LI_ABORTED) + xfs_rui_item_free(RUI_ITEM(lip)); +} + +/* + * The RUI is logged only once and cannot be moved in the log, so simply return + * the lsn at which it's been logged. + */ +STATIC xfs_lsn_t +xfs_rui_item_committed( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ + return lsn; +} + +/* + * The RUI dependency tracking op doesn't do squat. It can't because + * it doesn't know where the free extent is coming from. The dependency + * tracking has to be handled by the "enclosing" metadata object. For + * example, for inodes, the inode is locked throughout the extent freeing + * so the dependency should be recorded there. + */ +STATIC void +xfs_rui_item_committing( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ +} + +/* + * This is the ops vector shared by all rui log items. + */ +static const struct xfs_item_ops xfs_rui_item_ops = { + .iop_size = xfs_rui_item_size, + .iop_format = xfs_rui_item_format, + .iop_pin = xfs_rui_item_pin, + .iop_unpin = xfs_rui_item_unpin, + .iop_unlock = xfs_rui_item_unlock, + .iop_committed = xfs_rui_item_committed, + .iop_push = xfs_rui_item_push, + .iop_committing = xfs_rui_item_committing, +}; + +/* + * Allocate and initialize an rui item with the given number of extents. + */ +struct xfs_rui_log_item * +xfs_rui_init( + struct xfs_mount *mp, + uint nextents) + +{ + struct xfs_rui_log_item *ruip; + uint size; + + ASSERT(nextents > 0); + if (nextents > XFS_RUI_MAX_FAST_EXTENTS) { + size = (uint)(sizeof(struct xfs_rui_log_item) + + ((nextents - 1) * sizeof(struct xfs_map_extent))); + ruip = kmem_zalloc(size, KM_SLEEP); + } else { + ruip = kmem_zone_zalloc(xfs_rui_zone, KM_SLEEP); + } + + xfs_log_item_init(mp, &ruip->rui_item, XFS_LI_RUI, &xfs_rui_item_ops); + ruip->rui_format.rui_nextents = nextents; + ruip->rui_format.rui_id = (uintptr_t)(void *)ruip; + atomic_set(&ruip->rui_next_extent, 0); + atomic_set(&ruip->rui_refcount, 2); + + return ruip; +} + +/* + * Copy an RUI format buffer from the given buf, and into the destination + * RUI format structure. The RUI/RUD items were designed not to need any + * special alignment handling. + */ +int +xfs_rui_copy_format( + struct xfs_log_iovec *buf, + struct xfs_rui_log_format *dst_rui_fmt) +{ + struct xfs_rui_log_format *src_rui_fmt; + uint len; + + src_rui_fmt = buf->i_addr; + len = sizeof(struct xfs_rui_log_format) + + (src_rui_fmt->rui_nextents - 1) * + sizeof(struct xfs_map_extent); + + if (buf->i_len == len) { + memcpy((char *)dst_rui_fmt, (char *)src_rui_fmt, len); + return 0; + } + return -EFSCORRUPTED; +} + +/* + * Freeing the RUI requires that we remove it from the AIL if it has already + * been placed there. However, the RUI may not yet have been placed in the AIL + * when called by xfs_rui_release() from RUD processing due to the ordering of + * committed vs unpin operations in bulk insert operations. Hence the reference + * count to ensure only the last caller frees the RUI. + */ +void +xfs_rui_release( + struct xfs_rui_log_item *ruip) +{ + if (atomic_dec_and_test(&ruip->rui_refcount)) { + xfs_trans_ail_remove(&ruip->rui_item, SHUTDOWN_LOG_IO_ERROR); + xfs_rui_item_free(ruip); + } +} + +static inline struct xfs_rud_log_item *RUD_ITEM(struct xfs_log_item *lip) +{ + return container_of(lip, struct xfs_rud_log_item, rud_item); +} + +STATIC void +xfs_rud_item_free(struct xfs_rud_log_item *rudp) +{ + if (rudp->rud_format.rud_nextents > XFS_RUD_MAX_FAST_EXTENTS) + kmem_free(rudp); + else + kmem_zone_free(xfs_rud_zone, rudp); +} + +/* + * This returns the number of iovecs needed to log the given rud item. + * We only need 1 iovec for an rud item. It just logs the rud_log_format + * structure. + */ +static inline int +xfs_rud_item_sizeof( + struct xfs_rud_log_item *rudp) +{ + return sizeof(struct xfs_rud_log_format) + + (rudp->rud_format.rud_nextents - 1) * + sizeof(struct xfs_map_extent); +} + +STATIC void +xfs_rud_item_size( + struct xfs_log_item *lip, + int *nvecs, + int *nbytes) +{ + *nvecs += 1; + *nbytes += xfs_rud_item_sizeof(RUD_ITEM(lip)); +} + +/* + * This is called to fill in the vector of log iovecs for the + * given rud log item. We use only 1 iovec, and we point that + * at the rud_log_format structure embedded in the rud item. + * It is at this point that we assert that all of the extent + * slots in the rud item have been filled. + */ +STATIC void +xfs_rud_item_format( + struct xfs_log_item *lip, + struct xfs_log_vec *lv) +{ + struct xfs_rud_log_item *rudp = RUD_ITEM(lip); + struct xfs_log_iovec *vecp = NULL; + + ASSERT(rudp->rud_next_extent == rudp->rud_format.rud_nextents); + + rudp->rud_format.rud_type = XFS_LI_RUD; + rudp->rud_format.rud_size = 1; + + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_RUD_FORMAT, &rudp->rud_format, + xfs_rud_item_sizeof(rudp)); +} + +/* + * Pinning has no meaning for an rud item, so just return. + */ +STATIC void +xfs_rud_item_pin( + struct xfs_log_item *lip) +{ +} + +/* + * Since pinning has no meaning for an rud item, unpinning does + * not either. + */ +STATIC void +xfs_rud_item_unpin( + struct xfs_log_item *lip, + int remove) +{ +} + +/* + * There isn't much you can do to push on an rud item. It is simply stuck + * waiting for the log to be flushed to disk. + */ +STATIC uint +xfs_rud_item_push( + struct xfs_log_item *lip, + struct list_head *buffer_list) +{ + return XFS_ITEM_PINNED; +} + +/* + * The RUD is either committed or aborted if the transaction is cancelled. If + * the transaction is cancelled, drop our reference to the RUI and free the + * RUD. + */ +STATIC void +xfs_rud_item_unlock( + struct xfs_log_item *lip) +{ + struct xfs_rud_log_item *rudp = RUD_ITEM(lip); + + if (lip->li_flags & XFS_LI_ABORTED) { + xfs_rui_release(rudp->rud_ruip); + xfs_rud_item_free(rudp); + } +} + +/* + * When the rud item is committed to disk, all we need to do is delete our + * reference to our partner rui item and then free ourselves. Since we're + * freeing ourselves we must return -1 to keep the transaction code from + * further referencing this item. + */ +STATIC xfs_lsn_t +xfs_rud_item_committed( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ + struct xfs_rud_log_item *rudp = RUD_ITEM(lip); + + /* + * Drop the RUI reference regardless of whether the RUD has been + * aborted. Once the RUD transaction is constructed, it is the sole + * responsibility of the RUD to release the RUI (even if the RUI is + * aborted due to log I/O error). + */ + xfs_rui_release(rudp->rud_ruip); + xfs_rud_item_free(rudp); + + return (xfs_lsn_t)-1; +} + +/* + * The RUD dependency tracking op doesn't do squat. It can't because + * it doesn't know where the free extent is coming from. The dependency + * tracking has to be handled by the "enclosing" metadata object. For + * example, for inodes, the inode is locked throughout the extent freeing + * so the dependency should be recorded there. + */ +STATIC void +xfs_rud_item_committing( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ +} + +/* + * This is the ops vector shared by all rud log items. + */ +static const struct xfs_item_ops xfs_rud_item_ops = { + .iop_size = xfs_rud_item_size, + .iop_format = xfs_rud_item_format, + .iop_pin = xfs_rud_item_pin, + .iop_unpin = xfs_rud_item_unpin, + .iop_unlock = xfs_rud_item_unlock, + .iop_committed = xfs_rud_item_committed, + .iop_push = xfs_rud_item_push, + .iop_committing = xfs_rud_item_committing, +}; + +/* + * Allocate and initialize an rud item with the given number of extents. + */ +struct xfs_rud_log_item * +xfs_rud_init( + struct xfs_mount *mp, + struct xfs_rui_log_item *ruip, + uint nextents) + +{ + struct xfs_rud_log_item *rudp; + uint size; + + ASSERT(nextents > 0); + if (nextents > XFS_RUD_MAX_FAST_EXTENTS) { + size = (uint)(sizeof(struct xfs_rud_log_item) + + ((nextents - 1) * sizeof(struct xfs_map_extent))); + rudp = kmem_zalloc(size, KM_SLEEP); + } else { + rudp = kmem_zone_zalloc(xfs_rud_zone, KM_SLEEP); + } + + xfs_log_item_init(mp, &rudp->rud_item, XFS_LI_RUD, &xfs_rud_item_ops); + rudp->rud_ruip = ruip; + rudp->rud_format.rud_nextents = nextents; + rudp->rud_format.rud_rui_id = ruip->rui_format.rui_id; + + return rudp; +} diff --git a/fs/xfs/xfs_rmap_item.h b/fs/xfs/xfs_rmap_item.h new file mode 100644 index 0000000..bd36ab5 --- /dev/null +++ b/fs/xfs/xfs_rmap_item.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_RMAP_ITEM_H__ +#define __XFS_RMAP_ITEM_H__ + +/* + * There are (currently) three pairs of rmap btree redo item types: map, unmap, + * and convert. The common abbreviations for these are RUI (rmap update + * intent) and RUD (rmap update done). The redo item type is encoded in the + * flags field of each xfs_map_extent. + * + * *I items should be recorded in the *first* of a series of rolled + * transactions, and the *D items should be recorded in the same transaction + * that records the associated rmapbt updates. Typically, the first + * transaction will record a bmbt update, followed by some number of + * transactions containing rmapbt updates, and finally transactions with any + * bnobt/cntbt updates. + * + * Should the system crash after the commit of the first transaction but + * before the commit of the final transaction in a series, log recovery will + * use the redo information recorded by the intent items to replay the + * (rmapbt/bnobt/cntbt) metadata updates in the non-first transaction. + */ + +/* kernel only RUI/RUD definitions */ + +struct xfs_mount; +struct kmem_zone; + +/* + * Max number of extents in fast allocation path. + */ +#define XFS_RUI_MAX_FAST_EXTENTS 16 + +/* + * Define RUI flag bits. Manipulated by set/clear/test_bit operators. + */ +#define XFS_RUI_RECOVERED 1 + +/* + * This is the "rmap update intent" log item. It is used to log the fact that + * some reverse mappings need to change. It is used in conjunction with the + * "rmap update done" log item described below. + * + * These log items follow the same rules as struct xfs_efi_log_item; see the + * comments about that structure (in xfs_extfree_item.h) for more details. + */ +struct xfs_rui_log_item { + struct xfs_log_item rui_item; + atomic_t rui_refcount; + atomic_t rui_next_extent; + unsigned long rui_flags; /* misc flags */ + struct xfs_rui_log_format rui_format; +}; + +/* + * This is the "rmap update done" log item. It is used to log the fact that + * some rmapbt updates mentioned in an earlier rui item have been performed. + */ +struct xfs_rud_log_item { + struct xfs_log_item rud_item; + struct xfs_rui_log_item *rud_ruip; + uint rud_next_extent; + struct xfs_rud_log_format rud_format; +}; + +/* + * Max number of extents in fast allocation path. + */ +#define XFS_RUD_MAX_FAST_EXTENTS 16 + +extern struct kmem_zone *xfs_rui_zone; +extern struct kmem_zone *xfs_rud_zone; + +struct xfs_rui_log_item *xfs_rui_init(struct xfs_mount *, uint); +struct xfs_rud_log_item *xfs_rud_init(struct xfs_mount *, + struct xfs_rui_log_item *, uint); +int xfs_rui_copy_format(struct xfs_log_iovec *buf, + struct xfs_rui_log_format *dst_rui_fmt); +void xfs_rui_item_free(struct xfs_rui_log_item *); +void xfs_rui_release(struct xfs_rui_log_item *); + +#endif /* __XFS_RMAP_ITEM_H__ */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 1575849..a8300e4 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -47,6 +47,7 @@ #include "xfs_sysfs.h" #include "xfs_ondisk.h" #include "xfs_defer.h" +#include "xfs_rmap_item.h" #include #include @@ -1762,8 +1763,26 @@ xfs_init_zones(void) if (!xfs_icreate_zone) goto out_destroy_ili_zone; + xfs_rud_zone = kmem_zone_init((sizeof(struct xfs_rud_log_item) + + ((XFS_RUD_MAX_FAST_EXTENTS - 1) * + sizeof(struct xfs_map_extent))), + "xfs_rud_item"); + if (!xfs_rud_zone) + goto out_destroy_icreate_zone; + + xfs_rui_zone = kmem_zone_init((sizeof(struct xfs_rui_log_item) + + ((XFS_RUI_MAX_FAST_EXTENTS - 1) * + sizeof(struct xfs_map_extent))), + "xfs_rui_item"); + if (!xfs_rui_zone) + goto out_destroy_rud_zone; + return 0; + out_destroy_rud_zone: + kmem_zone_destroy(xfs_rud_zone); + out_destroy_icreate_zone: + kmem_zone_destroy(xfs_icreate_zone); out_destroy_ili_zone: kmem_zone_destroy(xfs_ili_zone); out_destroy_inode_zone: @@ -1802,6 +1821,8 @@ xfs_destroy_zones(void) * destroy caches. */ rcu_barrier(); + kmem_zone_destroy(xfs_rui_zone); + kmem_zone_destroy(xfs_rud_zone); kmem_zone_destroy(xfs_icreate_zone); kmem_zone_destroy(xfs_ili_zone); kmem_zone_destroy(xfs_inode_zone); From darrick.wong@oracle.com Thu Jun 16 20:22:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_LOLITA1, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 69BFF7DB3 for ; Thu, 16 Jun 2016 20:22:32 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3AA918F804B for ; Thu, 16 Jun 2016 18:22:32 -0700 (PDT) X-ASG-Debug-ID: 1466126548-04cbb01fed69650001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id VzYRQG76az85qaZR (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:28 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1MPRY007435 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:25 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MNTf018149 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:24 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1MNlO027871; Fri, 17 Jun 2016 01:22:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:22 -0700 Subject: [PATCH 042/119] xfs: log rmap intent items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 042/119] xfs: log rmap intent items To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:22:21 -0700 Message-ID: <146612654128.12839.11872963796909332527.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126548 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 22034 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a mechanism for higher levels to create RUI/RUD items, submit them to the log, and a stub function to deal with recovered RUI items. These parts will be connected to the rmapbt in a later patch. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/xfs_log_recover.c | 344 +++++++++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_trans.h | 17 ++ fs/xfs/xfs_trans_rmap.c | 235 +++++++++++++++++++++++++++++++ 4 files changed, 589 insertions(+), 8 deletions(-) create mode 100644 fs/xfs/xfs_trans_rmap.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 8ae0a10..1980110 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -110,6 +110,7 @@ xfs-y += xfs_log.o \ xfs_trans_buf.o \ xfs_trans_extfree.o \ xfs_trans_inode.o \ + xfs_trans_rmap.o \ # optional features xfs-$(CONFIG_XFS_QUOTA) += xfs_dquot.o \ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index b33187b..c9fe0c4 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -44,6 +44,7 @@ #include "xfs_bmap_btree.h" #include "xfs_error.h" #include "xfs_dir2.h" +#include "xfs_rmap_item.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) @@ -1912,6 +1913,8 @@ xlog_recover_reorder_trans( case XFS_LI_QUOTAOFF: case XFS_LI_EFD: case XFS_LI_EFI: + case XFS_LI_RUI: + case XFS_LI_RUD: trace_xfs_log_recover_item_reorder_tail(log, trans, item, pass); list_move_tail(&item->ri_list, &inode_list); @@ -3416,6 +3419,101 @@ xlog_recover_efd_pass2( } /* + * This routine is called to create an in-core extent rmap update + * item from the rui format structure which was logged on disk. + * It allocates an in-core rui, copies the extents from the format + * structure into it, and adds the rui to the AIL with the given + * LSN. + */ +STATIC int +xlog_recover_rui_pass2( + struct xlog *log, + struct xlog_recover_item *item, + xfs_lsn_t lsn) +{ + int error; + struct xfs_mount *mp = log->l_mp; + struct xfs_rui_log_item *ruip; + struct xfs_rui_log_format *rui_formatp; + + rui_formatp = item->ri_buf[0].i_addr; + + ruip = xfs_rui_init(mp, rui_formatp->rui_nextents); + error = xfs_rui_copy_format(&item->ri_buf[0], &ruip->rui_format); + if (error) { + xfs_rui_item_free(ruip); + return error; + } + atomic_set(&ruip->rui_next_extent, rui_formatp->rui_nextents); + + spin_lock(&log->l_ailp->xa_lock); + /* + * The RUI has two references. One for the RUD and one for RUI to ensure + * it makes it into the AIL. Insert the RUI into the AIL directly and + * drop the RUI reference. Note that xfs_trans_ail_update() drops the + * AIL lock. + */ + xfs_trans_ail_update(log->l_ailp, &ruip->rui_item, lsn); + xfs_rui_release(ruip); + return 0; +} + + +/* + * This routine is called when an RUD format structure is found in a committed + * transaction in the log. Its purpose is to cancel the corresponding RUI if it + * was still in the log. To do this it searches the AIL for the RUI with an id + * equal to that in the RUD format structure. If we find it we drop the RUD + * reference, which removes the RUI from the AIL and frees it. + */ +STATIC int +xlog_recover_rud_pass2( + struct xlog *log, + struct xlog_recover_item *item) +{ + struct xfs_rud_log_format *rud_formatp; + struct xfs_rui_log_item *ruip = NULL; + struct xfs_log_item *lip; + __uint64_t rui_id; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp = log->l_ailp; + + rud_formatp = item->ri_buf[0].i_addr; + ASSERT(item->ri_buf[0].i_len == (sizeof(struct xfs_rud_log_format) + + ((rud_formatp->rud_nextents - 1) * + sizeof(struct xfs_map_extent)))); + rui_id = rud_formatp->rud_rui_id; + + /* + * Search for the RUI with the id in the RUD format structure in the + * AIL. + */ + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + if (lip->li_type == XFS_LI_RUI) { + ruip = (struct xfs_rui_log_item *)lip; + if (ruip->rui_format.rui_id == rui_id) { + /* + * Drop the RUD reference to the RUI. This + * removes the RUI from the AIL and frees it. + */ + spin_unlock(&ailp->xa_lock); + xfs_rui_release(ruip); + spin_lock(&ailp->xa_lock); + break; + } + } + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } + + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + + return 0; +} + +/* * This routine is called when an inode create format structure is found in a * committed transaction in the log. It's purpose is to initialise the inodes * being allocated on disk. This requires us to get inode cluster buffers that @@ -3640,6 +3738,8 @@ xlog_recover_ra_pass2( case XFS_LI_EFI: case XFS_LI_EFD: case XFS_LI_QUOTAOFF: + case XFS_LI_RUI: + case XFS_LI_RUD: default: break; } @@ -3663,6 +3763,8 @@ xlog_recover_commit_pass1( case XFS_LI_EFD: case XFS_LI_DQUOT: case XFS_LI_ICREATE: + case XFS_LI_RUI: + case XFS_LI_RUD: /* nothing to do in pass 1 */ return 0; default: @@ -3693,6 +3795,10 @@ xlog_recover_commit_pass2( return xlog_recover_efi_pass2(log, item, trans->r_lsn); case XFS_LI_EFD: return xlog_recover_efd_pass2(log, item); + case XFS_LI_RUI: + return xlog_recover_rui_pass2(log, item, trans->r_lsn); + case XFS_LI_RUD: + return xlog_recover_rud_pass2(log, item); case XFS_LI_DQUOT: return xlog_recover_dquot_pass2(log, buffer_list, item, trans->r_lsn); @@ -4165,6 +4271,18 @@ xlog_recover_process_data( return 0; } +/* Is this log item a deferred action intent? */ +static inline bool xlog_item_is_intent(struct xfs_log_item *lip) +{ + switch (lip->li_type) { + case XFS_LI_EFI: + case XFS_LI_RUI: + return true; + default: + return false; + } +} + /* * Process an extent free intent item that was recovered from * the log. We need to free the extents that it describes. @@ -4265,17 +4383,23 @@ xlog_recover_process_efis( lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); while (lip != NULL) { /* - * We're done when we see something other than an EFI. - * There should be no EFIs left in the AIL now. + * We're done when we see something other than an intent. + * There should be no intents left in the AIL now. */ - if (lip->li_type != XFS_LI_EFI) { + if (!xlog_item_is_intent(lip)) { #ifdef DEBUG for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) - ASSERT(lip->li_type != XFS_LI_EFI); + ASSERT(!xlog_item_is_intent(lip)); #endif break; } + /* Skip anything that isn't an EFI */ + if (lip->li_type != XFS_LI_EFI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + /* * Skip EFIs that we've already processed. */ @@ -4320,14 +4444,20 @@ xlog_recover_cancel_efis( * We're done when we see something other than an EFI. * There should be no EFIs left in the AIL now. */ - if (lip->li_type != XFS_LI_EFI) { + if (!xlog_item_is_intent(lip)) { #ifdef DEBUG for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) - ASSERT(lip->li_type != XFS_LI_EFI); + ASSERT(!xlog_item_is_intent(lip)); #endif break; } + /* Skip anything that isn't an EFI */ + if (lip->li_type != XFS_LI_EFI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + efip = container_of(lip, struct xfs_efi_log_item, efi_item); spin_unlock(&ailp->xa_lock); @@ -4343,6 +4473,190 @@ xlog_recover_cancel_efis( } /* + * Process an rmap update intent item that was recovered from the log. + * We need to update the rmapbt. + */ +STATIC int +xlog_recover_process_rui( + struct xfs_mount *mp, + struct xfs_rui_log_item *ruip) +{ + int i; + int error = 0; + struct xfs_map_extent *rmap; + xfs_fsblock_t startblock_fsb; + bool op_ok; + + ASSERT(!test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags)); + + /* + * First check the validity of the extents described by the + * RUI. If any are bad, then assume that all are bad and + * just toss the RUI. + */ + for (i = 0; i < ruip->rui_format.rui_nextents; i++) { + rmap = &(ruip->rui_format.rui_extents[i]); + startblock_fsb = XFS_BB_TO_FSB(mp, + XFS_FSB_TO_DADDR(mp, rmap->me_startblock)); + switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) { + case XFS_RMAP_EXTENT_MAP: + case XFS_RMAP_EXTENT_MAP_SHARED: + case XFS_RMAP_EXTENT_UNMAP: + case XFS_RMAP_EXTENT_UNMAP_SHARED: + case XFS_RMAP_EXTENT_CONVERT: + case XFS_RMAP_EXTENT_CONVERT_SHARED: + case XFS_RMAP_EXTENT_ALLOC: + case XFS_RMAP_EXTENT_FREE: + op_ok = true; + break; + default: + op_ok = false; + break; + } + if (!op_ok || (startblock_fsb == 0) || + (rmap->me_len == 0) || + (startblock_fsb >= mp->m_sb.sb_dblocks) || + (rmap->me_len >= mp->m_sb.sb_agblocks) || + (rmap->me_flags & ~XFS_RMAP_EXTENT_FLAGS)) { + /* + * This will pull the RUI from the AIL and + * free the memory associated with it. + */ + set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags); + xfs_rui_release(ruip); + return -EIO; + } + } + + /* XXX: do nothing for now */ + set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags); + xfs_rui_release(ruip); + return error; +} + +/* + * When this is called, all of the RUIs which did not have + * corresponding RUDs should be in the AIL. What we do now + * is update the rmaps associated with each one. + * + * Since we process the RUIs in normal transactions, they + * will be removed at some point after the commit. This prevents + * us from just walking down the list processing each one. + * We'll use a flag in the RUI to skip those that we've already + * processed and use the AIL iteration mechanism's generation + * count to try to speed this up at least a bit. + * + * When we start, we know that the RUIs are the only things in + * the AIL. As we process them, however, other items are added + * to the AIL. Since everything added to the AIL must come after + * everything already in the AIL, we stop processing as soon as + * we see something other than an RUI in the AIL. + */ +STATIC int +xlog_recover_process_ruis( + struct xlog *log) +{ + struct xfs_log_item *lip; + struct xfs_rui_log_item *ruip; + int error = 0; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp; + + ailp = log->l_ailp; + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + /* + * We're done when we see something other than an intent. + * There should be no intents left in the AIL now. + */ + if (!xlog_item_is_intent(lip)) { +#ifdef DEBUG + for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) + ASSERT(!xlog_item_is_intent(lip)); +#endif + break; + } + + /* Skip anything that isn't an RUI */ + if (lip->li_type != XFS_LI_RUI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + /* + * Skip RUIs that we've already processed. + */ + ruip = container_of(lip, struct xfs_rui_log_item, rui_item); + if (test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags)) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + spin_unlock(&ailp->xa_lock); + error = xlog_recover_process_rui(log->l_mp, ruip); + spin_lock(&ailp->xa_lock); + if (error) + goto out; + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } +out: + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + return error; +} + +/* + * A cancel occurs when the mount has failed and we're bailing out. Release all + * pending RUIs so they don't pin the AIL. + */ +STATIC int +xlog_recover_cancel_ruis( + struct xlog *log) +{ + struct xfs_log_item *lip; + struct xfs_rui_log_item *ruip; + int error = 0; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp; + + ailp = log->l_ailp; + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + /* + * We're done when we see something other than an RUI. + * There should be no RUIs left in the AIL now. + */ + if (!xlog_item_is_intent(lip)) { +#ifdef DEBUG + for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) + ASSERT(!xlog_item_is_intent(lip)); +#endif + break; + } + + /* Skip anything that isn't an RUI */ + if (lip->li_type != XFS_LI_RUI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + ruip = container_of(lip, struct xfs_rui_log_item, rui_item); + + spin_unlock(&ailp->xa_lock); + xfs_rui_release(ruip); + spin_lock(&ailp->xa_lock); + + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } + + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + return error; +} + +/* * This routine performs a transaction to null out a bad inode pointer * in an agi unlinked inode hash bucket. */ @@ -5144,11 +5458,19 @@ xlog_recover_finish( */ if (log->l_flags & XLOG_RECOVERY_NEEDED) { int error; + + error = xlog_recover_process_ruis(log); + if (error) { + xfs_alert(log->l_mp, "Failed to recover RUIs"); + return error; + } + error = xlog_recover_process_efis(log); if (error) { xfs_alert(log->l_mp, "Failed to recover EFIs"); return error; } + /* * Sync the log to get all the EFIs out of the AIL. * This isn't absolutely necessary, but it helps in @@ -5176,9 +5498,15 @@ xlog_recover_cancel( struct xlog *log) { int error = 0; + int err2; - if (log->l_flags & XLOG_RECOVERY_NEEDED) - error = xlog_recover_cancel_efis(log); + if (log->l_flags & XLOG_RECOVERY_NEEDED) { + error = xlog_recover_cancel_ruis(log); + + err2 = xlog_recover_cancel_efis(log); + if (err2 && !error) + error = err2; + } return error; } diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index f8d363f..c48be63 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -235,4 +235,21 @@ void xfs_trans_buf_copy_type(struct xfs_buf *dst_bp, extern kmem_zone_t *xfs_trans_zone; extern kmem_zone_t *xfs_log_item_desc_zone; +enum xfs_rmap_intent_type; + +struct xfs_rui_log_item *xfs_trans_get_rui(struct xfs_trans *tp, uint nextents); +void xfs_trans_log_start_rmap_update(struct xfs_trans *tp, + struct xfs_rui_log_item *ruip, enum xfs_rmap_intent_type type, + __uint64_t owner, int whichfork, xfs_fileoff_t startoff, + xfs_fsblock_t startblock, xfs_filblks_t blockcount, + xfs_exntst_t state); + +struct xfs_rud_log_item *xfs_trans_get_rud(struct xfs_trans *tp, + struct xfs_rui_log_item *ruip, uint nextents); +int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp, + struct xfs_rud_log_item *rudp, enum xfs_rmap_intent_type type, + __uint64_t owner, int whichfork, xfs_fileoff_t startoff, + xfs_fsblock_t startblock, xfs_filblks_t blockcount, + xfs_exntst_t state); + #endif /* __XFS_TRANS_H__ */ diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c new file mode 100644 index 0000000..b55a725 --- /dev/null +++ b/fs/xfs/xfs_trans_rmap.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_rmap_item.h" +#include "xfs_alloc.h" +#include "xfs_rmap_btree.h" + +/* + * This routine is called to allocate an "rmap update intent" + * log item that will hold nextents worth of extents. The + * caller must use all nextents extents, because we are not + * flexible about this at all. + */ +struct xfs_rui_log_item * +xfs_trans_get_rui( + struct xfs_trans *tp, + uint nextents) +{ + struct xfs_rui_log_item *ruip; + + ASSERT(tp != NULL); + ASSERT(nextents > 0); + + ruip = xfs_rui_init(tp->t_mountp, nextents); + ASSERT(ruip != NULL); + + /* + * Get a log_item_desc to point at the new item. + */ + xfs_trans_add_item(tp, &ruip->rui_item); + return ruip; +} + +/* + * This routine is called to indicate that the described + * extent is to be logged as needing to be freed. It should + * be called once for each extent to be freed. + */ +void +xfs_trans_log_start_rmap_update( + struct xfs_trans *tp, + struct xfs_rui_log_item *ruip, + enum xfs_rmap_intent_type type, + __uint64_t owner, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state) +{ + uint next_extent; + struct xfs_map_extent *rmap; + + tp->t_flags |= XFS_TRANS_DIRTY; + ruip->rui_item.li_desc->lid_flags |= XFS_LID_DIRTY; + + /* + * atomic_inc_return gives us the value after the increment; + * we want to use it as an array index so we need to subtract 1 from + * it. + */ + next_extent = atomic_inc_return(&ruip->rui_next_extent) - 1; + ASSERT(next_extent < ruip->rui_format.rui_nextents); + rmap = &(ruip->rui_format.rui_extents[next_extent]); + rmap->me_owner = owner; + rmap->me_startblock = startblock; + rmap->me_startoff = startoff; + rmap->me_len = blockcount; + rmap->me_flags = 0; + if (state == XFS_EXT_UNWRITTEN) + rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN; + if (whichfork == XFS_ATTR_FORK) + rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK; + switch (type) { + case XFS_RMAP_MAP: + rmap->me_flags |= XFS_RMAP_EXTENT_MAP; + break; + case XFS_RMAP_MAP_SHARED: + rmap->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED; + break; + case XFS_RMAP_UNMAP: + rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP; + break; + case XFS_RMAP_UNMAP_SHARED: + rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED; + break; + case XFS_RMAP_CONVERT: + rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT; + break; + case XFS_RMAP_CONVERT_SHARED: + rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED; + break; + case XFS_RMAP_ALLOC: + rmap->me_flags |= XFS_RMAP_EXTENT_ALLOC; + break; + case XFS_RMAP_FREE: + rmap->me_flags |= XFS_RMAP_EXTENT_FREE; + break; + default: + ASSERT(0); + } +} + + +/* + * This routine is called to allocate an "extent free done" + * log item that will hold nextents worth of extents. The + * caller must use all nextents extents, because we are not + * flexible about this at all. + */ +struct xfs_rud_log_item * +xfs_trans_get_rud( + struct xfs_trans *tp, + struct xfs_rui_log_item *ruip, + uint nextents) +{ + struct xfs_rud_log_item *rudp; + + ASSERT(tp != NULL); + ASSERT(nextents > 0); + + rudp = xfs_rud_init(tp->t_mountp, ruip, nextents); + ASSERT(rudp != NULL); + + /* + * Get a log_item_desc to point at the new item. + */ + xfs_trans_add_item(tp, &rudp->rud_item); + return rudp; +} + +/* + * Finish an rmap update and log it to the RUD. Note that the transaction is + * marked dirty regardless of whether the rmap update succeeds or fails to + * support the RUI/RUD lifecycle rules. + */ +int +xfs_trans_log_finish_rmap_update( + struct xfs_trans *tp, + struct xfs_rud_log_item *rudp, + enum xfs_rmap_intent_type type, + __uint64_t owner, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state) +{ + uint next_extent; + struct xfs_map_extent *rmap; + int error; + + /* XXX: actually finish the rmap update here */ + error = -EFSCORRUPTED; + + /* + * Mark the transaction dirty, even on error. This ensures the + * transaction is aborted, which: + * + * 1.) releases the RUI and frees the RUD + * 2.) shuts down the filesystem + */ + tp->t_flags |= XFS_TRANS_DIRTY; + rudp->rud_item.li_desc->lid_flags |= XFS_LID_DIRTY; + + next_extent = rudp->rud_next_extent; + ASSERT(next_extent < rudp->rud_format.rud_nextents); + rmap = &(rudp->rud_format.rud_extents[next_extent]); + rmap->me_owner = owner; + rmap->me_startblock = startblock; + rmap->me_startoff = startoff; + rmap->me_len = blockcount; + rmap->me_flags = 0; + if (state == XFS_EXT_UNWRITTEN) + rmap->me_flags |= XFS_RMAP_EXTENT_UNWRITTEN; + if (whichfork == XFS_ATTR_FORK) + rmap->me_flags |= XFS_RMAP_EXTENT_ATTR_FORK; + switch (type) { + case XFS_RMAP_MAP: + rmap->me_flags |= XFS_RMAP_EXTENT_MAP; + break; + case XFS_RMAP_MAP_SHARED: + rmap->me_flags |= XFS_RMAP_EXTENT_MAP_SHARED; + break; + case XFS_RMAP_UNMAP: + rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP; + break; + case XFS_RMAP_UNMAP_SHARED: + rmap->me_flags |= XFS_RMAP_EXTENT_UNMAP_SHARED; + break; + case XFS_RMAP_CONVERT: + rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT; + break; + case XFS_RMAP_CONVERT_SHARED: + rmap->me_flags |= XFS_RMAP_EXTENT_CONVERT_SHARED; + break; + case XFS_RMAP_ALLOC: + rmap->me_flags |= XFS_RMAP_EXTENT_ALLOC; + break; + case XFS_RMAP_FREE: + rmap->me_flags |= XFS_RMAP_EXTENT_FREE; + break; + default: + ASSERT(0); + } + rudp->rud_next_extent++; + + return error; +} From darrick.wong@oracle.com Thu Jun 16 20:22:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D99077CA7 for ; Thu, 16 Jun 2016 20:22:46 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 60816AC002 for ; Thu, 16 Jun 2016 18:22:46 -0700 (PDT) X-ASG-Debug-ID: 1466126552-04bdf01e13959c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id UlTE9mbw5neh1sd2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:32 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1MUdd026714 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:30 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MTse014077 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:29 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1MTZj027882; Fri, 17 Jun 2016 01:22:29 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:29 -0700 Subject: [PATCH 043/119] xfs: enable the xfs_defer mechanism to process rmaps to update From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 043/119] xfs: enable the xfs_defer mechanism to process rmaps to update To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:22:27 -0700 Message-ID: <146612654775.12839.16417290544621580173.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126552 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4630 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Connect the xfs_defer mechanism with the pieces that we'll need to handle deferred rmap updates. We'll wire up the existing code to our new deferred mechanism later. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.h | 1 fs/xfs/xfs_defer_item.c | 124 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 743fc32..920642e62 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_RMAP, XFS_DEFER_OPS_TYPE_FREE, XFS_DEFER_OPS_TYPE_MAX, }; diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c index 1c2d556..dbd10fc 100644 --- a/fs/xfs/xfs_defer_item.c +++ b/fs/xfs/xfs_defer_item.c @@ -31,6 +31,8 @@ #include "xfs_trace.h" #include "xfs_bmap.h" #include "xfs_extfree_item.h" +#include "xfs_rmap_btree.h" +#include "xfs_rmap_item.h" /* Extent Freeing */ @@ -136,11 +138,133 @@ const struct xfs_defer_op_type xfs_extent_free_defer_type = { .cancel_item = xfs_bmap_free_cancel_item, }; +/* Reverse Mapping */ + +/* Sort rmap intents by AG. */ +static int +xfs_rmap_update_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_mount *mp = priv; + struct xfs_rmap_intent *ra; + struct xfs_rmap_intent *rb; + + ra = container_of(a, struct xfs_rmap_intent, ri_list); + rb = container_of(b, struct xfs_rmap_intent, ri_list); + return XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) - + XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock); +} + +/* Get an RUI. */ +STATIC void * +xfs_rmap_update_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return xfs_trans_get_rui(tp, count); +} + +/* Log rmap updates in the intent item. */ +STATIC void +xfs_rmap_update_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ + struct xfs_rmap_intent *rmap; + + rmap = container_of(item, struct xfs_rmap_intent, ri_list); + xfs_trans_log_start_rmap_update(tp, intent, rmap->ri_type, + rmap->ri_owner, rmap->ri_whichfork, + rmap->ri_bmap.br_startoff, + rmap->ri_bmap.br_startblock, + rmap->ri_bmap.br_blockcount, + rmap->ri_bmap.br_state); +} + +/* Get an RUD so we can process all the deferred rmap updates. */ +STATIC void * +xfs_rmap_update_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return xfs_trans_get_rud(tp, intent, count); +} + +/* Process a deferred rmap update. */ +STATIC int +xfs_rmap_update_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + struct xfs_rmap_intent *rmap; + int error; + + rmap = container_of(item, struct xfs_rmap_intent, ri_list); + error = xfs_trans_log_finish_rmap_update(tp, done_item, + rmap->ri_type, + rmap->ri_owner, rmap->ri_whichfork, + rmap->ri_bmap.br_startoff, + rmap->ri_bmap.br_startblock, + rmap->ri_bmap.br_blockcount, + rmap->ri_bmap.br_state); + kmem_free(rmap); + return error; +} + +/* Clean up after processing deferred rmaps. */ +STATIC void +xfs_rmap_update_finish_cleanup( + struct xfs_trans *tp, + void *state, + int error) +{ +} + +/* Abort all pending RUIs. */ +STATIC void +xfs_rmap_update_abort_intent( + void *intent) +{ + xfs_rui_release(intent); +} + +/* Cancel a deferred rmap update. */ +STATIC void +xfs_rmap_update_cancel_item( + struct list_head *item) +{ + struct xfs_rmap_intent *rmap; + + rmap = container_of(item, struct xfs_rmap_intent, ri_list); + kmem_free(rmap); +} + +const struct xfs_defer_op_type xfs_rmap_update_defer_type = { + .type = XFS_DEFER_OPS_TYPE_RMAP, + .max_items = XFS_RUI_MAX_FAST_EXTENTS, + .diff_items = xfs_rmap_update_diff_items, + .create_intent = xfs_rmap_update_create_intent, + .abort_intent = xfs_rmap_update_abort_intent, + .log_item = xfs_rmap_update_log_item, + .create_done = xfs_rmap_update_create_done, + .finish_item = xfs_rmap_update_finish_item, + .finish_cleanup = xfs_rmap_update_finish_cleanup, + .cancel_item = xfs_rmap_update_cancel_item, +}; + /* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_rmap_update_defer_type); xfs_defer_init_op_type(&xfs_extent_free_defer_type); } From darrick.wong@oracle.com Thu Jun 16 20:22:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C015A7CA7 for ; Thu, 16 Jun 2016 20:22:47 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 717798F804B for ; Thu, 16 Jun 2016 18:22:47 -0700 (PDT) X-ASG-Debug-ID: 1466126561-04bdf01e15959e0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id FiACyEnScjJx907E (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:41 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1MbAZ007498 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:38 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Mbe5007674 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:37 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MaTI023775; Fri, 17 Jun 2016 01:22:36 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:35 -0700 Subject: [PATCH 044/119] xfs: propagate bmap updates to rmapbt From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 044/119] xfs: propagate bmap updates to rmapbt To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:22:34 -0700 Message-ID: <146612655409.12839.4069768871045909071.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126561 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19188 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we map, unmap, or convert an extent in a file's data or attr fork, schedule a respective update in the rmapbt. Previous versions of this patch required a 1:1 correspondence between bmap and rmap, but this is no longer true. v2: Remove the 1:1 correspondence requirement now that we have the ability to make interval queries against the rmapbt. Update the commit message to reflect the broad restructuring of this patch. Fix the bmap shift code to adjust the rmaps correctly. v3: Use the deferred operations code to handle redo operations atomically and deadlock free. Plumb in all five rmap actions (map, unmap, convert extent, alloc, free); we'll use the first three now for file data, and reflink will want the last two. Add an error injection site to test log recovery. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 56 ++++++++- fs/xfs/libxfs/xfs_rmap.c | 252 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 24 ++++ fs/xfs/xfs_bmap_util.c | 1 fs/xfs/xfs_defer_item.c | 6 + fs/xfs/xfs_error.h | 4 - fs/xfs/xfs_log_recover.c | 56 +++++++++ fs/xfs/xfs_trans.h | 3 fs/xfs/xfs_trans_rmap.c | 7 + 9 files changed, 393 insertions(+), 16 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 61c0231..507fd74 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -46,6 +46,7 @@ #include "xfs_symlink.h" #include "xfs_attr_leaf.h" #include "xfs_filestream.h" +#include "xfs_rmap_btree.h" kmem_zone_t *xfs_bmap_free_item_zone; @@ -2178,6 +2179,11 @@ xfs_bmap_add_extent_delay_real( ASSERT(0); } + /* add reverse mapping */ + error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new); + if (error) + goto done; + /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(bma->ip, whichfork)) { int tmp_logflags; /* partial log flag return val */ @@ -2714,6 +2720,11 @@ xfs_bmap_add_extent_unwritten_real( ASSERT(0); } + /* update reverse mappings */ + error = xfs_rmap_convert_extent(mp, dfops, ip, XFS_DATA_FORK, new); + if (error) + goto done; + /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) { int tmp_logflags; /* partial log flag return val */ @@ -3106,6 +3117,11 @@ xfs_bmap_add_extent_hole_real( break; } + /* add reverse mapping */ + error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new); + if (error) + goto done; + /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(bma->ip, whichfork)) { int tmp_logflags; /* partial log flag return val */ @@ -5032,6 +5048,14 @@ xfs_bmap_del_extent( ++*idx; break; } + + /* remove reverse mapping */ + if (!delay) { + error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del); + if (error) + goto done; + } + /* * If we need to, add to list of extents to delete. */ @@ -5569,7 +5593,8 @@ xfs_bmse_shift_one( struct xfs_bmbt_rec_host *gotp, struct xfs_btree_cur *cur, int *logflags, - enum shift_direction direction) + enum shift_direction direction, + struct xfs_defer_ops *dfops) { struct xfs_ifork *ifp; struct xfs_mount *mp; @@ -5617,9 +5642,13 @@ xfs_bmse_shift_one( /* check whether to merge the extent or shift it down */ if (xfs_bmse_can_merge(&adj_irec, &got, offset_shift_fsb)) { - return xfs_bmse_merge(ip, whichfork, offset_shift_fsb, - *current_ext, gotp, adj_irecp, - cur, logflags); + error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb, + *current_ext, gotp, adj_irecp, + cur, logflags); + if (error) + return error; + adj_irec = got; + goto update_rmap; } } else { startoff = got.br_startoff + offset_shift_fsb; @@ -5656,9 +5685,10 @@ update_current_ext: (*current_ext)--; xfs_bmbt_set_startoff(gotp, startoff); *logflags |= XFS_ILOG_CORE; + adj_irec = got; if (!cur) { *logflags |= XFS_ILOG_DEXT; - return 0; + goto update_rmap; } error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, @@ -5668,8 +5698,18 @@ update_current_ext: XFS_WANT_CORRUPTED_RETURN(mp, i == 1); got.br_startoff = startoff; - return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, - got.br_blockcount, got.br_state); + error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, + got.br_blockcount, got.br_state); + if (error) + return error; + +update_rmap: + /* update reverse mapping */ + error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &adj_irec); + if (error) + return error; + adj_irec.br_startoff = startoff; + return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &adj_irec); } /* @@ -5797,7 +5837,7 @@ xfs_bmap_shift_extents( while (nexts++ < num_exts) { error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, ¤t_ext, gotp, cur, &logflags, - direction); + direction, dfops); if (error) goto del_cursor; /* diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 76fc5c2..f179ea4 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -36,6 +36,8 @@ #include "xfs_trace.h" #include "xfs_error.h" #include "xfs_extent_busy.h" +#include "xfs_bmap.h" +#include "xfs_inode.h" /* * Lookup the first record less than or equal to [bno, len, owner, offset] @@ -1212,3 +1214,253 @@ xfs_rmapbt_query_range( return xfs_btree_query_range(cur, &low_brec, &high_brec, xfs_rmapbt_query_range_helper, &query); } + +/* Clean up after calling xfs_rmap_finish_one. */ +void +xfs_rmap_finish_one_cleanup( + struct xfs_trans *tp, + struct xfs_btree_cur *rcur, + int error) +{ + struct xfs_buf *agbp; + + if (rcur == NULL) + return; + agbp = rcur->bc_private.a.agbp; + xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(tp, agbp); +} + +/* + * Process one of the deferred rmap operations. We pass back the + * btree cursor to maintain our lock on the rmapbt between calls. + * This saves time and eliminates a buffer deadlock between the + * superblock and the AGF because we'll always grab them in the same + * order. + */ +int +xfs_rmap_finish_one( + struct xfs_trans *tp, + enum xfs_rmap_intent_type type, + __uint64_t owner, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state, + struct xfs_btree_cur **pcur) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_btree_cur *rcur; + struct xfs_buf *agbp = NULL; + int error = 0; + xfs_agnumber_t agno; + struct xfs_owner_info oinfo; + xfs_agblock_t bno; + bool unwritten; + + agno = XFS_FSB_TO_AGNO(mp, startblock); + ASSERT(agno != NULLAGNUMBER); + bno = XFS_FSB_TO_AGBNO(mp, startblock); + + trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork, + startoff, blockcount, state); + + if (XFS_TEST_ERROR(false, mp, + XFS_ERRTAG_RMAP_FINISH_ONE, + XFS_RANDOM_RMAP_FINISH_ONE)) + return -EIO; + + /* + * If we haven't gotten a cursor or the cursor AG doesn't match + * the startblock, get one now. + */ + rcur = *pcur; + if (rcur != NULL && rcur->bc_private.a.agno != agno) { + xfs_rmap_finish_one_cleanup(tp, rcur, 0); + rcur = NULL; + *pcur = NULL; + } + if (rcur == NULL) { + error = xfs_free_extent_fix_freelist(tp, agno, &agbp); + if (error) + return error; + if (!agbp) + return -EFSCORRUPTED; + + rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); + if (!rcur) { + error = -ENOMEM; + goto out_cur; + } + } + *pcur = rcur; + + xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff); + unwritten = state == XFS_EXT_UNWRITTEN; + bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock); + + switch (type) { + case XFS_RMAP_MAP: + error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); + break; + case XFS_RMAP_UNMAP: + error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, + &oinfo); + break; + case XFS_RMAP_CONVERT: + error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, + &oinfo); + break; + case XFS_RMAP_ALLOC: + error = __xfs_rmap_alloc(rcur, bno, blockcount, unwritten, + &oinfo); + break; + case XFS_RMAP_FREE: + error = __xfs_rmap_free(rcur, bno, blockcount, unwritten, + &oinfo); + break; + default: + ASSERT(0); + error = -EFSCORRUPTED; + } + return error; + +out_cur: + xfs_trans_brelse(tp, agbp); + + return error; +} + +/* + * Record a rmap intent; the list is kept sorted first by AG and then by + * increasing age. + */ +static int +__xfs_rmap_add( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_rmap_intent *ri) +{ + struct xfs_rmap_intent *new; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock), + ri->ri_type, + XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock), + ri->ri_owner, ri->ri_whichfork, + ri->ri_bmap.br_startoff, + ri->ri_bmap.br_blockcount, + ri->ri_bmap.br_state); + + new = kmem_zalloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS); + *new = *ri; + + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &new->ri_list); + return 0; +} + +/* Map an extent into a file. */ +int +xfs_rmap_map_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_MAP; + ri.ri_owner = ip->i_ino; + ri.ri_whichfork = whichfork; + ri.ri_bmap = *PREV; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Unmap an extent out of a file. */ +int +xfs_rmap_unmap_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_UNMAP; + ri.ri_owner = ip->i_ino; + ri.ri_whichfork = whichfork; + ri.ri_bmap = *PREV; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Convert a data fork extent from unwritten to real or vice versa. */ +int +xfs_rmap_convert_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_CONVERT; + ri.ri_owner = ip->i_ino; + ri.ri_whichfork = whichfork; + ri.ri_bmap = *PREV; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Schedule the creation of an rmap for non-file data. */ +int +xfs_rmap_alloc_defer( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + __uint64_t owner) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_ALLOC; + ri.ri_owner = owner; + ri.ri_whichfork = XFS_DATA_FORK; + ri.ri_bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); + ri.ri_bmap.br_blockcount = len; + ri.ri_bmap.br_startoff = 0; + ri.ri_bmap.br_state = XFS_EXT_NORM; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Schedule the deletion of an rmap for non-file data. */ +int +xfs_rmap_free_defer( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + __uint64_t owner) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_FREE; + ri.ri_owner = owner; + ri.ri_whichfork = XFS_DATA_FORK; + ri.ri_bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); + ri.ri_bmap.br_blockcount = len; + ri.ri_bmap.br_startoff = 0; + ri.ri_bmap.br_state = XFS_EXT_NORM; + + return __xfs_rmap_add(mp, dfops, &ri); +} diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index aff60dc..5df406e 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -106,4 +106,28 @@ struct xfs_rmap_intent { struct xfs_bmbt_irec ri_bmap; }; +/* functions for updating the rmapbt based on bmbt map/unmap operations */ +int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_rmap_alloc_defer(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + __uint64_t owner); +int xfs_rmap_free_defer(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + __uint64_t owner); + +void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp, + struct xfs_btree_cur *rcur, int error); +int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type, + __uint64_t owner, int whichfork, xfs_fileoff_t startoff, + xfs_fsblock_t startblock, xfs_filblks_t blockcount, + xfs_exntst_t state, struct xfs_btree_cur **pcur); + #endif /* __XFS_RMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 62d194e..450fd49 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -41,6 +41,7 @@ #include "xfs_trace.h" #include "xfs_icache.h" #include "xfs_log.h" +#include "xfs_rmap_btree.h" /* Kernel only BMAP related definitions and functions */ diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c index dbd10fc..9ed060d 100644 --- a/fs/xfs/xfs_defer_item.c +++ b/fs/xfs/xfs_defer_item.c @@ -213,7 +213,8 @@ xfs_rmap_update_finish_item( rmap->ri_bmap.br_startoff, rmap->ri_bmap.br_startblock, rmap->ri_bmap.br_blockcount, - rmap->ri_bmap.br_state); + rmap->ri_bmap.br_state, + (struct xfs_btree_cur **)state); kmem_free(rmap); return error; } @@ -225,6 +226,9 @@ xfs_rmap_update_finish_cleanup( void *state, int error) { + struct xfs_btree_cur *rcur = state; + + xfs_rmap_finish_one_cleanup(tp, rcur, error); } /* Abort all pending RUIs. */ diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index ee4680e..6bc614c 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -91,7 +91,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_ERRTAG_DIOWRITE_IOERR 20 #define XFS_ERRTAG_BMAPIFORMAT 21 #define XFS_ERRTAG_FREE_EXTENT 22 -#define XFS_ERRTAG_MAX 23 +#define XFS_ERRTAG_RMAP_FINISH_ONE 23 +#define XFS_ERRTAG_MAX 24 /* * Random factors for above tags, 1 means always, 2 means 1/2 time, etc. @@ -119,6 +120,7 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_RANDOM_DIOWRITE_IOERR (XFS_RANDOM_DEFAULT/10) #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT #define XFS_RANDOM_FREE_EXTENT 1 +#define XFS_RANDOM_RMAP_FINISH_ONE 1 #ifdef DEBUG extern int xfs_error_test_active; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index c9fe0c4..f7f9635 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -45,6 +45,7 @@ #include "xfs_error.h" #include "xfs_dir2.h" #include "xfs_rmap_item.h" +#include "xfs_rmap_btree.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) @@ -4486,6 +4487,12 @@ xlog_recover_process_rui( struct xfs_map_extent *rmap; xfs_fsblock_t startblock_fsb; bool op_ok; + struct xfs_rud_log_item *rudp; + enum xfs_rmap_intent_type type; + int whichfork; + xfs_exntst_t state; + struct xfs_trans *tp; + struct xfs_btree_cur *rcur = NULL; ASSERT(!test_bit(XFS_RUI_RECOVERED, &ruip->rui_flags)); @@ -4528,9 +4535,54 @@ xlog_recover_process_rui( } } - /* XXX: do nothing for now */ + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); + if (error) + return error; + rudp = xfs_trans_get_rud(tp, ruip, ruip->rui_format.rui_nextents); + + for (i = 0; i < ruip->rui_format.rui_nextents; i++) { + rmap = &(ruip->rui_format.rui_extents[i]); + state = (rmap->me_flags & XFS_RMAP_EXTENT_UNWRITTEN) ? + XFS_EXT_UNWRITTEN : XFS_EXT_NORM; + whichfork = (rmap->me_flags & XFS_RMAP_EXTENT_ATTR_FORK) ? + XFS_ATTR_FORK : XFS_DATA_FORK; + switch (rmap->me_flags & XFS_RMAP_EXTENT_TYPE_MASK) { + case XFS_RMAP_EXTENT_MAP: + type = XFS_RMAP_MAP; + break; + case XFS_RMAP_EXTENT_UNMAP: + type = XFS_RMAP_UNMAP; + break; + case XFS_RMAP_EXTENT_CONVERT: + type = XFS_RMAP_CONVERT; + break; + case XFS_RMAP_EXTENT_ALLOC: + type = XFS_RMAP_ALLOC; + break; + case XFS_RMAP_EXTENT_FREE: + type = XFS_RMAP_FREE; + break; + default: + error = -EFSCORRUPTED; + goto abort_error; + } + error = xfs_trans_log_finish_rmap_update(tp, rudp, type, + rmap->me_owner, whichfork, + rmap->me_startoff, rmap->me_startblock, + rmap->me_len, state, &rcur); + if (error) + goto abort_error; + + } + + xfs_rmap_finish_one_cleanup(tp, rcur, error); set_bit(XFS_RUI_RECOVERED, &ruip->rui_flags); - xfs_rui_release(ruip); + error = xfs_trans_commit(tp); + return error; + +abort_error: + xfs_rmap_finish_one_cleanup(tp, rcur, error); + xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index c48be63..f59d934 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -244,12 +244,13 @@ void xfs_trans_log_start_rmap_update(struct xfs_trans *tp, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state); +struct xfs_btree_cur; struct xfs_rud_log_item *xfs_trans_get_rud(struct xfs_trans *tp, struct xfs_rui_log_item *ruip, uint nextents); int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp, struct xfs_rud_log_item *rudp, enum xfs_rmap_intent_type type, __uint64_t owner, int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, - xfs_exntst_t state); + xfs_exntst_t state, struct xfs_btree_cur **pcur); #endif /* __XFS_TRANS_H__ */ diff --git a/fs/xfs/xfs_trans_rmap.c b/fs/xfs/xfs_trans_rmap.c index b55a725..0c0df18 100644 --- a/fs/xfs/xfs_trans_rmap.c +++ b/fs/xfs/xfs_trans_rmap.c @@ -170,14 +170,15 @@ xfs_trans_log_finish_rmap_update( xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, - xfs_exntst_t state) + xfs_exntst_t state, + struct xfs_btree_cur **pcur) { uint next_extent; struct xfs_map_extent *rmap; int error; - /* XXX: actually finish the rmap update here */ - error = -EFSCORRUPTED; + error = xfs_rmap_finish_one(tp, type, owner, whichfork, startoff, + startblock, blockcount, state, pcur); /* * Mark the transaction dirty, even on error. This ensures the From darrick.wong@oracle.com Thu Jun 16 20:22:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BAF127CCC for ; Thu, 16 Jun 2016 20:22:48 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3342FAC001 for ; Thu, 16 Jun 2016 18:22:48 -0700 (PDT) X-ASG-Debug-ID: 1466126566-04cb6c542657490001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id GbRSBvpgw6mw9uj1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:46 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Mi1b026858 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:44 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Minh018536 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:44 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MgxE019542; Fri, 17 Jun 2016 01:22:43 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:42 -0700 Subject: [PATCH 045/119] xfs: add rmap btree geometry feature flag From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 045/119] xfs: add rmap btree geometry feature flag To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:22:40 -0700 Message-ID: <146612656051.12839.8811990871879453367.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126566 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1494 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner So xfs_info and other userspace utilities know the filesystem is using this feature. Signed-off-by: Dave Chinner --- fs/xfs/libxfs/xfs_fs.h | 1 + fs/xfs/xfs_fsops.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index f5ec9c5..7945505 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -206,6 +206,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */ +#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* Reverse mapping btree */ /* * Minimum and maximum sizes need for growth checks. diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 3772f6c..5980d5c 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -105,7 +105,9 @@ xfs_fs_geometry( (xfs_sb_version_hasfinobt(&mp->m_sb) ? XFS_FSOP_GEOM_FLAGS_FINOBT : 0) | (xfs_sb_version_hassparseinodes(&mp->m_sb) ? - XFS_FSOP_GEOM_FLAGS_SPINODES : 0); + XFS_FSOP_GEOM_FLAGS_SPINODES : 0) | + (xfs_sb_version_hasrmapbt(&mp->m_sb) ? + XFS_FSOP_GEOM_FLAGS_RMAPBT : 0); geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? mp->m_sb.sb_logsectsize : BBSIZE; geo->rtsectsize = mp->m_sb.sb_blocksize; From darrick.wong@oracle.com Thu Jun 16 20:22:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5115C7DCA for ; Thu, 16 Jun 2016 20:22:54 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id C98A1AC003 for ; Thu, 16 Jun 2016 18:22:53 -0700 (PDT) X-ASG-Debug-ID: 1466126571-04cb6c5425574a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id zZm4YqGar2iDgHcL (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:22:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1MnTv007584 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:50 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1MnSE007798 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:49 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1MmSO027957; Fri, 17 Jun 2016 01:22:48 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:48 -0700 Subject: [PATCH 046/119] xfs: add rmap btree block detection to log recovery From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 046/119] xfs: add rmap btree block detection to log recovery To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:22:46 -0700 Message-ID: <146612656689.12839.658842468753557889.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126572 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1017 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner So such blocks can be correctly identified and have their operations structutes attached to validate recovery has not resulted in a correct block. Signed-off-by: Dave Chinner --- fs/xfs/xfs_log_recover.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index f7f9635..dbfbc26 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2233,6 +2233,7 @@ xlog_recover_get_buf_lsn( case XFS_ABTC_CRC_MAGIC: case XFS_ABTB_MAGIC: case XFS_ABTC_MAGIC: + case XFS_RMAP_CRC_MAGIC: case XFS_IBT_CRC_MAGIC: case XFS_IBT_MAGIC: { struct xfs_btree_block *btb = blk; @@ -2401,6 +2402,9 @@ xlog_recover_validate_buf_type( case XFS_BMAP_MAGIC: bp->b_ops = &xfs_bmbt_buf_ops; break; + case XFS_RMAP_CRC_MAGIC: + bp->b_ops = &xfs_rmapbt_buf_ops; + break; default: xfs_warn(mp, "Bad btree block magic!"); ASSERT(0); From darrick.wong@oracle.com Thu Jun 16 20:23:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id CD4257CBC for ; Thu, 16 Jun 2016 20:23:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 908E98F804C for ; Thu, 16 Jun 2016 18:23:01 -0700 (PDT) X-ASG-Debug-ID: 1466126579-04cbb01fef69690001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 4cBxCHTlJEssPdCV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:00 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1MwOi007630 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:58 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Mvxa014722 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:22:57 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Mt9p007435; Fri, 17 Jun 2016 01:22:56 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:22:54 -0700 Subject: [PATCH 047/119] xfs: disable XFS_IOC_SWAPEXT when rmap btree is enabled From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 047/119] xfs: disable XFS_IOC_SWAPEXT when rmap btree is enabled To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:22:53 -0700 Message-ID: <146612657322.12839.9067889093004523073.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126580 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1049 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Swapping extents between two inodes requires the owner to be updated in the rmap tree for all the extents that are swapped. This code does not yet exist, so switch off the XFS_IOC_SWAPEXT ioctl until support has been implemented. This will need to be done before the rmap btree code can have the experimental tag removed. Signed-off-by: Dave Chinner [darrick.wong@oracle.com: fix extent swapping when rmap enabled] Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_bmap_util.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 450fd49..8666873 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1618,6 +1618,10 @@ xfs_swap_extents( __uint64_t tmp; int lock_flags; + /* XXX: we can't do this with rmap, will fix later */ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + return -EOPNOTSUPP; + tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); if (!tempifp) { error = -ENOMEM; From darrick.wong@oracle.com Thu Jun 16 20:23:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0CD847DC1 for ; Thu, 16 Jun 2016 20:23:08 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id B2BD9304048 for ; Thu, 16 Jun 2016 18:23:07 -0700 (PDT) X-ASG-Debug-ID: 1466126585-04bdf01e1395a20001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Y8h0ec43uQADicFc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:05 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1N2Ah007948 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:03 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1N2vg014850 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:02 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1N1BI019679; Fri, 17 Jun 2016 01:23:01 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:01 -0700 Subject: [PATCH 048/119] xfs: don't update rmapbt when fixing agfl From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 048/119] xfs: don't update rmapbt when fixing agfl To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:22:59 -0700 Message-ID: <146612657955.12839.6406507864344687918.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126585 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3409 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Allow a caller of xfs_alloc_fix_freelist to disable rmapbt updates when fixing the AG freelist. xfs_repair needs this during phase 5 to be able to adjust the freelist while it's reconstructing the rmap btree; the missing entries will be added back at the very end of phase 5 once the AGFL contents settle down. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 40 ++++++++++++++++++++++++++-------------- fs/xfs/libxfs/xfs_alloc.h | 3 +++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 4c8ffd4..6eabab1 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2092,26 +2092,38 @@ xfs_alloc_fix_freelist( * anything other than extra overhead when we need to put more blocks * back on the free list? Maybe we should only do this when space is * getting low or the AGFL is more than half full? + * + * The NOSHRINK flag prevents the AGFL from being shrunk if it's too + * big; the NORMAP flag prevents AGFL expand/shrink operations from + * updating the rmapbt. Both flags are used in xfs_repair while we're + * rebuilding the rmapbt, and neither are used by the kernel. They're + * both required to ensure that rmaps are correctly recorded for the + * regenerated AGFL, bnobt, and cntbt. See repair/phase5.c and + * repair/rmap.c in xfsprogs for details. */ - xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); - while (pag->pagf_flcount > need) { - struct xfs_buf *bp; + memset(&targs, 0, sizeof(targs)); + if (!(flags & XFS_ALLOC_FLAG_NOSHRINK)) { + if (!(flags & XFS_ALLOC_FLAG_NORMAP)) + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); + while (pag->pagf_flcount > need) { + struct xfs_buf *bp; - error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); - if (error) - goto out_agbp_relse; - error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, - &targs.oinfo, 1); - if (error) - goto out_agbp_relse; - bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); - xfs_trans_binval(tp, bp); + error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); + if (error) + goto out_agbp_relse; + error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, + &targs.oinfo, 1); + if (error) + goto out_agbp_relse; + bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); + xfs_trans_binval(tp, bp); + } } - memset(&targs, 0, sizeof(targs)); targs.tp = tp; targs.mp = mp; - xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); + if (!(flags & XFS_ALLOC_FLAG_NORMAP)) + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); targs.agbp = agbp; targs.agno = args->agno; targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 7b6c66b..7b9e67e 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -54,6 +54,9 @@ typedef unsigned int xfs_alloctype_t; */ #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ +#define XFS_ALLOC_FLAG_NORMAP 0x00000004 /* don't modify the rmapbt */ +#define XFS_ALLOC_FLAG_NOSHRINK 0x00000008 /* don't shrink the freelist */ + /* * Argument structure for xfs_alloc routines. From darrick.wong@oracle.com Thu Jun 16 20:23:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1BE2C7CBC for ; Thu, 16 Jun 2016 20:23:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id D6EC6304048 for ; Thu, 16 Jun 2016 18:23:12 -0700 (PDT) X-ASG-Debug-ID: 1466126591-04cb6c5425574e0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id OGiLdZIHoz9CXqpQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:11 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1N83V008044 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:09 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1N8sp019139 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:08 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1N7uv028171; Fri, 17 Jun 2016 01:23:07 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:07 -0700 Subject: [PATCH 049/119] xfs: enable the rmap btree functionality From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 049/119] xfs: enable the rmap btree functionality To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:23:05 -0700 Message-ID: <146612658581.12839.14068666392735480433.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126591 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1667 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Add the feature flag to the supported matrix so that the kernel can mount and use rmap btree enabled filesystems v2: Move the EXPERIMENTAL message to fill_super so it only prints once. Signed-off-by: Dave Chinner [darrick.wong@oracle.com: move the experimental tag] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 3 ++- fs/xfs/xfs_super.c | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 6efc7a3..1b08237 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -457,7 +457,8 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ - (XFS_SB_FEAT_RO_COMPAT_FINOBT) + (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ + XFS_SB_FEAT_RO_COMPAT_RMAPBT) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool xfs_sb_has_ro_compat_feature( diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index a8300e4..9328821 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1571,6 +1571,10 @@ xfs_fs_fill_super( xfs_alert(mp, "EXPERIMENTAL sparse inode feature enabled. Use at your own risk!"); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + xfs_alert(mp, + "EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!"); + error = xfs_mountfs(mp); if (error) goto out_filestream_unmount; From darrick.wong@oracle.com Thu Jun 16 20:23:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 950897CBC for ; Thu, 16 Jun 2016 20:23:22 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5691B30404E for ; Thu, 16 Jun 2016 18:23:22 -0700 (PDT) X-ASG-Debug-ID: 1466126599-04cbb01fee696c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id zEZ0cPgOx926nLaV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1NGma027399 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:23:16 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1NEDx013005 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:14 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NDST024023; Fri, 17 Jun 2016 01:23:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:13 -0700 Subject: [PATCH 050/119] xfs: count the blocks in a btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 050/119] xfs: count the blocks in a btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:12 -0700 Message-ID: <146612659218.12839.17928675947317698460.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126600 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1712 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a helper method to count the number of blocks in a short form btree. The refcount and rmap btrees need to know the number of blocks already in use to set up their per-AG block reservations during mount. v2: Use btree_visit_blocks instead of open-coding our own traversal routine. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_btree.c | 22 ++++++++++++++++++++++ fs/xfs/libxfs/xfs_btree.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 4b90419..50b2c32 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -4803,3 +4803,25 @@ xfs_btree_query_range( return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, fn, priv); } + +int +xfs_btree_count_blocks_helper( + struct xfs_btree_cur *cur, + int level, + void *data) +{ + xfs_extlen_t *blocks = data; + (*blocks)++; + + return 0; +} + +/* Count the blocks in a btree and return the result in *blocks. */ +int +xfs_btree_count_blocks( + struct xfs_btree_cur *cur, + xfs_extlen_t *blocks) +{ + return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper, + blocks); +} diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 9963c48..6fa13a9 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -519,4 +519,6 @@ typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level, int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, xfs_btree_visit_blocks_fn fn, void *data); +int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks); + #endif /* __XFS_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:23:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 528CF7CB4 for ; Thu, 16 Jun 2016 20:23:29 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id D35B8AC004 for ; Thu, 16 Jun 2016 18:23:28 -0700 (PDT) X-ASG-Debug-ID: 1466126606-04bdf01e1095a50001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id yo7VkwSnJh5tz0Ew (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:27 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1NMrJ027461 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:23 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NMKF019434 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:22 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NKKn007543; Fri, 17 Jun 2016 01:23:21 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:19 -0700 Subject: [PATCH 051/119] xfs: introduce tracepoints for AG reservation code From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 051/119] xfs: introduce tracepoints for AG reservation code To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:18 -0700 Message-ID: <146612659841.12839.7635720851652960531.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126607 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2699 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_trace.h | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 6466adc..c50479a 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2558,6 +2558,75 @@ DEFINE_RMAPBT_EVENT(xfs_rmap_map_gtrec); DEFINE_RMAPBT_EVENT(xfs_rmap_convert_gtrec); DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result); +/* dummy definitions to avoid breaking bisectability; will be removed later */ +#ifndef XFS_AG_RESV_DUMMY +#define XFS_AG_RESV_DUMMY +enum xfs_ag_resv_type { + XFS_AG_RESV_NONE = 0, + XFS_AG_RESV_METADATA, + XFS_AG_RESV_AGFL, +}; +struct xfs_ag_resv { + xfs_extlen_t ar_reserved; + xfs_extlen_t ar_asked; +}; +#define xfs_perag_resv(...) NULL +#endif + +/* per-AG reservation */ +DECLARE_EVENT_CLASS(xfs_ag_resv_class, + TP_PROTO(struct xfs_perag *pag, enum xfs_ag_resv_type resv, + xfs_extlen_t len), + TP_ARGS(pag, resv, len), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(int, resv) + __field(xfs_extlen_t, freeblks) + __field(xfs_extlen_t, flcount) + __field(xfs_extlen_t, reserved) + __field(xfs_extlen_t, asked) + __field(xfs_extlen_t, len) + ), + TP_fast_assign( + struct xfs_ag_resv *r = xfs_perag_resv(pag, resv); + + __entry->dev = pag->pag_mount->m_super->s_dev; + __entry->agno = pag->pag_agno; + __entry->resv = resv; + __entry->freeblks = pag->pagf_freeblks; + __entry->flcount = pag->pagf_flcount; + __entry->reserved = r ? r->ar_reserved : 0; + __entry->asked = r ? r->ar_asked : 0; + __entry->len = len; + ), + TP_printk("dev %d:%d agno %u resv %d freeblks %u flcount %u resv %u ask %u len %u\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->resv, + __entry->freeblks, + __entry->flcount, + __entry->reserved, + __entry->asked, + __entry->len) +) +#define DEFINE_AG_RESV_EVENT(name) \ +DEFINE_EVENT(xfs_ag_resv_class, name, \ + TP_PROTO(struct xfs_perag *pag, enum xfs_ag_resv_type type, \ + xfs_extlen_t len), \ + TP_ARGS(pag, type, len)) + +/* per-AG reservation tracepoints */ +DEFINE_AG_RESV_EVENT(xfs_ag_resv_init); +DEFINE_AG_RESV_EVENT(xfs_ag_resv_free); +DEFINE_AG_RESV_EVENT(xfs_ag_resv_alloc_extent); +DEFINE_AG_RESV_EVENT(xfs_ag_resv_free_extent); +DEFINE_AG_RESV_EVENT(xfs_ag_resv_critical); +DEFINE_AG_RESV_EVENT(xfs_ag_resv_needed); + +DEFINE_AG_ERROR_EVENT(xfs_ag_resv_free_error); +DEFINE_AG_ERROR_EVENT(xfs_ag_resv_init_error); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:23:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 410427DEE for ; Thu, 16 Jun 2016 20:23:35 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 046DD304039 for ; Thu, 16 Jun 2016 18:23:34 -0700 (PDT) X-ASG-Debug-ID: 1466126610-04cbb01fec696d0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id mnPPp6cm7juUiqTw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1NRLi008137 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:28 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NRaJ008563 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:27 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NQmn024038; Fri, 17 Jun 2016 01:23:26 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:26 -0700 Subject: [PATCH 052/119] xfs: set up per-AG free space reservations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 052/119] xfs: set up per-AG free space reservations To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:24 -0700 Message-ID: <146612660467.12839.14363093932068766563.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126610 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 31504 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines One unfortunate quirk of the reference count btree -- it can expand in size when blocks are written to *other* allocation groups if, say, one large extent becomes a lot of tiny extents. Since we don't want to start throwing errors in the middle of CoWing, we need to reserve some blocks to handle future expansion. Use the count of how many reserved blocks we need to have on hand to create a virtual reservation in the AG. Through selective clamping of the maximum length of allocation requests and of the length of the longest free extent, we can make it look like there's less free space in the AG unless the reservation owner is asking for blocks. In other words, play some accounting tricks in-core to make sure that we always have blocks available. On the plus side, there's nothing to clean up if we crash, which is contrast to the strategy that the rough draft used (actually removing extents from the freespace btrees). v2: There's really only two kinds of per-AG reservation pools -- one to feed the AGFL (rmapbt), and one to feed everything else (refcountbt). Bearing that in mind, we can embed the reservation controls in xfs_perag and greatly simplify the block accounting. Furthermore, fix some longstanding accounting bugs that were a direct result of the goofy "allocate a block and later fix up the accounting" strategy by integrating the reservation accounting code more tightly with the allocator. This eliminates the ENOSPC complaints resulting from refcount btree splits during truncate operations. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_ag_resv.c | 318 ++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_ag_resv.h | 35 ++++ fs/xfs/libxfs/xfs_alloc.c | 93 ++++++++--- fs/xfs/libxfs/xfs_alloc.h | 8 + fs/xfs/libxfs/xfs_bmap.c | 6 - fs/xfs/libxfs/xfs_ialloc_btree.c | 2 fs/xfs/xfs_filestream.c | 4 fs/xfs/xfs_fsops.c | 2 fs/xfs/xfs_mount.h | 34 ++++ fs/xfs/xfs_trace.h | 36 +--- fs/xfs/xfs_trans_extfree.c | 3 12 files changed, 485 insertions(+), 57 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_ag_resv.c create mode 100644 fs/xfs/libxfs/xfs_ag_resv.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 1980110..c7a864e 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -52,6 +52,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_inode_fork.o \ xfs_inode_buf.o \ xfs_log_rlimit.o \ + xfs_ag_resv.o \ xfs_rmap.o \ xfs_rmap_btree.o \ xfs_sb.o \ diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c new file mode 100644 index 0000000..4d390b7 --- /dev/null +++ b/fs/xfs/libxfs/xfs_ag_resv.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_alloc.h" +#include "xfs_error.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" +#include "xfs_trans.h" +#include "xfs_bit.h" +#include "xfs_bmap.h" +#include "xfs_bmap_btree.h" +#include "xfs_ag_resv.h" +#include "xfs_trans_space.h" +#include "xfs_rmap_btree.h" +#include "xfs_btree.h" + +/* + * Per-AG Block Reservations + * + * For some kinds of allocation group metadata structures, it is advantageous + * to reserve a small number of blocks in each AG so that future expansions of + * that data structure do not encounter ENOSPC because errors during a btree + * split cause the filesystem to go offline. + * + * Prior to the introduction of reflink, this wasn't an issue because the free + * space btrees maintain a reserve of space (the AGFL) to handle any expansion + * that may be necessary; and allocations of other metadata (inodes, BMBT, + * dir/attr) aren't restricted to a single AG. However, with reflink it is + * possible to allocate all the space in an AG, have subsequent reflink/CoW + * activity expand the refcount btree, and discover that there's no space left + * to handle that expansion. Since we can calculate the maximum size of the + * refcount btree, we can reserve space for it and avoid ENOSPC. + * + * Handling per-AG reservations consists of three changes to the allocator's + * behavior: First, because these reservations are always needed, we decrease + * the ag_max_usable counter to reflect the size of the AG after the reserved + * blocks are taken. Second, the reservations must be reflected in the + * fdblocks count to maintain proper accounting. Third, each AG must maintain + * its own reserved block counter so that we can calculate the amount of space + * that must remain free to maintain the reservations. Fourth, the "remaining + * reserved blocks" count must be used when calculating the length of the + * longest free extent in an AG and to clamp maxlen in the per-AG allocation + * functions. In other words, we maintain a virtual allocation via in-core + * accounting tricks so that we don't have to clean up after a crash. :) + * + * Reserved blocks can be managed by passing one of the enum xfs_ag_resv_type + * values via struct xfs_alloc_arg or directly to the xfs_free_extent + * function. It might seem a little funny to maintain a reservoir of blocks + * to feed another reservoir, but the AGFL only holds enough blocks to get + * through the next transaction. The per-AG reservation is to ensure (we + * hope) that each AG never runs out of blocks. Each data structure wanting + * to use the reservation system should update ask/used in xfs_ag_resv_init. + */ + +/* + * Are we critically low on blocks? For now we'll define that as the number + * of blocks we can get our hands on being less than 10% of what we reserved + * or less than some arbitrary number (eight). + */ +bool +xfs_ag_resv_critical( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + xfs_extlen_t avail; + xfs_extlen_t orig; + + switch (type) { + case XFS_AG_RESV_METADATA: + avail = pag->pagf_freeblks - pag->pag_agfl_resv.ar_reserved; + orig = pag->pag_meta_resv.ar_asked; + break; + case XFS_AG_RESV_AGFL: + avail = pag->pagf_freeblks + pag->pagf_flcount - + pag->pag_meta_resv.ar_reserved; + orig = pag->pag_agfl_resv.ar_asked; + break; + default: + ASSERT(0); + return false; + } + + trace_xfs_ag_resv_critical(pag, type, avail); + + return avail < orig / 10 || avail < XFS_BTREE_MAXLEVELS; +} + +/* + * How many blocks are reserved but not used, and therefore must not be + * allocated away? + */ +xfs_extlen_t +xfs_ag_resv_needed( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + xfs_extlen_t len; + + len = pag->pag_meta_resv.ar_reserved + pag->pag_agfl_resv.ar_reserved; + switch (type) { + case XFS_AG_RESV_METADATA: + case XFS_AG_RESV_AGFL: + len -= xfs_perag_resv(pag, type)->ar_reserved; + break; + case XFS_AG_RESV_NONE: + /* empty */ + break; + default: + ASSERT(0); + } + + trace_xfs_ag_resv_needed(pag, type, len); + + return len; +} + +/* Clean out a reservation */ +static int +__xfs_ag_resv_free( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + struct xfs_ag_resv *resv; + struct xfs_ag_resv t; + int error; + + trace_xfs_ag_resv_free(pag, type, 0); + + resv = xfs_perag_resv(pag, type); + t = *resv; + resv->ar_reserved = 0; + resv->ar_asked = 0; + pag->pag_mount->m_ag_max_usable += t.ar_asked; + + error = xfs_mod_fdblocks(pag->pag_mount, t.ar_reserved, true); + if (error) + trace_xfs_ag_resv_free_error(pag->pag_mount, pag->pag_agno, + error, _RET_IP_); + return error; +} + +/* Free a per-AG reservation. */ +int +xfs_ag_resv_free( + struct xfs_perag *pag) +{ + int error = 0; + int err2; + + err2 = __xfs_ag_resv_free(pag, XFS_AG_RESV_AGFL); + if (err2 && !error) + error = err2; + err2 = __xfs_ag_resv_free(pag, XFS_AG_RESV_METADATA); + if (err2 && !error) + error = err2; + return error; +} + +static int +__xfs_ag_resv_init( + struct xfs_perag *pag, + enum xfs_ag_resv_type type, + xfs_extlen_t ask, + xfs_extlen_t used) +{ + struct xfs_mount *mp = pag->pag_mount; + struct xfs_ag_resv *resv; + int error; + + resv = xfs_perag_resv(pag, type); + if (used > ask) + ask = used; + resv->ar_asked = ask; + resv->ar_reserved = ask - used; + mp->m_ag_max_usable -= ask; + + trace_xfs_ag_resv_init(pag, type, ask); + + error = xfs_mod_fdblocks(mp, -(int64_t)resv->ar_reserved, true); + if (error) + trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno, + error, _RET_IP_); + + return error; +} + +/* Create a per-AG block reservation. */ +int +xfs_ag_resv_init( + struct xfs_perag *pag) +{ + xfs_extlen_t ask; + xfs_extlen_t used; + int error = 0; + int err2; + + if (pag->pag_meta_resv.ar_asked) + goto init_agfl; + + /* Create the metadata reservation. */ + ask = used = 0; + + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, ask, used); + if (err2 && !error) + error = err2; + +init_agfl: + if (pag->pag_agfl_resv.ar_asked) + return error; + + /* Create the AGFL metadata reservation */ + ask = used = 0; + + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_AGFL, ask, used); + if (err2 && !error) + error = err2; + + return error; +} + +/* Allocate a block from the reservation. */ +void +xfs_ag_resv_alloc_extent( + struct xfs_perag *pag, + enum xfs_ag_resv_type type, + struct xfs_alloc_arg *args) +{ + struct xfs_ag_resv *resv; + xfs_extlen_t leftover; + uint field; + + trace_xfs_ag_resv_alloc_extent(pag, type, args->len); + + switch (type) { + case XFS_AG_RESV_METADATA: + case XFS_AG_RESV_AGFL: + resv = xfs_perag_resv(pag, type); + break; + default: + ASSERT(0); + /* fall through */ + case XFS_AG_RESV_NONE: + field = args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : + XFS_TRANS_SB_FDBLOCKS; + xfs_trans_mod_sb(args->tp, field, -(int64_t)args->len); + return; + } + + if (args->len > resv->ar_reserved) { + leftover = args->len - resv->ar_reserved; + if (type != XFS_AG_RESV_AGFL) + xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_FDBLOCKS, + -(int64_t)leftover); + resv->ar_reserved = 0; + } else + resv->ar_reserved -= args->len; +} + +/* Free a block to the reservation. */ +void +xfs_ag_resv_free_extent( + struct xfs_perag *pag, + enum xfs_ag_resv_type type, + struct xfs_trans *tp, + xfs_extlen_t len) +{ + xfs_extlen_t leftover; + struct xfs_ag_resv *resv; + + trace_xfs_ag_resv_free_extent(pag, type, len); + + switch (type) { + case XFS_AG_RESV_METADATA: + case XFS_AG_RESV_AGFL: + resv = xfs_perag_resv(pag, type); + break; + default: + ASSERT(0); + /* fall through */ + case XFS_AG_RESV_NONE: + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (int64_t)len); + return; + } + + if (resv->ar_reserved + len > resv->ar_asked) { + leftover = resv->ar_reserved + len - resv->ar_asked; + if (type != XFS_AG_RESV_AGFL) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, + (int64_t)leftover); + resv->ar_reserved = resv->ar_asked; + } else + resv->ar_reserved += len; +} diff --git a/fs/xfs/libxfs/xfs_ag_resv.h b/fs/xfs/libxfs/xfs_ag_resv.h new file mode 100644 index 0000000..8d6c687 --- /dev/null +++ b/fs/xfs/libxfs/xfs_ag_resv.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_AG_RESV_H__ +#define __XFS_AG_RESV_H__ + +int xfs_ag_resv_free(struct xfs_perag *pag); +int xfs_ag_resv_init(struct xfs_perag *pag); + +bool xfs_ag_resv_critical(struct xfs_perag *pag, enum xfs_ag_resv_type type); +xfs_extlen_t xfs_ag_resv_needed(struct xfs_perag *pag, + enum xfs_ag_resv_type type); + +void xfs_ag_resv_alloc_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, + struct xfs_alloc_arg *args); +void xfs_ag_resv_free_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, + struct xfs_trans *tp, xfs_extlen_t len); + +#endif /* __XFS_AG_RESV_H__ */ diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 6eabab1..5f05c4e 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -37,6 +37,7 @@ #include "xfs_trans.h" #include "xfs_buf_item.h" #include "xfs_log.h" +#include "xfs_ag_resv.h" struct workqueue_struct *xfs_alloc_wq; @@ -682,12 +683,29 @@ xfs_alloc_ag_vextent( xfs_alloc_arg_t *args) /* argument structure for allocation */ { int error=0; + xfs_extlen_t reservation; + xfs_extlen_t oldmax; ASSERT(args->minlen > 0); ASSERT(args->maxlen > 0); ASSERT(args->minlen <= args->maxlen); ASSERT(args->mod < args->prod); ASSERT(args->alignment > 0); + + /* + * Clamp maxlen to the amount of free space minus any reservations + * that have been made. + */ + oldmax = args->maxlen; + reservation = xfs_ag_resv_needed(args->pag, args->resv); + if (args->maxlen > args->pag->pagf_freeblks - reservation) + args->maxlen = args->pag->pagf_freeblks - reservation; + if (args->maxlen == 0) { + args->agbno = NULLAGBLOCK; + args->maxlen = oldmax; + return 0; + } + /* * Branch to correct routine based on the type. */ @@ -707,12 +725,14 @@ xfs_alloc_ag_vextent( /* NOTREACHED */ } + args->maxlen = oldmax; + if (error || args->agbno == NULLAGBLOCK) return error; ASSERT(args->len >= args->minlen); ASSERT(args->len <= args->maxlen); - ASSERT(!args->wasfromfl || !args->isfl); + ASSERT(!args->wasfromfl || args->resv != XFS_AG_RESV_AGFL); ASSERT(args->agbno % args->alignment == 0); /* if not file data, insert new block into the reverse map btree */ @@ -734,12 +754,7 @@ xfs_alloc_ag_vextent( args->agbno, args->len)); } - if (!args->isfl) { - xfs_trans_mod_sb(args->tp, args->wasdel ? - XFS_TRANS_SB_RES_FDBLOCKS : - XFS_TRANS_SB_FDBLOCKS, - -((long)(args->len))); - } + xfs_ag_resv_alloc_extent(args->pag, args->resv, args); XFS_STATS_INC(args->mp, xs_allocx); XFS_STATS_ADD(args->mp, xs_allocb, args->len); @@ -1601,7 +1616,8 @@ xfs_alloc_ag_vextent_small( * to respect minleft even when pulling from the * freelist. */ - else if (args->minlen == 1 && args->alignment == 1 && !args->isfl && + else if (args->minlen == 1 && args->alignment == 1 && + args->resv != XFS_AG_RESV_AGFL && (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) > args->minleft)) { error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); @@ -1672,7 +1688,7 @@ xfs_free_ag_extent( xfs_agblock_t bno, /* starting block number */ xfs_extlen_t len, /* length of extent */ struct xfs_owner_info *oinfo, /* extent owner */ - int isfl) /* set if is freelist blocks - no sb acctg */ + enum xfs_ag_resv_type type) /* extent reservation type */ { xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */ @@ -1900,21 +1916,22 @@ xfs_free_ag_extent( */ pag = xfs_perag_get(mp, agno); error = xfs_alloc_update_counters(tp, pag, agbp, len); + xfs_ag_resv_free_extent(pag, type, tp, len); xfs_perag_put(pag); if (error) goto error0; - if (!isfl) - xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); XFS_STATS_INC(mp, xs_freex); XFS_STATS_ADD(mp, xs_freeb, len); - trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); + trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL, + haveleft, haveright); return 0; error0: - trace_xfs_free_extent(mp, agno, bno, len, isfl, -1, -1); + trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL, + -1, -1); if (bno_cur) xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); if (cnt_cur) @@ -1939,21 +1956,43 @@ xfs_alloc_compute_maxlevels( } /* - * Find the length of the longest extent in an AG. + * Find the length of the longest extent in an AG. The 'need' parameter + * specifies how much space we're going to need for the AGFL and the + * 'reserved' parameter tells us how many blocks in this AG are reserved for + * other callers. */ xfs_extlen_t xfs_alloc_longest_free_extent( struct xfs_mount *mp, struct xfs_perag *pag, - xfs_extlen_t need) + xfs_extlen_t need, + xfs_extlen_t reserved) { xfs_extlen_t delta = 0; + /* + * If the AGFL needs a recharge, we'll have to subtract that from the + * longest extent. + */ if (need > pag->pagf_flcount) delta = need - pag->pagf_flcount; + /* + * If we cannot maintain others' reservations with space from the + * not-longest freesp extents, we'll have to subtract /that/ from + * the longest extent too. + */ + if (pag->pagf_freeblks - pag->pagf_longest < reserved) + delta += reserved - (pag->pagf_freeblks - pag->pagf_longest); + + /* + * If the longest extent is long enough to satisfy all the + * reservations and AGFL rules in place, we can return this extent. + */ if (pag->pagf_longest > delta) return pag->pagf_longest - delta; + + /* Otherwise, let the caller try for 1 block if there's space. */ return pag->pagf_flcount > 0 || pag->pagf_longest > 0; } @@ -1993,20 +2032,24 @@ xfs_alloc_space_available( { struct xfs_perag *pag = args->pag; xfs_extlen_t longest; + xfs_extlen_t reservation; /* blocks that are still reserved */ int available; if (flags & XFS_ALLOC_FLAG_FREEING) return true; + reservation = xfs_ag_resv_needed(pag, args->resv); + /* do we have enough contiguous free space for the allocation? */ - longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free); + longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free, + reservation); if ((args->minlen + args->alignment + args->minalignslop - 1) > longest) return false; - /* do have enough free space remaining for the allocation? */ + /* do we have enough free space remaining for the allocation? */ available = (int)(pag->pagf_freeblks + pag->pagf_flcount - - min_free - args->total); - if (available < (int)args->minleft) + reservation - min_free - args->total); + if (available < (int)args->minleft || available <= 0) return false; return true; @@ -2112,7 +2155,8 @@ xfs_alloc_fix_freelist( if (error) goto out_agbp_relse; error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, - &targs.oinfo, 1); + &targs.oinfo, + XFS_AG_RESV_AGFL); if (error) goto out_agbp_relse; bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); @@ -2126,7 +2170,7 @@ xfs_alloc_fix_freelist( xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); targs.agbp = agbp; targs.agno = args->agno; - targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; + targs.alignment = targs.minlen = targs.prod = 1; targs.type = XFS_ALLOCTYPE_THIS_AG; targs.pag = pag; error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp); @@ -2137,6 +2181,7 @@ xfs_alloc_fix_freelist( while (pag->pagf_flcount < need) { targs.agbno = 0; targs.maxlen = need - pag->pagf_flcount; + targs.resv = XFS_AG_RESV_AGFL; /* Allocate as many blocks as possible at once. */ error = xfs_alloc_ag_vextent(&targs); @@ -2815,7 +2860,8 @@ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ - struct xfs_owner_info *oinfo) /* extent owner */ + struct xfs_owner_info *oinfo, /* extent owner */ + enum xfs_ag_resv_type type) /* block reservation type */ { struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *agbp; @@ -2824,6 +2870,7 @@ xfs_free_extent( int error; ASSERT(len != 0); + ASSERT(type != XFS_AG_RESV_AGFL); trace_xfs_bmap_free_deferred(mp, agno, 0, agbno, len); @@ -2843,7 +2890,7 @@ xfs_free_extent( agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), err); - error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, 0); + error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type); if (error) goto err; diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 7b9e67e..9f6373a4 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -87,10 +87,10 @@ typedef struct xfs_alloc_arg { xfs_alloctype_t otype; /* original allocation type */ char wasdel; /* set if allocation was prev delayed */ char wasfromfl; /* set if allocation is from freelist */ - char isfl; /* set if is freelist blocks - !acctg */ char userdata; /* mask defining userdata treatment */ xfs_fsblock_t firstblock; /* io first block allocated */ struct xfs_owner_info oinfo; /* owner of blocks being allocated */ + enum xfs_ag_resv_type resv; /* block reservation to use */ } xfs_alloc_arg_t; /* @@ -106,7 +106,8 @@ unsigned int xfs_alloc_set_aside(struct xfs_mount *mp); unsigned int xfs_alloc_ag_max_usable(struct xfs_mount *mp); xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp, - struct xfs_perag *pag, xfs_extlen_t need); + struct xfs_perag *pag, xfs_extlen_t need, + xfs_extlen_t reserved); unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp, struct xfs_perag *pag); @@ -184,7 +185,8 @@ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ - struct xfs_owner_info *oinfo); /* extent owner */ + struct xfs_owner_info *oinfo, /* extent owner */ + enum xfs_ag_resv_type type); /* block reservation type */ int /* error */ xfs_alloc_lookup_ge( diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 507fd74..972dfc2 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -47,6 +47,7 @@ #include "xfs_attr_leaf.h" #include "xfs_filestream.h" #include "xfs_rmap_btree.h" +#include "xfs_ag_resv.h" kmem_zone_t *xfs_bmap_free_item_zone; @@ -3501,7 +3502,8 @@ xfs_bmap_longest_free_extent( } longest = xfs_alloc_longest_free_extent(mp, pag, - xfs_alloc_min_freelist(mp, pag)); + xfs_alloc_min_freelist(mp, pag), + xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE)); if (*blen < longest) *blen = longest; @@ -3780,7 +3782,7 @@ xfs_bmap_btalloc( } args.minleft = ap->minleft; args.wasdel = ap->wasdel; - args.isfl = 0; + args.resv = XFS_AG_RESV_NONE; args.userdata = ap->userdata; if (ap->userdata & XFS_ALLOC_USERDATA_ZERO) args.ip = ap->ip; diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index f9ea86b..fd26550 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c @@ -131,7 +131,7 @@ xfs_inobt_free_block( xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT); return xfs_free_extent(cur->bc_tp, XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1, - &oinfo); + &oinfo, XFS_AG_RESV_NONE); } STATIC int diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index 4a33a33..c8005fd 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c @@ -30,6 +30,7 @@ #include "xfs_mru_cache.h" #include "xfs_filestream.h" #include "xfs_trace.h" +#include "xfs_ag_resv.h" struct xfs_fstrm_item { struct xfs_mru_cache_elem mru; @@ -198,7 +199,8 @@ xfs_filestream_pick_ag( } longest = xfs_alloc_longest_free_extent(mp, pag, - xfs_alloc_min_freelist(mp, pag)); + xfs_alloc_min_freelist(mp, pag), + xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE)); if (((minlen && longest >= minlen) || (!minlen && pag->pagf_freeblks >= minfree)) && (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) || diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 5980d5c..cd4de75 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -551,7 +551,7 @@ xfs_growfs_data_private( error = xfs_free_extent(tp, XFS_AGB_TO_FSB(mp, agno, be32_to_cpu(agf->agf_length) - new), - new, &oinfo); + new, &oinfo, XFS_AG_RESV_NONE); if (error) goto error0; } diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index b36676c..e18d74e 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -325,6 +325,20 @@ xfs_mp_fail_writes(struct xfs_mount *mp) } #endif +/* per-AG block reservation data structures*/ +enum xfs_ag_resv_type { + XFS_AG_RESV_NONE = 0, + XFS_AG_RESV_METADATA, + XFS_AG_RESV_AGFL, +}; + +struct xfs_ag_resv { + /* number of block reserved here */ + xfs_extlen_t ar_reserved; + /* number of blocks originally asked for */ + xfs_extlen_t ar_asked; +}; + /* * Per-ag incore structure, copies of information in agf and agi, to improve the * performance of allocation group selection. @@ -372,8 +386,28 @@ typedef struct xfs_perag { /* for rcu-safe freeing */ struct rcu_head rcu_head; int pagb_count; /* pagb slots in use */ + + /* Blocks reserved for all kinds of metadata. */ + struct xfs_ag_resv pag_meta_resv; + /* Blocks reserved for just AGFL-based metadata. */ + struct xfs_ag_resv pag_agfl_resv; } xfs_perag_t; +static inline struct xfs_ag_resv * +xfs_perag_resv( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + switch (type) { + case XFS_AG_RESV_METADATA: + return &pag->pag_meta_resv; + case XFS_AG_RESV_AGFL: + return &pag->pag_agfl_resv; + default: + return NULL; + } +} + extern void xfs_uuid_table_free(void); extern int xfs_log_sbcount(xfs_mount_t *); extern __uint64_t xfs_default_resblks(xfs_mount_t *mp); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index c50479a..b421b28 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1569,14 +1569,15 @@ TRACE_EVENT(xfs_agf, TRACE_EVENT(xfs_free_extent, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, - xfs_extlen_t len, bool isfl, int haveleft, int haveright), - TP_ARGS(mp, agno, agbno, len, isfl, haveleft, haveright), + xfs_extlen_t len, enum xfs_ag_resv_type resv, int haveleft, + int haveright), + TP_ARGS(mp, agno, agbno, len, resv, haveleft, haveright), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_agnumber_t, agno) __field(xfs_agblock_t, agbno) __field(xfs_extlen_t, len) - __field(int, isfl) + __field(int, resv) __field(int, haveleft) __field(int, haveright) ), @@ -1585,16 +1586,16 @@ TRACE_EVENT(xfs_free_extent, __entry->agno = agno; __entry->agbno = agbno; __entry->len = len; - __entry->isfl = isfl; + __entry->resv = resv; __entry->haveleft = haveleft; __entry->haveright = haveright; ), - TP_printk("dev %d:%d agno %u agbno %u len %u isfl %d %s", + TP_printk("dev %d:%d agno %u agbno %u len %u resv %d %s", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->agno, __entry->agbno, __entry->len, - __entry->isfl, + __entry->resv, __entry->haveleft ? (__entry->haveright ? "both" : "left") : (__entry->haveright ? "right" : "none")) @@ -1621,7 +1622,7 @@ DECLARE_EVENT_CLASS(xfs_alloc_class, __field(short, otype) __field(char, wasdel) __field(char, wasfromfl) - __field(char, isfl) + __field(int, resv) __field(char, userdata) __field(xfs_fsblock_t, firstblock) ), @@ -1642,13 +1643,13 @@ DECLARE_EVENT_CLASS(xfs_alloc_class, __entry->otype = args->otype; __entry->wasdel = args->wasdel; __entry->wasfromfl = args->wasfromfl; - __entry->isfl = args->isfl; + __entry->resv = args->resv; __entry->userdata = args->userdata; __entry->firstblock = args->firstblock; ), TP_printk("dev %d:%d agno %u agbno %u minlen %u maxlen %u mod %u " "prod %u minleft %u total %u alignment %u minalignslop %u " - "len %u type %s otype %s wasdel %d wasfromfl %d isfl %d " + "len %u type %s otype %s wasdel %d wasfromfl %d resv %d " "userdata %d firstblock 0x%llx", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->agno, @@ -1666,7 +1667,7 @@ DECLARE_EVENT_CLASS(xfs_alloc_class, __print_symbolic(__entry->otype, XFS_ALLOC_TYPES), __entry->wasdel, __entry->wasfromfl, - __entry->isfl, + __entry->resv, __entry->userdata, (unsigned long long)__entry->firstblock) ) @@ -2558,21 +2559,6 @@ DEFINE_RMAPBT_EVENT(xfs_rmap_map_gtrec); DEFINE_RMAPBT_EVENT(xfs_rmap_convert_gtrec); DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result); -/* dummy definitions to avoid breaking bisectability; will be removed later */ -#ifndef XFS_AG_RESV_DUMMY -#define XFS_AG_RESV_DUMMY -enum xfs_ag_resv_type { - XFS_AG_RESV_NONE = 0, - XFS_AG_RESV_METADATA, - XFS_AG_RESV_AGFL, -}; -struct xfs_ag_resv { - xfs_extlen_t ar_reserved; - xfs_extlen_t ar_asked; -}; -#define xfs_perag_resv(...) NULL -#endif - /* per-AG reservation */ DECLARE_EVENT_CLASS(xfs_ag_resv_class, TP_PROTO(struct xfs_perag *pag, enum xfs_ag_resv_type resv, diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index d1b8833..ecb9a68 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c @@ -125,7 +125,8 @@ xfs_trans_free_extent( struct xfs_extent *extp; int error; - error = xfs_free_extent(tp, start_block, ext_len, oinfo); + error = xfs_free_extent(tp, start_block, ext_len, oinfo, + XFS_AG_RESV_NONE); /* * Mark the transaction dirty, even on error. This ensures the From darrick.wong@oracle.com Thu Jun 16 20:23:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EF41E7DF6 for ; Thu, 16 Jun 2016 20:23:38 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id BB6D98F804B for ; Thu, 16 Jun 2016 18:23:38 -0700 (PDT) X-ASG-Debug-ID: 1466126616-04cb6c542757560001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Si5pmgLtcN2BEGyt (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:36 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1NXLf027503 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:34 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NXW5015359 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:33 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NX6s024102; Fri, 17 Jun 2016 01:23:33 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:32 -0700 Subject: [PATCH 053/119] xfs: define tracepoints for refcount btree activities From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 053/119] xfs: define tracepoints for refcount btree activities To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:31 -0700 Message-ID: <146612661116.12839.16240431642040339922.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126616 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12142 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Define all the tracepoints we need to inspect the refcount btree runtime operation. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_trace.h | 302 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index b421b28..6ed7cbf 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -40,6 +40,16 @@ struct xfs_inode_log_format; struct xfs_bmbt_irec; struct xfs_btree_cur; +#ifndef XFS_REFCOUNT_IREC_PLACEHOLDER +#define XFS_REFCOUNT_IREC_PLACEHOLDER +/* Placeholder definition to avoid breaking bisectability. */ +struct xfs_refcount_irec { + xfs_agblock_t rc_startblock; /* starting block number */ + xfs_extlen_t rc_blockcount; /* count of free blocks */ + xfs_nlink_t rc_refcount; /* number of inodes linked here */ +}; +#endif + DECLARE_EVENT_CLASS(xfs_attr_list_class, TP_PROTO(struct xfs_attr_list_context *ctx), TP_ARGS(ctx), @@ -2613,6 +2623,298 @@ DEFINE_AG_RESV_EVENT(xfs_ag_resv_needed); DEFINE_AG_ERROR_EVENT(xfs_ag_resv_free_error); DEFINE_AG_ERROR_EVENT(xfs_ag_resv_init_error); +/* refcount tracepoint classes */ + +/* reuse the discard trace class for agbno/aglen-based traces */ +#define DEFINE_AG_EXTENT_EVENT(name) DEFINE_DISCARD_EVENT(name) + +/* ag btree lookup tracepoint class */ +#define XFS_AG_BTREE_CMP_FORMAT_STR \ + { XFS_LOOKUP_EQ, "eq" }, \ + { XFS_LOOKUP_LE, "le" }, \ + { XFS_LOOKUP_GE, "ge" } +DECLARE_EVENT_CLASS(xfs_ag_btree_lookup_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + xfs_agblock_t agbno, xfs_lookup_t dir), + TP_ARGS(mp, agno, agbno, dir), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, agbno) + __field(xfs_lookup_t, dir) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->agbno = agbno; + __entry->dir = dir; + ), + TP_printk("dev %d:%d agno %u agbno %u cmp %s(%d)\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->agbno, + __print_symbolic(__entry->dir, XFS_AG_BTREE_CMP_FORMAT_STR), + __entry->dir) +) + +#define DEFINE_AG_BTREE_LOOKUP_EVENT(name) \ +DEFINE_EVENT(xfs_ag_btree_lookup_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + xfs_agblock_t agbno, xfs_lookup_t dir), \ + TP_ARGS(mp, agno, agbno, dir)) + +/* single-rcext tracepoint class */ +DECLARE_EVENT_CLASS(xfs_refcount_extent_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + struct xfs_refcount_irec *irec), + TP_ARGS(mp, agno, irec), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, startblock) + __field(xfs_extlen_t, blockcount) + __field(xfs_nlink_t, refcount) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->startblock = irec->rc_startblock; + __entry->blockcount = irec->rc_blockcount; + __entry->refcount = irec->rc_refcount; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->startblock, + __entry->blockcount, + __entry->refcount) +) + +#define DEFINE_REFCOUNT_EXTENT_EVENT(name) \ +DEFINE_EVENT(xfs_refcount_extent_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + struct xfs_refcount_irec *irec), \ + TP_ARGS(mp, agno, irec)) + +/* single-rcext and an agbno tracepoint class */ +DECLARE_EVENT_CLASS(xfs_refcount_extent_at_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + struct xfs_refcount_irec *irec, xfs_agblock_t agbno), + TP_ARGS(mp, agno, irec, agbno), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, startblock) + __field(xfs_extlen_t, blockcount) + __field(xfs_nlink_t, refcount) + __field(xfs_agblock_t, agbno) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->startblock = irec->rc_startblock; + __entry->blockcount = irec->rc_blockcount; + __entry->refcount = irec->rc_refcount; + __entry->agbno = agbno; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u @ agbno %u\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->startblock, + __entry->blockcount, + __entry->refcount, + __entry->agbno) +) + +#define DEFINE_REFCOUNT_EXTENT_AT_EVENT(name) \ +DEFINE_EVENT(xfs_refcount_extent_at_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + struct xfs_refcount_irec *irec, xfs_agblock_t agbno), \ + TP_ARGS(mp, agno, irec, agbno)) + +/* double-rcext tracepoint class */ +DECLARE_EVENT_CLASS(xfs_refcount_double_extent_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2), + TP_ARGS(mp, agno, i1, i2), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, i1_startblock) + __field(xfs_extlen_t, i1_blockcount) + __field(xfs_nlink_t, i1_refcount) + __field(xfs_agblock_t, i2_startblock) + __field(xfs_extlen_t, i2_blockcount) + __field(xfs_nlink_t, i2_refcount) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->i1_startblock = i1->rc_startblock; + __entry->i1_blockcount = i1->rc_blockcount; + __entry->i1_refcount = i1->rc_refcount; + __entry->i2_startblock = i2->rc_startblock; + __entry->i2_blockcount = i2->rc_blockcount; + __entry->i2_refcount = i2->rc_refcount; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- " + "agbno %u len %u refcount %u\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->i1_startblock, + __entry->i1_blockcount, + __entry->i1_refcount, + __entry->i2_startblock, + __entry->i2_blockcount, + __entry->i2_refcount) +) + +#define DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(name) \ +DEFINE_EVENT(xfs_refcount_double_extent_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2), \ + TP_ARGS(mp, agno, i1, i2)) + +/* double-rcext and an agbno tracepoint class */ +DECLARE_EVENT_CLASS(xfs_refcount_double_extent_at_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2, + xfs_agblock_t agbno), + TP_ARGS(mp, agno, i1, i2, agbno), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, i1_startblock) + __field(xfs_extlen_t, i1_blockcount) + __field(xfs_nlink_t, i1_refcount) + __field(xfs_agblock_t, i2_startblock) + __field(xfs_extlen_t, i2_blockcount) + __field(xfs_nlink_t, i2_refcount) + __field(xfs_agblock_t, agbno) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->i1_startblock = i1->rc_startblock; + __entry->i1_blockcount = i1->rc_blockcount; + __entry->i1_refcount = i1->rc_refcount; + __entry->i2_startblock = i2->rc_startblock; + __entry->i2_blockcount = i2->rc_blockcount; + __entry->i2_refcount = i2->rc_refcount; + __entry->agbno = agbno; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- " + "agbno %u len %u refcount %u @ agbno %u\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->i1_startblock, + __entry->i1_blockcount, + __entry->i1_refcount, + __entry->i2_startblock, + __entry->i2_blockcount, + __entry->i2_refcount, + __entry->agbno) +) + +#define DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(name) \ +DEFINE_EVENT(xfs_refcount_double_extent_at_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2, \ + xfs_agblock_t agbno), \ + TP_ARGS(mp, agno, i1, i2, agbno)) + +/* triple-rcext tracepoint class */ +DECLARE_EVENT_CLASS(xfs_refcount_triple_extent_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2, + struct xfs_refcount_irec *i3), + TP_ARGS(mp, agno, i1, i2, i3), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, i1_startblock) + __field(xfs_extlen_t, i1_blockcount) + __field(xfs_nlink_t, i1_refcount) + __field(xfs_agblock_t, i2_startblock) + __field(xfs_extlen_t, i2_blockcount) + __field(xfs_nlink_t, i2_refcount) + __field(xfs_agblock_t, i3_startblock) + __field(xfs_extlen_t, i3_blockcount) + __field(xfs_nlink_t, i3_refcount) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->i1_startblock = i1->rc_startblock; + __entry->i1_blockcount = i1->rc_blockcount; + __entry->i1_refcount = i1->rc_refcount; + __entry->i2_startblock = i2->rc_startblock; + __entry->i2_blockcount = i2->rc_blockcount; + __entry->i2_refcount = i2->rc_refcount; + __entry->i3_startblock = i3->rc_startblock; + __entry->i3_blockcount = i3->rc_blockcount; + __entry->i3_refcount = i3->rc_refcount; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u refcount %u -- " + "agbno %u len %u refcount %u -- " + "agbno %u len %u refcount %u\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->i1_startblock, + __entry->i1_blockcount, + __entry->i1_refcount, + __entry->i2_startblock, + __entry->i2_blockcount, + __entry->i2_refcount, + __entry->i3_startblock, + __entry->i3_blockcount, + __entry->i3_refcount) +); + +#define DEFINE_REFCOUNT_TRIPLE_EXTENT_EVENT(name) \ +DEFINE_EVENT(xfs_refcount_triple_extent_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + struct xfs_refcount_irec *i1, struct xfs_refcount_irec *i2, \ + struct xfs_refcount_irec *i3), \ + TP_ARGS(mp, agno, i1, i2, i3)) + +/* refcount btree tracepoints */ +DEFINE_BUSY_EVENT(xfs_refcountbt_alloc_block); +DEFINE_BUSY_EVENT(xfs_refcountbt_free_block); +DEFINE_AG_BTREE_LOOKUP_EVENT(xfs_refcountbt_lookup); +DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcountbt_get); +DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcountbt_update); +DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcountbt_insert); +DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcountbt_delete); +DEFINE_AG_ERROR_EVENT(xfs_refcountbt_insert_error); +DEFINE_AG_ERROR_EVENT(xfs_refcountbt_delete_error); +DEFINE_AG_ERROR_EVENT(xfs_refcountbt_update_error); + +/* refcount adjustment tracepoints */ +DEFINE_AG_EXTENT_EVENT(xfs_refcount_increase); +DEFINE_AG_EXTENT_EVENT(xfs_refcount_decrease); +DEFINE_REFCOUNT_TRIPLE_EXTENT_EVENT(xfs_refcount_merge_center_extents); +DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_modify_extent); +DEFINE_REFCOUNT_EXTENT_AT_EVENT(xfs_refcount_split_extent); +DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_merge_left_extent); +DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_merge_right_extent); +DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(xfs_refcount_find_left_extent); +DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(xfs_refcount_find_right_extent); +DEFINE_AG_ERROR_EVENT(xfs_refcount_adjust_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_merge_center_extents_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_modify_extent_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_split_extent_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_merge_left_extent_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_merge_right_extent_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_find_left_extent_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_find_right_extent_error); +DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_rec_order_error); + +/* reflink helpers */ +DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared); +DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared_result); +DEFINE_AG_ERROR_EVENT(xfs_refcount_find_shared_error); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:23:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 110867DD4 for ; Thu, 16 Jun 2016 20:23:49 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id D47AB8F804B for ; Thu, 16 Jun 2016 18:23:48 -0700 (PDT) X-ASG-Debug-ID: 1466126626-04cbb01fed69700001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 2XfKrGDVI5GAKErS (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:46 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1NgSp027574 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:42 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Nesv008756 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:40 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NdEO024120; Fri, 17 Jun 2016 01:23:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:39 -0700 Subject: [PATCH 054/119] xfs: introduce refcount btree definitions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 054/119] xfs: introduce refcount btree definitions To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:37 -0700 Message-ID: <146612661755.12839.13699464885618790847.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126626 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9262 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add new per-AG refcount btree definitions to the per-AG structures. v2: Move the reflink inode flag out of the way of the DAX flag, and add the new cowextsize flag. v3: Don't allow pNFS to export reflinked files; this will be removed some day when the Linux pNFS server supports it. [hch: don't allow pNFS export of reflinked files] [darrick: fix the feature test in hch's patch] Signed-off-by: Darrick J. Wong Signed-off-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_alloc.c | 5 +++++ fs/xfs/libxfs/xfs_btree.c | 5 +++-- fs/xfs/libxfs/xfs_btree.h | 3 +++ fs/xfs/libxfs/xfs_format.h | 29 ++++++++++++++++++++++++++--- fs/xfs/libxfs/xfs_rmap_btree.c | 7 +++++-- fs/xfs/libxfs/xfs_types.h | 2 +- fs/xfs/xfs_inode.h | 5 +++++ fs/xfs/xfs_mount.h | 3 +++ fs/xfs/xfs_pnfs.c | 7 +++++++ 9 files changed, 58 insertions(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 5f05c4e..9009b1f 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2448,6 +2448,10 @@ xfs_agf_verify( be32_to_cpu(agf->agf_btreeblks) > be32_to_cpu(agf->agf_length)) return false; + if (xfs_sb_version_hasreflink(&mp->m_sb) && + be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS) + return false; + return true;; } @@ -2568,6 +2572,7 @@ xfs_alloc_read_agf( be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); pag->pagf_levels[XFS_BTNUM_RMAPi] = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); + pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level); spin_lock_init(&pag->pagb_lock); pag->pagb_count = 0; #ifdef __KERNEL__ diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 50b2c32..1593239 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -45,9 +45,10 @@ kmem_zone_t *xfs_btree_cur_zone; */ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, - XFS_FIBT_MAGIC }, + XFS_FIBT_MAGIC, 0 }, { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC, - XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC } + XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC, + XFS_REFC_CRC_MAGIC } }; #define xfs_btree_magic(cur) \ xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 6fa13a9..9b5a921 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -66,6 +66,7 @@ union xfs_btree_rec { #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) #define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi) +#define XFS_BTNUM_REFC ((xfs_btnum_t)XFS_BTNUM_REFCi) /* * For logging record fields. @@ -99,6 +100,7 @@ do { \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ + case XFS_BTNUM_REFC: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -121,6 +123,7 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ case XFS_BTNUM_RMAP: \ __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ + case XFS_BTNUM_REFC: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 1b08237..63a97a9 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -456,6 +456,7 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ +#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ XFS_SB_FEAT_RO_COMPAT_RMAPBT) @@ -546,6 +547,12 @@ static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp) (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT); } +static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp) +{ + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && + (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK); +} + /* * end of superblock version macros */ @@ -640,12 +647,15 @@ typedef struct xfs_agf { __be32 agf_btreeblks; /* # of blocks held in AGF btrees */ uuid_t agf_uuid; /* uuid of filesystem */ + __be32 agf_refcount_root; /* refcount tree root block */ + __be32 agf_refcount_level; /* refcount btree levels */ + /* * reserve some contiguous space for future logged fields before we add * the unlogged fields. This makes the range logging via flags and * structure offsets much simpler. */ - __be64 agf_spare64[16]; + __be64 agf_spare64[15]; /* unlogged fields, written during buffer writeback. */ __be64 agf_lsn; /* last write sequence */ @@ -1033,9 +1043,14 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) * 16 bits of the XFS_XFLAG_s range. */ #define XFS_DIFLAG2_DAX_BIT 0 /* use DAX for this inode */ +#define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */ +#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */ #define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT) +#define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT) +#define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT) -#define XFS_DIFLAG2_ANY (XFS_DIFLAG2_DAX) +#define XFS_DIFLAG2_ANY \ + (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE) /* * Inode number format: @@ -1382,7 +1397,8 @@ xfs_rmap_ino_owner( #define XFS_RMAP_OWN_AG (-5ULL) /* AG freespace btree blocks */ #define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */ #define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ -#define XFS_RMAP_OWN_MIN (-8ULL) /* guard */ +#define XFS_RMAP_OWN_REFC (-8ULL) /* refcount tree */ +#define XFS_RMAP_OWN_MIN (-9ULL) /* guard */ #define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63))) @@ -1530,6 +1546,13 @@ xfs_owner_info_pack( } /* + * Reference Count Btree format definitions + * + */ +#define XFS_REFC_CRC_MAGIC 0x52334643 /* 'R3FC' */ + + +/* * BMAP Btree format definitions * * This includes both the root block definition that sits inside an inode fork diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c index 9adb930..090dbbe 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.c +++ b/fs/xfs/libxfs/xfs_rmap_btree.c @@ -475,6 +475,9 @@ void xfs_rmapbt_compute_maxlevels( struct xfs_mount *mp) { - mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, - mp->m_rmap_mnr, mp->m_sb.sb_agblocks); + if (xfs_sb_version_hasreflink(&mp->m_sb)) + mp->m_rmap_maxlevels = XFS_BTREE_MAXLEVELS; + else + mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, + mp->m_rmap_mnr, mp->m_sb.sb_agblocks); } diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h index da87796..690d616 100644 --- a/fs/xfs/libxfs/xfs_types.h +++ b/fs/xfs/libxfs/xfs_types.h @@ -112,7 +112,7 @@ typedef enum { typedef enum { XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi, - XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_MAX + XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_MAX } xfs_btnum_t; struct xfs_name { diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 633f2af..d0ea6ff 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -202,6 +202,11 @@ xfs_get_initial_prid(struct xfs_inode *dp) return XFS_PROJID_DEFAULT; } +static inline bool xfs_is_reflink_inode(struct xfs_inode *ip) +{ + return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; +} + /* * In-core inode flags. */ diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index e18d74e..823ee63 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -391,6 +391,9 @@ typedef struct xfs_perag { struct xfs_ag_resv pag_meta_resv; /* Blocks reserved for just AGFL-based metadata. */ struct xfs_ag_resv pag_agfl_resv; + + /* reference count */ + __uint8_t pagf_refcount_level; } xfs_perag_t; static inline struct xfs_ag_resv * diff --git a/fs/xfs/xfs_pnfs.c b/fs/xfs/xfs_pnfs.c index d5b7566..b21f532 100644 --- a/fs/xfs/xfs_pnfs.c +++ b/fs/xfs/xfs_pnfs.c @@ -139,6 +139,13 @@ xfs_fs_map_blocks( return -ENXIO; /* + * The pNFS block layout spec actually supports reflink like + * functionality, but the Linux pNFS server doesn't implement it yet. + */ + if (xfs_is_reflink_inode(ip)) + return -ENXIO; + + /* * Lock out any other I/O before we flush and invalidate the pagecache, * and then hand out a layout to the remote system. This is very * similar to direct I/O, except that the synchronization is much more From darrick.wong@oracle.com Thu Jun 16 20:23:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2D9FC7DF9 for ; Thu, 16 Jun 2016 20:23:51 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id E28A1304039 for ; Thu, 16 Jun 2016 18:23:50 -0700 (PDT) X-ASG-Debug-ID: 1466126629-04bdf01e1795aa0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id cDrPpzcfq0blw1Sl (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:49 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Nkb5008296 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:47 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NkWD008806 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:46 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NjuE019776; Fri, 17 Jun 2016 01:23:46 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:45 -0700 Subject: [PATCH 055/119] xfs: add refcount btree stats infrastructure From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 055/119] xfs: add refcount btree stats infrastructure To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:44 -0700 Message-ID: <146612662397.12839.11882093928585610827.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126629 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2941 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines The refcount btree presents the same stats as the other btrees, so add all the code for that now. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_btree.h | 5 +++-- fs/xfs/xfs_stats.c | 1 + fs/xfs/xfs_stats.h | 18 +++++++++++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 9b5a921..93e761e 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -100,7 +100,7 @@ do { \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ - case XFS_BTNUM_REFC: break; \ + case XFS_BTNUM_REFC: __XFS_BTREE_STATS_INC(__mp, refcbt, stat); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -123,7 +123,8 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ case XFS_BTNUM_RMAP: \ __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ - case XFS_BTNUM_REFC: break; \ + case XFS_BTNUM_REFC: \ + __XFS_BTREE_STATS_ADD(__mp, refcbt, stat, val); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c index f04f547..e447deb 100644 --- a/fs/xfs/xfs_stats.c +++ b/fs/xfs/xfs_stats.c @@ -62,6 +62,7 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf) { "ibt2", XFSSTAT_END_IBT_V2 }, { "fibt2", XFSSTAT_END_FIBT_V2 }, { "rmapbt", XFSSTAT_END_RMAP_V2 }, + { "refcntbt", XFSSTAT_END_REFCOUNT }, /* we print both series of quota information together */ { "qm", XFSSTAT_END_QM }, }; diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h index 657865f..79ad2e6 100644 --- a/fs/xfs/xfs_stats.h +++ b/fs/xfs/xfs_stats.h @@ -213,7 +213,23 @@ struct xfsstats { __uint32_t xs_rmap_2_alloc; __uint32_t xs_rmap_2_free; __uint32_t xs_rmap_2_moves; -#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_RMAP_V2+6) +#define XFSSTAT_END_REFCOUNT (XFSSTAT_END_RMAP_V2 + 15) + __uint32_t xs_refcbt_2_lookup; + __uint32_t xs_refcbt_2_compare; + __uint32_t xs_refcbt_2_insrec; + __uint32_t xs_refcbt_2_delrec; + __uint32_t xs_refcbt_2_newroot; + __uint32_t xs_refcbt_2_killroot; + __uint32_t xs_refcbt_2_increment; + __uint32_t xs_refcbt_2_decrement; + __uint32_t xs_refcbt_2_lshift; + __uint32_t xs_refcbt_2_rshift; + __uint32_t xs_refcbt_2_split; + __uint32_t xs_refcbt_2_join; + __uint32_t xs_refcbt_2_alloc; + __uint32_t xs_refcbt_2_free; + __uint32_t xs_refcbt_2_moves; +#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_REFCOUNT + 6) __uint32_t xs_qm_dqreclaims; __uint32_t xs_qm_dqreclaim_misses; __uint32_t xs_qm_dquot_dups; From darrick.wong@oracle.com Thu Jun 16 20:23:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D20697E0B for ; Thu, 16 Jun 2016 20:23:57 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 58CF9AC003 for ; Thu, 16 Jun 2016 18:23:57 -0700 (PDT) X-ASG-Debug-ID: 1466126635-04cb6c542457600001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id rFzwrFU8wB6ls7ek (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:23:55 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1NrwZ008343 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:53 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NrJY015682 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:23:53 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1NqH6019833; Fri, 17 Jun 2016 01:23:52 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:51 -0700 Subject: [PATCH 056/119] xfs: refcount btree add more reserved blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 056/119] xfs: refcount btree add more reserved blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:50 -0700 Message-ID: <146612663025.12839.7110368805724068545.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126635 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1636 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since XFS reserves a small amount of space in each AG as the minimum free space needed for an operation, save some more space in case we touch the refcount btree. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 13 +++++++++++++ fs/xfs/libxfs/xfs_format.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 9009b1f..14f8a69d 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -52,10 +52,23 @@ STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); +unsigned int +xfs_refc_block( + struct xfs_mount *mp) +{ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + return XFS_RMAP_BLOCK(mp) + 1; + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + return XFS_FIBT_BLOCK(mp) + 1; + return XFS_IBT_BLOCK(mp) + 1; +} + xfs_extlen_t xfs_prealloc_blocks( struct xfs_mount *mp) { + if (xfs_sb_version_hasreflink(&mp->m_sb)) + return xfs_refc_block(mp) + 1; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) return XFS_RMAP_BLOCK(mp) + 1; if (xfs_sb_version_hasfinobt(&mp->m_sb)) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 63a97a9..adeeb08 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1551,6 +1551,8 @@ xfs_owner_info_pack( */ #define XFS_REFC_CRC_MAGIC 0x52334643 /* 'R3FC' */ +unsigned int xfs_refc_block(struct xfs_mount *mp); + /* * BMAP Btree format definitions From darrick.wong@oracle.com Thu Jun 16 20:24:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 382C57CB5 for ; Thu, 16 Jun 2016 20:24:08 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id E904130404E for ; Thu, 16 Jun 2016 18:24:07 -0700 (PDT) X-ASG-Debug-ID: 1466126644-04bdf01e1795ac0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id pbC8eS0fDJwafyU4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1O0eH027697 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:00 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1O0or020074 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:00 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Nwg0019887; Fri, 17 Jun 2016 01:23:58 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:23:58 -0700 Subject: [PATCH 057/119] xfs: define the on-disk refcount btree format From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 057/119] xfs: define the on-disk refcount btree format To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:23:56 -0700 Message-ID: <146612663650.12839.17431740697281020048.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126644 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 18584 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Start constructing the refcount btree implementation by establishing the on-disk format and everything needed to read, write, and manipulate the refcount btree blocks. v2: Calculate a separate maxlevels for the refcount btree. v3: Enable the tracking of per-cursor stats for refcount btrees. The refcount update code will use this to guess if it's time to split a refcountbt update across two transactions to avoid exhausing the transaction reservation. xfs_refcountbt_init_cursor can be called under the ilock, so use KM_NOFS to prevent fs activity with a lock held. This should shut up some of the lockdep warnings. Signed-off-by: Darrick J. Wong [hch: allocate the cursor with KM_NOFS to quiet lockdep] Signed-off-by: Christoph Hellwig --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_btree.c | 3 + fs/xfs/libxfs/xfs_btree.h | 12 ++ fs/xfs/libxfs/xfs_format.h | 32 ++++++ fs/xfs/libxfs/xfs_refcount_btree.c | 178 ++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount_btree.h | 67 ++++++++++++++ fs/xfs/libxfs/xfs_sb.c | 9 ++ fs/xfs/libxfs/xfs_shared.h | 2 fs/xfs/libxfs/xfs_trans_resv.c | 2 fs/xfs/libxfs/xfs_trans_resv.h | 1 fs/xfs/xfs_mount.c | 2 fs/xfs/xfs_mount.h | 3 + fs/xfs/xfs_ondisk.h | 3 + fs/xfs/xfs_trace.h | 11 -- 14 files changed, 315 insertions(+), 11 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_refcount_btree.c create mode 100644 fs/xfs/libxfs/xfs_refcount_btree.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index c7a864e..3f579af 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -55,6 +55,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_ag_resv.o \ xfs_rmap.o \ xfs_rmap_btree.o \ + xfs_refcount_btree.o \ xfs_sb.o \ xfs_symlink_remote.o \ xfs_trans_resv.o \ diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 1593239..9c84184 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -1214,6 +1214,9 @@ xfs_btree_set_refs( case XFS_BTNUM_RMAP: xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF); break; + case XFS_BTNUM_REFC: + xfs_buf_set_ref(bp, XFS_REFC_BTREE_REF); + break; default: ASSERT(0); } diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index 93e761e..dbf299f 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -43,6 +43,7 @@ union xfs_btree_key { xfs_alloc_key_t alloc; struct xfs_inobt_key inobt; struct xfs_rmap_key rmap; + struct xfs_refcount_key refc; }; union xfs_btree_rec { @@ -51,6 +52,7 @@ union xfs_btree_rec { struct xfs_alloc_rec alloc; struct xfs_inobt_rec inobt; struct xfs_rmap_rec rmap; + struct xfs_refcount_rec refc; }; /* @@ -221,6 +223,15 @@ union xfs_btree_irec { xfs_bmbt_irec_t b; xfs_inobt_rec_incore_t i; struct xfs_rmap_irec r; + struct xfs_refcount_irec rc; +}; + +/* Per-AG btree private information. */ +union xfs_btree_cur_private { + struct { + unsigned long nr_ops; /* # record updates */ + int shape_changes; /* # of extent splits */ + } refc; }; /* @@ -247,6 +258,7 @@ typedef struct xfs_btree_cur struct xfs_buf *agbp; /* agf/agi buffer pointer */ struct xfs_defer_ops *dfops; /* deferred updates */ xfs_agnumber_t agno; /* ag number */ + union xfs_btree_cur_private priv; } a; struct { /* needed for BMAP */ struct xfs_inode *ip; /* pointer to our inode */ diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index adeeb08..3b0cae2 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1553,6 +1553,38 @@ xfs_owner_info_pack( unsigned int xfs_refc_block(struct xfs_mount *mp); +/* + * Data record/key structure + * + * Each record associates a range of physical blocks (starting at + * rc_startblock and ending rc_blockcount blocks later) with a + * reference count (rc_refcount). A record is only stored in the + * btree if the refcount is > 2. An entry in the free block btree + * means that the refcount is 0, and no entries anywhere means that + * the refcount is 1, as was true in XFS before reflinking. + */ +struct xfs_refcount_rec { + __be32 rc_startblock; /* starting block number */ + __be32 rc_blockcount; /* count of blocks */ + __be32 rc_refcount; /* number of inodes linked here */ +}; + +struct xfs_refcount_key { + __be32 rc_startblock; /* starting block number */ +}; + +struct xfs_refcount_irec { + xfs_agblock_t rc_startblock; /* starting block number */ + xfs_extlen_t rc_blockcount; /* count of free blocks */ + xfs_nlink_t rc_refcount; /* number of inodes linked here */ +}; + +#define MAXREFCOUNT ((xfs_nlink_t)~0U) +#define MAXREFCEXTLEN ((xfs_extlen_t)~0U) + +/* btree pointer type */ +typedef __be32 xfs_refcount_ptr_t; + /* * BMAP Btree format definitions diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c new file mode 100644 index 0000000..359cf0c --- /dev/null +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_btree.h" +#include "xfs_bmap.h" +#include "xfs_refcount_btree.h" +#include "xfs_alloc.h" +#include "xfs_error.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" +#include "xfs_trans.h" +#include "xfs_bit.h" + +static struct xfs_btree_cur * +xfs_refcountbt_dup_cursor( + struct xfs_btree_cur *cur) +{ + return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, + cur->bc_private.a.agbp, cur->bc_private.a.agno, + cur->bc_private.a.dfops); +} + +STATIC bool +xfs_refcountbt_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); + struct xfs_perag *pag = bp->b_pag; + unsigned int level; + + if (block->bb_magic != cpu_to_be32(XFS_REFC_CRC_MAGIC)) + return false; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return false; + if (!xfs_btree_sblock_v5hdr_verify(bp)) + return false; + + level = be16_to_cpu(block->bb_level); + if (pag && pag->pagf_init) { + if (level >= pag->pagf_refcount_level) + return false; + } else if (level >= mp->m_refc_maxlevels) + return false; + + return xfs_btree_sblock_verify(bp, mp->m_refc_mxr[level != 0]); +} + +STATIC void +xfs_refcountbt_read_verify( + struct xfs_buf *bp) +{ + if (!xfs_btree_sblock_verify_crc(bp)) + xfs_buf_ioerror(bp, -EFSBADCRC); + else if (!xfs_refcountbt_verify(bp)) + xfs_buf_ioerror(bp, -EFSCORRUPTED); + + if (bp->b_error) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_verifier_error(bp); + } +} + +STATIC void +xfs_refcountbt_write_verify( + struct xfs_buf *bp) +{ + if (!xfs_refcountbt_verify(bp)) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_buf_ioerror(bp, -EFSCORRUPTED); + xfs_verifier_error(bp); + return; + } + xfs_btree_sblock_calc_crc(bp); + +} + +const struct xfs_buf_ops xfs_refcountbt_buf_ops = { + .name = "xfs_refcountbt", + .verify_read = xfs_refcountbt_read_verify, + .verify_write = xfs_refcountbt_write_verify, +}; + +static const struct xfs_btree_ops xfs_refcountbt_ops = { + .rec_len = sizeof(struct xfs_refcount_rec), + .key_len = sizeof(struct xfs_refcount_key), + + .dup_cursor = xfs_refcountbt_dup_cursor, + .buf_ops = &xfs_refcountbt_buf_ops, +}; + +/* + * Allocate a new refcount btree cursor. + */ +struct xfs_btree_cur * +xfs_refcountbt_init_cursor( + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno, + struct xfs_defer_ops *dfops) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + struct xfs_btree_cur *cur; + + ASSERT(agno != NULLAGNUMBER); + ASSERT(agno < mp->m_sb.sb_agcount); + cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); + + cur->bc_tp = tp; + cur->bc_mp = mp; + cur->bc_btnum = XFS_BTNUM_REFC; + cur->bc_blocklog = mp->m_sb.sb_blocklog; + cur->bc_ops = &xfs_refcountbt_ops; + + cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); + + cur->bc_private.a.agbp = agbp; + cur->bc_private.a.agno = agno; + cur->bc_private.a.dfops = dfops; + cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; + + cur->bc_private.a.priv.refc.nr_ops = 0; + cur->bc_private.a.priv.refc.shape_changes = 0; + + return cur; +} + +/* + * Calculate the number of records in a refcount btree block. + */ +int +xfs_refcountbt_maxrecs( + struct xfs_mount *mp, + int blocklen, + bool leaf) +{ + blocklen -= XFS_REFCOUNT_BLOCK_LEN; + + if (leaf) + return blocklen / sizeof(struct xfs_refcount_rec); + return blocklen / (sizeof(struct xfs_refcount_key) + + sizeof(xfs_refcount_ptr_t)); +} + +/* Compute the maximum height of a refcount btree. */ +void +xfs_refcountbt_compute_maxlevels( + struct xfs_mount *mp) +{ + mp->m_refc_maxlevels = xfs_btree_compute_maxlevels(mp, + mp->m_refc_mnr, mp->m_sb.sb_agblocks); +} diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h new file mode 100644 index 0000000..9e9ad7c --- /dev/null +++ b/fs/xfs/libxfs/xfs_refcount_btree.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_REFCOUNT_BTREE_H__ +#define __XFS_REFCOUNT_BTREE_H__ + +/* + * Reference Count Btree on-disk structures + */ + +struct xfs_buf; +struct xfs_btree_cur; +struct xfs_mount; + +/* + * Btree block header size + */ +#define XFS_REFCOUNT_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN + +/* + * Record, key, and pointer address macros for btree blocks. + * + * (note that some of these may appear unused, but they are used in userspace) + */ +#define XFS_REFCOUNT_REC_ADDR(block, index) \ + ((struct xfs_refcount_rec *) \ + ((char *)(block) + \ + XFS_REFCOUNT_BLOCK_LEN + \ + (((index) - 1) * sizeof(struct xfs_refcount_rec)))) + +#define XFS_REFCOUNT_KEY_ADDR(block, index) \ + ((struct xfs_refcount_key *) \ + ((char *)(block) + \ + XFS_REFCOUNT_BLOCK_LEN + \ + ((index) - 1) * sizeof(struct xfs_refcount_key))) + +#define XFS_REFCOUNT_PTR_ADDR(block, index, maxrecs) \ + ((xfs_refcount_ptr_t *) \ + ((char *)(block) + \ + XFS_REFCOUNT_BLOCK_LEN + \ + (maxrecs) * sizeof(struct xfs_refcount_key) + \ + ((index) - 1) * sizeof(xfs_refcount_ptr_t))) + +extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp, + struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, + struct xfs_defer_ops *dfops); +extern int xfs_refcountbt_maxrecs(struct xfs_mount *mp, int blocklen, + bool leaf); +extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); + +#endif /* __XFS_REFCOUNT_BTREE_H__ */ diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index 59c9f59..a937071 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c @@ -38,6 +38,8 @@ #include "xfs_ialloc_btree.h" #include "xfs_log.h" #include "xfs_rmap_btree.h" +#include "xfs_bmap.h" +#include "xfs_refcount_btree.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. @@ -740,6 +742,13 @@ xfs_sb_mount_common( mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2; mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2; + mp->m_refc_mxr[0] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, + true); + mp->m_refc_mxr[1] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, + false); + mp->m_refc_mnr[0] = mp->m_refc_mxr[0] / 2; + mp->m_refc_mnr[1] = mp->m_refc_mxr[1] / 2; + mp->m_bsize = XFS_FSB_TO_BB(mp, 1); mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK, sbp->sb_inopblock); diff --git a/fs/xfs/libxfs/xfs_shared.h b/fs/xfs/libxfs/xfs_shared.h index 0c5b30b..c6f4eb4 100644 --- a/fs/xfs/libxfs/xfs_shared.h +++ b/fs/xfs/libxfs/xfs_shared.h @@ -39,6 +39,7 @@ extern const struct xfs_buf_ops xfs_agf_buf_ops; extern const struct xfs_buf_ops xfs_agfl_buf_ops; extern const struct xfs_buf_ops xfs_allocbt_buf_ops; extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; +extern const struct xfs_buf_ops xfs_refcountbt_buf_ops; extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; extern const struct xfs_buf_ops xfs_bmbt_buf_ops; @@ -122,6 +123,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *); #define XFS_INO_REF 2 #define XFS_ATTR_BTREE_REF 1 #define XFS_DQUOT_REF 1 +#define XFS_REFC_BTREE_REF 1 /* * Flags for xfs_trans_ichgtime(). diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index 301ef2f..7c840e1 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -73,7 +73,7 @@ xfs_calc_buf_res( * * Keep in mind that max depth is calculated separately for each type of tree. */ -static uint +uint xfs_allocfree_log_count( struct xfs_mount *mp, uint num_ops) diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h index 0eb46ed..36a1511 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.h +++ b/fs/xfs/libxfs/xfs_trans_resv.h @@ -102,5 +102,6 @@ struct xfs_trans_resv { #define XFS_ATTRRM_LOG_COUNT 3 void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp); +uint xfs_allocfree_log_count(struct xfs_mount *mp, uint num_ops); #endif /* __XFS_TRANS_RESV_H__ */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 879f3ef..48b8b1e 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -43,6 +43,7 @@ #include "xfs_icache.h" #include "xfs_sysfs.h" #include "xfs_rmap_btree.h" +#include "xfs_refcount_btree.h" static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -682,6 +683,7 @@ xfs_mountfs( xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); xfs_ialloc_compute_maxlevels(mp); xfs_rmapbt_compute_maxlevels(mp); + xfs_refcountbt_compute_maxlevels(mp); xfs_set_maxicount(mp); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 823ee63..a516a1f 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -118,10 +118,13 @@ typedef struct xfs_mount { uint m_inobt_mnr[2]; /* min inobt btree records */ uint m_rmap_mxr[2]; /* max rmap btree records */ uint m_rmap_mnr[2]; /* min rmap btree records */ + uint m_refc_mxr[2]; /* max refc btree records */ + uint m_refc_mnr[2]; /* min refc btree records */ uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_in_maxlevels; /* max inobt btree levels. */ uint m_rmap_maxlevels; /* max rmap btree levels */ + uint m_refc_maxlevels; /* max refcount btree level */ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ uint m_alloc_set_aside; /* space we can't use */ uint m_ag_max_usable; /* max space per AG */ diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 48d544f..3742216 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -47,6 +47,8 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_dsymlink_hdr, 56); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_key, 4); XFS_CHECK_STRUCT_SIZE(struct xfs_inobt_rec, 16); + XFS_CHECK_STRUCT_SIZE(struct xfs_refcount_key, 4); + XFS_CHECK_STRUCT_SIZE(struct xfs_refcount_rec, 12); XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_key, 20); XFS_CHECK_STRUCT_SIZE(struct xfs_rmap_rec, 24); XFS_CHECK_STRUCT_SIZE(struct xfs_timestamp, 8); @@ -54,6 +56,7 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(xfs_alloc_ptr_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_alloc_rec_t, 8); XFS_CHECK_STRUCT_SIZE(xfs_inobt_ptr_t, 4); + XFS_CHECK_STRUCT_SIZE(xfs_refcount_ptr_t, 4); XFS_CHECK_STRUCT_SIZE(xfs_rmap_ptr_t, 4); /* dir/attr trees */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 6ed7cbf..67ce2d8 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -39,16 +39,7 @@ struct xfs_buf_log_format; struct xfs_inode_log_format; struct xfs_bmbt_irec; struct xfs_btree_cur; - -#ifndef XFS_REFCOUNT_IREC_PLACEHOLDER -#define XFS_REFCOUNT_IREC_PLACEHOLDER -/* Placeholder definition to avoid breaking bisectability. */ -struct xfs_refcount_irec { - xfs_agblock_t rc_startblock; /* starting block number */ - xfs_extlen_t rc_blockcount; /* count of free blocks */ - xfs_nlink_t rc_refcount; /* number of inodes linked here */ -}; -#endif +struct xfs_refcount_irec; DECLARE_EVENT_CLASS(xfs_attr_list_class, TP_PROTO(struct xfs_attr_list_context *ctx), From darrick.wong@oracle.com Thu Jun 16 20:24:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id BDECD7DE8 for ; Thu, 16 Jun 2016 20:24:15 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 85573304039 for ; Thu, 16 Jun 2016 18:24:15 -0700 (PDT) X-ASG-Debug-ID: 1466126654-04cb6c5426576c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id InCu555HPgnkIAie (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:14 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1O5ds027934 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:06 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1O5F8020400 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:05 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1O4Da024222; Fri, 17 Jun 2016 01:24:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:04 -0700 Subject: [PATCH 058/119] xfs: add refcount btree support to growfs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 058/119] xfs: add refcount btree support to growfs To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:03 -0700 Message-ID: <146612664301.12839.559089610866542364.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126654 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2019 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Modify the growfs code to initialize new refcount btree blocks. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_fsops.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index cd4de75..3c1ded1 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -257,6 +257,11 @@ xfs_growfs_data_private( agf->agf_longest = cpu_to_be32(tmpsize); if (xfs_sb_version_hascrc(&mp->m_sb)) uuid_copy(&agf->agf_uuid, &mp->m_sb.sb_meta_uuid); + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + agf->agf_refcount_root = cpu_to_be32( + xfs_refc_block(mp)); + agf->agf_refcount_level = cpu_to_be32(1); + } error = xfs_bwrite(bp); xfs_buf_relse(bp); @@ -448,6 +453,17 @@ xfs_growfs_data_private( rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); + /* account for refc btree root */ + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + rrec = XFS_RMAP_REC_ADDR(block, 5); + rrec->rm_startblock = cpu_to_be32( + xfs_refc_block(mp)); + rrec->rm_blockcount = cpu_to_be32(1); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + } + error = xfs_bwrite(bp); xfs_buf_relse(bp); if (error) @@ -505,6 +521,28 @@ xfs_growfs_data_private( goto error0; } + /* + * refcount btree root block + */ + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + bp = xfs_growfs_get_hdr_buf(mp, + XFS_AGB_TO_DADDR(mp, agno, xfs_refc_block(mp)), + BTOBB(mp->m_sb.sb_blocksize), 0, + &xfs_refcountbt_buf_ops); + if (!bp) { + error = -ENOMEM; + goto error0; + } + + xfs_btree_init_block(mp, bp, XFS_REFC_CRC_MAGIC, + 0, 0, agno, + XFS_BTREE_CRC_BLOCKS); + + error = xfs_bwrite(bp); + xfs_buf_relse(bp); + if (error) + goto error0; + } } xfs_trans_agblocks_delta(tp, nfree); /* From darrick.wong@oracle.com Thu Jun 16 20:24:16 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9C9F87DE8 for ; Thu, 16 Jun 2016 20:24:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6479B304039 for ; Thu, 16 Jun 2016 18:24:16 -0700 (PDT) X-ASG-Debug-ID: 1466126655-04cbb01fed69750001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id VXh6Y7fMDShHBf8O (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1OCXL028064 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:12 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1OCtS009615 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:12 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1OBoP019956; Fri, 17 Jun 2016 01:24:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:10 -0700 Subject: [PATCH 059/119] xfs: account for the refcount btree in the alloc/free log reservation From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 059/119] xfs: account for the refcount btree in the alloc/free log reservation To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:09 -0700 Message-ID: <146612664925.12839.17667207190553223295.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126655 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1499 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Every time we allocate or free an extent, we might need to split the refcount btree. Reserve some blocks in the transaction to handle this possibility. (Reproduced by generic/167 over NFS atop XFS) Signed-off-by: Christoph Hellwig [darrick.wong@oracle.com: add commit message] Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_trans_resv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index 7c840e1..a59838f 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -67,7 +67,8 @@ xfs_calc_buf_res( * Per-extent log reservation for the btree changes involved in freeing or * allocating an extent. In classic XFS there were two trees that will be * modified (bnobt + cntbt). With rmap enabled, there are three trees - * (rmapbt). The number of blocks reserved is based on the formula: + * (rmapbt). With reflink, there are four trees (refcountbt). The number of + * blocks reserved is based on the formula: * * num trees * ((2 blocks/level * max depth) - 1) * @@ -83,6 +84,8 @@ xfs_allocfree_log_count( blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1); + if (xfs_sb_version_hasreflink(&mp->m_sb)) + blocks += num_ops * (2 * mp->m_refc_maxlevels - 1); return blocks; } From darrick.wong@oracle.com Thu Jun 16 20:24:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C23967DE8 for ; Thu, 16 Jun 2016 20:24:27 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 38C9FAC002 for ; Thu, 16 Jun 2016 18:24:27 -0700 (PDT) X-ASG-Debug-ID: 1466126663-04cbb01fee69760001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id a9w0GxQKHAxuyDNC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:23 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1OIO1008795 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:19 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1OIBl009818 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:18 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1OHLu028469; Fri, 17 Jun 2016 01:24:17 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:17 -0700 Subject: [PATCH 060/119] xfs: add refcount btree operations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 060/119] xfs: add refcount btree operations To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:15 -0700 Message-ID: <146612665559.12839.8945136486858187070.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126663 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15934 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Implement the generic btree operations required to manipulate refcount btree blocks. The implementation is similar to the bmapbt, though it will only allocate and free blocks from the AG. v2: Remove init_rec_from_key since we no longer need it, and add tracepoints when refcount btree operations fail. Since the refcount root and level fields are separate from the existing roots and levels array, they need a separate logging flag. Signed-off-by: Darrick J. Wong [hch: fix logging of AGF refcount btree fields] Signed-off-by: Christoph Hellwig --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_alloc.c | 4 + fs/xfs/libxfs/xfs_format.h | 5 + fs/xfs/libxfs/xfs_refcount.c | 177 ++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount.h | 30 +++++ fs/xfs/libxfs/xfs_refcount_btree.c | 197 ++++++++++++++++++++++++++++++++++++ 6 files changed, 413 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/libxfs/xfs_refcount.c create mode 100644 fs/xfs/libxfs/xfs_refcount.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 3f579af..e0c3067 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -55,6 +55,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_ag_resv.o \ xfs_rmap.o \ xfs_rmap_btree.o \ + xfs_refcount.o \ xfs_refcount_btree.o \ xfs_sb.o \ xfs_symlink_remote.o \ diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 14f8a69d..be5d0df 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2326,6 +2326,10 @@ xfs_alloc_log_agf( offsetof(xfs_agf_t, agf_longest), offsetof(xfs_agf_t, agf_btreeblks), offsetof(xfs_agf_t, agf_uuid), + offsetof(xfs_agf_t, agf_refcount_root), + offsetof(xfs_agf_t, agf_refcount_level), + /* needed so that we don't log the whole rest of the structure: */ + offsetof(xfs_agf_t, agf_spare64), sizeof(xfs_agf_t) }; diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 3b0cae2..45bbdad 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -680,7 +680,10 @@ typedef struct xfs_agf { #define XFS_AGF_LONGEST 0x00000400 #define XFS_AGF_BTREEBLKS 0x00000800 #define XFS_AGF_UUID 0x00001000 -#define XFS_AGF_NUM_BITS 13 +#define XFS_AGF_REFCOUNT_ROOT 0x00002000 +#define XFS_AGF_REFCOUNT_LEVEL 0x00004000 +#define XFS_AGF_SPARE64 0x00008000 +#define XFS_AGF_NUM_BITS 16 #define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1) #define XFS_AGF_FLAGS \ diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c new file mode 100644 index 0000000..4d483b5 --- /dev/null +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_btree.h" +#include "xfs_bmap.h" +#include "xfs_refcount_btree.h" +#include "xfs_alloc.h" +#include "xfs_error.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" +#include "xfs_trans.h" +#include "xfs_bit.h" +#include "xfs_refcount.h" + +/* + * Look up the first record less than or equal to [bno, len] in the btree + * given by cur. + */ +int +xfs_refcountbt_lookup_le( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + int *stat) +{ + trace_xfs_refcountbt_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, + XFS_LOOKUP_LE); + cur->bc_rec.rc.rc_startblock = bno; + cur->bc_rec.rc.rc_blockcount = 0; + return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); +} + +/* + * Look up the first record greater than or equal to [bno, len] in the btree + * given by cur. + */ +int +xfs_refcountbt_lookup_ge( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + int *stat) +{ + trace_xfs_refcountbt_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, + XFS_LOOKUP_GE); + cur->bc_rec.rc.rc_startblock = bno; + cur->bc_rec.rc.rc_blockcount = 0; + return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); +} + +/* + * Get the data from the pointed-to record. + */ +int +xfs_refcountbt_get_rec( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec, + int *stat) +{ + union xfs_btree_rec *rec; + int error; + + error = xfs_btree_get_rec(cur, &rec, stat); + if (!error && *stat == 1) { + irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock); + irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount); + irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount); + trace_xfs_refcountbt_get(cur->bc_mp, cur->bc_private.a.agno, + irec); + } + return error; +} + +/* + * Update the record referred to by cur to the value given + * by [bno, len, refcount]. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_refcountbt_update( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec) +{ + union xfs_btree_rec rec; + int error; + + trace_xfs_refcountbt_update(cur->bc_mp, cur->bc_private.a.agno, irec); + rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock); + rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount); + rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount); + error = xfs_btree_update(cur, &rec); + if (error) + trace_xfs_refcountbt_update_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Insert the record referred to by cur to the value given + * by [bno, len, refcount]. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_refcountbt_insert( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec, + int *i) +{ + int error; + + trace_xfs_refcountbt_insert(cur->bc_mp, cur->bc_private.a.agno, irec); + cur->bc_rec.rc.rc_startblock = irec->rc_startblock; + cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount; + cur->bc_rec.rc.rc_refcount = irec->rc_refcount; + error = xfs_btree_insert(cur, i); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); +out_error: + if (error) + trace_xfs_refcountbt_insert_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Remove the record referred to by cur, then set the pointer to the spot + * where the record could be re-inserted, in case we want to increment or + * decrement the cursor. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_refcountbt_delete( + struct xfs_btree_cur *cur, + int *i) +{ + struct xfs_refcount_irec irec; + int found_rec; + int error; + + error = xfs_refcountbt_get_rec(cur, &irec, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + trace_xfs_refcountbt_delete(cur->bc_mp, cur->bc_private.a.agno, &irec); + error = xfs_btree_delete(cur, i); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); + if (error) + goto out_error; + error = xfs_refcountbt_lookup_ge(cur, irec.rc_startblock, &found_rec); +out_error: + if (error) + trace_xfs_refcountbt_delete_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h new file mode 100644 index 0000000..8ea65c6 --- /dev/null +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_REFCOUNT_H__ +#define __XFS_REFCOUNT_H__ + +extern int xfs_refcountbt_lookup_le(struct xfs_btree_cur *cur, + xfs_agblock_t bno, int *stat); +extern int xfs_refcountbt_lookup_ge(struct xfs_btree_cur *cur, + xfs_agblock_t bno, int *stat); +extern int xfs_refcountbt_get_rec(struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec, int *stat); + +#endif /* __XFS_REFCOUNT_H__ */ diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c index 359cf0c..7093c71 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.c +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -44,6 +44,153 @@ xfs_refcountbt_dup_cursor( cur->bc_private.a.dfops); } +STATIC void +xfs_refcountbt_set_root( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr, + int inc) +{ + struct xfs_buf *agbp = cur->bc_private.a.agbp; + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); + struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); + + ASSERT(ptr->s != 0); + + agf->agf_refcount_root = ptr->s; + be32_add_cpu(&agf->agf_refcount_level, inc); + pag->pagf_refcount_level += inc; + xfs_perag_put(pag); + + xfs_alloc_log_agf(cur->bc_tp, agbp, + XFS_AGF_REFCOUNT_ROOT | XFS_AGF_REFCOUNT_LEVEL); +} + +STATIC int +xfs_refcountbt_alloc_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *start, + union xfs_btree_ptr *new, + int *stat) +{ + struct xfs_alloc_arg args; /* block allocation args */ + int error; /* error return value */ + + memset(&args, 0, sizeof(args)); + args.tp = cur->bc_tp; + args.mp = cur->bc_mp; + args.type = XFS_ALLOCTYPE_NEAR_BNO; + args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, + xfs_refc_block(args.mp)); + args.firstblock = args.fsbno; + xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); + args.minlen = args.maxlen = args.prod = 1; + + error = xfs_alloc_vextent(&args); + if (error) + goto out_error; + trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, + args.agbno, 1); + if (args.fsbno == NULLFSBLOCK) { + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 0; + return 0; + } + ASSERT(args.agno == cur->bc_private.a.agno); + ASSERT(args.len == 1); + + new->s = cpu_to_be32(args.agbno); + + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 1; + return 0; + +out_error: + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); + return error; +} + +STATIC int +xfs_refcountbt_free_block( + struct xfs_btree_cur *cur, + struct xfs_buf *bp) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_trans *tp = cur->bc_tp; + xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); + struct xfs_owner_info oinfo; + + trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, + XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); + xfs_bmap_add_free(mp, cur->bc_private.a.dfops, fsbno, 1, + &oinfo); + xfs_trans_binval(tp, bp); + return 0; +} + +STATIC int +xfs_refcountbt_get_minrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_refc_mnr[level != 0]; +} + +STATIC int +xfs_refcountbt_get_maxrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_refc_mxr[level != 0]; +} + +STATIC void +xfs_refcountbt_init_key_from_rec( + union xfs_btree_key *key, + union xfs_btree_rec *rec) +{ + ASSERT(rec->refc.rc_startblock != 0); + + key->refc.rc_startblock = rec->refc.rc_startblock; +} + +STATIC void +xfs_refcountbt_init_rec_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_rec *rec) +{ + ASSERT(cur->bc_rec.rc.rc_startblock != 0); + + rec->refc.rc_startblock = cpu_to_be32(cur->bc_rec.rc.rc_startblock); + rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount); + rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount); +} + +STATIC void +xfs_refcountbt_init_ptr_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); + + ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); + ASSERT(agf->agf_refcount_root != 0); + + ptr->s = agf->agf_refcount_root; +} + +STATIC __int64_t +xfs_refcountbt_key_diff( + struct xfs_btree_cur *cur, + union xfs_btree_key *key) +{ + struct xfs_refcount_irec *rec = &cur->bc_rec.rc; + struct xfs_refcount_key *kp = &key->refc; + + return (__int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock; +} + STATIC bool xfs_refcountbt_verify( struct xfs_buf *bp) @@ -106,12 +253,62 @@ const struct xfs_buf_ops xfs_refcountbt_buf_ops = { .verify_write = xfs_refcountbt_write_verify, }; +#if defined(DEBUG) || defined(XFS_WARN) +STATIC int +xfs_refcountbt_keys_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return be32_to_cpu(k1->refc.rc_startblock) < + be32_to_cpu(k2->refc.rc_startblock); +} + +STATIC int +xfs_refcountbt_recs_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_rec *r1, + union xfs_btree_rec *r2) +{ + struct xfs_refcount_irec a, b; + + int ret = be32_to_cpu(r1->refc.rc_startblock) + + be32_to_cpu(r1->refc.rc_blockcount) <= + be32_to_cpu(r2->refc.rc_startblock); + if (!ret) { + a.rc_startblock = be32_to_cpu(r1->refc.rc_startblock); + a.rc_blockcount = be32_to_cpu(r1->refc.rc_blockcount); + a.rc_refcount = be32_to_cpu(r1->refc.rc_refcount); + b.rc_startblock = be32_to_cpu(r2->refc.rc_startblock); + b.rc_blockcount = be32_to_cpu(r2->refc.rc_blockcount); + b.rc_refcount = be32_to_cpu(r2->refc.rc_refcount); + trace_xfs_refcount_rec_order_error(cur->bc_mp, + cur->bc_private.a.agno, &a, &b); + } + + return ret; +} +#endif /* DEBUG */ + static const struct xfs_btree_ops xfs_refcountbt_ops = { .rec_len = sizeof(struct xfs_refcount_rec), .key_len = sizeof(struct xfs_refcount_key), .dup_cursor = xfs_refcountbt_dup_cursor, + .set_root = xfs_refcountbt_set_root, + .alloc_block = xfs_refcountbt_alloc_block, + .free_block = xfs_refcountbt_free_block, + .get_minrecs = xfs_refcountbt_get_minrecs, + .get_maxrecs = xfs_refcountbt_get_maxrecs, + .init_key_from_rec = xfs_refcountbt_init_key_from_rec, + .init_rec_from_cur = xfs_refcountbt_init_rec_from_cur, + .init_ptr_from_cur = xfs_refcountbt_init_ptr_from_cur, + .key_diff = xfs_refcountbt_key_diff, .buf_ops = &xfs_refcountbt_buf_ops, +#if defined(DEBUG) || defined(XFS_WARN) + .keys_inorder = xfs_refcountbt_keys_inorder, + .recs_inorder = xfs_refcountbt_recs_inorder, +#endif }; /* From darrick.wong@oracle.com Thu Jun 16 20:24:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 535D17CB4 for ; Thu, 16 Jun 2016 20:24:33 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 074638F804B for ; Thu, 16 Jun 2016 18:24:32 -0700 (PDT) X-ASG-Debug-ID: 1466126668-04bdf01e1395b00001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id uSJBJpuHXHXGqi5V (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:28 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1OQ68028170 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:24:26 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1OPsx014767 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:25 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1OOPH024420; Fri, 17 Jun 2016 01:24:25 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:24 -0700 Subject: [PATCH 061/119] xfs: create refcount update intent log items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 061/119] xfs: create refcount update intent log items To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:22 -0700 Message-ID: <146612666207.12839.4040372869535080968.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126668 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 22465 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create refcount update intent/done log items to record redo information in the log. Because we need to roll transactions between updating the bmbt mapping and updating the reverse mapping, we also have to track the status of the metadata updates that will be recorded in the post-roll transactions, just in case we crash before committing the final transaction. This mechanism enables log recovery to finish what was already started. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_log_format.h | 52 ++++- fs/xfs/xfs_refcount_item.c | 459 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_refcount_item.h | 100 +++++++++ fs/xfs/xfs_super.c | 21 ++ 5 files changed, 631 insertions(+), 2 deletions(-) create mode 100644 fs/xfs/xfs_refcount_item.c create mode 100644 fs/xfs/xfs_refcount_item.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index e0c3067..322c386 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -107,6 +107,7 @@ xfs-y += xfs_log.o \ xfs_extfree_item.o \ xfs_icreate_item.o \ xfs_inode_item.o \ + xfs_refcount_item.o \ xfs_rmap_item.o \ xfs_log_recover.o \ xfs_trans_ail.o \ diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index b9627b7..1dfa02c 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -112,7 +112,9 @@ static inline uint xlog_get_cycle(char *ptr) #define XLOG_REG_TYPE_ICREATE 20 #define XLOG_REG_TYPE_RUI_FORMAT 21 #define XLOG_REG_TYPE_RUD_FORMAT 22 -#define XLOG_REG_TYPE_MAX 22 +#define XLOG_REG_TYPE_CUI_FORMAT 23 +#define XLOG_REG_TYPE_CUD_FORMAT 24 +#define XLOG_REG_TYPE_MAX 24 /* * Flags to log operation header @@ -231,6 +233,8 @@ typedef struct xfs_trans_header { #define XFS_LI_ICREATE 0x123f #define XFS_LI_RUI 0x1240 /* rmap update intent */ #define XFS_LI_RUD 0x1241 +#define XFS_LI_CUI 0x1242 /* refcount update intent */ +#define XFS_LI_CUD 0x1243 #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ @@ -242,7 +246,9 @@ typedef struct xfs_trans_header { { XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \ { XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \ { XFS_LI_RUI, "XFS_LI_RUI" }, \ - { XFS_LI_RUD, "XFS_LI_RUD" } + { XFS_LI_RUD, "XFS_LI_RUD" }, \ + { XFS_LI_CUI, "XFS_LI_CUI" }, \ + { XFS_LI_CUD, "XFS_LI_CUD" } /* * Inode Log Item Format definitions. @@ -667,6 +673,48 @@ struct xfs_rud_log_format { }; /* + * CUI/CUD (refcount update) log format definitions + */ +struct xfs_phys_extent { + __uint64_t pe_startblock; + __uint32_t pe_len; + __uint32_t pe_flags; +}; + +/* refcount pe_flags: upper bits are flags, lower byte is type code */ +#define XFS_REFCOUNT_EXTENT_INCREASE 1 +#define XFS_REFCOUNT_EXTENT_DECREASE 2 +#define XFS_REFCOUNT_EXTENT_ALLOC_COW 3 +#define XFS_REFCOUNT_EXTENT_FREE_COW 4 +#define XFS_REFCOUNT_EXTENT_TYPE_MASK 0xFF + +/* + * This is the structure used to lay out a cui log item in the + * log. The cui_extents field is a variable size array whose + * size is given by cui_nextents. + */ +struct xfs_cui_log_format { + __uint16_t cui_type; /* cui log item type */ + __uint16_t cui_size; /* size of this item */ + __uint32_t cui_nextents; /* # extents to free */ + __uint64_t cui_id; /* cui identifier */ + struct xfs_phys_extent cui_extents[1]; /* array of extents */ +}; + +/* + * This is the structure used to lay out a cud log item in the + * log. The cud_extents array is a variable size array whose + * size is given by cud_nextents; + */ +struct xfs_cud_log_format { + __uint16_t cud_type; /* cud log item type */ + __uint16_t cud_size; /* size of this item */ + __uint32_t cud_nextents; /* # of extents freed */ + __uint64_t cud_cui_id; /* id of corresponding cui */ + struct xfs_phys_extent cud_extents[1]; /* array of extents */ +}; + +/* * Dquot Log format definitions. * * The first two fields must be the type and size fitting into diff --git a/fs/xfs/xfs_refcount_item.c b/fs/xfs/xfs_refcount_item.c new file mode 100644 index 0000000..681d068 --- /dev/null +++ b/fs/xfs/xfs_refcount_item.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_buf_item.h" +#include "xfs_refcount_item.h" +#include "xfs_log.h" + + +kmem_zone_t *xfs_cui_zone; +kmem_zone_t *xfs_cud_zone; + +static inline struct xfs_cui_log_item *CUI_ITEM(struct xfs_log_item *lip) +{ + return container_of(lip, struct xfs_cui_log_item, cui_item); +} + +void +xfs_cui_item_free( + struct xfs_cui_log_item *cuip) +{ + if (cuip->cui_format.cui_nextents > XFS_CUI_MAX_FAST_EXTENTS) + kmem_free(cuip); + else + kmem_zone_free(xfs_cui_zone, cuip); +} + +/* + * This returns the number of iovecs needed to log the given cui item. + * We only need 1 iovec for an cui item. It just logs the cui_log_format + * structure. + */ +static inline int +xfs_cui_item_sizeof( + struct xfs_cui_log_item *cuip) +{ + return sizeof(struct xfs_cui_log_format) + + (cuip->cui_format.cui_nextents - 1) * + sizeof(struct xfs_phys_extent); +} + +STATIC void +xfs_cui_item_size( + struct xfs_log_item *lip, + int *nvecs, + int *nbytes) +{ + *nvecs += 1; + *nbytes += xfs_cui_item_sizeof(CUI_ITEM(lip)); +} + +/* + * This is called to fill in the vector of log iovecs for the + * given cui log item. We use only 1 iovec, and we point that + * at the cui_log_format structure embedded in the cui item. + * It is at this point that we assert that all of the extent + * slots in the cui item have been filled. + */ +STATIC void +xfs_cui_item_format( + struct xfs_log_item *lip, + struct xfs_log_vec *lv) +{ + struct xfs_cui_log_item *cuip = CUI_ITEM(lip); + struct xfs_log_iovec *vecp = NULL; + + ASSERT(atomic_read(&cuip->cui_next_extent) == + cuip->cui_format.cui_nextents); + + cuip->cui_format.cui_type = XFS_LI_CUI; + cuip->cui_format.cui_size = 1; + + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_CUI_FORMAT, &cuip->cui_format, + xfs_cui_item_sizeof(cuip)); +} + +/* + * Pinning has no meaning for an cui item, so just return. + */ +STATIC void +xfs_cui_item_pin( + struct xfs_log_item *lip) +{ +} + +/* + * The unpin operation is the last place an CUI is manipulated in the log. It is + * either inserted in the AIL or aborted in the event of a log I/O error. In + * either case, the CUI transaction has been successfully committed to make it + * this far. Therefore, we expect whoever committed the CUI to either construct + * and commit the CUD or drop the CUD's reference in the event of error. Simply + * drop the log's CUI reference now that the log is done with it. + */ +STATIC void +xfs_cui_item_unpin( + struct xfs_log_item *lip, + int remove) +{ + struct xfs_cui_log_item *cuip = CUI_ITEM(lip); + + xfs_cui_release(cuip); +} + +/* + * CUI items have no locking or pushing. However, since CUIs are pulled from + * the AIL when their corresponding CUDs are committed to disk, their situation + * is very similar to being pinned. Return XFS_ITEM_PINNED so that the caller + * will eventually flush the log. This should help in getting the CUI out of + * the AIL. + */ +STATIC uint +xfs_cui_item_push( + struct xfs_log_item *lip, + struct list_head *buffer_list) +{ + return XFS_ITEM_PINNED; +} + +/* + * The CUI has been either committed or aborted if the transaction has been + * cancelled. If the transaction was cancelled, an CUD isn't going to be + * constructed and thus we free the CUI here directly. + */ +STATIC void +xfs_cui_item_unlock( + struct xfs_log_item *lip) +{ + if (lip->li_flags & XFS_LI_ABORTED) + xfs_cui_item_free(CUI_ITEM(lip)); +} + +/* + * The CUI is logged only once and cannot be moved in the log, so simply return + * the lsn at which it's been logged. + */ +STATIC xfs_lsn_t +xfs_cui_item_committed( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ + return lsn; +} + +/* + * The CUI dependency tracking op doesn't do squat. It can't because + * it doesn't know where the free extent is coming from. The dependency + * tracking has to be handled by the "enclosing" metadata object. For + * example, for inodes, the inode is locked throughout the extent freeing + * so the dependency should be recorded there. + */ +STATIC void +xfs_cui_item_committing( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ +} + +/* + * This is the ops vector shared by all cui log items. + */ +static const struct xfs_item_ops xfs_cui_item_ops = { + .iop_size = xfs_cui_item_size, + .iop_format = xfs_cui_item_format, + .iop_pin = xfs_cui_item_pin, + .iop_unpin = xfs_cui_item_unpin, + .iop_unlock = xfs_cui_item_unlock, + .iop_committed = xfs_cui_item_committed, + .iop_push = xfs_cui_item_push, + .iop_committing = xfs_cui_item_committing, +}; + +/* + * Allocate and initialize an cui item with the given number of extents. + */ +struct xfs_cui_log_item * +xfs_cui_init( + struct xfs_mount *mp, + uint nextents) + +{ + struct xfs_cui_log_item *cuip; + uint size; + + ASSERT(nextents > 0); + if (nextents > XFS_CUI_MAX_FAST_EXTENTS) { + size = (uint)(sizeof(struct xfs_cui_log_item) + + ((nextents - 1) * sizeof(struct xfs_phys_extent))); + cuip = kmem_zalloc(size, KM_SLEEP); + } else { + cuip = kmem_zone_zalloc(xfs_cui_zone, KM_SLEEP); + } + + xfs_log_item_init(mp, &cuip->cui_item, XFS_LI_CUI, &xfs_cui_item_ops); + cuip->cui_format.cui_nextents = nextents; + cuip->cui_format.cui_id = (uintptr_t)(void *)cuip; + atomic_set(&cuip->cui_next_extent, 0); + atomic_set(&cuip->cui_refcount, 2); + + return cuip; +} + +/* + * Copy an CUI format buffer from the given buf, and into the destination + * CUI format structure. The CUI/CUD items were designed not to need any + * special alignment handling. + */ +int +xfs_cui_copy_format( + struct xfs_log_iovec *buf, + struct xfs_cui_log_format *dst_cui_fmt) +{ + struct xfs_cui_log_format *src_cui_fmt; + uint len; + + src_cui_fmt = buf->i_addr; + len = sizeof(struct xfs_cui_log_format) + + (src_cui_fmt->cui_nextents - 1) * + sizeof(struct xfs_phys_extent); + + if (buf->i_len == len) { + memcpy((char *)dst_cui_fmt, (char *)src_cui_fmt, len); + return 0; + } + return -EFSCORRUPTED; +} + +/* + * Freeing the CUI requires that we remove it from the AIL if it has already + * been placed there. However, the CUI may not yet have been placed in the AIL + * when called by xfs_cui_release() from CUD processing due to the ordering of + * committed vs unpin operations in bulk insert operations. Hence the reference + * count to ensure only the last caller frees the CUI. + */ +void +xfs_cui_release( + struct xfs_cui_log_item *cuip) +{ + if (atomic_dec_and_test(&cuip->cui_refcount)) { + xfs_trans_ail_remove(&cuip->cui_item, SHUTDOWN_LOG_IO_ERROR); + xfs_cui_item_free(cuip); + } +} + +static inline struct xfs_cud_log_item *CUD_ITEM(struct xfs_log_item *lip) +{ + return container_of(lip, struct xfs_cud_log_item, cud_item); +} + +STATIC void +xfs_cud_item_free(struct xfs_cud_log_item *cudp) +{ + if (cudp->cud_format.cud_nextents > XFS_CUD_MAX_FAST_EXTENTS) + kmem_free(cudp); + else + kmem_zone_free(xfs_cud_zone, cudp); +} + +/* + * This returns the number of iovecs needed to log the given cud item. + * We only need 1 iovec for an cud item. It just logs the cud_log_format + * structure. + */ +static inline int +xfs_cud_item_sizeof( + struct xfs_cud_log_item *cudp) +{ + return sizeof(struct xfs_cud_log_format) + + (cudp->cud_format.cud_nextents - 1) * + sizeof(struct xfs_phys_extent); +} + +STATIC void +xfs_cud_item_size( + struct xfs_log_item *lip, + int *nvecs, + int *nbytes) +{ + *nvecs += 1; + *nbytes += xfs_cud_item_sizeof(CUD_ITEM(lip)); +} + +/* + * This is called to fill in the vector of log iovecs for the + * given cud log item. We use only 1 iovec, and we point that + * at the cud_log_format structure embedded in the cud item. + * It is at this point that we assert that all of the extent + * slots in the cud item have been filled. + */ +STATIC void +xfs_cud_item_format( + struct xfs_log_item *lip, + struct xfs_log_vec *lv) +{ + struct xfs_cud_log_item *cudp = CUD_ITEM(lip); + struct xfs_log_iovec *vecp = NULL; + + ASSERT(cudp->cud_next_extent == cudp->cud_format.cud_nextents); + + cudp->cud_format.cud_type = XFS_LI_CUD; + cudp->cud_format.cud_size = 1; + + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_CUD_FORMAT, &cudp->cud_format, + xfs_cud_item_sizeof(cudp)); +} + +/* + * Pinning has no meaning for an cud item, so just return. + */ +STATIC void +xfs_cud_item_pin( + struct xfs_log_item *lip) +{ +} + +/* + * Since pinning has no meaning for an cud item, unpinning does + * not either. + */ +STATIC void +xfs_cud_item_unpin( + struct xfs_log_item *lip, + int remove) +{ +} + +/* + * There isn't much you can do to push on an cud item. It is simply stuck + * waiting for the log to be flushed to disk. + */ +STATIC uint +xfs_cud_item_push( + struct xfs_log_item *lip, + struct list_head *buffer_list) +{ + return XFS_ITEM_PINNED; +} + +/* + * The CUD is either committed or aborted if the transaction is cancelled. If + * the transaction is cancelled, drop our reference to the CUI and free the + * CUD. + */ +STATIC void +xfs_cud_item_unlock( + struct xfs_log_item *lip) +{ + struct xfs_cud_log_item *cudp = CUD_ITEM(lip); + + if (lip->li_flags & XFS_LI_ABORTED) { + xfs_cui_release(cudp->cud_cuip); + xfs_cud_item_free(cudp); + } +} + +/* + * When the cud item is committed to disk, all we need to do is delete our + * reference to our partner cui item and then free ourselves. Since we're + * freeing ourselves we must return -1 to keep the transaction code from + * further referencing this item. + */ +STATIC xfs_lsn_t +xfs_cud_item_committed( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ + struct xfs_cud_log_item *cudp = CUD_ITEM(lip); + + /* + * Drop the CUI reference regardless of whether the CUD has been + * aborted. Once the CUD transaction is constructed, it is the sole + * responsibility of the CUD to release the CUI (even if the CUI is + * aborted due to log I/O error). + */ + xfs_cui_release(cudp->cud_cuip); + xfs_cud_item_free(cudp); + + return (xfs_lsn_t)-1; +} + +/* + * The CUD dependency tracking op doesn't do squat. It can't because + * it doesn't know where the free extent is coming from. The dependency + * tracking has to be handled by the "enclosing" metadata object. For + * example, for inodes, the inode is locked throughout the extent freeing + * so the dependency should be recorded there. + */ +STATIC void +xfs_cud_item_committing( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ +} + +/* + * This is the ops vector shared by all cud log items. + */ +static const struct xfs_item_ops xfs_cud_item_ops = { + .iop_size = xfs_cud_item_size, + .iop_format = xfs_cud_item_format, + .iop_pin = xfs_cud_item_pin, + .iop_unpin = xfs_cud_item_unpin, + .iop_unlock = xfs_cud_item_unlock, + .iop_committed = xfs_cud_item_committed, + .iop_push = xfs_cud_item_push, + .iop_committing = xfs_cud_item_committing, +}; + +/* + * Allocate and initialize an cud item with the given number of extents. + */ +struct xfs_cud_log_item * +xfs_cud_init( + struct xfs_mount *mp, + struct xfs_cui_log_item *cuip, + uint nextents) + +{ + struct xfs_cud_log_item *cudp; + uint size; + + ASSERT(nextents > 0); + if (nextents > XFS_CUD_MAX_FAST_EXTENTS) { + size = (uint)(sizeof(struct xfs_cud_log_item) + + ((nextents - 1) * sizeof(struct xfs_phys_extent))); + cudp = kmem_zalloc(size, KM_SLEEP); + } else { + cudp = kmem_zone_zalloc(xfs_cud_zone, KM_SLEEP); + } + + xfs_log_item_init(mp, &cudp->cud_item, XFS_LI_CUD, &xfs_cud_item_ops); + cudp->cud_cuip = cuip; + cudp->cud_format.cud_nextents = nextents; + cudp->cud_format.cud_cui_id = cuip->cui_format.cui_id; + + return cudp; +} diff --git a/fs/xfs/xfs_refcount_item.h b/fs/xfs/xfs_refcount_item.h new file mode 100644 index 0000000..9af4c9b --- /dev/null +++ b/fs/xfs/xfs_refcount_item.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_REFCOUNT_ITEM_H__ +#define __XFS_REFCOUNT_ITEM_H__ + +/* + * There are (currently) two pairs of refcount btree redo item types: + * increase and decrease. The log items for these are CUI (refcount + * update intent) and CUD (refcount update done). The redo item type + * is encoded in the flags field of each xfs_map_extent. + * + * *I items should be recorded in the *first* of a series of rolled + * transactions, and the *D items should be recorded in the same + * transaction that records the associated refcountbt updates. + * + * Should the system crash after the commit of the first transaction + * but before the commit of the final transaction in a series, log + * recovery will use the redo information recorded by the intent items + * to replay the refcountbt metadata updates. + */ + +/* kernel only CUI/CUD definitions */ + +struct xfs_mount; +struct kmem_zone; + +/* + * Max number of extents in fast allocation path. + */ +#define XFS_CUI_MAX_FAST_EXTENTS 16 + +/* + * Define CUI flag bits. Manipulated by set/clear/test_bit operators. + */ +#define XFS_CUI_RECOVERED 1 + +/* + * This is the "refcount update intent" log item. It is used to log + * the fact that some reverse mappings need to change. It is used in + * conjunction with the "refcount update done" log item described + * below. + * + * These log items follow the same rules as struct xfs_efi_log_item; + * see the comments about that structure (in xfs_extfree_item.h) for + * more details. + */ +struct xfs_cui_log_item { + struct xfs_log_item cui_item; + atomic_t cui_refcount; + atomic_t cui_next_extent; + unsigned long cui_flags; /* misc flags */ + struct xfs_cui_log_format cui_format; +}; + +/* + * This is the "refcount update done" log item. It is used to log the + * fact that some refcountbt updates mentioned in an earlier cui item + * have been performed. + */ +struct xfs_cud_log_item { + struct xfs_log_item cud_item; + struct xfs_cui_log_item *cud_cuip; + uint cud_next_extent; + struct xfs_cud_log_format cud_format; +}; + +/* + * Max number of extents in fast allocation path. + */ +#define XFS_CUD_MAX_FAST_EXTENTS 16 + +extern struct kmem_zone *xfs_cui_zone; +extern struct kmem_zone *xfs_cud_zone; + +struct xfs_cui_log_item *xfs_cui_init(struct xfs_mount *, uint); +struct xfs_cud_log_item *xfs_cud_init(struct xfs_mount *, + struct xfs_cui_log_item *, uint); +int xfs_cui_copy_format(struct xfs_log_iovec *buf, + struct xfs_cui_log_format *dst_cui_fmt); +void xfs_cui_item_free(struct xfs_cui_log_item *); +void xfs_cui_release(struct xfs_cui_log_item *); + +#endif /* __XFS_REFCOUNT_ITEM_H__ */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 9328821..a0c7bdc 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -48,6 +48,7 @@ #include "xfs_ondisk.h" #include "xfs_defer.h" #include "xfs_rmap_item.h" +#include "xfs_refcount_item.h" #include #include @@ -1781,8 +1782,26 @@ xfs_init_zones(void) if (!xfs_rui_zone) goto out_destroy_rud_zone; + xfs_cud_zone = kmem_zone_init((sizeof(struct xfs_cud_log_item) + + ((XFS_CUD_MAX_FAST_EXTENTS - 1) * + sizeof(struct xfs_phys_extent))), + "xfs_cud_item"); + if (!xfs_cud_zone) + goto out_destroy_rui_zone; + + xfs_cui_zone = kmem_zone_init((sizeof(struct xfs_cui_log_item) + + ((XFS_CUI_MAX_FAST_EXTENTS - 1) * + sizeof(struct xfs_phys_extent))), + "xfs_cui_item"); + if (!xfs_cui_zone) + goto out_destroy_cud_zone; + return 0; + out_destroy_cud_zone: + kmem_zone_destroy(xfs_cud_zone); + out_destroy_rui_zone: + kmem_zone_destroy(xfs_rui_zone); out_destroy_rud_zone: kmem_zone_destroy(xfs_rud_zone); out_destroy_icreate_zone: @@ -1825,6 +1844,8 @@ xfs_destroy_zones(void) * destroy caches. */ rcu_barrier(); + kmem_zone_destroy(xfs_cui_zone); + kmem_zone_destroy(xfs_cud_zone); kmem_zone_destroy(xfs_rui_zone); kmem_zone_destroy(xfs_rud_zone); kmem_zone_destroy(xfs_icreate_zone); From darrick.wong@oracle.com Thu Jun 16 20:24:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_LOLITA1, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 534377E2D for ; Thu, 16 Jun 2016 20:24:40 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 12A2A304048 for ; Thu, 16 Jun 2016 18:24:40 -0700 (PDT) X-ASG-Debug-ID: 1466126676-04bdf01e1395b10001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id iurqtOh1qHSPWp75 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:36 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1OWCn008948 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:24:33 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1OWed014836 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:32 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1OV8Y020068; Fri, 17 Jun 2016 01:24:31 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:30 -0700 Subject: [PATCH 062/119] xfs: log refcount intent items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 062/119] xfs: log refcount intent items To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:29 -0700 Message-ID: <146612666945.12839.17831346063394478114.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126676 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 21358 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a mechanism for higher levels to create CUI/CUD items, submit them to the log, and a stub function to deal with recovered CUI items. These parts will be connected to the refcountbt in a later patch. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_log_format.h | 2 fs/xfs/libxfs/xfs_refcount.h | 14 ++ fs/xfs/xfs_log_recover.c | 299 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_trace.h | 30 ++++ fs/xfs/xfs_trans.h | 15 ++ fs/xfs/xfs_trans_refcount.c | 192 ++++++++++++++++++++++++++ 7 files changed, 552 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/xfs_trans_refcount.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 322c386..2945270 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -114,6 +114,7 @@ xfs-y += xfs_log.o \ xfs_trans_buf.o \ xfs_trans_extfree.o \ xfs_trans_inode.o \ + xfs_trans_refcount.o \ xfs_trans_rmap.o \ # optional features diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 1dfa02c..923b08f 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -688,6 +688,8 @@ struct xfs_phys_extent { #define XFS_REFCOUNT_EXTENT_FREE_COW 4 #define XFS_REFCOUNT_EXTENT_TYPE_MASK 0xFF +#define XFS_REFCOUNT_EXTENT_FLAGS (XFS_REFCOUNT_EXTENT_TYPE_MASK) + /* * This is the structure used to lay out a cui log item in the * log. The cui_extents field is a variable size array whose diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index 8ea65c6..0b36c1d 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -27,4 +27,18 @@ extern int xfs_refcountbt_lookup_ge(struct xfs_btree_cur *cur, extern int xfs_refcountbt_get_rec(struct xfs_btree_cur *cur, struct xfs_refcount_irec *irec, int *stat); +enum xfs_refcount_intent_type { + XFS_REFCOUNT_INCREASE, + XFS_REFCOUNT_DECREASE, + XFS_REFCOUNT_ALLOC_COW, + XFS_REFCOUNT_FREE_COW, +}; + +struct xfs_refcount_intent { + struct list_head ri_list; + enum xfs_refcount_intent_type ri_type; + xfs_fsblock_t ri_startblock; + xfs_extlen_t ri_blockcount; +}; + #endif /* __XFS_REFCOUNT_H__ */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index dbfbc26..e0a470a 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -46,6 +46,7 @@ #include "xfs_dir2.h" #include "xfs_rmap_item.h" #include "xfs_rmap_btree.h" +#include "xfs_refcount_item.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) @@ -1916,6 +1917,8 @@ xlog_recover_reorder_trans( case XFS_LI_EFI: case XFS_LI_RUI: case XFS_LI_RUD: + case XFS_LI_CUI: + case XFS_LI_CUD: trace_xfs_log_recover_item_reorder_tail(log, trans, item, pass); list_move_tail(&item->ri_list, &inode_list); @@ -3519,6 +3522,101 @@ xlog_recover_rud_pass2( } /* + * This routine is called to create an in-core extent refcount update + * item from the cui format structure which was logged on disk. + * It allocates an in-core cui, copies the extents from the format + * structure into it, and adds the cui to the AIL with the given + * LSN. + */ +STATIC int +xlog_recover_cui_pass2( + struct xlog *log, + struct xlog_recover_item *item, + xfs_lsn_t lsn) +{ + int error; + struct xfs_mount *mp = log->l_mp; + struct xfs_cui_log_item *cuip; + struct xfs_cui_log_format *cui_formatp; + + cui_formatp = item->ri_buf[0].i_addr; + + cuip = xfs_cui_init(mp, cui_formatp->cui_nextents); + error = xfs_cui_copy_format(&item->ri_buf[0], &cuip->cui_format); + if (error) { + xfs_cui_item_free(cuip); + return error; + } + atomic_set(&cuip->cui_next_extent, cui_formatp->cui_nextents); + + spin_lock(&log->l_ailp->xa_lock); + /* + * The CUI has two references. One for the CUD and one for CUI to ensure + * it makes it into the AIL. Insert the CUI into the AIL directly and + * drop the CUI reference. Note that xfs_trans_ail_update() drops the + * AIL lock. + */ + xfs_trans_ail_update(log->l_ailp, &cuip->cui_item, lsn); + xfs_cui_release(cuip); + return 0; +} + + +/* + * This routine is called when an CUD format structure is found in a committed + * transaction in the log. Its purpose is to cancel the corresponding CUI if it + * was still in the log. To do this it searches the AIL for the CUI with an id + * equal to that in the CUD format structure. If we find it we drop the CUD + * reference, which removes the CUI from the AIL and frees it. + */ +STATIC int +xlog_recover_cud_pass2( + struct xlog *log, + struct xlog_recover_item *item) +{ + struct xfs_cud_log_format *cud_formatp; + struct xfs_cui_log_item *cuip = NULL; + struct xfs_log_item *lip; + __uint64_t cui_id; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp = log->l_ailp; + + cud_formatp = item->ri_buf[0].i_addr; + ASSERT(item->ri_buf[0].i_len == (sizeof(struct xfs_cud_log_format) + + ((cud_formatp->cud_nextents - 1) * + sizeof(struct xfs_phys_extent)))); + cui_id = cud_formatp->cud_cui_id; + + /* + * Search for the CUI with the id in the CUD format structure in the + * AIL. + */ + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + if (lip->li_type == XFS_LI_CUI) { + cuip = (struct xfs_cui_log_item *)lip; + if (cuip->cui_format.cui_id == cui_id) { + /* + * Drop the CUD reference to the CUI. This + * removes the CUI from the AIL and frees it. + */ + spin_unlock(&ailp->xa_lock); + xfs_cui_release(cuip); + spin_lock(&ailp->xa_lock); + break; + } + } + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } + + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + + return 0; +} + +/* * This routine is called when an inode create format structure is found in a * committed transaction in the log. It's purpose is to initialise the inodes * being allocated on disk. This requires us to get inode cluster buffers that @@ -3745,6 +3843,8 @@ xlog_recover_ra_pass2( case XFS_LI_QUOTAOFF: case XFS_LI_RUI: case XFS_LI_RUD: + case XFS_LI_CUI: + case XFS_LI_CUD: default: break; } @@ -3770,6 +3870,8 @@ xlog_recover_commit_pass1( case XFS_LI_ICREATE: case XFS_LI_RUI: case XFS_LI_RUD: + case XFS_LI_CUI: + case XFS_LI_CUD: /* nothing to do in pass 1 */ return 0; default: @@ -3804,6 +3906,10 @@ xlog_recover_commit_pass2( return xlog_recover_rui_pass2(log, item, trans->r_lsn); case XFS_LI_RUD: return xlog_recover_rud_pass2(log, item); + case XFS_LI_CUI: + return xlog_recover_cui_pass2(log, item, trans->r_lsn); + case XFS_LI_CUD: + return xlog_recover_cud_pass2(log, item); case XFS_LI_DQUOT: return xlog_recover_dquot_pass2(log, buffer_list, item, trans->r_lsn); @@ -4282,6 +4388,7 @@ static inline bool xlog_item_is_intent(struct xfs_log_item *lip) switch (lip->li_type) { case XFS_LI_EFI: case XFS_LI_RUI: + case XFS_LI_CUI: return true; default: return false; @@ -4713,6 +4820,186 @@ xlog_recover_cancel_ruis( } /* + * Process a refcount update intent item that was recovered from the log. + * We need to update the refcountbt. + */ +STATIC int +xlog_recover_process_cui( + struct xfs_mount *mp, + struct xfs_cui_log_item *cuip) +{ + int i; + int error = 0; + struct xfs_phys_extent *refc; + xfs_fsblock_t startblock_fsb; + bool op_ok; + + ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags)); + + /* + * First check the validity of the extents described by the + * CUI. If any are bad, then assume that all are bad and + * just toss the CUI. + */ + for (i = 0; i < cuip->cui_format.cui_nextents; i++) { + refc = &(cuip->cui_format.cui_extents[i]); + startblock_fsb = XFS_BB_TO_FSB(mp, + XFS_FSB_TO_DADDR(mp, refc->pe_startblock)); + switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) { + case XFS_REFCOUNT_EXTENT_INCREASE: + case XFS_REFCOUNT_EXTENT_DECREASE: + case XFS_REFCOUNT_EXTENT_ALLOC_COW: + case XFS_REFCOUNT_EXTENT_FREE_COW: + op_ok = true; + break; + default: + op_ok = false; + break; + } + if (!op_ok || (startblock_fsb == 0) || + (refc->pe_len == 0) || + (startblock_fsb >= mp->m_sb.sb_dblocks) || + (refc->pe_len >= mp->m_sb.sb_agblocks) || + (refc->pe_flags & ~XFS_REFCOUNT_EXTENT_FLAGS)) { + /* + * This will pull the CUI from the AIL and + * free the memory associated with it. + */ + set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags); + xfs_cui_release(cuip); + return -EIO; + } + } + + /* XXX: do nothing for now */ + set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags); + xfs_cui_release(cuip); + return error; +} + +/* + * When this is called, all of the CUIs which did not have + * corresponding CUDs should be in the AIL. What we do now + * is update the rmaps associated with each one. + * + * Since we process the CUIs in normal transactions, they + * will be removed at some point after the commit. This prevents + * us from just walking down the list processing each one. + * We'll use a flag in the CUI to skip those that we've already + * processed and use the AIL iteration mechanism's generation + * count to try to speed this up at least a bit. + * + * When we start, we know that the CUIs are the only things in + * the AIL. As we process them, however, other items are added + * to the AIL. Since everything added to the AIL must come after + * everything already in the AIL, we stop processing as soon as + * we see something other than an CUI in the AIL. + */ +STATIC int +xlog_recover_process_cuis( + struct xlog *log) +{ + struct xfs_log_item *lip; + struct xfs_cui_log_item *cuip; + int error = 0; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp; + + ailp = log->l_ailp; + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + /* + * We're done when we see something other than an intent. + * There should be no intents left in the AIL now. + */ + if (!xlog_item_is_intent(lip)) { +#ifdef DEBUG + for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) + ASSERT(!xlog_item_is_intent(lip)); +#endif + break; + } + + /* Skip anything that isn't an CUI */ + if (lip->li_type != XFS_LI_CUI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + /* + * Skip CUIs that we've already processed. + */ + cuip = container_of(lip, struct xfs_cui_log_item, cui_item); + if (test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags)) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + spin_unlock(&ailp->xa_lock); + error = xlog_recover_process_cui(log->l_mp, cuip); + spin_lock(&ailp->xa_lock); + if (error) + goto out; + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } +out: + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + return error; +} + +/* + * A cancel occurs when the mount has failed and we're bailing out. Release all + * pending CUIs so they don't pin the AIL. + */ +STATIC int +xlog_recover_cancel_cuis( + struct xlog *log) +{ + struct xfs_log_item *lip; + struct xfs_cui_log_item *cuip; + int error = 0; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp; + + ailp = log->l_ailp; + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + /* + * We're done when we see something other than an CUI. + * There should be no CUIs left in the AIL now. + */ + if (!xlog_item_is_intent(lip)) { +#ifdef DEBUG + for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) + ASSERT(!xlog_item_is_intent(lip)); +#endif + break; + } + + /* Skip anything that isn't an CUI */ + if (lip->li_type != XFS_LI_CUI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + cuip = container_of(lip, struct xfs_cui_log_item, cui_item); + + spin_unlock(&ailp->xa_lock); + xfs_cui_release(cuip); + spin_lock(&ailp->xa_lock); + + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } + + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + return error; +} + +/* * This routine performs a transaction to null out a bad inode pointer * in an agi unlinked inode hash bucket. */ @@ -5515,6 +5802,12 @@ xlog_recover_finish( if (log->l_flags & XLOG_RECOVERY_NEEDED) { int error; + error = xlog_recover_process_cuis(log); + if (error) { + xfs_alert(log->l_mp, "Failed to recover CUIs"); + return error; + } + error = xlog_recover_process_ruis(log); if (error) { xfs_alert(log->l_mp, "Failed to recover RUIs"); @@ -5557,7 +5850,11 @@ xlog_recover_cancel( int err2; if (log->l_flags & XLOG_RECOVERY_NEEDED) { - error = xlog_recover_cancel_ruis(log); + error = xlog_recover_cancel_cuis(log); + + err2 = xlog_recover_cancel_ruis(log); + if (err2 && !error) + error = err2; err2 = xlog_recover_cancel_efis(log); if (err2 && !error) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 67ce2d8..1f6cee0 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2906,6 +2906,36 @@ DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared); DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared_result); DEFINE_AG_ERROR_EVENT(xfs_refcount_find_shared_error); +TRACE_EVENT(xfs_refcount_finish_one_leftover, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, + int type, xfs_agblock_t agbno, + xfs_extlen_t len, xfs_extlen_t adjusted), + TP_ARGS(mp, agno, type, agbno, len, adjusted), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(int, type) + __field(xfs_agblock_t, agbno) + __field(xfs_extlen_t, len) + __field(xfs_extlen_t, adjusted) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->type = type; + __entry->agbno = agbno; + __entry->len = len; + __entry->adjusted = adjusted; + ), + TP_printk("dev %d:%d type %d agno %u agbno %u len %u adjusted %u", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->type, + __entry->agno, + __entry->agbno, + __entry->len, + __entry->adjusted) +); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index f59d934..2b197fd 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -253,4 +253,19 @@ int xfs_trans_log_finish_rmap_update(struct xfs_trans *tp, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state, struct xfs_btree_cur **pcur); +enum xfs_refcount_intent_type; + +struct xfs_cui_log_item *xfs_trans_get_cui(struct xfs_trans *tp, uint nextents); +void xfs_trans_log_start_refcount_update(struct xfs_trans *tp, + struct xfs_cui_log_item *cuip, + enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, + xfs_filblks_t blockcount); + +struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp, + struct xfs_cui_log_item *cuip, uint nextents); +int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp, + struct xfs_cud_log_item *cudp, + enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, + xfs_extlen_t blockcount, struct xfs_btree_cur **pcur); + #endif /* __XFS_TRANS_H__ */ diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c new file mode 100644 index 0000000..32701e4 --- /dev/null +++ b/fs/xfs/xfs_trans_refcount.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_refcount_item.h" +#include "xfs_alloc.h" +#include "xfs_refcount.h" + +/* + * This routine is called to allocate an "refcount update intent" + * log item that will hold nextents worth of extents. The + * caller must use all nextents extents, because we are not + * flexible about this at all. + */ +struct xfs_cui_log_item * +xfs_trans_get_cui( + struct xfs_trans *tp, + uint nextents) +{ + struct xfs_cui_log_item *cuip; + + ASSERT(tp != NULL); + ASSERT(nextents > 0); + + cuip = xfs_cui_init(tp->t_mountp, nextents); + ASSERT(cuip != NULL); + + /* + * Get a log_item_desc to point at the new item. + */ + xfs_trans_add_item(tp, &cuip->cui_item); + return cuip; +} + +/* + * This routine is called to indicate that the described + * extent is to be logged as needing to be freed. It should + * be called once for each extent to be freed. + */ +void +xfs_trans_log_start_refcount_update( + struct xfs_trans *tp, + struct xfs_cui_log_item *cuip, + enum xfs_refcount_intent_type type, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount) +{ + uint next_extent; + struct xfs_phys_extent *refc; + + tp->t_flags |= XFS_TRANS_DIRTY; + cuip->cui_item.li_desc->lid_flags |= XFS_LID_DIRTY; + + /* + * atomic_inc_return gives us the value after the increment; + * we want to use it as an array index so we need to subtract 1 from + * it. + */ + next_extent = atomic_inc_return(&cuip->cui_next_extent) - 1; + ASSERT(next_extent < cuip->cui_format.cui_nextents); + refc = &(cuip->cui_format.cui_extents[next_extent]); + refc->pe_startblock = startblock; + refc->pe_len = blockcount; + refc->pe_flags = 0; + switch (type) { + case XFS_REFCOUNT_INCREASE: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_INCREASE; + break; + case XFS_REFCOUNT_DECREASE: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_DECREASE; + break; + case XFS_REFCOUNT_ALLOC_COW: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_ALLOC_COW; + break; + case XFS_REFCOUNT_FREE_COW: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_FREE_COW; + break; + default: + ASSERT(0); + } +} + + +/* + * This routine is called to allocate an "extent free done" + * log item that will hold nextents worth of extents. The + * caller must use all nextents extents, because we are not + * flexible about this at all. + */ +struct xfs_cud_log_item * +xfs_trans_get_cud( + struct xfs_trans *tp, + struct xfs_cui_log_item *cuip, + uint nextents) +{ + struct xfs_cud_log_item *cudp; + + ASSERT(tp != NULL); + ASSERT(nextents > 0); + + cudp = xfs_cud_init(tp->t_mountp, cuip, nextents); + ASSERT(cudp != NULL); + + /* + * Get a log_item_desc to point at the new item. + */ + xfs_trans_add_item(tp, &cudp->cud_item); + return cudp; +} + +/* + * Finish an refcount update and log it to the CUD. Note that the transaction is + * marked dirty regardless of whether the refcount update succeeds or fails to + * support the CUI/CUD lifecycle rules. + */ +int +xfs_trans_log_finish_refcount_update( + struct xfs_trans *tp, + struct xfs_cud_log_item *cudp, + enum xfs_refcount_intent_type type, + xfs_fsblock_t startblock, + xfs_extlen_t blockcount, + struct xfs_btree_cur **pcur) +{ + uint next_extent; + struct xfs_phys_extent *refc; + int error; + + /* XXX: leave this empty for now */ + error = -EFSCORRUPTED; + + /* + * Mark the transaction dirty, even on error. This ensures the + * transaction is aborted, which: + * + * 1.) releases the CUI and frees the CUD + * 2.) shuts down the filesystem + */ + tp->t_flags |= XFS_TRANS_DIRTY; + cudp->cud_item.li_desc->lid_flags |= XFS_LID_DIRTY; + + next_extent = cudp->cud_next_extent; + ASSERT(next_extent < cudp->cud_format.cud_nextents); + refc = &(cudp->cud_format.cud_extents[next_extent]); + refc->pe_startblock = startblock; + refc->pe_len = blockcount; + refc->pe_flags = 0; + switch (type) { + case XFS_REFCOUNT_INCREASE: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_INCREASE; + break; + case XFS_REFCOUNT_DECREASE: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_DECREASE; + break; + case XFS_REFCOUNT_ALLOC_COW: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_ALLOC_COW; + break; + case XFS_REFCOUNT_FREE_COW: + refc->pe_flags |= XFS_REFCOUNT_EXTENT_FREE_COW; + break; + default: + ASSERT(0); + } + cudp->cud_next_extent++; + + return error; +} From darrick.wong@oracle.com Thu Jun 16 20:24:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id DA5CA7CB4 for ; Thu, 16 Jun 2016 20:24:48 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id AB404304039 for ; Thu, 16 Jun 2016 18:24:48 -0700 (PDT) X-ASG-Debug-ID: 1466126684-04cb6c542757730001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Ab8rHDtkcPm0PxLw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:45 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Ofjw028252 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:24:41 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Oeb2015057 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:40 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ObTI007926; Fri, 17 Jun 2016 01:24:39 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:37 -0700 Subject: [PATCH 063/119] xfs: adjust refcount of an extent of blocks in refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 063/119] xfs: adjust refcount of an extent of blocks in refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:35 -0700 Message-ID: <146612667589.12839.17197885347586278821.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126684 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 25238 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide functions to adjust the reference counts for an extent of physical blocks stored in the refcount btree. v2: Refactor the left/right split code into a single function. Track the number of btree shape changes and record updates during a refcount update so that we can decide if we need to get a fresh transaction to continue. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_refcount.c | 783 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_error.h | 4 2 files changed, 786 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 4d483b5..d13393b 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -37,6 +37,12 @@ #include "xfs_bit.h" #include "xfs_refcount.h" +/* Allowable refcount adjustment amounts. */ +enum xfs_refc_adjust_op { + XFS_REFCOUNT_ADJUST_INCREASE = 1, + XFS_REFCOUNT_ADJUST_DECREASE = -1, +}; + /* * Look up the first record less than or equal to [bno, len] in the btree * given by cur. @@ -175,3 +181,780 @@ out_error: cur->bc_private.a.agno, error, _RET_IP_); return error; } + +/* + * Adjusting the Reference Count + * + * As stated elsewhere, the reference count btree (refcbt) stores + * >1 reference counts for extents of physical blocks. In this + * operation, we're either raising or lowering the reference count of + * some subrange stored in the tree: + * + * <------ adjustment range ------> + * ----+ +---+-----+ +--+--------+--------- + * 2 | | 3 | 4 | |17| 55 | 10 + * ----+ +---+-----+ +--+--------+--------- + * X axis is physical blocks number; + * reference counts are the numbers inside the rectangles + * + * The first thing we need to do is to ensure that there are no + * refcount extents crossing either boundary of the range to be + * adjusted. For any extent that does cross a boundary, split it into + * two extents so that we can increment the refcount of one of the + * pieces later: + * + * <------ adjustment range ------> + * ----+ +---+-----+ +--+--------+----+---- + * 2 | | 3 | 2 | |17| 55 | 10 | 10 + * ----+ +---+-----+ +--+--------+----+---- + * + * For this next step, let's assume that all the physical blocks in + * the adjustment range are mapped to a file and are therefore in use + * at least once. Therefore, we can infer that any gap in the + * refcount tree within the adjustment range represents a physical + * extent with refcount == 1: + * + * <------ adjustment range ------> + * ----+---+---+-----+-+--+--------+----+---- + * 2 |"1"| 3 | 2 |1|17| 55 | 10 | 10 + * ----+---+---+-----+-+--+--------+----+---- + * ^ + * + * For each extent that falls within the interval range, figure out + * which extent is to the left or the right of that extent. Now we + * have a left, current, and right extent. If the new reference count + * of the center extent enables us to merge left, center, and right + * into one record covering all three, do so. If the center extent is + * at the left end of the range, abuts the left extent, and its new + * reference count matches the left extent's record, then merge them. + * If the center extent is at the right end of the range, abuts the + * right extent, and the reference counts match, merge those. In the + * example, we can left merge (assuming an increment operation): + * + * <------ adjustment range ------> + * --------+---+-----+-+--+--------+----+---- + * 2 | 3 | 2 |1|17| 55 | 10 | 10 + * --------+---+-----+-+--+--------+----+---- + * ^ + * + * For all other extents within the range, adjust the reference count + * or delete it if the refcount falls below 2. If we were + * incrementing, the end result looks like this: + * + * <------ adjustment range ------> + * --------+---+-----+-+--+--------+----+---- + * 2 | 4 | 3 |2|18| 56 | 11 | 10 + * --------+---+-----+-+--+--------+----+---- + * + * The result of a decrement operation looks as such: + * + * <------ adjustment range ------> + * ----+ +---+ +--+--------+----+---- + * 2 | | 2 | |16| 54 | 9 | 10 + * ----+ +---+ +--+--------+----+---- + * DDDD 111111DD + * + * The blocks marked "D" are freed; the blocks marked "1" are only + * referenced once and therefore the record is removed from the + * refcount btree. + */ + +#define RCNEXT(rc) ((rc).rc_startblock + (rc).rc_blockcount) +/* + * Split a refcount extent that crosses agbno. + */ +STATIC int +xfs_refcount_split_extent( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + bool *shape_changed) +{ + struct xfs_refcount_irec rcext, tmp; + int found_rec; + int error; + + *shape_changed = false; + error = xfs_refcountbt_lookup_le(cur, agbno, &found_rec); + if (error) + goto out_error; + if (!found_rec) + return 0; + + error = xfs_refcountbt_get_rec(cur, &rcext, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (rcext.rc_startblock == agbno || RCNEXT(rcext) <= agbno) + return 0; + + *shape_changed = true; + trace_xfs_refcount_split_extent(cur->bc_mp, cur->bc_private.a.agno, + &rcext, agbno); + + /* Establish the right extent. */ + tmp = rcext; + tmp.rc_startblock = agbno; + tmp.rc_blockcount -= (agbno - rcext.rc_startblock); + error = xfs_refcountbt_update(cur, &tmp); + if (error) + goto out_error; + + /* Insert the left extent. */ + tmp = rcext; + tmp.rc_blockcount = agbno - rcext.rc_startblock; + error = xfs_refcountbt_insert(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + return error; + +out_error: + trace_xfs_refcount_split_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Merge the left, center, and right extents. + */ +STATIC int +xfs_refcount_merge_center_extent( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *left, + struct xfs_refcount_irec *center, + unsigned long long extlen, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen) +{ + int error; + int found_rec; + + error = xfs_refcountbt_lookup_ge(cur, center->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + if (center->rc_refcount > 1) { + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + } + + error = xfs_refcountbt_lookup_le(cur, left->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + left->rc_blockcount = extlen; + error = xfs_refcountbt_update(cur, left); + if (error) + goto out_error; + + *aglen = 0; + return error; + +out_error: + trace_xfs_refcount_merge_center_extents_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Merge with the left extent. + */ +STATIC int +xfs_refcount_merge_left_extent( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *left, + struct xfs_refcount_irec *cleft, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen) +{ + int error; + int found_rec; + + if (cleft->rc_refcount > 1) { + error = xfs_refcountbt_lookup_le(cur, cleft->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + } + + error = xfs_refcountbt_lookup_le(cur, left->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + left->rc_blockcount += cleft->rc_blockcount; + error = xfs_refcountbt_update(cur, left); + if (error) + goto out_error; + + *agbno += cleft->rc_blockcount; + *aglen -= cleft->rc_blockcount; + return error; + +out_error: + trace_xfs_refcount_merge_left_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Merge with the right extent. + */ +STATIC int +xfs_refcount_merge_right_extent( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *right, + struct xfs_refcount_irec *cright, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen) +{ + int error; + int found_rec; + + if (cright->rc_refcount > 1) { + error = xfs_refcountbt_lookup_le(cur, cright->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + } + + error = xfs_refcountbt_lookup_le(cur, right->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + right->rc_startblock -= cright->rc_blockcount; + right->rc_blockcount += cright->rc_blockcount; + error = xfs_refcountbt_update(cur, right); + if (error) + goto out_error; + + *aglen -= cright->rc_blockcount; + return error; + +out_error: + trace_xfs_refcount_merge_right_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Find the left extent and the one after it (cleft). This function assumes + * that we've already split any extent crossing agbno. + */ +STATIC int +xfs_refcount_find_left_extents( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *left, + struct xfs_refcount_irec *cleft, + xfs_agblock_t agbno, + xfs_extlen_t aglen) +{ + struct xfs_refcount_irec tmp; + int error; + int found_rec; + + left->rc_blockcount = cleft->rc_blockcount = 0; + error = xfs_refcountbt_lookup_le(cur, agbno - 1, &found_rec); + if (error) + goto out_error; + if (!found_rec) + return 0; + + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + if (RCNEXT(tmp) != agbno) + return 0; + /* We have a left extent; retrieve (or invent) the next right one */ + *left = tmp; + + error = xfs_btree_increment(cur, 0, &found_rec); + if (error) + goto out_error; + if (found_rec) { + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + /* if tmp starts at the end of our range, just use that */ + if (tmp.rc_startblock == agbno) + *cleft = tmp; + else { + /* + * There's a gap in the refcntbt at the start of the + * range we're interested in (refcount == 1) so + * create the implied extent and pass it back. + */ + cleft->rc_startblock = agbno; + cleft->rc_blockcount = min(aglen, + tmp.rc_startblock - agbno); + cleft->rc_refcount = 1; + } + } else { + /* + * No extents, so pretend that there's one covering the whole + * range. + */ + cleft->rc_startblock = agbno; + cleft->rc_blockcount = aglen; + cleft->rc_refcount = 1; + } + trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_private.a.agno, + left, cleft, agbno); + return error; + +out_error: + trace_xfs_refcount_find_left_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Find the right extent and the one before it (cright). This function + * assumes that we've already split any extents crossing agbno + aglen. + */ +STATIC int +xfs_refcount_find_right_extents( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *right, + struct xfs_refcount_irec *cright, + xfs_agblock_t agbno, + xfs_extlen_t aglen) +{ + struct xfs_refcount_irec tmp; + int error; + int found_rec; + + right->rc_blockcount = cright->rc_blockcount = 0; + error = xfs_refcountbt_lookup_ge(cur, agbno + aglen, &found_rec); + if (error) + goto out_error; + if (!found_rec) + return 0; + + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + if (tmp.rc_startblock != agbno + aglen) + return 0; + /* We have a right extent; retrieve (or invent) the next left one */ + *right = tmp; + + error = xfs_btree_decrement(cur, 0, &found_rec); + if (error) + goto out_error; + if (found_rec) { + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + /* if tmp ends at the end of our range, just use that */ + if (RCNEXT(tmp) == agbno + aglen) + *cright = tmp; + else { + /* + * There's a gap in the refcntbt at the end of the + * range we're interested in (refcount == 1) so + * create the implied extent and pass it back. + */ + cright->rc_startblock = max(agbno, RCNEXT(tmp)); + cright->rc_blockcount = right->rc_startblock - + cright->rc_startblock; + cright->rc_refcount = 1; + } + } else { + /* + * No extents, so pretend that there's one covering the whole + * range. + */ + cright->rc_startblock = agbno; + cright->rc_blockcount = aglen; + cright->rc_refcount = 1; + } + trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_private.a.agno, + cright, right, agbno + aglen); + return error; + +out_error: + trace_xfs_refcount_find_right_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} +#undef RCNEXT + +/* + * Try to merge with any extents on the boundaries of the adjustment range. + */ +STATIC int +xfs_refcount_merge_extents( + struct xfs_btree_cur *cur, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen, + enum xfs_refc_adjust_op adjust, + bool *shape_changed) +{ + struct xfs_refcount_irec left = {0}, cleft = {0}; + struct xfs_refcount_irec cright = {0}, right = {0}; + int error; + unsigned long long ulen; + bool cequal; + + *shape_changed = false; + /* + * Find the extent just below agbno [left], just above agbno [cleft], + * just below (agbno + aglen) [cright], and just above (agbno + aglen) + * [right]. + */ + error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno, + *aglen); + if (error) + return error; + error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno, + *aglen); + if (error) + return error; + + /* No left or right extent to merge; exit. */ + if (left.rc_blockcount == 0 && right.rc_blockcount == 0) + return 0; + + *shape_changed = true; + cequal = (cleft.rc_startblock == cright.rc_startblock) && + (cleft.rc_blockcount == cright.rc_blockcount); + + /* Try to merge left, cleft, and right. cleft must == cright. */ + ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount + + right.rc_blockcount; + if (left.rc_blockcount != 0 && right.rc_blockcount != 0 && + cleft.rc_blockcount != 0 && cright.rc_blockcount != 0 && + cequal && + left.rc_refcount == cleft.rc_refcount + adjust && + right.rc_refcount == cleft.rc_refcount + adjust && + ulen < MAXREFCEXTLEN) { + trace_xfs_refcount_merge_center_extents(cur->bc_mp, + cur->bc_private.a.agno, &left, &cleft, &right); + return xfs_refcount_merge_center_extent(cur, &left, &cleft, + ulen, agbno, aglen); + } + + /* Try to merge left and cleft. */ + ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount; + if (left.rc_blockcount != 0 && cleft.rc_blockcount != 0 && + left.rc_refcount == cleft.rc_refcount + adjust && + ulen < MAXREFCEXTLEN) { + trace_xfs_refcount_merge_left_extent(cur->bc_mp, + cur->bc_private.a.agno, &left, &cleft); + error = xfs_refcount_merge_left_extent(cur, &left, &cleft, + agbno, aglen); + if (error) + return error; + + /* + * If we just merged left + cleft and cleft == cright, + * we no longer have a cright to merge with right. We're done. + */ + if (cequal) + return 0; + } + + /* Try to merge cright and right. */ + ulen = (unsigned long long)right.rc_blockcount + cright.rc_blockcount; + if (right.rc_blockcount != 0 && cright.rc_blockcount != 0 && + right.rc_refcount == cright.rc_refcount + adjust && + ulen < MAXREFCEXTLEN) { + trace_xfs_refcount_merge_right_extent(cur->bc_mp, + cur->bc_private.a.agno, &cright, &right); + return xfs_refcount_merge_right_extent(cur, &right, &cright, + agbno, aglen); + } + + return error; +} + +/* + * While we're adjusting the refcounts records of an extent, we have + * to keep an eye on the number of extents we're dirtying -- run too + * many in a single transaction and we'll exceed the transaction's + * reservation and crash the fs. Each record adds 12 bytes to the + * log (plus any key updates) so we'll conservatively assume 24 bytes + * per record. We must also leave space for btree splits on both ends + * of the range and space for the CUD and a new CUI. + * + * XXX: This is a pretty hand-wavy estimate. The penalty for guessing + * true incorrectly is a shutdown FS; the penalty for guessing false + * incorrectly is more transaction rolls than might be necessary. + * Be conservative here. + */ +static bool +xfs_refcount_still_have_space( + struct xfs_btree_cur *cur) +{ + unsigned long overhead; + + overhead = cur->bc_private.a.priv.refc.shape_changes * + xfs_allocfree_log_count(cur->bc_mp, 1); + overhead *= cur->bc_mp->m_sb.sb_blocksize; + + /* + * Only allow 2 refcount extent updates per transaction if the + * refcount continue update "error" has been injected. + */ + if (cur->bc_private.a.priv.refc.nr_ops > 2 && + XFS_TEST_ERROR(false, cur->bc_mp, + XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE, + XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE)) + return false; + + if (cur->bc_private.a.priv.refc.nr_ops == 0) + return true; + else if (overhead > cur->bc_tp->t_log_res) + return false; + return cur->bc_tp->t_log_res - overhead > + cur->bc_private.a.priv.refc.nr_ops * 32; +} + +/* + * Adjust the refcounts of middle extents. At this point we should have + * split extents that crossed the adjustment range; merged with adjacent + * extents; and updated agbno/aglen to reflect the merges. Therefore, + * all we have to do is update the extents inside [agbno, agbno + aglen]. + */ +STATIC int +xfs_refcount_adjust_extents( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_extlen_t *adjusted, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops, + struct xfs_owner_info *oinfo) +{ + struct xfs_refcount_irec ext, tmp; + int error; + int found_rec, found_tmp; + xfs_fsblock_t fsbno; + + /* Merging did all the work already. */ + if (aglen == 0) + return 0; + + error = xfs_refcountbt_lookup_ge(cur, agbno, &found_rec); + if (error) + goto out_error; + + while (aglen > 0 && xfs_refcount_still_have_space(cur)) { + error = xfs_refcountbt_get_rec(cur, &ext, &found_rec); + if (error) + goto out_error; + if (!found_rec) { + ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks; + ext.rc_blockcount = 0; + ext.rc_refcount = 0; + } + + /* + * Deal with a hole in the refcount tree; if a file maps to + * these blocks and there's no refcountbt recourd, pretend that + * there is one with refcount == 1. + */ + if (ext.rc_startblock != agbno) { + tmp.rc_startblock = agbno; + tmp.rc_blockcount = min(aglen, + ext.rc_startblock - agbno); + tmp.rc_refcount = 1 + adj; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &tmp); + + /* + * Either cover the hole (increment) or + * delete the range (decrement). + */ + if (tmp.rc_refcount) { + error = xfs_refcountbt_insert(cur, &tmp, + &found_tmp); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_tmp == 1, out_error); + cur->bc_private.a.priv.refc.nr_ops++; + } else { + fsbno = XFS_AGB_TO_FSB(cur->bc_mp, + cur->bc_private.a.agno, + tmp.rc_startblock); + xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, + tmp.rc_blockcount, oinfo); + } + + (*adjusted) += tmp.rc_blockcount; + agbno += tmp.rc_blockcount; + aglen -= tmp.rc_blockcount; + + error = xfs_refcountbt_lookup_ge(cur, agbno, + &found_rec); + if (error) + goto out_error; + } + + /* Stop if there's nothing left to modify */ + if (aglen == 0 || !xfs_refcount_still_have_space(cur)) + break; + + /* + * Adjust the reference count and either update the tree + * (incr) or free the blocks (decr). + */ + if (ext.rc_refcount == MAXREFCOUNT) + goto skip; + ext.rc_refcount += adj; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &ext); + if (ext.rc_refcount > 1) { + error = xfs_refcountbt_update(cur, &ext); + if (error) + goto out_error; + cur->bc_private.a.priv.refc.nr_ops++; + } else if (ext.rc_refcount == 1) { + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_rec == 1, out_error); + cur->bc_private.a.priv.refc.nr_ops++; + goto advloop; + } else { + fsbno = XFS_AGB_TO_FSB(cur->bc_mp, + cur->bc_private.a.agno, + ext.rc_startblock); + xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, + ext.rc_blockcount, oinfo); + } + +skip: + error = xfs_btree_increment(cur, 0, &found_rec); + if (error) + goto out_error; + +advloop: + (*adjusted) += ext.rc_blockcount; + agbno += ext.rc_blockcount; + aglen -= ext.rc_blockcount; + } + + return error; +out_error: + trace_xfs_refcount_modify_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* Adjust the reference count of a range of AG blocks. */ +STATIC int +xfs_refcount_adjust( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_extlen_t *adjusted, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops, + struct xfs_owner_info *oinfo) +{ + xfs_extlen_t orig_aglen; + bool shape_changed; + int shape_changes = 0; + int error; + + *adjusted = 0; + switch (adj) { + case XFS_REFCOUNT_ADJUST_INCREASE: + trace_xfs_refcount_increase(cur->bc_mp, cur->bc_private.a.agno, + agbno, aglen); + break; + case XFS_REFCOUNT_ADJUST_DECREASE: + trace_xfs_refcount_decrease(cur->bc_mp, cur->bc_private.a.agno, + agbno, aglen); + break; + default: + ASSERT(0); + } + + /* + * Ensure that no rcextents cross the boundary of the adjustment range. + */ + error = xfs_refcount_split_extent(cur, agbno, &shape_changed); + if (error) + goto out_error; + if (shape_changed) + shape_changes++; + + error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed); + if (error) + goto out_error; + if (shape_changed) + shape_changes++; + + /* + * Try to merge with the left or right extents of the range. + */ + orig_aglen = aglen; + error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj, + &shape_changed); + if (error) + goto out_error; + if (shape_changed) + shape_changes++; + (*adjusted) += orig_aglen - aglen; + if (shape_changes) + cur->bc_private.a.priv.refc.shape_changes++; + + /* Now that we've taken care of the ends, adjust the middle extents */ + error = xfs_refcount_adjust_extents(cur, agbno, aglen, adjusted, adj, + dfops, oinfo); + if (error) + goto out_error; + + return 0; + +out_error: + trace_xfs_refcount_adjust_error(cur->bc_mp, cur->bc_private.a.agno, + error, _RET_IP_); + return error; +} diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 6bc614c..ffeffb5 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -92,7 +92,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_ERRTAG_BMAPIFORMAT 21 #define XFS_ERRTAG_FREE_EXTENT 22 #define XFS_ERRTAG_RMAP_FINISH_ONE 23 -#define XFS_ERRTAG_MAX 24 +#define XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE 24 +#define XFS_ERRTAG_MAX 25 /* * Random factors for above tags, 1 means always, 2 means 1/2 time, etc. @@ -121,6 +122,7 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT #define XFS_RANDOM_FREE_EXTENT 1 #define XFS_RANDOM_RMAP_FINISH_ONE 1 +#define XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE 1 #ifdef DEBUG extern int xfs_error_test_active; From darrick.wong@oracle.com Thu Jun 16 20:24:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1C9767E39 for ; Thu, 16 Jun 2016 20:24:53 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id E21BC304048 for ; Thu, 16 Jun 2016 18:24:52 -0700 (PDT) X-ASG-Debug-ID: 1466126689-04cb6c542557730001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id sSHftcDQXeD75zS0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:49 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Okla009069 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:47 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Oktl021239 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:46 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1OiZD007982; Fri, 17 Jun 2016 01:24:45 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:43 -0700 Subject: [PATCH 064/119] xfs: connect refcount adjust functions to upper layers From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 064/119] xfs: connect refcount adjust functions to upper layers To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:42 -0700 Message-ID: <146612668240.12839.9385528375591866350.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126689 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17687 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the upper level interface to schedule and finish deferred refcount operations via the deferred ops mechanism. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_defer.h | 1 fs/xfs/libxfs/xfs_refcount.c | 171 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount.h | 12 +++ fs/xfs/xfs_defer_item.c | 132 ++++++++++++++++++++++++++++++++ fs/xfs/xfs_error.h | 4 + fs/xfs/xfs_log_recover.c | 79 +++++++++++++++++++ fs/xfs/xfs_trace.h | 3 + fs/xfs/xfs_trans.h | 6 + fs/xfs/xfs_trans_refcount.c | 10 ++ 9 files changed, 411 insertions(+), 7 deletions(-) diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 920642e62..4081b00 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_REFCOUNT, XFS_DEFER_OPS_TYPE_RMAP, XFS_DEFER_OPS_TYPE_FREE, XFS_DEFER_OPS_TYPE_MAX, diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index d13393b..bfbdbad 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -958,3 +958,174 @@ out_error: error, _RET_IP_); return error; } + +/* Clean up after calling xfs_refcount_finish_one. */ +void +xfs_refcount_finish_one_cleanup( + struct xfs_trans *tp, + struct xfs_btree_cur *rcur, + int error) +{ + struct xfs_buf *agbp; + + if (rcur == NULL) + return; + agbp = rcur->bc_private.a.agbp; + xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(tp, agbp); +} + +/* + * Process one of the deferred refcount operations. We pass back the + * btree cursor to maintain our lock on the btree between calls. + * This saves time and eliminates a buffer deadlock between the + * superblock and the AGF because we'll always grab them in the same + * order. + */ +int +xfs_refcount_finish_one( + struct xfs_trans *tp, + struct xfs_defer_ops *dfops, + enum xfs_refcount_intent_type type, + xfs_fsblock_t startblock, + xfs_extlen_t blockcount, + xfs_extlen_t *adjusted, + struct xfs_btree_cur **pcur) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_btree_cur *rcur; + struct xfs_buf *agbp = NULL; + int error = 0; + xfs_agnumber_t agno; + xfs_agblock_t bno; + unsigned long nr_ops = 0; + int shape_changes = 0; + + agno = XFS_FSB_TO_AGNO(mp, startblock); + ASSERT(agno != NULLAGNUMBER); + bno = XFS_FSB_TO_AGBNO(mp, startblock); + + trace_xfs_refcount_deferred(mp, XFS_FSB_TO_AGNO(mp, startblock), + type, XFS_FSB_TO_AGBNO(mp, startblock), + blockcount); + + if (XFS_TEST_ERROR(false, mp, + XFS_ERRTAG_REFCOUNT_FINISH_ONE, + XFS_RANDOM_REFCOUNT_FINISH_ONE)) + return -EIO; + + /* + * If we haven't gotten a cursor or the cursor AG doesn't match + * the startblock, get one now. + */ + rcur = *pcur; + if (rcur != NULL && rcur->bc_private.a.agno != agno) { + nr_ops = rcur->bc_private.a.priv.refc.nr_ops; + shape_changes = rcur->bc_private.a.priv.refc.shape_changes; + xfs_refcount_finish_one_cleanup(tp, rcur, 0); + rcur = NULL; + *pcur = NULL; + } + if (rcur == NULL) { + error = xfs_alloc_read_agf(tp->t_mountp, tp, agno, + XFS_ALLOC_FLAG_FREEING, &agbp); + if (error) + return error; + if (!agbp) + return -EFSCORRUPTED; + + rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, dfops); + if (!rcur) { + error = -ENOMEM; + goto out_cur; + } + rcur->bc_private.a.priv.refc.nr_ops = nr_ops; + rcur->bc_private.a.priv.refc.shape_changes = shape_changes; + } + *pcur = rcur; + + switch (type) { + case XFS_REFCOUNT_INCREASE: + error = xfs_refcount_adjust(rcur, bno, blockcount, adjusted, + XFS_REFCOUNT_ADJUST_INCREASE, dfops, NULL); + break; + case XFS_REFCOUNT_DECREASE: + error = xfs_refcount_adjust(rcur, bno, blockcount, adjusted, + XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL); + break; + default: + ASSERT(0); + error = -EFSCORRUPTED; + } + if (!error && *adjusted != blockcount) + trace_xfs_refcount_finish_one_leftover(mp, agno, type, + bno, blockcount, *adjusted); + return error; + +out_cur: + xfs_trans_brelse(tp, agbp); + + return error; +} + +/* + * Record a refcount intent for later processing. + */ +static int +__xfs_refcount_add( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_refcount_intent *ri) +{ + struct xfs_refcount_intent *new; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 0; + + trace_xfs_refcount_defer(mp, XFS_FSB_TO_AGNO(mp, ri->ri_startblock), + ri->ri_type, XFS_FSB_TO_AGBNO(mp, ri->ri_startblock), + ri->ri_blockcount); + + new = kmem_zalloc(sizeof(struct xfs_refcount_intent), + KM_SLEEP | KM_NOFS); + *new = *ri; + + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_REFCOUNT, &new->ri_list); + return 0; +} + +/* + * Increase the reference count of the blocks backing a file's extent. + */ +int +xfs_refcount_increase_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_INCREASE; + ri.ri_startblock = PREV->br_startblock; + ri.ri_blockcount = PREV->br_blockcount; + + return __xfs_refcount_add(mp, dfops, &ri); +} + +/* + * Decrease the reference count of the blocks backing a file's extent. + */ +int +xfs_refcount_decrease_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_DECREASE; + ri.ri_startblock = PREV->br_startblock; + ri.ri_blockcount = PREV->br_blockcount; + + return __xfs_refcount_add(mp, dfops, &ri); +} diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index 0b36c1d..92c05ea 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -41,4 +41,16 @@ struct xfs_refcount_intent { xfs_extlen_t ri_blockcount; }; +extern int xfs_refcount_increase_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); +extern int xfs_refcount_decrease_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); + +extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp, + struct xfs_btree_cur *rcur, int error); +extern int xfs_refcount_finish_one(struct xfs_trans *tp, + struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, + xfs_fsblock_t startblock, xfs_extlen_t blockcount, + xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur); + #endif /* __XFS_REFCOUNT_H__ */ diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c index 9ed060d..2cac94f 100644 --- a/fs/xfs/xfs_defer_item.c +++ b/fs/xfs/xfs_defer_item.c @@ -33,6 +33,8 @@ #include "xfs_extfree_item.h" #include "xfs_rmap_btree.h" #include "xfs_rmap_item.h" +#include "xfs_refcount.h" +#include "xfs_refcount_item.h" /* Extent Freeing */ @@ -263,12 +265,142 @@ const struct xfs_defer_op_type xfs_rmap_update_defer_type = { .cancel_item = xfs_rmap_update_cancel_item, }; +/* Reference Counting */ + +/* Sort rmap intents by AG. */ +static int +xfs_refcount_update_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_mount *mp = priv; + struct xfs_refcount_intent *ra; + struct xfs_refcount_intent *rb; + + ra = container_of(a, struct xfs_refcount_intent, ri_list); + rb = container_of(b, struct xfs_refcount_intent, ri_list); + return XFS_FSB_TO_AGNO(mp, ra->ri_startblock) - + XFS_FSB_TO_AGNO(mp, rb->ri_startblock); +} + +/* Get an CUI. */ +STATIC void * +xfs_refcount_update_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return xfs_trans_get_cui(tp, count); +} + +/* Log refcount updates in the intent item. */ +STATIC void +xfs_refcount_update_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ + struct xfs_refcount_intent *refc; + + refc = container_of(item, struct xfs_refcount_intent, ri_list); + xfs_trans_log_start_refcount_update(tp, intent, refc->ri_type, + refc->ri_startblock, + refc->ri_blockcount); +} + +/* Get an CUD so we can process all the deferred refcount updates. */ +STATIC void * +xfs_refcount_update_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return xfs_trans_get_cud(tp, intent, count); +} + +/* Process a deferred refcount update. */ +STATIC int +xfs_refcount_update_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + struct xfs_refcount_intent *refc; + xfs_extlen_t adjusted; + int error; + + refc = container_of(item, struct xfs_refcount_intent, ri_list); + error = xfs_trans_log_finish_refcount_update(tp, done_item, dop, + refc->ri_type, + refc->ri_startblock, + refc->ri_blockcount, + &adjusted, + (struct xfs_btree_cur **)state); + /* Did we run out of reservation? Requeue what we didn't finish. */ + if (!error && adjusted < refc->ri_blockcount) { + ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE || + refc->ri_type == XFS_REFCOUNT_DECREASE); + refc->ri_startblock += adjusted; + refc->ri_blockcount -= adjusted; + return -EAGAIN; + } + kmem_free(refc); + return error; +} + +/* Clean up after processing deferred refcounts. */ +STATIC void +xfs_refcount_update_finish_cleanup( + struct xfs_trans *tp, + void *state, + int error) +{ + struct xfs_btree_cur *rcur = state; + + xfs_refcount_finish_one_cleanup(tp, rcur, error); +} + +/* Abort all pending CUIs. */ +STATIC void +xfs_refcount_update_abort_intent( + void *intent) +{ + xfs_cui_release(intent); +} + +/* Cancel a deferred refcount update. */ +STATIC void +xfs_refcount_update_cancel_item( + struct list_head *item) +{ + struct xfs_refcount_intent *refc; + + refc = container_of(item, struct xfs_refcount_intent, ri_list); + kmem_free(refc); +} + +const struct xfs_defer_op_type xfs_refcount_update_defer_type = { + .type = XFS_DEFER_OPS_TYPE_REFCOUNT, + .max_items = XFS_CUI_MAX_FAST_EXTENTS, + .diff_items = xfs_refcount_update_diff_items, + .create_intent = xfs_refcount_update_create_intent, + .abort_intent = xfs_refcount_update_abort_intent, + .log_item = xfs_refcount_update_log_item, + .create_done = xfs_refcount_update_create_done, + .finish_item = xfs_refcount_update_finish_item, + .finish_cleanup = xfs_refcount_update_finish_cleanup, + .cancel_item = xfs_refcount_update_cancel_item, +}; + /* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_refcount_update_defer_type); xfs_defer_init_op_type(&xfs_rmap_update_defer_type); xfs_defer_init_op_type(&xfs_extent_free_defer_type); } diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index ffeffb5..83d7b62 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -93,7 +93,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_ERRTAG_FREE_EXTENT 22 #define XFS_ERRTAG_RMAP_FINISH_ONE 23 #define XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE 24 -#define XFS_ERRTAG_MAX 25 +#define XFS_ERRTAG_REFCOUNT_FINISH_ONE 25 +#define XFS_ERRTAG_MAX 26 /* * Random factors for above tags, 1 means always, 2 means 1/2 time, etc. @@ -123,6 +124,7 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_RANDOM_FREE_EXTENT 1 #define XFS_RANDOM_RMAP_FINISH_ONE 1 #define XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE 1 +#define XFS_RANDOM_REFCOUNT_FINISH_ONE 1 #ifdef DEBUG extern int xfs_error_test_active; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index e0a470a..ee37dc5 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -47,6 +47,7 @@ #include "xfs_rmap_item.h" #include "xfs_rmap_btree.h" #include "xfs_refcount_item.h" +#include "xfs_refcount.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) @@ -4833,6 +4834,15 @@ xlog_recover_process_cui( struct xfs_phys_extent *refc; xfs_fsblock_t startblock_fsb; bool op_ok; + struct xfs_cud_log_item *cudp; + struct xfs_trans *tp; + struct xfs_btree_cur *rcur = NULL; + enum xfs_refcount_intent_type type; + xfs_fsblock_t firstfsb; + xfs_extlen_t adjusted; + struct xfs_bmbt_irec irec; + struct xfs_defer_ops dfops; + bool requeue_only = false; ASSERT(!test_bit(XFS_CUI_RECOVERED, &cuip->cui_flags)); @@ -4871,9 +4881,74 @@ xlog_recover_process_cui( } } - /* XXX: do nothing for now */ + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); + if (error) + return error; + cudp = xfs_trans_get_cud(tp, cuip, cuip->cui_format.cui_nextents); + + xfs_defer_init(&dfops, &firstfsb); + for (i = 0; i < cuip->cui_format.cui_nextents; i++) { + refc = &(cuip->cui_format.cui_extents[i]); + switch (refc->pe_flags & XFS_REFCOUNT_EXTENT_TYPE_MASK) { + case XFS_REFCOUNT_EXTENT_INCREASE: + type = XFS_REFCOUNT_INCREASE; + break; + case XFS_REFCOUNT_EXTENT_DECREASE: + type = XFS_REFCOUNT_DECREASE; + break; + case XFS_REFCOUNT_EXTENT_ALLOC_COW: + type = XFS_REFCOUNT_ALLOC_COW; + break; + case XFS_REFCOUNT_EXTENT_FREE_COW: + type = XFS_REFCOUNT_FREE_COW; + break; + default: + error = -EFSCORRUPTED; + goto abort_error; + } + if (requeue_only) + adjusted = 0; + else + error = xfs_trans_log_finish_refcount_update(tp, cudp, + &dfops, type, refc->pe_startblock, refc->pe_len, + &adjusted, &rcur); + if (error) + goto abort_error; + + /* Requeue what we didn't finish. */ + if (adjusted < refc->pe_len) { + irec.br_startblock = refc->pe_startblock + adjusted; + irec.br_blockcount = refc->pe_len - adjusted; + switch (type) { + case XFS_REFCOUNT_INCREASE: + error = xfs_refcount_increase_extent( + tp->t_mountp, &dfops, &irec); + break; + case XFS_REFCOUNT_DECREASE: + error = xfs_refcount_decrease_extent( + tp->t_mountp, &dfops, &irec); + break; + default: + ASSERT(0); + } + if (error) + goto abort_error; + requeue_only = true; + } + } + + xfs_refcount_finish_one_cleanup(tp, rcur, error); + error = xfs_defer_finish(&tp, &dfops, NULL); + if (error) + goto abort_error; set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags); - xfs_cui_release(cuip); + error = xfs_trans_commit(tp); + return error; + +abort_error: + xfs_refcount_finish_one_cleanup(tp, rcur, error); + xfs_defer_cancel(&dfops); + xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 1f6cee0..8366102 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2905,6 +2905,9 @@ DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_rec_order_error); DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared); DEFINE_AG_EXTENT_EVENT(xfs_refcount_find_shared_result); DEFINE_AG_ERROR_EVENT(xfs_refcount_find_shared_error); +#define DEFINE_REFCOUNT_DEFERRED_EVENT DEFINE_PHYS_EXTENT_DEFERRED_EVENT +DEFINE_REFCOUNT_DEFERRED_EVENT(xfs_refcount_defer); +DEFINE_REFCOUNT_DEFERRED_EVENT(xfs_refcount_deferred); TRACE_EVENT(xfs_refcount_finish_one_leftover, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 2b197fd..6b6cb4a 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -33,6 +33,7 @@ struct xfs_trans; struct xfs_trans_res; struct xfs_dquot_acct; struct xfs_busy_extent; +struct xfs_defer_ops; typedef struct xfs_log_item { struct list_head li_ail; /* AIL pointers */ @@ -264,8 +265,9 @@ void xfs_trans_log_start_refcount_update(struct xfs_trans *tp, struct xfs_cud_log_item *xfs_trans_get_cud(struct xfs_trans *tp, struct xfs_cui_log_item *cuip, uint nextents); int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp, - struct xfs_cud_log_item *cudp, + struct xfs_cud_log_item *cudp, struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, - xfs_extlen_t blockcount, struct xfs_btree_cur **pcur); + xfs_extlen_t blockcount, xfs_extlen_t *adjusted, + struct xfs_btree_cur **pcur); #endif /* __XFS_TRANS_H__ */ diff --git a/fs/xfs/xfs_trans_refcount.c b/fs/xfs/xfs_trans_refcount.c index 32701e4..de30c5a 100644 --- a/fs/xfs/xfs_trans_refcount.c +++ b/fs/xfs/xfs_trans_refcount.c @@ -142,17 +142,19 @@ int xfs_trans_log_finish_refcount_update( struct xfs_trans *tp, struct xfs_cud_log_item *cudp, + struct xfs_defer_ops *dop, enum xfs_refcount_intent_type type, xfs_fsblock_t startblock, xfs_extlen_t blockcount, + xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur) { uint next_extent; struct xfs_phys_extent *refc; int error; - /* XXX: leave this empty for now */ - error = -EFSCORRUPTED; + error = xfs_refcount_finish_one(tp, dop, type, startblock, + blockcount, adjusted, pcur); /* * Mark the transaction dirty, even on error. This ensures the @@ -187,6 +189,10 @@ xfs_trans_log_finish_refcount_update( ASSERT(0); } cudp->cud_next_extent++; + if (!error && *adjusted != blockcount) { + refc->pe_len = *adjusted; + cudp->cud_format.cud_nextents = cudp->cud_next_extent; + } return error; } From darrick.wong@oracle.com Thu Jun 16 20:24:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 41C517E3E for ; Thu, 16 Jun 2016 20:24:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 12349304048 for ; Thu, 16 Jun 2016 18:24:55 -0700 (PDT) X-ASG-Debug-ID: 1466126693-04cbb01fec697a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id ayrkDYUdtzW1NDAm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:24:53 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Op7P009085 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:51 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1OoJd017018 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:24:51 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1OoGe028748; Fri, 17 Jun 2016 01:24:50 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:50 -0700 Subject: [PATCH 065/119] xfs: adjust refcount when unmapping file blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 065/119] xfs: adjust refcount when unmapping file blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:48 -0700 Message-ID: <146612668881.12839.2370993652366720708.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126693 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1307 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we're unmapping blocks from a reflinked file, decrease the refcount of the affected blocks and free the extents that are no longer in use. v2: Use deferred ops system to avoid deadlocks and running out of transaction reservation. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 972dfc2..9044e39 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -48,6 +48,7 @@ #include "xfs_filestream.h" #include "xfs_rmap_btree.h" #include "xfs_ag_resv.h" +#include "xfs_refcount.h" kmem_zone_t *xfs_bmap_free_item_zone; @@ -5061,9 +5062,16 @@ xfs_bmap_del_extent( /* * If we need to, add to list of extents to delete. */ - if (do_fx) - xfs_bmap_add_free(mp, dfops, del->br_startblock, - del->br_blockcount, NULL); + if (do_fx) { + if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) { + error = xfs_refcount_decrease_extent(mp, dfops, del); + if (error) + goto done; + } else + xfs_bmap_add_free(mp, dfops, del->br_startblock, + del->br_blockcount, NULL); + } + /* * Adjust inode # blocks in the file. */ From darrick.wong@oracle.com Thu Jun 16 20:25:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EE3797E3A for ; Thu, 16 Jun 2016 20:25:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id B0FA88F804B for ; Thu, 16 Jun 2016 18:25:01 -0700 (PDT) X-ASG-Debug-ID: 1466126700-04cbb01fef697c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id gGwBvTe2fxlUcC6u (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:00 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Ovh4028405 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:24:58 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Ovuf015344 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:24:57 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Ouol028853; Fri, 17 Jun 2016 01:24:57 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:24:56 -0700 Subject: [PATCH 066/119] xfs: add refcount btree block detection to log recovery From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 066/119] xfs: add refcount btree block detection to log recovery To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:24:55 -0700 Message-ID: <146612669508.12839.12845120903495427776.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126700 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 900 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach log recovery how to deal with refcount btree blocks. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_log_recover.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index ee37dc5..2235d94 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2238,6 +2238,7 @@ xlog_recover_get_buf_lsn( case XFS_ABTB_MAGIC: case XFS_ABTC_MAGIC: case XFS_RMAP_CRC_MAGIC: + case XFS_REFC_CRC_MAGIC: case XFS_IBT_CRC_MAGIC: case XFS_IBT_MAGIC: { struct xfs_btree_block *btb = blk; @@ -2409,6 +2410,9 @@ xlog_recover_validate_buf_type( case XFS_RMAP_CRC_MAGIC: bp->b_ops = &xfs_rmapbt_buf_ops; break; + case XFS_REFC_CRC_MAGIC: + bp->b_ops = &xfs_refcountbt_buf_ops; + break; default: xfs_warn(mp, "Bad btree block magic!"); ASSERT(0); From darrick.wong@oracle.com Thu Jun 16 20:25:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 21C2C7CB4 for ; Thu, 16 Jun 2016 20:25:09 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D76038F804B for ; Thu, 16 Jun 2016 18:25:08 -0700 (PDT) X-ASG-Debug-ID: 1466126706-04bdf01e1795b50001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id w55Kp5ddNcLI1xAN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1P4Lj009458 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:05 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1P36o010741 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:04 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1P3JH024633; Fri, 17 Jun 2016 01:25:03 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:02 -0700 Subject: [PATCH 067/119] xfs: refcount btree requires more reserved space From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 067/119] xfs: refcount btree requires more reserved space To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:01 -0700 Message-ID: <146612670132.12839.1688051800857080032.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126707 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2906 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines The reference count btree is allocated from the free space, which means that we have to ensure that an AG can't run out of free space while performing a refcount operation. In the pathological case each AG block has its own refcntbt record, so we have to keep that much space available. v2: Calculate the maximum possible size of the rmap and refcount btrees based on minimally-full btree blocks. This increases the per-AG block reservations to handle the worst case btree size. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 3 +++ fs/xfs/libxfs/xfs_refcount_btree.c | 23 +++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount_btree.h | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index be5d0df..c46db76 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -38,6 +38,7 @@ #include "xfs_buf_item.h" #include "xfs_log.h" #include "xfs_ag_resv.h" +#include "xfs_refcount_btree.h" struct workqueue_struct *xfs_alloc_wq; @@ -138,6 +139,8 @@ xfs_alloc_ag_max_usable(struct xfs_mount *mp) /* rmap root block + full tree split on full AG */ blocks += 1 + (2 * mp->m_ag_maxlevels) - 1; } + if (xfs_sb_version_hasreflink(&mp->m_sb)) + blocks += xfs_refcountbt_max_size(mp); return mp->m_sb.sb_agblocks - blocks; } diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c index 7093c71..a944fca 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.c +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -373,3 +373,26 @@ xfs_refcountbt_compute_maxlevels( mp->m_refc_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_refc_mnr, mp->m_sb.sb_agblocks); } + +/* Calculate the refcount btree size for some records. */ +xfs_extlen_t +xfs_refcountbt_calc_size( + struct xfs_mount *mp, + unsigned long long len) +{ + return xfs_btree_calc_size(mp, mp->m_refc_mnr, len); +} + +/* + * Calculate the maximum refcount btree size. + */ +xfs_extlen_t +xfs_refcountbt_max_size( + struct xfs_mount *mp) +{ + /* Bail out if we're uninitialized, which can happen in mkfs. */ + if (mp->m_refc_mxr[0] == 0) + return 0; + + return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); +} diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h index 9e9ad7c..780b02f 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.h +++ b/fs/xfs/libxfs/xfs_refcount_btree.h @@ -64,4 +64,8 @@ extern int xfs_refcountbt_maxrecs(struct xfs_mount *mp, int blocklen, bool leaf); extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); +extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, + unsigned long long len); +extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); + #endif /* __XFS_REFCOUNT_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:25:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A50D87DDC for ; Thu, 16 Jun 2016 20:25:15 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 312B7AC003 for ; Thu, 16 Jun 2016 18:25:15 -0700 (PDT) X-ASG-Debug-ID: 1466126713-04bdf01e1595b60001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id CyMFeXVT8lf0fMC1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:13 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1PBYR028843 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:11 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1P9d5010862 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:10 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1P9N4028936; Fri, 17 Jun 2016 01:25:09 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:09 -0700 Subject: [PATCH 068/119] xfs: introduce reflink utility functions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 068/119] xfs: introduce reflink utility functions To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, "Darrick J. Wong" Date: Thu, 16 Jun 2016 18:25:07 -0700 Message-ID: <146612670758.12839.3762058851402658987.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126713 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4339 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines These functions will be used by the other reflink functions to find the maximum length of a range of shared blocks. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_refcount.c | 109 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount.h | 4 ++ 2 files changed, 113 insertions(+) diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index bfbdbad..ebbb714 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1129,3 +1129,112 @@ xfs_refcount_decrease_extent( return __xfs_refcount_add(mp, dfops, &ri); } + +/* + * Given an AG extent, find the lowest-numbered run of shared blocks within + * that range and return the range in fbno/flen. If find_maximal is set, + * return the longest extent of shared blocks; if not, just return the first + * extent we find. If no shared blocks are found, flen will be set to zero. + */ +int +xfs_refcount_find_shared( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_agblock_t *fbno, + xfs_extlen_t *flen, + bool find_maximal) +{ + struct xfs_btree_cur *cur; + struct xfs_buf *agbp; + struct xfs_refcount_irec tmp; + int error; + int i, have; + int bt_error = XFS_BTREE_ERROR; + + trace_xfs_refcount_find_shared(mp, agno, agbno, aglen); + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + goto out; + cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); + + /* By default, skip the whole range */ + *fbno = agbno + aglen; + *flen = 0; + + /* Try to find a refcount extent that crosses the start */ + error = xfs_refcountbt_lookup_le(cur, agbno, &have); + if (error) + goto out_error; + if (!have) { + /* No left extent, look at the next one */ + error = xfs_btree_increment(cur, 0, &have); + if (error) + goto out_error; + if (!have) + goto done; + } + error = xfs_refcountbt_get_rec(cur, &tmp, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + /* If the extent ends before the start, look at the next one */ + if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) { + error = xfs_btree_increment(cur, 0, &have); + if (error) + goto out_error; + if (!have) + goto done; + error = xfs_refcountbt_get_rec(cur, &tmp, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } + + /* If the extent ends after the range we want, bail out */ + if (tmp.rc_startblock >= agbno + aglen) + goto done; + + /* We found the start of a shared extent! */ + if (tmp.rc_startblock < agbno) { + tmp.rc_blockcount -= (agbno - tmp.rc_startblock); + tmp.rc_startblock = agbno; + } + + *fbno = tmp.rc_startblock; + *flen = min(tmp.rc_blockcount, agbno + aglen - *fbno); + if (!find_maximal) + goto done; + + /* Otherwise, find the end of this shared extent */ + while (*fbno + *flen < agbno + aglen) { + error = xfs_btree_increment(cur, 0, &have); + if (error) + goto out_error; + if (!have) + break; + error = xfs_refcountbt_get_rec(cur, &tmp, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (tmp.rc_startblock >= agbno + aglen || + tmp.rc_startblock != *fbno + *flen) + break; + *flen = min(*flen + tmp.rc_blockcount, agbno + aglen - *fbno); + } + +done: + bt_error = XFS_BTREE_NOERROR; + trace_xfs_refcount_find_shared_result(mp, agno, *fbno, *flen); + +out_error: + xfs_btree_del_cursor(cur, bt_error); + xfs_buf_relse(agbp); +out: + if (error) + trace_xfs_refcount_find_shared_error(mp, agno, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index 92c05ea..b7b83b8 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -53,4 +53,8 @@ extern int xfs_refcount_finish_one(struct xfs_trans *tp, xfs_fsblock_t startblock, xfs_extlen_t blockcount, xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur); +extern int xfs_refcount_find_shared(struct xfs_mount *mp, xfs_agnumber_t agno, + xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, + xfs_extlen_t *flen, bool find_maximal); + #endif /* __XFS_REFCOUNT_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:25:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 021CD7CB4 for ; Thu, 16 Jun 2016 20:25:24 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id C9011304048 for ; Thu, 16 Jun 2016 18:25:23 -0700 (PDT) X-ASG-Debug-ID: 1466126719-04cb6c5425577f0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id tckMixS1TBn2tMgC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1PH8K028929 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:25:17 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1PGNF015852 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:25:16 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1PGQ5028947; Fri, 17 Jun 2016 01:25:16 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:15 -0700 Subject: [PATCH 069/119] xfs: create bmbt update intent log items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 069/119] xfs: create bmbt update intent log items To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:14 -0700 Message-ID: <146612671397.12839.14026922023398231899.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126720 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 22349 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create bmbt update intent/done log items to record redo information in the log. Because we roll transactions multiple times for reflink operations, we also have to track the status of the metadata updates that will be recorded in the post-roll transactions in case we crash before committing the final transaction. This mechanism enables log recovery to finish what was already started. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_log_format.h | 52 ++++- fs/xfs/xfs_bmap_item.c | 459 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_bmap_item.h | 97 ++++++++ fs/xfs/xfs_super.c | 21 ++ 5 files changed, 628 insertions(+), 2 deletions(-) create mode 100644 fs/xfs/xfs_bmap_item.c create mode 100644 fs/xfs/xfs_bmap_item.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 2945270..d2ce5db 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -103,6 +103,7 @@ xfs-y += xfs_aops.o \ # low-level transaction/log code xfs-y += xfs_log.o \ xfs_log_cil.o \ + xfs_bmap_item.o \ xfs_buf_item.o \ xfs_extfree_item.o \ xfs_icreate_item.o \ diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 923b08f..320a305 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -114,7 +114,9 @@ static inline uint xlog_get_cycle(char *ptr) #define XLOG_REG_TYPE_RUD_FORMAT 22 #define XLOG_REG_TYPE_CUI_FORMAT 23 #define XLOG_REG_TYPE_CUD_FORMAT 24 -#define XLOG_REG_TYPE_MAX 24 +#define XLOG_REG_TYPE_BUI_FORMAT 25 +#define XLOG_REG_TYPE_BUD_FORMAT 26 +#define XLOG_REG_TYPE_MAX 26 /* * Flags to log operation header @@ -235,6 +237,8 @@ typedef struct xfs_trans_header { #define XFS_LI_RUD 0x1241 #define XFS_LI_CUI 0x1242 /* refcount update intent */ #define XFS_LI_CUD 0x1243 +#define XFS_LI_BUI 0x1244 /* bmbt update intent */ +#define XFS_LI_BUD 0x1245 #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ @@ -248,7 +252,9 @@ typedef struct xfs_trans_header { { XFS_LI_RUI, "XFS_LI_RUI" }, \ { XFS_LI_RUD, "XFS_LI_RUD" }, \ { XFS_LI_CUI, "XFS_LI_CUI" }, \ - { XFS_LI_CUD, "XFS_LI_CUD" } + { XFS_LI_CUD, "XFS_LI_CUD" }, \ + { XFS_LI_BUI, "XFS_LI_BUI" }, \ + { XFS_LI_BUD, "XFS_LI_BUD" } /* * Inode Log Item Format definitions. @@ -717,6 +723,48 @@ struct xfs_cud_log_format { }; /* + * BUI/BUD (inode block mapping) log format definitions + */ + +/* bmbt me_flags: upper bits are flags, lower byte is type code */ +#define XFS_BMAP_EXTENT_MAP 1 +#define XFS_BMAP_EXTENT_UNMAP 2 +#define XFS_BMAP_EXTENT_TYPE_MASK 0xFF + +#define XFS_BMAP_EXTENT_ATTR_FORK (1U << 31) +#define XFS_BMAP_EXTENT_UNWRITTEN (1U << 30) + +#define XFS_BMAP_EXTENT_FLAGS (XFS_BMAP_EXTENT_TYPE_MASK | \ + XFS_BMAP_EXTENT_ATTR_FORK | \ + XFS_BMAP_EXTENT_UNWRITTEN) + +/* + * This is the structure used to lay out an bui log item in the + * log. The bui_extents field is a variable size array whose + * size is given by bui_nextents. + */ +struct xfs_bui_log_format { + __uint16_t bui_type; /* bui log item type */ + __uint16_t bui_size; /* size of this item */ + __uint32_t bui_nextents; /* # extents to free */ + __uint64_t bui_id; /* bui identifier */ + struct xfs_map_extent bui_extents[1]; /* array of extents to bmap */ +}; + +/* + * This is the structure used to lay out an bud log item in the + * log. The bud_extents array is a variable size array whose + * size is given by bud_nextents; + */ +struct xfs_bud_log_format { + __uint16_t bud_type; /* bud log item type */ + __uint16_t bud_size; /* size of this item */ + __uint32_t bud_nextents; /* # of extents freed */ + __uint64_t bud_bui_id; /* id of corresponding bui */ + struct xfs_map_extent bud_extents[1]; /* array of extents bmapped */ +}; + +/* * Dquot Log format definitions. * * The first two fields must be the type and size fitting into diff --git a/fs/xfs/xfs_bmap_item.c b/fs/xfs/xfs_bmap_item.c new file mode 100644 index 0000000..19bd7dd --- /dev/null +++ b/fs/xfs/xfs_bmap_item.c @@ -0,0 +1,459 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_buf_item.h" +#include "xfs_bmap_item.h" +#include "xfs_log.h" + + +kmem_zone_t *xfs_bui_zone; +kmem_zone_t *xfs_bud_zone; + +static inline struct xfs_bui_log_item *BUI_ITEM(struct xfs_log_item *lip) +{ + return container_of(lip, struct xfs_bui_log_item, bui_item); +} + +void +xfs_bui_item_free( + struct xfs_bui_log_item *buip) +{ + if (buip->bui_format.bui_nextents > XFS_BUI_MAX_FAST_EXTENTS) + kmem_free(buip); + else + kmem_zone_free(xfs_bui_zone, buip); +} + +/* + * This returns the number of iovecs needed to log the given bui item. + * We only need 1 iovec for an bui item. It just logs the bui_log_format + * structure. + */ +static inline int +xfs_bui_item_sizeof( + struct xfs_bui_log_item *buip) +{ + return sizeof(struct xfs_bui_log_format) + + (buip->bui_format.bui_nextents - 1) * + sizeof(struct xfs_map_extent); +} + +STATIC void +xfs_bui_item_size( + struct xfs_log_item *lip, + int *nvecs, + int *nbytes) +{ + *nvecs += 1; + *nbytes += xfs_bui_item_sizeof(BUI_ITEM(lip)); +} + +/* + * This is called to fill in the vector of log iovecs for the + * given bui log item. We use only 1 iovec, and we point that + * at the bui_log_format structure embedded in the bui item. + * It is at this point that we assert that all of the extent + * slots in the bui item have been filled. + */ +STATIC void +xfs_bui_item_format( + struct xfs_log_item *lip, + struct xfs_log_vec *lv) +{ + struct xfs_bui_log_item *buip = BUI_ITEM(lip); + struct xfs_log_iovec *vecp = NULL; + + ASSERT(atomic_read(&buip->bui_next_extent) == + buip->bui_format.bui_nextents); + + buip->bui_format.bui_type = XFS_LI_BUI; + buip->bui_format.bui_size = 1; + + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUI_FORMAT, &buip->bui_format, + xfs_bui_item_sizeof(buip)); +} + +/* + * Pinning has no meaning for an bui item, so just return. + */ +STATIC void +xfs_bui_item_pin( + struct xfs_log_item *lip) +{ +} + +/* + * The unpin operation is the last place an BUI is manipulated in the log. It is + * either inserted in the AIL or aborted in the event of a log I/O error. In + * either case, the BUI transaction has been successfully committed to make it + * this far. Therefore, we expect whoever committed the BUI to either construct + * and commit the BUD or drop the BUD's reference in the event of error. Simply + * drop the log's BUI reference now that the log is done with it. + */ +STATIC void +xfs_bui_item_unpin( + struct xfs_log_item *lip, + int remove) +{ + struct xfs_bui_log_item *buip = BUI_ITEM(lip); + + xfs_bui_release(buip); +} + +/* + * BUI items have no locking or pushing. However, since BUIs are pulled from + * the AIL when their corresponding BUDs are committed to disk, their situation + * is very similar to being pinned. Return XFS_ITEM_PINNED so that the caller + * will eventually flush the log. This should help in getting the BUI out of + * the AIL. + */ +STATIC uint +xfs_bui_item_push( + struct xfs_log_item *lip, + struct list_head *buffer_list) +{ + return XFS_ITEM_PINNED; +} + +/* + * The BUI has been either committed or aborted if the transaction has been + * cancelled. If the transaction was cancelled, an BUD isn't going to be + * constructed and thus we free the BUI here directly. + */ +STATIC void +xfs_bui_item_unlock( + struct xfs_log_item *lip) +{ + if (lip->li_flags & XFS_LI_ABORTED) + xfs_bui_item_free(BUI_ITEM(lip)); +} + +/* + * The BUI is logged only once and cannot be moved in the log, so simply return + * the lsn at which it's been logged. + */ +STATIC xfs_lsn_t +xfs_bui_item_committed( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ + return lsn; +} + +/* + * The BUI dependency tracking op doesn't do squat. It can't because + * it doesn't know where the free extent is coming from. The dependency + * tracking has to be handled by the "enclosing" metadata object. For + * example, for inodes, the inode is locked throughout the extent freeing + * so the dependency should be recorded there. + */ +STATIC void +xfs_bui_item_committing( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ +} + +/* + * This is the ops vector shared by all bui log items. + */ +static const struct xfs_item_ops xfs_bui_item_ops = { + .iop_size = xfs_bui_item_size, + .iop_format = xfs_bui_item_format, + .iop_pin = xfs_bui_item_pin, + .iop_unpin = xfs_bui_item_unpin, + .iop_unlock = xfs_bui_item_unlock, + .iop_committed = xfs_bui_item_committed, + .iop_push = xfs_bui_item_push, + .iop_committing = xfs_bui_item_committing, +}; + +/* + * Allocate and initialize an bui item with the given number of extents. + */ +struct xfs_bui_log_item * +xfs_bui_init( + struct xfs_mount *mp, + uint nextents) + +{ + struct xfs_bui_log_item *buip; + uint size; + + ASSERT(nextents > 0); + if (nextents > XFS_BUI_MAX_FAST_EXTENTS) { + size = (uint)(sizeof(struct xfs_bui_log_item) + + ((nextents - 1) * sizeof(struct xfs_map_extent))); + buip = kmem_zalloc(size, KM_SLEEP); + } else { + buip = kmem_zone_zalloc(xfs_bui_zone, KM_SLEEP); + } + + xfs_log_item_init(mp, &buip->bui_item, XFS_LI_BUI, &xfs_bui_item_ops); + buip->bui_format.bui_nextents = nextents; + buip->bui_format.bui_id = (uintptr_t)(void *)buip; + atomic_set(&buip->bui_next_extent, 0); + atomic_set(&buip->bui_refcount, 2); + + return buip; +} + +/* + * Copy an BUI format buffer from the given buf, and into the destination + * BUI format structure. The BUI/BUD items were designed not to need any + * special alignment handling. + */ +int +xfs_bui_copy_format( + struct xfs_log_iovec *buf, + struct xfs_bui_log_format *dst_bui_fmt) +{ + struct xfs_bui_log_format *src_bui_fmt; + uint len; + + src_bui_fmt = buf->i_addr; + len = sizeof(struct xfs_bui_log_format) + + (src_bui_fmt->bui_nextents - 1) * + sizeof(struct xfs_map_extent); + + if (buf->i_len == len) { + memcpy((char *)dst_bui_fmt, (char *)src_bui_fmt, len); + return 0; + } + return -EFSCORRUPTED; +} + +/* + * Freeing the BUI requires that we remove it from the AIL if it has already + * been placed there. However, the BUI may not yet have been placed in the AIL + * when called by xfs_bui_release() from BUD processing due to the ordering of + * committed vs unpin operations in bulk insert operations. Hence the reference + * count to ensure only the last caller frees the BUI. + */ +void +xfs_bui_release( + struct xfs_bui_log_item *buip) +{ + if (atomic_dec_and_test(&buip->bui_refcount)) { + xfs_trans_ail_remove(&buip->bui_item, SHUTDOWN_LOG_IO_ERROR); + xfs_bui_item_free(buip); + } +} + +static inline struct xfs_bud_log_item *BUD_ITEM(struct xfs_log_item *lip) +{ + return container_of(lip, struct xfs_bud_log_item, bud_item); +} + +STATIC void +xfs_bud_item_free(struct xfs_bud_log_item *budp) +{ + if (budp->bud_format.bud_nextents > XFS_BUD_MAX_FAST_EXTENTS) + kmem_free(budp); + else + kmem_zone_free(xfs_bud_zone, budp); +} + +/* + * This returns the number of iovecs needed to log the given bud item. + * We only need 1 iovec for an bud item. It just logs the bud_log_format + * structure. + */ +static inline int +xfs_bud_item_sizeof( + struct xfs_bud_log_item *budp) +{ + return sizeof(struct xfs_bud_log_format) + + (budp->bud_format.bud_nextents - 1) * + sizeof(struct xfs_map_extent); +} + +STATIC void +xfs_bud_item_size( + struct xfs_log_item *lip, + int *nvecs, + int *nbytes) +{ + *nvecs += 1; + *nbytes += xfs_bud_item_sizeof(BUD_ITEM(lip)); +} + +/* + * This is called to fill in the vector of log iovecs for the + * given bud log item. We use only 1 iovec, and we point that + * at the bud_log_format structure embedded in the bud item. + * It is at this point that we assert that all of the extent + * slots in the bud item have been filled. + */ +STATIC void +xfs_bud_item_format( + struct xfs_log_item *lip, + struct xfs_log_vec *lv) +{ + struct xfs_bud_log_item *budp = BUD_ITEM(lip); + struct xfs_log_iovec *vecp = NULL; + + ASSERT(budp->bud_next_extent == budp->bud_format.bud_nextents); + + budp->bud_format.bud_type = XFS_LI_BUD; + budp->bud_format.bud_size = 1; + + xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_BUD_FORMAT, &budp->bud_format, + xfs_bud_item_sizeof(budp)); +} + +/* + * Pinning has no meaning for an bud item, so just return. + */ +STATIC void +xfs_bud_item_pin( + struct xfs_log_item *lip) +{ +} + +/* + * Since pinning has no meaning for an bud item, unpinning does + * not either. + */ +STATIC void +xfs_bud_item_unpin( + struct xfs_log_item *lip, + int remove) +{ +} + +/* + * There isn't much you can do to push on an bud item. It is simply stuck + * waiting for the log to be flushed to disk. + */ +STATIC uint +xfs_bud_item_push( + struct xfs_log_item *lip, + struct list_head *buffer_list) +{ + return XFS_ITEM_PINNED; +} + +/* + * The BUD is either committed or aborted if the transaction is cancelled. If + * the transaction is cancelled, drop our reference to the BUI and free the + * BUD. + */ +STATIC void +xfs_bud_item_unlock( + struct xfs_log_item *lip) +{ + struct xfs_bud_log_item *budp = BUD_ITEM(lip); + + if (lip->li_flags & XFS_LI_ABORTED) { + xfs_bui_release(budp->bud_buip); + xfs_bud_item_free(budp); + } +} + +/* + * When the bud item is committed to disk, all we need to do is delete our + * reference to our partner bui item and then free ourselves. Since we're + * freeing ourselves we must return -1 to keep the transaction code from + * further referencing this item. + */ +STATIC xfs_lsn_t +xfs_bud_item_committed( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ + struct xfs_bud_log_item *budp = BUD_ITEM(lip); + + /* + * Drop the BUI reference regardless of whether the BUD has been + * aborted. Once the BUD transaction is constructed, it is the sole + * responsibility of the BUD to release the BUI (even if the BUI is + * aborted due to log I/O error). + */ + xfs_bui_release(budp->bud_buip); + xfs_bud_item_free(budp); + + return (xfs_lsn_t)-1; +} + +/* + * The BUD dependency tracking op doesn't do squat. It can't because + * it doesn't know where the free extent is coming from. The dependency + * tracking has to be handled by the "enclosing" metadata object. For + * example, for inodes, the inode is locked throughout the extent freeing + * so the dependency should be recorded there. + */ +STATIC void +xfs_bud_item_committing( + struct xfs_log_item *lip, + xfs_lsn_t lsn) +{ +} + +/* + * This is the ops vector shared by all bud log items. + */ +static const struct xfs_item_ops xfs_bud_item_ops = { + .iop_size = xfs_bud_item_size, + .iop_format = xfs_bud_item_format, + .iop_pin = xfs_bud_item_pin, + .iop_unpin = xfs_bud_item_unpin, + .iop_unlock = xfs_bud_item_unlock, + .iop_committed = xfs_bud_item_committed, + .iop_push = xfs_bud_item_push, + .iop_committing = xfs_bud_item_committing, +}; + +/* + * Allocate and initialize an bud item with the given number of extents. + */ +struct xfs_bud_log_item * +xfs_bud_init( + struct xfs_mount *mp, + struct xfs_bui_log_item *buip, + uint nextents) + +{ + struct xfs_bud_log_item *budp; + uint size; + + ASSERT(nextents > 0); + if (nextents > XFS_BUD_MAX_FAST_EXTENTS) { + size = (uint)(sizeof(struct xfs_bud_log_item) + + ((nextents - 1) * sizeof(struct xfs_map_extent))); + budp = kmem_zalloc(size, KM_SLEEP); + } else { + budp = kmem_zone_zalloc(xfs_bud_zone, KM_SLEEP); + } + + xfs_log_item_init(mp, &budp->bud_item, XFS_LI_BUD, &xfs_bud_item_ops); + budp->bud_buip = buip; + budp->bud_format.bud_nextents = nextents; + budp->bud_format.bud_bui_id = buip->bui_format.bui_id; + + return budp; +} diff --git a/fs/xfs/xfs_bmap_item.h b/fs/xfs/xfs_bmap_item.h new file mode 100644 index 0000000..a992c09 --- /dev/null +++ b/fs/xfs/xfs_bmap_item.h @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_BMAP_ITEM_H__ +#define __XFS_BMAP_ITEM_H__ + +/* + * There are (currently) two pairs of bmap btree redo item types: map & unmap. + * The common abbreviations for these are BUI (bmap update intent) and BUD + * (bmap update done). The redo item type is encoded in the flags field of + * each xfs_map_extent. + * + * *I items should be recorded in the *first* of a series of rolled + * transactions, and the *D items should be recorded in the same transaction + * that records the associated bmbt updates. + * + * Should the system crash after the commit of the first transaction but + * before the commit of the final transaction in a series, log recovery will + * use the redo information recorded by the intent items to replay the + * bmbt metadata updates in the non-first transaction. + */ + +/* kernel only BUI/BUD definitions */ + +struct xfs_mount; +struct kmem_zone; + +/* + * Max number of extents in fast allocation path. + */ +#define XFS_BUI_MAX_FAST_EXTENTS 16 + +/* + * Define BUI flag bits. Manipulated by set/clear/test_bit operators. + */ +#define XFS_BUI_RECOVERED 1 + +/* + * This is the "bmap update intent" log item. It is used to log the fact that + * some reverse mappings need to change. It is used in conjunction with the + * "bmap update done" log item described below. + * + * These log items follow the same rules as struct xfs_efi_log_item; see the + * comments about that structure (in xfs_extfree_item.h) for more details. + */ +struct xfs_bui_log_item { + struct xfs_log_item bui_item; + atomic_t bui_refcount; + atomic_t bui_next_extent; + unsigned long bui_flags; /* misc flags */ + struct xfs_bui_log_format bui_format; +}; + +/* + * This is the "bmap update done" log item. It is used to log the fact that + * some bmbt updates mentioned in an earlier bui item have been performed. + */ +struct xfs_bud_log_item { + struct xfs_log_item bud_item; + struct xfs_bui_log_item *bud_buip; + uint bud_next_extent; + struct xfs_bud_log_format bud_format; +}; + +/* + * Max number of extents in fast allocation path. + */ +#define XFS_BUD_MAX_FAST_EXTENTS 16 + +extern struct kmem_zone *xfs_bui_zone; +extern struct kmem_zone *xfs_bud_zone; + +struct xfs_bui_log_item *xfs_bui_init(struct xfs_mount *, uint); +struct xfs_bud_log_item *xfs_bud_init(struct xfs_mount *, + struct xfs_bui_log_item *, uint); +int xfs_bui_copy_format(struct xfs_log_iovec *buf, + struct xfs_bui_log_format *dst_bui_fmt); +void xfs_bui_item_free(struct xfs_bui_log_item *); +void xfs_bui_release(struct xfs_bui_log_item *); + +#endif /* __XFS_BMAP_ITEM_H__ */ diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index a0c7bdc..18f74b3 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -49,6 +49,7 @@ #include "xfs_defer.h" #include "xfs_rmap_item.h" #include "xfs_refcount_item.h" +#include "xfs_bmap_item.h" #include #include @@ -1796,8 +1797,26 @@ xfs_init_zones(void) if (!xfs_cui_zone) goto out_destroy_cud_zone; + xfs_bud_zone = kmem_zone_init((sizeof(struct xfs_bud_log_item) + + ((XFS_BUD_MAX_FAST_EXTENTS - 1) * + sizeof(struct xfs_map_extent))), + "xfs_bud_item"); + if (!xfs_bud_zone) + goto out_destroy_cui_zone; + + xfs_bui_zone = kmem_zone_init((sizeof(struct xfs_bui_log_item) + + ((XFS_BUI_MAX_FAST_EXTENTS - 1) * + sizeof(struct xfs_map_extent))), + "xfs_bui_item"); + if (!xfs_bui_zone) + goto out_destroy_bud_zone; + return 0; + out_destroy_bud_zone: + kmem_zone_destroy(xfs_bud_zone); + out_destroy_cui_zone: + kmem_zone_destroy(xfs_cui_zone); out_destroy_cud_zone: kmem_zone_destroy(xfs_cud_zone); out_destroy_rui_zone: @@ -1844,6 +1863,8 @@ xfs_destroy_zones(void) * destroy caches. */ rcu_barrier(); + kmem_zone_destroy(xfs_bui_zone); + kmem_zone_destroy(xfs_bud_zone); kmem_zone_destroy(xfs_cui_zone); kmem_zone_destroy(xfs_cud_zone); kmem_zone_destroy(xfs_rui_zone); From darrick.wong@oracle.com Thu Jun 16 20:25:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 856DE7E2D for ; Thu, 16 Jun 2016 20:25:34 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 56E62304039 for ; Thu, 16 Jun 2016 18:25:34 -0700 (PDT) X-ASG-Debug-ID: 1466126732-04cbb01fef69820001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id FNTxfRwoQpSdf564 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:32 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1PUVK009707 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:30 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1PUib022338 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:30 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1PTl6020412; Fri, 17 Jun 2016 01:25:29 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:28 -0700 Subject: [PATCH 071/119] xfs: map an inode's offset to an exact physical block From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 071/119] xfs: map an inode's offset to an exact physical block To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:27 -0700 Message-ID: <146612672734.12839.14219026280860191575.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126732 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6448 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach the bmap routine to know how to map a range of file blocks to a specific range of physical blocks, instead of simply allocating fresh blocks. This enables reflink to map a file to blocks that are already in use. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_bmap.h | 10 +++++++ fs/xfs/xfs_trace.h | 54 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 9044e39..c29dcdb 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3872,6 +3872,55 @@ xfs_bmap_btalloc( } /* + * For a remap operation, just "allocate" an extent at the address that the + * caller passed in, and ensure that the AGFL is the right size. The caller + * will then map the "allocated" extent into the file somewhere. + */ +STATIC int +xfs_bmap_remap_alloc( + struct xfs_bmalloca *ap) +{ + struct xfs_trans *tp = ap->tp; + struct xfs_mount *mp = tp->t_mountp; + xfs_agblock_t bno; + struct xfs_alloc_arg args; + int error; + + /* + * validate that the block number is legal - the enables us to detect + * and handle a silent filesystem corruption rather than crashing. + */ + memset(&args, 0, sizeof(struct xfs_alloc_arg)); + args.tp = ap->tp; + args.mp = ap->tp->t_mountp; + bno = *ap->firstblock; + args.agno = XFS_FSB_TO_AGNO(mp, bno); + ASSERT(args.agno < mp->m_sb.sb_agcount); + args.agbno = XFS_FSB_TO_AGBNO(mp, bno); + ASSERT(args.agbno < mp->m_sb.sb_agblocks); + + /* "Allocate" the extent from the range we passed in. */ + trace_xfs_bmap_remap_alloc(ap->ip, *ap->firstblock, ap->length); + ap->blkno = bno; + ap->ip->i_d.di_nblocks += ap->length; + xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); + + /* Fix the freelist, like a real allocator does. */ + args.userdata = 1; + args.pag = xfs_perag_get(args.mp, args.agno); + ASSERT(args.pag); + + error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); + if (error) + goto error0; +error0: + xfs_perag_put(args.pag); + if (error) + trace_xfs_bmap_remap_alloc_error(ap->ip, error, _RET_IP_); + return error; +} + +/* * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. * It figures out where to ask the underlying allocator to put the new extent. */ @@ -3879,6 +3928,8 @@ STATIC int xfs_bmap_alloc( struct xfs_bmalloca *ap) /* bmap alloc argument struct */ { + if (ap->flags & XFS_BMAPI_REMAP) + return xfs_bmap_remap_alloc(ap); if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata) return xfs_bmap_rtalloc(ap); return xfs_bmap_btalloc(ap); @@ -4515,6 +4566,12 @@ xfs_bmapi_write( ASSERT(len > 0); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + if (whichfork == XFS_ATTR_FORK) + ASSERT(!(flags & XFS_BMAPI_REMAP)); + if (flags & XFS_BMAPI_REMAP) { + ASSERT(!(flags & XFS_BMAPI_PREALLOC)); + ASSERT(!(flags & XFS_BMAPI_CONVERT)); + } /* zeroing is for currently only for data extents, not metadata */ ASSERT((flags & (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)) != @@ -4576,6 +4633,12 @@ xfs_bmapi_write( wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); /* + * Make sure we only reflink into a hole. + */ + if (flags & XFS_BMAPI_REMAP) + ASSERT(inhole); + + /* * First, deal with the hole before the allocated space * that we found, if any. */ diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 62a66d0..fb2fd4c 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -97,6 +97,13 @@ struct xfs_bmap_free_item */ #define XFS_BMAPI_ZERO 0x080 +/* + * Map the inode offset to the block given in ap->firstblock. Primarily + * used for reflink. The range must be in a hole, and this flag cannot be + * turned on with PREALLOC or CONVERT, and cannot be used on the attr fork. + */ +#define XFS_BMAPI_REMAP 0x100 + #define XFS_BMAPI_FLAGS \ { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ { XFS_BMAPI_METADATA, "METADATA" }, \ @@ -105,7 +112,8 @@ struct xfs_bmap_free_item { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ { XFS_BMAPI_CONTIG, "CONTIG" }, \ { XFS_BMAPI_CONVERT, "CONVERT" }, \ - { XFS_BMAPI_ZERO, "ZERO" } + { XFS_BMAPI_ZERO, "ZERO" }, \ + { XFS_BMAPI_REMAP, "REMAP" } static inline int xfs_bmapi_aflag(int w) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 8366102..8844c9f 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2939,6 +2939,60 @@ TRACE_EVENT(xfs_refcount_finish_one_leftover, __entry->adjusted) ); +/* simple inode-based error/%ip tracepoint class */ +DECLARE_EVENT_CLASS(xfs_inode_error_class, + TP_PROTO(struct xfs_inode *ip, int error, unsigned long caller_ip), + TP_ARGS(ip, error, caller_ip), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(int, error) + __field(unsigned long, caller_ip) + ), + TP_fast_assign( + __entry->dev = VFS_I(ip)->i_sb->s_dev; + __entry->ino = ip->i_ino; + __entry->error = error; + __entry->caller_ip = caller_ip; + ), + TP_printk("dev %d:%d ino %llx error %d caller %ps", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->error, + (char *)__entry->caller_ip) +); + +#define DEFINE_INODE_ERROR_EVENT(name) \ +DEFINE_EVENT(xfs_inode_error_class, name, \ + TP_PROTO(struct xfs_inode *ip, int error, \ + unsigned long caller_ip), \ + TP_ARGS(ip, error, caller_ip)) + +/* reflink allocator */ +TRACE_EVENT(xfs_bmap_remap_alloc, + TP_PROTO(struct xfs_inode *ip, xfs_fsblock_t fsbno, + xfs_extlen_t len), + TP_ARGS(ip, fsbno, len), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(xfs_fsblock_t, fsbno) + __field(xfs_extlen_t, len) + ), + TP_fast_assign( + __entry->dev = VFS_I(ip)->i_sb->s_dev; + __entry->ino = ip->i_ino; + __entry->fsbno = fsbno; + __entry->len = len; + ), + TP_printk("dev %d:%d ino 0x%llx fsbno 0x%llx len %x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->fsbno, + __entry->len) +); +DEFINE_INODE_ERROR_EVENT(xfs_bmap_remap_alloc_error); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:25:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_LOLITA1, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 47E227E2D for ; Thu, 16 Jun 2016 20:25:35 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 19422304039 for ; Thu, 16 Jun 2016 18:25:35 -0700 (PDT) X-ASG-Debug-ID: 1466126730-04cb6c542757870001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id a4xEtXDsr76JSgVg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:31 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1PNSR009684 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:24 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1PN6r011084 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:23 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1PMkh028957; Fri, 17 Jun 2016 01:25:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:22 -0700 Subject: [PATCH 070/119] xfs: log bmap intent items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 070/119] xfs: log bmap intent items To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:20 -0700 Message-ID: <146612672092.12839.1498624909455170579.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126730 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19604 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a mechanism for higher levels to create BUI/BUD items, submit them to the log, and a stub function to deal with recovered BUI items. These parts will be connected to the rmapbt in a later patch. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_bmap.h | 13 ++ fs/xfs/xfs_log_recover.c | 301 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_trans.h | 18 +++ fs/xfs/xfs_trans_bmap.c | 201 +++++++++++++++++++++++++++++++ 5 files changed, 533 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/xfs_trans_bmap.c diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index d2ce5db..941afe6 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -112,6 +112,7 @@ xfs-y += xfs_log.o \ xfs_rmap_item.o \ xfs_log_recover.o \ xfs_trans_ail.o \ + xfs_trans_bmap.o \ xfs_trans_buf.o \ xfs_trans_extfree.o \ xfs_trans_inode.o \ diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 862ea464..62a66d0 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -209,4 +209,17 @@ struct xfs_bmbt_rec_host * struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp); +enum xfs_bmap_intent_type { + XFS_BMAP_MAP, + XFS_BMAP_UNMAP, +}; + +struct xfs_bmap_intent { + struct list_head bi_list; + enum xfs_bmap_intent_type bi_type; + struct xfs_inode *bi_owner; + int bi_whichfork; + struct xfs_bmbt_irec bi_bmap; +}; + #endif /* __XFS_BMAP_H__ */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 2235d94..42000f4 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -48,6 +48,8 @@ #include "xfs_rmap_btree.h" #include "xfs_refcount_item.h" #include "xfs_refcount.h" +#include "xfs_bmap_item.h" +#include "xfs_bmap.h" #define BLK_AVG(blk1, blk2) ((blk1+blk2) >> 1) @@ -1920,6 +1922,8 @@ xlog_recover_reorder_trans( case XFS_LI_RUD: case XFS_LI_CUI: case XFS_LI_CUD: + case XFS_LI_BUI: + case XFS_LI_BUD: trace_xfs_log_recover_item_reorder_tail(log, trans, item, pass); list_move_tail(&item->ri_list, &inode_list); @@ -3622,6 +3626,101 @@ xlog_recover_cud_pass2( } /* + * This routine is called to create an in-core extent bmap update + * item from the bui format structure which was logged on disk. + * It allocates an in-core bui, copies the extents from the format + * structure into it, and adds the bui to the AIL with the given + * LSN. + */ +STATIC int +xlog_recover_bui_pass2( + struct xlog *log, + struct xlog_recover_item *item, + xfs_lsn_t lsn) +{ + int error; + struct xfs_mount *mp = log->l_mp; + struct xfs_bui_log_item *buip; + struct xfs_bui_log_format *bui_formatp; + + bui_formatp = item->ri_buf[0].i_addr; + + buip = xfs_bui_init(mp, bui_formatp->bui_nextents); + error = xfs_bui_copy_format(&item->ri_buf[0], &buip->bui_format); + if (error) { + xfs_bui_item_free(buip); + return error; + } + atomic_set(&buip->bui_next_extent, bui_formatp->bui_nextents); + + spin_lock(&log->l_ailp->xa_lock); + /* + * The RUI has two references. One for the RUD and one for RUI to ensure + * it makes it into the AIL. Insert the RUI into the AIL directly and + * drop the RUI reference. Note that xfs_trans_ail_update() drops the + * AIL lock. + */ + xfs_trans_ail_update(log->l_ailp, &buip->bui_item, lsn); + xfs_bui_release(buip); + return 0; +} + + +/* + * This routine is called when an BUD format structure is found in a committed + * transaction in the log. Its purpose is to cancel the corresponding BUI if it + * was still in the log. To do this it searches the AIL for the BUI with an id + * equal to that in the BUD format structure. If we find it we drop the BUD + * reference, which removes the BUI from the AIL and frees it. + */ +STATIC int +xlog_recover_bud_pass2( + struct xlog *log, + struct xlog_recover_item *item) +{ + struct xfs_bud_log_format *bud_formatp; + struct xfs_bui_log_item *buip = NULL; + struct xfs_log_item *lip; + __uint64_t bui_id; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp = log->l_ailp; + + bud_formatp = item->ri_buf[0].i_addr; + ASSERT(item->ri_buf[0].i_len == (sizeof(struct xfs_bud_log_format) + + ((bud_formatp->bud_nextents - 1) * + sizeof(struct xfs_map_extent)))); + bui_id = bud_formatp->bud_bui_id; + + /* + * Search for the BUI with the id in the BUD format structure in the + * AIL. + */ + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + if (lip->li_type == XFS_LI_BUI) { + buip = (struct xfs_bui_log_item *)lip; + if (buip->bui_format.bui_id == bui_id) { + /* + * Drop the BUD reference to the BUI. This + * removes the BUI from the AIL and frees it. + */ + spin_unlock(&ailp->xa_lock); + xfs_bui_release(buip); + spin_lock(&ailp->xa_lock); + break; + } + } + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } + + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + + return 0; +} + +/* * This routine is called when an inode create format structure is found in a * committed transaction in the log. It's purpose is to initialise the inodes * being allocated on disk. This requires us to get inode cluster buffers that @@ -3850,6 +3949,8 @@ xlog_recover_ra_pass2( case XFS_LI_RUD: case XFS_LI_CUI: case XFS_LI_CUD: + case XFS_LI_BUI: + case XFS_LI_BUD: default: break; } @@ -3877,6 +3978,8 @@ xlog_recover_commit_pass1( case XFS_LI_RUD: case XFS_LI_CUI: case XFS_LI_CUD: + case XFS_LI_BUI: + case XFS_LI_BUD: /* nothing to do in pass 1 */ return 0; default: @@ -3915,6 +4018,10 @@ xlog_recover_commit_pass2( return xlog_recover_cui_pass2(log, item, trans->r_lsn); case XFS_LI_CUD: return xlog_recover_cud_pass2(log, item); + case XFS_LI_BUI: + return xlog_recover_bui_pass2(log, item, trans->r_lsn); + case XFS_LI_BUD: + return xlog_recover_bud_pass2(log, item); case XFS_LI_DQUOT: return xlog_recover_dquot_pass2(log, buffer_list, item, trans->r_lsn); @@ -4394,6 +4501,7 @@ static inline bool xlog_item_is_intent(struct xfs_log_item *lip) case XFS_LI_EFI: case XFS_LI_RUI: case XFS_LI_CUI: + case XFS_LI_BUI: return true; default: return false; @@ -5079,6 +5187,187 @@ xlog_recover_cancel_cuis( } /* + * Process a bmap update intent item that was recovered from the log. + * We need to update some inode's bmbt. + */ +STATIC int +xlog_recover_process_bui( + struct xfs_mount *mp, + struct xfs_bui_log_item *buip) +{ + int i; + int error = 0; + struct xfs_map_extent *bmap; + xfs_fsblock_t startblock_fsb; + xfs_fsblock_t inode_fsb; + bool op_ok; + + ASSERT(!test_bit(XFS_BUI_RECOVERED, &buip->bui_flags)); + + /* + * First check the validity of the extents described by the + * BUI. If any are bad, then assume that all are bad and + * just toss the BUI. + */ + for (i = 0; i < buip->bui_format.bui_nextents; i++) { + bmap = &(buip->bui_format.bui_extents[i]); + startblock_fsb = XFS_BB_TO_FSB(mp, + XFS_FSB_TO_DADDR(mp, bmap->me_startblock)); + inode_fsb = XFS_BB_TO_FSB(mp, XFS_FSB_TO_DADDR(mp, + XFS_INO_TO_FSB(mp, bmap->me_owner))); + switch (bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) { + case XFS_BMAP_EXTENT_MAP: + case XFS_BMAP_EXTENT_UNMAP: + op_ok = true; + break; + default: + op_ok = false; + break; + } + if (!op_ok || (startblock_fsb == 0) || + (bmap->me_len == 0) || + (inode_fsb == 0) || + (startblock_fsb >= mp->m_sb.sb_dblocks) || + (bmap->me_len >= mp->m_sb.sb_agblocks) || + (inode_fsb >= mp->m_sb.sb_agblocks) || + (bmap->me_flags & ~XFS_BMAP_EXTENT_FLAGS)) { + /* + * This will pull the BUI from the AIL and + * free the memory associated with it. + */ + set_bit(XFS_BUI_RECOVERED, &buip->bui_flags); + xfs_bui_release(buip); + return -EIO; + } + } + + /* XXX: do nothing for now */ + set_bit(XFS_BUI_RECOVERED, &buip->bui_flags); + xfs_bui_release(buip); + return error; +} + +/* + * When this is called, all of the BUIs which did not have + * corresponding BUDs should be in the AIL. What we do now + * is update the bmbts associated with each one. + * + * Since we process the BUIs in normal transactions, they + * will be removed at some point after the commit. This prevents + * us from just walking down the list processing each one. + * We'll use a flag in the BUI to skip those that we've already + * processed and use the AIL iteration mechanism's generation + * count to try to speed this up at least a bit. + * + * When we start, we know that the BUIs are the only things in + * the AIL. As we process them, however, other items are added + * to the AIL. + */ +STATIC int +xlog_recover_process_buis( + struct xlog *log) +{ + struct xfs_log_item *lip; + struct xfs_bui_log_item *buip; + int error = 0; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp; + + ailp = log->l_ailp; + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + /* + * We're done when we see something other than an intent. + * There should be no intents left in the AIL now. + */ + if (!xlog_item_is_intent(lip)) { +#ifdef DEBUG + for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) + ASSERT(!xlog_item_is_intent(lip)); +#endif + break; + } + + /* Skip anything that isn't a BUI */ + if (lip->li_type != XFS_LI_BUI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + /* + * Skip BUIs that we've already processed. + */ + buip = container_of(lip, struct xfs_bui_log_item, bui_item); + if (test_bit(XFS_BUI_RECOVERED, &buip->bui_flags)) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + spin_unlock(&ailp->xa_lock); + error = xlog_recover_process_bui(log->l_mp, buip); + spin_lock(&ailp->xa_lock); + if (error) + goto out; + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } +out: + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + return error; +} + +/* + * A cancel occurs when the mount has failed and we're bailing out. Release all + * pending BUIs so they don't pin the AIL. + */ +STATIC int +xlog_recover_cancel_buis( + struct xlog *log) +{ + struct xfs_log_item *lip; + struct xfs_bui_log_item *buip; + int error = 0; + struct xfs_ail_cursor cur; + struct xfs_ail *ailp; + + ailp = log->l_ailp; + spin_lock(&ailp->xa_lock); + lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); + while (lip != NULL) { + /* + * We're done when we see something other than an RUI. + * There should be no RUIs left in the AIL now. + */ + if (!xlog_item_is_intent(lip)) { +#ifdef DEBUG + for (; lip; lip = xfs_trans_ail_cursor_next(ailp, &cur)) + ASSERT(!xlog_item_is_intent(lip)); +#endif + break; + } + + /* Skip anything that isn't a BUI */ + if (lip->li_type != XFS_LI_BUI) { + lip = xfs_trans_ail_cursor_next(ailp, &cur); + continue; + } + + buip = container_of(lip, struct xfs_bui_log_item, bui_item); + + spin_unlock(&ailp->xa_lock); + xfs_bui_release(buip); + spin_lock(&ailp->xa_lock); + + lip = xfs_trans_ail_cursor_next(ailp, &cur); + } + + xfs_trans_ail_cursor_done(&cur); + spin_unlock(&ailp->xa_lock); + return error; +} + +/* * This routine performs a transaction to null out a bad inode pointer * in an agi unlinked inode hash bucket. */ @@ -5881,6 +6170,12 @@ xlog_recover_finish( if (log->l_flags & XLOG_RECOVERY_NEEDED) { int error; + error = xlog_recover_process_buis(log); + if (error) { + xfs_alert(log->l_mp, "Failed to recover BUIs"); + return error; + } + error = xlog_recover_process_cuis(log); if (error) { xfs_alert(log->l_mp, "Failed to recover CUIs"); @@ -5929,7 +6224,11 @@ xlog_recover_cancel( int err2; if (log->l_flags & XLOG_RECOVERY_NEEDED) { - error = xlog_recover_cancel_cuis(log); + error = xlog_recover_cancel_buis(log); + + err2 = xlog_recover_cancel_cuis(log); + if (err2 && !error) + error = err2; err2 = xlog_recover_cancel_ruis(log); if (err2 && !error) diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 6b6cb4a..cda7d92 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -270,4 +270,22 @@ int xfs_trans_log_finish_refcount_update(struct xfs_trans *tp, xfs_extlen_t blockcount, xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur); +enum xfs_bmap_intent_type; + +struct xfs_bui_log_item *xfs_trans_get_bui(struct xfs_trans *tp, uint nextents); +void xfs_trans_log_start_bmap_update(struct xfs_trans *tp, + struct xfs_bui_log_item *buip, enum xfs_bmap_intent_type type, + __uint64_t owner, int whichfork, xfs_fileoff_t startoff, + xfs_fsblock_t startblock, xfs_filblks_t blockcount, + xfs_exntst_t state); + +struct xfs_bud_log_item *xfs_trans_get_bud(struct xfs_trans *tp, + struct xfs_bui_log_item *buip, uint nextents); +int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp, + struct xfs_bud_log_item *rudp, struct xfs_defer_ops *dfops, + enum xfs_bmap_intent_type type, struct xfs_inode *ip, + int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, + xfs_filblks_t blockcount, xfs_exntst_t state, + struct xfs_btree_cur **pcur); + #endif /* __XFS_TRANS_H__ */ diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c new file mode 100644 index 0000000..1517c83 --- /dev/null +++ b/fs/xfs/xfs_trans_bmap.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_trans.h" +#include "xfs_trans_priv.h" +#include "xfs_bmap_item.h" +#include "xfs_alloc.h" +#include "xfs_bmap.h" +#include "xfs_inode.h" + +/* + * This routine is called to allocate an "bmap update intent" + * log item that will hold nextents worth of extents. The + * caller must use all nextents extents, because we are not + * flexible about this at all. + */ +struct xfs_bui_log_item * +xfs_trans_get_bui( + struct xfs_trans *tp, + uint nextents) +{ + struct xfs_bui_log_item *buip; + + ASSERT(tp != NULL); + ASSERT(nextents > 0); + + buip = xfs_bui_init(tp->t_mountp, nextents); + ASSERT(buip != NULL); + + /* + * Get a log_item_desc to point at the new item. + */ + xfs_trans_add_item(tp, &buip->bui_item); + return buip; +} + +/* + * This routine is called to indicate that the described + * extent is to be logged as needing to be freed. It should + * be called once for each extent to be freed. + */ +void +xfs_trans_log_start_bmap_update( + struct xfs_trans *tp, + struct xfs_bui_log_item *buip, + enum xfs_bmap_intent_type type, + __uint64_t owner, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state) +{ + uint next_extent; + struct xfs_map_extent *bmap; + + tp->t_flags |= XFS_TRANS_DIRTY; + buip->bui_item.li_desc->lid_flags |= XFS_LID_DIRTY; + + /* + * atomic_inc_return gives us the value after the increment; + * we want to use it as an array index so we need to subtract 1 from + * it. + */ + next_extent = atomic_inc_return(&buip->bui_next_extent) - 1; + ASSERT(next_extent < buip->bui_format.bui_nextents); + bmap = &(buip->bui_format.bui_extents[next_extent]); + bmap->me_owner = owner; + bmap->me_startblock = startblock; + bmap->me_startoff = startoff; + bmap->me_len = blockcount; + bmap->me_flags = 0; + if (state == XFS_EXT_UNWRITTEN) + bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN; + if (whichfork == XFS_ATTR_FORK) + bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK; + switch (type) { + case XFS_BMAP_MAP: + bmap->me_flags |= XFS_BMAP_EXTENT_MAP; + break; + case XFS_BMAP_UNMAP: + bmap->me_flags |= XFS_BMAP_EXTENT_UNMAP; + break; + default: + ASSERT(0); + } +} + + +/* + * This routine is called to allocate an "extent free done" + * log item that will hold nextents worth of extents. The + * caller must use all nextents extents, because we are not + * flexible about this at all. + */ +struct xfs_bud_log_item * +xfs_trans_get_bud( + struct xfs_trans *tp, + struct xfs_bui_log_item *buip, + uint nextents) +{ + struct xfs_bud_log_item *budp; + + ASSERT(tp != NULL); + ASSERT(nextents > 0); + + budp = xfs_bud_init(tp->t_mountp, buip, nextents); + ASSERT(budp != NULL); + + /* + * Get a log_item_desc to point at the new item. + */ + xfs_trans_add_item(tp, &budp->bud_item); + return budp; +} + +/* + * Finish an bmap update and log it to the BUD. Note that the transaction is + * marked dirty regardless of whether the bmap update succeeds or fails to + * support the BUI/BUD lifecycle rules. + */ +int +xfs_trans_log_finish_bmap_update( + struct xfs_trans *tp, + struct xfs_bud_log_item *budp, + struct xfs_defer_ops *dop, + enum xfs_bmap_intent_type type, + struct xfs_inode *ip, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state, + struct xfs_btree_cur **pcur) +{ + uint next_extent; + struct xfs_map_extent *bmap; + int error; + + error = -EFSCORRUPTED; + + /* + * Mark the transaction dirty, even on error. This ensures the + * transaction is aborted, which: + * + * 1.) releases the BUI and frees the BUD + * 2.) shuts down the filesystem + */ + tp->t_flags |= XFS_TRANS_DIRTY; + budp->bud_item.li_desc->lid_flags |= XFS_LID_DIRTY; + + next_extent = budp->bud_next_extent; + ASSERT(next_extent < budp->bud_format.bud_nextents); + bmap = &(budp->bud_format.bud_extents[next_extent]); + bmap->me_owner = ip->i_ino; + bmap->me_startblock = startblock; + bmap->me_startoff = startoff; + bmap->me_len = blockcount; + bmap->me_flags = 0; + if (state == XFS_EXT_UNWRITTEN) + bmap->me_flags |= XFS_BMAP_EXTENT_UNWRITTEN; + if (whichfork == XFS_ATTR_FORK) + bmap->me_flags |= XFS_BMAP_EXTENT_ATTR_FORK; + switch (type) { + case XFS_BMAP_MAP: + bmap->me_flags |= XFS_BMAP_EXTENT_MAP; + break; + case XFS_BMAP_UNMAP: + bmap->me_flags |= XFS_BMAP_EXTENT_UNMAP; + break; + default: + ASSERT(0); + } + budp->bud_next_extent++; + + return error; +} From darrick.wong@oracle.com Thu Jun 16 20:25:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9FD507E2D for ; Thu, 16 Jun 2016 20:25:42 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5DEA38F804C for ; Thu, 16 Jun 2016 18:25:42 -0700 (PDT) X-ASG-Debug-ID: 1466126739-04bdf01e1595b80001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 73oxhwZ9zOwxtuqg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1PbVk009823 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:37 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Pact017932 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:36 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1PZm0020422; Fri, 17 Jun 2016 01:25:35 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:35 -0700 Subject: [PATCH 072/119] xfs: implement deferred bmbt map/unmap operations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 072/119] xfs: implement deferred bmbt map/unmap operations To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:33 -0700 Message-ID: <146612673365.12839.17819633232208042020.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126739 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14386 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Implement deferred versions of the inode block map/unmap functions. These will be used in subsequent patches to make reflink operations atomic. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 124 +++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_bmap.h | 11 ++++ fs/xfs/libxfs/xfs_defer.h | 1 fs/xfs/xfs_defer_item.c | 113 +++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_error.h | 4 + fs/xfs/xfs_log_recover.c | 77 +++++++++++++++++++++++++++- fs/xfs/xfs_trace.h | 5 ++ fs/xfs/xfs_trans.h | 3 - fs/xfs/xfs_trans_bmap.c | 6 +- 9 files changed, 336 insertions(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index c29dcdb..63cfb1c 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -6127,3 +6127,127 @@ out: xfs_trans_cancel(tp); return error; } + +/* Record a bmap intent. */ +static int +__xfs_bmap_add( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_bmap_intent *bi) +{ + int error; + struct xfs_bmap_intent *new; + + ASSERT(bi->bi_whichfork == XFS_DATA_FORK); + + trace_xfs_bmap_defer(mp, XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock), + bi->bi_type, + XFS_FSB_TO_AGBNO(mp, bi->bi_bmap.br_startblock), + bi->bi_owner->i_ino, bi->bi_whichfork, + bi->bi_bmap.br_startoff, + bi->bi_bmap.br_blockcount, + bi->bi_bmap.br_state); + + new = kmem_zalloc(sizeof(struct xfs_bmap_intent), KM_SLEEP | KM_NOFS); + *new = *bi; + + error = xfs_defer_join(dfops, bi->bi_owner); + if (error) + return error; + + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &new->bi_list); + return 0; +} + +/* Map an extent into a file. */ +int +xfs_bmap_map_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_bmap_intent bi; + + bi.bi_type = XFS_BMAP_MAP; + bi.bi_owner = ip; + bi.bi_whichfork = whichfork; + bi.bi_bmap = *PREV; + + return __xfs_bmap_add(mp, dfops, &bi); +} + +/* Unmap an extent out of a file. */ +int +xfs_bmap_unmap_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_bmap_intent bi; + + bi.bi_type = XFS_BMAP_UNMAP; + bi.bi_owner = ip; + bi.bi_whichfork = whichfork; + bi.bi_bmap = *PREV; + + return __xfs_bmap_add(mp, dfops, &bi); +} + +/* + * Process one of the deferred bmap operations. We pass back the + * btree cursor to maintain our lock on the bmapbt between calls. + */ +int +xfs_bmap_finish_one( + struct xfs_trans *tp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + enum xfs_bmap_intent_type type, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state) +{ + struct xfs_bmbt_irec bmap; + int nimaps = 1; + xfs_fsblock_t firstfsb; + int error = 0; + + bmap.br_startblock = startblock; + bmap.br_startoff = startoff; + bmap.br_blockcount = blockcount; + bmap.br_state = state; + + trace_xfs_bmap_deferred(tp->t_mountp, + XFS_FSB_TO_AGNO(tp->t_mountp, startblock), type, + XFS_FSB_TO_AGBNO(tp->t_mountp, startblock), + ip->i_ino, whichfork, startoff, blockcount, state); + + if (XFS_TEST_ERROR(false, tp->t_mountp, + XFS_ERRTAG_BMAP_FINISH_ONE, + XFS_RANDOM_BMAP_FINISH_ONE)) + return -EIO; + + switch (type) { + case XFS_BMAP_MAP: + firstfsb = bmap.br_startblock; + error = xfs_bmapi_write(tp, ip, bmap.br_startoff, + bmap.br_blockcount, + XFS_BMAPI_REMAP, &firstfsb, + bmap.br_blockcount, &bmap, &nimaps, + dfops); + break; + case XFS_BMAP_UNMAP: + /* not implemented for now */ + default: + ASSERT(0); + error = -EFSCORRUPTED; + } + + return error; +} diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index fb2fd4c..394a22c 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -230,4 +230,15 @@ struct xfs_bmap_intent { struct xfs_bmbt_irec bi_bmap; }; +int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, enum xfs_bmap_intent_type type, + int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, + xfs_filblks_t blockcount, xfs_exntst_t state); +int xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); + #endif /* __XFS_BMAP_H__ */ diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index 4081b00..47aa048 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_BMAP, XFS_DEFER_OPS_TYPE_REFCOUNT, XFS_DEFER_OPS_TYPE_RMAP, XFS_DEFER_OPS_TYPE_FREE, diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c index 2cac94f..c9ebddc 100644 --- a/fs/xfs/xfs_defer_item.c +++ b/fs/xfs/xfs_defer_item.c @@ -35,6 +35,9 @@ #include "xfs_rmap_item.h" #include "xfs_refcount.h" #include "xfs_refcount_item.h" +#include "xfs_bmap.h" +#include "xfs_bmap_item.h" +#include "xfs_inode.h" /* Extent Freeing */ @@ -394,12 +397,122 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = { .cancel_item = xfs_refcount_update_cancel_item, }; +/* Inode Block Mapping */ + +/* Sort bmap intents by inode. */ +static int +xfs_bmap_update_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_bmap_intent *ba; + struct xfs_bmap_intent *bb; + + ba = container_of(a, struct xfs_bmap_intent, bi_list); + bb = container_of(b, struct xfs_bmap_intent, bi_list); + return ba->bi_owner->i_ino - bb->bi_owner->i_ino; +} + +/* Get an BUI. */ +STATIC void * +xfs_bmap_update_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return xfs_trans_get_bui(tp, count); +} + +/* Log bmap updates in the intent item. */ +STATIC void +xfs_bmap_update_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ + struct xfs_bmap_intent *bmap; + + bmap = container_of(item, struct xfs_bmap_intent, bi_list); + xfs_trans_log_start_bmap_update(tp, intent, bmap->bi_type, + bmap->bi_owner->i_ino, bmap->bi_whichfork, + bmap->bi_bmap.br_startoff, + bmap->bi_bmap.br_startblock, + bmap->bi_bmap.br_blockcount, + bmap->bi_bmap.br_state); +} + +/* Get an BUD so we can process all the deferred rmap updates. */ +STATIC void * +xfs_bmap_update_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return xfs_trans_get_bud(tp, intent, count); +} + +/* Process a deferred rmap update. */ +STATIC int +xfs_bmap_update_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + struct xfs_bmap_intent *bmap; + int error; + + bmap = container_of(item, struct xfs_bmap_intent, bi_list); + error = xfs_trans_log_finish_bmap_update(tp, done_item, dop, + bmap->bi_type, + bmap->bi_owner, bmap->bi_whichfork, + bmap->bi_bmap.br_startoff, + bmap->bi_bmap.br_startblock, + bmap->bi_bmap.br_blockcount, + bmap->bi_bmap.br_state); + kmem_free(bmap); + return error; +} + +/* Abort all pending BUIs. */ +STATIC void +xfs_bmap_update_abort_intent( + void *intent) +{ + xfs_bui_release(intent); +} + +/* Cancel a deferred rmap update. */ +STATIC void +xfs_bmap_update_cancel_item( + struct list_head *item) +{ + struct xfs_bmap_intent *bmap; + + bmap = container_of(item, struct xfs_bmap_intent, bi_list); + kmem_free(bmap); +} + +const struct xfs_defer_op_type xfs_bmap_update_defer_type = { + .type = XFS_DEFER_OPS_TYPE_BMAP, + .max_items = XFS_BUI_MAX_FAST_EXTENTS, + .diff_items = xfs_bmap_update_diff_items, + .create_intent = xfs_bmap_update_create_intent, + .abort_intent = xfs_bmap_update_abort_intent, + .log_item = xfs_bmap_update_log_item, + .create_done = xfs_bmap_update_create_done, + .finish_item = xfs_bmap_update_finish_item, + .cancel_item = xfs_bmap_update_cancel_item, +}; + /* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_bmap_update_defer_type); xfs_defer_init_op_type(&xfs_refcount_update_defer_type); xfs_defer_init_op_type(&xfs_rmap_update_defer_type); xfs_defer_init_op_type(&xfs_extent_free_defer_type); diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 83d7b62..16a60de 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -94,7 +94,8 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_ERRTAG_RMAP_FINISH_ONE 23 #define XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE 24 #define XFS_ERRTAG_REFCOUNT_FINISH_ONE 25 -#define XFS_ERRTAG_MAX 26 +#define XFS_ERRTAG_BMAP_FINISH_ONE 26 +#define XFS_ERRTAG_MAX 27 /* * Random factors for above tags, 1 means always, 2 means 1/2 time, etc. @@ -125,6 +126,7 @@ extern void xfs_verifier_error(struct xfs_buf *bp); #define XFS_RANDOM_RMAP_FINISH_ONE 1 #define XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE 1 #define XFS_RANDOM_REFCOUNT_FINISH_ONE 1 +#define XFS_RANDOM_BMAP_FINISH_ONE 1 #ifdef DEBUG extern int xfs_error_test_active; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 42000f4..3faaf10 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -5201,6 +5201,14 @@ xlog_recover_process_bui( xfs_fsblock_t startblock_fsb; xfs_fsblock_t inode_fsb; bool op_ok; + struct xfs_bud_log_item *budp; + enum xfs_bmap_intent_type type; + int whichfork; + xfs_exntst_t state; + struct xfs_trans *tp; + struct xfs_inode **ips; + struct xfs_defer_ops dfops; + xfs_fsblock_t firstfsb; ASSERT(!test_bit(XFS_BUI_RECOVERED, &buip->bui_flags)); @@ -5241,9 +5249,74 @@ xlog_recover_process_bui( } } - /* XXX: do nothing for now */ + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &tp); + if (error) + return error; + budp = xfs_trans_get_bud(tp, buip, buip->bui_format.bui_nextents); + + xfs_defer_init(&dfops, &firstfsb); + + /* Grab all the inodes we'll need. */ + ips = kmem_zalloc(sizeof(struct xfs_inode *) * + buip->bui_format.bui_nextents, KM_SLEEP); + for (i = 0; i < buip->bui_format.bui_nextents; i++) { + bmap = &(buip->bui_format.bui_extents[i]); + error = xfs_iget(mp, tp, bmap->me_owner, 0, XFS_ILOCK_EXCL, + &ips[i]); + if (error) + goto err_inodes; + } + + /* Process deferred bmap items. */ + for (i = 0; i < buip->bui_format.bui_nextents; i++) { + bmap = &(buip->bui_format.bui_extents[i]); + state = (bmap->me_flags & XFS_BMAP_EXTENT_UNWRITTEN) ? + XFS_EXT_UNWRITTEN : XFS_EXT_NORM; + whichfork = (bmap->me_flags & XFS_BMAP_EXTENT_ATTR_FORK) ? + XFS_ATTR_FORK : XFS_DATA_FORK; + switch (bmap->me_flags & XFS_BMAP_EXTENT_TYPE_MASK) { + case XFS_BMAP_EXTENT_MAP: + type = XFS_BMAP_MAP; + break; + case XFS_BMAP_EXTENT_UNMAP: + type = XFS_BMAP_UNMAP; + break; + default: + error = -EFSCORRUPTED; + goto err_dfops; + } + xfs_trans_ijoin(tp, ips[i], 0); + + error = xfs_trans_log_finish_bmap_update(tp, budp, &dfops, type, + ips[i], whichfork, bmap->me_startoff, + bmap->me_startblock, bmap->me_len, + state); + if (error) + goto err_dfops; + + } + + /* Finish transaction, free inodes. */ + error = xfs_defer_finish(&tp, &dfops, NULL); + if (error) + goto err_dfops; set_bit(XFS_BUI_RECOVERED, &buip->bui_flags); - xfs_bui_release(buip); + error = xfs_trans_commit(tp); + for (i = 0; i < buip->bui_format.bui_nextents; i++) { + xfs_iunlock(ips[i], XFS_ILOCK_EXCL); + IRELE(ips[i]); + } + + return error; + +err_dfops: + xfs_defer_cancel(&dfops); +err_inodes: + for (i = 0; i < buip->bui_format.bui_nextents; i++) { + xfs_iunlock(ips[i], XFS_ILOCK_EXCL); + IRELE(ips[i]); + } + xfs_trans_cancel(tp); return error; } diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 8844c9f..a18e321 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2560,6 +2560,11 @@ DEFINE_RMAPBT_EVENT(xfs_rmap_map_gtrec); DEFINE_RMAPBT_EVENT(xfs_rmap_convert_gtrec); DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result); +/* deferred bmbt updates */ +#define DEFINE_BMAP_DEFERRED_EVENT DEFINE_RMAP_DEFERRED_EVENT +DEFINE_BMAP_DEFERRED_EVENT(xfs_bmap_defer); +DEFINE_BMAP_DEFERRED_EVENT(xfs_bmap_deferred); + /* per-AG reservation */ DECLARE_EVENT_CLASS(xfs_ag_resv_class, TP_PROTO(struct xfs_perag *pag, enum xfs_ag_resv_type resv, diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index cda7d92..6e890bc 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h @@ -285,7 +285,6 @@ int xfs_trans_log_finish_bmap_update(struct xfs_trans *tp, struct xfs_bud_log_item *rudp, struct xfs_defer_ops *dfops, enum xfs_bmap_intent_type type, struct xfs_inode *ip, int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, - xfs_filblks_t blockcount, xfs_exntst_t state, - struct xfs_btree_cur **pcur); + xfs_filblks_t blockcount, xfs_exntst_t state); #endif /* __XFS_TRANS_H__ */ diff --git a/fs/xfs/xfs_trans_bmap.c b/fs/xfs/xfs_trans_bmap.c index 1517c83..97f395a 100644 --- a/fs/xfs/xfs_trans_bmap.c +++ b/fs/xfs/xfs_trans_bmap.c @@ -154,14 +154,14 @@ xfs_trans_log_finish_bmap_update( xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, - xfs_exntst_t state, - struct xfs_btree_cur **pcur) + xfs_exntst_t state) { uint next_extent; struct xfs_map_extent *bmap; int error; - error = -EFSCORRUPTED; + error = xfs_bmap_finish_one(tp, dop, ip, type, whichfork, startoff, + startblock, blockcount, state); /* * Mark the transaction dirty, even on error. This ensures the From darrick.wong@oracle.com Thu Jun 16 20:25:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D53A17E6F for ; Thu, 16 Jun 2016 20:25:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id A2E498F8050 for ; Thu, 16 Jun 2016 18:25:46 -0700 (PDT) X-ASG-Debug-ID: 1466126744-04cb6c5425578b0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 8GxTmDhBd27BSecb (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:45 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1PgKM009869 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:42 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1PgJw018091 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:42 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1PfWs024881; Fri, 17 Jun 2016 01:25:42 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:41 -0700 Subject: [PATCH 073/119] xfs: return work remaining at the end of a bunmapi operation From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 073/119] xfs: return work remaining at the end of a bunmapi operation To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:40 -0700 Message-ID: <146612674005.12839.11363895165190702626.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126744 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3601 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Return the range of file blocks that bunmapi didn't free. This hint is used by CoW and reflink to figure out what part of an extent actually got freed so that it can set up the appropriate atomic remapping of just the freed range. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 36 ++++++++++++++++++++++++++++++------ fs/xfs/libxfs/xfs_bmap.h | 4 ++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 63cfb1c..5af4593 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5165,17 +5165,16 @@ done: * *done is set. */ int /* error */ -xfs_bunmapi( +__xfs_bunmapi( xfs_trans_t *tp, /* transaction pointer */ struct xfs_inode *ip, /* incore inode */ xfs_fileoff_t bno, /* starting offset to unmap */ - xfs_filblks_t len, /* length to unmap in file */ + xfs_filblks_t *rlen, /* i/o: amount remaining */ int flags, /* misc flags */ xfs_extnum_t nexts, /* number of extents max */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ - struct xfs_defer_ops *dfops, /* i/o: list extents to free */ - int *done) /* set if not done yet */ + struct xfs_defer_ops *dfops) /* i/o: deferred updates */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ xfs_bmbt_irec_t del; /* extent being deleted */ @@ -5197,6 +5196,7 @@ xfs_bunmapi( int wasdel; /* was a delayed alloc extent */ int whichfork; /* data or attribute fork */ xfs_fsblock_t sum; + xfs_filblks_t len = *rlen; /* length to unmap in file */ trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); @@ -5223,7 +5223,7 @@ xfs_bunmapi( return error; nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); if (nextents == 0) { - *done = 1; + *rlen = 0; return 0; } XFS_STATS_INC(mp, xs_blk_unmap); @@ -5492,7 +5492,10 @@ nodelete: extno++; } } - *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0; + if (bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0) + *rlen = 0; + else + *rlen = bno - start + 1; /* * Convert to a btree if necessary. @@ -5548,6 +5551,27 @@ error0: return error; } +/* Unmap a range of a file. */ +int +xfs_bunmapi( + xfs_trans_t *tp, + struct xfs_inode *ip, + xfs_fileoff_t bno, + xfs_filblks_t len, + int flags, + xfs_extnum_t nexts, + xfs_fsblock_t *firstblock, + struct xfs_defer_ops *dfops, + int *done) +{ + int error; + + error = __xfs_bunmapi(tp, ip, bno, &len, flags, nexts, firstblock, + dfops); + *done = (len == 0); + return error; +} + /* * Determine whether an extent shift can be accomplished by a merge with the * extent that precedes the target hole of the shift. diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 394a22c..97828c5 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -197,6 +197,10 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fsblock_t *firstblock, xfs_extlen_t total, struct xfs_bmbt_irec *mval, int *nmap, struct xfs_defer_ops *dfops); +int __xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, + xfs_fileoff_t bno, xfs_filblks_t *rlen, int flags, + xfs_extnum_t nexts, xfs_fsblock_t *firstblock, + struct xfs_defer_ops *dfops); int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, From darrick.wong@oracle.com Thu Jun 16 20:25:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1BFB47E64 for ; Thu, 16 Jun 2016 20:25:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 859B2AC001 for ; Thu, 16 Jun 2016 18:25:54 -0700 (PDT) X-ASG-Debug-ID: 1466126751-04cbb01fec69840001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id xzP3n8Mw83reLmMU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:51 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Pnfn029169 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:49 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Pm5L022679 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:49 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Pmwt024890; Fri, 17 Jun 2016 01:25:48 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:47 -0700 Subject: [PATCH 074/119] xfs: define tracepoints for reflink activities From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 074/119] xfs: define tracepoints for reflink activities To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:46 -0700 Message-ID: <146612674632.12839.17197563754649199978.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126751 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11846 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Define all the tracepoints we need to inspect the runtime operation of reflink/dedupe/copy-on-write. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_trace.h | 333 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index a18e321..fe9c6f8 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2998,6 +2998,339 @@ TRACE_EVENT(xfs_bmap_remap_alloc, ); DEFINE_INODE_ERROR_EVENT(xfs_bmap_remap_alloc_error); +/* reflink tracepoint classes */ + +/* two-file io tracepoint class */ +DECLARE_EVENT_CLASS(xfs_double_io_class, + TP_PROTO(struct xfs_inode *src, xfs_off_t soffset, xfs_off_t len, + struct xfs_inode *dest, xfs_off_t doffset), + TP_ARGS(src, soffset, len, dest, doffset), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, src_ino) + __field(loff_t, src_isize) + __field(loff_t, src_disize) + __field(loff_t, src_offset) + __field(size_t, len) + __field(xfs_ino_t, dest_ino) + __field(loff_t, dest_isize) + __field(loff_t, dest_disize) + __field(loff_t, dest_offset) + ), + TP_fast_assign( + __entry->dev = VFS_I(src)->i_sb->s_dev; + __entry->src_ino = src->i_ino; + __entry->src_isize = VFS_I(src)->i_size; + __entry->src_disize = src->i_d.di_size; + __entry->src_offset = soffset; + __entry->len = len; + __entry->dest_ino = dest->i_ino; + __entry->dest_isize = VFS_I(dest)->i_size; + __entry->dest_disize = dest->i_d.di_size; + __entry->dest_offset = doffset; + ), + TP_printk("dev %d:%d count %zd " + "ino 0x%llx isize 0x%llx disize 0x%llx offset 0x%llx -> " + "ino 0x%llx isize 0x%llx disize 0x%llx offset 0x%llx", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->len, + __entry->src_ino, + __entry->src_isize, + __entry->src_disize, + __entry->src_offset, + __entry->dest_ino, + __entry->dest_isize, + __entry->dest_disize, + __entry->dest_offset) +) + +#define DEFINE_DOUBLE_IO_EVENT(name) \ +DEFINE_EVENT(xfs_double_io_class, name, \ + TP_PROTO(struct xfs_inode *src, xfs_off_t soffset, xfs_off_t len, \ + struct xfs_inode *dest, xfs_off_t doffset), \ + TP_ARGS(src, soffset, len, dest, doffset)) + +/* two-file vfs io tracepoint class */ +DECLARE_EVENT_CLASS(xfs_double_vfs_io_class, + TP_PROTO(struct inode *src, u64 soffset, u64 len, + struct inode *dest, u64 doffset), + TP_ARGS(src, soffset, len, dest, doffset), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(unsigned long, src_ino) + __field(loff_t, src_isize) + __field(loff_t, src_offset) + __field(size_t, len) + __field(unsigned long, dest_ino) + __field(loff_t, dest_isize) + __field(loff_t, dest_offset) + ), + TP_fast_assign( + __entry->dev = src->i_sb->s_dev; + __entry->src_ino = src->i_ino; + __entry->src_isize = i_size_read(src); + __entry->src_offset = soffset; + __entry->len = len; + __entry->dest_ino = dest->i_ino; + __entry->dest_isize = i_size_read(dest); + __entry->dest_offset = doffset; + ), + TP_printk("dev %d:%d count %zd " + "ino 0x%lx isize 0x%llx offset 0x%llx -> " + "ino 0x%lx isize 0x%llx offset 0x%llx", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->len, + __entry->src_ino, + __entry->src_isize, + __entry->src_offset, + __entry->dest_ino, + __entry->dest_isize, + __entry->dest_offset) +) + +#define DEFINE_DOUBLE_VFS_IO_EVENT(name) \ +DEFINE_EVENT(xfs_double_vfs_io_class, name, \ + TP_PROTO(struct inode *src, u64 soffset, u64 len, \ + struct inode *dest, u64 doffset), \ + TP_ARGS(src, soffset, len, dest, doffset)) + +/* CoW write tracepoint */ +DECLARE_EVENT_CLASS(xfs_copy_on_write_class, + TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk, xfs_fsblock_t pblk, + xfs_extlen_t len, xfs_fsblock_t new_pblk), + TP_ARGS(ip, lblk, pblk, len, new_pblk), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(xfs_fileoff_t, lblk) + __field(xfs_fsblock_t, pblk) + __field(xfs_extlen_t, len) + __field(xfs_fsblock_t, new_pblk) + ), + TP_fast_assign( + __entry->dev = VFS_I(ip)->i_sb->s_dev; + __entry->ino = ip->i_ino; + __entry->lblk = lblk; + __entry->pblk = pblk; + __entry->len = len; + __entry->new_pblk = new_pblk; + ), + TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx pblk 0x%llx " + "len 0x%x new_pblk %llu", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->lblk, + __entry->pblk, + __entry->len, + __entry->new_pblk) +) + +#define DEFINE_COW_EVENT(name) \ +DEFINE_EVENT(xfs_copy_on_write_class, name, \ + TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk, xfs_fsblock_t pblk, \ + xfs_extlen_t len, xfs_fsblock_t new_pblk), \ + TP_ARGS(ip, lblk, pblk, len, new_pblk)) + +/* inode/irec events */ +DECLARE_EVENT_CLASS(xfs_inode_irec_class, + TP_PROTO(struct xfs_inode *ip, struct xfs_bmbt_irec *irec), + TP_ARGS(ip, irec), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(xfs_fileoff_t, lblk) + __field(xfs_extlen_t, len) + __field(xfs_fsblock_t, pblk) + ), + TP_fast_assign( + __entry->dev = VFS_I(ip)->i_sb->s_dev; + __entry->ino = ip->i_ino; + __entry->lblk = irec->br_startoff; + __entry->len = irec->br_blockcount; + __entry->pblk = irec->br_startblock; + ), + TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx len 0x%x pblk %llu", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->lblk, + __entry->len, + __entry->pblk) +); +#define DEFINE_INODE_IREC_EVENT(name) \ +DEFINE_EVENT(xfs_inode_irec_class, name, \ + TP_PROTO(struct xfs_inode *ip, struct xfs_bmbt_irec *irec), \ + TP_ARGS(ip, irec)) + +/* refcount/reflink tracepoint definitions */ + +/* reflink tracepoints */ +DEFINE_INODE_EVENT(xfs_reflink_set_inode_flag); +DEFINE_INODE_EVENT(xfs_reflink_unset_inode_flag); +DEFINE_ITRUNC_EVENT(xfs_reflink_update_inode_size); +DEFINE_IOMAP_EVENT(xfs_reflink_remap_imap); +TRACE_EVENT(xfs_reflink_remap_blocks_loop, + TP_PROTO(struct xfs_inode *src, xfs_fileoff_t soffset, + xfs_filblks_t len, struct xfs_inode *dest, + xfs_fileoff_t doffset), + TP_ARGS(src, soffset, len, dest, doffset), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, src_ino) + __field(xfs_fileoff_t, src_lblk) + __field(xfs_filblks_t, len) + __field(xfs_ino_t, dest_ino) + __field(xfs_fileoff_t, dest_lblk) + ), + TP_fast_assign( + __entry->dev = VFS_I(src)->i_sb->s_dev; + __entry->src_ino = src->i_ino; + __entry->src_lblk = soffset; + __entry->len = len; + __entry->dest_ino = dest->i_ino; + __entry->dest_lblk = doffset; + ), + TP_printk("dev %d:%d len 0x%llx " + "ino 0x%llx offset 0x%llx blocks -> " + "ino 0x%llx offset 0x%llx blocks", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->len, + __entry->src_ino, + __entry->src_lblk, + __entry->dest_ino, + __entry->dest_lblk) +); +TRACE_EVENT(xfs_reflink_punch_range, + TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk, + xfs_extlen_t len), + TP_ARGS(ip, lblk, len), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(xfs_fileoff_t, lblk) + __field(xfs_extlen_t, len) + ), + TP_fast_assign( + __entry->dev = VFS_I(ip)->i_sb->s_dev; + __entry->ino = ip->i_ino; + __entry->lblk = lblk; + __entry->len = len; + ), + TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx len 0x%x", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->lblk, + __entry->len) +); +TRACE_EVENT(xfs_reflink_remap, + TP_PROTO(struct xfs_inode *ip, xfs_fileoff_t lblk, + xfs_extlen_t len, xfs_fsblock_t new_pblk), + TP_ARGS(ip, lblk, len, new_pblk), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_ino_t, ino) + __field(xfs_fileoff_t, lblk) + __field(xfs_extlen_t, len) + __field(xfs_fsblock_t, new_pblk) + ), + TP_fast_assign( + __entry->dev = VFS_I(ip)->i_sb->s_dev; + __entry->ino = ip->i_ino; + __entry->lblk = lblk; + __entry->len = len; + __entry->new_pblk = new_pblk; + ), + TP_printk("dev %d:%d ino 0x%llx lblk 0x%llx len 0x%x new_pblk %llu", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->ino, + __entry->lblk, + __entry->len, + __entry->new_pblk) +); +DEFINE_DOUBLE_IO_EVENT(xfs_reflink_remap_range); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_remap_range_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_set_inode_flag_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_update_inode_size_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_reflink_main_loop_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_read_iomap_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_remap_blocks_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_remap_extent_error); + +/* dedupe tracepoints */ +DEFINE_DOUBLE_IO_EVENT(xfs_reflink_compare_extents); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_compare_extents_error); + +/* ioctl tracepoints */ +DEFINE_DOUBLE_VFS_IO_EVENT(xfs_ioctl_reflink); +DEFINE_DOUBLE_VFS_IO_EVENT(xfs_ioctl_clone_range); +DEFINE_DOUBLE_VFS_IO_EVENT(xfs_ioctl_file_extent_same); +TRACE_EVENT(xfs_ioctl_clone, + TP_PROTO(struct inode *src, struct inode *dest), + TP_ARGS(src, dest), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(unsigned long, src_ino) + __field(loff_t, src_isize) + __field(unsigned long, dest_ino) + __field(loff_t, dest_isize) + ), + TP_fast_assign( + __entry->dev = src->i_sb->s_dev; + __entry->src_ino = src->i_ino; + __entry->src_isize = i_size_read(src); + __entry->dest_ino = dest->i_ino; + __entry->dest_isize = i_size_read(dest); + ), + TP_printk("dev %d:%d " + "ino 0x%lx isize 0x%llx -> " + "ino 0x%lx isize 0x%llx\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->src_ino, + __entry->src_isize, + __entry->dest_ino, + __entry->dest_isize) +); + +/* unshare tracepoints */ +DEFINE_SIMPLE_IO_EVENT(xfs_reflink_unshare); +DEFINE_SIMPLE_IO_EVENT(xfs_reflink_cow_eof_block); +DEFINE_PAGE_EVENT(xfs_reflink_unshare_page); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_unshare_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_cow_eof_block_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_dirty_page_error); + +/* copy on write */ +DEFINE_INODE_IREC_EVENT(xfs_reflink_irec_is_shared); + +DEFINE_RW_EVENT(xfs_reflink_reserve_cow_range); +DEFINE_INODE_IREC_EVENT(xfs_reflink_reserve_cow_extent); +DEFINE_RW_EVENT(xfs_reflink_allocate_cow_range); +DEFINE_INODE_IREC_EVENT(xfs_reflink_allocate_cow_extent); + +DEFINE_INODE_IREC_EVENT(xfs_reflink_bounce_dio_write); +DEFINE_IOMAP_EVENT(xfs_reflink_find_cow_mapping); +DEFINE_INODE_IREC_EVENT(xfs_reflink_trim_irec); +DEFINE_SIMPLE_IO_EVENT(xfs_iomap_cow_delay); + +DEFINE_SIMPLE_IO_EVENT(xfs_reflink_cancel_cow_range); +DEFINE_SIMPLE_IO_EVENT(xfs_reflink_end_cow); +DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_remap); +DEFINE_INODE_IREC_EVENT(xfs_reflink_cow_remap_piece); + +DEFINE_INODE_ERROR_EVENT(xfs_reflink_reserve_cow_range_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_reserve_cow_extent_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_allocate_cow_range_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_cancel_cow_range_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_end_cow_error); + +DEFINE_COW_EVENT(xfs_reflink_fork_buf); +DEFINE_COW_EVENT(xfs_reflink_finish_fork_buf); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_fork_buf_error); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_finish_fork_buf_error); + +DEFINE_INODE_EVENT(xfs_reflink_cancel_pending_cow); +DEFINE_INODE_IREC_EVENT(xfs_reflink_cancel_cow); +DEFINE_INODE_ERROR_EVENT(xfs_reflink_cancel_pending_cow_error); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:25:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8D1837E7C for ; Thu, 16 Jun 2016 20:25:59 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5C11D8F804C for ; Thu, 16 Jun 2016 18:25:59 -0700 (PDT) X-ASG-Debug-ID: 1466126757-04cbb01fef69870001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id dYRKAJ4fF6hENA7u (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:25:58 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1PtA3009923 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:56 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1PtA7022772 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:25:55 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Pswd024899; Fri, 17 Jun 2016 01:25:54 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:25:54 -0700 Subject: [PATCH 075/119] xfs: add reflink feature flag to geometry From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 075/119] xfs: add reflink feature flag to geometry To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:52 -0700 Message-ID: <146612675269.12839.6729634542114964609.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126757 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1638 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Report the reflink feature in the XFS geometry so that xfs_info and friends know the filesystem has this feature. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 3 ++- fs/xfs/xfs_fsops.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 7945505..6f4f2c3 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -206,7 +206,8 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */ -#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* Reverse mapping btree */ +#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */ +#define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */ /* * Minimum and maximum sizes need for growth checks. diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 3c1ded1..84e7ba3 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -107,7 +107,9 @@ xfs_fs_geometry( (xfs_sb_version_hassparseinodes(&mp->m_sb) ? XFS_FSOP_GEOM_FLAGS_SPINODES : 0) | (xfs_sb_version_hasrmapbt(&mp->m_sb) ? - XFS_FSOP_GEOM_FLAGS_RMAPBT : 0); + XFS_FSOP_GEOM_FLAGS_RMAPBT : 0) | + (xfs_sb_version_hasreflink(&mp->m_sb) ? + XFS_FSOP_GEOM_FLAGS_REFLINK : 0); geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? mp->m_sb.sb_logsectsize : BBSIZE; geo->rtsectsize = mp->m_sb.sb_blocksize; From darrick.wong@oracle.com Thu Jun 16 20:26:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 171647E64 for ; Thu, 16 Jun 2016 20:26:06 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id BC7BD304048 for ; Thu, 16 Jun 2016 18:26:05 -0700 (PDT) X-ASG-Debug-ID: 1466126763-04bdf01e1795bc0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id r9HBTDyRdw3bwoTh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Q10T010214 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:02 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Q1KH022964 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:01 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Q0bK024916; Fri, 17 Jun 2016 01:26:00 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:00 -0700 Subject: [PATCH 076/119] xfs: don't allow reflinked dir/dev/fifo/socket/pipe files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 076/119] xfs: don't allow reflinked dir/dev/fifo/socket/pipe files To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:25:59 -0700 Message-ID: <146612675894.12839.15938070770878804836.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126764 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1586 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Only non-rt files can be reflinked, so check that when we load an inode. Also, don't leak the attr fork if there's a failure. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_fork.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index bbcc8c7..7699a03 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -121,6 +121,26 @@ xfs_iformat_fork( return -EFSCORRUPTED; } + if (unlikely(xfs_is_reflink_inode(ip) && + (VFS_I(ip)->i_mode & S_IFMT) != S_IFREG)) { + xfs_warn(ip->i_mount, + "corrupt dinode %llu, wrong file type for reflink.", + ip->i_ino); + XFS_CORRUPTION_ERROR("xfs_iformat(reflink)", + XFS_ERRLEVEL_LOW, ip->i_mount, dip); + return -EFSCORRUPTED; + } + + if (unlikely(xfs_is_reflink_inode(ip) && + (ip->i_d.di_flags & XFS_DIFLAG_REALTIME))) { + xfs_warn(ip->i_mount, + "corrupt dinode %llu, has reflink+realtime flag set.", + ip->i_ino); + XFS_CORRUPTION_ERROR("xfs_iformat(reflink)", + XFS_ERRLEVEL_LOW, ip->i_mount, dip); + return -EFSCORRUPTED; + } + switch (VFS_I(ip)->i_mode & S_IFMT) { case S_IFIFO: case S_IFCHR: @@ -208,7 +228,8 @@ xfs_iformat_fork( XFS_CORRUPTION_ERROR("xfs_iformat(8)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); - return -EFSCORRUPTED; + error = -EFSCORRUPTED; + break; } error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size); From darrick.wong@oracle.com Thu Jun 16 20:26:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 189037CB4 for ; Thu, 16 Jun 2016 20:26:14 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id D98618F804B for ; Thu, 16 Jun 2016 18:26:13 -0700 (PDT) X-ASG-Debug-ID: 1466126770-04cb6c542757910001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id J945RLpHwE4OG6E3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Q7cU010308 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:26:07 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Q7Lc017301 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:26:07 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Q7au029200; Fri, 17 Jun 2016 01:26:07 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:06 -0700 Subject: [PATCH 077/119] xfs: introduce the CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 077/119] xfs: introduce the CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:05 -0700 Message-ID: <146612676517.12839.5004444315047596126.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126770 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 20463 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Introduce a new in-core fork for storing copy-on-write delalloc reservations and allocated extents that are in the process of being written out. v2: fix up bmapi_read so that we can query the CoW fork, and have it return a "hole" extent if there's no CoW fork. Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_bmap.c | 27 +++++++-- fs/xfs/libxfs/xfs_bmap.h | 22 +++++++- fs/xfs/libxfs/xfs_bmap_btree.c | 1 fs/xfs/libxfs/xfs_inode_fork.c | 47 +++++++++++++++- fs/xfs/libxfs/xfs_inode_fork.h | 28 ++++++++-- fs/xfs/libxfs/xfs_rmap.c | 2 + fs/xfs/libxfs/xfs_types.h | 1 fs/xfs/xfs_icache.c | 5 ++ fs/xfs/xfs_inode.h | 4 + fs/xfs/xfs_reflink.c | 114 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 23 ++++++++ fs/xfs/xfs_trace.h | 4 + 13 files changed, 258 insertions(+), 21 deletions(-) create mode 100644 fs/xfs/xfs_reflink.c create mode 100644 fs/xfs/xfs_reflink.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 941afe6..56c384b 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -91,6 +91,7 @@ xfs-y += xfs_aops.o \ xfs_message.o \ xfs_mount.o \ xfs_mru_cache.o \ + xfs_reflink.o \ xfs_stats.o \ xfs_super.o \ xfs_symlink.o \ diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 5af4593..ccfaf60 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -2924,6 +2924,7 @@ xfs_bmap_add_extent_hole_real( ASSERT(!isnullstartblock(new->br_startblock)); ASSERT(!bma->cur || !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); + ASSERT(whichfork != XFS_COW_FORK); XFS_STATS_INC(mp, xs_add_exlist); @@ -4058,12 +4059,11 @@ xfs_bmapi_read( int error; int eof; int n = 0; - int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + int whichfork = xfs_bmapi_whichfork(flags); ASSERT(*nmap >= 1); ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE| - XFS_BMAPI_IGSTATE))); + XFS_BMAPI_IGSTATE|XFS_BMAPI_COWFORK))); ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)); if (unlikely(XFS_TEST_ERROR( @@ -4081,6 +4081,16 @@ xfs_bmapi_read( ifp = XFS_IFORK_PTR(ip, whichfork); + /* No CoW fork? Return a hole. */ + if (whichfork == XFS_COW_FORK && !ifp) { + mval->br_startoff = bno; + mval->br_startblock = HOLESTARTBLOCK; + mval->br_blockcount = len; + mval->br_state = XFS_EXT_NORM; + *nmap = 1; + return 0; + } + if (!(ifp->if_flags & XFS_IFEXTENTS)) { error = xfs_iread_extents(NULL, ip, whichfork); if (error) @@ -4433,8 +4443,7 @@ xfs_bmapi_convert_unwritten( xfs_filblks_t len, int flags) { - int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + int whichfork = xfs_bmapi_whichfork(flags); struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); int tmp_logflags = 0; int error; @@ -4450,6 +4459,8 @@ xfs_bmapi_convert_unwritten( (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) return 0; + ASSERT(whichfork != XFS_COW_FORK); + /* * Modify (by adding) the state flag, if writing. */ @@ -4862,6 +4873,8 @@ xfs_bmap_del_extent( if (whichfork == XFS_ATTR_FORK) state |= BMAP_ATTRFORK; + else if (whichfork == XFS_COW_FORK) + state |= BMAP_COWFORK; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT((*idx >= 0) && (*idx < ifp->if_bytes / @@ -5200,8 +5213,8 @@ __xfs_bunmapi( trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); - whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + whichfork = xfs_bmapi_whichfork(flags); + ASSERT(whichfork != XFS_COW_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); if (unlikely( XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index 97828c5..a8ef1c6 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -104,6 +104,9 @@ struct xfs_bmap_free_item */ #define XFS_BMAPI_REMAP 0x100 +/* Map something in the CoW fork. */ +#define XFS_BMAPI_COWFORK 0x200 + #define XFS_BMAPI_FLAGS \ { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ { XFS_BMAPI_METADATA, "METADATA" }, \ @@ -113,12 +116,23 @@ struct xfs_bmap_free_item { XFS_BMAPI_CONTIG, "CONTIG" }, \ { XFS_BMAPI_CONVERT, "CONVERT" }, \ { XFS_BMAPI_ZERO, "ZERO" }, \ - { XFS_BMAPI_REMAP, "REMAP" } + { XFS_BMAPI_REMAP, "REMAP" }, \ + { XFS_BMAPI_COWFORK, "COWFORK" } static inline int xfs_bmapi_aflag(int w) { - return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : 0); + return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : + (w == XFS_COW_FORK ? XFS_BMAPI_COWFORK : 0)); +} + +static inline int xfs_bmapi_whichfork(int bmapi_flags) +{ + if (bmapi_flags & XFS_BMAPI_COWFORK) + return XFS_COW_FORK; + else if (bmapi_flags & XFS_BMAPI_ATTRFORK) + return XFS_ATTR_FORK; + return XFS_DATA_FORK; } /* @@ -139,13 +153,15 @@ static inline int xfs_bmapi_aflag(int w) #define BMAP_LEFT_VALID (1 << 6) #define BMAP_RIGHT_VALID (1 << 7) #define BMAP_ATTRFORK (1 << 8) +#define BMAP_COWFORK (1 << 9) #define XFS_BMAP_EXT_FLAGS \ { BMAP_LEFT_CONTIG, "LC" }, \ { BMAP_RIGHT_CONTIG, "RC" }, \ { BMAP_LEFT_FILLING, "LF" }, \ { BMAP_RIGHT_FILLING, "RF" }, \ - { BMAP_ATTRFORK, "ATTR" } + { BMAP_ATTRFORK, "ATTR" }, \ + { BMAP_COWFORK, "COW" } /* diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 3e68f9a..a5a8d37 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -776,6 +776,7 @@ xfs_bmbt_init_cursor( { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_btree_cur *cur; + ASSERT(whichfork != XFS_COW_FORK); cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 7699a03..d29954a 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -206,9 +206,14 @@ xfs_iformat_fork( XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW, ip->i_mount); return -EFSCORRUPTED; } - if (error) { + if (error) return error; + + if (xfs_is_reflink_inode(ip)) { + ASSERT(ip->i_cowfp == NULL); + xfs_ifork_init_cow(ip); } + if (!XFS_DFORK_Q(dip)) return 0; @@ -247,6 +252,9 @@ xfs_iformat_fork( if (error) { kmem_zone_free(xfs_ifork_zone, ip->i_afp); ip->i_afp = NULL; + if (ip->i_cowfp) + kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); + ip->i_cowfp = NULL; xfs_idestroy_fork(ip, XFS_DATA_FORK); } return error; @@ -761,6 +769,9 @@ xfs_idestroy_fork( if (whichfork == XFS_ATTR_FORK) { kmem_zone_free(xfs_ifork_zone, ip->i_afp); ip->i_afp = NULL; + } else if (whichfork == XFS_COW_FORK) { + kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); + ip->i_cowfp = NULL; } } @@ -948,6 +959,19 @@ xfs_iext_get_ext( } } +/* XFS_IEXT_STATE_TO_FORK() -- Convert BMAP state flags to an inode fork. */ +xfs_ifork_t * +XFS_IEXT_STATE_TO_FORK( + struct xfs_inode *ip, + int state) +{ + if (state & BMAP_COWFORK) + return ip->i_cowfp; + else if (state & BMAP_ATTRFORK) + return ip->i_afp; + return &ip->i_df; +} + /* * Insert new item(s) into the extent records for incore inode * fork 'ifp'. 'count' new items are inserted at index 'idx'. @@ -960,7 +984,7 @@ xfs_iext_insert( xfs_bmbt_irec_t *new, /* items to insert */ int state) /* type of extent conversion */ { - xfs_ifork_t *ifp = (state & BMAP_ATTRFORK) ? ip->i_afp : &ip->i_df; + xfs_ifork_t *ifp = XFS_IEXT_STATE_TO_FORK(ip, state); xfs_extnum_t i; /* extent record index */ trace_xfs_iext_insert(ip, idx, new, state, _RET_IP_); @@ -1210,7 +1234,7 @@ xfs_iext_remove( int ext_diff, /* number of extents to remove */ int state) /* type of extent conversion */ { - xfs_ifork_t *ifp = (state & BMAP_ATTRFORK) ? ip->i_afp : &ip->i_df; + xfs_ifork_t *ifp = XFS_IEXT_STATE_TO_FORK(ip, state); xfs_extnum_t nextents; /* number of extents in file */ int new_size; /* size of extents after removal */ @@ -1955,3 +1979,20 @@ xfs_iext_irec_update_extoffs( ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff; } } + +/* + * Initialize an inode's copy-on-write fork. + */ +void +xfs_ifork_init_cow( + struct xfs_inode *ip) +{ + if (ip->i_cowfp) + return; + + ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone, + KM_SLEEP | KM_NOFS); + ip->i_cowfp->if_flags = XFS_IFEXTENTS; + ip->i_cformat = XFS_DINODE_FMT_EXTENTS; + ip->i_cnextents = 0; +} diff --git a/fs/xfs/libxfs/xfs_inode_fork.h b/fs/xfs/libxfs/xfs_inode_fork.h index f95e072..44d38eb 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.h +++ b/fs/xfs/libxfs/xfs_inode_fork.h @@ -92,7 +92,9 @@ typedef struct xfs_ifork { #define XFS_IFORK_PTR(ip,w) \ ((w) == XFS_DATA_FORK ? \ &(ip)->i_df : \ - (ip)->i_afp) + ((w) == XFS_ATTR_FORK ? \ + (ip)->i_afp : \ + (ip)->i_cowfp)) #define XFS_IFORK_DSIZE(ip) \ (XFS_IFORK_Q(ip) ? \ XFS_IFORK_BOFF(ip) : \ @@ -105,26 +107,38 @@ typedef struct xfs_ifork { #define XFS_IFORK_SIZE(ip,w) \ ((w) == XFS_DATA_FORK ? \ XFS_IFORK_DSIZE(ip) : \ - XFS_IFORK_ASIZE(ip)) + ((w) == XFS_ATTR_FORK ? \ + XFS_IFORK_ASIZE(ip) : \ + 0)) #define XFS_IFORK_FORMAT(ip,w) \ ((w) == XFS_DATA_FORK ? \ (ip)->i_d.di_format : \ - (ip)->i_d.di_aformat) + ((w) == XFS_ATTR_FORK ? \ + (ip)->i_d.di_aformat : \ + (ip)->i_cformat)) #define XFS_IFORK_FMT_SET(ip,w,n) \ ((w) == XFS_DATA_FORK ? \ ((ip)->i_d.di_format = (n)) : \ - ((ip)->i_d.di_aformat = (n))) + ((w) == XFS_ATTR_FORK ? \ + ((ip)->i_d.di_aformat = (n)) : \ + ((ip)->i_cformat = (n)))) #define XFS_IFORK_NEXTENTS(ip,w) \ ((w) == XFS_DATA_FORK ? \ (ip)->i_d.di_nextents : \ - (ip)->i_d.di_anextents) + ((w) == XFS_ATTR_FORK ? \ + (ip)->i_d.di_anextents : \ + (ip)->i_cnextents)) #define XFS_IFORK_NEXT_SET(ip,w,n) \ ((w) == XFS_DATA_FORK ? \ ((ip)->i_d.di_nextents = (n)) : \ - ((ip)->i_d.di_anextents = (n))) + ((w) == XFS_ATTR_FORK ? \ + ((ip)->i_d.di_anextents = (n)) : \ + ((ip)->i_cnextents = (n)))) #define XFS_IFORK_MAXEXT(ip, w) \ (XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t)) +xfs_ifork_t *XFS_IEXT_STATE_TO_FORK(struct xfs_inode *ip, int state); + int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, struct xfs_inode_log_item *, int); @@ -169,4 +183,6 @@ void xfs_iext_irec_update_extoffs(struct xfs_ifork *, int, int); extern struct kmem_zone *xfs_ifork_zone; +extern void xfs_ifork_init_cow(struct xfs_inode *ip); + #endif /* __XFS_INODE_FORK_H__ */ diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index f179ea4..611107c 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -1346,6 +1346,8 @@ __xfs_rmap_add( if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; + if (ri->ri_whichfork == XFS_COW_FORK) + return 0; trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock), ri->ri_type, diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h index 690d616..cf044c0 100644 --- a/fs/xfs/libxfs/xfs_types.h +++ b/fs/xfs/libxfs/xfs_types.h @@ -93,6 +93,7 @@ typedef __int64_t xfs_sfiloff_t; /* signed block number in a file */ */ #define XFS_DATA_FORK 0 #define XFS_ATTR_FORK 1 +#define XFS_COW_FORK 2 /* * Min numbers of data/attr fork btree root pointers. diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 99ee6eee..06f3b8c 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -76,6 +76,9 @@ xfs_inode_alloc( ip->i_mount = mp; memset(&ip->i_imap, 0, sizeof(struct xfs_imap)); ip->i_afp = NULL; + ip->i_cowfp = NULL; + ip->i_cnextents = 0; + ip->i_cformat = XFS_DINODE_FMT_EXTENTS; memset(&ip->i_df, 0, sizeof(xfs_ifork_t)); ip->i_flags = 0; ip->i_delayed_blks = 0; @@ -101,6 +104,8 @@ xfs_inode_free_callback( if (ip->i_afp) xfs_idestroy_fork(ip, XFS_ATTR_FORK); + if (ip->i_cowfp) + xfs_idestroy_fork(ip, XFS_COW_FORK); if (ip->i_itemp) { ASSERT(!(ip->i_itemp->ili_item.li_flags & XFS_LI_IN_AIL)); diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index d0ea6ff..797fcc7 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -47,6 +47,7 @@ typedef struct xfs_inode { /* Extent information. */ xfs_ifork_t *i_afp; /* attribute fork pointer */ + xfs_ifork_t *i_cowfp; /* copy on write extents */ xfs_ifork_t i_df; /* data fork */ /* operations vectors */ @@ -65,6 +66,9 @@ typedef struct xfs_inode { struct xfs_icdinode i_d; /* most of ondisk inode */ + xfs_extnum_t i_cnextents; /* # of extents in cow fork */ + unsigned int i_cformat; /* format of cow fork */ + /* VFS inode */ struct inode i_vnode; /* embedded VFS inode */ } xfs_inode_t; diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c new file mode 100644 index 0000000..7adbb83 --- /dev/null +++ b/fs/xfs/xfs_reflink.c @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_inode.h" +#include "xfs_trans.h" +#include "xfs_inode_item.h" +#include "xfs_bmap.h" +#include "xfs_bmap_util.h" +#include "xfs_error.h" +#include "xfs_dir2.h" +#include "xfs_dir2_priv.h" +#include "xfs_ioctl.h" +#include "xfs_trace.h" +#include "xfs_log.h" +#include "xfs_icache.h" +#include "xfs_pnfs.h" +#include "xfs_refcount_btree.h" +#include "xfs_refcount.h" +#include "xfs_bmap_btree.h" +#include "xfs_trans_space.h" +#include "xfs_bit.h" +#include "xfs_alloc.h" +#include "xfs_quota_defs.h" +#include "xfs_quota.h" +#include "xfs_btree.h" +#include "xfs_bmap_btree.h" +#include "xfs_reflink.h" + +/* + * Copy on Write of Shared Blocks + * + * XFS must preserve "the usual" file semantics even when two files share + * the same physical blocks. This means that a write to one file must not + * alter the blocks in a different file; the way that we'll do that is + * through the use of a copy-on-write mechanism. At a high level, that + * means that when we want to write to a shared block, we allocate a new + * block, write the data to the new block, and if that succeeds we map the + * new block into the file. + * + * XFS provides a "delayed allocation" mechanism that defers the allocation + * of disk blocks to dirty-but-not-yet-mapped file blocks as long as + * possible. This reduces fragmentation by enabling the filesystem to ask + * for bigger chunks less often, which is exactly what we want for CoW. + * + * The delalloc mechanism begins when the kernel wants to make a block + * writable (write_begin or page_mkwrite). If the offset is not mapped, we + * create a delalloc mapping, which is a regular in-core extent, but without + * a real startblock. (For delalloc mappings, the startblock encodes both + * a flag that this is a delalloc mapping, and a worst-case estimate of how + * many blocks might be required to put the mapping into the BMBT.) delalloc + * mappings are a reservation against the free space in the filesystem; + * adjacent mappings can also be combined into fewer larger mappings. + * + * When dirty pages are being written out (typically in writepage), the + * delalloc reservations are converted into real mappings by allocating + * blocks and replacing the delalloc mapping with real ones. A delalloc + * mapping can be replaced by several real ones if the free space is + * fragmented. + * + * We want to adapt the delalloc mechanism for copy-on-write, since the + * write paths are similar. The first two steps (creating the reservation + * and allocating the blocks) are exactly the same as delalloc except that + * the mappings must be stored in a separate CoW fork because we do not want + * to disturb the mapping in the data fork until we're sure that the write + * succeeded. IO completion in this case is the process of removing the old + * mapping from the data fork and moving the new mapping from the CoW fork to + * the data fork. This will be discussed shortly. + * + * For now, unaligned directio writes will be bounced back to the page cache. + * Block-aligned directio writes will use the same mechanism as buffered + * writes. + * + * CoW remapping must be done after the data block write completes, + * because we don't want to destroy the old data fork map until we're sure + * the new block has been written. Since the new mappings are kept in a + * separate fork, we can simply iterate these mappings to find the ones + * that cover the file blocks that we just CoW'd. For each extent, simply + * unmap the corresponding range in the data fork, map the new range into + * the data fork, and remove the extent from the CoW fork. + * + * Since the remapping operation can be applied to an arbitrary file + * range, we record the need for the remap step as a flag in the ioend + * instead of declaring a new IO type. This is required for direct io + * because we only have ioend for the whole dio, and we have to be able to + * remember the presence of unwritten blocks and CoW blocks with a single + * ioend structure. Better yet, the more ground we can cover with one + * ioend, the better. + */ diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h new file mode 100644 index 0000000..820b151 --- /dev/null +++ b/fs/xfs/xfs_reflink.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_REFLINK_H +#define __XFS_REFLINK_H 1 + +#endif /* __XFS_REFLINK_H */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index fe9c6f8..079075f 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -269,10 +269,10 @@ DECLARE_EVENT_CLASS(xfs_bmap_class, __field(unsigned long, caller_ip) ), TP_fast_assign( - struct xfs_ifork *ifp = (state & BMAP_ATTRFORK) ? - ip->i_afp : &ip->i_df; + struct xfs_ifork *ifp; struct xfs_bmbt_irec r; + ifp = XFS_IEXT_STATE_TO_FORK(ip, state); xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx), &r); __entry->dev = VFS_I(ip)->i_sb->s_dev; __entry->ino = ip->i_ino; From darrick.wong@oracle.com Thu Jun 16 20:26:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id CC6E57CB4 for ; Thu, 16 Jun 2016 20:26:21 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 52274AC001 for ; Thu, 16 Jun 2016 18:26:21 -0700 (PDT) X-ASG-Debug-ID: 1466126778-04cbb01fec698a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Qt39VmPw08V5hrsZ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:19 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1QGTd010357 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:16 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QF2b023378 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:15 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QDX8008359; Fri, 17 Jun 2016 01:26:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:13 -0700 Subject: [PATCH 078/119] xfs: support bmapping delalloc extents in the CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 078/119] xfs: support bmapping delalloc extents in the CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:11 -0700 Message-ID: <146612677161.12839.2197894379412170153.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126778 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8268 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Allow the creation of delayed allocation extents in the CoW fork. In a subsequent patch we'll wire up write_begin and page_mkwrite to actually do this. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 29 +++++++++++++++++----------- fs/xfs/libxfs/xfs_bmap.h | 2 +- fs/xfs/xfs_iomap.c | 48 +++++++++++++++++++++++++++++++++++++--------- fs/xfs/xfs_iomap.h | 2 ++ 4 files changed, 60 insertions(+), 21 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index ccfaf60..18b94e6 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -2760,6 +2760,7 @@ done: STATIC void xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ + int whichfork, xfs_extnum_t *idx, /* extent number to update/insert */ xfs_bmbt_irec_t *new) /* new data to add to file extents */ { @@ -2771,8 +2772,10 @@ xfs_bmap_add_extent_hole_delay( int state; /* state bits, accessed thru macros */ xfs_filblks_t temp=0; /* temp for indirect calculations */ - ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + ifp = XFS_IFORK_PTR(ip, whichfork); state = 0; + if (whichfork == XFS_COW_FORK) + state |= BMAP_COWFORK; ASSERT(isnullstartblock(new->br_startblock)); /* @@ -2790,7 +2793,7 @@ xfs_bmap_add_extent_hole_delay( * Check and set flags if the current (right) segment exists. * If it doesn't exist, we're converting the hole at end-of-file. */ - if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { + if (*idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { state |= BMAP_RIGHT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right); @@ -4140,6 +4143,7 @@ xfs_bmapi_read( STATIC int xfs_bmapi_reserve_delalloc( struct xfs_inode *ip, + int whichfork, xfs_fileoff_t aoff, xfs_filblks_t len, struct xfs_bmbt_irec *got, @@ -4148,7 +4152,7 @@ xfs_bmapi_reserve_delalloc( int eof) { struct xfs_mount *mp = ip->i_mount; - struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); xfs_extlen_t alen; xfs_extlen_t indlen; char rt = XFS_IS_REALTIME_INODE(ip); @@ -4207,7 +4211,7 @@ xfs_bmapi_reserve_delalloc( got->br_startblock = nullstartblock(indlen); got->br_blockcount = alen; got->br_state = XFS_EXT_NORM; - xfs_bmap_add_extent_hole_delay(ip, lastx, got); + xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got); /* * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay @@ -4239,6 +4243,7 @@ out_unreserve_quota: int xfs_bmapi_delay( struct xfs_inode *ip, /* incore inode */ + int whichfork, /* data or cow fork? */ xfs_fileoff_t bno, /* starting file offs. mapped */ xfs_filblks_t len, /* length to map in file */ struct xfs_bmbt_irec *mval, /* output: map values */ @@ -4246,7 +4251,7 @@ xfs_bmapi_delay( int flags) /* XFS_BMAPI_... */ { struct xfs_mount *mp = ip->i_mount; - struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_bmbt_irec got; /* current file extent record */ struct xfs_bmbt_irec prev; /* previous file extent record */ xfs_fileoff_t obno; /* old block number (offset) */ @@ -4256,14 +4261,15 @@ xfs_bmapi_delay( int n = 0; /* current extent index */ int error = 0; + ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_COW_FORK); ASSERT(*nmap >= 1); ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); ASSERT(!(flags & ~XFS_BMAPI_ENTIRE)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); if (unlikely(XFS_TEST_ERROR( - (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS && - XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE), + (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { XFS_ERROR_REPORT("xfs_bmapi_delay", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; @@ -4274,19 +4280,20 @@ xfs_bmapi_delay( XFS_STATS_INC(mp, xs_blk_mapw); - if (!(ifp->if_flags & XFS_IFEXTENTS)) { - error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK); + if (whichfork == XFS_DATA_FORK && !(ifp->if_flags & XFS_IFEXTENTS)) { + error = xfs_iread_extents(NULL, ip, whichfork); if (error) return error; } - xfs_bmap_search_extents(ip, bno, XFS_DATA_FORK, &eof, &lastx, &got, &prev); + xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); end = bno + len; obno = bno; while (bno < end && n < *nmap) { if (eof || got.br_startoff > bno) { - error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got, + error = xfs_bmapi_reserve_delalloc(ip, whichfork, + bno, len, &got, &prev, &lastx, eof); if (error) { if (n == 0) { diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index a8ef1c6..d90f88e 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -205,7 +205,7 @@ int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip, int xfs_bmapi_read(struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, struct xfs_bmbt_irec *mval, int *nmap, int flags); -int xfs_bmapi_delay(struct xfs_inode *ip, xfs_fileoff_t bno, +int xfs_bmapi_delay(struct xfs_inode *ip, int whichfork, xfs_fileoff_t bno, xfs_filblks_t len, struct xfs_bmbt_irec *mval, int *nmap, int flags); int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 61b61f51..82c4697 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -560,12 +560,13 @@ check_writeio: return alloc_blocks; } -int -xfs_iomap_write_delay( +STATIC int +__xfs_iomap_write_delay( xfs_inode_t *ip, xfs_off_t offset, size_t count, - xfs_bmbt_irec_t *ret_imap) + xfs_bmbt_irec_t *ret_imap, + int whichfork) { xfs_mount_t *mp = ip->i_mount; xfs_fileoff_t offset_fsb; @@ -591,10 +592,14 @@ xfs_iomap_write_delay( extsz = xfs_get_extsz_hint(ip); offset_fsb = XFS_B_TO_FSBT(mp, offset); - error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count, - imap, XFS_WRITE_IMAPS, &prealloc); - if (error) - return error; + if (whichfork == XFS_DATA_FORK) { + error = xfs_iomap_eof_want_preallocate(mp, ip, offset, count, + imap, XFS_WRITE_IMAPS, &prealloc); + if (error) + return error; + } else { + prealloc = 0; + } retry: if (prealloc) { @@ -626,8 +631,8 @@ retry: ASSERT(last_fsb > offset_fsb); nimaps = XFS_WRITE_IMAPS; - error = xfs_bmapi_delay(ip, offset_fsb, last_fsb - offset_fsb, - imap, &nimaps, XFS_BMAPI_ENTIRE); + error = xfs_bmapi_delay(ip, whichfork, offset_fsb, + last_fsb - offset_fsb, imap, &nimaps, XFS_BMAPI_ENTIRE); switch (error) { case 0: case -ENOSPC: @@ -665,6 +670,31 @@ retry: return 0; } +int +xfs_iomap_write_delay( + xfs_inode_t *ip, + xfs_off_t offset, + size_t count, + xfs_bmbt_irec_t *ret_imap) +{ + return __xfs_iomap_write_delay(ip, offset, count, ret_imap, + XFS_DATA_FORK); +} + +int +xfs_iomap_cow_delay( + xfs_inode_t *ip, + xfs_off_t offset, + size_t count, + xfs_bmbt_irec_t *ret_imap) +{ + ASSERT(XFS_IFORK_PTR(ip, XFS_COW_FORK) != NULL); + trace_xfs_iomap_cow_delay(ip, offset, count); + + return __xfs_iomap_write_delay(ip, offset, count, ret_imap, + XFS_COW_FORK); +} + /* * Pass in a delayed allocate extent, convert it to real extents; * return to the caller the extent we create which maps on top of diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index 8688e66..f6a9adf 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -28,5 +28,7 @@ int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, struct xfs_bmbt_irec *); int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t); +int xfs_iomap_cow_delay(struct xfs_inode *, xfs_off_t, size_t, + struct xfs_bmbt_irec *); #endif /* __XFS_IOMAP_H__*/ From darrick.wong@oracle.com Thu Jun 16 20:26:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id AA33D7E8A for ; Thu, 16 Jun 2016 20:26:27 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5A974304039 for ; Thu, 16 Jun 2016 18:26:27 -0700 (PDT) X-ASG-Debug-ID: 1466126784-04bdf01e1795be0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id m8MpsjXw78tNEnOi (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:24 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1QMvH029654 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:22 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QMBf023459 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:22 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QJ6Q008378; Fri, 17 Jun 2016 01:26:21 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:19 -0700 Subject: [PATCH 079/119] xfs: create delalloc extents in CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 079/119] xfs: create delalloc extents in CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:18 -0700 Message-ID: <146612677795.12839.15535158428152936702.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126784 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7140 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Wire up write_begin and page_mkwrite to detect shared extents and create delayed allocation extents in the CoW fork. v2: Make trim_extent better at constraining the extent to just the range passed in. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_aops.c | 10 +++ fs/xfs/xfs_file.c | 10 +++ fs/xfs/xfs_reflink.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 3 + 4 files changed, 181 insertions(+) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 4c463b9..66a2a9b 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -31,6 +31,7 @@ #include "xfs_bmap.h" #include "xfs_bmap_util.h" #include "xfs_bmap_btree.h" +#include "xfs_reflink.h" #include #include #include @@ -1567,6 +1568,15 @@ xfs_vm_write_begin( if (!page) return -ENOMEM; + /* Reserve delalloc blocks for CoW. */ + status = xfs_reflink_reserve_cow_range(XFS_I(mapping->host), pos, len); + if (status) { + unlock_page(page); + put_page(page); + *pagep = NULL; + return status; + } + status = __block_write_begin(page, pos, len, xfs_get_blocks); if (xfs_mp_fail_writes(mp)) status = -EIO; diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 47fc632..148d0b3 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -37,6 +37,7 @@ #include "xfs_log.h" #include "xfs_icache.h" #include "xfs_pnfs.h" +#include "xfs_reflink.h" #include #include @@ -1550,6 +1551,14 @@ xfs_filemap_page_mkwrite( file_update_time(vma->vm_file); xfs_ilock(XFS_I(inode), XFS_MMAPLOCK_SHARED); + /* Reserve delalloc blocks for CoW. */ + ret = xfs_reflink_reserve_cow_range(XFS_I(inode), + vmf->page->index << PAGE_SHIFT, PAGE_SIZE); + if (ret) { + ret = block_page_mkwrite_return(ret); + goto out; + } + if (IS_DAX(inode)) { ret = __dax_mkwrite(vma, vmf, xfs_get_blocks_dax_fault); } else { @@ -1557,6 +1566,7 @@ xfs_filemap_page_mkwrite( ret = block_page_mkwrite_return(ret); } +out: xfs_iunlock(XFS_I(inode), XFS_MMAPLOCK_SHARED); sb_end_pagefault(inode->i_sb); diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 7adbb83..112d86b 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -51,6 +51,7 @@ #include "xfs_btree.h" #include "xfs_bmap_btree.h" #include "xfs_reflink.h" +#include "xfs_iomap.h" /* * Copy on Write of Shared Blocks @@ -112,3 +113,160 @@ * ioend structure. Better yet, the more ground we can cover with one * ioend, the better. */ + +/* Trim extent to fit a logical block range. */ +static void +xfs_trim_extent( + struct xfs_bmbt_irec *irec, + xfs_fileoff_t bno, + xfs_filblks_t len) +{ + xfs_fileoff_t distance; + xfs_fileoff_t end = bno + len; + + if (irec->br_startoff + irec->br_blockcount <= bno || + irec->br_startoff >= end) { + irec->br_blockcount = 0; + return; + } + + if (irec->br_startoff < bno) { + distance = bno - irec->br_startoff; + if (irec->br_startblock != DELAYSTARTBLOCK && + irec->br_startblock != HOLESTARTBLOCK) + irec->br_startblock += distance; + irec->br_startoff += distance; + irec->br_blockcount -= distance; + } + + if (end < irec->br_startoff + irec->br_blockcount) { + distance = irec->br_startoff + irec->br_blockcount - end; + irec->br_blockcount -= distance; + } +} + +/* Find the shared ranges under an irec, and set up delalloc extents. */ +static int +xfs_reflink_reserve_cow_extent( + struct xfs_inode *ip, + struct xfs_bmbt_irec *irec) +{ + struct xfs_bmbt_irec rec; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + xfs_extlen_t aglen; + xfs_agblock_t fbno; + xfs_extlen_t flen; + xfs_fileoff_t lblk; + xfs_off_t foffset; + xfs_extlen_t distance; + size_t fsize; + int error = 0; + + /* Holes, unwritten, and delalloc extents cannot be shared */ + if (ISUNWRITTEN(irec) || + irec->br_startblock == HOLESTARTBLOCK || + irec->br_startblock == DELAYSTARTBLOCK) + return 0; + + trace_xfs_reflink_reserve_cow_extent(ip, irec); + agno = XFS_FSB_TO_AGNO(ip->i_mount, irec->br_startblock); + agbno = XFS_FSB_TO_AGBNO(ip->i_mount, irec->br_startblock); + lblk = irec->br_startoff; + aglen = irec->br_blockcount; + + while (aglen > 0) { + /* Find maximal fork range within this extent */ + error = xfs_refcount_find_shared(ip->i_mount, agno, agbno, + aglen, &fbno, &flen, true); + if (error) + break; + if (flen == 0) { + distance = fbno - agbno; + goto advloop; + } + + /* Add as much as we can to the cow fork */ + foffset = XFS_FSB_TO_B(ip->i_mount, lblk + fbno - agbno); + fsize = XFS_FSB_TO_B(ip->i_mount, flen); + error = xfs_iomap_cow_delay(ip, foffset, fsize, &rec); + if (error) + break; + + distance = (rec.br_startoff - lblk) + rec.br_blockcount; +advloop: + if (aglen < distance) + break; + aglen -= distance; + agbno += distance; + lblk += distance; + } + + if (error) + trace_xfs_reflink_reserve_cow_extent_error(ip, error, _RET_IP_); + return error; +} + +/* + * Create CoW reservations for all shared blocks within a byte range of + * a file. + */ +int +xfs_reflink_reserve_cow_range( + struct xfs_inode *ip, + xfs_off_t pos, + xfs_off_t len) +{ + struct xfs_bmbt_irec imap; + int nimaps; + int error = 0; + xfs_fileoff_t lblk; + xfs_fileoff_t next_lblk; + struct xfs_ifork *ifp; + struct xfs_bmbt_rec_host *gotp; + xfs_extnum_t idx; + + if (!xfs_is_reflink_inode(ip)) + return 0; + + trace_xfs_reflink_reserve_cow_range(ip, len, pos, 0); + + lblk = XFS_B_TO_FSBT(ip->i_mount, pos); + next_lblk = XFS_B_TO_FSB(ip->i_mount, pos + len); + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + xfs_ilock(ip, XFS_ILOCK_EXCL); + while (lblk < next_lblk) { + /* Already reserved? Skip the refcount btree access. */ + gotp = xfs_iext_bno_to_ext(ifp, lblk, &idx); + if (gotp) { + xfs_bmbt_get_all(gotp, &imap); + if (imap.br_startoff <= lblk && + imap.br_startoff + imap.br_blockcount > lblk) { + lblk = imap.br_startoff + imap.br_blockcount; + continue; + } + } + + /* Read extent from the source file. */ + nimaps = 1; + error = xfs_bmapi_read(ip, lblk, next_lblk - lblk, &imap, + &nimaps, 0); + if (error) + break; + + if (nimaps == 0) + break; + + /* Fork all the shared blocks in this extent. */ + error = xfs_reflink_reserve_cow_extent(ip, &imap); + if (error) + break; + + lblk += imap.br_blockcount; + } + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + if (error) + trace_xfs_reflink_reserve_cow_range_error(ip, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 820b151..7b0a215 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -20,4 +20,7 @@ #ifndef __XFS_REFLINK_H #define __XFS_REFLINK_H 1 +extern int xfs_reflink_reserve_cow_range(struct xfs_inode *ip, xfs_off_t pos, + xfs_off_t len); + #endif /* __XFS_REFLINK_H */ From darrick.wong@oracle.com Thu Jun 16 20:26:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E717F7DDC for ; Thu, 16 Jun 2016 20:26:32 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 99D6A8F8050 for ; Thu, 16 Jun 2016 18:26:32 -0700 (PDT) X-ASG-Debug-ID: 1466126789-04bdf01e1095be0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id WcahryPvTNL2T7Q9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:29 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1QROP010420 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:28 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QQ78012323 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:27 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QQmP025075; Fri, 17 Jun 2016 01:26:26 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:25 -0700 Subject: [PATCH 080/119] xfs: support allocating delayed extents in CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 080/119] xfs: support allocating delayed extents in CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:24 -0700 Message-ID: <146612678437.12839.13258189648049039325.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126789 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9621 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Modify xfs_bmap_add_extent_delay_real() so that we can convert delayed allocation extents in the CoW fork to real allocations, and wire this up all the way back to xfs_iomap_write_allocate(). In a subsequent patch, we'll modify the writepage handler to call this. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 51 ++++++++++++++++++++++++++++++++-------------- fs/xfs/xfs_aops.c | 6 ++++- fs/xfs/xfs_iomap.c | 7 +++++- fs/xfs/xfs_iomap.h | 2 +- 4 files changed, 46 insertions(+), 20 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 18b94e6..8b419b3 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -141,7 +141,8 @@ xfs_bmbt_lookup_ge( */ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork) { - return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && + return whichfork != XFS_COW_FORK && + XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && XFS_IFORK_NEXTENTS(ip, whichfork) > XFS_IFORK_MAXEXT(ip, whichfork); } @@ -151,7 +152,8 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork) */ static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork) { - return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && + return whichfork != XFS_COW_FORK && + XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && XFS_IFORK_NEXTENTS(ip, whichfork) <= XFS_IFORK_MAXEXT(ip, whichfork); } @@ -641,6 +643,7 @@ xfs_bmap_btree_to_extents( mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); + ASSERT(whichfork != XFS_COW_FORK); ASSERT(ifp->if_flags & XFS_IFEXTENTS); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE); rblock = ifp->if_broot; @@ -707,6 +710,7 @@ xfs_bmap_extents_to_btree( xfs_bmbt_ptr_t *pp; /* root block address pointer */ mp = ip->i_mount; + ASSERT(whichfork != XFS_COW_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS); @@ -838,6 +842,7 @@ xfs_bmap_local_to_extents_empty( { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + ASSERT(whichfork != XFS_COW_FORK); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); ASSERT(ifp->if_bytes == 0); ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); @@ -1671,7 +1676,8 @@ xfs_bmap_one_block( */ STATIC int /* error */ xfs_bmap_add_extent_delay_real( - struct xfs_bmalloca *bma) + struct xfs_bmalloca *bma, + int whichfork) { struct xfs_bmbt_irec *new = &bma->got; int diff; /* temp value */ @@ -1689,11 +1695,14 @@ xfs_bmap_add_extent_delay_real( xfs_filblks_t temp=0; /* value for da_new calculations */ xfs_filblks_t temp2=0;/* value for da_new calculations */ int tmp_rval; /* partial logging flags */ - int whichfork = XFS_DATA_FORK; struct xfs_mount *mp; + xfs_extnum_t *nextents; mp = bma->ip->i_mount; ifp = XFS_IFORK_PTR(bma->ip, whichfork); + ASSERT(whichfork != XFS_ATTR_FORK); + nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents : + &bma->ip->i_d.di_nextents); ASSERT(bma->idx >= 0); ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); @@ -1707,6 +1716,9 @@ xfs_bmap_add_extent_delay_real( #define RIGHT r[1] #define PREV r[2] + if (whichfork == XFS_COW_FORK) + state |= BMAP_COWFORK; + /* * Set up a bunch of variables to make the tests simpler. */ @@ -1793,7 +1805,7 @@ xfs_bmap_add_extent_delay_real( trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_iext_remove(bma->ip, bma->idx + 1, 2, state); - bma->ip->i_d.di_nextents--; + (*nextents)--; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -1895,7 +1907,7 @@ xfs_bmap_add_extent_delay_real( xfs_bmbt_set_startblock(ep, new->br_startblock); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -1965,7 +1977,7 @@ xfs_bmap_add_extent_delay_real( temp = PREV.br_blockcount - new->br_blockcount; xfs_bmbt_set_blockcount(ep, temp); xfs_iext_insert(bma->ip, bma->idx, 1, new, state); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -2049,7 +2061,7 @@ xfs_bmap_add_extent_delay_real( trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -2118,7 +2130,7 @@ xfs_bmap_add_extent_delay_real( RIGHT.br_blockcount = temp2; /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -2216,7 +2228,8 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork); done: - bma->logflags |= rval; + if (whichfork != XFS_COW_FORK) + bma->logflags |= rval; return error; #undef LEFT #undef RIGHT @@ -3856,7 +3869,8 @@ xfs_bmap_btalloc( ASSERT(nullfb || fb_agno == args.agno || (ap->dfops->dop_low && fb_agno < args.agno)); ap->length = args.len; - ap->ip->i_d.di_nblocks += args.len; + if (!(ap->flags & XFS_BMAPI_COWFORK)) + ap->ip->i_d.di_nblocks += args.len; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); if (ap->wasdel) ap->ip->i_delayed_blks -= args.len; @@ -4330,8 +4344,7 @@ xfs_bmapi_allocate( struct xfs_bmalloca *bma) { struct xfs_mount *mp = bma->ip->i_mount; - int whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + int whichfork = xfs_bmapi_whichfork(bma->flags); struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); int tmp_logflags = 0; int error; @@ -4420,7 +4433,7 @@ xfs_bmapi_allocate( bma->got.br_state = XFS_EXT_UNWRITTEN; if (bma->wasdel) - error = xfs_bmap_add_extent_delay_real(bma); + error = xfs_bmap_add_extent_delay_real(bma, whichfork); else error = xfs_bmap_add_extent_hole_real(bma, whichfork); @@ -4574,8 +4587,7 @@ xfs_bmapi_write( orig_mval = mval; orig_nmap = *nmap; #endif - whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + whichfork = xfs_bmapi_whichfork(flags); ASSERT(*nmap >= 1); ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); @@ -4586,6 +4598,11 @@ xfs_bmapi_write( ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); if (whichfork == XFS_ATTR_FORK) ASSERT(!(flags & XFS_BMAPI_REMAP)); + if (whichfork == XFS_COW_FORK) { + ASSERT(!(flags & XFS_BMAPI_REMAP)); + ASSERT(!(flags & XFS_BMAPI_PREALLOC)); + ASSERT(!(flags & XFS_BMAPI_CONVERT)); + } if (flags & XFS_BMAPI_REMAP) { ASSERT(!(flags & XFS_BMAPI_PREALLOC)); ASSERT(!(flags & XFS_BMAPI_CONVERT)); @@ -4655,6 +4672,8 @@ xfs_bmapi_write( */ if (flags & XFS_BMAPI_REMAP) ASSERT(inhole); + if (flags & XFS_BMAPI_COWFORK) + ASSERT(!inhole); /* * First, deal with the hole before the allocated space diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 66a2a9b..50c4bf11 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -337,9 +337,11 @@ xfs_map_blocks( if (type == XFS_IO_DELALLOC && (!nimaps || isnullstartblock(imap->br_startblock))) { - error = xfs_iomap_write_allocate(ip, offset, imap); + error = xfs_iomap_write_allocate(ip, XFS_DATA_FORK, offset, + imap); if (!error) - trace_xfs_map_blocks_alloc(ip, offset, count, type, imap); + trace_xfs_map_blocks_alloc(ip, offset, count, type, + imap); return error; } diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 82c4697..e7e1346 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -708,6 +708,7 @@ xfs_iomap_cow_delay( int xfs_iomap_write_allocate( xfs_inode_t *ip, + int whichfork, xfs_off_t offset, xfs_bmbt_irec_t *imap) { @@ -720,8 +721,12 @@ xfs_iomap_write_allocate( xfs_trans_t *tp; int nimaps; int error = 0; + int flags = 0; int nres; + if (whichfork == XFS_COW_FORK) + flags |= XFS_BMAPI_COWFORK; + /* * Make sure that the dquots are there. */ @@ -811,7 +816,7 @@ xfs_iomap_write_allocate( * pointer that the caller gave to us. */ error = xfs_bmapi_write(tp, ip, map_start_fsb, - count_fsb, 0, &first_block, + count_fsb, flags, &first_block, nres, imap, &nimaps, &dfops); if (error) diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index f6a9adf..ba037d6 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h @@ -25,7 +25,7 @@ int xfs_iomap_write_direct(struct xfs_inode *, xfs_off_t, size_t, struct xfs_bmbt_irec *, int); int xfs_iomap_write_delay(struct xfs_inode *, xfs_off_t, size_t, struct xfs_bmbt_irec *); -int xfs_iomap_write_allocate(struct xfs_inode *, xfs_off_t, +int xfs_iomap_write_allocate(struct xfs_inode *, int, xfs_off_t, struct xfs_bmbt_irec *); int xfs_iomap_write_unwritten(struct xfs_inode *, xfs_off_t, xfs_off_t); int xfs_iomap_cow_delay(struct xfs_inode *, xfs_off_t, size_t, From darrick.wong@oracle.com Thu Jun 16 20:26:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F061D7E18 for ; Thu, 16 Jun 2016 20:26:39 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 65375AC002 for ; Thu, 16 Jun 2016 18:26:39 -0700 (PDT) X-ASG-Debug-ID: 1466126796-04cb6c542757a10001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 08vh6BcAuyC4dGaq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:36 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1QX1U010459 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:34 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QXAh019075 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:33 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QWpG020607; Fri, 17 Jun 2016 01:26:32 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:32 -0700 Subject: [PATCH 081/119] xfs: allocate delayed extents in CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 081/119] xfs: allocate delayed extents in CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:30 -0700 Message-ID: <146612679068.12839.13248247674043879834.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126796 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7889 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Modify the writepage handler to find and convert pending delalloc extents to real allocations. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_aops.c | 57 ++++++++++++++++++++++++--- fs/xfs/xfs_aops.h | 4 +- fs/xfs/xfs_reflink.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 5 ++ 4 files changed, 164 insertions(+), 8 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 50c4bf11..802d432 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -312,10 +312,15 @@ xfs_map_blocks( int error = 0; int bmapi_flags = XFS_BMAPI_ENTIRE; int nimaps = 1; + int whichfork; + bool need_alloc; if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; + whichfork = (type == XFS_IO_COW ? XFS_COW_FORK : XFS_DATA_FORK); + need_alloc = (type == XFS_IO_DELALLOC); + if (type == XFS_IO_UNWRITTEN) bmapi_flags |= XFS_BMAPI_IGSTATE; @@ -328,16 +333,29 @@ xfs_map_blocks( count = mp->m_super->s_maxbytes - offset; end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + count); offset_fsb = XFS_B_TO_FSBT(mp, offset); - error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, - imap, &nimaps, bmapi_flags); + + if (type == XFS_IO_COW) + error = xfs_reflink_find_cow_mapping(ip, offset, imap, + &need_alloc); + else { + error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, + imap, &nimaps, bmapi_flags); + /* + * Truncate an overwrite extent if there's a pending CoW + * reservation before the end of this extent. This forces us + * to come back to writepage to take care of the CoW. + */ + if (nimaps && type == XFS_IO_OVERWRITE) + xfs_reflink_trim_irec_to_next_cow(ip, offset_fsb, imap); + } xfs_iunlock(ip, XFS_ILOCK_SHARED); if (error) return error; - if (type == XFS_IO_DELALLOC && + if (need_alloc && (!nimaps || isnullstartblock(imap->br_startblock))) { - error = xfs_iomap_write_allocate(ip, XFS_DATA_FORK, offset, + error = xfs_iomap_write_allocate(ip, whichfork, offset, imap); if (!error) trace_xfs_map_blocks_alloc(ip, offset, count, type, @@ -625,7 +643,8 @@ xfs_check_page_type( if (type == XFS_IO_DELALLOC) return true; } else if (buffer_dirty(bh) && buffer_mapped(bh)) { - if (type == XFS_IO_OVERWRITE) + if (type == XFS_IO_OVERWRITE || + type == XFS_IO_COW) return true; } @@ -637,6 +656,26 @@ xfs_check_page_type( return false; } +/* + * Figure out if CoW is pending at this offset. + */ +static bool +xfs_is_cow_io( + struct xfs_inode *ip, + xfs_off_t offset) +{ + bool is_cow; + + if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb)) + return false; + + xfs_ilock(ip, XFS_ILOCK_SHARED); + is_cow = xfs_reflink_is_cow_pending(ip, offset); + xfs_iunlock(ip, XFS_ILOCK_SHARED); + + return is_cow; +} + STATIC void xfs_vm_invalidatepage( struct page *page, @@ -745,6 +784,7 @@ xfs_writepage_map( int error = 0; int count = 0; int uptodate = 1; + unsigned int new_type; bh = head = page_buffers(page); offset = page_offset(page); @@ -776,8 +816,11 @@ xfs_writepage_map( wpc->imap_valid = false; } } else if (buffer_uptodate(bh)) { - if (wpc->io_type != XFS_IO_OVERWRITE) { - wpc->io_type = XFS_IO_OVERWRITE; + new_type = xfs_is_cow_io(XFS_I(inode), offset) ? + XFS_IO_COW : XFS_IO_OVERWRITE; + + if (wpc->io_type != new_type) { + wpc->io_type = new_type; wpc->imap_valid = false; } } else { diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 814aab7..ee64d57 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -28,13 +28,15 @@ enum { XFS_IO_DELALLOC, /* covers delalloc region */ XFS_IO_UNWRITTEN, /* covers allocated but uninitialized data */ XFS_IO_OVERWRITE, /* covers already allocated extent */ + XFS_IO_COW, /* covers copy-on-write extent */ }; #define XFS_IO_TYPES \ { XFS_IO_INVALID, "invalid" }, \ { XFS_IO_DELALLOC, "delalloc" }, \ { XFS_IO_UNWRITTEN, "unwritten" }, \ - { XFS_IO_OVERWRITE, "overwrite" } + { XFS_IO_OVERWRITE, "overwrite" }, \ + { XFS_IO_COW, "CoW" } /* * Structure for buffered I/O completions. diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 112d86b..f0a9e42 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -270,3 +270,109 @@ xfs_reflink_reserve_cow_range( trace_xfs_reflink_reserve_cow_range_error(ip, error, _RET_IP_); return error; } + +/* + * Determine if there's a CoW reservation at a byte offset of an inode. + */ +bool +xfs_reflink_is_cow_pending( + struct xfs_inode *ip, + xfs_off_t offset) +{ + struct xfs_ifork *ifp; + struct xfs_bmbt_rec_host *gotp; + struct xfs_bmbt_irec irec; + xfs_fileoff_t bno; + xfs_extnum_t idx; + + if (!xfs_is_reflink_inode(ip)) + return false; + + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + bno = XFS_B_TO_FSBT(ip->i_mount, offset); + gotp = xfs_iext_bno_to_ext(ifp, bno, &idx); + + if (!gotp) + return false; + + xfs_bmbt_get_all(gotp, &irec); + if (bno >= irec.br_startoff + irec.br_blockcount || + bno < irec.br_startoff) + return false; + return true; +} + +/* + * Find the CoW reservation (and whether or not it needs block allocation) + * for a given byte offset of a file. + */ +int +xfs_reflink_find_cow_mapping( + struct xfs_inode *ip, + xfs_off_t offset, + struct xfs_bmbt_irec *imap, + bool *need_alloc) +{ + struct xfs_bmbt_irec irec; + struct xfs_ifork *ifp; + struct xfs_bmbt_rec_host *gotp; + xfs_fileoff_t bno; + xfs_extnum_t idx; + + /* Find the extent in the CoW fork. */ + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + bno = XFS_B_TO_FSBT(ip->i_mount, offset); + gotp = xfs_iext_bno_to_ext(ifp, bno, &idx); + xfs_bmbt_get_all(gotp, &irec); + + trace_xfs_reflink_find_cow_mapping(ip, offset, 1, XFS_IO_OVERWRITE, + &irec); + + /* If it's still delalloc, we must allocate later. */ + *imap = irec; + *need_alloc = !!(isnullstartblock(irec.br_startblock)); + + return 0; +} + +/* + * Trim an extent to end at the next CoW reservation past offset_fsb. + */ +int +xfs_reflink_trim_irec_to_next_cow( + struct xfs_inode *ip, + xfs_fileoff_t offset_fsb, + struct xfs_bmbt_irec *imap) +{ + struct xfs_bmbt_irec irec; + struct xfs_ifork *ifp; + struct xfs_bmbt_rec_host *gotp; + xfs_extnum_t idx; + + if (!xfs_is_reflink_inode(ip)) + return 0; + + /* Find the extent in the CoW fork. */ + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + gotp = xfs_iext_bno_to_ext(ifp, offset_fsb, &idx); + if (!gotp) + return 0; + xfs_bmbt_get_all(gotp, &irec); + + /* This is the extent before; try sliding up one. */ + if (irec.br_startoff < offset_fsb) { + idx++; + if (idx >= ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) + return 0; + gotp = xfs_iext_get_ext(ifp, idx); + xfs_bmbt_get_all(gotp, &irec); + } + + if (irec.br_startoff >= imap->br_startoff + imap->br_blockcount) + return 0; + + imap->br_blockcount = irec.br_startoff - imap->br_startoff; + trace_xfs_reflink_trim_irec(ip, imap); + + return 0; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 7b0a215..a2a23f5 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -22,5 +22,10 @@ extern int xfs_reflink_reserve_cow_range(struct xfs_inode *ip, xfs_off_t pos, xfs_off_t len); +extern bool xfs_reflink_is_cow_pending(struct xfs_inode *ip, xfs_off_t offset); +extern int xfs_reflink_find_cow_mapping(struct xfs_inode *ip, xfs_off_t offset, + struct xfs_bmbt_irec *imap, bool *need_alloc); +extern int xfs_reflink_trim_irec_to_next_cow(struct xfs_inode *ip, + xfs_fileoff_t offset_fsb, struct xfs_bmbt_irec *imap); #endif /* __XFS_REFLINK_H */ From darrick.wong@oracle.com Thu Jun 16 20:26:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9D3F47CB4 for ; Thu, 16 Jun 2016 20:26:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 606E2304039 for ; Thu, 16 Jun 2016 18:26:46 -0700 (PDT) X-ASG-Debug-ID: 1466126804-04cb6c542457a20001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ETOGYdt9mrpBDdkw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:44 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1QfbB029762 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:42 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QfZm019228 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:41 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Qcq4008506; Fri, 17 Jun 2016 01:26:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:38 -0700 Subject: [PATCH 082/119] xfs: support removing extents from CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 082/119] xfs: support removing extents from CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:37 -0700 Message-ID: <146612679701.12839.15113049094821910868.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126804 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7121 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a helper method to remove extents from the CoW fork without any of the side effects (rmapbt/bmbt updates) of the regular extent deletion routine. We'll eventually use this to clear out the CoW fork during ioend processing. v2: Use bmapi_read to iterate and trim the CoW extents instead of reading them raw via the iext code. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 176 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_bmap.h | 1 2 files changed, 177 insertions(+) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 8b419b3..2ba513b 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -4981,6 +4981,7 @@ xfs_bmap_del_extent( /* * Matches the whole extent. Delete the entry. */ + trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_iext_remove(ip, *idx, 1, whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0); --*idx; @@ -5198,6 +5199,181 @@ done: } /* + * xfs_bunmapi_cow() -- Remove the relevant parts of the CoW fork. + * See xfs_bmap_del_extent. + * @ip: XFS inode. + * @idx: Extent number to delete. + * @del: Extent to remove. + */ +int +xfs_bunmapi_cow( + xfs_inode_t *ip, + xfs_bmbt_irec_t *del) +{ + xfs_filblks_t da_new; /* new delay-alloc indirect blocks */ + xfs_filblks_t da_old; /* old delay-alloc indirect blocks */ + xfs_fsblock_t del_endblock = 0;/* first block past del */ + xfs_fileoff_t del_endoff; /* first offset past del */ + int delay; /* current block is delayed allocated */ + xfs_bmbt_rec_host_t *ep; /* current extent entry pointer */ + int error; /* error return value */ + xfs_bmbt_irec_t got; /* current extent entry */ + xfs_fileoff_t got_endoff; /* first offset past got */ + xfs_ifork_t *ifp; /* inode fork pointer */ + xfs_mount_t *mp; /* mount structure */ + xfs_filblks_t nblks; /* quota/sb block count */ + xfs_bmbt_irec_t new; /* new record to be inserted */ + /* REFERENCED */ + uint qfield; /* quota field to update */ + xfs_filblks_t temp; /* for indirect length calculations */ + xfs_filblks_t temp2; /* for indirect length calculations */ + int state = BMAP_COWFORK; + int eof; + xfs_extnum_t eidx; + + mp = ip->i_mount; + XFS_STATS_INC(mp, xs_del_exlist); + + ep = xfs_bmap_search_extents(ip, del->br_startoff, XFS_COW_FORK, &eof, + &eidx, &got, &new); + + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + ASSERT((eidx >= 0) && (eidx < ifp->if_bytes / + (uint)sizeof(xfs_bmbt_rec_t))); + ASSERT(del->br_blockcount > 0); + ASSERT(got.br_startoff <= del->br_startoff); + del_endoff = del->br_startoff + del->br_blockcount; + got_endoff = got.br_startoff + got.br_blockcount; + ASSERT(got_endoff >= del_endoff); + delay = isnullstartblock(got.br_startblock); + ASSERT(isnullstartblock(del->br_startblock) == delay); + qfield = 0; + error = 0; + /* + * If deleting a real allocation, must free up the disk space. + */ + if (!delay) { + nblks = del->br_blockcount; + qfield = XFS_TRANS_DQ_BCOUNT; + /* + * Set up del_endblock and cur for later. + */ + del_endblock = del->br_startblock + del->br_blockcount; + da_old = da_new = 0; + } else { + da_old = startblockval(got.br_startblock); + da_new = 0; + nblks = 0; + } + qfield = qfield; + nblks = nblks; + + /* + * Set flag value to use in switch statement. + * Left-contig is 2, right-contig is 1. + */ + switch (((got.br_startoff == del->br_startoff) << 1) | + (got_endoff == del_endoff)) { + case 3: + /* + * Matches the whole extent. Delete the entry. + */ + xfs_iext_remove(ip, eidx, 1, BMAP_COWFORK); + --eidx; + break; + + case 2: + /* + * Deleting the first part of the extent. + */ + trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_); + xfs_bmbt_set_startoff(ep, del_endoff); + temp = got.br_blockcount - del->br_blockcount; + xfs_bmbt_set_blockcount(ep, temp); + if (delay) { + temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), + da_old); + xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + da_new = temp; + break; + } + xfs_bmbt_set_startblock(ep, del_endblock); + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + break; + + case 1: + /* + * Deleting the last part of the extent. + */ + temp = got.br_blockcount - del->br_blockcount; + trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_); + xfs_bmbt_set_blockcount(ep, temp); + if (delay) { + temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), + da_old); + xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + da_new = temp; + break; + } + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + break; + + case 0: + /* + * Deleting the middle of the extent. + */ + temp = del->br_startoff - got.br_startoff; + trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_); + xfs_bmbt_set_blockcount(ep, temp); + new.br_startoff = del_endoff; + temp2 = got_endoff - del_endoff; + new.br_blockcount = temp2; + new.br_state = got.br_state; + if (!delay) { + new.br_startblock = del_endblock; + } else { + temp = xfs_bmap_worst_indlen(ip, temp); + xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); + temp2 = xfs_bmap_worst_indlen(ip, temp2); + new.br_startblock = nullstartblock((int)temp2); + da_new = temp + temp2; + while (da_new > da_old) { + if (temp) { + temp--; + da_new--; + xfs_bmbt_set_startblock(ep, + nullstartblock((int)temp)); + } + if (da_new == da_old) + break; + if (temp2) { + temp2--; + da_new--; + new.br_startblock = + nullstartblock((int)temp2); + } + } + } + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + xfs_iext_insert(ip, eidx + 1, 1, &new, state); + ++eidx; + break; + } + + /* + * Account for change in delayed indirect blocks. + * Nothing to do for disk quota accounting here. + */ + ASSERT(da_old >= da_new); + if (da_old > da_new) + xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false); + + return error; +} + +/* * Unmap (remove) blocks from a file. * If nexts is nonzero then the number of extents to remove is limited to * that value. If not all extents in the block range can be removed then diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h index d90f88e..1c7ab70 100644 --- a/fs/xfs/libxfs/xfs_bmap.h +++ b/fs/xfs/libxfs/xfs_bmap.h @@ -221,6 +221,7 @@ int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, struct xfs_defer_ops *dfops, int *done); +int xfs_bunmapi_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *del); int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, xfs_extnum_t num); uint xfs_default_attroffset(struct xfs_inode *ip); From darrick.wong@oracle.com Thu Jun 16 20:26:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BC66C7DF6 for ; Thu, 16 Jun 2016 20:26:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 454F3AC002 for ; Thu, 16 Jun 2016 18:26:55 -0700 (PDT) X-ASG-Debug-ID: 1466126812-04cbb01fee698f0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id aINCv6em0wgT46WS (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Qm0i029846 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:48 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QmWf023874 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:48 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QkXE008514; Fri, 17 Jun 2016 01:26:47 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:45 -0700 Subject: [PATCH 083/119] xfs: move mappings from cow fork to data fork after copy-write From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 083/119] xfs: move mappings from cow fork to data fork after copy-write To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:43 -0700 Message-ID: <146612680331.12839.3985620410576071705.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126812 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10574 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines After the write component of a copy-write operation finishes, clean up the bookkeeping left behind. On error, we simply free the new blocks and pass the error up. If we succeed, however, then we must remove the old data fork mapping and move the cow fork mapping to the data fork. v2: If CoW fails, we need to remove the CoW fork mapping and free the blocks. Furthermore, if xfs_cancel_ioend happens, we also need to clean out all the CoW record keeping. v3: When we're removing CoW extents, only free one extent per transaction to avoid running out of reservation. Also, xfs_cancel_ioend mustn't clean out the CoW fork because it is called when async writeback can't get an inode lock and will try again. v4: Use bmapi_read to iterate the CoW fork instead of calling the iext functions directly, and make the CoW remapping atomic by using the deferred ops mechanism which takes care of logging redo items for us. Signed-off-by: Darrick J. Wong [hch: Call the CoW failure function during xfs_cancel_ioend] Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_aops.c | 22 ++++ fs/xfs/xfs_reflink.c | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 8 ++ 3 files changed, 278 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 802d432..232039c 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -262,6 +262,23 @@ xfs_end_io( error = -EIO; /* + * For a CoW extent, we need to move the mapping from the CoW fork + * to the data fork. If instead an error happened, just dump the + * new blocks. + */ + if (ioend->io_type == XFS_IO_COW) { + if (ioend->io_bio->bi_error) { + error = xfs_reflink_cancel_cow_range(ip, + ioend->io_offset, ioend->io_size); + goto done; + } + error = xfs_reflink_end_cow(ip, ioend->io_offset, + ioend->io_size); + if (error) + goto done; + } + + /* * For unwritten extents we need to issue transactions to convert a * range to normal written extens after the data I/O has finished. * Detecting and handling completion IO errors is done individually @@ -276,7 +293,8 @@ xfs_end_io( } else if (ioend->io_append_trans) { error = xfs_setfilesize_ioend(ioend, error); } else { - ASSERT(!xfs_ioend_is_append(ioend)); + ASSERT(!xfs_ioend_is_append(ioend) || + ioend->io_type == XFS_IO_COW); } done: @@ -290,7 +308,7 @@ xfs_end_bio( struct xfs_ioend *ioend = bio->bi_private; struct xfs_mount *mp = XFS_I(ioend->io_inode)->i_mount; - if (ioend->io_type == XFS_IO_UNWRITTEN) + if (ioend->io_type == XFS_IO_UNWRITTEN || ioend->io_type == XFS_IO_COW) queue_work(mp->m_unwritten_workqueue, &ioend->io_work); else if (ioend->io_append_trans) queue_work(mp->m_data_workqueue, &ioend->io_work); diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index f0a9e42..59c8e86 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -52,6 +52,7 @@ #include "xfs_bmap_btree.h" #include "xfs_reflink.h" #include "xfs_iomap.h" +#include "xfs_rmap_btree.h" /* * Copy on Write of Shared Blocks @@ -376,3 +377,252 @@ xfs_reflink_trim_irec_to_next_cow( return 0; } + +/* + * Cancel all pending CoW reservations for some block range of an inode. + */ +int +xfs_reflink_cancel_cow_blocks( + struct xfs_inode *ip, + struct xfs_trans **tpp, + xfs_fileoff_t offset_fsb, + xfs_fileoff_t end_fsb) +{ + struct xfs_bmbt_irec irec; + struct xfs_ifork *ifp; + xfs_filblks_t count_fsb; + xfs_fsblock_t firstfsb; + struct xfs_defer_ops dfops; + int error = 0; + int nimaps; + + if (!xfs_is_reflink_inode(ip)) + return 0; + + /* Go find the old extent in the CoW fork. */ + count_fsb = (xfs_filblks_t)(end_fsb - offset_fsb); + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + while (count_fsb) { + nimaps = 1; + error = xfs_bmapi_read(ip, offset_fsb, count_fsb, &irec, + &nimaps, XFS_BMAPI_COWFORK); + if (error) + break; + ASSERT(nimaps == 1); + + xfs_trim_extent(&irec, offset_fsb, count_fsb); + trace_xfs_reflink_cancel_cow(ip, &irec); + + if (irec.br_startblock == DELAYSTARTBLOCK) { + /* Free a delayed allocation. */ + xfs_mod_fdblocks(ip->i_mount, irec.br_blockcount, + false); + ip->i_delayed_blks -= irec.br_blockcount; + + /* Remove the mapping from the CoW fork. */ + error = xfs_bunmapi_cow(ip, &irec); + if (error) + break; + } else if (irec.br_startblock == HOLESTARTBLOCK) { + /* empty */ + } else { + xfs_trans_ijoin(*tpp, ip, 0); + xfs_defer_init(&dfops, &firstfsb); + + xfs_bmap_add_free(ip->i_mount, &dfops, + irec.br_startblock, irec.br_blockcount, + NULL); + + /* Update quota accounting */ + xfs_trans_mod_dquot_byino(*tpp, ip, XFS_TRANS_DQ_BCOUNT, + -(long)irec.br_blockcount); + + /* Roll the transaction */ + error = xfs_defer_finish(tpp, &dfops, ip); + if (error) { + xfs_defer_cancel(&dfops); + break; + } + + /* Remove the mapping from the CoW fork. */ + error = xfs_bunmapi_cow(ip, &irec); + if (error) + break; + } + + /* Roll on... */ + count_fsb -= irec.br_startoff + irec.br_blockcount - offset_fsb; + offset_fsb = irec.br_startoff + irec.br_blockcount; + } + + return error; +} + +/* + * Cancel all pending CoW reservations for some byte range of an inode. + */ +int +xfs_reflink_cancel_cow_range( + struct xfs_inode *ip, + xfs_off_t offset, + xfs_off_t count) +{ + struct xfs_trans *tp; + xfs_fileoff_t offset_fsb; + xfs_fileoff_t end_fsb; + int error; + + trace_xfs_reflink_cancel_cow_range(ip, offset, count); + + offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); + if (count == NULLFILEOFF) + end_fsb = NULLFILEOFF; + else + end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); + + /* Start a rolling transaction to remove the mappings */ + error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, + 0, 0, 0, &tp); + if (error) + goto out; + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + + /* Scrape out the old CoW reservations */ + error = xfs_reflink_cancel_cow_blocks(ip, &tp, offset_fsb, end_fsb); + if (error) + goto out_defer; + + error = xfs_trans_commit(tp); + if (error) + goto out; + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return 0; + +out_defer: + xfs_trans_cancel(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); +out: + trace_xfs_reflink_cancel_cow_range_error(ip, error, _RET_IP_); + return error; +} + +/* + * Remap parts of a file's data fork after a successful CoW. + */ +int +xfs_reflink_end_cow( + struct xfs_inode *ip, + xfs_off_t offset, + xfs_off_t count) +{ + struct xfs_bmbt_irec irec; + struct xfs_bmbt_irec uirec; + struct xfs_trans *tp; + struct xfs_ifork *ifp; + xfs_fileoff_t offset_fsb; + xfs_fileoff_t end_fsb; + xfs_filblks_t count_fsb; + xfs_fsblock_t firstfsb; + struct xfs_defer_ops dfops; + int done; + int error; + unsigned int resblks; + xfs_filblks_t ilen; + xfs_filblks_t rlen; + int nimaps; + + trace_xfs_reflink_end_cow(ip, offset, count); + + offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); + end_fsb = XFS_B_TO_FSB(ip->i_mount, offset + count); + count_fsb = (xfs_filblks_t)(end_fsb - offset_fsb); + + /* Start a rolling transaction to switch the mappings */ + resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK); + error = xfs_trans_alloc(ip->i_mount, &M_RES(ip->i_mount)->tr_write, + resblks, 0, 0, &tp); + if (error) + goto out; + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + + /* Go find the old extent in the CoW fork. */ + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + while (count_fsb) { + /* Read extent from the source file */ + nimaps = 1; + error = xfs_bmapi_read(ip, offset_fsb, count_fsb, &irec, + &nimaps, XFS_BMAPI_COWFORK); + if (error) + goto out_cancel; + ASSERT(nimaps == 1); + + ASSERT(irec.br_startblock != DELAYSTARTBLOCK); + xfs_trim_extent(&irec, offset_fsb, count_fsb); + trace_xfs_reflink_cow_remap(ip, &irec); + + /* + * We can have a hole in the CoW fork if part of a directio + * write is CoW but part of it isn't. + */ + rlen = ilen = irec.br_blockcount; + if (irec.br_startblock == HOLESTARTBLOCK) + goto next_extent; + + /* Unmap the old blocks in the data fork. */ + done = false; + while (rlen) { + xfs_defer_init(&dfops, &firstfsb); + error = __xfs_bunmapi(tp, ip, irec.br_startoff, + &rlen, 0, 1, &firstfsb, &dfops); + if (error) + goto out_defer; + + /* Trim the extent to whatever got unmapped. */ + uirec = irec; + xfs_trim_extent(&uirec, irec.br_startoff + rlen, + irec.br_blockcount - rlen); + irec.br_blockcount = rlen; + trace_xfs_reflink_cow_remap_piece(ip, &uirec); + + /* Map the new blocks into the data fork. */ + error = xfs_bmap_map_extent(tp->t_mountp, &dfops, + ip, XFS_DATA_FORK, &uirec); + if (error) + goto out_defer; + + /* Remove the mapping from the CoW fork. */ + error = xfs_bunmapi_cow(ip, &uirec); + if (error) + goto out_defer; + + error = xfs_defer_finish(&tp, &dfops, ip); + if (error) + goto out_defer; + } + +next_extent: + /* Roll on... */ + count_fsb -= irec.br_startoff + ilen - offset_fsb; + offset_fsb = irec.br_startoff + ilen; + } + + error = xfs_trans_commit(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + if (error) + goto out; + return 0; + +out_defer: + xfs_defer_cancel(&dfops); +out_cancel: + xfs_trans_cancel(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); +out: + trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index a2a23f5..27ae6c0 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -28,4 +28,12 @@ extern int xfs_reflink_find_cow_mapping(struct xfs_inode *ip, xfs_off_t offset, extern int xfs_reflink_trim_irec_to_next_cow(struct xfs_inode *ip, xfs_fileoff_t offset_fsb, struct xfs_bmbt_irec *imap); +extern int xfs_reflink_cancel_cow_blocks(struct xfs_inode *ip, + struct xfs_trans **tpp, xfs_fileoff_t offset_fsb, + xfs_fileoff_t end_fsb); +extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset, + xfs_off_t count); +extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, + xfs_off_t count); + #endif /* __XFS_REFLINK_H */ From darrick.wong@oracle.com Thu Jun 16 20:26:58 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 98C047E23 for ; Thu, 16 Jun 2016 20:26:58 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5C7EC304039 for ; Thu, 16 Jun 2016 18:26:58 -0700 (PDT) X-ASG-Debug-ID: 1466126815-04cbb01fef69900001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id N5z9I6S1nBUX0qtR (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:26:55 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1QrlW010631 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:53 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Qrwq019387 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:26:53 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QqW0025172; Fri, 17 Jun 2016 01:26:52 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:52 -0700 Subject: [PATCH 084/119] xfs: implement CoW for directio writes From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 084/119] xfs: implement CoW for directio writes To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:50 -0700 Message-ID: <146612681049.12839.2763550972204033113.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126815 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11699 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines For O_DIRECT writes to shared blocks, we have to CoW them just like we would with buffered writes. For writes that are not block-aligned, just bounce them to the page cache. For block-aligned writes, however, we can do better than that. Use the same mechanisms that we employ for buffered CoW to set up a delalloc reservation, allocate all the blocks at once, issue the writes against the new blocks and use the same ioend functions to remap the blocks after the write. This should be fairly performant. v2: Turns out that there's no way for xfs_end_io_direct_write to know if the write completed successfully. Therefore, do /not/ use the ioend for dio cow post-processing; instead, move it to xfs_vm_do_dio where we *can* tell if the write succeeded or not. v3: Update the file size if we do a directio CoW across EOF. This can happen if the last block is shared, the cowextsize hint is set, and we do a dio write past the end of the file. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_aops.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++--- fs/xfs/xfs_file.c | 12 ++++- fs/xfs/xfs_reflink.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 5 ++ 4 files changed, 225 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 232039c..31318b3 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -40,6 +40,7 @@ /* flags for direct write completions */ #define XFS_DIO_FLAG_UNWRITTEN (1 << 0) #define XFS_DIO_FLAG_APPEND (1 << 1) +#define XFS_DIO_FLAG_COW (1 << 2) /* * structure owned by writepages passed to individual writepage calls @@ -1130,18 +1131,24 @@ xfs_map_direct( struct inode *inode, struct buffer_head *bh_result, struct xfs_bmbt_irec *imap, - xfs_off_t offset) + xfs_off_t offset, + bool is_cow) { uintptr_t *flags = (uintptr_t *)&bh_result->b_private; xfs_off_t size = bh_result->b_size; trace_xfs_get_blocks_map_direct(XFS_I(inode), offset, size, - ISUNWRITTEN(imap) ? XFS_IO_UNWRITTEN : XFS_IO_OVERWRITE, imap); + ISUNWRITTEN(imap) ? XFS_IO_UNWRITTEN : is_cow ? XFS_IO_COW : + XFS_IO_OVERWRITE, imap); if (ISUNWRITTEN(imap)) { *flags |= XFS_DIO_FLAG_UNWRITTEN; set_buffer_defer_completion(bh_result); - } else if (offset + size > i_size_read(inode) || offset + size < 0) { + } else if (is_cow) { + *flags |= XFS_DIO_FLAG_COW; + set_buffer_defer_completion(bh_result); + } + if (offset + size > i_size_read(inode) || offset + size < 0) { *flags |= XFS_DIO_FLAG_APPEND; set_buffer_defer_completion(bh_result); } @@ -1187,6 +1194,43 @@ xfs_map_trim_size( bh_result->b_size = mapping_size; } +/* Bounce unaligned directio writes to the page cache. */ +static int +xfs_bounce_unaligned_dio_write( + struct xfs_inode *ip, + xfs_fileoff_t offset_fsb, + struct xfs_bmbt_irec *imap) +{ + bool shared; + struct xfs_bmbt_irec irec; + xfs_fileoff_t delta; + int error; + + irec = *imap; + if (offset_fsb > irec.br_startoff) { + delta = offset_fsb - irec.br_startoff; + irec.br_blockcount -= delta; + irec.br_startblock += delta; + irec.br_startoff = offset_fsb; + } + error = xfs_reflink_irec_is_shared(ip, &irec, &shared); + if (error) + return error; + /* + * Are we doing a DIO write to a shared block? In + * the ideal world we at least would fork full blocks, + * but for now just fall back to buffered mode. Yuck. + * Use -EREMCHG ("remote address changed") to signal + * this, since in general XFS doesn't do this sort of + * fallback. + */ + if (shared) { + trace_xfs_reflink_bounce_dio_write(ip, imap); + return -EREMCHG; + } + return 0; +} + STATIC int __xfs_get_blocks( struct inode *inode, @@ -1206,6 +1250,8 @@ __xfs_get_blocks( xfs_off_t offset; ssize_t size; int new = 0; + bool is_cow = false; + bool need_alloc = false; if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; @@ -1237,8 +1283,27 @@ __xfs_get_blocks( end_fsb = XFS_B_TO_FSB(mp, (xfs_ufsize_t)offset + size); offset_fsb = XFS_B_TO_FSBT(mp, offset); - error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, - &imap, &nimaps, XFS_BMAPI_ENTIRE); + if (create && direct) + is_cow = xfs_reflink_is_cow_pending(ip, offset); + if (is_cow) + error = xfs_reflink_find_cow_mapping(ip, offset, &imap, + &need_alloc); + else { + error = xfs_bmapi_read(ip, offset_fsb, end_fsb - offset_fsb, + &imap, &nimaps, XFS_BMAPI_ENTIRE); + /* + * Truncate an overwrite extent if there's a pending CoW + * reservation before the end of this extent. This forces us + * to come back to writepage to take care of the CoW. + */ + if (create && direct && nimaps && + imap.br_startblock != HOLESTARTBLOCK && + imap.br_startblock != DELAYSTARTBLOCK && + !ISUNWRITTEN(&imap)) + xfs_reflink_trim_irec_to_next_cow(ip, offset_fsb, + &imap); + } + ASSERT(!need_alloc); if (error) goto out_unlock; @@ -1310,6 +1375,13 @@ __xfs_get_blocks( if (imap.br_startblock != HOLESTARTBLOCK && imap.br_startblock != DELAYSTARTBLOCK && (create || !ISUNWRITTEN(&imap))) { + if (create && direct && !is_cow) { + error = xfs_bounce_unaligned_dio_write(ip, offset_fsb, + &imap); + if (error) + return error; + } + xfs_map_buffer(inode, bh_result, &imap, offset); if (ISUNWRITTEN(&imap)) set_buffer_unwritten(bh_result); @@ -1318,7 +1390,8 @@ __xfs_get_blocks( if (dax_fault) ASSERT(!ISUNWRITTEN(&imap)); else - xfs_map_direct(inode, bh_result, &imap, offset); + xfs_map_direct(inode, bh_result, &imap, offset, + is_cow); } } @@ -1452,7 +1525,11 @@ xfs_end_io_direct_write( trace_xfs_end_io_direct_write_unwritten(ip, offset, size); error = xfs_iomap_write_unwritten(ip, offset, size); - } else if (flags & XFS_DIO_FLAG_APPEND) { + } + if (flags & XFS_DIO_FLAG_COW) { + error = xfs_reflink_end_cow(ip, offset, size); + } + if (flags & XFS_DIO_FLAG_APPEND) { struct xfs_trans *tp; trace_xfs_end_io_direct_write_append(ip, offset, size); @@ -1475,6 +1552,27 @@ xfs_vm_direct_IO( dio_iodone_t *endio = NULL; int flags = 0; struct block_device *bdev; + loff_t end; + loff_t block_mask; + bool dio_cow = false; + int error; + + /* If this is a block-aligned directio CoW, remap immediately. */ + end = iocb->ki_pos + iov_iter_count(iter); + block_mask = (1 << inode->i_blkbits) - 1; + if (iov_iter_rw(iter) == WRITE && + xfs_is_reflink_inode(XFS_I(inode)) && + !((iocb->ki_pos | end) & block_mask)) { + dio_cow = true; + error = xfs_reflink_reserve_cow_range(XFS_I(inode), + iocb->ki_pos, iov_iter_count(iter)); + if (error) + return error; + error = xfs_reflink_allocate_cow_range(XFS_I(inode), + iocb->ki_pos, iov_iter_count(iter)); + if (error) + return error; + } if (iov_iter_rw(iter) == WRITE) { endio = xfs_end_io_direct_write; diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 148d0b3..b979f01 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -896,10 +896,18 @@ xfs_file_write_iter( if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return -EIO; - if ((iocb->ki_flags & IOCB_DIRECT) || IS_DAX(inode)) + /* + * Allow DIO to fall back to buffered *only* in the case that we're + * doing a reflink CoW. + */ + if ((iocb->ki_flags & IOCB_DIRECT) || IS_DAX(inode)) { ret = xfs_file_dio_aio_write(iocb, from); - else + if (ret == -EREMCHG) + goto buffered; + } else { +buffered: ret = xfs_file_buffered_aio_write(iocb, from); + } if (ret > 0) { XFS_STATS_ADD(ip->i_mount, xs_write_bytes, ret); diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 59c8e86..113f333 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -146,6 +146,51 @@ xfs_trim_extent( } } +/* + * Determine if any of the blocks in this mapping are shared. + */ +int +xfs_reflink_irec_is_shared( + struct xfs_inode *ip, + struct xfs_bmbt_irec *irec, + bool *shared) +{ + xfs_agnumber_t agno; + xfs_agblock_t agbno; + xfs_extlen_t aglen; + xfs_agblock_t fbno; + xfs_extlen_t flen; + int error = 0; + + /* Holes, unwritten, and delalloc extents cannot be shared */ + if (!xfs_is_reflink_inode(ip) || + ISUNWRITTEN(irec) || + irec->br_startblock == HOLESTARTBLOCK || + irec->br_startblock == DELAYSTARTBLOCK) { + *shared = false; + return 0; + } + + trace_xfs_reflink_irec_is_shared(ip, irec); + + agno = XFS_FSB_TO_AGNO(ip->i_mount, irec->br_startblock); + agbno = XFS_FSB_TO_AGBNO(ip->i_mount, irec->br_startblock); + aglen = irec->br_blockcount; + + /* Are there any shared blocks here? */ + error = xfs_refcount_find_shared(ip->i_mount, agno, agbno, + aglen, &fbno, &flen, false); + if (error) + return error; + if (flen == 0) { + *shared = false; + return 0; + } + + *shared = true; + return 0; +} + /* Find the shared ranges under an irec, and set up delalloc extents. */ static int xfs_reflink_reserve_cow_extent( @@ -273,6 +318,66 @@ xfs_reflink_reserve_cow_range( } /* + * Allocate blocks to all CoW reservations within a byte range of a file. + */ +int +xfs_reflink_allocate_cow_range( + struct xfs_inode *ip, + xfs_off_t pos, + xfs_off_t len) +{ + struct xfs_ifork *ifp; + struct xfs_bmbt_rec_host *gotp; + struct xfs_bmbt_irec imap; + int error = 0; + xfs_fileoff_t start_lblk; + xfs_fileoff_t end_lblk; + xfs_extnum_t idx; + + if (!xfs_is_reflink_inode(ip)) + return 0; + + trace_xfs_reflink_allocate_cow_range(ip, len, pos, 0); + + start_lblk = XFS_B_TO_FSBT(ip->i_mount, pos); + end_lblk = XFS_B_TO_FSB(ip->i_mount, pos + len); + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + xfs_ilock(ip, XFS_ILOCK_EXCL); + + gotp = xfs_iext_bno_to_ext(ifp, start_lblk, &idx); + while (gotp) { + xfs_bmbt_get_all(gotp, &imap); + + if (imap.br_startoff >= end_lblk) + break; + if (!isnullstartblock(imap.br_startblock)) + goto advloop; + xfs_trim_extent(&imap, start_lblk, end_lblk - start_lblk); + trace_xfs_reflink_allocate_cow_extent(ip, &imap); + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + error = xfs_iomap_write_allocate(ip, XFS_COW_FORK, + XFS_FSB_TO_B(ip->i_mount, imap.br_startoff + + imap.br_blockcount - 1), &imap); + xfs_ilock(ip, XFS_ILOCK_EXCL); + if (error) + break; +advloop: + /* Roll on... */ + idx++; + if (idx >= ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) + break; + gotp = xfs_iext_get_ext(ifp, idx); + } + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + if (error) + trace_xfs_reflink_allocate_cow_range_error(ip, error, _RET_IP_); + return error; +} + +/* * Determine if there's a CoW reservation at a byte offset of an inode. */ bool diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 27ae6c0..fb128dd 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -20,8 +20,13 @@ #ifndef __XFS_REFLINK_H #define __XFS_REFLINK_H 1 +extern int xfs_reflink_irec_is_shared(struct xfs_inode *ip, + struct xfs_bmbt_irec *imap, bool *shared); + extern int xfs_reflink_reserve_cow_range(struct xfs_inode *ip, xfs_off_t pos, xfs_off_t len); +extern int xfs_reflink_allocate_cow_range(struct xfs_inode *ip, xfs_off_t pos, + xfs_off_t len); extern bool xfs_reflink_is_cow_pending(struct xfs_inode *ip, xfs_off_t offset); extern int xfs_reflink_find_cow_mapping(struct xfs_inode *ip, xfs_off_t offset, struct xfs_bmbt_irec *imap, bool *need_alloc); From darrick.wong@oracle.com Thu Jun 16 20:27:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D900E7E23 for ; Thu, 16 Jun 2016 20:27:07 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 975F8304048 for ; Thu, 16 Jun 2016 18:27:07 -0700 (PDT) X-ASG-Debug-ID: 1466126825-04bdf01e1795c20001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ejw0LLDXK1sCjLZm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:05 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1R1pw030010 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:27:02 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1R1ZR018218 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:01 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1QwZb008541; Fri, 17 Jun 2016 01:26:59 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:26:58 -0700 Subject: [PATCH 085/119] xfs: copy-on-write reflinked blocks when zeroing ranges of blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 085/119] xfs: copy-on-write reflinked blocks when zeroing ranges of blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:26:56 -0700 Message-ID: <146612681688.12839.10527590239958274522.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126825 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4174 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we're writing zeroes to a reflinked block (such as when we're punching a reflinked range), we need to fork the the block and write to that, otherwise we can corrupt the other reflinks. v2: Only call the end_cow functions if we had set should_fork, and release the buffer if xfs_map_cow_blocks fails. Signed-off-by: Darrick J. Wong [hch@lst.de: Only call the end_cow functions if we had set should_fork] Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_aops.c | 12 ++++++++++++ fs/xfs/xfs_bmap_util.c | 38 ++++++++++++++++++++++++++++++++++++-- fs/xfs/xfs_reflink.h | 4 ++++ 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 31318b3..812bae5 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -394,6 +394,18 @@ xfs_map_blocks( return 0; } +/* + * Find a CoW mapping and ensure that blocks have been allocated to it. + */ +int +xfs_map_cow_blocks( + struct inode *inode, + xfs_off_t offset, + struct xfs_bmbt_irec *imap) +{ + return xfs_map_blocks(inode, offset, imap, XFS_IO_COW); +} + STATIC bool xfs_imap_valid( struct inode *inode, diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 8666873..79225fb 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -42,6 +42,8 @@ #include "xfs_icache.h" #include "xfs_log.h" #include "xfs_rmap_btree.h" +#include "xfs_iomap.h" +#include "xfs_reflink.h" /* Kernel only BMAP related definitions and functions */ @@ -1042,7 +1044,8 @@ xfs_zero_remaining_bytes( xfs_buf_t *bp; xfs_mount_t *mp = ip->i_mount; int nimap; - int error = 0; + int error = 0, err2; + bool should_fork = false; /* * Avoid doing I/O beyond eof - it's not necessary @@ -1055,6 +1058,11 @@ xfs_zero_remaining_bytes( if (endoff > XFS_ISIZE(ip)) endoff = XFS_ISIZE(ip); + error = xfs_reflink_reserve_cow_range(ip, startoff, + endoff - startoff + 1); + if (error) + return error; + for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { uint lock_mode; @@ -1063,6 +1071,10 @@ xfs_zero_remaining_bytes( lock_mode = xfs_ilock_data_map_shared(ip); error = xfs_bmapi_read(ip, offset_fsb, 1, &imap, &nimap, 0); + + /* Do we need to CoW this block? */ + if (error == 0 && nimap == 1) + should_fork = xfs_reflink_is_cow_pending(ip, offset); xfs_iunlock(ip, lock_mode); if (error || nimap < 1) @@ -1084,7 +1096,7 @@ xfs_zero_remaining_bytes( lastoffset = endoff; /* DAX can just zero the backing device directly */ - if (IS_DAX(VFS_I(ip))) { + if (IS_DAX(VFS_I(ip)) && !should_fork) { error = dax_zero_page_range(VFS_I(ip), offset, lastoffset - offset + 1, xfs_get_blocks_direct); @@ -1105,8 +1117,30 @@ xfs_zero_remaining_bytes( (offset - XFS_FSB_TO_B(mp, imap.br_startoff)), 0, lastoffset - offset + 1); + if (should_fork) { + xfs_fsblock_t new_fsbno; + + error = xfs_map_cow_blocks(VFS_I(ip), offset, &imap); + if (error) { + xfs_buf_relse(bp); + return error; + } + new_fsbno = imap.br_startblock + + (offset_fsb - imap.br_startoff); + XFS_BUF_SET_ADDR(bp, XFS_FSB_TO_DADDR(mp, new_fsbno)); + } + error = xfs_bwrite(bp); xfs_buf_relse(bp); + if (should_fork) { + if (error) { + err2 = xfs_reflink_cancel_cow_range(ip, offset, + lastoffset - offset + 1); + return error; + } + error = xfs_reflink_end_cow(ip, offset, + lastoffset - offset + 1); + } if (error) return error; } diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index fb128dd..2f3c829 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -41,4 +41,8 @@ extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset, extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t count); +/* xfs_aops.c */ +extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, + struct xfs_bmbt_irec *imap); + #endif /* __XFS_REFLINK_H */ From darrick.wong@oracle.com Thu Jun 16 20:27:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 25D517EA6 for ; Thu, 16 Jun 2016 20:27:10 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id DD09F8F8050 for ; Thu, 16 Jun 2016 18:27:09 -0700 (PDT) X-ASG-Debug-ID: 1466126828-04cb6c542757a70001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 1a0mxo4KXdgcm6VU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:08 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1R6Mq030281 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:06 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1R5e3024326 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:06 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1R5iZ025213; Fri, 17 Jun 2016 01:27:05 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:04 -0700 Subject: [PATCH 086/119] xfs: cancel CoW reservations and clear inode reflink flag when freeing blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 086/119] xfs: cancel CoW reservations and clear inode reflink flag when freeing blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:03 -0700 Message-ID: <146612682326.12839.16807060939543436332.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126828 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2485 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we're freeing blocks (truncate, punch, etc.), clear all CoW reservations in the range being freed. If the file block count drops to zero, also clear the inode reflink flag. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_bmap_util.c | 34 ++++++++++++++++++++++++++++++++++ fs/xfs/xfs_inode.c | 13 +++++++++++++ 2 files changed, 47 insertions(+) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 79225fb..9285111 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1147,6 +1147,32 @@ xfs_zero_remaining_bytes( return error; } +STATIC int +xfs_free_cow_space( + struct xfs_inode *ip, + struct xfs_trans **tpp, + xfs_fileoff_t startoffset_fsb, + xfs_fileoff_t endoffset_fsb) +{ + int error; + + /* Remove any pending CoW reservations. */ + error = xfs_reflink_cancel_cow_blocks(ip, tpp, startoffset_fsb, + endoffset_fsb); + if (error) + goto out; + + /* + * Clear the reflink flag if we freed everything. + */ + if (ip->i_d.di_nblocks == 0) { + ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); + } +out: + return error; +} + int xfs_free_file_space( struct xfs_inode *ip, @@ -1294,6 +1320,14 @@ xfs_free_file_space( if (error) goto error0; + /* Remove CoW reservations and inode flag if applicable. */ + if (done && xfs_is_reflink_inode(ip)) { + error = xfs_free_cow_space(ip, &tp, startoffset_fsb, + endoffset_fsb); + if (error) + goto error0; + } + error = xfs_trans_commit(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); } diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index e08eaea..b8d3c4f 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -49,6 +49,7 @@ #include "xfs_trans_priv.h" #include "xfs_log.h" #include "xfs_bmap_btree.h" +#include "xfs_reflink.h" kmem_zone_t *xfs_inode_zone; @@ -1586,6 +1587,18 @@ xfs_itruncate_extents( goto out; } + /* Remove all pending CoW reservations. */ + error = xfs_reflink_cancel_cow_blocks(ip, &tp, first_unmap_block, + last_block); + if (error) + goto out; + + /* + * Clear the reflink flag if we truncated everything. + */ + if (ip->i_d.di_nblocks == 0 && xfs_is_reflink_inode(ip)) + ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + /* * Always re-log the inode so that our permanent transaction can keep * on rolling it forward in the log. From darrick.wong@oracle.com Thu Jun 16 20:27:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E9ED17E8D for ; Thu, 16 Jun 2016 20:27:17 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 9B33B30404E for ; Thu, 16 Jun 2016 18:27:17 -0700 (PDT) X-ASG-Debug-ID: 1466126835-04bdf01e1095c20001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 9GnQd4P8hfHAjioc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:16 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1RDhc011187 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:14 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RDFp024482 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:13 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RBDL008595; Fri, 17 Jun 2016 01:27:12 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:11 -0700 Subject: [PATCH 087/119] xfs: cancel pending CoW reservations when destroying inodes From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 087/119] xfs: cancel pending CoW reservations when destroying inodes To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:09 -0700 Message-ID: <146612682953.12839.449371855172899748.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126836 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1308 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When destroying the inode, cancel all pending reservations in the CoW fork so that all the reserved blocks go back to the free pile. In theory this sort of cleanup is only needed to clean up after write errors. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_super.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 18f74b3..09f9af7 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -50,6 +50,7 @@ #include "xfs_rmap_item.h" #include "xfs_refcount_item.h" #include "xfs_bmap_item.h" +#include "xfs_reflink.h" #include #include @@ -939,6 +940,7 @@ xfs_fs_destroy_inode( struct inode *inode) { struct xfs_inode *ip = XFS_I(inode); + int error; trace_xfs_destroy_inode(ip); @@ -946,6 +948,12 @@ xfs_fs_destroy_inode( XFS_STATS_INC(ip->i_mount, vn_rele); XFS_STATS_INC(ip->i_mount, vn_remove); + error = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF); + if (error && !XFS_FORCED_SHUTDOWN(ip->i_mount)) + xfs_warn(ip->i_mount, "Error %d while evicting CoW blocks " + "for inode %llu.", + error, ip->i_ino); + xfs_inactive(ip); ASSERT(XFS_FORCED_SHUTDOWN(ip->i_mount) || ip->i_delayed_blks == 0); From darrick.wong@oracle.com Thu Jun 16 20:27:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D98657EB0 for ; Thu, 16 Jun 2016 20:27:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9C1828F804C for ; Thu, 16 Jun 2016 18:27:27 -0700 (PDT) X-ASG-Debug-ID: 1466126843-04cb6c542557a90001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id q6zzGuVMFWL4qXHA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:23 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1RL1n011224 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:21 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RKvr024611 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:21 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RK8N025336; Fri, 17 Jun 2016 01:27:20 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:19 -0700 Subject: [PATCH 088/119] xfs: store in-progress CoW allocations in the refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 088/119] xfs: store in-progress CoW allocations in the refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:15 -0700 Message-ID: <146612683577.12839.112247431798278299.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126843 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 24545 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Due to the way the CoW algorithm in XFS works, there's an interval during which blocks allocated to handle a CoW can be lost -- if the FS goes down after the blocks are allocated but before the block remapping takes place. This is exacerbated by the cowextsz hint -- allocated reservations can sit around for a while, waiting to get used. Since the refcount btree doesn't normally store records with refcount of 1, we can use it to record these in-progress extents. In-progress blocks cannot be shared because they're not user-visible, so there shouldn't be any conflicts with other programs. This is a better solution than holding EFIs during writeback because (a) EFIs can't be relogged currently, (b) even if they could, EFIs are bound by available log space, which puts an unnecessary upper bound on how much CoW we can have in flight, and (c) we already have a mechanism to track blocks. At mount time, read the refcount records and free anything we find with a refcount of 1 because those were in-progress when the FS went down. v2: Use the deferred operations system to avoid deadlocks and blowing out the transaction reservation. This allows us to unmap a CoW extent from the refcountbt and into a file atomically. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 11 + fs/xfs/libxfs/xfs_format.h | 3 fs/xfs/libxfs/xfs_refcount.c | 321 +++++++++++++++++++++++++++++++++++++++++- fs/xfs/libxfs/xfs_refcount.h | 7 + fs/xfs/xfs_log_recover.c | 12 ++ fs/xfs/xfs_mount.c | 7 + fs/xfs/xfs_reflink.c | 144 +++++++++++++++++++ fs/xfs/xfs_reflink.h | 2 fs/xfs/xfs_super.c | 6 + fs/xfs/xfs_trace.h | 4 + 10 files changed, 511 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 2ba513b..0909532 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -4705,6 +4705,17 @@ xfs_bmapi_write( goto error0; if (bma.blkno == NULLFSBLOCK) break; + + /* + * If this is a CoW allocation, record the data in + * the refcount btree for orphan recovery. + */ + if (whichfork == XFS_COW_FORK) { + error = xfs_refcount_alloc_cow_extent(mp, dfops, + bma.blkno, bma.length); + if (error) + goto error0; + } } /* Deal with the allocated space we found. */ diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 45bbdad..3d336e9 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1401,7 +1401,8 @@ xfs_rmap_ino_owner( #define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */ #define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ #define XFS_RMAP_OWN_REFC (-8ULL) /* refcount tree */ -#define XFS_RMAP_OWN_MIN (-9ULL) /* guard */ +#define XFS_RMAP_OWN_COW (-9ULL) /* cow allocations */ +#define XFS_RMAP_OWN_MIN (-10ULL) /* guard */ #define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63))) diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index ebbb714..88f91d5 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -36,13 +36,23 @@ #include "xfs_trans.h" #include "xfs_bit.h" #include "xfs_refcount.h" +#include "xfs_rmap_btree.h" /* Allowable refcount adjustment amounts. */ enum xfs_refc_adjust_op { XFS_REFCOUNT_ADJUST_INCREASE = 1, XFS_REFCOUNT_ADJUST_DECREASE = -1, + XFS_REFCOUNT_ADJUST_COW_ALLOC = 0, + XFS_REFCOUNT_ADJUST_COW_FREE = -1, }; +STATIC int __xfs_refcount_cow_alloc(struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, xfs_extlen_t aglen, + struct xfs_defer_ops *dfops); +STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, xfs_extlen_t aglen, + struct xfs_defer_ops *dfops); + /* * Look up the first record less than or equal to [bno, len] in the btree * given by cur. @@ -468,6 +478,8 @@ out_error: return error; } +#define XFS_FIND_RCEXT_SHARED 1 +#define XFS_FIND_RCEXT_COW 2 /* * Find the left extent and the one after it (cleft). This function assumes * that we've already split any extent crossing agbno. @@ -478,7 +490,8 @@ xfs_refcount_find_left_extents( struct xfs_refcount_irec *left, struct xfs_refcount_irec *cleft, xfs_agblock_t agbno, - xfs_extlen_t aglen) + xfs_extlen_t aglen, + int flags) { struct xfs_refcount_irec tmp; int error; @@ -498,6 +511,10 @@ xfs_refcount_find_left_extents( if (RCNEXT(tmp) != agbno) return 0; + if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2) + return 0; + if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1) + return 0; /* We have a left extent; retrieve (or invent) the next right one */ *left = tmp; @@ -554,7 +571,8 @@ xfs_refcount_find_right_extents( struct xfs_refcount_irec *right, struct xfs_refcount_irec *cright, xfs_agblock_t agbno, - xfs_extlen_t aglen) + xfs_extlen_t aglen, + int flags) { struct xfs_refcount_irec tmp; int error; @@ -574,6 +592,10 @@ xfs_refcount_find_right_extents( if (tmp.rc_startblock != agbno + aglen) return 0; + if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2) + return 0; + if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1) + return 0; /* We have a right extent; retrieve (or invent) the next left one */ *right = tmp; @@ -630,6 +652,7 @@ xfs_refcount_merge_extents( xfs_agblock_t *agbno, xfs_extlen_t *aglen, enum xfs_refc_adjust_op adjust, + int flags, bool *shape_changed) { struct xfs_refcount_irec left = {0}, cleft = {0}; @@ -645,11 +668,11 @@ xfs_refcount_merge_extents( * [right]. */ error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno, - *aglen); + *aglen, flags); if (error) return error; error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno, - *aglen); + *aglen, flags); if (error) return error; @@ -936,7 +959,7 @@ xfs_refcount_adjust( */ orig_aglen = aglen; error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj, - &shape_changed); + XFS_FIND_RCEXT_SHARED, &shape_changed); if (error) goto out_error; if (shape_changed) @@ -1053,6 +1076,18 @@ xfs_refcount_finish_one( error = xfs_refcount_adjust(rcur, bno, blockcount, adjusted, XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL); break; + case XFS_REFCOUNT_ALLOC_COW: + *adjusted = 0; + error = __xfs_refcount_cow_alloc(rcur, bno, blockcount, dfops); + if (!error) + *adjusted = blockcount; + break; + case XFS_REFCOUNT_FREE_COW: + *adjusted = 0; + error = __xfs_refcount_cow_free(rcur, bno, blockcount, dfops); + if (!error) + *adjusted = blockcount; + break; default: ASSERT(0); error = -EFSCORRUPTED; @@ -1238,3 +1273,279 @@ out: trace_xfs_refcount_find_shared_error(mp, agno, error, _RET_IP_); return error; } + +/* + * Recovering CoW Blocks After a Crash + * + * Due to the way that the copy on write mechanism works, there's a window of + * opportunity in which we can lose track of allocated blocks during a crash. + * Because CoW uses delayed allocation in the in-core CoW fork, writeback + * causes blocks to be allocated and stored in the CoW fork. The blocks are + * no longer in the free space btree but are not otherwise recorded anywhere + * until the write completes and the blocks are mapped into the file. A crash + * in between allocation and remapping results in the replacement blocks being + * lost. This situation is exacerbated by the CoW extent size hint because + * allocations can hang around for long time. + * + * However, there is a place where we can record these allocations before they + * become mappings -- the reference count btree. The btree does not record + * extents with refcount == 1, so we can record allocations with a refcount of + * 1. Blocks being used for CoW writeout cannot be shared, so there should be + * no conflict with shared block records. These mappings should be created + * when we allocate blocks to the CoW fork and deleted when they're removed + * from the CoW fork. + * + * Minor nit: records for in-progress CoW allocations and records for shared + * extents must never be merged, to preserve the property that (except for CoW + * allocations) there are no refcount btree entries with refcount == 1. The + * only time this could potentially happen is when unsharing a block that's + * adjacent to CoW allocations, so we must be careful to avoid this. + * + * At mount time we recover lost CoW allocations by searching the refcount + * btree for these refcount == 1 mappings. These represent CoW allocations + * that were in progress at the time the filesystem went down, so we can free + * them to get the space back. + * + * This mechanism is superior to creating EFIs for unmapped CoW extents for + * several reasons -- first, EFIs pin the tail of the log and would have to be + * periodically relogged to avoid filling up the log. Second, CoW completions + * will have to file an EFD and create new EFIs for whatever remains in the + * CoW fork; this partially takes care of (1) but extent-size reservations + * will have to periodically relog even if there's no writeout in progress. + * This can happen if the CoW extent size hint is set, which you really want. + * Third, EFIs cannot currently be automatically relogged into newer + * transactions to advance the log tail. Fourth, stuffing the log full of + * EFIs places an upper bound on the number of CoW allocations that can be + * held filesystem-wide at any given time. Recording them in the refcount + * btree doesn't require us to maintain any state in memory and doesn't pin + * the log. + */ +/* + * Adjust the refcounts of CoW allocations. These allocations are "magic" + * in that they're not referenced anywhere else in the filesystem, so we + * stash them in the refcount btree with a refcount of 1 until either file + * remapping (or CoW cancellation) happens. + */ +STATIC int +xfs_refcount_adjust_cow_extents( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops, + struct xfs_owner_info *oinfo) +{ + struct xfs_refcount_irec ext, tmp; + int error; + int found_rec, found_tmp; + + if (aglen == 0) + return 0; + + /* Find any overlapping refcount records */ + error = xfs_refcountbt_lookup_ge(cur, agbno, &found_rec); + if (error) + goto out_error; + error = xfs_refcountbt_get_rec(cur, &ext, &found_rec); + if (error) + goto out_error; + if (!found_rec) { + ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks; + ext.rc_blockcount = 0; + ext.rc_refcount = 0; + } + + switch (adj) { + case XFS_REFCOUNT_ADJUST_COW_ALLOC: + /* Adding a CoW reservation, there should be nothing here. */ + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_startblock >= agbno + aglen, out_error); + + tmp.rc_startblock = agbno; + tmp.rc_blockcount = aglen; + tmp.rc_refcount = 1; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &tmp); + + error = xfs_refcountbt_insert(cur, &tmp, + &found_tmp); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_tmp == 1, out_error); + break; + case XFS_REFCOUNT_ADJUST_COW_FREE: + /* Removing a CoW reservation, there should be one extent. */ + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_startblock == agbno, out_error); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_blockcount == aglen, out_error); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_refcount == 1, out_error); + + ext.rc_refcount = 0; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &ext); + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_rec == 1, out_error); + break; + default: + ASSERT(0); + } + + return error; +out_error: + trace_xfs_refcount_modify_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Add or remove refcount btree entries for CoW reservations. + */ +STATIC int +xfs_refcount_adjust_cow( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops) +{ + bool shape_changed; + int error; + + /* + * Ensure that no rcextents cross the boundary of the adjustment range. + */ + error = xfs_refcount_split_extent(cur, agbno, &shape_changed); + if (error) + goto out_error; + + error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed); + if (error) + goto out_error; + + /* + * Try to merge with the left or right extents of the range. + */ + error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj, + XFS_FIND_RCEXT_COW, &shape_changed); + if (error) + goto out_error; + + /* Now that we've taken care of the ends, adjust the middle extents */ + error = xfs_refcount_adjust_cow_extents(cur, agbno, aglen, adj, + dfops, NULL); + if (error) + goto out_error; + + return 0; + +out_error: + trace_xfs_refcount_adjust_cow_error(cur->bc_mp, cur->bc_private.a.agno, + error, _RET_IP_); + return error; +} + +/* + * Record a CoW allocation in the refcount btree. + */ +STATIC int +__xfs_refcount_cow_alloc( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + struct xfs_defer_ops *dfops) +{ + int error; + + trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_private.a.agno, + agbno, aglen); + + /* Add refcount btree reservation */ + error = xfs_refcount_adjust_cow(rcur, agbno, aglen, + XFS_REFCOUNT_ADJUST_COW_ALLOC, dfops); + if (error) + return error; + + /* Add rmap entry */ + if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { + error = xfs_rmap_alloc_defer(rcur->bc_mp, dfops, + rcur->bc_private.a.agno, + agbno, aglen, XFS_RMAP_OWN_COW); + if (error) + return error; + } + + return error; +} + +/* + * Remove a CoW allocation from the refcount btree. + */ +STATIC int +__xfs_refcount_cow_free( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + struct xfs_defer_ops *dfops) +{ + int error; + + trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_private.a.agno, + agbno, aglen); + + /* Remove refcount btree reservation */ + error = xfs_refcount_adjust_cow(rcur, agbno, aglen, + XFS_REFCOUNT_ADJUST_COW_FREE, dfops); + if (error) + return error; + + /* Remove rmap entry */ + if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { + error = xfs_rmap_free_defer(rcur->bc_mp, dfops, + rcur->bc_private.a.agno, + agbno, aglen, XFS_RMAP_OWN_COW); + if (error) + return error; + } + + return error; +} + +/* Record a CoW staging extent in the refcount btree. */ +int +xfs_refcount_alloc_cow_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_fsblock_t fsb, + xfs_extlen_t len) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_ALLOC_COW; + ri.ri_startblock = fsb; + ri.ri_blockcount = len; + + return __xfs_refcount_add(mp, dfops, &ri); +} + +/* Forget a CoW staging event in the refcount btree. */ +int +xfs_refcount_free_cow_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_fsblock_t fsb, + xfs_extlen_t len) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_FREE_COW; + ri.ri_startblock = fsb; + ri.ri_blockcount = len; + + return __xfs_refcount_add(mp, dfops, &ri); +} diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index b7b83b8..6665eeb 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -57,4 +57,11 @@ extern int xfs_refcount_find_shared(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_maximal); +extern int xfs_refcount_alloc_cow_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, + xfs_extlen_t len); +extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, + xfs_extlen_t len); + #endif /* __XFS_REFCOUNT_H__ */ diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 3faaf10..58a700b 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -5040,6 +5040,18 @@ xlog_recover_process_cui( error = xfs_refcount_decrease_extent( tp->t_mountp, &dfops, &irec); break; + case XFS_REFCOUNT_ALLOC_COW: + error = xfs_refcount_alloc_cow_extent( + tp->t_mountp, &dfops, + irec.br_startblock, + irec.br_blockcount); + break; + case XFS_REFCOUNT_FREE_COW: + error = xfs_refcount_free_cow_extent( + tp->t_mountp, &dfops, + irec.br_startblock, + irec.br_blockcount); + break; default: ASSERT(0); } diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 48b8b1e..6351dce 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -44,6 +44,7 @@ #include "xfs_sysfs.h" #include "xfs_rmap_btree.h" #include "xfs_refcount_btree.h" +#include "xfs_reflink.h" static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -960,6 +961,12 @@ xfs_mountfs( if (error) xfs_warn(mp, "Unable to allocate reserve blocks. Continuing without reserve pool."); + + /* Recover any CoW blocks that never got remapped. */ + error = xfs_reflink_recover_cow(mp); + if (error && !XFS_FORCED_SHUTDOWN(mp)) + xfs_err(mp, + "Error %d recovering leftover CoW allocations.", error); } return 0; diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 113f333..0f9cc82 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -534,6 +534,13 @@ xfs_reflink_cancel_cow_blocks( xfs_trans_ijoin(*tpp, ip, 0); xfs_defer_init(&dfops, &firstfsb); + /* Free the CoW orphan record. */ + error = xfs_refcount_free_cow_extent(ip->i_mount, + &dfops, irec.br_startblock, + irec.br_blockcount); + if (error) + break; + xfs_bmap_add_free(ip->i_mount, &dfops, irec.br_startblock, irec.br_blockcount, NULL); @@ -694,6 +701,13 @@ xfs_reflink_end_cow( irec.br_blockcount = rlen; trace_xfs_reflink_cow_remap_piece(ip, &uirec); + /* Free the CoW orphan record. */ + error = xfs_refcount_free_cow_extent(tp->t_mountp, + &dfops, uirec.br_startblock, + uirec.br_blockcount); + if (error) + goto out_defer; + /* Map the new blocks into the data fork. */ error = xfs_bmap_map_extent(tp->t_mountp, &dfops, ip, XFS_DATA_FORK, &uirec); @@ -731,3 +745,133 @@ out: trace_xfs_reflink_end_cow_error(ip, error, _RET_IP_); return error; } + +struct xfs_reflink_recovery { + struct list_head rr_list; + struct xfs_refcount_irec rr_rrec; +}; + +/* + * Find and remove leftover CoW reservations. + */ +STATIC int +xfs_reflink_recover_cow_ag( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct list_head debris; + struct xfs_trans *tp; + struct xfs_btree_cur *cur; + struct xfs_buf *agbp; + struct xfs_refcount_irec tmp; + struct xfs_reflink_recovery *rr, *n; + struct xfs_defer_ops dfops; + xfs_fsblock_t fsb; + int i, have; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + return error; + cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); + + /* Start iterating btree entries. */ + INIT_LIST_HEAD(&debris); + error = xfs_refcountbt_lookup_ge(cur, 0, &have); + if (error) + goto out_error; + while (have) { + /* If refcount == 1, save the stashed entry for later. */ + error = xfs_refcountbt_get_rec(cur, &tmp, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (tmp.rc_refcount != 1) + goto advloop; + + rr = kmem_alloc(sizeof(struct xfs_reflink_recovery), KM_SLEEP); + rr->rr_rrec = tmp; + list_add_tail(&rr->rr_list, &debris); + +advloop: + /* Look at the next one */ + error = xfs_btree_increment(cur, 0, &have); + if (error) + goto out_error; + } + + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + xfs_buf_relse(agbp); + + /* Now iterate the list to free the leftovers */ + list_for_each_entry(rr, &debris, rr_list) { + /* Set up transaction. */ + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); + if (error) + goto out_free; + + trace_xfs_reflink_recover_extent(mp, agno, &rr->rr_rrec); + + /* Free the orphan record */ + xfs_defer_init(&dfops, &fsb); + fsb = XFS_AGB_TO_FSB(mp, agno, rr->rr_rrec.rc_startblock); + error = xfs_refcount_free_cow_extent(mp, &dfops, fsb, + rr->rr_rrec.rc_blockcount); + if (error) + goto out_defer; + + /* Free the block. */ + xfs_bmap_add_free(mp, &dfops, fsb, + rr->rr_rrec.rc_blockcount, NULL); + + error = xfs_defer_finish(&tp, &dfops, NULL); + if (error) + goto out_defer; + + error = xfs_trans_commit(tp); + if (error) + goto out_cancel; + } + goto out_free; + +out_defer: + xfs_defer_cancel(&dfops); +out_cancel: + xfs_trans_cancel(tp); + +out_free: + /* Free the leftover list */ + list_for_each_entry_safe(rr, n, &debris, rr_list) { + list_del(&rr->rr_list); + kmem_free(rr); + } + + return error; + +out_error: + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); + xfs_buf_relse(agbp); + return error; +} + +/* + * Free leftover CoW reservations that didn't get cleaned out. + */ +int +xfs_reflink_recover_cow( + struct xfs_mount *mp) +{ + xfs_agnumber_t agno; + int error = 0; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 0; + + for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + error = xfs_reflink_recover_cow_ag(mp, agno); + if (error) + break; + } + + return error; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 2f3c829..0f5fd0c 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -41,6 +41,8 @@ extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset, extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t count); +extern int xfs_reflink_recover_cow(struct xfs_mount *mp); + /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, struct xfs_bmbt_irec *imap); diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 09f9af7..87e997a 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1306,6 +1306,12 @@ xfs_fs_remount( */ xfs_restore_resvblks(mp); xfs_log_work_queue(mp); + + /* Recover any CoW blocks that never got remapped. */ + error = xfs_reflink_recover_cow(mp); + if (error && !XFS_FORCED_SHUTDOWN(mp)) + xfs_err(mp, + "Error %d recovering leftover CoW allocations.", error); } /* rw -> ro */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 079075f..fe4a5be 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2889,14 +2889,18 @@ DEFINE_AG_ERROR_EVENT(xfs_refcountbt_update_error); /* refcount adjustment tracepoints */ DEFINE_AG_EXTENT_EVENT(xfs_refcount_increase); DEFINE_AG_EXTENT_EVENT(xfs_refcount_decrease); +DEFINE_AG_EXTENT_EVENT(xfs_refcount_cow_increase); +DEFINE_AG_EXTENT_EVENT(xfs_refcount_cow_decrease); DEFINE_REFCOUNT_TRIPLE_EXTENT_EVENT(xfs_refcount_merge_center_extents); DEFINE_REFCOUNT_EXTENT_EVENT(xfs_refcount_modify_extent); +DEFINE_REFCOUNT_EXTENT_EVENT(xfs_reflink_recover_extent); DEFINE_REFCOUNT_EXTENT_AT_EVENT(xfs_refcount_split_extent); DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_merge_left_extent); DEFINE_REFCOUNT_DOUBLE_EXTENT_EVENT(xfs_refcount_merge_right_extent); DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(xfs_refcount_find_left_extent); DEFINE_REFCOUNT_DOUBLE_EXTENT_AT_EVENT(xfs_refcount_find_right_extent); DEFINE_AG_ERROR_EVENT(xfs_refcount_adjust_error); +DEFINE_AG_ERROR_EVENT(xfs_refcount_adjust_cow_error); DEFINE_AG_ERROR_EVENT(xfs_refcount_merge_center_extents_error); DEFINE_AG_ERROR_EVENT(xfs_refcount_modify_extent_error); DEFINE_AG_ERROR_EVENT(xfs_refcount_split_extent_error); From darrick.wong@oracle.com Thu Jun 16 20:27:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5A2517ECA for ; Thu, 16 Jun 2016 20:27:33 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2AE9530404E for ; Thu, 16 Jun 2016 18:27:33 -0700 (PDT) X-ASG-Debug-ID: 1466126850-04cbb01fef69940001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id jAHYMdLoqBBA0abP (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1RRgX011256 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:28 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RRdC024829 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:27 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RQMT020876; Fri, 17 Jun 2016 01:27:26 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:26 -0700 Subject: [PATCH 089/119] xfs: reflink extents from one file to another From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 089/119] xfs: reflink extents from one file to another To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:24 -0700 Message-ID: <146612684450.12839.1184517921225715964.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126850 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13945 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Reflink extents from one file to another; that is to say, iteratively remove the mappings from the destination file, copy the mappings from the source file to the destination file, and increment the reference count of all the blocks that got remapped. v2: Call xfs_defer_cancel before cancelling the transaction if the remap operation fails. Use the deferred operations system to avoid deadlocks or blowing out the transaction reservation, and make the entire reflink operation atomic for each extent being remapped. The destination file's i_size will be updated if necessary to avoid violating the assumption that there are no shared blocks past the EOF block. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_reflink.c | 426 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 3 2 files changed, 429 insertions(+) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 0f9cc82..c01c0c7 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -875,3 +875,429 @@ xfs_reflink_recover_cow( return error; } + +/* + * Reflinking (Block) Ranges of Two Files Together + * + * First, ensure that the reflink flag is set on both inodes. The flag is an + * optimization to avoid unnecessary refcount btree lookups in the write path. + * + * Now we can iteratively remap the range of extents (and holes) in src to the + * corresponding ranges in dest. Let drange and srange denote the ranges of + * logical blocks in dest and src touched by the reflink operation. + * + * While the length of drange is greater than zero, + * - Read src's bmbt at the start of srange ("imap") + * - If imap doesn't exist, make imap appear to start at the end of srange + * with zero length. + * - If imap starts before srange, advance imap to start at srange. + * - If imap goes beyond srange, truncate imap to end at the end of srange. + * - Punch (imap start - srange start + imap len) blocks from dest at + * offset (drange start). + * - If imap points to a real range of pblks, + * > Increase the refcount of the imap's pblks + * > Map imap's pblks into dest at the offset + * (drange start + imap start - srange start) + * - Advance drange and srange by (imap start - srange start + imap len) + * + * Finally, if the reflink made dest longer, update both the in-core and + * on-disk file sizes. + * + * ASCII Art Demonstration: + * + * Let's say we want to reflink this source file: + * + * ----SSSSSSS-SSSSS----SSSSSS (src file) + * <--------------------> + * + * into this destination file: + * + * --DDDDDDDDDDDDDDDDDDD--DDD (dest file) + * <--------------------> + * '-' means a hole, and 'S' and 'D' are written blocks in the src and dest. + * Observe that the range has different logical offsets in either file. + * + * Consider that the first extent in the source file doesn't line up with our + * reflink range. Unmapping and remapping are separate operations, so we can + * unmap more blocks from the destination file than we remap. + * + * ----SSSSSSS-SSSSS----SSSSSS + * <-------> + * --DDDDD---------DDDDD--DDD + * <-------> + * + * Now remap the source extent into the destination file: + * + * ----SSSSSSS-SSSSS----SSSSSS + * <-------> + * --DDDDD--SSSSSSSDDDDD--DDD + * <-------> + * + * Do likewise with the second hole and extent in our range. Holes in the + * unmap range don't affect our operation. + * + * ----SSSSSSS-SSSSS----SSSSSS + * <----> + * --DDDDD--SSSSSSS-SSSSS-DDD + * <----> + * + * Finally, unmap and remap part of the third extent. This will increase the + * size of the destination file. + * + * ----SSSSSSS-SSSSS----SSSSSS + * <-----> + * --DDDDD--SSSSSSS-SSSSS----SSS + * <-----> + * + * Once we update the destination file's i_size, we're done. + */ + +/* + * Ensure the reflink bit is set in both inodes. + */ +STATIC int +xfs_reflink_set_inode_flag( + struct xfs_inode *src, + struct xfs_inode *dest) +{ + struct xfs_mount *mp = src->i_mount; + int error; + struct xfs_trans *tp; + + if (xfs_is_reflink_inode(src) && xfs_is_reflink_inode(dest)) + return 0; + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); + if (error) + goto out_error; + + /* Lock both files against IO */ + if (src->i_ino == dest->i_ino) + xfs_ilock(src, XFS_ILOCK_EXCL); + else + xfs_lock_two_inodes(src, dest, XFS_ILOCK_EXCL); + + if (!xfs_is_reflink_inode(src)) { + trace_xfs_reflink_set_inode_flag(src); + xfs_trans_ijoin(tp, src, XFS_ILOCK_EXCL); + src->i_d.di_flags2 |= XFS_DIFLAG2_REFLINK; + xfs_trans_log_inode(tp, src, XFS_ILOG_CORE); + xfs_ifork_init_cow(src); + } else + xfs_iunlock(src, XFS_ILOCK_EXCL); + + if (src->i_ino == dest->i_ino) + goto commit_flags; + + if (!xfs_is_reflink_inode(dest)) { + trace_xfs_reflink_set_inode_flag(dest); + xfs_trans_ijoin(tp, dest, XFS_ILOCK_EXCL); + dest->i_d.di_flags2 |= XFS_DIFLAG2_REFLINK; + xfs_trans_log_inode(tp, dest, XFS_ILOG_CORE); + xfs_ifork_init_cow(dest); + } else + xfs_iunlock(dest, XFS_ILOCK_EXCL); + +commit_flags: + error = xfs_trans_commit(tp); + if (error) + goto out_error; + return error; + +out_error: + trace_xfs_reflink_set_inode_flag_error(dest, error, _RET_IP_); + return error; +} + +/* + * Update destination inode size, if necessary. + */ +STATIC int +xfs_reflink_update_dest( + struct xfs_inode *dest, + xfs_off_t newlen) +{ + struct xfs_mount *mp = dest->i_mount; + struct xfs_trans *tp; + int error; + + if (newlen <= i_size_read(VFS_I(dest))) + return 0; + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); + if (error) + goto out_error; + + xfs_ilock(dest, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, dest, XFS_ILOCK_EXCL); + + trace_xfs_reflink_update_inode_size(dest, newlen); + i_size_write(VFS_I(dest), newlen); + dest->i_d.di_size = newlen; + xfs_trans_log_inode(tp, dest, XFS_ILOG_CORE); + + error = xfs_trans_commit(tp); + if (error) + goto out_error; + return error; + +out_error: + trace_xfs_reflink_update_inode_size_error(dest, error, _RET_IP_); + return error; +} + +/* + * Unmap a range of blocks from a file, then map other blocks into the hole. + * The range to unmap is (destoff : destoff + srcioff + irec->br_blockcount). + * The extent irec is mapped into dest at irec->br_startoff. + */ +STATIC int +xfs_reflink_remap_extent( + struct xfs_inode *ip, + struct xfs_bmbt_irec *irec, + xfs_fileoff_t destoff, + xfs_off_t new_isize) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + xfs_fsblock_t firstfsb; + unsigned int resblks; + struct xfs_defer_ops dfops; + struct xfs_bmbt_irec uirec; + bool real_extent; + xfs_filblks_t rlen; + xfs_filblks_t unmap_len; + xfs_off_t newlen; + int error; + + unmap_len = irec->br_startoff + irec->br_blockcount - destoff; + trace_xfs_reflink_punch_range(ip, destoff, unmap_len); + + /* Only remap normal extents. */ + real_extent = (irec->br_startblock != HOLESTARTBLOCK && + irec->br_startblock != DELAYSTARTBLOCK && + !ISUNWRITTEN(irec)); + + /* Start a rolling transaction to switch the mappings */ + resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); + if (error) + goto out; + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + + /* If we're not just clearing space, then do we have enough quota? */ + if (real_extent) { + error = xfs_trans_reserve_quota_nblks(tp, ip, + irec->br_blockcount, 0, XFS_QMOPT_RES_REGBLKS); + if (error) + goto out_cancel; + } + + trace_xfs_reflink_remap(ip, irec->br_startoff, + irec->br_blockcount, irec->br_startblock); + + /* Unmap the old blocks in the data fork. */ + rlen = unmap_len; + while (rlen) { + xfs_defer_init(&dfops, &firstfsb); + error = __xfs_bunmapi(tp, ip, destoff, &rlen, 0, 1, + &firstfsb, &dfops); + if (error) + goto out_defer; + + /* Trim the extent to whatever got unmapped. */ + uirec = *irec; + xfs_trim_extent(&uirec, destoff + rlen, unmap_len - rlen); + unmap_len = rlen; + + /* If this isn't a real mapping, we're done. */ + if (!real_extent || uirec.br_blockcount == 0) + goto next_extent; + + trace_xfs_reflink_remap(ip, uirec.br_startoff, + uirec.br_blockcount, uirec.br_startblock); + + /* Update the refcount tree */ + error = xfs_refcount_increase_extent(mp, &dfops, &uirec); + if (error) + goto out_defer; + + /* Map the new blocks into the data fork. */ + error = xfs_bmap_map_extent(mp, &dfops, ip, XFS_DATA_FORK, + &uirec); + if (error) + goto out_defer; + + /* Update quota accounting. */ + xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, + uirec.br_blockcount); + + /* Update dest isize if needed. */ + newlen = XFS_FSB_TO_B(mp, + uirec.br_startoff + uirec.br_blockcount); + newlen = min_t(xfs_off_t, newlen, new_isize); + if (newlen > i_size_read(VFS_I(ip))) { + trace_xfs_reflink_update_inode_size(ip, newlen); + i_size_write(VFS_I(ip), newlen); + ip->i_d.di_size = newlen; + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + } + +next_extent: + /* Process all the deferred stuff. */ + error = xfs_defer_finish(&tp, &dfops, ip); + if (error) + goto out_defer; + } + + error = xfs_trans_commit(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); + if (error) + goto out; + return 0; + +out_defer: + xfs_defer_cancel(&dfops); +out_cancel: + xfs_trans_cancel(tp); + xfs_iunlock(ip, XFS_ILOCK_EXCL); +out: + trace_xfs_reflink_remap_extent_error(ip, error, _RET_IP_); + return error; +} + +/* + * Iteratively remap one file's extents (and holes) to another's. + */ +STATIC int +xfs_reflink_remap_blocks( + struct xfs_inode *src, + xfs_fileoff_t srcoff, + struct xfs_inode *dest, + xfs_fileoff_t destoff, + xfs_filblks_t len, + xfs_off_t new_isize) +{ + struct xfs_bmbt_irec imap; + int nimaps; + int error = 0; + xfs_filblks_t range_len; + + /* drange = (destoff, destoff + len); srange = (srcoff, srcoff + len) */ + while (len) { + trace_xfs_reflink_remap_blocks_loop(src, srcoff, len, + dest, destoff); + /* Read extent from the source file */ + nimaps = 1; + xfs_ilock(src, XFS_ILOCK_EXCL); + error = xfs_bmapi_read(src, srcoff, len, &imap, &nimaps, 0); + xfs_iunlock(src, XFS_ILOCK_EXCL); + if (error) + goto err; + ASSERT(nimaps == 1); + xfs_trim_extent(&imap, srcoff, len); + + trace_xfs_reflink_remap_imap(src, srcoff, len, XFS_IO_OVERWRITE, + &imap); + + /* Translate imap into the destination file. */ + range_len = imap.br_startoff + imap.br_blockcount - srcoff; + imap.br_startoff += destoff - srcoff; + + /* Clear dest from destoff to the end of imap and map it in. */ + error = xfs_reflink_remap_extent(dest, &imap, destoff, + new_isize); + if (error) + goto err; + + if (fatal_signal_pending(current)) { + error = -EINTR; + goto err; + } + + /* Advance drange/srange */ + srcoff += range_len; + destoff += range_len; + len -= range_len; + } + + return 0; + +err: + trace_xfs_reflink_remap_blocks_error(dest, error, _RET_IP_); + return error; +} + +/* + * Link a range of blocks from one file to another. + */ +int +xfs_reflink_remap_range( + struct xfs_inode *src, + xfs_off_t srcoff, + struct xfs_inode *dest, + xfs_off_t destoff, + xfs_off_t len) +{ + struct xfs_mount *mp = src->i_mount; + xfs_fileoff_t sfsbno, dfsbno; + xfs_filblks_t fsblen; + int error; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return -EOPNOTSUPP; + + if (XFS_FORCED_SHUTDOWN(mp)) + return -EIO; + + /* Don't reflink realtime inodes */ + if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest)) + return -EINVAL; + + trace_xfs_reflink_remap_range(src, srcoff, len, dest, destoff); + + /* Lock both files against IO */ + if (src->i_ino == dest->i_ino) { + xfs_ilock(src, XFS_IOLOCK_EXCL); + xfs_ilock(src, XFS_MMAPLOCK_EXCL); + } else { + xfs_lock_two_inodes(src, dest, XFS_IOLOCK_EXCL); + xfs_lock_two_inodes(src, dest, XFS_MMAPLOCK_EXCL); + } + + error = xfs_reflink_set_inode_flag(src, dest); + if (error) + goto out_error; + + /* + * Invalidate the page cache so that we can clear any CoW mappings + * in the destination file. + */ + truncate_inode_pages_range(&VFS_I(dest)->i_data, destoff, + PAGE_ALIGN(destoff + len) - 1); + + dfsbno = XFS_B_TO_FSBT(mp, destoff); + sfsbno = XFS_B_TO_FSBT(mp, srcoff); + fsblen = XFS_B_TO_FSB(mp, len); + error = xfs_reflink_remap_blocks(src, sfsbno, dest, dfsbno, fsblen, + destoff + len); + if (error) + goto out_error; + + error = xfs_reflink_update_dest(dest, destoff + len); + if (error) + goto out_error; + +out_error: + xfs_iunlock(src, XFS_MMAPLOCK_EXCL); + xfs_iunlock(src, XFS_IOLOCK_EXCL); + if (src->i_ino != dest->i_ino) { + xfs_iunlock(dest, XFS_MMAPLOCK_EXCL); + xfs_iunlock(dest, XFS_IOLOCK_EXCL); + } + if (error) + trace_xfs_reflink_remap_range_error(dest, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 0f5fd0c..92c0ebd 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -43,6 +43,9 @@ extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, extern int xfs_reflink_recover_cow(struct xfs_mount *mp); +extern int xfs_reflink_remap_range(struct xfs_inode *src, xfs_off_t srcoff, + struct xfs_inode *dest, xfs_off_t destoff, xfs_off_t len); + /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, struct xfs_bmbt_irec *imap); From darrick.wong@oracle.com Thu Jun 16 20:27:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3BB3E7ED0 for ; Thu, 16 Jun 2016 20:27:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id F3B26304048 for ; Thu, 16 Jun 2016 18:27:37 -0700 (PDT) X-ASG-Debug-ID: 1466126855-04cbb01fec69940001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id laZRqSw0mD7518k9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:35 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1RXKN030563 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:34 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RXCc024933 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:33 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1RWkm020892; Fri, 17 Jun 2016 01:27:33 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:32 -0700 Subject: [PATCH 090/119] xfs: add clone file and clone range vfs functions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 090/119] xfs: add clone file and clone range vfs functions To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:31 -0700 Message-ID: <146612685092.12839.15947435528001594579.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126855 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5903 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Define two VFS functions which allow userspace to reflink a range of blocks between two files or to reflink one file's contents to another. These functions fit the new VFS ioctls that standardize the checking for the btrfs CLONE and CLONE RANGE ioctls. v2: Plug into the VFS function pointers instead of handling ioctls directly. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 11 ++++ fs/xfs/xfs_file.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_ioctl.c | 2 + 3 files changed, 155 insertions(+) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 6f4f2c3..788e006 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -533,6 +533,17 @@ typedef struct xfs_swapext #define XFS_IOC_GOINGDOWN _IOR ('X', 125, __uint32_t) /* XFS_IOC_GETFSUUID ---------- deprecated 140 */ +/* reflink ioctls; these MUST match the btrfs ioctl definitions */ +/* from struct btrfs_ioctl_clone_range_args */ +struct xfs_clone_args { + __s64 src_fd; + __u64 src_offset; + __u64 src_length; + __u64 dest_offset; +}; + +#define XFS_IOC_CLONE _IOW (0x94, 9, int) +#define XFS_IOC_CLONE_RANGE _IOW (0x94, 13, struct xfs_clone_args) #ifndef HAVE_BBMACROS /* diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index b979f01..c2953bd 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1050,6 +1050,146 @@ out_unlock: return error; } +/* + * Flush all file writes out to disk. + */ +static int +xfs_file_wait_for_io( + struct inode *inode, + loff_t offset, + size_t len) +{ + loff_t rounding; + loff_t ioffset; + loff_t iendoffset; + loff_t bs; + int ret; + + bs = inode->i_sb->s_blocksize; + inode_dio_wait(inode); + + rounding = max_t(xfs_off_t, bs, PAGE_SIZE); + ioffset = round_down(offset, rounding); + iendoffset = round_up(offset + len, rounding) - 1; + ret = filemap_write_and_wait_range(inode->i_mapping, ioffset, + iendoffset); + return ret; +} + +/* Hook up to the VFS reflink function */ +STATIC int +xfs_file_share_range( + struct file *file_in, + loff_t pos_in, + struct file *file_out, + loff_t pos_out, + u64 len) +{ + struct inode *inode_in; + struct inode *inode_out; + ssize_t ret; + loff_t bs; + loff_t isize; + int same_inode; + loff_t blen; + + inode_in = file_inode(file_in); + inode_out = file_inode(file_out); + bs = inode_out->i_sb->s_blocksize; + + /* Don't touch certain kinds of inodes */ + if (IS_IMMUTABLE(inode_out)) + return -EPERM; + if (IS_SWAPFILE(inode_in) || + IS_SWAPFILE(inode_out)) + return -ETXTBSY; + + /* Reflink only works within this filesystem. */ + if (inode_in->i_sb != inode_out->i_sb) + return -EXDEV; + same_inode = (inode_in->i_ino == inode_out->i_ino); + + /* Don't reflink dirs, pipes, sockets... */ + if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) + return -EISDIR; + if (S_ISFIFO(inode_in->i_mode) || S_ISFIFO(inode_out->i_mode)) + return -EINVAL; + if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) + return -EINVAL; + + /* Are we going all the way to the end? */ + isize = i_size_read(inode_in); + if (isize == 0) + return 0; + if (len == 0) + len = isize - pos_in; + + /* Ensure offsets don't wrap and the input is inside i_size */ + if (pos_in + len < pos_in || pos_out + len < pos_out || + pos_in + len > isize) + return -EINVAL; + + /* If we're linking to EOF, continue to the block boundary. */ + if (pos_in + len == isize) + blen = ALIGN(isize, bs) - pos_in; + else + blen = len; + + /* Only reflink if we're aligned to block boundaries */ + if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_in + blen, bs) || + !IS_ALIGNED(pos_out, bs) || !IS_ALIGNED(pos_out + blen, bs)) + return -EINVAL; + + /* Don't allow overlapped reflink within the same file */ + if (same_inode && pos_out + blen > pos_in && pos_out < pos_in + blen) + return -EINVAL; + + /* Wait for the completion of any pending IOs on srcfile */ + ret = xfs_file_wait_for_io(inode_in, pos_in, len); + if (ret) + goto out_unlock; + ret = xfs_file_wait_for_io(inode_out, pos_out, len); + if (ret) + goto out_unlock; + + ret = xfs_reflink_remap_range(XFS_I(inode_in), pos_in, XFS_I(inode_out), + pos_out, len); + if (ret < 0) + goto out_unlock; + +out_unlock: + return ret; +} + +STATIC ssize_t +xfs_file_copy_range( + struct file *file_in, + loff_t pos_in, + struct file *file_out, + loff_t pos_out, + size_t len, + unsigned int flags) +{ + int error; + + error = xfs_file_share_range(file_in, pos_in, file_out, pos_out, + len); + if (error) + return error; + return len; +} + +STATIC int +xfs_file_clone_range( + struct file *file_in, + loff_t pos_in, + struct file *file_out, + loff_t pos_out, + u64 len) +{ + return xfs_file_share_range(file_in, pos_in, file_out, pos_out, + len); +} STATIC int xfs_file_open( @@ -1719,6 +1859,8 @@ const struct file_operations xfs_file_operations = { .release = xfs_file_release, .fsync = xfs_file_fsync, .fallocate = xfs_file_fallocate, + .copy_file_range = xfs_file_copy_range, + .clone_file_range = xfs_file_clone_range, }; const struct file_operations xfs_dir_file_operations = { diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index dbca737..0e06a82 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -41,6 +41,7 @@ #include "xfs_trans.h" #include "xfs_pnfs.h" #include "xfs_acl.h" +#include "xfs_reflink.h" #include #include @@ -49,6 +50,7 @@ #include #include #include +#include /* * xfs_find_handle maps from userspace xfs_fsop_handlereq structure to From darrick.wong@oracle.com Thu Jun 16 20:27:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B4A987E18 for ; Thu, 16 Jun 2016 20:27:46 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 65624304039 for ; Thu, 16 Jun 2016 18:27:46 -0700 (PDT) X-ASG-Debug-ID: 1466126863-04bdf01e1795c50001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id bSGae2V5BbLZD1D8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:43 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Rfmn011428 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:27:41 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Rf21018901 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:27:41 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1ReiJ029521; Fri, 17 Jun 2016 01:27:41 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:40 -0700 Subject: [PATCH 091/119] xfs: add dedupe range vfs function From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 091/119] xfs: add dedupe range vfs function To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:37 -0700 Message-ID: <146612685727.12839.7433660689105580169.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126863 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9356 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Define a VFS function which allows userspace to request that the kernel reflink a range of blocks between two files if the ranges' contents match. The function fits the new VFS ioctl that standardizes the checking for the btrfs EXTENT SAME ioctl. v2: Plug into the VFS function pointers instead of handling ioctls directly, and lock the pages so they don't disappear while we're trying to compare them. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 30 +++++++++++ fs/xfs/xfs_file.c | 48 +++++++++++++++++- fs/xfs/xfs_reflink.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 5 ++ 4 files changed, 204 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 788e006..6230230 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -542,8 +542,38 @@ struct xfs_clone_args { __u64 dest_offset; }; +/* extent-same (dedupe) ioctls; these MUST match the btrfs ioctl definitions */ +#define XFS_EXTENT_DATA_SAME 0 +#define XFS_EXTENT_DATA_DIFFERS 1 + +/* from struct btrfs_ioctl_file_extent_same_info */ +struct xfs_extent_data_info { + __s64 fd; /* in - destination file */ + __u64 logical_offset; /* in - start of extent in destination */ + __u64 bytes_deduped; /* out - total # of bytes we were able + * to dedupe from this file */ + /* status of this dedupe operation: + * < 0 for error + * == XFS_EXTENT_DATA_SAME if dedupe succeeds + * == XFS_EXTENT_DATA_DIFFERS if data differs + */ + __s32 status; /* out - see above description */ + __u32 reserved; +}; + +/* from struct btrfs_ioctl_file_extent_same_args */ +struct xfs_extent_data { + __u64 logical_offset; /* in - start of extent in source */ + __u64 length; /* in - length of extent */ + __u16 dest_count; /* in - total elements in info array */ + __u16 reserved1; + __u32 reserved2; + struct xfs_extent_data_info info[0]; +}; + #define XFS_IOC_CLONE _IOW (0x94, 9, int) #define XFS_IOC_CLONE_RANGE _IOW (0x94, 13, struct xfs_clone_args) +#define XFS_IOC_FILE_EXTENT_SAME _IOWR(0x94, 54, struct xfs_extent_data) #ifndef HAVE_BBMACROS /* diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index c2953bd..02e9139 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1083,7 +1083,8 @@ xfs_file_share_range( loff_t pos_in, struct file *file_out, loff_t pos_out, - u64 len) + u64 len, + bool is_dedupe) { struct inode *inode_in; struct inode *inode_out; @@ -1092,6 +1093,7 @@ xfs_file_share_range( loff_t isize; int same_inode; loff_t blen; + unsigned int flags = 0; inode_in = file_inode(file_in); inode_out = file_inode(file_out); @@ -1129,6 +1131,15 @@ xfs_file_share_range( pos_in + len > isize) return -EINVAL; + /* Don't allow dedupe past EOF in the dest file */ + if (is_dedupe) { + loff_t disize; + + disize = i_size_read(inode_out); + if (pos_out >= disize || pos_out + len > disize) + return -EINVAL; + } + /* If we're linking to EOF, continue to the block boundary. */ if (pos_in + len == isize) blen = ALIGN(isize, bs) - pos_in; @@ -1152,8 +1163,10 @@ xfs_file_share_range( if (ret) goto out_unlock; + if (is_dedupe) + flags |= XFS_REFLINK_DEDUPE; ret = xfs_reflink_remap_range(XFS_I(inode_in), pos_in, XFS_I(inode_out), - pos_out, len); + pos_out, len, flags); if (ret < 0) goto out_unlock; @@ -1173,7 +1186,7 @@ xfs_file_copy_range( int error; error = xfs_file_share_range(file_in, pos_in, file_out, pos_out, - len); + len, false); if (error) return error; return len; @@ -1188,7 +1201,33 @@ xfs_file_clone_range( u64 len) { return xfs_file_share_range(file_in, pos_in, file_out, pos_out, - len); + len, false); +} + +#define XFS_MAX_DEDUPE_LEN (16 * 1024 * 1024) +STATIC ssize_t +xfs_file_dedupe_range( + struct file *src_file, + u64 loff, + u64 len, + struct file *dst_file, + u64 dst_loff) +{ + int error; + + /* + * Limit the total length we will dedupe for each operation. + * This is intended to bound the total time spent in this + * ioctl to something sane. + */ + if (len > XFS_MAX_DEDUPE_LEN) + len = XFS_MAX_DEDUPE_LEN; + + error = xfs_file_share_range(src_file, loff, dst_file, dst_loff, + len, true); + if (error) + return error; + return len; } STATIC int @@ -1861,6 +1900,7 @@ const struct file_operations xfs_file_operations = { .fallocate = xfs_file_fallocate, .copy_file_range = xfs_file_copy_range, .clone_file_range = xfs_file_clone_range, + .dedupe_file_range = xfs_file_dedupe_range, }; const struct file_operations xfs_dir_file_operations = { diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index c01c0c7..c42a6e1 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1231,6 +1231,111 @@ err: } /* + * Read a page's worth of file data into the page cache. Return the page + * locked. + */ +static struct page * +xfs_get_page( + struct inode *inode, + xfs_off_t offset) +{ + struct address_space *mapping; + struct page *page; + pgoff_t n; + + n = offset >> PAGE_SHIFT; + mapping = inode->i_mapping; + page = read_mapping_page(mapping, n, NULL); + if (IS_ERR(page)) + return page; + if (!PageUptodate(page)) { + put_page(page); + return ERR_PTR(-EIO); + } + lock_page(page); + return page; +} + +/* + * Compare extents of two files to see if they are the same. + */ +static int +xfs_compare_extents( + struct inode *src, + xfs_off_t srcoff, + struct inode *dest, + xfs_off_t destoff, + xfs_off_t len, + bool *is_same) +{ + xfs_off_t src_poff; + xfs_off_t dest_poff; + void *src_addr; + void *dest_addr; + struct page *src_page; + struct page *dest_page; + xfs_off_t cmp_len; + bool same; + int error; + + error = -EINVAL; + same = true; + while (len) { + src_poff = srcoff & (PAGE_SIZE - 1); + dest_poff = destoff & (PAGE_SIZE - 1); + cmp_len = min(PAGE_SIZE - src_poff, + PAGE_SIZE - dest_poff); + cmp_len = min(cmp_len, len); + ASSERT(cmp_len > 0); + + trace_xfs_reflink_compare_extents(XFS_I(src), srcoff, cmp_len, + XFS_I(dest), destoff); + + src_page = xfs_get_page(src, srcoff); + if (IS_ERR(src_page)) { + error = PTR_ERR(src_page); + goto out_error; + } + dest_page = xfs_get_page(dest, destoff); + if (IS_ERR(dest_page)) { + error = PTR_ERR(dest_page); + unlock_page(src_page); + put_page(src_page); + goto out_error; + } + src_addr = kmap_atomic(src_page); + dest_addr = kmap_atomic(dest_page); + + flush_dcache_page(src_page); + flush_dcache_page(dest_page); + + if (memcmp(src_addr + src_poff, dest_addr + dest_poff, cmp_len)) + same = false; + + kunmap_atomic(dest_addr); + kunmap_atomic(src_addr); + unlock_page(dest_page); + unlock_page(src_page); + put_page(dest_page); + put_page(src_page); + + if (!same) + break; + + srcoff += cmp_len; + destoff += cmp_len; + len -= cmp_len; + } + + *is_same = same; + return 0; + +out_error: + trace_xfs_reflink_compare_extents_error(XFS_I(dest), error, _RET_IP_); + return error; +} + +/* * Link a range of blocks from one file to another. */ int @@ -1239,12 +1344,14 @@ xfs_reflink_remap_range( xfs_off_t srcoff, struct xfs_inode *dest, xfs_off_t destoff, - xfs_off_t len) + xfs_off_t len, + unsigned int flags) { struct xfs_mount *mp = src->i_mount; xfs_fileoff_t sfsbno, dfsbno; xfs_filblks_t fsblen; int error; + bool is_same; if (!xfs_sb_version_hasreflink(&mp->m_sb)) return -EOPNOTSUPP; @@ -1256,6 +1363,9 @@ xfs_reflink_remap_range( if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest)) return -EINVAL; + if (flags & ~XFS_REFLINK_ALL) + return -EINVAL; + trace_xfs_reflink_remap_range(src, srcoff, len, dest, destoff); /* Lock both files against IO */ @@ -1267,6 +1377,21 @@ xfs_reflink_remap_range( xfs_lock_two_inodes(src, dest, XFS_MMAPLOCK_EXCL); } + /* + * Check that the extents are the same. + */ + if (flags & XFS_REFLINK_DEDUPE) { + is_same = false; + error = xfs_compare_extents(VFS_I(src), srcoff, VFS_I(dest), + destoff, len, &is_same); + if (error) + goto out_error; + if (!is_same) { + error = -EBADE; + goto out_error; + } + } + error = xfs_reflink_set_inode_flag(src, dest); if (error) goto out_error; diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 92c0ebd..1d38b97 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -43,8 +43,11 @@ extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, extern int xfs_reflink_recover_cow(struct xfs_mount *mp); +#define XFS_REFLINK_DEDUPE 1 /* only reflink if contents match */ +#define XFS_REFLINK_ALL (XFS_REFLINK_DEDUPE) extern int xfs_reflink_remap_range(struct xfs_inode *src, xfs_off_t srcoff, - struct xfs_inode *dest, xfs_off_t destoff, xfs_off_t len); + struct xfs_inode *dest, xfs_off_t destoff, xfs_off_t len, + unsigned int flags); /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, From darrick.wong@oracle.com Thu Jun 16 20:27:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8269D7E18 for ; Thu, 16 Jun 2016 20:27:55 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 09A73AC002 for ; Thu, 16 Jun 2016 18:27:54 -0700 (PDT) X-ASG-Debug-ID: 1466126872-04cb6c542657af0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id grY7dFKe2qNUe7M6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1RlVl011442 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:47 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Rl8M020533 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:47 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Rl85029531; Fri, 17 Jun 2016 01:27:47 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:46 -0700 Subject: [PATCH 092/119] xfs: teach get_bmapx and fiemap about shared extents and the CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 092/119] xfs: teach get_bmapx and fiemap about shared extents and the CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:45 -0700 Message-ID: <146612686537.12839.9576429345676177064.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126872 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5849 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach xfs_getbmapx how to report shared extents and CoW fork contents, then modify the FIEMAP formatters to set the appropriate flags. A previous version of this patch only modified the fiemap formatter, which is insufficient. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 4 ++- fs/xfs/xfs_bmap_util.c | 66 ++++++++++++++++++++++++++++++++++++++++++------ fs/xfs/xfs_iops.c | 2 + 3 files changed, 63 insertions(+), 9 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 6230230..b1af423 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -81,14 +81,16 @@ struct getbmapx { #define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */ #define BMV_IF_DELALLOC 0x8 /* rtn status BMV_OF_DELALLOC if req */ #define BMV_IF_NO_HOLES 0x10 /* Do not return holes */ +#define BMV_IF_COWFORK 0x20 /* return CoW fork rather than data */ #define BMV_IF_VALID \ (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC| \ - BMV_IF_DELALLOC|BMV_IF_NO_HOLES) + BMV_IF_DELALLOC|BMV_IF_NO_HOLES|BMV_IF_COWFORK) /* bmv_oflags values - returned for each non-header segment */ #define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ #define BMV_OF_DELALLOC 0x2 /* segment = delayed allocation */ #define BMV_OF_LAST 0x4 /* segment is the last in the file */ +#define BMV_OF_SHARED 0x8 /* segment shared with another file */ /* * Structure for XFS_IOC_FSSETDM. diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 9285111..3d71a17 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -44,6 +44,7 @@ #include "xfs_rmap_btree.h" #include "xfs_iomap.h" #include "xfs_reflink.h" +#include "xfs_refcount.h" /* Kernel only BMAP related definitions and functions */ @@ -391,6 +392,7 @@ xfs_bmap_count_blocks( STATIC int xfs_getbmapx_fix_eof_hole( xfs_inode_t *ip, /* xfs incore inode pointer */ + int whichfork, struct getbmapx *out, /* output structure */ int prealloced, /* this is a file with * preallocated data space */ @@ -420,7 +422,7 @@ xfs_getbmapx_fix_eof_hole( else out->bmv_block = xfs_fsb_to_db(ip, startblock); fileblock = XFS_BB_TO_FSB(ip->i_mount, out->bmv_offset); - ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + ifp = XFS_IFORK_PTR(ip, whichfork); if (xfs_iext_bno_to_ext(ifp, fileblock, &lastx) && (lastx == (ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t))-1)) out->bmv_oflags |= BMV_OF_LAST; @@ -464,9 +466,19 @@ xfs_getbmap( mp = ip->i_mount; iflags = bmv->bmv_iflags; - whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK; - if (whichfork == XFS_ATTR_FORK) { + if ((iflags & BMV_IF_ATTRFORK) && (iflags & BMV_IF_COWFORK)) + return -EINVAL; + + if (iflags & BMV_IF_ATTRFORK) + whichfork = XFS_ATTR_FORK; + else if (iflags & BMV_IF_COWFORK) + whichfork = XFS_COW_FORK; + else + whichfork = XFS_DATA_FORK; + + switch (whichfork) { + case XFS_ATTR_FORK: if (XFS_IFORK_Q(ip)) { if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS && ip->i_d.di_aformat != XFS_DINODE_FMT_BTREE && @@ -482,7 +494,15 @@ xfs_getbmap( prealloced = 0; fixlen = 1LL << 32; - } else { + break; + case XFS_COW_FORK: + if (ip->i_cformat != XFS_DINODE_FMT_EXTENTS) + return -EINVAL; + + prealloced = 0; + fixlen = XFS_ISIZE(ip); + break; + default: if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && ip->i_d.di_format != XFS_DINODE_FMT_BTREE && ip->i_d.di_format != XFS_DINODE_FMT_LOCAL) @@ -496,6 +516,7 @@ xfs_getbmap( prealloced = 0; fixlen = XFS_ISIZE(ip); } + break; } if (bmv->bmv_length == -1) { @@ -522,7 +543,8 @@ xfs_getbmap( return -ENOMEM; xfs_ilock(ip, XFS_IOLOCK_SHARED); - if (whichfork == XFS_DATA_FORK) { + switch (whichfork) { + case XFS_DATA_FORK: if (!(iflags & BMV_IF_DELALLOC) && (ip->i_delayed_blks || XFS_ISIZE(ip) > ip->i_d.di_size)) { error = filemap_write_and_wait(VFS_I(ip)->i_mapping); @@ -540,8 +562,14 @@ xfs_getbmap( } lock = xfs_ilock_data_map_shared(ip); - } else { + break; + case XFS_COW_FORK: + lock = XFS_ILOCK_SHARED; + xfs_ilock(ip, lock); + break; + case XFS_ATTR_FORK: lock = xfs_ilock_attr_map_shared(ip); + break; } /* @@ -616,8 +644,30 @@ xfs_getbmap( goto out_free_map; } - if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext], - prealloced, bmvend, + /* Is this a shared block? */ + if (whichfork == XFS_DATA_FORK && + map[i].br_startblock != DELAYSTARTBLOCK && + map[i].br_startblock != HOLESTARTBLOCK && + !ISUNWRITTEN(&map[i]) && xfs_is_reflink_inode(ip)) { + xfs_agblock_t ebno; + xfs_extlen_t elen; + + error = xfs_refcount_find_shared(mp, + XFS_FSB_TO_AGNO(mp, + map[i].br_startblock), + XFS_FSB_TO_AGBNO(mp, + map[i].br_startblock), + map[i].br_blockcount, + &ebno, &elen, true); + if (error) + goto out_free_map; + if (elen) + out[cur_ext].bmv_oflags |= + BMV_OF_SHARED; + } + + if (!xfs_getbmapx_fix_eof_hole(ip, whichfork, + &out[cur_ext], prealloced, bmvend, map[i].br_startblock)) goto out_free_map; diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index c5d4eba..e57bfe8 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1025,6 +1025,8 @@ xfs_fiemap_format( if (bmv->bmv_oflags & BMV_OF_PREALLOC) fiemap_flags |= FIEMAP_EXTENT_UNWRITTEN; + else if (bmv->bmv_oflags & BMV_OF_SHARED) + fiemap_flags |= FIEMAP_EXTENT_SHARED; else if (bmv->bmv_oflags & BMV_OF_DELALLOC) { fiemap_flags |= (FIEMAP_EXTENT_DELALLOC | FIEMAP_EXTENT_UNKNOWN); From darrick.wong@oracle.com Thu Jun 16 20:27:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6941B7E88 for ; Thu, 16 Jun 2016 20:27:59 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 1B5048F804C for ; Thu, 16 Jun 2016 18:27:59 -0700 (PDT) X-ASG-Debug-ID: 1466126877-04bdf01e1795c70001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id WUpIqMY2znjDlB5J (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:27:57 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1RsNR030716 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:27:55 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1RsYv019121 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:27:54 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Rrxk020972; Fri, 17 Jun 2016 01:27:53 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:53 -0700 Subject: [PATCH 093/119] xfs: swap inode reflink flags when swapping inode extents From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 093/119] xfs: swap inode reflink flags when swapping inode extents To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:51 -0700 Message-ID: <146612687170.12839.4966658279995436156.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126877 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1316 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we're swapping the extents of two inodes, be sure to swap the reflink inode flag too. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_bmap_util.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index 3d71a17..a5f5515 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1735,6 +1735,8 @@ xfs_swap_extents( int taforkblks = 0; __uint64_t tmp; int lock_flags; + struct xfs_ifork *cowfp; + __uint64_t f; /* XXX: we can't do this with rmap, will fix later */ if (xfs_sb_version_hasrmapbt(&mp->m_sb)) @@ -1948,6 +1950,19 @@ xfs_swap_extents( break; } + /* Do we have to swap reflink flags? */ + if ((ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK) ^ + (tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK)) { + f = ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; + ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; + tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK; + cowfp = ip->i_cowfp; + ip->i_cowfp = tip->i_cowfp; + tip->i_cowfp = cowfp; + } + xfs_trans_log_inode(tp, ip, src_log_flags); xfs_trans_log_inode(tp, tip, target_log_flags); From darrick.wong@oracle.com Thu Jun 16 20:28:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 11FC07EAE for ; Thu, 16 Jun 2016 20:28:10 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id B97C48F804C for ; Thu, 16 Jun 2016 18:28:09 -0700 (PDT) X-ASG-Debug-ID: 1466126886-04bdf01e1095c70001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id cTlEJpWOx9oClJjB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1S2Jf030981 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:28:03 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1S2v2019533 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:02 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Rx4e008782; Fri, 17 Jun 2016 01:28:01 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:27:59 -0700 Subject: [PATCH 094/119] xfs: unshare a range of blocks via fallocate From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 094/119] xfs: unshare a range of blocks via fallocate To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:27:58 -0700 Message-ID: <146612687793.12839.6066978539560923776.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126887 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10128 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Now that we have an fallocate flag to unshare a range of blocks, make XFS actually implement it. v2: NFS doesn't pass around struct file pointers, which means that our unshare functions all crash when filp == NULL. We don't need filp anyway, so remove all the parts where we pass filp around. Signed-off-by: Darrick J. Wong [hch@lst.de: pass inode instead of file to xfs_reflink_dirty_range] Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 6 + fs/xfs/xfs_reflink.c | 314 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 2 3 files changed, 321 insertions(+), 1 deletion(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 02e9139..618bd12 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1011,9 +1011,13 @@ xfs_file_fallocate( if (mode & FALLOC_FL_ZERO_RANGE) error = xfs_zero_file_space(ip, offset, len); - else + else { + error = xfs_reflink_unshare(ip, offset, len); + if (error) + goto out_unlock; error = xfs_alloc_file_space(ip, offset, len, XFS_BMAPI_PREALLOC); + } if (error) goto out_unlock; } diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index c42a6e1..78f24c3 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1426,3 +1426,317 @@ out_error: trace_xfs_reflink_remap_range_error(dest, error, _RET_IP_); return error; } + +/* + * Dirty all the shared blocks within a byte range of a file so that they're + * rewritten elsewhere. Similar to generic_perform_write(). + */ +static int +xfs_reflink_dirty_range( + struct inode *inode, + xfs_off_t pos, + xfs_off_t len) +{ + struct address_space *mapping; + const struct address_space_operations *a_ops; + int error; + unsigned int flags; + struct page *page; + struct page *rpage; + unsigned long offset; /* Offset into pagecache page */ + unsigned long bytes; /* Bytes to write to page */ + void *fsdata; + + mapping = inode->i_mapping; + a_ops = mapping->a_ops; + flags = AOP_FLAG_UNINTERRUPTIBLE; + do { + + offset = (pos & (PAGE_SIZE - 1)); + bytes = min_t(unsigned long, PAGE_SIZE - offset, len); + rpage = xfs_get_page(inode, pos); + if (IS_ERR(rpage)) { + error = PTR_ERR(rpage); + break; + } + + unlock_page(rpage); + error = a_ops->write_begin(NULL, mapping, pos, bytes, flags, + &page, &fsdata); + put_page(rpage); + if (error < 0) + break; + + trace_xfs_reflink_unshare_page(inode, page, pos, bytes); + + if (!PageUptodate(page)) { + xfs_err(XFS_I(inode)->i_mount, + "%s: STALE? ino=%llu pos=%llu\n", + __func__, XFS_I(inode)->i_ino, pos); + WARN_ON(1); + } + if (mapping_writably_mapped(mapping)) + flush_dcache_page(page); + + error = a_ops->write_end(NULL, mapping, pos, bytes, bytes, + page, fsdata); + if (error < 0) + break; + else if (error == 0) { + error = -EIO; + break; + } else { + bytes = error; + error = 0; + } + + cond_resched(); + + pos += bytes; + len -= bytes; + + balance_dirty_pages_ratelimited(mapping); + if (fatal_signal_pending(current)) { + error = -EINTR; + break; + } + } while (len > 0); + + return error; +} + +/* + * The user wants to preemptively CoW all shared blocks in this file, + * which enables us to turn off the reflink flag. Iterate all + * extents which are not prealloc/delalloc to see which ranges are + * mentioned in the refcount tree, then read those blocks into the + * pagecache, dirty them, fsync them back out, and then we can update + * the inode flag. What happens if we run out of memory? :) + */ +STATIC int +xfs_reflink_dirty_extents( + struct xfs_inode *ip, + xfs_fileoff_t fbno, + xfs_filblks_t end, + xfs_off_t isize) +{ + struct xfs_mount *mp = ip->i_mount; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + xfs_extlen_t aglen; + xfs_agblock_t rbno; + xfs_extlen_t rlen; + xfs_off_t fpos; + xfs_off_t flen; + struct xfs_bmbt_irec map[2]; + int nmaps; + int error; + + while (end - fbno > 0) { + nmaps = 1; + /* + * Look for extents in the file. Skip holes, delalloc, or + * unwritten extents; they can't be reflinked. + */ + error = xfs_bmapi_read(ip, fbno, end - fbno, map, &nmaps, 0); + if (error) + goto out; + if (nmaps == 0) + break; + if (map[0].br_startblock == HOLESTARTBLOCK || + map[0].br_startblock == DELAYSTARTBLOCK || + ISUNWRITTEN(&map[0])) + goto next; + + map[1] = map[0]; + while (map[1].br_blockcount) { + agno = XFS_FSB_TO_AGNO(mp, map[1].br_startblock); + agbno = XFS_FSB_TO_AGBNO(mp, map[1].br_startblock); + aglen = map[1].br_blockcount; + + error = xfs_refcount_find_shared(mp, agno, agbno, aglen, + &rbno, &rlen, true); + if (error) + goto out; + if (rlen == 0) + goto skip_copy; + + /* Dirty the pages */ + xfs_iunlock(ip, XFS_ILOCK_EXCL); + fpos = XFS_FSB_TO_B(mp, map[1].br_startoff + + (rbno - agbno)); + flen = XFS_FSB_TO_B(mp, rlen); + if (fpos + flen > isize) + flen = isize - fpos; + error = xfs_reflink_dirty_range(VFS_I(ip), fpos, flen); + xfs_ilock(ip, XFS_ILOCK_EXCL); + if (error) + goto out; +skip_copy: + map[1].br_blockcount -= (rbno - agbno + rlen); + map[1].br_startoff += (rbno - agbno + rlen); + map[1].br_startblock += (rbno - agbno + rlen); + } + +next: + fbno = map[0].br_startoff + map[0].br_blockcount; + } +out: + return error; +} + +/* Iterate the extents; if there are no reflinked blocks, clear the flag. */ +STATIC int +xfs_reflink_try_clear_inode_flag( + struct xfs_inode *ip, + xfs_off_t old_isize) +{ + struct xfs_mount *mp = ip->i_mount; + struct xfs_trans *tp; + xfs_fileoff_t fbno; + xfs_filblks_t end; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + xfs_extlen_t aglen; + xfs_agblock_t rbno; + xfs_extlen_t rlen; + struct xfs_bmbt_irec map[2]; + int nmaps; + int error = 0; + + /* Start a rolling transaction to remove the mappings */ + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, 0, 0, 0, &tp); + if (error) + return error; + + xfs_ilock(ip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, ip, 0); + + if (old_isize != i_size_read(VFS_I(ip))) + goto cancel; + if (!(ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK)) + goto cancel; + + fbno = 0; + end = XFS_B_TO_FSB(mp, old_isize); + while (end - fbno > 0) { + nmaps = 1; + /* + * Look for extents in the file. Skip holes, delalloc, or + * unwritten extents; they can't be reflinked. + */ + error = xfs_bmapi_read(ip, fbno, end - fbno, map, &nmaps, 0); + if (error) + goto cancel; + if (nmaps == 0) + break; + if (map[0].br_startblock == HOLESTARTBLOCK || + map[0].br_startblock == DELAYSTARTBLOCK || + ISUNWRITTEN(&map[0])) + goto next; + + map[1] = map[0]; + while (map[1].br_blockcount) { + agno = XFS_FSB_TO_AGNO(mp, map[1].br_startblock); + agbno = XFS_FSB_TO_AGBNO(mp, map[1].br_startblock); + aglen = map[1].br_blockcount; + + error = xfs_refcount_find_shared(mp, agno, agbno, aglen, + &rbno, &rlen, false); + if (error) + goto cancel; + /* Is there still a shared block here? */ + if (rlen > 0) { + error = 0; + goto cancel; + } + + map[1].br_blockcount -= aglen; + map[1].br_startoff += aglen; + map[1].br_startblock += aglen; + } + +next: + fbno = map[0].br_startoff + map[0].br_blockcount; + } + + /* + * We didn't find any shared blocks so turn off the reflink flag. + * First, get rid of any leftover CoW mappings. + */ + error = xfs_reflink_cancel_cow_blocks(ip, &tp, 0, NULLFILEOFF); + if (error) + goto cancel; + + /* Clear the inode flag. */ + trace_xfs_reflink_unset_inode_flag(ip); + ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + xfs_trans_ijoin(tp, ip, 0); + xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); + + error = xfs_trans_commit(tp); + if (error) + goto out; + + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return 0; +cancel: + xfs_trans_cancel(tp); +out: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + return error; +} + +/* + * Pre-COW all shared blocks within a given byte range of a file and turn off + * the reflink flag if we unshare all of the file's blocks. + */ +int +xfs_reflink_unshare( + struct xfs_inode *ip, + xfs_off_t offset, + xfs_off_t len) +{ + struct xfs_mount *mp = ip->i_mount; + xfs_fileoff_t fbno; + xfs_filblks_t end; + xfs_off_t old_isize, isize; + int error; + + if (!xfs_is_reflink_inode(ip)) + return 0; + + trace_xfs_reflink_unshare(ip, offset, len); + + inode_dio_wait(VFS_I(ip)); + + /* Try to CoW the selected ranges */ + xfs_ilock(ip, XFS_ILOCK_EXCL); + fbno = XFS_B_TO_FSB(mp, offset); + old_isize = isize = i_size_read(VFS_I(ip)); + end = XFS_B_TO_FSB(mp, offset + len); + error = xfs_reflink_dirty_extents(ip, fbno, end, isize); + if (error) + goto out_unlock; + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + /* Wait for the IO to finish */ + error = filemap_write_and_wait(VFS_I(ip)->i_mapping); + if (error) + goto out; + + /* Turn off the reflink flag if we unshared the whole file */ + if (offset == 0 && len == isize) { + error = xfs_reflink_try_clear_inode_flag(ip, old_isize); + if (error) + goto out; + } + + return 0; + +out_unlock: + xfs_iunlock(ip, XFS_ILOCK_EXCL); +out: + trace_xfs_reflink_unshare_error(ip, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 1d38b97..a369b2a 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -48,6 +48,8 @@ extern int xfs_reflink_recover_cow(struct xfs_mount *mp); extern int xfs_reflink_remap_range(struct xfs_inode *src, xfs_off_t srcoff, struct xfs_inode *dest, xfs_off_t destoff, xfs_off_t len, unsigned int flags); +extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, + xfs_off_t len); /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, From darrick.wong@oracle.com Thu Jun 16 20:28:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B27AF7EEB for ; Thu, 16 Jun 2016 20:28:13 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 844578F804C for ; Thu, 16 Jun 2016 18:28:13 -0700 (PDT) X-ASG-Debug-ID: 1466126891-04cbb01fec69990001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id SGlPzdMEBTTBu1Wo (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:12 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1S6eI011748 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:06 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1S6hD021004 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:06 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1S6hD029653; Fri, 17 Jun 2016 01:28:06 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:05 -0700 Subject: [PATCH 095/119] xfs: CoW shared EOF block when truncating file From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 095/119] xfs: CoW shared EOF block when truncating file To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:04 -0700 Message-ID: <146612688440.12839.3166686602599403800.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126892 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3189 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When shrinking a file, the VFS zeroes everything in the associated page between the new EOF and the previous EOF to avoid leaking data. If this block is shared we need to CoW it before the VFS does its zeroing to avoid corrupting the other files. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_iops.c | 9 +++++++++ fs/xfs/xfs_reflink.c | 42 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 1 + 3 files changed, 52 insertions(+) diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index e57bfe8..0fa86bd 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -38,6 +38,7 @@ #include "xfs_dir2.h" #include "xfs_trans_space.h" #include "xfs_pnfs.h" +#include "xfs_reflink.h" #include #include @@ -816,6 +817,14 @@ xfs_setattr_size( } /* + * CoW the EOF block of the file if it's necessary to avoid + * corrupting other files. + */ + error = xfs_reflink_cow_eof_block(ip, newsize); + if (error) + return error; + + /* * We are going to log the inode size change in this transaction so * any previous writes that are beyond the on disk EOF and the new * EOF that have not been written out need to be written here. If we diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 78f24c3..b42ffb0 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1740,3 +1740,45 @@ out: trace_xfs_reflink_unshare_error(ip, error, _RET_IP_); return error; } + +/* + * If we're trying to truncate a file whose last block is shared and the new + * size isn't aligned to a block boundary, we need to dirty that last block + * ahead of the VFS zeroing the page. + */ +int +xfs_reflink_cow_eof_block( + struct xfs_inode *ip, + xfs_off_t newsize) +{ + struct xfs_mount *mp = ip->i_mount; + xfs_fileoff_t fbno; + xfs_off_t isize; + int error; + + if (!xfs_is_reflink_inode(ip) || + (newsize & ((1 << VFS_I(ip)->i_blkbits) - 1)) == 0) + return 0; + + /* Try to CoW the shared last block */ + xfs_ilock(ip, XFS_ILOCK_EXCL); + fbno = XFS_B_TO_FSBT(mp, newsize); + isize = i_size_read(VFS_I(ip)); + + if (newsize > isize) + trace_xfs_reflink_cow_eof_block(ip, isize, newsize - isize); + else + trace_xfs_reflink_cow_eof_block(ip, newsize, isize - newsize); + + error = xfs_reflink_dirty_extents(ip, fbno, fbno + 1, isize); + if (error) + goto out_unlock; + xfs_iunlock(ip, XFS_ILOCK_EXCL); + + return 0; + +out_unlock: + xfs_iunlock(ip, XFS_ILOCK_EXCL); + trace_xfs_reflink_cow_eof_block_error(ip, error, _RET_IP_); + return error; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index a369b2a..437087c5 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -50,6 +50,7 @@ extern int xfs_reflink_remap_range(struct xfs_inode *src, xfs_off_t srcoff, unsigned int flags); extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len); +extern int xfs_reflink_cow_eof_block(struct xfs_inode *ip, xfs_off_t newsize); /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, From darrick.wong@oracle.com Thu Jun 16 20:28:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id CC7FC7EF3 for ; Thu, 16 Jun 2016 20:28:21 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 65809AC002 for ; Thu, 16 Jun 2016 18:28:21 -0700 (PDT) X-ASG-Debug-ID: 1466126899-04bdf01e1595c90001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id ZmGhYMn6FfPgzSU9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1SEUu011825 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:14 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1SE5r021133 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:14 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1SDnf029664; Fri, 17 Jun 2016 01:28:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:13 -0700 Subject: [PATCH 096/119] xfs: support FS_XFLAG_REFLINK on reflink filesystems From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 096/119] xfs: support FS_XFLAG_REFLINK on reflink filesystems To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:10 -0700 Message-ID: <146612689065.12839.12038513561394516073.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126900 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3000 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add support for reporting the "reflink" inode flag in the XFS-specific getxflags ioctl, and allow the user to clear the flag if file size is zero. v2: Move the reflink flag out of the way of the DAX flag, and add the new cowextsize flag. v3: do not report (or allow changes to) FL_NOCOW_FL, since we don't support a flag to prevent CoWing and the reflink flag is a poor proxy. We'll try to design away the need for the NOCOW flag. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_inode.c | 2 ++ fs/xfs/xfs_ioctl.c | 4 ++++ fs/xfs/xfs_reflink.c | 26 ++++++++++++++++++++++++++ fs/xfs/xfs_reflink.h | 4 ++++ 4 files changed, 36 insertions(+) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index b8d3c4f..127bf54 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -652,6 +652,8 @@ _xfs_dic2xflags( if (di_flags2 & XFS_DIFLAG2_ANY) { if (di_flags2 & XFS_DIFLAG2_DAX) flags |= FS_XFLAG_DAX; + if (di_flags2 & XFS_DIFLAG2_REFLINK) + flags |= FS_XFLAG_REFLINK; } if (has_attr) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 0e06a82..b8eceee 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1258,6 +1258,10 @@ xfs_ioctl_setattr( trace_xfs_ioctl_setattr(ip); + code = xfs_reflink_check_flag_adjust(ip, &fa->fsx_xflags); + if (code) + return code; + code = xfs_ioctl_setattr_check_projid(ip, fa); if (code) return code; diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index b42ffb0..7c64104 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1782,3 +1782,29 @@ out_unlock: trace_xfs_reflink_cow_eof_block_error(ip, error, _RET_IP_); return error; } + +/* + * Ensure that the only change we allow to the inode reflink flag is to clear + * it when the fs supports reflink and the size is zero. + */ +int +xfs_reflink_check_flag_adjust( + struct xfs_inode *ip, + unsigned int *xflags) +{ + unsigned int chg; + + chg = !!(*xflags & FS_XFLAG_REFLINK) ^ !!xfs_is_reflink_inode(ip); + + if (!chg) + return 0; + if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb)) + return -EOPNOTSUPP; + if (i_size_read(VFS_I(ip)) != 0) + return -EINVAL; + if (*xflags & FS_XFLAG_REFLINK) { + *xflags &= ~FS_XFLAG_REFLINK; + return 0; + } + return 0; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 437087c5..97e8705 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -52,6 +52,10 @@ extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, xfs_off_t len); extern int xfs_reflink_cow_eof_block(struct xfs_inode *ip, xfs_off_t newsize); +extern void xfs_reflink_get_lxflags(struct xfs_inode *ip, unsigned int *flags); +extern int xfs_reflink_check_flag_adjust(struct xfs_inode *ip, + unsigned int *xflags); + /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, struct xfs_bmbt_irec *imap); From darrick.wong@oracle.com Thu Jun 16 20:28:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 906A37EFA for ; Thu, 16 Jun 2016 20:28:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 61F6C8F804C for ; Thu, 16 Jun 2016 18:28:27 -0700 (PDT) X-ASG-Debug-ID: 1466126903-04cb6c542657b10001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id HVXCauA4kCamrHJB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:24 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1SLCx031169 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:28:21 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1SLBr019799 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:21 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1SKRH025596; Fri, 17 Jun 2016 01:28:20 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:19 -0700 Subject: [PATCH 097/119] xfs: create a separate cow extent size hint for the allocator From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 097/119] xfs: create a separate cow extent size hint for the allocator To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:18 -0700 Message-ID: <146612689831.12839.939478487228706208.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126904 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 16286 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a per-inode extent size allocator hint for copy-on-write. This hint is separate from the existing extent size hint so that CoW can take advantage of the fragmentation-reducing properties of extent size hints without disabling delalloc for regular writes. The extent size hint that's fed to the allocator during a copy on write operation is the greater of the cowextsize and regular extsize hint. During reflink, if we're sharing the entire source file to the entire destination file and the destination file doesn't already have a cowextsize hint, propagate the source file's cowextsize hint to the destination file. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 13 +++++++- fs/xfs/libxfs/xfs_format.h | 3 +- fs/xfs/libxfs/xfs_fs.h | 3 +- fs/xfs/libxfs/xfs_inode_buf.c | 4 ++ fs/xfs/libxfs/xfs_inode_buf.h | 1 + fs/xfs/libxfs/xfs_log_format.h | 3 +- fs/xfs/xfs_bmap_util.c | 9 ++++- fs/xfs/xfs_inode.c | 33 ++++++++++++++++++++ fs/xfs/xfs_inode.h | 1 + fs/xfs/xfs_inode_item.c | 2 + fs/xfs/xfs_ioctl.c | 67 +++++++++++++++++++++++++++++++++++++++- fs/xfs/xfs_iomap.c | 5 ++- fs/xfs/xfs_itable.c | 5 +++ fs/xfs/xfs_reflink.c | 36 +++++++++++++++++---- 14 files changed, 166 insertions(+), 19 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 0909532..a6c08bf 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -3665,7 +3665,13 @@ xfs_bmap_btalloc( else if (mp->m_dalign) stripe_align = mp->m_dalign; - align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; + if (ap->userdata) { + if (ap->flags & XFS_BMAPI_COWFORK) + align = xfs_get_cowextsz_hint(ap->ip); + else + align = xfs_get_extsz_hint(ap->ip); + } else + align = 0; if (unlikely(align)) { error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, align, 0, ap->eof, 0, ap->conv, @@ -4178,7 +4184,10 @@ xfs_bmapi_reserve_delalloc( alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff); /* Figure out the extent size, adjust alen */ - extsz = xfs_get_extsz_hint(ip); + if (whichfork == XFS_COW_FORK) + extsz = xfs_get_cowextsz_hint(ip); + else + extsz = xfs_get_extsz_hint(ip); if (extsz) { error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof, 1, 0, &aoff, &alen); diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 3d336e9..a35f4e5 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -890,7 +890,8 @@ typedef struct xfs_dinode { __be64 di_changecount; /* number of attribute changes */ __be64 di_lsn; /* flush sequence */ __be64 di_flags2; /* more random flags */ - __u8 di_pad2[16]; /* more padding for future expansion */ + __be32 di_cowextsize; /* basic cow extent size for file */ + __u8 di_pad2[12]; /* more padding for future expansion */ /* fields only written to during inode creation */ xfs_timestamp_t di_crtime; /* time created */ diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index b1af423..10ebf99 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -278,7 +278,8 @@ typedef struct xfs_bstat { #define bs_projid bs_projid_lo /* (previously just bs_projid) */ __u16 bs_forkoff; /* inode fork offset in bytes */ __u16 bs_projid_hi; /* higher part of project id */ - unsigned char bs_pad[10]; /* pad space, unused */ + unsigned char bs_pad[6]; /* pad space, unused */ + __u32 bs_cowextsize; /* cow extent size */ __u32 bs_dmevmask; /* DMIG event mask */ __u16 bs_dmstate; /* DMIG state info */ __u16 bs_aextents; /* attribute number of extents */ diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 44f325c..2efa42c 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -267,6 +267,7 @@ xfs_inode_from_disk( to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); to->di_flags2 = be64_to_cpu(from->di_flags2); + to->di_cowextsize = be32_to_cpu(from->di_cowextsize); } } @@ -316,7 +317,7 @@ xfs_inode_to_disk( to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); to->di_flags2 = cpu_to_be64(from->di_flags2); - + to->di_cowextsize = cpu_to_be32(from->di_cowextsize); to->di_ino = cpu_to_be64(ip->i_ino); to->di_lsn = cpu_to_be64(lsn); memset(to->di_pad2, 0, sizeof(to->di_pad2)); @@ -368,6 +369,7 @@ xfs_log_dinode_to_disk( to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); to->di_flags2 = cpu_to_be64(from->di_flags2); + to->di_cowextsize = cpu_to_be32(from->di_cowextsize); to->di_ino = cpu_to_be64(from->di_ino); to->di_lsn = cpu_to_be64(from->di_lsn); memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2)); diff --git a/fs/xfs/libxfs/xfs_inode_buf.h b/fs/xfs/libxfs/xfs_inode_buf.h index 958c543..6848a0a 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.h +++ b/fs/xfs/libxfs/xfs_inode_buf.h @@ -47,6 +47,7 @@ struct xfs_icdinode { __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ __uint64_t di_flags2; /* more random flags */ + __uint32_t di_cowextsize; /* basic cow extent size for file */ xfs_ictimestamp_t di_crtime; /* time created */ }; diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h index 320a305..9cab67f 100644 --- a/fs/xfs/libxfs/xfs_log_format.h +++ b/fs/xfs/libxfs/xfs_log_format.h @@ -423,7 +423,8 @@ struct xfs_log_dinode { __uint64_t di_changecount; /* number of attribute changes */ xfs_lsn_t di_lsn; /* flush sequence */ __uint64_t di_flags2; /* more random flags */ - __uint8_t di_pad2[16]; /* more padding for future expansion */ + __uint32_t di_cowextsize; /* basic cow extent size for file */ + __uint8_t di_pad2[12]; /* more padding for future expansion */ /* fields only written to during inode creation */ xfs_ictimestamp_t di_crtime; /* time created */ diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index a5f5515..b0c2c6d5 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -499,8 +499,13 @@ xfs_getbmap( if (ip->i_cformat != XFS_DINODE_FMT_EXTENTS) return -EINVAL; - prealloced = 0; - fixlen = XFS_ISIZE(ip); + if (xfs_get_cowextsz_hint(ip)) { + prealloced = 1; + fixlen = mp->m_super->s_maxbytes; + } else { + prealloced = 0; + fixlen = XFS_ISIZE(ip); + } break; default: if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS && diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 127bf54..480e48a 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -78,6 +78,27 @@ xfs_get_extsz_hint( } /* + * Helper function to extract CoW extent size hint from inode. + * Between the extent size hint and the CoW extent size hint, we + * return the greater of the two. + */ +xfs_extlen_t +xfs_get_cowextsz_hint( + struct xfs_inode *ip) +{ + xfs_extlen_t a, b; + + a = 0; + if (ip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) + a = ip->i_d.di_cowextsize; + b = xfs_get_extsz_hint(ip); + + if (a > b) + return a; + return b; +} + +/* * These two are wrapper routines around the xfs_ilock() routine used to * centralize some grungy code. They are used in places that wish to lock the * inode solely for reading the extents. The reason these places can't just @@ -654,6 +675,8 @@ _xfs_dic2xflags( flags |= FS_XFLAG_DAX; if (di_flags2 & XFS_DIFLAG2_REFLINK) flags |= FS_XFLAG_REFLINK; + if (di_flags2 & XFS_DIFLAG2_COWEXTSIZE) + flags |= FS_XFLAG_COWEXTSIZE; } if (has_attr) @@ -837,6 +860,7 @@ xfs_ialloc( if (ip->i_d.di_version == 3) { inode->i_version = 1; ip->i_d.di_flags2 = 0; + ip->i_d.di_cowextsize = 0; ip->i_d.di_crtime.t_sec = (__int32_t)tv.tv_sec; ip->i_d.di_crtime.t_nsec = (__int32_t)tv.tv_nsec; } @@ -899,6 +923,15 @@ xfs_ialloc( ip->i_d.di_flags |= di_flags; ip->i_d.di_flags2 |= di_flags2; } + if (pip && + (pip->i_d.di_flags2 & XFS_DIFLAG2_ANY) && + pip->i_d.di_version == 3 && + ip->i_d.di_version == 3) { + if (pip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) { + ip->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; + ip->i_d.di_cowextsize = pip->i_d.di_cowextsize; + } + } /* FALLTHROUGH */ case S_IFLNK: ip->i_d.di_format = XFS_DINODE_FMT_EXTENTS; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 797fcc7..2c1fb3f 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -419,6 +419,7 @@ int xfs_iflush(struct xfs_inode *, struct xfs_buf **); void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); xfs_extlen_t xfs_get_extsz_hint(struct xfs_inode *ip); +xfs_extlen_t xfs_get_cowextsz_hint(struct xfs_inode *ip); int xfs_dir_ialloc(struct xfs_trans **, struct xfs_inode *, umode_t, xfs_nlink_t, xfs_dev_t, prid_t, int, diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index a1b0761..9a1d62b 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -368,7 +368,7 @@ xfs_inode_to_log_dinode( to->di_crtime.t_sec = from->di_crtime.t_sec; to->di_crtime.t_nsec = from->di_crtime.t_nsec; to->di_flags2 = from->di_flags2; - + to->di_cowextsize = from->di_cowextsize; to->di_ino = ip->i_ino; to->di_lsn = lsn; memset(to->di_pad2, 0, sizeof(to->di_pad2)); diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index b8eceee..d2b4e81 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -900,6 +900,8 @@ xfs_ioc_fsgetxattr( xfs_ilock(ip, XFS_ILOCK_SHARED); fa.fsx_xflags = xfs_ip2xflags(ip); fa.fsx_extsize = ip->i_d.di_extsize << ip->i_mount->m_sb.sb_blocklog; + fa.fsx_cowextsize = ip->i_d.di_cowextsize << + ip->i_mount->m_sb.sb_blocklog; fa.fsx_projid = xfs_get_projid(ip); if (attr) { @@ -970,12 +972,13 @@ xfs_set_diflags( if (ip->i_d.di_version < 3) return; - di_flags2 = 0; + di_flags2 = (ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK); if (xflags & FS_XFLAG_DAX) di_flags2 |= XFS_DIFLAG2_DAX; + if (xflags & FS_XFLAG_COWEXTSIZE) + di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; ip->i_d.di_flags2 = di_flags2; - } STATIC void @@ -1216,6 +1219,56 @@ xfs_ioctl_setattr_check_extsize( return 0; } +/* + * CoW extent size hint validation rules are: + * + * 1. CoW extent size hint can only be set if reflink is enabled on the fs. + * The inode does not have to have any shared blocks, but it must be a v3. + * 2. FS_XFLAG_COWEXTSIZE is only valid for directories and regular files; + * for a directory, the hint is propagated to new files. + * 3. Can be changed on files & directories at any time. + * 4. CoW extsize hint of 0 turns off hints, clears inode flags. + * 5. Extent size must be a multiple of the appropriate block size. + * 6. The extent size hint must be limited to half the AG size to avoid + * alignment extending the extent beyond the limits of the AG. + */ +static int +xfs_ioctl_setattr_check_cowextsize( + struct xfs_inode *ip, + struct fsxattr *fa) +{ + struct xfs_mount *mp = ip->i_mount; + + if (!(fa->fsx_xflags & FS_XFLAG_COWEXTSIZE)) + return 0; + + if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb) || + ip->i_d.di_version != 3) + return -EINVAL; + + if (!S_ISREG(VFS_I(ip)->i_mode) && !S_ISDIR(VFS_I(ip)->i_mode)) + return -EINVAL; + + if (fa->fsx_cowextsize != 0) { + xfs_extlen_t size; + xfs_fsblock_t cowextsize_fsb; + + cowextsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_cowextsize); + if (cowextsize_fsb > MAXEXTLEN) + return -EINVAL; + + size = mp->m_sb.sb_blocksize; + if (cowextsize_fsb > mp->m_sb.sb_agblocks / 2) + return -EINVAL; + + if (fa->fsx_cowextsize % size) + return -EINVAL; + } else + fa->fsx_xflags &= ~FS_XFLAG_COWEXTSIZE; + + return 0; +} + static int xfs_ioctl_setattr_check_projid( struct xfs_inode *ip, @@ -1312,6 +1365,10 @@ xfs_ioctl_setattr( if (code) goto error_trans_cancel; + code = xfs_ioctl_setattr_check_cowextsize(ip, fa); + if (code) + goto error_trans_cancel; + code = xfs_ioctl_setattr_xflags(tp, ip, fa); if (code) goto error_trans_cancel; @@ -1347,6 +1404,12 @@ xfs_ioctl_setattr( ip->i_d.di_extsize = fa->fsx_extsize >> mp->m_sb.sb_blocklog; else ip->i_d.di_extsize = 0; + if (ip->i_d.di_version == 3 && + (ip->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE)) + ip->i_d.di_cowextsize = fa->fsx_cowextsize >> + mp->m_sb.sb_blocklog; + else + ip->i_d.di_cowextsize = 0; code = xfs_trans_commit(tp); diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index e7e1346..3914f0f 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -589,7 +589,10 @@ __xfs_iomap_write_delay( if (error) return error; - extsz = xfs_get_extsz_hint(ip); + if (whichfork == XFS_COW_FORK) + extsz = xfs_get_cowextsz_hint(ip); + else + extsz = xfs_get_extsz_hint(ip); offset_fsb = XFS_B_TO_FSBT(mp, offset); if (whichfork == XFS_DATA_FORK) { diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index ce73eb3..6da964a 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c @@ -111,6 +111,11 @@ xfs_bulkstat_one_int( buf->bs_aextents = dic->di_anextents; buf->bs_forkoff = XFS_IFORK_BOFF(ip); + if (dic->di_version == 3) { + if (dic->di_flags2 & XFS_DIFLAG2_COWEXTSIZE) + buf->bs_cowextsize = dic->di_cowextsize; + } + switch (dic->di_format) { case XFS_DINODE_FMT_DEV: buf->bs_rdev = ip->i_df.if_u2.if_rdev; diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 7c64104..d2c1547 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1010,18 +1010,19 @@ out_error: } /* - * Update destination inode size, if necessary. + * Update destination inode size & cowextsize hint, if necessary. */ STATIC int xfs_reflink_update_dest( struct xfs_inode *dest, - xfs_off_t newlen) + xfs_off_t newlen, + xfs_extlen_t cowextsize) { struct xfs_mount *mp = dest->i_mount; struct xfs_trans *tp; int error; - if (newlen <= i_size_read(VFS_I(dest))) + if (newlen <= i_size_read(VFS_I(dest)) && cowextsize == 0) return 0; error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0, 0, 0, &tp); @@ -1031,9 +1032,17 @@ xfs_reflink_update_dest( xfs_ilock(dest, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, dest, XFS_ILOCK_EXCL); - trace_xfs_reflink_update_inode_size(dest, newlen); - i_size_write(VFS_I(dest), newlen); - dest->i_d.di_size = newlen; + if (newlen > i_size_read(VFS_I(dest))) { + trace_xfs_reflink_update_inode_size(dest, newlen); + i_size_write(VFS_I(dest), newlen); + dest->i_d.di_size = newlen; + } + + if (cowextsize) { + dest->i_d.di_cowextsize = cowextsize; + dest->i_d.di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; + } + xfs_trans_log_inode(tp, dest, XFS_ILOG_CORE); error = xfs_trans_commit(tp); @@ -1351,6 +1360,7 @@ xfs_reflink_remap_range( xfs_fileoff_t sfsbno, dfsbno; xfs_filblks_t fsblen; int error; + xfs_extlen_t cowextsize; bool is_same; if (!xfs_sb_version_hasreflink(&mp->m_sb)) @@ -1411,7 +1421,19 @@ xfs_reflink_remap_range( if (error) goto out_error; - error = xfs_reflink_update_dest(dest, destoff + len); + /* + * Carry the cowextsize hint from src to dest if we're sharing the + * entire source file to the entire destination file, the source file + * has a cowextsize hint, and the destination file does not. + */ + cowextsize = 0; + if (srcoff == 0 && len == i_size_read(VFS_I(src)) && + (src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) && + destoff == 0 && len >= i_size_read(VFS_I(dest)) && + !(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE)) + cowextsize = src->i_d.di_cowextsize; + + error = xfs_reflink_update_dest(dest, destoff + len, cowextsize); if (error) goto out_error; From darrick.wong@oracle.com Thu Jun 16 20:28:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 075117D69 for ; Thu, 16 Jun 2016 20:28:41 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id C05C78F804B for ; Thu, 16 Jun 2016 18:28:40 -0700 (PDT) X-ASG-Debug-ID: 1466126917-04cb6c542557b20001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id mMZGt6P5LsIbgEYp (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:38 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1STYV011897 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:29 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1STdW026126 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:29 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1SQNx008855; Fri, 17 Jun 2016 01:28:27 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:26 -0700 Subject: [PATCH 098/119] xfs: preallocate blocks for worst-case btree expansion From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 098/119] xfs: preallocate blocks for worst-case btree expansion To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:24 -0700 Message-ID: <146612690470.12839.4608031019884955143.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126917 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14635 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines To gracefully handle the situation where a CoW operation turns a single refcount extent into a lot of tiny ones and then run out of space when a tree split has to happen, use the per-AG reserved block pool to pre-allocate all the space we'll ever need for a maximal btree. For a 4K block size, this only costs an overhead of 0.3% of available disk space. When reflink is enabled, we have an unfortunate problem with rmap -- since we can share a block billions of times, this means that the reverse mapping btree can expand basically infinitely. When an AG is so full that there are no free blocks with which to expand the rmapbt, the filesystem will shut down hard. This is rather annoying to the user, so use the AG reservation code to reserve a "reasonable" amount of space for rmap. We'll prevent reflinks and CoW operations if we think we're getting close to exhausting an AG's free space rather than shutting down, but this permanent reservation should be enough for "most" users. Hopefully. v2: Simplify the return value from xfs_perag_pool_free_block to a bool so that we can easily call xfs_trans_binval for both the per-AG pool and the real freeing case. Without this we fail to invalidate the btree buffer and will trip over the write verifier on a shrinking refcount btree. v3: Convert to the new per-AG reservation code. v4: Combine this patch with the one that adds the rmapbt reservation, since the rmapbt reservation is only needed for reflink filesystems. v5: If we detect errors while counting the refcount or rmap btrees, shut down the filesystem to avoid the scenario where the fs shuts down mid-transaction due to btree corruption, repair refuses to run until the log is clean, and the log cannot be cleaned because replay hits btree corruption and shuts down. Signed-off-by: Darrick J. Wong [hch@lst.de: ensure that we invalidate the freed btree buffer] Signed-off-by: Christoph Hellwig --- fs/xfs/libxfs/xfs_ag_resv.c | 11 +++++ fs/xfs/libxfs/xfs_alloc.c | 2 - fs/xfs/libxfs/xfs_refcount_btree.c | 61 +++++++++++++++++++++++++-- fs/xfs/libxfs/xfs_refcount_btree.h | 3 + fs/xfs/libxfs/xfs_rmap_btree.c | 80 ++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 7 +++ fs/xfs/xfs_fsops.c | 56 +++++++++++++++++++++++++ fs/xfs/xfs_fsops.h | 3 + fs/xfs/xfs_mount.c | 4 ++ fs/xfs/xfs_super.c | 5 ++ 10 files changed, 225 insertions(+), 7 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ag_resv.c b/fs/xfs/libxfs/xfs_ag_resv.c index 4d390b7..9cfe132 100644 --- a/fs/xfs/libxfs/xfs_ag_resv.c +++ b/fs/xfs/libxfs/xfs_ag_resv.c @@ -38,6 +38,7 @@ #include "xfs_trans_space.h" #include "xfs_rmap_btree.h" #include "xfs_btree.h" +#include "xfs_refcount_btree.h" /* * Per-AG Block Reservations @@ -225,6 +226,11 @@ xfs_ag_resv_init( /* Create the metadata reservation. */ ask = used = 0; + err2 = xfs_refcountbt_calc_reserves(pag->pag_mount, pag->pag_agno, + &ask, &used); + if (err2 && !error) + error = err2; + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, ask, used); if (err2 && !error) error = err2; @@ -236,6 +242,11 @@ init_agfl: /* Create the AGFL metadata reservation */ ask = used = 0; + err2 = xfs_rmapbt_calc_reserves(pag->pag_mount, pag->pag_agno, + &ask, &used); + if (err2 && !error) + error = err2; + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_AGFL, ask, used); if (err2 && !error) error = err2; diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index c46db76..188c359a 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -139,8 +139,6 @@ xfs_alloc_ag_max_usable(struct xfs_mount *mp) /* rmap root block + full tree split on full AG */ blocks += 1 + (2 * mp->m_ag_maxlevels) - 1; } - if (xfs_sb_version_hasreflink(&mp->m_sb)) - blocks += xfs_refcountbt_max_size(mp); return mp->m_sb.sb_agblocks - blocks; } diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c index a944fca..abf1ebf 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.c +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -76,6 +76,8 @@ xfs_refcountbt_alloc_block( struct xfs_alloc_arg args; /* block allocation args */ int error; /* error return value */ + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); + memset(&args, 0, sizeof(args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; @@ -85,6 +87,7 @@ xfs_refcountbt_alloc_block( args.firstblock = args.fsbno; xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); args.minlen = args.maxlen = args.prod = 1; + args.resv = XFS_AG_RESV_METADATA; error = xfs_alloc_vextent(&args); if (error) @@ -116,17 +119,20 @@ xfs_refcountbt_free_block( struct xfs_buf *bp) { struct xfs_mount *mp = cur->bc_mp; - struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); struct xfs_owner_info oinfo; + int error; trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); - xfs_bmap_add_free(mp, cur->bc_private.a.dfops, fsbno, 1, - &oinfo); - xfs_trans_binval(tp, bp); - return 0; + error = xfs_free_extent(cur->bc_tp, fsbno, 1, &oinfo, + XFS_AG_RESV_METADATA); + if (error) + return error; + + xfs_trans_binval(cur->bc_tp, bp); + return error; } STATIC int @@ -396,3 +402,48 @@ xfs_refcountbt_max_size( return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); } + +/* Count the blocks in the reference count tree. */ +static int +xfs_refcountbt_count_blocks( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *tree_blocks) +{ + struct xfs_buf *agbp; + struct xfs_btree_cur *cur; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + return error; + cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); + error = xfs_btree_count_blocks(cur, tree_blocks); + xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, agbp); + + return error; +} + +/* + * Figure out how many blocks to reserve and how many are used by this btree. + */ +int +xfs_refcountbt_calc_reserves( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *ask, + xfs_extlen_t *used) +{ + xfs_extlen_t tree_len = 0; + int error; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 0; + + *ask += xfs_refcountbt_max_size(mp); + error = xfs_refcountbt_count_blocks(mp, agno, &tree_len); + *used += tree_len; + + return error; +} diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h index 780b02f..3be7768 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.h +++ b/fs/xfs/libxfs/xfs_refcount_btree.h @@ -68,4 +68,7 @@ extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, unsigned long long len); extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); +extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp, + xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); + #endif /* __XFS_REFCOUNT_BTREE_H__ */ diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c index 090dbbe..0b045a6 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.c +++ b/fs/xfs/libxfs/xfs_rmap_btree.c @@ -34,6 +34,7 @@ #include "xfs_cksum.h" #include "xfs_error.h" #include "xfs_extent_busy.h" +#include "xfs_ag_resv.h" /* * Reverse map btree. @@ -60,6 +61,14 @@ * try to recover tree and file data from corrupt primary metadata. */ +static bool +xfs_rmapbt_need_reserve( + struct xfs_mount *mp) +{ + return xfs_sb_version_hasrmapbt(&mp->m_sb) && + xfs_sb_version_hasreflink(&mp->m_sb); +} + static struct xfs_btree_cur * xfs_rmapbt_dup_cursor( struct xfs_btree_cur *cur) @@ -481,3 +490,74 @@ xfs_rmapbt_compute_maxlevels( mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_rmap_mnr, mp->m_sb.sb_agblocks); } + +/* Calculate the refcount btree size for some records. */ +xfs_extlen_t +xfs_rmapbt_calc_size( + struct xfs_mount *mp, + unsigned long long len) +{ + return xfs_btree_calc_size(mp, mp->m_rmap_mnr, len); +} + +/* + * Calculate the maximum refcount btree size. + */ +xfs_extlen_t +xfs_rmapbt_max_size( + struct xfs_mount *mp) +{ + /* Bail out if we're uninitialized, which can happen in mkfs. */ + if (mp->m_rmap_mxr[0] == 0) + return 0; + + return xfs_rmapbt_calc_size(mp, mp->m_sb.sb_agblocks); +} + +/* Count the blocks in the reference count tree. */ +static int +xfs_rmapbt_count_blocks( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *tree_blocks) +{ + struct xfs_buf *agbp; + struct xfs_btree_cur *cur; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + return error; + cur = xfs_rmapbt_init_cursor(mp, NULL, agbp, agno); + error = xfs_btree_count_blocks(cur, tree_blocks); + xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, agbp); + + return error; +} + +/* + * Figure out how many blocks to reserve and how many are used by this btree. + */ +int +xfs_rmapbt_calc_reserves( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *ask, + xfs_extlen_t *used) +{ + xfs_extlen_t pool_len; + xfs_extlen_t tree_len = 0; + int error; + + if (!xfs_rmapbt_need_reserve(mp)) + return 0; + + /* Reserve 1% of the AG or enough for 1 block per record. */ + pool_len = max(mp->m_sb.sb_agblocks / 100, xfs_rmapbt_max_size(mp)); + *ask += pool_len; + error = xfs_rmapbt_count_blocks(mp, agno, &tree_len); + *used += tree_len; + + return error; +} diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 5df406e..f398e8b 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -130,4 +130,11 @@ int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state, struct xfs_btree_cur **pcur); +extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp, + unsigned long long len); +extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp); + +extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, + xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); + #endif /* __XFS_RMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 84e7ba3..e76aefc 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -42,6 +42,8 @@ #include "xfs_trace.h" #include "xfs_log.h" #include "xfs_filestream.h" +#include "xfs_refcount_btree.h" +#include "xfs_ag_resv.h" /* * File system operations @@ -677,6 +679,9 @@ xfs_growfs_data_private( continue; } } + + xfs_fs_reserve_ag_blocks(mp); + return saved_error ? saved_error : error; error0: @@ -971,3 +976,54 @@ xfs_do_force_shutdown( "Please umount the filesystem and rectify the problem(s)"); } } + +/* + * Reserve free space for per-AG metadata. + */ +void +xfs_fs_reserve_ag_blocks( + struct xfs_mount *mp) +{ + xfs_agnumber_t agno; + struct xfs_perag *pag; + int error = 0; + int err2; + + for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + pag = xfs_perag_get(mp, agno); + err2 = xfs_ag_resv_init(pag); + xfs_perag_put(pag); + if (err2 && !error) + error = err2; + } + + if (error) { + xfs_warn(mp, "Error %d reserving metadata blocks.", error); + xfs_force_shutdown(mp, (error == -EFSCORRUPTED) ? + SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR); + } +} + +/* + * Free space reserved for per-AG metadata. + */ +void +xfs_fs_unreserve_ag_blocks( + struct xfs_mount *mp) +{ + xfs_agnumber_t agno; + struct xfs_perag *pag; + int error = 0; + int err2; + + for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { + pag = xfs_perag_get(mp, agno); + err2 = xfs_ag_resv_free(pag); + xfs_perag_put(pag); + if (err2 && !error) + error = err2; + } + + if (error) + xfs_warn(mp, "Error %d unreserving metadata blocks.", error); +} diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h index f32713f..71e3248 100644 --- a/fs/xfs/xfs_fsops.h +++ b/fs/xfs/xfs_fsops.h @@ -26,4 +26,7 @@ extern int xfs_reserve_blocks(xfs_mount_t *mp, __uint64_t *inval, xfs_fsop_resblks_t *outval); extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags); +extern void xfs_fs_reserve_ag_blocks(struct xfs_mount *mp); +extern void xfs_fs_unreserve_ag_blocks(struct xfs_mount *mp); + #endif /* __XFS_FSOPS_H__ */ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 6351dce..db80832 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -45,6 +45,7 @@ #include "xfs_rmap_btree.h" #include "xfs_refcount_btree.h" #include "xfs_reflink.h" +#include "xfs_refcount_btree.h" static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -962,6 +963,8 @@ xfs_mountfs( xfs_warn(mp, "Unable to allocate reserve blocks. Continuing without reserve pool."); + xfs_fs_reserve_ag_blocks(mp); + /* Recover any CoW blocks that never got remapped. */ error = xfs_reflink_recover_cow(mp); if (error && !XFS_FORCED_SHUTDOWN(mp)) @@ -1013,6 +1016,7 @@ xfs_unmountfs( cancel_delayed_work_sync(&mp->m_eofblocks_work); + xfs_fs_unreserve_ag_blocks(mp); xfs_qm_unmount_quotas(mp); xfs_rtunmount_inodes(mp); IRELE(mp->m_rootip); diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 87e997a..10a0f721 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -51,6 +51,7 @@ #include "xfs_refcount_item.h" #include "xfs_bmap_item.h" #include "xfs_reflink.h" +#include "xfs_refcount_btree.h" #include #include @@ -1306,6 +1307,7 @@ xfs_fs_remount( */ xfs_restore_resvblks(mp); xfs_log_work_queue(mp); + xfs_fs_reserve_ag_blocks(mp); /* Recover any CoW blocks that never got remapped. */ error = xfs_reflink_recover_cow(mp); @@ -1323,6 +1325,9 @@ xfs_fs_remount( * reserve pool size so that if we get remounted rw, we can * return it to the same size. */ + + xfs_fs_unreserve_ag_blocks(mp); + xfs_save_resvblks(mp); xfs_quiesce_attr(mp); mp->m_flags |= XFS_MOUNT_RDONLY; From darrick.wong@oracle.com Thu Jun 16 20:28:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A92B77CF5 for ; Thu, 16 Jun 2016 20:28:41 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 7BF1C30404E for ; Thu, 16 Jun 2016 18:28:41 -0700 (PDT) X-ASG-Debug-ID: 1466126919-04cbb01fee699f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id EYFBIVLgFHLP9mwc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1SXKT011923 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:28:33 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1SXil020006 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:33 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1SWXi025670; Fri, 17 Jun 2016 01:28:33 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:32 -0700 Subject: [PATCH 099/119] xfs: don't allow reflink when the AG is low on space From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 099/119] xfs: don't allow reflink when the AG is low on space To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:31 -0700 Message-ID: <146612691118.12839.4806079419801697732.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126919 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2088 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines If the AG free space is down to the reserves, refuse to reflink our way out of space. Hopefully userspace will make a real copy and/or go elsewhere. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_reflink.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index d2c1547..f5195b7 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -53,6 +53,8 @@ #include "xfs_reflink.h" #include "xfs_iomap.h" #include "xfs_rmap_btree.h" +#include "xfs_sb.h" +#include "xfs_ag_resv.h" /* * Copy on Write of Shared Blocks @@ -1056,6 +1058,30 @@ out_error: } /* + * Do we have enough reserve in this AG to handle a reflink? The refcount + * btree already reserved all the space it needs, but the rmap btree can grow + * infinitely, so we won't allow more reflinks when the AG is down to the + * btree reserves. + */ +static int +xfs_reflink_ag_has_free_space( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_perag *pag; + int error = 0; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + pag = xfs_perag_get(mp, agno); + if (xfs_ag_resv_critical(pag, XFS_AG_RESV_AGFL)) + error = -ENOSPC; + xfs_perag_put(pag); + return error; +} + +/* * Unmap a range of blocks from a file, then map other blocks into the hole. * The range to unmap is (destoff : destoff + srcioff + irec->br_blockcount). * The extent irec is mapped into dest at irec->br_startoff. @@ -1087,6 +1113,14 @@ xfs_reflink_remap_extent( irec->br_startblock != DELAYSTARTBLOCK && !ISUNWRITTEN(irec)); + /* No reflinking if we're low on space */ + if (real_extent) { + error = xfs_reflink_ag_has_free_space(mp, + XFS_FSB_TO_AGNO(mp, irec->br_startblock)); + if (error) + goto out; + } + /* Start a rolling transaction to switch the mappings */ resblks = XFS_EXTENTADD_SPACE_RES(ip->i_mount, XFS_DATA_FORK); error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp); From darrick.wong@oracle.com Thu Jun 16 20:28:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2E4277F2D for ; Thu, 16 Jun 2016 20:28:45 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id E5881304048 for ; Thu, 16 Jun 2016 18:28:44 -0700 (PDT) X-ASG-Debug-ID: 1466126923-04cbb01fee69a00001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id nQ0rbPHKujBrDAgs (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:43 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Seu7031338 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:40 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1SdBZ015003 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:40 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Sdva025693; Fri, 17 Jun 2016 01:28:39 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:38 -0700 Subject: [PATCH 100/119] xfs: try other AGs to allocate a BMBT block From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 100/119] xfs: try other AGs to allocate a BMBT block To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:37 -0700 Message-ID: <146612691740.12839.10974086588065909798.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126923 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4665 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Prior to the introduction of reflink, allocating a block and mapping it into a file was performed in a single transaction with a single block reservation, and the allocator was supposed to find enough blocks to allocate the extent and any BMBT blocks that might be necessary (unless we're low on space). However, due to the way copy on write works, allocation and mapping have been split into two transactions, which means that we must be able to handle the case where we allocate an extent for CoW but that AG runs out of free space before the blocks can be mapped into a file, and the mapping requires a new BMBT block. When this happens, look in one of the other AGs for a BMBT block instead of taking the FS down. The same applies to the functions that convert a data fork to extents and later btree format. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_bmap.c | 30 ++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_bmap_btree.c | 17 +++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index a6c08bf..62ac322 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -753,6 +753,7 @@ xfs_bmap_extents_to_btree( args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); } else if (dfops->dop_low) { +try_another_ag: args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = *firstblock; } else { @@ -767,6 +768,21 @@ xfs_bmap_extents_to_btree( xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } + + /* + * During a CoW operation, the allocation and bmbt updates occur in + * different transactions. The mapping code tries to put new bmbt + * blocks near extents being mapped, but the only way to guarantee this + * is if the alloc and the mapping happen in a single transaction that + * has a block reservation. That isn't the case here, so if we run out + * of space we'll try again with another AG. + */ + if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && + args.fsbno == NULLFSBLOCK && + args.type == XFS_ALLOCTYPE_NEAR_BNO) { + dfops->dop_low = true; + goto try_another_ag; + } /* * Allocation can't fail, the space was reserved. */ @@ -902,6 +918,7 @@ xfs_bmap_local_to_extents( * file currently fits in an inode. */ if (*firstblock == NULLFSBLOCK) { +try_another_ag: args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino); args.type = XFS_ALLOCTYPE_START_BNO; } else { @@ -914,6 +931,19 @@ xfs_bmap_local_to_extents( if (error) goto done; + /* + * During a CoW operation, the allocation and bmbt updates occur in + * different transactions. The mapping code tries to put new bmbt + * blocks near extents being mapped, but the only way to guarantee this + * is if the alloc and the mapping happen in a single transaction that + * has a block reservation. That isn't the case here, so if we run out + * of space we'll try again with another AG. + */ + if (xfs_sb_version_hasreflink(&ip->i_mount->m_sb) && + args.fsbno == NULLFSBLOCK && + args.type == XFS_ALLOCTYPE_NEAR_BNO) { + goto try_another_ag; + } /* Can't fail, the space was reserved. */ ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(args.len == 1); diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index a5a8d37..9e7df9d 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -452,6 +452,7 @@ xfs_bmbt_alloc_block( if (args.fsbno == NULLFSBLOCK) { args.fsbno = be64_to_cpu(start->l); +try_another_ag: args.type = XFS_ALLOCTYPE_START_BNO; /* * Make sure there is sufficient room left in the AG to @@ -481,6 +482,22 @@ xfs_bmbt_alloc_block( if (error) goto error0; + /* + * During a CoW operation, the allocation and bmbt updates occur in + * different transactions. The mapping code tries to put new bmbt + * blocks near extents being mapped, but the only way to guarantee this + * is if the alloc and the mapping happen in a single transaction that + * has a block reservation. That isn't the case here, so if we run out + * of space we'll try again with another AG. + */ + if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && + args.fsbno == NULLFSBLOCK && + args.type == XFS_ALLOCTYPE_NEAR_BNO) { + cur->bc_private.b.dfops->dop_low = true; + args.fsbno = cur->bc_private.b.firstblock; + goto try_another_ag; + } + if (args.fsbno == NULLFSBLOCK && args.minleft) { /* * Could not find an AG with enough free space to satisfy From darrick.wong@oracle.com Thu Jun 16 20:28:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8E4C07E88 for ; Thu, 16 Jun 2016 20:28:50 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 50521304048 for ; Thu, 16 Jun 2016 18:28:50 -0700 (PDT) X-ASG-Debug-ID: 1466126928-04bdf01e1795cd0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id yzVZlGBLkgaVDuBv (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:48 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1SkrF031393 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:28:46 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1SkM0020261 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:46 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Sj5c025710; Fri, 17 Jun 2016 01:28:45 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:45 -0700 Subject: [PATCH 101/119] xfs: promote buffered writes to CoW when cowextsz is set From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 101/119] xfs: promote buffered writes to CoW when cowextsz is set To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:43 -0700 Message-ID: <146612692370.12839.6519871693319312435.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126928 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2321 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we're doing non-cow writes to a part of a file that already has a CoW reservation by virtue of cowextsz being set, promote the write to copy-on-write so that the entire extent can get written out as a single block, thereby reducing post-CoW fragmentation. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_aops.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 812bae5..31205fa 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -668,10 +668,12 @@ xfs_check_page_type( bh = head = page_buffers(page); do { if (buffer_unwritten(bh)) { - if (type == XFS_IO_UNWRITTEN) + if (type == XFS_IO_UNWRITTEN || + type == XFS_IO_COW) return true; } else if (buffer_delay(bh)) { - if (type == XFS_IO_DELALLOC) + if (type == XFS_IO_DELALLOC || + type == XFS_IO_COW) return true; } else if (buffer_dirty(bh) && buffer_mapped(bh)) { if (type == XFS_IO_OVERWRITE || @@ -836,25 +838,13 @@ xfs_writepage_map( continue; } - if (buffer_unwritten(bh)) { - if (wpc->io_type != XFS_IO_UNWRITTEN) { - wpc->io_type = XFS_IO_UNWRITTEN; - wpc->imap_valid = false; - } - } else if (buffer_delay(bh)) { - if (wpc->io_type != XFS_IO_DELALLOC) { - wpc->io_type = XFS_IO_DELALLOC; - wpc->imap_valid = false; - } - } else if (buffer_uptodate(bh)) { - new_type = xfs_is_cow_io(XFS_I(inode), offset) ? - XFS_IO_COW : XFS_IO_OVERWRITE; - - if (wpc->io_type != new_type) { - wpc->io_type = new_type; - wpc->imap_valid = false; - } - } else { + if (buffer_unwritten(bh)) + new_type = XFS_IO_UNWRITTEN; + else if (buffer_delay(bh)) + new_type = XFS_IO_DELALLOC; + else if (buffer_uptodate(bh)) + new_type = XFS_IO_OVERWRITE; + else { if (PageUptodate(page)) ASSERT(buffer_mapped(bh)); /* @@ -867,6 +857,13 @@ xfs_writepage_map( continue; } + if (xfs_is_cow_io(XFS_I(inode), offset)) + new_type = XFS_IO_COW; + if (wpc->io_type != new_type) { + wpc->io_type = new_type; + wpc->imap_valid = false; + } + if (wpc->imap_valid) wpc->imap_valid = xfs_imap_valid(inode, &wpc->imap, offset); From darrick.wong@oracle.com Thu Jun 16 20:29:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1500A7F5E for ; Thu, 16 Jun 2016 20:29:02 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id DAB35304048 for ; Thu, 16 Jun 2016 18:29:01 -0700 (PDT) X-ASG-Debug-ID: 1466126938-04cb6c542757b50001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 3dZlk5SHvvHDjYNd (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:28:58 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1SuGE031487 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:56 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1SuVE026679 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:28:56 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1SruT009025; Fri, 17 Jun 2016 01:28:55 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:53 -0700 Subject: [PATCH 102/119] xfs: garbage collect old cowextsz reservations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 102/119] xfs: garbage collect old cowextsz reservations To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:50 -0700 Message-ID: <146612692996.12839.9621556119809112650.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126938 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19990 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Trim CoW reservations made on behalf of a cowextsz hint if they get too old or we run low on quota, so long as we don't have dirty data awaiting writeback or directio operations in progress. Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_bmap_util.c | 3 + fs/xfs/xfs_file.c | 3 + fs/xfs/xfs_globals.c | 5 + fs/xfs/xfs_icache.c | 238 ++++++++++++++++++++++++++++++++++++++++++------ fs/xfs/xfs_icache.h | 7 + fs/xfs/xfs_inode.c | 4 + fs/xfs/xfs_iomap.c | 2 fs/xfs/xfs_linux.h | 1 fs/xfs/xfs_mount.c | 1 fs/xfs/xfs_mount.h | 2 fs/xfs/xfs_reflink.c | 35 +++++++ fs/xfs/xfs_reflink.h | 2 fs/xfs/xfs_super.c | 1 fs/xfs/xfs_sysctl.c | 9 ++ fs/xfs/xfs_sysctl.h | 1 fs/xfs/xfs_trace.h | 5 + 16 files changed, 287 insertions(+), 32 deletions(-) diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c index b0c2c6d5..584f276 100644 --- a/fs/xfs/xfs_bmap_util.c +++ b/fs/xfs/xfs_bmap_util.c @@ -1222,6 +1222,7 @@ xfs_free_cow_space( */ if (ip->i_d.di_nblocks == 0) { ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + xfs_inode_clear_cowblocks_tag(ip); xfs_trans_log_inode(*tpp, ip, XFS_ILOG_CORE); } out: @@ -1966,6 +1967,8 @@ xfs_swap_extents( cowfp = ip->i_cowfp; ip->i_cowfp = tip->i_cowfp; tip->i_cowfp = cowfp; + xfs_inode_set_cowblocks_tag(ip); + xfs_inode_set_cowblocks_tag(tip); } xfs_trans_log_inode(tp, ip, src_log_flags); diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 618bd12..ad6a467 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -859,6 +859,9 @@ write_retry: enospc = xfs_inode_free_quota_eofblocks(ip); if (enospc) goto write_retry; + enospc = xfs_inode_free_quota_cowblocks(ip); + if (enospc) + goto write_retry; } else if (ret == -ENOSPC && !enospc) { struct xfs_eofblocks eofb = {0}; diff --git a/fs/xfs/xfs_globals.c b/fs/xfs/xfs_globals.c index 4d41b24..f3f6aa9 100644 --- a/fs/xfs/xfs_globals.c +++ b/fs/xfs/xfs_globals.c @@ -21,8 +21,8 @@ /* * Tunable XFS parameters. xfs_params is required even when CONFIG_SYSCTL=n, * other XFS code uses these values. Times are measured in centisecs (i.e. - * 100ths of a second) with the exception of eofb_timer, which is measured in - * seconds. + * 100ths of a second) with the exception of eofb_timer and cowb_timer, which + * are measured in seconds. */ xfs_param_t xfs_params = { /* MIN DFLT MAX */ @@ -42,6 +42,7 @@ xfs_param_t xfs_params = { .inherit_nodfrg = { 0, 1, 1 }, .fstrm_timer = { 1, 30*100, 3600*100}, .eofb_timer = { 1, 300, 3600*24}, + .cowb_timer = { 1, 300, 3600*24}, }; struct xfs_globals xfs_globals = { diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 06f3b8c..884b570 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -33,6 +33,7 @@ #include "xfs_bmap_util.h" #include "xfs_dquot_item.h" #include "xfs_dquot.h" +#include "xfs_reflink.h" #include #include @@ -792,6 +793,33 @@ xfs_eofblocks_worker( xfs_queue_eofblocks(mp); } +/* + * Background scanning to trim preallocated CoW space. This is queued + * based on the 'speculative_cow_prealloc_lifetime' tunable (5m by default). + * (We'll just piggyback on the post-EOF prealloc space workqueue.) + */ +STATIC void +xfs_queue_cowblocks( + struct xfs_mount *mp) +{ + rcu_read_lock(); + if (radix_tree_tagged(&mp->m_perag_tree, XFS_ICI_COWBLOCKS_TAG)) + queue_delayed_work(mp->m_eofblocks_workqueue, + &mp->m_cowblocks_work, + msecs_to_jiffies(xfs_cowb_secs * 1000)); + rcu_read_unlock(); +} + +void +xfs_cowblocks_worker( + struct work_struct *work) +{ + struct xfs_mount *mp = container_of(to_delayed_work(work), + struct xfs_mount, m_cowblocks_work); + xfs_icache_free_cowblocks(mp, NULL); + xfs_queue_cowblocks(mp); +} + int xfs_inode_ag_iterator( struct xfs_mount *mp, @@ -1348,18 +1376,30 @@ xfs_inode_free_eofblocks( return ret; } -int -xfs_icache_free_eofblocks( +static int +__xfs_icache_free_eofblocks( struct xfs_mount *mp, - struct xfs_eofblocks *eofb) + struct xfs_eofblocks *eofb, + int (*execute)(struct xfs_inode *ip, int flags, + void *args), + int tag) { int flags = SYNC_TRYLOCK; if (eofb && (eofb->eof_flags & XFS_EOF_FLAGS_SYNC)) flags = SYNC_WAIT; - return xfs_inode_ag_iterator_tag(mp, xfs_inode_free_eofblocks, flags, - eofb, XFS_ICI_EOFBLOCKS_TAG); + return xfs_inode_ag_iterator_tag(mp, execute, flags, + eofb, tag); +} + +int +xfs_icache_free_eofblocks( + struct xfs_mount *mp, + struct xfs_eofblocks *eofb) +{ + return __xfs_icache_free_eofblocks(mp, eofb, xfs_inode_free_eofblocks, + XFS_ICI_EOFBLOCKS_TAG); } /* @@ -1368,9 +1408,11 @@ xfs_icache_free_eofblocks( * failure. We make a best effort by including each quota under low free space * conditions (less than 1% free space) in the scan. */ -int -xfs_inode_free_quota_eofblocks( - struct xfs_inode *ip) +static int +__xfs_inode_free_quota_eofblocks( + struct xfs_inode *ip, + int (*execute)(struct xfs_mount *mp, + struct xfs_eofblocks *eofb)) { int scan = 0; struct xfs_eofblocks eofb = {0}; @@ -1406,14 +1448,25 @@ xfs_inode_free_quota_eofblocks( } if (scan) - xfs_icache_free_eofblocks(ip->i_mount, &eofb); + execute(ip->i_mount, &eofb); return scan; } -void -xfs_inode_set_eofblocks_tag( - xfs_inode_t *ip) +int +xfs_inode_free_quota_eofblocks( + struct xfs_inode *ip) +{ + return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_eofblocks); +} + +static void +__xfs_inode_set_eofblocks_tag( + xfs_inode_t *ip, + void (*execute)(struct xfs_mount *mp), + void (*set_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, + int error, unsigned long caller_ip), + int tag) { struct xfs_mount *mp = ip->i_mount; struct xfs_perag *pag; @@ -1421,26 +1474,22 @@ xfs_inode_set_eofblocks_tag( pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); spin_lock(&pag->pag_ici_lock); - trace_xfs_inode_set_eofblocks_tag(ip); - tagged = radix_tree_tagged(&pag->pag_ici_root, - XFS_ICI_EOFBLOCKS_TAG); + tagged = radix_tree_tagged(&pag->pag_ici_root, tag); radix_tree_tag_set(&pag->pag_ici_root, - XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), - XFS_ICI_EOFBLOCKS_TAG); + XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), tag); if (!tagged) { /* propagate the eofblocks tag up into the perag radix tree */ spin_lock(&ip->i_mount->m_perag_lock); radix_tree_tag_set(&ip->i_mount->m_perag_tree, XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), - XFS_ICI_EOFBLOCKS_TAG); + tag); spin_unlock(&ip->i_mount->m_perag_lock); /* kick off background trimming */ - xfs_queue_eofblocks(ip->i_mount); + execute(ip->i_mount); - trace_xfs_perag_set_eofblocks(ip->i_mount, pag->pag_agno, - -1, _RET_IP_); + set_tp(ip->i_mount, pag->pag_agno, -1, _RET_IP_); } spin_unlock(&pag->pag_ici_lock); @@ -1448,31 +1497,162 @@ xfs_inode_set_eofblocks_tag( } void -xfs_inode_clear_eofblocks_tag( +xfs_inode_set_eofblocks_tag( xfs_inode_t *ip) { + trace_xfs_inode_set_eofblocks_tag(ip); + return __xfs_inode_set_eofblocks_tag(ip, xfs_queue_eofblocks, + trace_xfs_perag_set_eofblocks, + XFS_ICI_EOFBLOCKS_TAG); +} + +static void +__xfs_inode_clear_eofblocks_tag( + xfs_inode_t *ip, + void (*clear_tp)(struct xfs_mount *mp, xfs_agnumber_t agno, + int error, unsigned long caller_ip), + int tag) +{ struct xfs_mount *mp = ip->i_mount; struct xfs_perag *pag; pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); spin_lock(&pag->pag_ici_lock); - trace_xfs_inode_clear_eofblocks_tag(ip); radix_tree_tag_clear(&pag->pag_ici_root, - XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), - XFS_ICI_EOFBLOCKS_TAG); - if (!radix_tree_tagged(&pag->pag_ici_root, XFS_ICI_EOFBLOCKS_TAG)) { + XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), tag); + if (!radix_tree_tagged(&pag->pag_ici_root, tag)) { /* clear the eofblocks tag from the perag radix tree */ spin_lock(&ip->i_mount->m_perag_lock); radix_tree_tag_clear(&ip->i_mount->m_perag_tree, XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), - XFS_ICI_EOFBLOCKS_TAG); + tag); spin_unlock(&ip->i_mount->m_perag_lock); - trace_xfs_perag_clear_eofblocks(ip->i_mount, pag->pag_agno, - -1, _RET_IP_); + clear_tp(ip->i_mount, pag->pag_agno, -1, _RET_IP_); } spin_unlock(&pag->pag_ici_lock); xfs_perag_put(pag); } +void +xfs_inode_clear_eofblocks_tag( + xfs_inode_t *ip) +{ + trace_xfs_inode_clear_eofblocks_tag(ip); + return __xfs_inode_clear_eofblocks_tag(ip, + trace_xfs_perag_clear_eofblocks, XFS_ICI_EOFBLOCKS_TAG); +} + +/* + * Automatic CoW Reservation Freeing + * + * These functions automatically garbage collect leftover CoW reservations + * that were made on behalf of a cowextsize hint when we start to run out + * of quota or when the reservations sit around for too long. If the file + * has dirty pages or is undergoing writeback, its CoW reservations will + * be retained. + * + * The actual garbage collection piggybacks off the same code that runs + * the speculative EOF preallocation garbage collector. + */ +STATIC int +xfs_inode_free_cowblocks( + struct xfs_inode *ip, + int flags, + void *args) +{ + int ret; + struct xfs_eofblocks *eofb = args; + bool need_iolock = true; + int match; + + ASSERT(!eofb || (eofb && eofb->eof_scan_owner != 0)); + + if (!xfs_reflink_has_real_cow_blocks(ip)) { + trace_xfs_inode_free_cowblocks_invalid(ip); + xfs_inode_clear_cowblocks_tag(ip); + return 0; + } + + /* + * If the mapping is dirty or under writeback we cannot touch the + * CoW fork. Leave it alone if we're in the midst of a directio. + */ + if (mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_DIRTY) || + mapping_tagged(VFS_I(ip)->i_mapping, PAGECACHE_TAG_WRITEBACK) || + atomic_read(&VFS_I(ip)->i_dio_count)) + return 0; + + if (eofb) { + if (eofb->eof_flags & XFS_EOF_FLAGS_UNION) + match = xfs_inode_match_id_union(ip, eofb); + else + match = xfs_inode_match_id(ip, eofb); + if (!match) + return 0; + + /* skip the inode if the file size is too small */ + if (eofb->eof_flags & XFS_EOF_FLAGS_MINFILESIZE && + XFS_ISIZE(ip) < eofb->eof_min_file_size) + return 0; + + /* + * A scan owner implies we already hold the iolock. Skip it in + * xfs_free_eofblocks() to avoid deadlock. This also eliminates + * the possibility of EAGAIN being returned. + */ + if (eofb->eof_scan_owner == ip->i_ino) + need_iolock = false; + } + + /* Free the CoW blocks */ + if (need_iolock) { + xfs_ilock(ip, XFS_IOLOCK_EXCL); + xfs_ilock(ip, XFS_MMAPLOCK_EXCL); + } + + ret = xfs_reflink_cancel_cow_range(ip, 0, NULLFILEOFF); + + if (need_iolock) { + xfs_iunlock(ip, XFS_MMAPLOCK_EXCL); + xfs_iunlock(ip, XFS_IOLOCK_EXCL); + } + + return ret; +} + +int +xfs_icache_free_cowblocks( + struct xfs_mount *mp, + struct xfs_eofblocks *eofb) +{ + return __xfs_icache_free_eofblocks(mp, eofb, xfs_inode_free_cowblocks, + XFS_ICI_COWBLOCKS_TAG); +} + +int +xfs_inode_free_quota_cowblocks( + struct xfs_inode *ip) +{ + return __xfs_inode_free_quota_eofblocks(ip, xfs_icache_free_cowblocks); +} + +void +xfs_inode_set_cowblocks_tag( + xfs_inode_t *ip) +{ + trace_xfs_inode_set_eofblocks_tag(ip); + return __xfs_inode_set_eofblocks_tag(ip, xfs_queue_cowblocks, + trace_xfs_perag_set_eofblocks, + XFS_ICI_COWBLOCKS_TAG); +} + +void +xfs_inode_clear_cowblocks_tag( + xfs_inode_t *ip) +{ + trace_xfs_inode_clear_eofblocks_tag(ip); + return __xfs_inode_clear_eofblocks_tag(ip, + trace_xfs_perag_clear_eofblocks, XFS_ICI_COWBLOCKS_TAG); +} diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h index 62f1f91..a22ac92 100644 --- a/fs/xfs/xfs_icache.h +++ b/fs/xfs/xfs_icache.h @@ -40,6 +40,7 @@ struct xfs_eofblocks { in xfs_inode_ag_iterator */ #define XFS_ICI_RECLAIM_TAG 0 /* inode is to be reclaimed */ #define XFS_ICI_EOFBLOCKS_TAG 1 /* inode has blocks beyond EOF */ +#define XFS_ICI_COWBLOCKS_TAG 2 /* inode can have cow blocks to gc */ /* * Flags for xfs_iget() @@ -69,6 +70,12 @@ int xfs_icache_free_eofblocks(struct xfs_mount *, struct xfs_eofblocks *); int xfs_inode_free_quota_eofblocks(struct xfs_inode *ip); void xfs_eofblocks_worker(struct work_struct *); +void xfs_inode_set_cowblocks_tag(struct xfs_inode *ip); +void xfs_inode_clear_cowblocks_tag(struct xfs_inode *ip); +int xfs_icache_free_cowblocks(struct xfs_mount *, struct xfs_eofblocks *); +int xfs_inode_free_quota_cowblocks(struct xfs_inode *ip); +void xfs_cowblocks_worker(struct work_struct *); + int xfs_inode_ag_iterator(struct xfs_mount *mp, int (*execute)(struct xfs_inode *ip, int flags, void *args), int flags, void *args); diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 480e48a..fb9c2d7 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -1631,8 +1631,10 @@ xfs_itruncate_extents( /* * Clear the reflink flag if we truncated everything. */ - if (ip->i_d.di_nblocks == 0 && xfs_is_reflink_inode(ip)) + if (ip->i_d.di_nblocks == 0 && xfs_is_reflink_inode(ip)) { ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + xfs_inode_clear_cowblocks_tag(ip); + } /* * Always re-log the inode so that our permanent transaction can keep diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 3914f0f..58240b5 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -668,6 +668,8 @@ retry: */ if (prealloc) xfs_inode_set_eofblocks_tag(ip); + if (whichfork == XFS_COW_FORK && extsz > 0) + xfs_inode_set_cowblocks_tag(ip); *ret_imap = imap[0]; return 0; diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h index a8192dc..f05e2cf5 100644 --- a/fs/xfs/xfs_linux.h +++ b/fs/xfs/xfs_linux.h @@ -116,6 +116,7 @@ typedef __u32 xfs_nlink_t; #define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val #define xfs_fstrm_centisecs xfs_params.fstrm_timer.val #define xfs_eofb_secs xfs_params.eofb_timer.val +#define xfs_cowb_secs xfs_params.cowb_timer.val #define current_cpu() (raw_smp_processor_id()) #define current_pid() (current->pid) diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index db80832..e53853d 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -1015,6 +1015,7 @@ xfs_unmountfs( int error; cancel_delayed_work_sync(&mp->m_eofblocks_work); + cancel_delayed_work_sync(&mp->m_cowblocks_work); xfs_fs_unreserve_ag_blocks(mp); xfs_qm_unmount_quotas(mp); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index a516a1f..6b06d24 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -158,6 +158,8 @@ typedef struct xfs_mount { struct delayed_work m_reclaim_work; /* background inode reclaim */ struct delayed_work m_eofblocks_work; /* background eof blocks trimming */ + struct delayed_work m_cowblocks_work; /* background cow blocks + trimming */ bool m_update_sb; /* sb needs update in mount */ int64_t m_low_space[XFS_LOWSP_MAX]; /* low free space thresholds */ diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index f5195b7..9b14eb5 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1727,6 +1727,7 @@ next: /* Clear the inode flag. */ trace_xfs_reflink_unset_inode_flag(ip); ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK; + xfs_inode_clear_cowblocks_tag(ip); xfs_trans_ijoin(tp, ip, 0); xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); @@ -1864,3 +1865,37 @@ xfs_reflink_check_flag_adjust( } return 0; } + +/* + * Does this inode have any real CoW reservations? + */ +bool +xfs_reflink_has_real_cow_blocks( + struct xfs_inode *ip) +{ + struct xfs_bmbt_irec irec; + struct xfs_ifork *ifp; + struct xfs_bmbt_rec_host *gotp; + xfs_extnum_t idx; + + if (!xfs_is_reflink_inode(ip)) + return false; + + /* Go find the old extent in the CoW fork. */ + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + gotp = xfs_iext_bno_to_ext(ifp, 0, &idx); + while (gotp) { + xfs_bmbt_get_all(gotp, &irec); + + if (!isnullstartblock(irec.br_startblock)) + return true; + + /* Roll on... */ + idx++; + if (idx >= ifp->if_bytes / sizeof(xfs_bmbt_rec_t)) + break; + gotp = xfs_iext_get_ext(ifp, idx); + } + + return false; +} diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index 97e8705..12c2bc6 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h @@ -56,6 +56,8 @@ extern void xfs_reflink_get_lxflags(struct xfs_inode *ip, unsigned int *flags); extern int xfs_reflink_check_flag_adjust(struct xfs_inode *ip, unsigned int *xflags); +extern bool xfs_reflink_has_real_cow_blocks(struct xfs_inode *ip); + /* xfs_aops.c */ extern int xfs_map_cow_blocks(struct inode *inode, xfs_off_t offset, struct xfs_bmbt_irec *imap); diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 10a0f721..93d159a 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1504,6 +1504,7 @@ xfs_fs_fill_super( atomic_set(&mp->m_active_trans, 0); INIT_DELAYED_WORK(&mp->m_reclaim_work, xfs_reclaim_worker); INIT_DELAYED_WORK(&mp->m_eofblocks_work, xfs_eofblocks_worker); + INIT_DELAYED_WORK(&mp->m_cowblocks_work, xfs_cowblocks_worker); mp->m_kobj.kobject.kset = xfs_kset; mp->m_super = sb; diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c index aed74d3..afe1f66 100644 --- a/fs/xfs/xfs_sysctl.c +++ b/fs/xfs/xfs_sysctl.c @@ -184,6 +184,15 @@ static struct ctl_table xfs_table[] = { .extra1 = &xfs_params.eofb_timer.min, .extra2 = &xfs_params.eofb_timer.max, }, + { + .procname = "speculative_cow_prealloc_lifetime", + .data = &xfs_params.cowb_timer.val, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &xfs_params.cowb_timer.min, + .extra2 = &xfs_params.cowb_timer.max, + }, /* please keep this the last entry */ #ifdef CONFIG_PROC_FS { diff --git a/fs/xfs/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h index ffef453..984a349 100644 --- a/fs/xfs/xfs_sysctl.h +++ b/fs/xfs/xfs_sysctl.h @@ -48,6 +48,7 @@ typedef struct xfs_param { xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */ xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */ xfs_sysctl_val_t eofb_timer; /* Interval between eofb scan wakeups */ + xfs_sysctl_val_t cowb_timer; /* Interval between cowb scan wakeups */ } xfs_param_t; /* diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index fe4a5be..1d89f8f 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -136,6 +136,8 @@ DEFINE_PERAG_REF_EVENT(xfs_perag_set_reclaim); DEFINE_PERAG_REF_EVENT(xfs_perag_clear_reclaim); DEFINE_PERAG_REF_EVENT(xfs_perag_set_eofblocks); DEFINE_PERAG_REF_EVENT(xfs_perag_clear_eofblocks); +DEFINE_PERAG_REF_EVENT(xfs_perag_set_cowblocks); +DEFINE_PERAG_REF_EVENT(xfs_perag_clear_cowblocks); DECLARE_EVENT_CLASS(xfs_ag_class, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno), @@ -687,6 +689,9 @@ DEFINE_INODE_EVENT(xfs_dquot_dqdetach); DEFINE_INODE_EVENT(xfs_inode_set_eofblocks_tag); DEFINE_INODE_EVENT(xfs_inode_clear_eofblocks_tag); DEFINE_INODE_EVENT(xfs_inode_free_eofblocks_invalid); +DEFINE_INODE_EVENT(xfs_inode_set_cowblocks_tag); +DEFINE_INODE_EVENT(xfs_inode_clear_cowblocks_tag); +DEFINE_INODE_EVENT(xfs_inode_free_cowblocks_invalid); DEFINE_INODE_EVENT(xfs_filemap_fault); DEFINE_INODE_EVENT(xfs_filemap_pmd_fault); From darrick.wong@oracle.com Thu Jun 16 20:29:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 859D07F74 for ; Thu, 16 Jun 2016 20:29:06 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id F33CCAC003 for ; Thu, 16 Jun 2016 18:29:05 -0700 (PDT) X-ASG-Debug-ID: 1466126943-04cbb01fed69a20001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 3RscvonZU2xXZZ0F (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1T1bZ031568 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:29:01 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1T1SQ020633 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:01 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1T0TX025762; Fri, 17 Jun 2016 01:29:00 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:28:59 -0700 Subject: [PATCH 103/119] xfs: provide switch to force filesystem to copy-on-write all the time From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 103/119] xfs: provide switch to force filesystem to copy-on-write all the time To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:28:58 -0700 Message-ID: <146612693844.12839.11077451764521265088.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126944 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2905 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Make it possible to force XFS to use copy on write all the time, at least if reflink is turned on. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_refcount.c | 6 ++++++ fs/xfs/xfs_globals.c | 1 + fs/xfs/xfs_linux.h | 1 + fs/xfs/xfs_sysctl.c | 11 +++++++++++ fs/xfs/xfs_sysctl.h | 1 + 5 files changed, 20 insertions(+) diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 88f91d5..fd4369f 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1190,6 +1190,12 @@ xfs_refcount_find_shared( trace_xfs_refcount_find_shared(mp, agno, agbno, aglen); + if (xfs_always_cow) { + *fbno = agbno; + *flen = aglen; + return 0; + } + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) goto out; diff --git a/fs/xfs/xfs_globals.c b/fs/xfs/xfs_globals.c index f3f6aa9..9a55966 100644 --- a/fs/xfs/xfs_globals.c +++ b/fs/xfs/xfs_globals.c @@ -43,6 +43,7 @@ xfs_param_t xfs_params = { .fstrm_timer = { 1, 30*100, 3600*100}, .eofb_timer = { 1, 300, 3600*24}, .cowb_timer = { 1, 300, 3600*24}, + .always_cow = { 0, 0, 1 }, }; struct xfs_globals xfs_globals = { diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h index f05e2cf5..b70abad 100644 --- a/fs/xfs/xfs_linux.h +++ b/fs/xfs/xfs_linux.h @@ -117,6 +117,7 @@ typedef __u32 xfs_nlink_t; #define xfs_fstrm_centisecs xfs_params.fstrm_timer.val #define xfs_eofb_secs xfs_params.eofb_timer.val #define xfs_cowb_secs xfs_params.cowb_timer.val +#define xfs_always_cow xfs_params.always_cow.val #define current_cpu() (raw_smp_processor_id()) #define current_pid() (current->pid) diff --git a/fs/xfs/xfs_sysctl.c b/fs/xfs/xfs_sysctl.c index afe1f66..650b8d5 100644 --- a/fs/xfs/xfs_sysctl.c +++ b/fs/xfs/xfs_sysctl.c @@ -193,6 +193,17 @@ static struct ctl_table xfs_table[] = { .extra1 = &xfs_params.cowb_timer.min, .extra2 = &xfs_params.cowb_timer.max, }, +#ifdef DEBUG + { + .procname = "always_cow", + .data = &xfs_params.always_cow.val, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &xfs_params.always_cow.min, + .extra2 = &xfs_params.always_cow.max, + }, +#endif /* please keep this the last entry */ #ifdef CONFIG_PROC_FS { diff --git a/fs/xfs/xfs_sysctl.h b/fs/xfs/xfs_sysctl.h index 984a349..16099dc 100644 --- a/fs/xfs/xfs_sysctl.h +++ b/fs/xfs/xfs_sysctl.h @@ -49,6 +49,7 @@ typedef struct xfs_param { xfs_sysctl_val_t fstrm_timer; /* Filestream dir-AG assoc'n timeout. */ xfs_sysctl_val_t eofb_timer; /* Interval between eofb scan wakeups */ xfs_sysctl_val_t cowb_timer; /* Interval between cowb scan wakeups */ + xfs_sysctl_val_t always_cow; /* Always copy on write? */ } xfs_param_t; /* From darrick.wong@oracle.com Thu Jun 16 20:29:17 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 90A1B7F6C for ; Thu, 16 Jun 2016 20:29:17 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 50DD98F804B for ; Thu, 16 Jun 2016 18:29:17 -0700 (PDT) X-ASG-Debug-ID: 1466126954-04bdf01e1395d00001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 6TksABSxAvgpZKfJ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1T9sl012502 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:10 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1T9Gk027030 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:09 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1T8tG029894; Fri, 17 Jun 2016 01:29:08 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:06 -0700 Subject: [PATCH 104/119] xfs: increase log reservations for reflink From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 104/119] xfs: increase log reservations for reflink To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:04 -0700 Message-ID: <146612694469.12839.5547568012324469527.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126955 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2691 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Increase the log reservations to handle the increased rolling that happens at the end of copy-on-write operations. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_trans_resv.c | 16 +++++++++++++--- fs/xfs/libxfs/xfs_trans_resv.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c index a59838f..b456cca 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.c +++ b/fs/xfs/libxfs/xfs_trans_resv.c @@ -812,11 +812,18 @@ xfs_trans_resv_calc( * require a permanent reservation on space. */ resp->tr_write.tr_logres = xfs_calc_write_reservation(mp); - resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; + else + resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp); - resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + resp->tr_itruncate.tr_logcount = + XFS_ITRUNCATE_LOG_COUNT_REFLINK; + else + resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp); @@ -873,7 +880,10 @@ xfs_trans_resv_calc( resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp); - resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; + else + resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; /* diff --git a/fs/xfs/libxfs/xfs_trans_resv.h b/fs/xfs/libxfs/xfs_trans_resv.h index 36a1511..b7e5357 100644 --- a/fs/xfs/libxfs/xfs_trans_resv.h +++ b/fs/xfs/libxfs/xfs_trans_resv.h @@ -87,6 +87,7 @@ struct xfs_trans_resv { #define XFS_DEFAULT_LOG_COUNT 1 #define XFS_DEFAULT_PERM_LOG_COUNT 2 #define XFS_ITRUNCATE_LOG_COUNT 2 +#define XFS_ITRUNCATE_LOG_COUNT_REFLINK 8 #define XFS_INACTIVE_LOG_COUNT 2 #define XFS_CREATE_LOG_COUNT 2 #define XFS_CREATE_TMPFILE_LOG_COUNT 2 @@ -96,6 +97,7 @@ struct xfs_trans_resv { #define XFS_LINK_LOG_COUNT 2 #define XFS_RENAME_LOG_COUNT 2 #define XFS_WRITE_LOG_COUNT 2 +#define XFS_WRITE_LOG_COUNT_REFLINK 8 #define XFS_ADDAFORK_LOG_COUNT 2 #define XFS_ATTRINVAL_LOG_COUNT 1 #define XFS_ATTRSET_LOG_COUNT 3 From darrick.wong@oracle.com Thu Jun 16 20:29:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B58727F83 for ; Thu, 16 Jun 2016 20:29:22 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 679E48F804B for ; Thu, 16 Jun 2016 18:29:22 -0700 (PDT) X-ASG-Debug-ID: 1466126958-04bdf01e1795d10001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id JTAi4nqEFTE1mvU4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1TGhT031980 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:29:16 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1TFcT020982 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:16 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TEUl021348; Fri, 17 Jun 2016 01:29:15 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:14 -0700 Subject: [PATCH 105/119] xfs: use interval query for rmap alloc operations on shared files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 105/119] xfs: use interval query for rmap alloc operations on shared files To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:13 -0700 Message-ID: <146612695294.12839.18445352357542834698.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126958 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 20393 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When it's possible for reverse mappings to overlap (data fork extents of files on reflink filesystems), use the interval query function to find the left neighbor of an extent we're trying to add; and be careful to use the lookup functions to update the neighbors and/or add new extents. v2: xfs_rmap_find_left_neighbor() needs to calculate the high key of a query range correctly. We can also add a few shortcuts -- there are no left neighbors of a query at offset zero. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rmap.c | 483 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.h | 7 + fs/xfs/xfs_log_recover.c | 6 fs/xfs/xfs_trace.h | 14 + 4 files changed, 507 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 611107c..a9bd522 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -211,6 +211,160 @@ xfs_rmap_get_rec( return xfs_rmapbt_btrec_to_irec(rec, irec); } +struct xfs_find_left_neighbor_info { + struct xfs_rmap_irec high; + struct xfs_rmap_irec *irec; + int *stat; +}; + +/* For each rmap given, figure out if it matches the key we want. */ +STATIC int +xfs_rmap_find_left_neighbor_helper( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct xfs_find_left_neighbor_info *info = priv; + + trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, + cur->bc_private.a.agno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + rec->rm_flags); + + if (rec->rm_owner != info->high.rm_owner) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && + !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && + rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + + *info->irec = *rec; + *info->stat = 1; + return XFS_BTREE_QUERY_RANGE_ABORT; +} + +/* + * Find the record to the left of the given extent, being careful only to + * return a match with the same owner and adjacent physical and logical + * block ranges. + */ +int +xfs_rmap_find_left_neighbor( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + uint64_t owner, + uint64_t offset, + unsigned int flags, + struct xfs_rmap_irec *irec, + int *stat) +{ + struct xfs_find_left_neighbor_info info; + int error; + + *stat = 0; + if (bno == 0) + return 0; + info.high.rm_startblock = bno - 1; + info.high.rm_owner = owner; + if (!XFS_RMAP_NON_INODE_OWNER(owner) && + !(flags & XFS_RMAP_BMBT_BLOCK)) { + if (offset == 0) + return 0; + info.high.rm_offset = offset - 1; + } else + info.high.rm_offset = 0; + info.high.rm_flags = flags; + info.high.rm_blockcount = 0; + info.irec = irec; + info.stat = stat; + + trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, + cur->bc_private.a.agno, bno, 0, owner, offset, flags); + + error = xfs_rmapbt_query_range(cur, &info.high, &info.high, + xfs_rmap_find_left_neighbor_helper, &info); + if (error == XFS_BTREE_QUERY_RANGE_ABORT) + error = 0; + if (*stat) + trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, + cur->bc_private.a.agno, irec->rm_startblock, + irec->rm_blockcount, irec->rm_owner, + irec->rm_offset, irec->rm_flags); + return error; +} + +/* For each rmap given, figure out if it matches the key we want. */ +STATIC int +xfs_rmap_lookup_le_range_helper( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct xfs_find_left_neighbor_info *info = priv; + + trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, + cur->bc_private.a.agno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + rec->rm_flags); + + if (rec->rm_owner != info->high.rm_owner) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && + !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && + (rec->rm_offset > info->high.rm_offset || + rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + + *info->irec = *rec; + *info->stat = 1; + return XFS_BTREE_QUERY_RANGE_ABORT; +} + +/* + * Find the record to the left of the given extent, being careful only to + * return a match with the same owner and overlapping physical and logical + * block ranges. This is the overlapping-interval version of + * xfs_rmap_lookup_le. + */ +int +xfs_rmap_lookup_le_range( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + uint64_t owner, + uint64_t offset, + unsigned int flags, + struct xfs_rmap_irec *irec, + int *stat) +{ + struct xfs_find_left_neighbor_info info; + int error; + + info.high.rm_startblock = bno; + info.high.rm_owner = owner; + if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) + info.high.rm_offset = offset; + else + info.high.rm_offset = 0; + info.high.rm_flags = flags; + info.high.rm_blockcount = 0; + *stat = 0; + info.irec = irec; + info.stat = stat; + + trace_xfs_rmap_lookup_le_range(cur->bc_mp, + cur->bc_private.a.agno, bno, 0, owner, offset, flags); + error = xfs_rmapbt_query_range(cur, &info.high, &info.high, + xfs_rmap_lookup_le_range_helper, &info); + if (error == XFS_BTREE_QUERY_RANGE_ABORT) + error = 0; + if (*stat) + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, irec->rm_startblock, + irec->rm_blockcount, irec->rm_owner, + irec->rm_offset, irec->rm_flags); + return error; +} + /* * Find the extent in the rmap btree and remove it. * @@ -1159,6 +1313,168 @@ xfs_rmap_unmap( } /* + * Find an extent in the rmap btree and unmap it. For rmap extent types that + * can overlap (data fork rmaps on reflink filesystems) we must be careful + * that the prev/next records in the btree might belong to another owner. + * Therefore we must use delete+insert to alter any of the key fields. + * + * For every other situation there can only be one owner for a given extent, + * so we can call the regular _free function. + */ +STATIC int +xfs_rmap_unmap_shared( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + uint64_t ltoff; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * We should always have a left record because there's a static record + * for the AG headers at rm_startblock == 0 created by mkfs/growfs that + * will not ever be removed from the tree. + */ + error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, + <rec, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + ltoff = ltrec.rm_offset; + + /* Make sure the extent we found covers the entire freeing range. */ + XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && + ltrec.rm_startblock + ltrec.rm_blockcount >= + bno + len, out_error); + + /* Make sure the owner matches what we expect to find in the tree. */ + XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error); + + /* Make sure the unwritten flag matches. */ + XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == + (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); + + /* Check the offset. */ + XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error); + XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount, + out_error); + + if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { + /* Exact match, simply remove the record from rmap tree. */ + error = xfs_rmapbt_delete(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + if (error) + goto out_error; + } else if (ltrec.rm_startblock == bno) { + /* + * Overlap left hand side of extent: move the start, trim the + * length and update the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + + /* Delete prev rmap. */ + error = xfs_rmapbt_delete(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + if (error) + goto out_error; + + /* Add an rmap at the new offset. */ + ltrec.rm_startblock += len; + ltrec.rm_blockcount -= len; + ltrec.rm_offset += len; + error = xfs_rmapbt_insert(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + if (error) + goto out_error; + } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { + /* + * Overlap right hand side of extent: trim the length and + * update the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + ltrec.rm_blockcount -= len; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else { + /* + * Overlap middle of extent: trim the length of the existing + * record to the length of the new left-extent size, increment + * the insertion position so we can insert a new record + * containing the remaining right-extent space. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrr| |rrrr| + * bno len + */ + xfs_extlen_t orig_len = ltrec.rm_blockcount; + + /* Shrink the left side of the rmap */ + error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + ltrec.rm_blockcount = bno - ltrec.rm_startblock; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + + /* Add an rmap at the new offset */ + error = xfs_rmapbt_insert(cur, bno + len, + orig_len - len - ltrec.rm_blockcount, + ltrec.rm_owner, offset + len, + ltrec.rm_flags); + if (error) + goto out_error; + } + + trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_unmap_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* * Find an extent in the rmap btree and map it. */ STATIC int @@ -1172,6 +1488,159 @@ xfs_rmap_map( return __xfs_rmap_alloc(cur, bno, len, unwritten, oinfo); } +/* + * Find an extent in the rmap btree and map it. For rmap extent types that + * can overlap (data fork rmaps on reflink filesystems) we must be careful + * that the prev/next records in the btree might belong to another owner. + * Therefore we must use delete+insert to alter any of the key fields. + * + * For every other situation there can only be one owner for a given extent, + * so we can call the regular _alloc function. + */ +STATIC int +xfs_rmap_map_shared( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + struct xfs_rmap_irec gtrec; + int have_gt; + int have_lt; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags = 0; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* Is there a left record that abuts our range? */ + error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, + <rec, &have_lt); + if (error) + goto out_error; + if (have_lt && + !xfs_rmap_is_mergeable(<rec, owner, offset, len, flags)) + have_lt = 0; + + /* Is there a right record that abuts our range? */ + error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, + flags, &have_gt); + if (error) + goto out_error; + if (have_gt) { + error = xfs_rmap_get_rec(cur, >rec, &have_gt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); + trace_xfs_rmap_map_gtrec(cur->bc_mp, + cur->bc_private.a.agno, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + + if (!xfs_rmap_is_mergeable(>rec, owner, offset, len, flags)) + have_gt = 0; + } + + if (have_lt && + ltrec.rm_startblock + ltrec.rm_blockcount == bno && + ltrec.rm_offset + ltrec.rm_blockcount == offset) { + /* + * Left edge contiguous, merge into left record. + * + * ltbno ltlen + * orig: |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + ltrec.rm_blockcount += len; + if (have_gt && + bno + len == gtrec.rm_startblock && + offset + len == gtrec.rm_offset) { + /* + * Right edge also contiguous, delete right record + * and merge into left record. + * + * ltbno ltlen gtbno gtlen + * orig: |ooooooooo| |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| + */ + ltrec.rm_blockcount += gtrec.rm_blockcount; + error = xfs_rmapbt_delete(cur, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (error) + goto out_error; + } + + /* Point the cursor back to the left record and update. */ + error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else if (have_gt && + bno + len == gtrec.rm_startblock && + offset + len == gtrec.rm_offset) { + /* + * Right edge contiguous, merge into right record. + * + * gtbno gtlen + * Orig: |ooooooooo| + * adding: |aaaaaaaaa| + * Result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + /* Delete the old record. */ + error = xfs_rmapbt_delete(cur, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (error) + goto out_error; + + /* Move the start and re-add it. */ + gtrec.rm_startblock = bno; + gtrec.rm_blockcount += len; + gtrec.rm_offset = offset; + error = xfs_rmapbt_insert(cur, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (error) + goto out_error; + } else { + /* + * No contiguous edge with identical owner, insert + * new record at current cursor position. + */ + error = xfs_rmapbt_insert(cur, bno, len, owner, offset, flags); + if (error) + goto out_error; + } + + trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_map_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + struct xfs_rmapbt_query_range_info { xfs_rmapbt_query_range_fn fn; void *priv; @@ -1304,10 +1773,18 @@ xfs_rmap_finish_one( case XFS_RMAP_MAP: error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); break; + case XFS_RMAP_MAP_SHARED: + error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten, + &oinfo); + break; case XFS_RMAP_UNMAP: error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, &oinfo); break; + case XFS_RMAP_UNMAP_SHARED: + error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten, + &oinfo); + break; case XFS_RMAP_CONVERT: error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, &oinfo); @@ -1375,7 +1852,8 @@ xfs_rmap_map_extent( { struct xfs_rmap_intent ri; - ri.ri_type = XFS_RMAP_MAP; + ri.ri_type = xfs_is_reflink_inode(ip) ? XFS_RMAP_MAP_SHARED : + XFS_RMAP_MAP; ri.ri_owner = ip->i_ino; ri.ri_whichfork = whichfork; ri.ri_bmap = *PREV; @@ -1394,7 +1872,8 @@ xfs_rmap_unmap_extent( { struct xfs_rmap_intent ri; - ri.ri_type = XFS_RMAP_UNMAP; + ri.ri_type = xfs_is_reflink_inode(ip) ? XFS_RMAP_UNMAP_SHARED : + XFS_RMAP_UNMAP; ri.ri_owner = ip->i_ino; ri.ri_whichfork = whichfork; ri.ri_bmap = *PREV; diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index f398e8b..5baa81f 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -70,6 +70,13 @@ int xfs_rmapbt_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno, int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat); +int xfs_rmap_find_left_neighbor(struct xfs_btree_cur *cur, xfs_agblock_t bno, + uint64_t owner, uint64_t offset, unsigned int flags, + struct xfs_rmap_irec *irec, int *stat); +int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_agblock_t bno, + uint64_t owner, uint64_t offset, unsigned int flags, + struct xfs_rmap_irec *irec, int *stat); + /* functions for updating the rmapbt for bmbt blocks and AG btree blocks */ int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 58a700b..b2d2e0a 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4774,9 +4774,15 @@ xlog_recover_process_rui( case XFS_RMAP_EXTENT_MAP: type = XFS_RMAP_MAP; break; + case XFS_RMAP_EXTENT_MAP_SHARED: + type = XFS_RMAP_MAP_SHARED; + break; case XFS_RMAP_EXTENT_UNMAP: type = XFS_RMAP_UNMAP; break; + case XFS_RMAP_EXTENT_UNMAP_SHARED: + type = XFS_RMAP_UNMAP_SHARED; + break; case XFS_RMAP_EXTENT_CONVERT: type = XFS_RMAP_CONVERT; break; diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 1d89f8f..d64bab7 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2509,6 +2509,13 @@ DEFINE_RMAP_EVENT(xfs_rmap_convert_done); DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_error); DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_state); +DEFINE_RMAP_EVENT(xfs_rmap_unmap); +DEFINE_RMAP_EVENT(xfs_rmap_unmap_done); +DEFINE_AG_ERROR_EVENT(xfs_rmap_unmap_error); +DEFINE_RMAP_EVENT(xfs_rmap_map); +DEFINE_RMAP_EVENT(xfs_rmap_map_done); +DEFINE_AG_ERROR_EVENT(xfs_rmap_map_error); + DECLARE_EVENT_CLASS(xfs_rmapbt_class, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, @@ -2560,10 +2567,15 @@ DEFINE_RMAPBT_EVENT(xfs_rmapbt_delete); DEFINE_AG_ERROR_EVENT(xfs_rmapbt_insert_error); DEFINE_AG_ERROR_EVENT(xfs_rmapbt_delete_error); DEFINE_AG_ERROR_EVENT(xfs_rmapbt_update_error); + +DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_candidate); +DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result); +DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_query); +DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_candidate); DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_result); +DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range); DEFINE_RMAPBT_EVENT(xfs_rmap_map_gtrec); DEFINE_RMAPBT_EVENT(xfs_rmap_convert_gtrec); -DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result); /* deferred bmbt updates */ #define DEFINE_BMAP_DEFERRED_EVENT DEFINE_RMAP_DEFERRED_EVENT From darrick.wong@oracle.com Thu Jun 16 20:29:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 929907F85 for ; Thu, 16 Jun 2016 20:29:28 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0CFD4AC002 for ; Thu, 16 Jun 2016 18:29:27 -0700 (PDT) X-ASG-Debug-ID: 1466126964-04cb6c542757b80001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id NaH3tix9unMRRi70 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:24 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1TMlo032049 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:22 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TMo5027302 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:22 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TLev021362; Fri, 17 Jun 2016 01:29:21 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:20 -0700 Subject: [PATCH 106/119] xfs: convert unwritten status of reverse mappings for shared files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 106/119] xfs: convert unwritten status of reverse mappings for shared files To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:19 -0700 Message-ID: <146612695940.12839.9168024514454491402.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126964 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13625 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a function to convert an unwritten extent to a real one and vice versa when shared extents are possible. v2: Move rmap unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rmap.c | 385 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_log_recover.c | 3 2 files changed, 387 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index a9bd522..29d08fc 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -1293,6 +1293,384 @@ xfs_rmap_convert( return __xfs_rmap_convert(cur, bno, len, unwritten, oinfo); } +/* + * Convert an unwritten extent to a real extent or vice versa. If there is no + * possibility of overlapping extents, delegate to the simpler convert + * function. + */ +STATIC int +xfs_rmap_convert_shared( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec r[4]; /* neighbor extent entries */ + /* left is 0, right is 1, prev is 2 */ + /* new is 3 */ + uint64_t owner; + uint64_t offset; + uint64_t new_endoff; + unsigned int oldext; + unsigned int newext; + unsigned int flags = 0; + int i; + int state = 0; + int error; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); + oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; + new_endoff = offset + len; + trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * For the initial lookup, look for and exact match or the left-adjacent + * record for our insertion point. This will also give us the record for + * start block contiguity tests. + */ + error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, + &PREV, &i); + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + + ASSERT(PREV.rm_offset <= offset); + ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); + ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); + newext = ~oldext & XFS_RMAP_UNWRITTEN; + + /* + * Set flags determining what part of the previous oldext allocation + * extent is being replaced by a newext allocation. + */ + if (PREV.rm_offset == offset) + state |= RMAP_LEFT_FILLING; + if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) + state |= RMAP_RIGHT_FILLING; + + /* Is there a left record that abuts our range? */ + error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, + &LEFT, &i); + if (error) + goto done; + if (i) { + state |= RMAP_LEFT_VALID; + XFS_WANT_CORRUPTED_GOTO(mp, + LEFT.rm_startblock + LEFT.rm_blockcount <= bno, + done); + if (xfs_rmap_is_mergeable(&LEFT, owner, offset, len, newext)) + state |= RMAP_LEFT_CONTIG; + } + + /* Is there a right record that abuts our range? */ + error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, + newext, &i); + if (error) + goto done; + if (i) { + state |= RMAP_RIGHT_VALID; + error = xfs_rmap_get_rec(cur, &RIGHT, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, + done); + trace_xfs_rmap_convert_gtrec(cur->bc_mp, + cur->bc_private.a.agno, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (xfs_rmap_is_mergeable(&RIGHT, owner, offset, len, newext)) + state |= RMAP_RIGHT_CONTIG; + } + + /* check that left + prev + right is not too long */ + if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == + (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && + (unsigned long)LEFT.rm_blockcount + len + + RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) + state &= ~RMAP_RIGHT_CONTIG; + + trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, + _RET_IP_); + /* + * Switch out based on the FILLING and CONTIG state bits. + */ + switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left and right neighbors are both contiguous with new. + */ + error = xfs_rmapbt_delete(cur, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (error) + goto done; + error = xfs_rmapbt_delete(cur, PREV.rm_startblock, + PREV.rm_blockcount, PREV.rm_owner, + PREV.rm_offset, PREV.rm_flags); + if (error) + goto done; + NEW = LEFT; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left neighbor is contiguous, the right is not. + */ + error = xfs_rmapbt_delete(cur, PREV.rm_startblock, + PREV.rm_blockcount, PREV.rm_owner, + PREV.rm_offset, PREV.rm_flags); + if (error) + goto done; + NEW = LEFT; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += PREV.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The right neighbor is contiguous, the left is not. + */ + error = xfs_rmapbt_delete(cur, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (error) + goto done; + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += RIGHT.rm_blockcount; + NEW.rm_flags = RIGHT.rm_flags; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: + /* + * Setting all of a previous oldext extent to newext. + * Neither the left nor right neighbors are contiguous with + * the new one. + */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_flags = newext; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is contiguous. + */ + NEW = PREV; + error = xfs_rmapbt_delete(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW.rm_offset += len; + NEW.rm_startblock += len; + NEW.rm_blockcount -= len; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW = LEFT; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is not contiguous. + */ + NEW = PREV; + error = xfs_rmapbt_delete(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW.rm_offset += len; + NEW.rm_startblock += len; + NEW.rm_blockcount -= len; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + error = xfs_rmapbt_insert(cur, bno, len, owner, offset, newext); + if (error) + goto done; + break; + + case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is contiguous with the new allocation. + */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount = offset - NEW.rm_offset; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + NEW = RIGHT; + error = xfs_rmapbt_delete(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW.rm_offset = offset; + NEW.rm_startblock = bno; + NEW.rm_blockcount += len; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + break; + + case RMAP_RIGHT_FILLING: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is not contiguous. + */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_rmapbt_insert(cur, bno, len, owner, offset, newext); + if (error) + goto done; + break; + + case 0: + /* + * Setting the middle part of a previous oldext extent to + * newext. Contiguity is impossible here. + * One extent becomes three extents. + */ + /* new right extent - oldext */ + NEW.rm_startblock = bno + len; + NEW.rm_owner = owner; + NEW.rm_offset = new_endoff; + NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - + new_endoff; + NEW.rm_flags = PREV.rm_flags; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, + NEW.rm_flags); + if (error) + goto done; + /* new left extent - oldext */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount = offset - NEW.rm_offset; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + /* new middle extent - newext */ + NEW.rm_startblock = bno; + NEW.rm_blockcount = len; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_flags = newext; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, + NEW.rm_flags); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_CONTIG: + case RMAP_RIGHT_CONTIG: + /* + * These cases are all impossible. + */ + ASSERT(0); + } + + trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +done: + if (error) + trace_xfs_rmap_convert_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + #undef NEW #undef LEFT #undef RIGHT @@ -1789,6 +2167,10 @@ xfs_rmap_finish_one( error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, &oinfo); break; + case XFS_RMAP_CONVERT_SHARED: + error = xfs_rmap_convert_shared(rcur, bno, blockcount, + !unwritten, &oinfo); + break; case XFS_RMAP_ALLOC: error = __xfs_rmap_alloc(rcur, bno, blockcount, unwritten, &oinfo); @@ -1892,7 +2274,8 @@ xfs_rmap_convert_extent( { struct xfs_rmap_intent ri; - ri.ri_type = XFS_RMAP_CONVERT; + ri.ri_type = xfs_is_reflink_inode(ip) ? XFS_RMAP_CONVERT_SHARED : + XFS_RMAP_CONVERT; ri.ri_owner = ip->i_ino; ri.ri_whichfork = whichfork; ri.ri_bmap = *PREV; diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index b2d2e0a..9372fc5 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -4786,6 +4786,9 @@ xlog_recover_process_rui( case XFS_RMAP_EXTENT_CONVERT: type = XFS_RMAP_CONVERT; break; + case XFS_RMAP_EXTENT_CONVERT_SHARED: + type = XFS_RMAP_CONVERT_SHARED; + break; case XFS_RMAP_EXTENT_ALLOC: type = XFS_RMAP_ALLOC; break; From darrick.wong@oracle.com Thu Jun 16 20:29:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9461F7F8E for ; Thu, 16 Jun 2016 20:29:36 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1DCC5AC002 for ; Thu, 16 Jun 2016 18:29:36 -0700 (PDT) X-ASG-Debug-ID: 1466126973-04cb6c542457b80001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id SpJfqteAnTaYSMmU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:34 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1TSio012709 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:29 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TRqG016131 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:28 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1TRuW029995; Fri, 17 Jun 2016 01:29:27 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:27 -0700 Subject: [PATCH 107/119] xfs: set a default CoW extent size of 32 blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 107/119] xfs: set a default CoW extent size of 32 blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:25 -0700 Message-ID: <146612696580.12839.10793081509573349729.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126974 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1029 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines If the admin doesn't set a CoW extent size or a regular extent size hint, default to creating CoW reservations 32 blocks long to reduce fragmentation. Signed-off-by: DarricK J. Wong --- fs/xfs/xfs_inode.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index fb9c2d7..f2971e2 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -80,7 +80,8 @@ xfs_get_extsz_hint( /* * Helper function to extract CoW extent size hint from inode. * Between the extent size hint and the CoW extent size hint, we - * return the greater of the two. + * return the greater of the two. If the value is zero (automatic), + * default to 32 blocks. */ xfs_extlen_t xfs_get_cowextsz_hint( @@ -93,9 +94,10 @@ xfs_get_cowextsz_hint( a = ip->i_d.di_cowextsize; b = xfs_get_extsz_hint(ip); - if (a > b) - return a; - return b; + a = max(a, b); + if (a == 0) + return 32; + return a; } /* From darrick.wong@oracle.com Thu Jun 16 20:29:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6D4ED7F9F for ; Thu, 16 Jun 2016 20:29:39 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 278F7304039 for ; Thu, 16 Jun 2016 18:29:39 -0700 (PDT) X-ASG-Debug-ID: 1466126977-04cbb01fef69ab0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 3ljWjPSTGT50eA1z (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:37 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1TZRe032147 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:35 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TYFK027536 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:35 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TX0f026018; Fri, 17 Jun 2016 01:29:34 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:33 -0700 Subject: [PATCH 108/119] xfs: don't allow realtime and reflinked files to mix From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 108/119] xfs: don't allow realtime and reflinked files to mix To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:32 -0700 Message-ID: <146612697207.12839.14767562689881261858.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126977 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1507 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines We don't support sharing blocks on the realtime device. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_buf.c | 10 ++++++++++ fs/xfs/xfs_ioctl.c | 4 ++++ 2 files changed, 14 insertions(+) diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 2efa42c..c4cbd2b 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -386,6 +386,9 @@ xfs_dinode_verify( xfs_ino_t ino, struct xfs_dinode *dip) { + uint16_t flags; + uint64_t flags2; + if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) return false; @@ -402,6 +405,13 @@ xfs_dinode_verify( return false; if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid)) return false; + + /* don't let reflink and realtime mix */ + flags = be16_to_cpu(dip->di_flags); + flags2 = be64_to_cpu(dip->di_flags2); + if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & XFS_DIFLAG_REALTIME)) + return false; + return true; } diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index d2b4e81..f103b15 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1031,6 +1031,10 @@ xfs_ioctl_setattr_xflags( return -EINVAL; } + /* Don't allow us to set realtime mode for a reflinked file. */ + if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip)) + return -EINVAL; + /* * Can't modify an immutable/append-only file unless * we have appropriate permission. From darrick.wong@oracle.com Thu Jun 16 20:29:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 133897F5A for ; Thu, 16 Jun 2016 20:29:49 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id CBABE304051 for ; Thu, 16 Jun 2016 18:29:48 -0700 (PDT) X-ASG-Debug-ID: 1466126986-04cbb01fee69ac0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id t7WXUIYfXUzBIud4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:47 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Tfom012894 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:41 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TeDU016323 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:41 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Teq7026059; Fri, 17 Jun 2016 01:29:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:39 -0700 Subject: [PATCH 109/119] xfs: don't mix reflink and DAX mode for now From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 109/119] xfs: don't mix reflink and DAX mode for now To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:38 -0700 Message-ID: <146612697833.12839.1404813608223714641.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466126987 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2358 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since we don't have a strategy for handling both DAX and reflink, for now we'll just prohibit both being set at the same time. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_inode_buf.c | 4 ++++ fs/xfs/xfs_file.c | 4 ++++ fs/xfs/xfs_ioctl.c | 4 ++++ fs/xfs/xfs_iops.c | 1 + 4 files changed, 13 insertions(+) diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index c4cbd2b..3f7053a 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -412,6 +412,10 @@ xfs_dinode_verify( if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & XFS_DIFLAG_REALTIME)) return false; + /* don't let reflink and dax mix */ + if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags2 & XFS_DIFLAG2_DAX)) + return false; + return true; } diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index ad6a467..e8e93f8 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -1126,6 +1126,10 @@ xfs_file_share_range( if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) return -EINVAL; + /* Don't share DAX file data for now. */ + if (IS_DAX(inode_in) || IS_DAX(inode_out)) + return -EINVAL; + /* Are we going all the way to the end? */ isize = i_size_read(inode_in); if (isize == 0) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index f103b15..aa9645c 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -1035,6 +1035,10 @@ xfs_ioctl_setattr_xflags( if ((fa->fsx_xflags & FS_XFLAG_REALTIME) && xfs_is_reflink_inode(ip)) return -EINVAL; + /* Don't allow us to set DAX mode for a reflinked file for now. */ + if ((fa->fsx_xflags & FS_XFLAG_DAX) && xfs_is_reflink_inode(ip)) + return -EINVAL; + /* * Can't modify an immutable/append-only file unless * we have appropriate permission. diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 0fa86bd..95073db 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -1217,6 +1217,7 @@ xfs_diflags_to_iflags( inode->i_flags |= S_NOATIME; if (S_ISREG(inode->i_mode) && ip->i_mount->m_sb.sb_blocksize == PAGE_SIZE && + !xfs_is_reflink_inode(ip) && (ip->i_mount->m_flags & XFS_MOUNT_DAX || ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)) inode->i_flags |= S_DAX; From darrick.wong@oracle.com Thu Jun 16 20:29:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3DB067FB5 for ; Thu, 16 Jun 2016 20:29:53 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id F1CC5304039 for ; Thu, 16 Jun 2016 18:29:52 -0700 (PDT) X-ASG-Debug-ID: 1466126991-04bdf01e1795d40001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id qQTzgf24LQOXAMfA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:29:51 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1TlgK032280 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:47 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TkFE027778 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:47 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TkZM026064; Fri, 17 Jun 2016 01:29:46 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:46 -0700 Subject: [PATCH 110/119] xfs: fail ->bmap for reflink inodes From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 110/119] xfs: fail ->bmap for reflink inodes To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:44 -0700 Message-ID: <146612698458.12839.11124463692768922526.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466126991 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1238 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Christoph Hellwig Have xfs_vm_bmap return zero for reflinked files. This hack prevents using a file with shared blocks as a swap file, because we don't want to deal with CoW when we're (probably) low on memory. Signed-off-by: Christoph Hellwig [darrick.wong@oracle.com: add a more descriptive changelog] Signed-off-by: Darrick J. Wong --- fs/xfs/xfs_aops.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 31205fa..83fd028 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1827,6 +1827,17 @@ xfs_vm_bmap( trace_xfs_vm_bmap(XFS_I(inode)); xfs_ilock(ip, XFS_IOLOCK_SHARED); + + /* + * The swap code (ab-)uses ->bmap to get a block mapping and then + * bypasseѕ the file system for actual I/O. We really can't allow + * that on reflinks inodes, so we have to skip out here. And yes, + * 0 is the magic code for a bmap error.. + */ + if (xfs_is_reflink_inode(ip)) { + xfs_iunlock(ip, XFS_IOLOCK_SHARED); + return 0; + } filemap_write_and_wait(mapping); xfs_iunlock(ip, XFS_IOLOCK_SHARED); return generic_block_bmap(mapping, block, xfs_get_blocks); From darrick.wong@oracle.com Thu Jun 16 20:30:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C724A7FB1 for ; Thu, 16 Jun 2016 20:30:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 87017304048 for ; Thu, 16 Jun 2016 18:30:02 -0700 (PDT) X-ASG-Debug-ID: 1466127000-04bdf01e1095d90001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id fQEameOAHLXqMZ3v (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Tt1h012926 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:29:55 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1TtZJ021652 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:29:55 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TqG8009314; Fri, 17 Jun 2016 01:29:53 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:52 -0700 Subject: [PATCH 111/119] xfs: recognize the reflink feature bit From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 111/119] xfs: recognize the reflink feature bit To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:50 -0700 Message-ID: <146612699086.12839.3691139509716303306.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127000 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1734 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add the reflink feature flag to the set of recognized feature flags. This enables users to write to reflink filesystems. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_format.h | 3 ++- fs/xfs/xfs_super.c | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index a35f4e5..211a8b5 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -459,7 +459,8 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ - XFS_SB_FEAT_RO_COMPAT_RMAPBT) + XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ + XFS_SB_FEAT_RO_COMPAT_REFLINK) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool xfs_sb_has_ro_compat_feature( diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 93d159a..5fdf2e7 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -1587,6 +1587,9 @@ xfs_fs_fill_super( "DAX unsupported by block device. Turning off DAX."); mp->m_flags &= ~XFS_MOUNT_DAX; } + if (xfs_sb_version_hasreflink(&mp->m_sb)) + xfs_alert(mp, + "DAX and reflink have not been tested together!"); } if (xfs_sb_version_hassparseinodes(&mp->m_sb)) @@ -1597,6 +1600,10 @@ xfs_fs_fill_super( xfs_alert(mp, "EXPERIMENTAL reverse mapping btree feature enabled. Use at your own risk!"); + if (xfs_sb_version_hasreflink(&mp->m_sb)) + xfs_alert(mp, + "EXPERIMENTAL reflink feature enabled. Use at your own risk!"); + error = xfs_mountfs(mp); if (error) goto out_filestream_unmount; From darrick.wong@oracle.com Thu Jun 16 20:30:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9DF8A7FC8 for ; Thu, 16 Jun 2016 20:30:11 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6A9EB304039 for ; Thu, 16 Jun 2016 18:30:11 -0700 (PDT) X-ASG-Debug-ID: 1466127006-04cb6c542557bc0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 5byMWYv0RRqpOPgX (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1U09T012944 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:00 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Tx14016598 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:00 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1TxWV026139; Fri, 17 Jun 2016 01:29:59 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:29:58 -0700 Subject: [PATCH 112/119] xfs: introduce the XFS_IOC_GETFSMAPX ioctl From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 112/119] xfs: introduce the XFS_IOC_GETFSMAPX ioctl To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:29:57 -0700 Message-ID: <146612699713.12839.10667733856057619716.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127007 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 24146 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Introduce a new ioctl that uses the reverse mapping btree to return information about the physical layout of the filesystem. v2: shorten the device field to u32 since that's all we need for dev_t. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_fs.h | 62 ++++++++ fs/xfs/libxfs/xfs_refcount.c | 51 +++++- fs/xfs/libxfs/xfs_refcount.h | 4 fs/xfs/xfs_fsops.c | 338 ++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_fsops.h | 6 + fs/xfs/xfs_ioctl.c | 76 +++++++++ fs/xfs/xfs_ioctl32.c | 1 fs/xfs/xfs_trace.h | 76 +++++++++ 8 files changed, 600 insertions(+), 14 deletions(-) diff --git a/fs/xfs/libxfs/xfs_fs.h b/fs/xfs/libxfs/xfs_fs.h index 10ebf99..8a1b96a 100644 --- a/fs/xfs/libxfs/xfs_fs.h +++ b/fs/xfs/libxfs/xfs_fs.h @@ -93,6 +93,67 @@ struct getbmapx { #define BMV_OF_SHARED 0x8 /* segment shared with another file */ /* + * Structure for XFS_IOC_GETFSMAPX. + * + * Similar to XFS_IOC_GETBMAPX, the first two elements in the array are + * used to constrain the output. The first element in the array should + * represent the lowest disk address that the user wants to learn about. + * The second element in the array should represent the highest disk + * address to query. Subsequent array elements will be filled out by the + * command. + * + * The fmv_iflags field is only used in the first structure. The + * fmv_oflags field is filled in for each returned structure after the + * second structure. The fmv_unused1 fields in the first two array + * elements must be zero. + * + * The fmv_count, fmv_entries, and fmv_iflags fields in the second array + * element must be zero. + * + * fmv_block, fmv_offset, and fmv_length are expressed in units of 512 + * byte sectors. + */ +#ifndef HAVE_GETFSMAPX +struct getfsmapx { + __u32 fmv_device; /* device id */ + __u32 fmv_unused1; /* future use, must be zero */ + __u64 fmv_block; /* starting block */ + __u64 fmv_owner; /* owner id */ + __u64 fmv_offset; /* file offset of segment */ + __u64 fmv_length; /* length of segment, blocks */ + __u32 fmv_oflags; /* mapping flags */ + __u32 fmv_iflags; /* control flags (1st structure) */ + __u32 fmv_count; /* # of entries in array incl. input */ + __u32 fmv_entries; /* # of entries filled in (output). */ + __u64 fmv_unused2; /* future use, must be zero */ +}; +#endif + +/* fmv_flags values - set by XFS_IOC_GETFSMAPX caller. */ +/* no flags defined yet */ +#define FMV_IF_VALID 0 + +/* fmv_flags values - returned for each non-header segment */ +#define FMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ +#define FMV_OF_ATTR_FORK 0x2 /* segment = attribute fork */ +#define FMV_OF_EXTENT_MAP 0x4 /* segment = extent map */ +#define FMV_OF_SHARED 0x8 /* segment = shared with another file */ +#define FMV_OF_SPECIAL_OWNER 0x10 /* owner is a special value */ +#define FMV_OF_LAST 0x20 /* segment is the last in the FS */ + +/* fmv_owner special values */ +#define FMV_OWN_FREE (-1ULL) /* free space */ +#define FMV_OWN_UNKNOWN (-2ULL) /* unknown owner */ +#define FMV_OWN_FS (-3ULL) /* static fs metadata */ +#define FMV_OWN_LOG (-4ULL) /* journalling log */ +#define FMV_OWN_AG (-5ULL) /* per-AG metadata */ +#define FMV_OWN_INOBT (-6ULL) /* inode btree blocks */ +#define FMV_OWN_INODES (-7ULL) /* inodes */ +#define FMV_OWN_REFC (-8ULL) /* refcount tree */ +#define FMV_OWN_COW (-9ULL) /* cow allocations */ +#define FMV_OWN_DEFECTIVE (-10ULL) /* bad blocks */ + +/* * Structure for XFS_IOC_FSSETDM. * For use by backup and restore programs to set the XFS on-disk inode * fields di_dmevmask and di_dmstate. These must be set to exactly and @@ -502,6 +563,7 @@ typedef struct xfs_swapext #define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap) #define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64) #define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks) +#define XFS_IOC_GETFSMAPX _IOWR('X', 59, struct getfsmapx) /* * ioctl commands that replace IRIX syssgi()'s diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index fd4369f..e8d8702 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1172,8 +1172,9 @@ xfs_refcount_decrease_extent( * extent we find. If no shared blocks are found, flen will be set to zero. */ int -xfs_refcount_find_shared( +__xfs_refcount_find_shared( struct xfs_mount *mp, + struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen, @@ -1182,23 +1183,13 @@ xfs_refcount_find_shared( bool find_maximal) { struct xfs_btree_cur *cur; - struct xfs_buf *agbp; struct xfs_refcount_irec tmp; - int error; int i, have; int bt_error = XFS_BTREE_ERROR; + int error; trace_xfs_refcount_find_shared(mp, agno, agbno, aglen); - if (xfs_always_cow) { - *fbno = agbno; - *flen = aglen; - return 0; - } - - error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); - if (error) - goto out; cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); /* By default, skip the whole range */ @@ -1273,14 +1264,46 @@ done: out_error: xfs_btree_del_cursor(cur, bt_error); - xfs_buf_relse(agbp); -out: if (error) trace_xfs_refcount_find_shared_error(mp, agno, error, _RET_IP_); return error; } /* + * Given an AG extent, find the lowest-numbered run of shared blocks within + * that range and return the range in fbno/flen. + */ +int +xfs_refcount_find_shared( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_agblock_t *fbno, + xfs_extlen_t *flen, + bool find_maximal) +{ + struct xfs_buf *agbp; + int error; + + if (xfs_always_cow) { + *fbno = agbno; + *flen = aglen; + return 0; + } + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + return error; + + error = __xfs_refcount_find_shared(mp, agbp, agno, agbno, aglen, + fbno, flen, find_maximal); + + xfs_buf_relse(agbp); + return error; +} + +/* * Recovering CoW Blocks After a Crash * * Due to the way that the copy on write mechanism works, there's a window of diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index 6665eeb..44b0346 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -53,6 +53,10 @@ extern int xfs_refcount_finish_one(struct xfs_trans *tp, xfs_fsblock_t startblock, xfs_extlen_t blockcount, xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur); +extern int __xfs_refcount_find_shared(struct xfs_mount *mp, + struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t agbno, + xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, + bool find_maximal); extern int xfs_refcount_find_shared(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_maximal); diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index e76aefc..e69d9cf 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c @@ -44,6 +44,8 @@ #include "xfs_filestream.h" #include "xfs_refcount_btree.h" #include "xfs_ag_resv.h" +#include "xfs_bit.h" +#include "xfs_refcount.h" /* * File system operations @@ -1027,3 +1029,339 @@ xfs_fs_unreserve_ag_blocks( if (error) xfs_warn(mp, "Error %d unreserving metadata blocks.", error); } + +struct xfs_getfsmap_info { + struct getfsmapx *fmv; + xfs_fsmap_format_t formatter; + void *format_arg; + xfs_daddr_t next_daddr; + bool last; + xfs_agnumber_t start_ag; + struct xfs_rmap_irec low; +}; + +/* Compare a record against our starting point */ +static bool +xfs_getfsmap_compare( + xfs_agnumber_t agno, + struct xfs_getfsmap_info *info, + struct xfs_rmap_irec *rec) +{ + uint64_t x, y; + + if (rec->rm_startblock < info->low.rm_startblock) + return true; + if (rec->rm_startblock > info->low.rm_startblock) + return false; + + if (rec->rm_owner < info->low.rm_owner) + return true; + if (rec->rm_owner > info->low.rm_owner) + return false; + + x = xfs_rmap_irec_offset_pack(rec); + y = xfs_rmap_irec_offset_pack(&info->low); + if (x < y) + return true; + return false; +} + +STATIC bool +xfs_getfsmap_is_shared( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec) +{ + xfs_agblock_t fbno; + xfs_extlen_t flen; + int error; + + if (!xfs_sb_version_hasreflink(&cur->bc_mp->m_sb)) + return false; + + /* Are there any shared blocks here? */ + flen = 0; + error = __xfs_refcount_find_shared(cur->bc_mp, cur->bc_private.a.agbp, + cur->bc_private.a.agno, rec->rm_startblock, + rec->rm_blockcount, &fbno, &flen, false); + return error == 0 && flen > 0; +} + +/* Transform a rmap irec into a fsmapx */ +STATIC int +xfs_getfsmap_helper( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_getfsmap_info *info = priv; + xfs_fsblock_t fsb; + struct getfsmapx fmv; + xfs_daddr_t rec_daddr; + int error; + + fsb = XFS_AGB_TO_FSB(mp, cur->bc_private.a.agno, + rec->rm_startblock); + rec_daddr = XFS_FSB_TO_DADDR(mp, fsb); + + /* + * Filter out records that start before our startpoint, if the caller + * requested that. + */ + if (info->fmv->fmv_length && + xfs_getfsmap_compare(cur->bc_private.a.agno, info, rec)) { + rec_daddr = XFS_FSB_TO_DADDR(mp, fsb + + rec->rm_blockcount); + if (info->next_daddr < rec_daddr) + info->next_daddr = rec_daddr; + return XFS_BTREE_QUERY_RANGE_CONTINUE; + } + + /* We're just counting mappings */ + if (info->fmv->fmv_count == 2) { + if (rec_daddr > info->next_daddr) + info->fmv->fmv_entries++; + + if (info->last) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + + info->fmv->fmv_entries++; + + rec_daddr = XFS_FSB_TO_DADDR(mp, fsb + + rec->rm_blockcount); + if (info->next_daddr < rec_daddr) + info->next_daddr = rec_daddr; + return XFS_BTREE_QUERY_RANGE_CONTINUE; + } + + /* Did we find some free space? */ + if (rec_daddr > info->next_daddr) { + if (info->fmv->fmv_entries >= info->fmv->fmv_count - 2) + return XFS_BTREE_QUERY_RANGE_ABORT; + + trace_xfs_fsmap_mapping(mp, cur->bc_private.a.agno, + XFS_DADDR_TO_FSB(mp, info->next_daddr), + XFS_DADDR_TO_FSB(mp, rec_daddr - + info->next_daddr), + FMV_OWN_FREE, 0); + + fmv.fmv_device = new_encode_dev(mp->m_ddev_targp->bt_dev); + fmv.fmv_block = info->next_daddr; + fmv.fmv_owner = FMV_OWN_FREE; + fmv.fmv_offset = 0; + fmv.fmv_length = rec_daddr - info->next_daddr; + fmv.fmv_oflags = FMV_OF_SPECIAL_OWNER; + fmv.fmv_count = 0; + fmv.fmv_entries = 0; + fmv.fmv_unused1 = 0; + fmv.fmv_unused2 = 0; + error = info->formatter(&fmv, info->format_arg); + if (error) + return error; + info->fmv->fmv_entries++; + } + + if (info->last) + goto out; + + /* Fill out the extent we found */ + if (info->fmv->fmv_entries >= info->fmv->fmv_count - 2) + return XFS_BTREE_QUERY_RANGE_ABORT; + + trace_xfs_fsmap_mapping(mp, cur->bc_private.a.agno, + rec->rm_startblock, rec->rm_blockcount, rec->rm_owner, + rec->rm_offset); + + fmv.fmv_device = new_encode_dev(mp->m_ddev_targp->bt_dev); + fmv.fmv_block = rec_daddr; + fmv.fmv_owner = rec->rm_owner; + fmv.fmv_offset = XFS_FSB_TO_BB(mp, rec->rm_offset); + fmv.fmv_length = XFS_FSB_TO_BB(mp, rec->rm_blockcount); + fmv.fmv_oflags = 0; + fmv.fmv_count = 0; + fmv.fmv_entries = 0; + fmv.fmv_unused1 = 0; + fmv.fmv_unused2 = 0; + if (XFS_RMAP_NON_INODE_OWNER(rec->rm_owner)) + fmv.fmv_oflags |= FMV_OF_SPECIAL_OWNER; + if (rec->rm_flags & XFS_RMAP_UNWRITTEN) + fmv.fmv_oflags |= FMV_OF_PREALLOC; + if (rec->rm_flags & XFS_RMAP_ATTR_FORK) + fmv.fmv_oflags |= FMV_OF_ATTR_FORK; + if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK) + fmv.fmv_oflags |= FMV_OF_EXTENT_MAP; + if (fmv.fmv_oflags == 0 && xfs_getfsmap_is_shared(cur, rec)) + fmv.fmv_oflags |= FMV_OF_SHARED; + error = info->formatter(&fmv, info->format_arg); + if (error) + return error; + info->fmv->fmv_entries++; + +out: + rec_daddr = XFS_FSB_TO_DADDR(mp, fsb + rec->rm_blockcount); + if (info->next_daddr < rec_daddr) + info->next_daddr = rec_daddr; + return XFS_BTREE_QUERY_RANGE_CONTINUE; +} + +/* Do we recognize the device? */ +STATIC bool +xfs_getfsmap_is_valid_device( + struct xfs_mount *mp, + struct getfsmapx *fmv) +{ + return fmv->fmv_device == 0 || fmv->fmv_device == UINT_MAX || + fmv->fmv_device == new_encode_dev(mp->m_ddev_targp->bt_dev); +} + +/* + * Get filesystem's extents as described in fmv, and format for + * output. Calls formatter to fill the user's buffer until all + * extents are mapped, until the passed-in fmv->fmv_count slots have + * been filled, or until the formatter short-circuits the loop, if it + * is tracking filled-in extents on its own. + */ +int +xfs_getfsmap( + struct xfs_mount *mp, + struct getfsmapx *fmv, + xfs_fsmap_format_t formatter, + void *arg) +{ + struct xfs_getfsmap_info info; + struct xfs_buf *agbp = NULL; + struct xfs_btree_cur *bt_cur = NULL; + struct getfsmapx *fmv_low; + struct getfsmapx *fmv_high; + struct xfs_rmap_irec high; + xfs_fsblock_t start_fsb; + xfs_fsblock_t end_fsb; + xfs_agnumber_t end_ag; + xfs_agnumber_t agno; + xfs_daddr_t eofs; + xfs_extlen_t extlen; + int error = 0; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return -EOPNOTSUPP; + if (fmv->fmv_count < 2) + return -EINVAL; + if (fmv->fmv_iflags & (~FMV_IF_VALID)) + return -EINVAL; + fmv_low = fmv; + fmv_high = fmv + 1; + if (!xfs_getfsmap_is_valid_device(mp, fmv) || + !xfs_getfsmap_is_valid_device(mp, fmv_high) || + fmv_high->fmv_iflags || fmv_high->fmv_count || + fmv_high->fmv_length || fmv_high->fmv_entries || + fmv_high->fmv_unused1 || fmv->fmv_unused1 || + fmv_high->fmv_unused2 || fmv->fmv_unused2) + return -EINVAL; + + fmv->fmv_entries = 0; + eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); + if (fmv->fmv_block >= eofs) + return 0; + if (fmv_high->fmv_block >= eofs) + fmv_high->fmv_block = eofs - 1; + start_fsb = XFS_DADDR_TO_FSB(mp, fmv->fmv_block); + end_fsb = XFS_DADDR_TO_FSB(mp, fmv_high->fmv_block); + + /* Set up search keys */ + info.low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb); + info.low.rm_offset = XFS_DADDR_TO_FSB(mp, fmv->fmv_offset); + info.low.rm_owner = fmv->fmv_owner; + info.low.rm_blockcount = 0; + extlen = XFS_DADDR_TO_FSB(mp, fmv->fmv_length); + if (fmv->fmv_oflags & (FMV_OF_SPECIAL_OWNER | FMV_OF_EXTENT_MAP)) { + info.low.rm_startblock += extlen; + info.low.rm_owner = 0; + info.low.rm_offset = 0; + } else + info.low.rm_offset += extlen; + if (fmv->fmv_oflags & FMV_OF_ATTR_FORK) + info.low.rm_flags |= XFS_RMAP_ATTR_FORK; + if (fmv->fmv_oflags & FMV_OF_EXTENT_MAP) + info.low.rm_flags |= XFS_RMAP_BMBT_BLOCK; + if (fmv->fmv_oflags & FMV_OF_PREALLOC) + info.low.rm_flags |= XFS_RMAP_UNWRITTEN; + + high.rm_startblock = -1U; + high.rm_owner = ULLONG_MAX; + high.rm_offset = ULLONG_MAX; + high.rm_blockcount = 0; + high.rm_flags = XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK | + XFS_RMAP_UNWRITTEN; + info.fmv = fmv; + info.formatter = formatter; + info.format_arg = arg; + info.last = false; + + info.start_ag = XFS_FSB_TO_AGNO(mp, start_fsb); + end_ag = XFS_FSB_TO_AGNO(mp, end_fsb); + info.next_daddr = XFS_FSB_TO_DADDR(mp, XFS_AGB_TO_FSB(mp, info.start_ag, + info.low.rm_startblock)); + + /* Query each AG */ + for (agno = info.start_ag; agno <= end_ag; agno++) { + if (agno == end_ag) { + high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsb); + high.rm_offset = XFS_DADDR_TO_FSB(mp, + fmv_high->fmv_offset); + high.rm_owner = fmv_high->fmv_owner; + if (fmv_high->fmv_oflags & FMV_OF_ATTR_FORK) + high.rm_flags |= XFS_RMAP_ATTR_FORK; + if (fmv_high->fmv_oflags & FMV_OF_EXTENT_MAP) + high.rm_flags |= XFS_RMAP_BMBT_BLOCK; + if (fmv_high->fmv_oflags & FMV_OF_PREALLOC) + high.rm_flags |= XFS_RMAP_UNWRITTEN; + } + + if (bt_cur) { + xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, agbp); + bt_cur = NULL; + agbp = NULL; + } + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + goto err; + + trace_xfs_fsmap_low_key(mp, agno, info.low.rm_startblock, + info.low.rm_blockcount, info.low.rm_owner, + info.low.rm_offset); + + trace_xfs_fsmap_high_key(mp, agno, high.rm_startblock, + high.rm_blockcount, high.rm_owner, + high.rm_offset); + + bt_cur = xfs_rmapbt_init_cursor(mp, NULL, agbp, agno); + error = xfs_rmapbt_query_range(bt_cur, &info.low, &high, + xfs_getfsmap_helper, &info); + if (error) + goto err; + + if (agno == info.start_ag) { + info.low.rm_startblock = 0; + info.low.rm_owner = 0; + info.low.rm_offset = 0; + info.low.rm_flags = 0; + } + } + + /* Report any free space at the end of the AG */ + info.last = true; + error = xfs_getfsmap_helper(bt_cur, &high, &info); + if (error) + goto err; + +err: + if (bt_cur) + xfs_btree_del_cursor(bt_cur, error < 0 ? XFS_BTREE_ERROR : + XFS_BTREE_NOERROR); + if (agbp) + xfs_trans_brelse(NULL, agbp); + + return error; +} diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h index 71e3248..8101fb9 100644 --- a/fs/xfs/xfs_fsops.h +++ b/fs/xfs/xfs_fsops.h @@ -29,4 +29,10 @@ extern int xfs_fs_goingdown(xfs_mount_t *mp, __uint32_t inflags); extern void xfs_fs_reserve_ag_blocks(struct xfs_mount *mp); extern void xfs_fs_unreserve_ag_blocks(struct xfs_mount *mp); +/* fsmap to userspace formatter - copy to user & advance pointer */ +typedef int (*xfs_fsmap_format_t)(struct getfsmapx *, void *); + +int xfs_getfsmap(struct xfs_mount *mp, struct getfsmapx *fmv, + xfs_fsmap_format_t formatter, void *arg); + #endif /* __XFS_FSOPS_H__ */ diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index aa9645c..736e747 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -42,6 +42,7 @@ #include "xfs_pnfs.h" #include "xfs_acl.h" #include "xfs_reflink.h" +#include "xfs_btree.h" #include #include @@ -1611,6 +1612,76 @@ xfs_ioc_getbmapx( return 0; } +struct getfsmapx_info { + struct xfs_mount *mp; + struct getfsmapx __user *data; + __s64 last_flags; +}; + +STATIC int +xfs_getfsmapx_format(struct getfsmapx *fmv, void *priv) +{ + struct getfsmapx_info *info = priv; + + trace_xfs_getfsmap_mapping(info->mp, fmv->fmv_block, + fmv->fmv_length, fmv->fmv_owner, + fmv->fmv_offset, fmv->fmv_oflags); + + info->last_flags = fmv->fmv_oflags; + if (copy_to_user(info->data, fmv, sizeof(struct getfsmapx))) + return -EFAULT; + + info->data++; + return 0; +} + +STATIC int +xfs_ioc_getfsmapx( + struct xfs_inode *ip, + void __user *arg) +{ + struct getfsmapx_info info; + struct getfsmapx fmx[2]; + bool aborted = false; + int error; + + if (copy_from_user(&fmx, arg, 2 * sizeof(struct getfsmapx))) + return -EFAULT; + + trace_xfs_getfsmap_low_key(ip->i_mount, fmx[0].fmv_block, + fmx[0].fmv_length, fmx[0].fmv_owner, + fmx[0].fmv_offset, fmx[0].fmv_oflags); + + trace_xfs_getfsmap_high_key(ip->i_mount, fmx[1].fmv_block, + fmx[1].fmv_length, fmx[1].fmv_owner, + fmx[1].fmv_offset, fmx[1].fmv_oflags); + + info.mp = ip->i_mount; + info.data = (__force struct getfsmapx *)arg + 2; + error = xfs_getfsmap(ip->i_mount, fmx, xfs_getfsmapx_format, &info); + if (error == XFS_BTREE_QUERY_RANGE_ABORT) { + error = 0; + aborted = true; + } + if (error) + return error; + + /* If we didn't abort, set the "last" flag in the last fmx */ + if (!aborted && fmx[0].fmv_entries) { + info.data--; + info.last_flags |= FMV_OF_LAST; + if (copy_to_user(&info.data->fmv_oflags, &info.last_flags, + sizeof(info.last_flags))) + return -EFAULT; + } + + /* copy back header */ + if (copy_to_user(arg, fmx, 2 * sizeof(struct getfsmapx))) + return -EFAULT; + + return 0; +} + int xfs_ioc_swapext( xfs_swapext_t *sxp) @@ -1784,6 +1855,11 @@ xfs_file_ioctl( case XFS_IOC_GETBMAPX: return xfs_ioc_getbmapx(ip, arg); + case XFS_IOC_GETFSMAPX: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + return xfs_ioc_getfsmapx(ip, arg); + case XFS_IOC_FD_TO_HANDLE: case XFS_IOC_PATH_TO_HANDLE: case XFS_IOC_PATH_TO_FSHANDLE: { diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index 1a05d8a..337e436 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c @@ -558,6 +558,7 @@ xfs_file_compat_ioctl( case XFS_IOC_GOINGDOWN: case XFS_IOC_ERROR_INJECTION: case XFS_IOC_ERROR_CLEARALL: + case XFS_IOC_GETFSMAPX: return xfs_file_ioctl(filp, cmd, p); #ifndef BROKEN_X86_ALIGNMENT /* These are handled fine if no alignment issues */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index d64bab7..9fe812f 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -3352,6 +3352,82 @@ DEFINE_INODE_EVENT(xfs_reflink_cancel_pending_cow); DEFINE_INODE_IREC_EVENT(xfs_reflink_cancel_cow); DEFINE_INODE_ERROR_EVENT(xfs_reflink_cancel_pending_cow_error); +/* fsmap traces */ +DECLARE_EVENT_CLASS(xfs_fsmap_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, + xfs_extlen_t len, __uint64_t owner, __uint64_t offset), + TP_ARGS(mp, agno, agbno, len, owner, offset), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, agbno) + __field(xfs_extlen_t, len) + __field(__uint64_t, owner) + __field(__uint64_t, offset) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->agbno = agbno; + __entry->len = len; + __entry->owner = owner; + __entry->offset = offset; + ), + TP_printk("dev %d:%d agno %u agbno %u len %u owner %lld offset 0x%llx\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->agbno, + __entry->len, + __entry->owner, + __entry->offset) +) +#define DEFINE_FSMAP_EVENT(name) \ +DEFINE_EVENT(xfs_fsmap_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ + xfs_agblock_t agbno, xfs_extlen_t len, __uint64_t owner, \ + __uint64_t offset), \ + TP_ARGS(mp, agno, agbno, len, owner, offset)) +DEFINE_FSMAP_EVENT(xfs_fsmap_low_key); +DEFINE_FSMAP_EVENT(xfs_fsmap_high_key); +DEFINE_FSMAP_EVENT(xfs_fsmap_mapping); + +DECLARE_EVENT_CLASS(xfs_getfsmap_class, + TP_PROTO(struct xfs_mount *mp, xfs_daddr_t block, xfs_daddr_t len, + __uint64_t owner, __uint64_t offset, __uint64_t flags), + TP_ARGS(mp, block, len, owner, offset, flags), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_daddr_t, block) + __field(xfs_daddr_t, len) + __field(__uint64_t, owner) + __field(__uint64_t, offset) + __field(__uint64_t, flags) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->block = block; + __entry->len = len; + __entry->owner = owner; + __entry->offset = offset; + __entry->flags = flags; + ), + TP_printk("dev %d:%d block %llu len %llu owner %lld offset %llu flags 0x%llx\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->block, + __entry->len, + __entry->owner, + __entry->offset, + __entry->flags) +) +#define DEFINE_GETFSMAP_EVENT(name) \ +DEFINE_EVENT(xfs_getfsmap_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_daddr_t block, xfs_daddr_t len, \ + __uint64_t owner, __uint64_t offset, __uint64_t flags), \ + TP_ARGS(mp, block, len, owner, offset, flags)) +DEFINE_GETFSMAP_EVENT(xfs_getfsmap_low_key); +DEFINE_GETFSMAP_EVENT(xfs_getfsmap_high_key); +DEFINE_GETFSMAP_EVENT(xfs_getfsmap_mapping); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:30:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B7D377F8B for ; Thu, 16 Jun 2016 20:30:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1FD35AC001 for ; Thu, 16 Jun 2016 18:30:13 -0700 (PDT) X-ASG-Debug-ID: 1466127008-04cb6c542457bc0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id wdxkCocmbP94H7W8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:09 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1U6ZQ032697 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:06 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1U6h6017405 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:06 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1U5jG026176; Fri, 17 Jun 2016 01:30:05 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:05 -0700 Subject: [PATCH 113/119] xfs: scrub btree records and pointers while querying From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 113/119] xfs: scrub btree records and pointers while querying To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:03 -0700 Message-ID: <146612700354.12839.18272855403371334654.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127009 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 22426 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a function that walks a btree, checking the integrity of each btree block (headers, keys, records) and calling back to the caller to perform further checks on the records. v2: Prefix function names with xfs_ Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/libxfs/xfs_alloc.c | 33 +++ fs/xfs/libxfs/xfs_alloc.h | 3 fs/xfs/libxfs/xfs_btree.c | 12 + fs/xfs/libxfs/xfs_btree.h | 15 +- fs/xfs/libxfs/xfs_format.h | 2 fs/xfs/libxfs/xfs_rmap.c | 39 ++++ fs/xfs/libxfs/xfs_rmap_btree.h | 3 fs/xfs/libxfs/xfs_scrub.c | 396 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_scrub.h | 76 ++++++++ 10 files changed, 571 insertions(+), 9 deletions(-) create mode 100644 fs/xfs/libxfs/xfs_scrub.c create mode 100644 fs/xfs/libxfs/xfs_scrub.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 56c384b..8942390 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -58,6 +58,7 @@ xfs-y += $(addprefix libxfs/, \ xfs_refcount.o \ xfs_refcount_btree.o \ xfs_sb.o \ + xfs_scrub.o \ xfs_symlink_remote.o \ xfs_trans_resv.o \ ) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 188c359a..6fc1981 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -2924,3 +2924,36 @@ err: xfs_trans_brelse(tp, agbp); return error; } + +/* Is there a record covering a given extent? */ +int +xfs_alloc_record_exists( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool *is_freesp) +{ + int stat; + xfs_agblock_t fbno; + xfs_extlen_t flen; + int error; + + error = xfs_alloc_lookup_le(cur, bno, len, &stat); + if (error) + return error; + if (!stat) { + *is_freesp = false; + return 0; + } + + error = xfs_alloc_get_rec(cur, &fbno, &flen, &stat); + if (error) + return error; + if (!stat) { + *is_freesp = false; + return 0; + } + + *is_freesp = (fbno <= bno && fbno + flen >= bno + len); + return 0; +} diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 9f6373a4..4f2ce38 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -210,4 +210,7 @@ int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); +int xfs_alloc_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, bool *is_freesp); + #endif /* __XFS_ALLOC_H__ */ diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 9c84184..5260085 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -549,7 +549,7 @@ xfs_btree_ptr_offset( /* * Return a pointer to the n-th record in the btree block. */ -STATIC union xfs_btree_rec * +union xfs_btree_rec * xfs_btree_rec_addr( struct xfs_btree_cur *cur, int n, @@ -562,7 +562,7 @@ xfs_btree_rec_addr( /* * Return a pointer to the n-th key in the btree block. */ -STATIC union xfs_btree_key * +union xfs_btree_key * xfs_btree_key_addr( struct xfs_btree_cur *cur, int n, @@ -575,7 +575,7 @@ xfs_btree_key_addr( /* * Return a pointer to the n-th high key in the btree block. */ -STATIC union xfs_btree_key * +union xfs_btree_key * xfs_btree_high_key_addr( struct xfs_btree_cur *cur, int n, @@ -588,7 +588,7 @@ xfs_btree_high_key_addr( /* * Return a pointer to the n-th block pointer in the btree block. */ -STATIC union xfs_btree_ptr * +union xfs_btree_ptr * xfs_btree_ptr_addr( struct xfs_btree_cur *cur, int n, @@ -622,7 +622,7 @@ xfs_btree_get_iroot( * Retrieve the block pointer from the cursor at the given level. * This may be an inode btree root or from a buffer. */ -STATIC struct xfs_btree_block * /* generic btree block pointer */ +struct xfs_btree_block * /* generic btree block pointer */ xfs_btree_get_block( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level in btree */ @@ -1733,7 +1733,7 @@ error0: return error; } -STATIC int +int xfs_btree_lookup_get_block( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level in the btree */ diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h index dbf299f..6f22cb0 100644 --- a/fs/xfs/libxfs/xfs_btree.h +++ b/fs/xfs/libxfs/xfs_btree.h @@ -194,7 +194,6 @@ struct xfs_btree_ops { const struct xfs_buf_ops *buf_ops; -#if defined(DEBUG) || defined(XFS_WARN) /* check that k1 is lower than k2 */ int (*keys_inorder)(struct xfs_btree_cur *cur, union xfs_btree_key *k1, @@ -204,7 +203,6 @@ struct xfs_btree_ops { int (*recs_inorder)(struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2); -#endif }; /* btree ops flags */ @@ -537,4 +535,17 @@ int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks); +union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +union xfs_btree_key *xfs_btree_key_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +union xfs_btree_key *xfs_btree_high_key_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +union xfs_btree_ptr *xfs_btree_ptr_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +int xfs_btree_lookup_get_block(struct xfs_btree_cur *cur, int level, + union xfs_btree_ptr *pp, struct xfs_btree_block **blkp); +struct xfs_btree_block *xfs_btree_get_block(struct xfs_btree_cur *cur, + int level, struct xfs_buf **bpp); + #endif /* __XFS_BTREE_H__ */ diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 211a8b5..6ea8a84 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -518,7 +518,7 @@ static inline int xfs_sb_version_hasftype(struct xfs_sb *sbp) (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE)); } -static inline int xfs_sb_version_hasfinobt(xfs_sb_t *sbp) +static inline bool xfs_sb_version_hasfinobt(xfs_sb_t *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index 29d08fc..e7673ec 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -2328,3 +2328,42 @@ xfs_rmap_free_defer( return __xfs_rmap_add(mp, dfops, &ri); } + +/* Is there a record covering a given extent? */ +int +xfs_rmap_record_exists( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + struct xfs_owner_info *oinfo, + bool *has_rmap) +{ + uint64_t owner; + uint64_t offset; + unsigned int flags; + int stat; + struct xfs_rmap_irec irec; + int error; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &stat); + if (error) + return error; + if (!stat) { + *has_rmap = false; + return 0; + } + + error = xfs_rmap_get_rec(cur, &irec, &stat); + if (error) + return error; + if (!stat) { + *has_rmap = false; + return 0; + } + + *has_rmap = (irec.rm_startblock <= bno && + irec.rm_startblock + irec.rm_blockcount >= bno + len); + return 0; +} diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 5baa81f..2f072c8 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -144,4 +144,7 @@ extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp); extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); +extern int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, struct xfs_owner_info *oinfo, bool *has_rmap); + #endif /* __XFS_RMAP_BTREE_H__ */ diff --git a/fs/xfs/libxfs/xfs_scrub.c b/fs/xfs/libxfs/xfs_scrub.c new file mode 100644 index 0000000..d43d5c5 --- /dev/null +++ b/fs/xfs/libxfs/xfs_scrub.c @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_btree.h" +#include "xfs_bit.h" +#include "xfs_alloc.h" +#include "xfs_bmap.h" +#include "xfs_ialloc.h" +#include "xfs_refcount.h" +#include "xfs_alloc_btree.h" +#include "xfs_rmap_btree.h" +#include "xfs_log_format.h" +#include "xfs_trans.h" +#include "xfs_scrub.h" + +static const char * const btree_types[] = { + [XFS_BTNUM_BNO] = "bnobt", + [XFS_BTNUM_CNT] = "cntbt", + [XFS_BTNUM_RMAP] = "rmapbt", + [XFS_BTNUM_BMAP] = "bmapbt", + [XFS_BTNUM_INO] = "inobt", + [XFS_BTNUM_FINO] = "finobt", + [XFS_BTNUM_REFC] = "refcountbt", +}; + +/* Report a scrub corruption in dmesg. */ +void +xfs_btree_scrub_error( + struct xfs_btree_cur *cur, + int level, + const char *file, + int line, + const char *check) +{ + char buf[16]; + xfs_fsblock_t fsbno; + + if (cur->bc_ptrs[level] >= 1) + snprintf(buf, 16, " ptr %d", cur->bc_ptrs[level]); + else + buf[0] = 0; + + fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, cur->bc_bufs[level]->b_bn); + xfs_alert(cur->bc_mp, "scrub: %s btree corruption in block %u/%u%s: %s, file: %s, line: %d", + btree_types[cur->bc_btnum], + XFS_FSB_TO_AGNO(cur->bc_mp, fsbno), + XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), + buf, check, file, line); +} + +/* AG metadata scrubbing */ + +/* + * Make sure this record is in order and doesn't stray outside of the parent + * keys. + */ +static int +xfs_btree_scrub_rec( + struct xfs_btree_scrub *bs) +{ + struct xfs_btree_cur *cur = bs->cur; + union xfs_btree_rec *rec; + union xfs_btree_key key; + union xfs_btree_key *keyp; + struct xfs_btree_block *block; + struct xfs_btree_block *keyblock; + + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[0]); + rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); + + /* If this isn't the first record, are they in order? */ + XFS_BTREC_SCRUB_CHECK(bs, bs->firstrec || + cur->bc_ops->recs_inorder(cur, &bs->lastrec, rec)); + bs->firstrec = false; + bs->lastrec = *rec; + + if (cur->bc_nlevels == 1) + return 0; + + /* Is this at least as large as the parent low key? */ + cur->bc_ops->init_key_from_rec(&key, rec); + keyblock = XFS_BUF_TO_BLOCK(cur->bc_bufs[1]); + keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, 0, + cur->bc_ops->diff_two_keys(cur, keyp, &key) >= 0); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return 0; + + /* Is this no larger than the parent high key? */ + keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, 0, + cur->bc_ops->diff_two_keys(cur, &key, keyp) >= 0); + + return 0; +} + +/* + * Make sure this key is in order and doesn't stray outside of the parent + * keys. + */ +static int +xfs_btree_scrub_key( + struct xfs_btree_scrub *bs, + int level) +{ + struct xfs_btree_cur *cur = bs->cur; + union xfs_btree_key *key; + union xfs_btree_key *keyp; + struct xfs_btree_block *block; + struct xfs_btree_block *keyblock; + + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); + key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); + + /* If this isn't the first key, are they in order? */ + XFS_BTKEY_SCRUB_CHECK(bs, level, bs->firstkey[level] || + cur->bc_ops->keys_inorder(cur, &bs->lastkey[level], + key)); + bs->firstkey[level] = false; + bs->lastkey[level] = *key; + + if (level + 1 >= cur->bc_nlevels) + return 0; + + /* Is this at least as large as the parent low key? */ + keyblock = XFS_BUF_TO_BLOCK(cur->bc_bufs[level + 1]); + keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, level, + cur->bc_ops->diff_two_keys(cur, keyp, key) >= 0); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return 0; + + /* Is this no larger than the parent high key? */ + key = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); + keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, level, + cur->bc_ops->diff_two_keys(cur, key, keyp) >= 0); + + return 0; +} + +struct check_owner { + struct list_head list; + xfs_agblock_t bno; +}; + +/* + * Make sure this btree block isn't in the free list and that there's + * an rmap record for it. + */ +static int +xfs_btree_block_check_owner( + struct xfs_btree_scrub *bs, + xfs_agblock_t bno) +{ + bool has_rmap; + bool is_freesp; + int error; + + /* Check that this block isn't free */ + error = xfs_alloc_record_exists(bs->bno_cur, bno, 1, &is_freesp); + if (error) + goto err; + XFS_BTREC_SCRUB_CHECK(bs, !is_freesp); + + if (!bs->rmap_cur) + return 0; + + /* Check that there's an rmap record for this */ + error = xfs_rmap_record_exists(bs->rmap_cur, bno, 1, &bs->oinfo, + &has_rmap); + if (error) + goto err; + XFS_BTREC_SCRUB_CHECK(bs, has_rmap); +err: + return error; +} + +/* Check the owner of a btree block. */ +static int +xfs_btree_scrub_check_owner( + struct xfs_btree_scrub *bs, + struct xfs_buf *bp) +{ + struct xfs_btree_cur *cur = bs->cur; + xfs_agblock_t bno; + xfs_fsblock_t fsbno; + struct check_owner *co; + + fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, bp->b_bn); + bno = XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno); + + /* Do we need to defer this one? */ + if ((!bs->rmap_cur && xfs_sb_version_hasrmapbt(&cur->bc_mp->m_sb)) || + !bs->bno_cur) { + co = kmem_alloc(sizeof(struct check_owner), KM_SLEEP | KM_NOFS); + co->bno = bno; + list_add_tail(&co->list, &bs->to_check); + return 0; + } + + return xfs_btree_block_check_owner(bs, bno); +} + +/* + * Visit all nodes and leaves of a btree. Check that all pointers and + * records are in order, that the keys reflect the records, and use a callback + * so that the caller can verify individual records. The callback is the same + * as the one for xfs_btree_query_range, so therefore this function also + * returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a negative error code. + */ +int +xfs_btree_scrub( + struct xfs_btree_scrub *bs) +{ + struct xfs_btree_cur *cur = bs->cur; + union xfs_btree_ptr ptr; + union xfs_btree_ptr *pp; + union xfs_btree_rec *recp; + struct xfs_btree_block *block; + int level; + struct xfs_buf *bp; + int i; + struct check_owner *co, *n; + int error; + + /* Finish filling out the scrub state */ + bs->error = 0; + bs->firstrec = true; + for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) + bs->firstkey[i] = true; + bs->bno_cur = bs->rmap_cur = NULL; + INIT_LIST_HEAD(&bs->to_check); + if (bs->cur->bc_btnum != XFS_BTNUM_BNO) + bs->bno_cur = xfs_allocbt_init_cursor(cur->bc_mp, NULL, + bs->agf_bp, bs->cur->bc_private.a.agno, + XFS_BTNUM_BNO); + if (bs->cur->bc_btnum != XFS_BTNUM_RMAP && + xfs_sb_version_hasrmapbt(&cur->bc_mp->m_sb)) + bs->rmap_cur = xfs_rmapbt_init_cursor(cur->bc_mp, NULL, + bs->agf_bp, bs->cur->bc_private.a.agno); + + /* Load the root of the btree. */ + level = cur->bc_nlevels - 1; + cur->bc_ops->init_ptr_from_cur(cur, &ptr); + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); + if (error) + goto out; + + xfs_btree_get_block(cur, level, &bp); + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; + error = xfs_btree_scrub_check_owner(bs, bp); + if (error) + goto out; + + cur->bc_ptrs[level] = 1; + + while (level < cur->bc_nlevels) { + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); + + if (level == 0) { + /* End of leaf, pop back towards the root. */ + if (cur->bc_ptrs[level] > + be16_to_cpu(block->bb_numrecs)) { + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + /* Records in order for scrub? */ + error = xfs_btree_scrub_rec(bs); + if (error) + goto out; + + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); + error = bs->scrub_rec(bs, recp); + if (error < 0 || + error == XFS_BTREE_QUERY_RANGE_ABORT) + break; + + cur->bc_ptrs[level]++; + continue; + } + + /* End of node, pop back towards the root. */ + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + /* Keys in order for scrub? */ + error = xfs_btree_scrub_key(bs, level); + if (error) + goto out; + + /* Drill another level deeper. */ + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); + level--; + error = xfs_btree_lookup_get_block(cur, level, pp, + &block); + if (error) + goto out; + + xfs_btree_get_block(cur, level, &bp); + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; + + error = xfs_btree_scrub_check_owner(bs, bp); + if (error) + goto out; + + cur->bc_ptrs[level] = 1; + } + +out: + /* + * If we don't end this function with the cursor pointing at a record + * block, a subsequent non-error cursor deletion will not release + * node-level buffers, causing a buffer leak. This is quite possible + * with a zero-results range query, so release the buffers if we + * failed to return any results. + */ + if (cur->bc_bufs[0] == NULL) { + for (i = 0; i < cur->bc_nlevels; i++) { + if (cur->bc_bufs[i]) { + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); + cur->bc_bufs[i] = NULL; + cur->bc_ptrs[i] = 0; + cur->bc_ra[i] = 0; + } + } + } + + /* Check the deferred stuff */ + if (!error) { + if (bs->cur->bc_btnum == XFS_BTNUM_BNO) + bs->bno_cur = bs->cur; + else if (bs->cur->bc_btnum == XFS_BTNUM_RMAP) + bs->rmap_cur = bs->cur; + list_for_each_entry(co, &bs->to_check, list) { + error = xfs_btree_block_check_owner(bs, co->bno); + if (error) + break; + } + } + list_for_each_entry_safe(co, n, &bs->to_check, list) { + list_del(&co->list); + kmem_free(co); + } + + if (bs->bno_cur && bs->bno_cur != bs->cur) + xfs_btree_del_cursor(bs->bno_cur, XFS_BTREE_ERROR); + if (bs->rmap_cur && bs->rmap_cur != bs->cur) + xfs_btree_del_cursor(bs->rmap_cur, XFS_BTREE_ERROR); + + if (error || bs->error) + xfs_alert(cur->bc_mp, + "Corruption detected. Unmount and run xfs_repair."); + + return error; +} diff --git a/fs/xfs/libxfs/xfs_scrub.h b/fs/xfs/libxfs/xfs_scrub.h new file mode 100644 index 0000000..af80a9d --- /dev/null +++ b/fs/xfs/libxfs/xfs_scrub.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_SCRUB_H__ +#define __XFS_SCRUB_H__ + +/* btree scrub */ +struct xfs_btree_scrub; + +typedef int (*xfs_btree_scrub_rec_fn)( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec); + +struct xfs_btree_scrub { + /* caller-provided scrub state */ + struct xfs_btree_cur *cur; + xfs_btree_scrub_rec_fn scrub_rec; + struct xfs_buf *agi_bp; + struct xfs_buf *agf_bp; + struct xfs_buf *agfl_bp; + struct xfs_owner_info oinfo; + + /* internal scrub state */ + union xfs_btree_rec lastrec; + bool firstrec; + union xfs_btree_key lastkey[XFS_BTREE_MAXLEVELS]; + bool firstkey[XFS_BTREE_MAXLEVELS]; + struct xfs_btree_cur *rmap_cur; + struct xfs_btree_cur *bno_cur; + struct list_head to_check; + int error; +}; + +int xfs_btree_scrub(struct xfs_btree_scrub *bs); +void xfs_btree_scrub_error(struct xfs_btree_cur *cur, int level, + const char *file, int line, const char *check); +#define XFS_BTREC_SCRUB_CHECK(bs, fs_ok) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + } +#define XFS_BTREC_SCRUB_GOTO(bs, fs_ok, label) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + goto label; \ + } +#define XFS_BTKEY_SCRUB_CHECK(bs, level, fs_ok) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, (level), __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + } +#define XFS_BTKEY_SCRUB_GOTO(bs, level, fs_ok, label) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + goto label; \ + } + +#endif /* __XFS_SCRUB_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:30:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5F73F7F28 for ; Thu, 16 Jun 2016 20:30:21 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 17CB7304039 for ; Thu, 16 Jun 2016 18:30:21 -0700 (PDT) X-ASG-Debug-ID: 1466127018-04cbb01fec69bc0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id ANE8nEA52Fn2Pk4f (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:19 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UD3L013411 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:13 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UCT1017621 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:13 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UBRQ026311; Fri, 17 Jun 2016 01:30:12 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:11 -0700 Subject: [PATCH 114/119] xfs: create sysfs hooks to scrub various files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 114/119] xfs: create sysfs hooks to scrub various files To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:10 -0700 Message-ID: <146612700997.12839.14645543192839503554.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127018 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9787 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create some sysfs files so that we can scrub various AG metadata structures. The interface will be as follows: # cat /sys/fs/xfs/$dev/check/rmapbt 0:3 # echo 3 > /sys/fs/xfs/$dev/check/rmapbt -bash: echo: write error: (or it'll just return 0 if the metadata is fine) Signed-off-by: Darrick J. Wong --- fs/xfs/Makefile | 1 fs/xfs/xfs_mount.c | 9 ++ fs/xfs/xfs_mount.h | 1 fs/xfs/xfs_scrub_sysfs.c | 214 ++++++++++++++++++++++++++++++++++++++++++++++ fs/xfs/xfs_scrub_sysfs.h | 26 ++++++ 5 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 fs/xfs/xfs_scrub_sysfs.c create mode 100644 fs/xfs/xfs_scrub_sysfs.h diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index 8942390..7d93af2 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile @@ -93,6 +93,7 @@ xfs-y += xfs_aops.o \ xfs_mount.o \ xfs_mru_cache.o \ xfs_reflink.o \ + xfs_scrub_sysfs.o \ xfs_stats.o \ xfs_super.o \ xfs_symlink.o \ diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index e53853d..1f74f72 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c @@ -46,6 +46,7 @@ #include "xfs_refcount_btree.h" #include "xfs_reflink.h" #include "xfs_refcount_btree.h" +#include "xfs_scrub_sysfs.h" static DEFINE_MUTEX(xfs_uuid_table_mutex); @@ -705,10 +706,13 @@ xfs_mountfs( if (error) goto out_del_stats; + error = xfs_scrub_init(mp); + if (error) + goto out_remove_error_sysfs; error = xfs_uuid_mount(mp); if (error) - goto out_remove_error_sysfs; + goto out_remove_scrub; /* * Set the minimum read and write sizes @@ -993,6 +997,8 @@ xfs_mountfs( xfs_da_unmount(mp); out_remove_uuid: xfs_uuid_unmount(mp); + out_remove_scrub: + xfs_scrub_free(mp); out_remove_error_sysfs: xfs_error_sysfs_del(mp); out_del_stats: @@ -1093,6 +1099,7 @@ xfs_unmountfs( #endif xfs_free_perag(mp); + xfs_scrub_free(mp); xfs_error_sysfs_del(mp); xfs_sysfs_del(&mp->m_stats.xs_kobj); xfs_sysfs_del(&mp->m_kobj); diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 6b06d24..0e222d2 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -167,6 +167,7 @@ typedef struct xfs_mount { struct xfs_kobj m_error_kobj; struct xfs_kobj m_error_meta_kobj; struct xfs_error_cfg m_error_cfg[XFS_ERR_CLASS_MAX][XFS_ERR_ERRNO_MAX]; + struct xfs_kobj m_scrub_kobj; struct xstats m_stats; /* per-fs stats */ struct workqueue_struct *m_buf_workqueue; diff --git a/fs/xfs/xfs_scrub_sysfs.c b/fs/xfs/xfs_scrub_sysfs.c new file mode 100644 index 0000000..9942d55 --- /dev/null +++ b/fs/xfs/xfs_scrub_sysfs.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "xfs.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_btree.h" +#include "xfs_bmap.h" +#include "xfs_refcount.h" +#include "xfs_rmap_btree.h" +#include "xfs_alloc.h" +#include "xfs_ialloc.h" +#include "xfs_sysfs.h" +#include + +/* general scrub attributes */ +struct xfs_scrub_attr { + struct attribute attr; + bool (*is_visible)(struct xfs_mount *mp, struct xfs_scrub_attr *attr); + ssize_t (*show)(struct xfs_mount *mp, struct xfs_scrub_attr *attr, + char *buf); + ssize_t (*store)(struct xfs_mount *mp, struct xfs_scrub_attr *attr, + const char *buf, size_t count); +}; + +static inline struct xfs_scrub_attr * +to_scrub_attr(struct attribute *attr) +{ + return container_of(attr, struct xfs_scrub_attr, attr); +} + +static inline struct xfs_mount *to_mount(struct kobject *kobj) +{ + struct xfs_kobj *k = container_of(kobj, struct xfs_kobj, kobject); + + return container_of(k, struct xfs_mount, m_scrub_kobj); +} + +STATIC ssize_t +xfs_scrub_attr_show( + struct kobject *kobject, + struct attribute *attr, + char *buf) +{ + struct xfs_scrub_attr *sa = to_scrub_attr(attr); + struct xfs_mount *mp = to_mount(kobject); + + return sa->show ? sa->show(mp, sa, buf) : 0; +} + +STATIC ssize_t +xfs_scrub_attr_store( + struct kobject *kobject, + struct attribute *attr, + const char *buf, + size_t count) +{ + struct xfs_scrub_attr *sa = to_scrub_attr(attr); + struct xfs_mount *mp = to_mount(kobject); + + return sa->store ? sa->store(mp, sa, buf, count) : 0; +} + +STATIC umode_t +xfs_scrub_attr_visible( + struct kobject *kobject, + struct attribute *attr, + int unused) +{ + struct xfs_scrub_attr *sa = to_scrub_attr(attr); + struct xfs_mount *mp = to_mount(kobject); + + if (!sa->is_visible || sa->is_visible(mp, sa)) + return attr->mode; + return 0; +} + +static const struct sysfs_ops xfs_scrub_ops = { + .show = xfs_scrub_attr_show, + .store = xfs_scrub_attr_store, +}; + +static struct kobj_type xfs_scrub_ktype = { + .release = xfs_sysfs_release, + .sysfs_ops = &xfs_scrub_ops, +}; + +/* per-AG scrub attributes */ +struct xfs_agdata_scrub_attr { + struct xfs_scrub_attr sa; + bool (*has_feature)(struct xfs_sb *); + int (*scrub)(struct xfs_mount *mp, xfs_agnumber_t agno); +}; + +static inline struct xfs_agdata_scrub_attr * +to_agdata_scrub_attr(struct xfs_scrub_attr *sa) +{ + return container_of(sa, struct xfs_agdata_scrub_attr, sa); +} + +STATIC bool +xfs_agdata_scrub_visible( + struct xfs_mount *mp, + struct xfs_scrub_attr *sa) +{ + struct xfs_agdata_scrub_attr *asa = to_agdata_scrub_attr(sa); + + return (!asa->has_feature || asa->has_feature(&mp->m_sb)); +} + +STATIC ssize_t +xfs_agdata_scrub_show( + struct xfs_mount *mp, + struct xfs_scrub_attr *sa, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "0:%u\n", mp->m_sb.sb_agcount - 1); +} + +STATIC ssize_t +xfs_agdata_scrub_store( + struct xfs_mount *mp, + struct xfs_scrub_attr *sa, + const char *buf, + size_t count) +{ + unsigned long val; + xfs_agnumber_t agno; + struct xfs_agdata_scrub_attr *asa = to_agdata_scrub_attr(sa); + int error; + + error = kstrtoul(buf, 0, &val); + if (error) + return error; + agno = val; + if (agno >= mp->m_sb.sb_agcount) + return -EINVAL; + error = asa->scrub(mp, agno); + if (error) + return error; + return count; +} + +#define XFS_AGDATA_SCRUB_ATTR(_name, _fn) \ +static struct xfs_agdata_scrub_attr xfs_agdata_scrub_attr_##_name = { \ + .sa = { \ + .attr = {.name = __stringify(_name), .mode = 0600 }, \ + .is_visible = xfs_agdata_scrub_visible, \ + .show = xfs_agdata_scrub_show, \ + .store = xfs_agdata_scrub_store, \ + }, \ + .has_feature = _fn, \ + .scrub = xfs_##_name##_scrub, \ +} +#define XFS_AGDATA_SCRUB_LIST(name) &xfs_agdata_scrub_attr_##name.sa.attr + +static struct attribute *xfs_agdata_scrub_attrs[] = { + NULL, +}; + +static const struct attribute_group xfs_agdata_scrub_attr_group = { + .is_visible = xfs_scrub_attr_visible, + .attrs = xfs_agdata_scrub_attrs, +}; + +int +xfs_scrub_init( + struct xfs_mount *mp) +{ + int error; + + error = xfs_sysfs_init(&mp->m_scrub_kobj, &xfs_scrub_ktype, + &mp->m_kobj, "check"); + if (error) + return error; + + error = sysfs_create_group(&mp->m_scrub_kobj.kobject, + &xfs_agdata_scrub_attr_group); + if (error) + goto err; + return error; +err: + xfs_sysfs_del(&mp->m_scrub_kobj); + return error; +} + +void +xfs_scrub_free( + struct xfs_mount *mp) +{ + sysfs_remove_group(&mp->m_scrub_kobj.kobject, + &xfs_agdata_scrub_attr_group); + xfs_sysfs_del(&mp->m_scrub_kobj); +} diff --git a/fs/xfs/xfs_scrub_sysfs.h b/fs/xfs/xfs_scrub_sysfs.h new file mode 100644 index 0000000..d9a58f5 --- /dev/null +++ b/fs/xfs/xfs_scrub_sysfs.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_SCRUB_H +#define __XFS_SCRUB_H + +int xfs_scrub_init(struct xfs_mount *mp); +void xfs_scrub_free(struct xfs_mount *mp); + +#endif /* __XFS_SCRUB_H */ From darrick.wong@oracle.com Thu Jun 16 20:30:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 21AFF7FE5 for ; Thu, 16 Jun 2016 20:30:26 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D43378F804B for ; Thu, 16 Jun 2016 18:30:25 -0700 (PDT) X-ASG-Debug-ID: 1466127023-04bdf01e1595e70001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id nzHaEmJE5MdrsGl1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:23 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UIVG013463 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:30:18 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1UIqq022694 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:30:18 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1UIca030398; Fri, 17 Jun 2016 01:30:18 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:17 -0700 Subject: [PATCH 115/119] xfs: support scrubbing free space btrees From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 115/119] xfs: support scrubbing free space btrees To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:16 -0700 Message-ID: <146612701627.12839.18375212914216273798.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127023 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7517 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the free space btrees. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_alloc.c | 98 +++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_alloc.h | 3 + fs/xfs/libxfs/xfs_alloc_btree.c | 51 ++++++++++++++++++-- fs/xfs/xfs_scrub_sysfs.c | 5 ++ 4 files changed, 151 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 6fc1981..bc2a1b1 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -39,6 +39,7 @@ #include "xfs_log.h" #include "xfs_ag_resv.h" #include "xfs_refcount_btree.h" +#include "xfs_scrub.h" struct workqueue_struct *xfs_alloc_wq; @@ -2957,3 +2958,100 @@ xfs_alloc_record_exists( *is_freesp = (fbno <= bno && fbno + flen >= bno + len); return 0; } + +STATIC int +xfs_allocbt_scrub_rmap_check( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + xfs_err(cur->bc_mp, "%s: freespace in rmapbt! %u/%u %u %lld %lld %x", + __func__, cur->bc_private.a.agno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + rec->rm_flags); + return XFS_BTREE_QUERY_RANGE_ABORT; +} + +STATIC int +xfs_allocbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + xfs_agblock_t bno; + xfs_extlen_t len; + struct xfs_rmap_irec low; + struct xfs_rmap_irec high; + bool no_rmap; + int error; + + bno = be32_to_cpu(rec->alloc.ar_startblock); + len = be32_to_cpu(rec->alloc.ar_blockcount); + + XFS_BTREC_SCRUB_CHECK(bs, bno <= mp->m_sb.sb_agblocks); + XFS_BTREC_SCRUB_CHECK(bs, bno < bno + len); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <= + mp->m_sb.sb_agblocks); + + /* if rmapbt, make sure there's no record */ + if (!bs->rmap_cur) + return 0; + + memset(&low, 0, sizeof(low)); + low.rm_startblock = bno; + memset(&high, 0xFF, sizeof(high)); + high.rm_startblock = bno + len - 1; + + error = xfs_rmapbt_query_range(bs->rmap_cur, &low, &high, + &xfs_allocbt_scrub_rmap_check, NULL); + if (error && error != XFS_BTREE_QUERY_RANGE_ABORT) + goto err; + no_rmap = error == 0; + XFS_BTREC_SCRUB_CHECK(bs, no_rmap); +err: + return error; +} + +/* Scrub the freespace btrees for some AG. */ +STATIC int +xfs_allocbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno, + int which) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) + return error; + + bs.cur = xfs_allocbt_init_cursor(mp, NULL, bs.agf_bp, agno, which); + bs.scrub_rec = xfs_allocbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_AG); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} + +int +xfs_bnobt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_allocbt_scrub(mp, agno, XFS_BTNUM_BNO); +} + +int +xfs_cntbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_allocbt_scrub(mp, agno, XFS_BTNUM_CNT); +} diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h index 4f2ce38..f1fcc7e 100644 --- a/fs/xfs/libxfs/xfs_alloc.h +++ b/fs/xfs/libxfs/xfs_alloc.h @@ -213,4 +213,7 @@ xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); int xfs_alloc_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool *is_freesp); +int xfs_bnobt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); +int xfs_cntbt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); + #endif /* __XFS_ALLOC_H__ */ diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c index 5ba2dac..f9859e8 100644 --- a/fs/xfs/libxfs/xfs_alloc_btree.c +++ b/fs/xfs/libxfs/xfs_alloc_btree.c @@ -256,6 +256,26 @@ xfs_allocbt_key_diff( return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock; } +STATIC __int64_t +xfs_bnobt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->alloc.ar_startblock) - + be32_to_cpu(k1->alloc.ar_startblock); +} + +STATIC __int64_t +xfs_cntbt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->alloc.ar_blockcount) - + be32_to_cpu(k1->alloc.ar_blockcount); +} + static bool xfs_allocbt_verify( struct xfs_buf *bp) @@ -344,7 +364,6 @@ const struct xfs_buf_ops xfs_allocbt_buf_ops = { }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_allocbt_keys_inorder( struct xfs_btree_cur *cur, @@ -381,9 +400,29 @@ xfs_allocbt_recs_inorder( be32_to_cpu(r2->alloc.ar_startblock)); } } -#endif /* DEBUG */ -static const struct xfs_btree_ops xfs_allocbt_ops = { +static const struct xfs_btree_ops xfs_bnobt_ops = { + .rec_len = sizeof(xfs_alloc_rec_t), + .key_len = sizeof(xfs_alloc_key_t), + + .dup_cursor = xfs_allocbt_dup_cursor, + .set_root = xfs_allocbt_set_root, + .alloc_block = xfs_allocbt_alloc_block, + .free_block = xfs_allocbt_free_block, + .update_lastrec = xfs_allocbt_update_lastrec, + .get_minrecs = xfs_allocbt_get_minrecs, + .get_maxrecs = xfs_allocbt_get_maxrecs, + .init_key_from_rec = xfs_allocbt_init_key_from_rec, + .init_rec_from_cur = xfs_allocbt_init_rec_from_cur, + .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, + .key_diff = xfs_allocbt_key_diff, + .buf_ops = &xfs_allocbt_buf_ops, + .diff_two_keys = xfs_bnobt_diff_two_keys, + .keys_inorder = xfs_allocbt_keys_inorder, + .recs_inorder = xfs_allocbt_recs_inorder, +}; + +static const struct xfs_btree_ops xfs_cntbt_ops = { .rec_len = sizeof(xfs_alloc_rec_t), .key_len = sizeof(xfs_alloc_key_t), @@ -399,10 +438,9 @@ static const struct xfs_btree_ops xfs_allocbt_ops = { .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, .key_diff = xfs_allocbt_key_diff, .buf_ops = &xfs_allocbt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_cntbt_diff_two_keys, .keys_inorder = xfs_allocbt_keys_inorder, .recs_inorder = xfs_allocbt_recs_inorder, -#endif }; /* @@ -427,12 +465,13 @@ xfs_allocbt_init_cursor( cur->bc_mp = mp; cur->bc_btnum = btnum; cur->bc_blocklog = mp->m_sb.sb_blocklog; - cur->bc_ops = &xfs_allocbt_ops; if (btnum == XFS_BTNUM_CNT) { + cur->bc_ops = &xfs_cntbt_ops; cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; } else { + cur->bc_ops = &xfs_bnobt_ops; cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); } diff --git a/fs/xfs/xfs_scrub_sysfs.c b/fs/xfs/xfs_scrub_sysfs.c index 9942d55..efaa635 100644 --- a/fs/xfs/xfs_scrub_sysfs.c +++ b/fs/xfs/xfs_scrub_sysfs.c @@ -174,7 +174,12 @@ static struct xfs_agdata_scrub_attr xfs_agdata_scrub_attr_##_name = { \ } #define XFS_AGDATA_SCRUB_LIST(name) &xfs_agdata_scrub_attr_##name.sa.attr +XFS_AGDATA_SCRUB_ATTR(bnobt, NULL); +XFS_AGDATA_SCRUB_ATTR(cntbt, NULL); + static struct attribute *xfs_agdata_scrub_attrs[] = { + XFS_AGDATA_SCRUB_LIST(bnobt), + XFS_AGDATA_SCRUB_LIST(cntbt), NULL, }; From darrick.wong@oracle.com Thu Jun 16 20:30:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B72F67FE7 for ; Thu, 16 Jun 2016 20:30:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 78E80304039 for ; Thu, 16 Jun 2016 18:30:34 -0700 (PDT) X-ASG-Debug-ID: 1466127031-04cb6c542757c00001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id PzNhf91QwFJlKYvj (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:31 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UPp2013479 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:26 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UPbF018094 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:25 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UOIW026344; Fri, 17 Jun 2016 01:30:24 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:24 -0700 Subject: [PATCH 116/119] xfs: support scrubbing inode btrees From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 116/119] xfs: support scrubbing inode btrees To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:22 -0700 Message-ID: <146612702255.12839.10431805043902780580.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127031 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9224 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the inode btrees. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_ialloc.c | 178 +++++++++++++++++++++++++++++++++++--- fs/xfs/libxfs/xfs_ialloc.h | 2 fs/xfs/libxfs/xfs_ialloc_btree.c | 18 +++- fs/xfs/xfs_scrub_sysfs.c | 4 + 4 files changed, 180 insertions(+), 22 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 1982561..c496dd4 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -40,6 +40,8 @@ #include "xfs_icache.h" #include "xfs_trace.h" #include "xfs_log.h" +#include "xfs_rmap_btree.h" +#include "xfs_scrub.h" /* @@ -98,24 +100,14 @@ xfs_inobt_update( return xfs_btree_update(cur, &rec); } -/* - * Get the data from the pointed-to record. - */ -int /* error */ -xfs_inobt_get_rec( - struct xfs_btree_cur *cur, /* btree cursor */ - xfs_inobt_rec_incore_t *irec, /* btree record */ - int *stat) /* output: success/failure */ +STATIC void +xfs_inobt_btrec_to_irec( + struct xfs_mount *mp, + union xfs_btree_rec *rec, + struct xfs_inobt_rec_incore *irec) { - union xfs_btree_rec *rec; - int error; - - error = xfs_btree_get_rec(cur, &rec, stat); - if (error || *stat == 0) - return error; - irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino); - if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) { + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) { irec->ir_holemask = be16_to_cpu(rec->inobt.ir_u.sp.ir_holemask); irec->ir_count = rec->inobt.ir_u.sp.ir_count; irec->ir_freecount = rec->inobt.ir_u.sp.ir_freecount; @@ -130,6 +122,25 @@ xfs_inobt_get_rec( be32_to_cpu(rec->inobt.ir_u.f.ir_freecount); } irec->ir_free = be64_to_cpu(rec->inobt.ir_free); +} + +/* + * Get the data from the pointed-to record. + */ +int /* error */ +xfs_inobt_get_rec( + struct xfs_btree_cur *cur, /* btree cursor */ + xfs_inobt_rec_incore_t *irec, /* btree record */ + int *stat) /* output: success/failure */ +{ + union xfs_btree_rec *rec; + int error; + + error = xfs_btree_get_rec(cur, &rec, stat); + if (error || *stat == 0) + return error; + + xfs_inobt_btrec_to_irec(cur->bc_mp, rec, irec); return 0; } @@ -2650,3 +2661,138 @@ xfs_ialloc_pagi_init( xfs_trans_brelse(tp, bp); return 0; } + +STATIC int +xfs_iallocbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + struct xfs_inobt_rec_incore irec; + __uint16_t holemask; + xfs_agino_t agino; + xfs_agblock_t bno; + xfs_extlen_t len; + int holecount; + int i; + bool has_rmap = false; + struct xfs_owner_info oinfo; + int error = 0; + uint64_t holes; + + xfs_inobt_btrec_to_irec(mp, rec, &irec); + + XFS_BTREC_SCRUB_CHECK(bs, irec.ir_count <= XFS_INODES_PER_CHUNK); + XFS_BTREC_SCRUB_CHECK(bs, irec.ir_freecount <= XFS_INODES_PER_CHUNK); + agino = irec.ir_startino; + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); + + /* Handle non-sparse inodes */ + if (!xfs_inobt_issparse(irec.ir_holemask)) { + len = XFS_B_TO_FSB(mp, + XFS_INODES_PER_CHUNK * mp->m_sb.sb_inodesize); + bno = XFS_AGINO_TO_AGBNO(mp, agino); + + XFS_BTREC_SCRUB_CHECK(bs, bno < mp->m_sb.sb_agblocks) + XFS_BTREC_SCRUB_CHECK(bs, bno < bno + len); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <= + mp->m_sb.sb_agblocks); + + if (!bs->rmap_cur) + return error; + error = xfs_rmap_record_exists(bs->rmap_cur, bno, len, &oinfo, + &has_rmap); + if (error) + return error; + XFS_BTREC_SCRUB_CHECK(bs, has_rmap); + return 0; + } + + /* Check each chunk of a sparse inode cluster. */ + holemask = irec.ir_holemask; + holecount = 0; + len = XFS_B_TO_FSB(mp, + XFS_INODES_PER_HOLEMASK_BIT * mp->m_sb.sb_inodesize); + holes = ~xfs_inobt_irec_to_allocmask(&irec); + XFS_BTREC_SCRUB_CHECK(bs, (holes & irec.ir_free) == holes); + XFS_BTREC_SCRUB_CHECK(bs, irec.ir_freecount <= irec.ir_count); + + for (i = 0; i < XFS_INOBT_HOLEMASK_BITS; holemask >>= 1, + i++, agino += XFS_INODES_PER_HOLEMASK_BIT) { + if (holemask & 1) { + holecount += XFS_INODES_PER_HOLEMASK_BIT; + continue; + } + bno = XFS_AGINO_TO_AGBNO(mp, agino); + + XFS_BTREC_SCRUB_CHECK(bs, bno < mp->m_sb.sb_agblocks) + XFS_BTREC_SCRUB_CHECK(bs, bno < bno + len); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <= + mp->m_sb.sb_agblocks); + + if (!bs->rmap_cur) + continue; + error = xfs_rmap_record_exists(bs->rmap_cur, bno, len, &oinfo, + &has_rmap); + if (error) + break; + XFS_BTREC_SCRUB_CHECK(bs, has_rmap); + } + + XFS_BTREC_SCRUB_CHECK(bs, holecount <= XFS_INODES_PER_CHUNK); + XFS_BTREC_SCRUB_CHECK(bs, holecount + irec.ir_count == + XFS_INODES_PER_CHUNK); + + return error; +} + +/* Scrub the inode btrees for some AG. */ +STATIC int +xfs_iallocbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_btnum_t which) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_ialloc_read_agi(mp, NULL, agno, &bs.agi_bp); + if (error) + return error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) { + xfs_trans_brelse(NULL, bs.agi_bp); + return error; + } + + bs.cur = xfs_inobt_init_cursor(mp, NULL, bs.agi_bp, agno, which); + bs.scrub_rec = xfs_iallocbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_INOBT); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + xfs_trans_brelse(NULL, bs.agi_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} + +int +xfs_inobt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_iallocbt_scrub(mp, agno, XFS_BTNUM_INO); +} + +int +xfs_finobt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_iallocbt_scrub(mp, agno, XFS_BTNUM_FINO); +} diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h index 0bb8966..7ea6ff3 100644 --- a/fs/xfs/libxfs/xfs_ialloc.h +++ b/fs/xfs/libxfs/xfs_ialloc.h @@ -168,5 +168,7 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **bpp); +extern int xfs_inobt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); +extern int xfs_finobt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); #endif /* __XFS_IALLOC_H__ */ diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c index fd26550..81c673c 100644 --- a/fs/xfs/libxfs/xfs_ialloc_btree.c +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c @@ -204,6 +204,16 @@ xfs_inobt_key_diff( cur->bc_rec.i.ir_startino; } +STATIC __int64_t +xfs_inobt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->inobt.ir_startino) - + be32_to_cpu(k1->inobt.ir_startino); +} + static int xfs_inobt_verify( struct xfs_buf *bp) @@ -278,7 +288,6 @@ const struct xfs_buf_ops xfs_inobt_buf_ops = { .verify_write = xfs_inobt_write_verify, }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_inobt_keys_inorder( struct xfs_btree_cur *cur, @@ -298,7 +307,6 @@ xfs_inobt_recs_inorder( return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <= be32_to_cpu(r2->inobt.ir_startino); } -#endif /* DEBUG */ static const struct xfs_btree_ops xfs_inobt_ops = { .rec_len = sizeof(xfs_inobt_rec_t), @@ -315,10 +323,9 @@ static const struct xfs_btree_ops xfs_inobt_ops = { .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, .buf_ops = &xfs_inobt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_inobt_diff_two_keys, .keys_inorder = xfs_inobt_keys_inorder, .recs_inorder = xfs_inobt_recs_inorder, -#endif }; static const struct xfs_btree_ops xfs_finobt_ops = { @@ -336,10 +343,9 @@ static const struct xfs_btree_ops xfs_finobt_ops = { .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, .buf_ops = &xfs_inobt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_inobt_diff_two_keys, .keys_inorder = xfs_inobt_keys_inorder, .recs_inorder = xfs_inobt_recs_inorder, -#endif }; /* diff --git a/fs/xfs/xfs_scrub_sysfs.c b/fs/xfs/xfs_scrub_sysfs.c index efaa635..cb7812f 100644 --- a/fs/xfs/xfs_scrub_sysfs.c +++ b/fs/xfs/xfs_scrub_sysfs.c @@ -176,10 +176,14 @@ static struct xfs_agdata_scrub_attr xfs_agdata_scrub_attr_##_name = { \ XFS_AGDATA_SCRUB_ATTR(bnobt, NULL); XFS_AGDATA_SCRUB_ATTR(cntbt, NULL); +XFS_AGDATA_SCRUB_ATTR(inobt, NULL); +XFS_AGDATA_SCRUB_ATTR(finobt, xfs_sb_version_hasfinobt); static struct attribute *xfs_agdata_scrub_attrs[] = { XFS_AGDATA_SCRUB_LIST(bnobt), XFS_AGDATA_SCRUB_LIST(cntbt), + XFS_AGDATA_SCRUB_LIST(inobt), + XFS_AGDATA_SCRUB_LIST(finobt), NULL, }; From darrick.wong@oracle.com Thu Jun 16 20:30:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 356B27FA9 for ; Thu, 16 Jun 2016 20:30:39 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id ECBF630404E for ; Thu, 16 Jun 2016 18:30:38 -0700 (PDT) X-ASG-Debug-ID: 1466127036-04cbb01fed69c50001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 82m9135AvLdAvH0q (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:37 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UWWO013522 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:32 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UVkT024309 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:32 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UUvm021825; Fri, 17 Jun 2016 01:30:31 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:30 -0700 Subject: [PATCH 117/119] xfs: support scrubbing rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 117/119] xfs: support scrubbing rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:28 -0700 Message-ID: <146612702887.12839.3951774203711037031.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127036 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5193 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the rmap btree. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_rmap.c | 77 ++++++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rmap_btree.c | 4 -- fs/xfs/libxfs/xfs_rmap_btree.h | 2 + fs/xfs/xfs_scrub_sysfs.c | 2 + 4 files changed, 81 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index e7673ec..0c8a236 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -38,6 +38,7 @@ #include "xfs_extent_busy.h" #include "xfs_bmap.h" #include "xfs_inode.h" +#include "xfs_scrub.h" /* * Lookup the first record less than or equal to [bno, len, owner, offset] @@ -2367,3 +2368,79 @@ xfs_rmap_record_exists( irec.rm_startblock + irec.rm_blockcount >= bno + len); return 0; } + +STATIC int +xfs_rmapbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + struct xfs_rmap_irec irec; + bool is_freesp; + bool non_inode; + bool is_unwritten; + bool is_bmbt; + bool is_attr; + int error; + + error = xfs_rmapbt_btrec_to_irec(rec, &irec); + if (error) + return error; + + XFS_BTREC_SCRUB_CHECK(bs, irec.rm_startblock < mp->m_sb.sb_agblocks) + XFS_BTREC_SCRUB_CHECK(bs, irec.rm_startblock < irec.rm_startblock + + irec.rm_blockcount); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)irec.rm_startblock + + irec.rm_blockcount <= mp->m_sb.sb_agblocks) + + non_inode = XFS_RMAP_NON_INODE_OWNER(irec.rm_owner); + is_bmbt = irec.rm_flags & XFS_RMAP_ATTR_FORK; + is_attr = irec.rm_flags & XFS_RMAP_BMBT_BLOCK; + is_unwritten = irec.rm_flags & XFS_RMAP_UNWRITTEN; + + XFS_BTREC_SCRUB_CHECK(bs, !is_bmbt || irec.rm_offset == 0); + XFS_BTREC_SCRUB_CHECK(bs, !non_inode || irec.rm_offset == 0); + XFS_BTREC_SCRUB_CHECK(bs, !is_unwritten || !(is_bmbt || non_inode || + is_attr)); + XFS_BTREC_SCRUB_CHECK(bs, !non_inode || !(is_bmbt || is_unwritten || + is_attr)); + + /* check there's no record in freesp btrees */ + error = xfs_alloc_record_exists(bs->bno_cur, irec.rm_startblock, + irec.rm_blockcount, &is_freesp); + if (error) + goto err; + XFS_BTREC_SCRUB_CHECK(bs, !is_freesp); + + /* XXX: check with the owner */ + +err: + return error; +} + +/* Scrub the rmap btree for some AG. */ +int +xfs_rmapbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) + return error; + + bs.cur = xfs_rmapbt_init_cursor(mp, NULL, bs.agf_bp, agno); + bs.scrub_rec = xfs_rmapbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_AG); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} diff --git a/fs/xfs/libxfs/xfs_rmap_btree.c b/fs/xfs/libxfs/xfs_rmap_btree.c index 0b045a6..9861e49 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.c +++ b/fs/xfs/libxfs/xfs_rmap_btree.c @@ -372,7 +372,6 @@ const struct xfs_buf_ops xfs_rmapbt_buf_ops = { .verify_write = xfs_rmapbt_write_verify, }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_rmapbt_keys_inorder( struct xfs_btree_cur *cur, @@ -408,7 +407,6 @@ xfs_rmapbt_recs_inorder( return 1; return 0; } -#endif /* DEBUG */ static const struct xfs_btree_ops xfs_rmapbt_ops = { .rec_len = sizeof(struct xfs_rmap_rec), @@ -428,10 +426,8 @@ static const struct xfs_btree_ops xfs_rmapbt_ops = { .key_diff = xfs_rmapbt_key_diff, .buf_ops = &xfs_rmapbt_buf_ops, .diff_two_keys = xfs_rmapbt_diff_two_keys, -#if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_rmapbt_keys_inorder, .recs_inorder = xfs_rmapbt_recs_inorder, -#endif }; /* diff --git a/fs/xfs/libxfs/xfs_rmap_btree.h b/fs/xfs/libxfs/xfs_rmap_btree.h index 2f072c8..3f8742d 100644 --- a/fs/xfs/libxfs/xfs_rmap_btree.h +++ b/fs/xfs/libxfs/xfs_rmap_btree.h @@ -147,4 +147,6 @@ extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, extern int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo, bool *has_rmap); +int xfs_rmapbt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); + #endif /* __XFS_RMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_scrub_sysfs.c b/fs/xfs/xfs_scrub_sysfs.c index cb7812f..c2256f3 100644 --- a/fs/xfs/xfs_scrub_sysfs.c +++ b/fs/xfs/xfs_scrub_sysfs.c @@ -178,12 +178,14 @@ XFS_AGDATA_SCRUB_ATTR(bnobt, NULL); XFS_AGDATA_SCRUB_ATTR(cntbt, NULL); XFS_AGDATA_SCRUB_ATTR(inobt, NULL); XFS_AGDATA_SCRUB_ATTR(finobt, xfs_sb_version_hasfinobt); +XFS_AGDATA_SCRUB_ATTR(rmapbt, xfs_sb_version_hasrmapbt); static struct attribute *xfs_agdata_scrub_attrs[] = { XFS_AGDATA_SCRUB_LIST(bnobt), XFS_AGDATA_SCRUB_LIST(cntbt), XFS_AGDATA_SCRUB_LIST(inobt), XFS_AGDATA_SCRUB_LIST(finobt), + XFS_AGDATA_SCRUB_LIST(rmapbt), NULL, }; From darrick.wong@oracle.com Thu Jun 16 20:30:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 453147EFB for ; Thu, 16 Jun 2016 20:30:45 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 14FBD304048 for ; Thu, 16 Jun 2016 18:30:45 -0700 (PDT) X-ASG-Debug-ID: 1466127041-04cbb01fee69c80001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 6m8DIrxbdoDBtBJ8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:42 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UbM5000500 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:39 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UbAk024400 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:37 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Ubio026456; Fri, 17 Jun 2016 01:30:37 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:36 -0700 Subject: [PATCH 118/119] xfs: support scrubbing refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 118/119] xfs: support scrubbing refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:35 -0700 Message-ID: <146612703518.12839.12399566032000681767.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127042 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10434 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the refcount btree. If rmap is available, check the reference count by performing an interval query against the rmapbt. v2: Handle the case where the rmap records are not all at least the length of the refcount extent. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_refcount.c | 224 ++++++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount.h | 2 fs/xfs/libxfs/xfs_refcount_btree.c | 16 ++- fs/xfs/xfs_scrub_sysfs.c | 2 4 files changed, 240 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index e8d8702..126dd57 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -37,6 +37,7 @@ #include "xfs_bit.h" #include "xfs_refcount.h" #include "xfs_rmap_btree.h" +#include "xfs_scrub.h" /* Allowable refcount adjustment amounts. */ enum xfs_refc_adjust_op { @@ -1578,3 +1579,226 @@ xfs_refcount_free_cow_extent( return __xfs_refcount_add(mp, dfops, &ri); } + +struct xfs_refcountbt_scrub_fragment { + struct xfs_rmap_irec rm; + struct list_head list; +}; + +struct xfs_refcountbt_scrub_rmap_check_info { + xfs_nlink_t nr; + struct xfs_refcount_irec rc; + struct list_head fragments; +}; + +static int +xfs_refcountbt_scrub_rmap_check( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct xfs_refcountbt_scrub_rmap_check_info *rsrci = priv; + struct xfs_refcountbt_scrub_fragment *frag; + xfs_agblock_t rm_last; + xfs_agblock_t rc_last; + + rm_last = rec->rm_startblock + rec->rm_blockcount; + rc_last = rsrci->rc.rc_startblock + rsrci->rc.rc_blockcount; + if (rec->rm_startblock <= rsrci->rc.rc_startblock && rm_last >= rc_last) + rsrci->nr++; + else { + frag = kmem_zalloc(sizeof(struct xfs_refcountbt_scrub_fragment), + KM_SLEEP); + frag->rm = *rec; + list_add_tail(&frag->list, &rsrci->fragments); + } + + return 0; +} + +STATIC void +xfs_refcountbt_process_rmap_fragments( + struct xfs_mount *mp, + struct xfs_refcountbt_scrub_rmap_check_info *rsrci) +{ + struct list_head worklist; + struct xfs_refcountbt_scrub_fragment *cur; + struct xfs_refcountbt_scrub_fragment *n; + xfs_agblock_t bno; + xfs_agblock_t rbno; + xfs_agblock_t next_rbno; + xfs_nlink_t nr; + xfs_nlink_t target_nr; + + target_nr = rsrci->rc.rc_refcount - rsrci->nr; + if (target_nr == 0) + return; + + /* + * There are (rsrci->rc.rc_refcount - rsrci->nr refcount) + * references we haven't found yet. Pull that many off the + * fragment list and figure out where the smallest rmap ends + * (and therefore the next rmap should start). All the rmaps + * we pull off should start at or before the beginning of the + * refcount record's range. + */ + INIT_LIST_HEAD(&worklist); + rbno = NULLAGBLOCK; + nr = 1; + list_for_each_entry_safe(cur, n, &rsrci->fragments, list) { + if (cur->rm.rm_startblock > rsrci->rc.rc_startblock) + goto fail; + bno = cur->rm.rm_startblock + cur->rm.rm_blockcount; + if (rbno > bno) + rbno = bno; + list_del(&cur->list); + list_add_tail(&cur->list, &worklist); + if (nr == target_nr) + break; + nr++; + } + + if (nr != target_nr) + goto fail; + + while (!list_empty(&rsrci->fragments)) { + /* Discard any fragments ending at rbno. */ + nr = 0; + next_rbno = NULLAGBLOCK; + list_for_each_entry_safe(cur, n, &worklist, list) { + bno = cur->rm.rm_startblock + cur->rm.rm_blockcount; + if (bno != rbno) { + if (next_rbno > bno) + next_rbno = bno; + continue; + } + list_del(&cur->list); + kmem_free(cur); + nr++; + } + + /* Empty list? We're done. */ + if (list_empty(&rsrci->fragments)) + break; + + /* Try to add nr rmaps starting at rbno to the worklist. */ + list_for_each_entry_safe(cur, n, &rsrci->fragments, list) { + bno = cur->rm.rm_startblock + cur->rm.rm_blockcount; + if (cur->rm.rm_startblock != rbno) + goto fail; + list_del(&cur->list); + list_add_tail(&cur->list, &worklist); + if (next_rbno > bno) + next_rbno = bno; + nr--; + if (nr == 0) + break; + } + + rbno = next_rbno; + } + + /* + * Make sure the last extent we processed ends at or beyond + * the end of the refcount extent. + */ + if (rbno < rsrci->rc.rc_startblock + rsrci->rc.rc_blockcount) + goto fail; + + rsrci->nr = rsrci->rc.rc_refcount; +fail: + /* Delete fragments and work list. */ + while (!list_empty(&worklist)) { + cur = list_first_entry(&worklist, + struct xfs_refcountbt_scrub_fragment, list); + list_del(&cur->list); + kmem_free(cur); + } + while (!list_empty(&rsrci->fragments)) { + cur = list_first_entry(&rsrci->fragments, + struct xfs_refcountbt_scrub_fragment, list); + list_del(&cur->list); + kmem_free(cur); + } +} + +STATIC int +xfs_refcountbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + struct xfs_rmap_irec low; + struct xfs_rmap_irec high; + struct xfs_refcount_irec irec; + struct xfs_refcountbt_scrub_rmap_check_info rsrci; + struct xfs_refcountbt_scrub_fragment *cur; + int error; + + irec.rc_startblock = be32_to_cpu(rec->refc.rc_startblock); + irec.rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount); + irec.rc_refcount = be32_to_cpu(rec->refc.rc_refcount); + + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_startblock < mp->m_sb.sb_agblocks); + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_startblock < irec.rc_startblock + + irec.rc_blockcount); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)irec.rc_startblock + + irec.rc_blockcount <= mp->m_sb.sb_agblocks); + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_refcount >= 1); + + /* confirm the refcount */ + if (!bs->rmap_cur) + return 0; + + memset(&low, 0, sizeof(low)); + low.rm_startblock = irec.rc_startblock; + memset(&high, 0xFF, sizeof(high)); + high.rm_startblock = irec.rc_startblock + irec.rc_blockcount - 1; + + rsrci.nr = 0; + rsrci.rc = irec; + INIT_LIST_HEAD(&rsrci.fragments); + error = xfs_rmapbt_query_range(bs->rmap_cur, &low, &high, + &xfs_refcountbt_scrub_rmap_check, &rsrci); + if (error && error != XFS_BTREE_QUERY_RANGE_ABORT) + goto err; + error = 0; + xfs_refcountbt_process_rmap_fragments(mp, &rsrci); + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_refcount == rsrci.nr); + +err: + while (!list_empty(&rsrci.fragments)) { + cur = list_first_entry(&rsrci.fragments, + struct xfs_refcountbt_scrub_fragment, list); + list_del(&cur->list); + kmem_free(cur); + } + return error; +} + +/* Scrub the refcount btree for some AG. */ +int +xfs_refcountbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) + return error; + + bs.cur = xfs_refcountbt_init_cursor(mp, NULL, bs.agf_bp, agno, NULL); + bs.scrub_rec = xfs_refcountbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_REFC); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} diff --git a/fs/xfs/libxfs/xfs_refcount.h b/fs/xfs/libxfs/xfs_refcount.h index 44b0346..d2317f1 100644 --- a/fs/xfs/libxfs/xfs_refcount.h +++ b/fs/xfs/libxfs/xfs_refcount.h @@ -68,4 +68,6 @@ extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, xfs_extlen_t len); +extern int xfs_refcountbt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); + #endif /* __XFS_REFCOUNT_H__ */ diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c index abf1ebf..c5d2942 100644 --- a/fs/xfs/libxfs/xfs_refcount_btree.c +++ b/fs/xfs/libxfs/xfs_refcount_btree.c @@ -197,6 +197,16 @@ xfs_refcountbt_key_diff( return (__int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock; } +STATIC __int64_t +xfs_refcountbt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->refc.rc_startblock) - + be32_to_cpu(k1->refc.rc_startblock); +} + STATIC bool xfs_refcountbt_verify( struct xfs_buf *bp) @@ -259,7 +269,6 @@ const struct xfs_buf_ops xfs_refcountbt_buf_ops = { .verify_write = xfs_refcountbt_write_verify, }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_refcountbt_keys_inorder( struct xfs_btree_cur *cur, @@ -288,13 +297,13 @@ xfs_refcountbt_recs_inorder( b.rc_startblock = be32_to_cpu(r2->refc.rc_startblock); b.rc_blockcount = be32_to_cpu(r2->refc.rc_blockcount); b.rc_refcount = be32_to_cpu(r2->refc.rc_refcount); + a = a; b = b; trace_xfs_refcount_rec_order_error(cur->bc_mp, cur->bc_private.a.agno, &a, &b); } return ret; } -#endif /* DEBUG */ static const struct xfs_btree_ops xfs_refcountbt_ops = { .rec_len = sizeof(struct xfs_refcount_rec), @@ -311,10 +320,9 @@ static const struct xfs_btree_ops xfs_refcountbt_ops = { .init_ptr_from_cur = xfs_refcountbt_init_ptr_from_cur, .key_diff = xfs_refcountbt_key_diff, .buf_ops = &xfs_refcountbt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_refcountbt_diff_two_keys, .keys_inorder = xfs_refcountbt_keys_inorder, .recs_inorder = xfs_refcountbt_recs_inorder, -#endif }; /* diff --git a/fs/xfs/xfs_scrub_sysfs.c b/fs/xfs/xfs_scrub_sysfs.c index c2256f3..ad51e05 100644 --- a/fs/xfs/xfs_scrub_sysfs.c +++ b/fs/xfs/xfs_scrub_sysfs.c @@ -179,6 +179,7 @@ XFS_AGDATA_SCRUB_ATTR(cntbt, NULL); XFS_AGDATA_SCRUB_ATTR(inobt, NULL); XFS_AGDATA_SCRUB_ATTR(finobt, xfs_sb_version_hasfinobt); XFS_AGDATA_SCRUB_ATTR(rmapbt, xfs_sb_version_hasrmapbt); +XFS_AGDATA_SCRUB_ATTR(refcountbt, xfs_sb_version_hasreflink); static struct attribute *xfs_agdata_scrub_attrs[] = { XFS_AGDATA_SCRUB_LIST(bnobt), @@ -186,6 +187,7 @@ static struct attribute *xfs_agdata_scrub_attrs[] = { XFS_AGDATA_SCRUB_LIST(inobt), XFS_AGDATA_SCRUB_LIST(finobt), XFS_AGDATA_SCRUB_LIST(rmapbt), + XFS_AGDATA_SCRUB_LIST(refcountbt), NULL, }; From darrick.wong@oracle.com Thu Jun 16 20:30:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6D6A8800B for ; Thu, 16 Jun 2016 20:30:51 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 06904AC001 for ; Thu, 16 Jun 2016 18:30:50 -0700 (PDT) X-ASG-Debug-ID: 1466127049-04bdf01e1395e90001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id YVMQ6FffRFfkqb5I (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:49 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UmSH000630 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:48 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Ul3Q018587 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:48 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Ulml030543; Fri, 17 Jun 2016 01:30:47 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:47 -0700 Subject: [PATCH v6 000/145] xfsprogs: add reverse mapping, reflink, dedupe, and online scrub support From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH v6 000/145] xfsprogs: add reverse mapping, reflink, dedupe, and online scrub support To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:45 -0700 Message-ID: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127049 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2823 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Hi all, This is the sixth revision of a patchset that adds to xfsprogs support for tracking reverse-mappings of physical blocks to file and metadata (rmap); support for mapping multiple file logical blocks to the same physical block (reflink); and implements the beginnings of online metadata scrubbing. Given the significant amount of design assumptions that change with block sharing, rmap and reflink are provided together. There shouldn't be any incompatible on-disk format changes, pending a thorough review of the patches within. The first few libxfs patches resync the xfsprogs libxfs with the kernel libxfs so that the new feature development can branch off (roughly) the same code. All patches in the kernel patchset that touch libxfs are provided here individually, and implement the same code changes. Patches to the actual xfsprogs programs are also provided -- xfs_db, xfs_logprint, and xfs_metadump are taught to examine the new on-disk data structures; xfs_io now knows how to inject errors for tests; mkfs can format the new features; and xfs_repair has been taught to check its own observations against the existing rmapbt and refcountbt and to regenerate the two indices. At the very end of the patchset is an initial implementation of twin "fsmap" commands in xfs_db and xfs_io for offline and online analysis of the filesystem. The last patch implements xfs_scrub which performs (very) limited online checking of the filesystem. It should work on any disk-based filesystem, and if it detects XFS it can trigger the in-kernel metadata b+tree scrubbing. The very first patch is a tool that can analyze xfs_buf deadlocks from ftrace output, and the patches after that merge various kernel libxfs changes into the xfsprogs libxfs so that the rest of the patches apply consistently. If you're going to start using this mess, you probably ought to just pull from my github trees for kernel[1], xfsprogs[2], and xfstests[3]. There are also updates for xfs-docs[4]. The kernel patches should apply to dchinner's for-next; xfsprogs patches to for-next; and xfstest to master. The kernel git tree already has for-next included. The patches have been xfstested with x64, i386, and armv7l--arm64, ppc64, and ppc64le no longer boot in qemu. All three architectures pass all 'clone' group tests except xfs/128 (which is the swapext test), and AFAICT don't cause any new failures for the 'auto' group. This is an extraordinary way to eat your data. Enjoy! Comments and questions are, as always, welcome. --D [1] https://github.com/djwong/linux/tree/djwong-devel [2] https://github.com/djwong/xfsprogs/tree/djwong-devel [3] https://github.com/djwong/xfstests/tree/djwong-devel [4] https://github.com/djwong/xfs-documentation/tree/djwong-devel From darrick.wong@oracle.com Thu Jun 16 20:30:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8FBCC800B for ; Thu, 16 Jun 2016 20:30:52 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4F6148F804C for ; Thu, 16 Jun 2016 18:30:52 -0700 (PDT) X-ASG-Debug-ID: 1466127049-04bdf01e1795ea0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id efYMYlt6G9hC5zAc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:30:49 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UiXo013628 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:44 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Ui7C018506 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:44 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UhPM021846; Fri, 17 Jun 2016 01:30:43 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:43 -0700 Subject: [PATCH 119/119] xfs: add btree scrub tracepoints From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 119/119] xfs: add btree scrub tracepoints To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:41 -0700 Message-ID: <146612704152.12839.9204196958776547302.stgit@birch.djwong.org> In-Reply-To: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127049 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3228 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_scrub.c | 14 ++++++++++++++ fs/xfs/xfs_trace.h | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/fs/xfs/libxfs/xfs_scrub.c b/fs/xfs/libxfs/xfs_scrub.c index d43d5c5..d43e742 100644 --- a/fs/xfs/libxfs/xfs_scrub.c +++ b/fs/xfs/libxfs/xfs_scrub.c @@ -34,6 +34,7 @@ #include "xfs_rmap_btree.h" #include "xfs_log_format.h" #include "xfs_trans.h" +#include "xfs_trace.h" #include "xfs_scrub.h" static const char * const btree_types[] = { @@ -88,6 +89,12 @@ xfs_btree_scrub_rec( struct xfs_btree_block *block; struct xfs_btree_block *keyblock; + trace_xfs_btree_scrub_rec(cur->bc_mp, cur->bc_private.a.agno, + XFS_FSB_TO_AGBNO(cur->bc_mp, + XFS_DADDR_TO_FSB(cur->bc_mp, + cur->bc_bufs[0]->b_bn)), + cur->bc_btnum, 0, cur->bc_nlevels, cur->bc_ptrs[0]); + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[0]); rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); @@ -135,6 +142,13 @@ xfs_btree_scrub_key( struct xfs_btree_block *block; struct xfs_btree_block *keyblock; + trace_xfs_btree_scrub_key(cur->bc_mp, cur->bc_private.a.agno, + XFS_FSB_TO_AGBNO(cur->bc_mp, + XFS_DADDR_TO_FSB(cur->bc_mp, + cur->bc_bufs[level]->b_bn)), + cur->bc_btnum, level, cur->bc_nlevels, + cur->bc_ptrs[level]); + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 9fe812f..e295374 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -3428,6 +3428,46 @@ DEFINE_GETFSMAP_EVENT(xfs_getfsmap_low_key); DEFINE_GETFSMAP_EVENT(xfs_getfsmap_high_key); DEFINE_GETFSMAP_EVENT(xfs_getfsmap_mapping); +/* scrub */ +DECLARE_EVENT_CLASS(xfs_scrub_sbtree_class, + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t bno, + xfs_btnum_t btnum, int level, int nlevels, int ptr), + TP_ARGS(mp, agno, bno, btnum, level, nlevels, ptr), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_btnum_t, btnum) + __field(xfs_agnumber_t, agno) + __field(xfs_agblock_t, bno) + __field(int, level) + __field(int, nlevels) + __field(int, ptr) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->agno = agno; + __entry->btnum = btnum; + __entry->bno = bno; + __entry->level = level; + __entry->nlevels = nlevels; + __entry->ptr = ptr; + ), + TP_printk("dev %d:%d agno %u agbno %u btnum %d level %d nlevels %d ptr %d\n", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->agno, + __entry->bno, + __entry->btnum, + __entry->level, + __entry->nlevels, + __entry->ptr) +) +#define DEFINE_SCRUB_SBTREE_EVENT(name) \ +DEFINE_EVENT(xfs_scrub_sbtree_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t bno, \ + xfs_btnum_t btnum, int level, int nlevels, int ptr), \ + TP_ARGS(mp, agno, bno, btnum, level, nlevels, ptr)) +DEFINE_SCRUB_SBTREE_EVENT(xfs_btree_scrub_rec); +DEFINE_SCRUB_SBTREE_EVENT(xfs_btree_scrub_key); + #endif /* _TRACE_XFS_H */ #undef TRACE_INCLUDE_PATH From darrick.wong@oracle.com Thu Jun 16 20:31:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 158FD801B for ; Thu, 16 Jun 2016 20:31:03 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id CC4268F8052 for ; Thu, 16 Jun 2016 18:31:02 -0700 (PDT) X-ASG-Debug-ID: 1466127059-04cb6c542457c40001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id MiHEuOWaRPbxbjLT (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:00 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1UsmY013665 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:55 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UspJ018655 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:30:54 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Ur0Z030551; Fri, 17 Jun 2016 01:30:53 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:53 -0700 Subject: [PATCH 001/145] xfs_buflock: add a tool that can be used to find buffer deadlocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 001/145] xfs_buflock: add a tool that can be used to find buffer deadlocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:51 -0700 Message-ID: <146612705189.16048.16879115408286697572.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127059 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6417 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add a (rough) python script that can parse the output of: # trace-cmd -e xfs_buf_*lock*' to identify xfs_buf deadlocks between XFS threads. Signed-off-by: Darrick J. Wong --- tools/xfsbuflock.py | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100755 tools/xfsbuflock.py diff --git a/tools/xfsbuflock.py b/tools/xfsbuflock.py new file mode 100755 index 0000000..f307461 --- /dev/null +++ b/tools/xfsbuflock.py @@ -0,0 +1,205 @@ +#!/usr/bin/env python3 + +# Read ftrace input, looking for XFS buffer deadlocks. +# +# Copyright (C) 2016 Oracle. All Rights Reserved. +# +# Author: Darrick J. Wong +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. +# +# Rough guide to using this script: +# Collect ftrace data from a deadlock: +# +# # trace-cmd record -e 'xfs_buf_*lock*' & +# ^Z +# # killall -INT trace-cmd +# +# +# Now analyze the captured trace data: +# +# # trace-cmd report | xfsbuflock.py +# === fsx-14956 === +# +# 3732.005575: xfs_buf_trylock_fail: dev 8:16 bno 0x1 nblks 0x1 hold 4 \ +# pincount 1 lock 0 flags DONE|KMEM caller 0xc009af36s +# Locked buffers: +# dev 8:16 bno 0x64c371 nblks 0x1 lock 1 owner fsx-14956@3732.005567 +# waiting: fsx-14954 +# dev 8:16 bno 0x64c380 nblks 0x8 lock 1 owner fsx-14956@3732.005571 +# dev 8:16 bno 0x64c378 nblks 0x8 lock 1 owner fsx-14956@3732.005570 +# === fsx-14954 === +# +# 3732.005592: xfs_buf_trylock_fail: dev 8:16 bno 0x64c371 nblks 0x1 hold 4 \ +# pincount 1 lock 0 flags ASYNC|DONE|KMEM caller 0xc009af36s +# Locked buffers: +# dev 8:16 bno 0x8 nblks 0x8 lock 1 owner fsx-14954@3732.005583 +# dev 8:16 bno 0x1 nblks 0x1 lock 1 owner fsx-14954@3732.005574 +# waiting: fsx-14956 +# waiting: fsx-14957 +# waiting: fsx-14958 +# dev 8:16 bno 0x10 nblks 0x8 lock 1 owner fsx-14954@3732.005585 +# +# As you can see, fsx-14596 is locking AGFs in violation of the locking +# order rules. + +import sys +import fileinput +from collections import namedtuple + +NR_BACKTRACE = 50 + +class Process: + def __init__(self, pid): + self.pid = pid; + self.bufs = set() + self.locked_bufs = set() + self.backtrace = [] + + def dump(self): + print('=== %s ===' % self.pid) + for bt in self.backtrace: + print('%f: %s' % (bt.time, bt.descr)) + print('Locked buffers:') + for buf in self.locked_bufs: + buf.dump() + +class Buffer: + def __init__(self, dev, bno, blen): + self.dev = dev + self.bno = int(bno, 0) + self.blen = int(blen, 0) + self.locked = False + self.locktime = None + self.owner = None + self.waiters = set() + + def trylock(self, process, time): + self.lockdone(process, time) + + def lockdone(self, process, time): + if self.locked: + print('Buffer already locked on line %d?!' % nr) + # process.dump() + # self.dump() + # assert False + if process in self.waiters: + self.waiters.remove(process) + self.locked = True + self.owner = process + self.locktime = time + process.locked_bufs.add(self) + process.bufs.add(self) + locked_buffers.add(self) + + def waitlock(self, process): + self.waiters.add(process) + + def unlock(self): + self.locked = False + if self in locked_buffers: + locked_buffers.remove(self) + if self.owner is not None and \ + self in self.owner.locked_bufs: + self.owner.locked_bufs.remove(self) + + def dump(self): + if self.owner is not None: + pid = '%s@%f' % (self.owner.pid, self.locktime) + else: + pid = '' + print('dev %s bno 0x%x nblks 0x%x lock %d owner %s' % \ + (self.dev, self.bno, self.blen, self.locked, \ + pid)) + for proc in self.waiters: + print(' waiting: %s' % proc.pid) + +Event = namedtuple('Event', 'time descr') + +# Read ftrace input, looking for events and for buffer lock info +processes = {} +buffers = {} +locked_buffers = set() + +def getbuf(toks): + if int(toks[7], 0) == 18446744073709551615: + return None + bufkey = ' '.join(toks[4:10]) + if bufkey in buffers: + return buffers[bufkey] + buf = Buffer(toks[5], toks[7], toks[9]) + buffers[bufkey] = buf + return buf + +nr = 0 +for line in fileinput.input(): + nr += 1 + toks = line.split() + if len(toks) < 4: + continue + pid = toks[0] + time = float(toks[2][:-1]) + fn = toks[3][:-1] + + if pid in processes: + proc = processes[pid] + else: + proc = Process(pid) + processes[pid] = proc + + if fn == 'xfs_buf_unlock' or fn == 'xfs_buf_item_unlock_stale': + buf = getbuf(toks) + if buf is not None: + buf.unlock() + elif fn == 'xfs_buf_lock_done': + buf = getbuf(toks) + if buf is not None: + buf.lockdone(proc, time) + elif fn == 'xfs_buf_lock': + buf = getbuf(toks) + if buf is not None: + buf.waitlock(proc) + elif fn == 'xfs_buf_trylock': + buf = getbuf(toks) + if buf is not None: + buf.trylock(proc, time) + elif fn == 'xfs_buf_item_unlock': + pass + else: + e = Event(time, ' '.join(toks[3:])) + proc.backtrace.append(e) + if len(proc.backtrace) > NR_BACKTRACE: + proc.backtrace.pop(0) + +deadlocked = set() +for buf in locked_buffers: + deadlocked.add(buf.owner) + +for proc in deadlocked: + proc.dump() + +sys.exit(0) + +for key in buffers: + buf = buffers[key] + if buf.locked: + print('dev %s bno 0x%x len 0x%x owner %s' % (buf.dev, buf.bno, buf.blen, buf.owner.pid)) + else: + print('dev %s bno 0x%x len 0x%x' % (buf.dev, buf.bno, buf.blen)) + +sys.exit(0) + +for pid in processes: + proc = processes[pid] From darrick.wong@oracle.com Thu Jun 16 20:31:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 335D38024 for ; Thu, 16 Jun 2016 20:31:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id C3F7730404E for ; Thu, 16 Jun 2016 18:31:07 -0700 (PDT) X-ASG-Debug-ID: 1466127064-04cb6c542757c70001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id kASfPg0aHDpr8km3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1V2Oo001055 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:31:03 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1V2Wu024021 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:02 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1UxwI009626; Fri, 17 Jun 2016 01:31:00 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:30:59 -0700 Subject: [PATCH 002/145] libxfs: port changes from kernel libxfs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 002/145] libxfs: port changes from kernel libxfs To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:30:58 -0700 Message-ID: <146612705805.16048.1345024248406024616.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127064 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10461 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, INFO_TLD, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.00 INFO_TLD URI: Contains an URL in the INFO top-level domain Port various changes between the kernel and xfsprogs. This cleans up both so that we can develop rmap and reflink on the same libxfs code. Signed-off-by: Darrick J. Wong --- libxfs/xfs_alloc.c | 5 +++-- libxfs/xfs_btree.c | 4 ++-- libxfs/xfs_da_btree.c | 51 ++++++++++++++++++++++++------------------------ libxfs/xfs_dir2_node.c | 2 ++ libxfs/xfs_dquot_buf.c | 10 +++++---- libxfs/xfs_format.h | 3 +-- libxfs/xfs_ialloc.c | 5 ++--- libxfs/xfs_inode_buf.c | 3 +-- libxfs/xfs_inode_buf.h | 2 -- libxfs/xfs_sb.c | 19 ++++++++++++++++++ 10 files changed, 61 insertions(+), 43 deletions(-) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index af40270..28b3fb9 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2411,8 +2411,9 @@ xfs_alloc_read_agf( be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); spin_lock_init(&pag->pagb_lock); pag->pagb_count = 0; - /* XXX: pagb_tree doesn't exist in userspace */ - //pag->pagb_tree = RB_ROOT; +#ifdef __KERNEL__ + pag->pagb_tree = RB_ROOT; +#endif pag->pagf_init = 1; } #ifdef DEBUG diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index a736cb5..1448fd6 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -243,7 +243,7 @@ xfs_btree_lblock_verify_crc( struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_mount *mp = bp->b_target->bt_mount; - if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) { + if (xfs_sb_version_hascrc(&mp->m_sb)) { if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.l.bb_lsn))) return false; return xfs_buf_verify_cksum(bp, XFS_BTREE_LBLOCK_CRC_OFF); @@ -281,7 +281,7 @@ xfs_btree_sblock_verify_crc( struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); struct xfs_mount *mp = bp->b_target->bt_mount; - if (xfs_sb_version_hascrc(&bp->b_target->bt_mount->m_sb)) { + if (xfs_sb_version_hascrc(&mp->m_sb)) { if (!xfs_log_check_lsn(mp, be64_to_cpu(block->bb_u.s.bb_lsn))) return false; return xfs_buf_verify_cksum(bp, XFS_BTREE_SBLOCK_CRC_OFF); diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c index f3c04ab..298252e 100644 --- a/libxfs/xfs_da_btree.c +++ b/libxfs/xfs_da_btree.c @@ -351,6 +351,7 @@ xfs_da3_split( struct xfs_da_state_blk *newblk; struct xfs_da_state_blk *addblk; struct xfs_da_intnode *node; + struct xfs_buf *bp; int max; int action = 0; int error; @@ -391,9 +392,7 @@ xfs_da3_split( break; } /* - * Entry wouldn't fit, split the leaf again. The new - * extrablk will be consumed by xfs_da3_node_split if - * the node is split. + * Entry wouldn't fit, split the leaf again. */ state->extravalid = 1; if (state->inleaf) { @@ -442,14 +441,6 @@ xfs_da3_split( return 0; /* - * xfs_da3_node_split() should have consumed any extra blocks we added - * during a double leaf split in the attr fork. This is guaranteed as - * we can't be here if the attr fork only has a single leaf block. - */ - ASSERT(state->extravalid == 0 || - state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC); - - /* * Split the root node. */ ASSERT(state->path.active == 0); @@ -461,31 +452,41 @@ xfs_da3_split( } /* - * Update pointers to the node which used to be block 0 and just got - * bumped because of the addition of a new root node. Note that the - * original block 0 could be at any position in the list of blocks in - * the tree. + * Update pointers to the node which used to be block 0 and + * just got bumped because of the addition of a new root node. + * There might be three blocks involved if a double split occurred, + * and the original block 0 could be at any position in the list. * - * Note: the magic numbers and sibling pointers are in the same physical - * place for both v2 and v3 headers (by design). Hence it doesn't matter - * which version of the xfs_da_intnode structure we use here as the - * result will be the same using either structure. + * Note: the magic numbers and sibling pointers are in the same + * physical place for both v2 and v3 headers (by design). Hence it + * doesn't matter which version of the xfs_da_intnode structure we use + * here as the result will be the same using either structure. */ node = oldblk->bp->b_addr; if (node->hdr.info.forw) { - ASSERT(be32_to_cpu(node->hdr.info.forw) == addblk->blkno); - node = addblk->bp->b_addr; + if (be32_to_cpu(node->hdr.info.forw) == addblk->blkno) { + bp = addblk->bp; + } else { + ASSERT(state->extravalid); + bp = state->extrablk.bp; + } + node = bp->b_addr; node->hdr.info.back = cpu_to_be32(oldblk->blkno); - xfs_trans_log_buf(state->args->trans, addblk->bp, + xfs_trans_log_buf(state->args->trans, bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); } node = oldblk->bp->b_addr; if (node->hdr.info.back) { - ASSERT(be32_to_cpu(node->hdr.info.back) == addblk->blkno); - node = addblk->bp->b_addr; + if (be32_to_cpu(node->hdr.info.back) == addblk->blkno) { + bp = addblk->bp; + } else { + ASSERT(state->extravalid); + bp = state->extrablk.bp; + } + node = bp->b_addr; node->hdr.info.forw = cpu_to_be32(oldblk->blkno); - xfs_trans_log_buf(state->args->trans, addblk->bp, + xfs_trans_log_buf(state->args->trans, bp, XFS_DA_LOGRANGE(node, &node->hdr.info, sizeof(node->hdr.info))); } diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c index 224daa6..04fecf1 100644 --- a/libxfs/xfs_dir2_node.c +++ b/libxfs/xfs_dir2_node.c @@ -2146,12 +2146,14 @@ xfs_dir2_node_replace( state = xfs_da_state_alloc(); state->args = args; state->mp = args->dp->i_mount; + /* * We have to save new inode number and ftype since * xfs_da3_node_lookup_int() is going to overwrite them */ inum = args->inumber; ftype = args->filetype; + /* * Lookup the entry to change in the btree. */ diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c index 433abe4..7b7ea83 100644 --- a/libxfs/xfs_dquot_buf.c +++ b/libxfs/xfs_dquot_buf.c @@ -37,11 +37,8 @@ int xfs_calc_dquots_per_chunk( unsigned int nbblks) /* basic block units */ { - - ASSERT(nbblks > 0); - return BBTOB(nbblks) / sizeof(xfs_dqblk_t); - -#if 0 /* kernel code that goes wrong in userspace! */ +#ifdef __KERNEL__ + /* kernel code that goes wrong in userspace! */ unsigned int ndquots; ASSERT(nbblks > 0); @@ -49,6 +46,9 @@ xfs_calc_dquots_per_chunk( do_div(ndquots, sizeof(xfs_dqblk_t)); return ndquots; +#else + ASSERT(nbblks > 0); + return BBTOB(nbblks) / sizeof(xfs_dqblk_t); #endif } diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index f89b6e0..825fa0c 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -469,7 +469,6 @@ xfs_sb_has_ro_compat_feature( #define XFS_SB_FEAT_INCOMPAT_FTYPE (1 << 0) /* filetype in dirent */ #define XFS_SB_FEAT_INCOMPAT_SPINODES (1 << 1) /* sparse inode chunks */ #define XFS_SB_FEAT_INCOMPAT_META_UUID (1 << 2) /* metadata UUID */ - #define XFS_SB_FEAT_INCOMPAT_ALL \ (XFS_SB_FEAT_INCOMPAT_FTYPE| \ XFS_SB_FEAT_INCOMPAT_SPINODES| \ @@ -533,7 +532,7 @@ static inline bool xfs_sb_version_hassparseinodes(struct xfs_sb *sbp) * user-visible UUID to be changed on V5 filesystems which have a * filesystem UUID stamped into every piece of metadata. */ -static inline int xfs_sb_version_hasmetauuid(xfs_sb_t *sbp) +static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID); diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 64c3acf..72e9ff7 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -1822,8 +1822,7 @@ xfs_difree_inode_chunk( if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ - xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, - XFS_AGINO_TO_AGBNO(mp, rec->ir_startino)), + xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, sagbno), mp->m_ialloc_blks); return; } @@ -2228,7 +2227,7 @@ xfs_imap_lookup( } xfs_trans_brelse(tp, agbp); - xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); if (error) return error; diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index e3d674d..c21a4e6 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -375,7 +375,7 @@ xfs_log_dinode_to_disk( } } -bool +static bool xfs_dinode_verify( struct xfs_mount *mp, xfs_ino_t ino, @@ -514,7 +514,6 @@ xfs_iread( } ASSERT(ip->i_d.di_version >= 2); - ip->i_delayed_blks = 0; /* diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h index 4ece9bf..958c543 100644 --- a/libxfs/xfs_inode_buf.h +++ b/libxfs/xfs_inode_buf.h @@ -72,8 +72,6 @@ void xfs_inode_to_disk(struct xfs_inode *ip, struct xfs_dinode *to, void xfs_inode_from_disk(struct xfs_inode *ip, struct xfs_dinode *from); void xfs_log_dinode_to_disk(struct xfs_log_dinode *from, struct xfs_dinode *to); -bool xfs_dinode_verify(struct xfs_mount *mp, xfs_ino_t ino, - struct xfs_dinode *dip); bool xfs_dinode_good_version(struct xfs_mount *mp, __u8 version); diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index 78ad889..67c7a65 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -256,6 +256,19 @@ xfs_mount_validate_sb( } /* + * Until this is fixed only page-sized or smaller data blocks work. + */ +#ifdef __KERNEL__ + if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { + xfs_warn(mp, + "File system with blocksize %d bytes. " + "Only pagesize (%ld) or less will currently work.", + sbp->sb_blocksize, PAGE_SIZE); + return -ENOSYS; + } +#endif + + /* * Currently only very few inode sizes are supported. */ switch (sbp->sb_inodesize) { @@ -277,6 +290,12 @@ xfs_mount_validate_sb( return -EFBIG; } +#ifdef __KERNEL__ + if (check_inprogress && sbp->sb_inprogress) { + xfs_warn(mp, "Offline file system operation in progress!"); + return -EFSCORRUPTED; + } +#endif return 0; } From darrick.wong@oracle.com Thu Jun 16 20:31:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 4F6D3802E for ; Thu, 16 Jun 2016 20:31:14 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1F60830405F for ; Thu, 16 Jun 2016 18:31:14 -0700 (PDT) X-ASG-Debug-ID: 1466127071-04cbb01fed69cf0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id rs4eZZZGvjlX9N6T (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:12 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1V7kQ014044 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:07 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1V6gD025352 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:07 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1V5bt021989; Fri, 17 Jun 2016 01:31:06 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:05 -0700 Subject: [PATCH 003/145] libxfs: backport changes from 4.5 From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 003/145] libxfs: backport changes from 4.5 To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:04 -0700 Message-ID: <146612706430.16048.5914881403419597862.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127072 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8676 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Backport changes from kernel 4.3 -> 4.5. Signed-off-by: Darrick J. Wong --- include/libxfs.h | 1 + libxfs/libxfs_api_defs.h | 2 +- libxfs/libxfs_priv.h | 8 -------- libxfs/xfs_alloc_btree.c | 4 ---- libxfs/xfs_attr.c | 2 ++ libxfs/xfs_dir2.h | 3 +-- libxfs/xfs_dir2_data.c | 14 +++++++------- libxfs/xfs_dquot_buf.c | 4 ++-- libxfs/xfs_ialloc_btree.c | 2 -- repair/dir2.c | 3 +-- repair/dir2.h | 20 ++++++++++++++++++++ repair/phase6.c | 2 +- 12 files changed, 36 insertions(+), 29 deletions(-) diff --git a/include/libxfs.h b/include/libxfs.h index cf2e20e..a34a3a9 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -163,6 +163,7 @@ extern unsigned int libxfs_log2_roundup(unsigned int i); extern int libxfs_alloc_file_space (struct xfs_inode *, xfs_off_t, xfs_off_t, int, int); +extern int libxfs_bmap_finish(xfs_trans_t **, xfs_bmap_free_t *, struct xfs_inode *); extern void libxfs_fs_repair_cmn_err(int, struct xfs_mount *, char *, ...); extern void libxfs_fs_cmn_err(int, struct xfs_mount *, char *, ...); diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 685c7a7..bb502e0 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -85,7 +85,7 @@ #define xfs_dir_replace libxfs_dir_replace #define xfs_dir2_isblock libxfs_dir2_isblock #define xfs_dir2_isleaf libxfs_dir2_isleaf -#define __xfs_dir2_data_freescan libxfs_dir2_data_freescan +#define xfs_dir2_data_freescan libxfs_dir2_data_freescan #define xfs_dir2_data_log_entry libxfs_dir2_data_log_entry #define xfs_dir2_data_log_header libxfs_dir2_data_log_header #define xfs_dir2_data_make_free libxfs_dir2_data_make_free diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index 2c5aba0..ef9ff3b 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -49,14 +49,6 @@ #ifndef __LIBXFS_INTERNAL_XFS_H__ #define __LIBXFS_INTERNAL_XFS_H__ -/* - * Repair doesn't have a inode when it calls libxfs_dir2_data_freescan, - * so we to work around this internally for now. - */ -#define xfs_dir2_data_freescan(ip, hdr, loghead) \ - __xfs_dir2_data_freescan((ip)->i_mount->m_dir_geo, \ - (ip)->d_ops, hdr, loghead) - #include "libxfs_api_defs.h" #include "platform_defs.h" #include "xfs.h" diff --git a/libxfs/xfs_alloc_btree.c b/libxfs/xfs_alloc_btree.c index 79d0fb9..094135f 100644 --- a/libxfs/xfs_alloc_btree.c +++ b/libxfs/xfs_alloc_btree.c @@ -289,8 +289,6 @@ xfs_allocbt_verify( level = be16_to_cpu(block->bb_level); switch (block->bb_magic) { case cpu_to_be32(XFS_ABTB_CRC_MAGIC): - if (!xfs_sb_version_hascrc(&mp->m_sb)) - return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; /* fall through */ @@ -302,8 +300,6 @@ xfs_allocbt_verify( return false; break; case cpu_to_be32(XFS_ABTC_CRC_MAGIC): - if (!xfs_sb_version_hascrc(&mp->m_sb)) - return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; /* fall through */ diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index afe3dcb..82a7c5e 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -134,6 +134,8 @@ xfs_attr_get( args.value = value; args.valuelen = *valuelenp; + /* Entirely possible to look up a name which doesn't exist */ + args.op_flags = XFS_DA_OP_OKNOENT; lock_mode = xfs_ilock_attr_map_shared(ip); if (!xfs_inode_hasattr(ip)) diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h index 0129e37..0a62e73 100644 --- a/libxfs/xfs_dir2.h +++ b/libxfs/xfs_dir2.h @@ -157,8 +157,7 @@ extern int xfs_dir2_isleaf(struct xfs_da_args *args, int *r); extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db, struct xfs_buf *bp); -extern void __xfs_dir2_data_freescan(struct xfs_da_geometry *geo, - const struct xfs_dir_ops *ops, +extern void xfs_dir2_data_freescan(struct xfs_inode *dp, struct xfs_dir2_data_hdr *hdr, int *loghead); extern void xfs_dir2_data_log_entry(struct xfs_da_args *args, struct xfs_buf *bp, struct xfs_dir2_data_entry *dep); diff --git a/libxfs/xfs_dir2_data.c b/libxfs/xfs_dir2_data.c index 6ae5cd2..c80ab7e 100644 --- a/libxfs/xfs_dir2_data.c +++ b/libxfs/xfs_dir2_data.c @@ -502,9 +502,8 @@ xfs_dir2_data_freeremove( * Given a data block, reconstruct its bestfree map. */ void -__xfs_dir2_data_freescan( - struct xfs_da_geometry *geo, - const struct xfs_dir_ops *ops, +xfs_dir2_data_freescan( + struct xfs_inode *dp, struct xfs_dir2_data_hdr *hdr, int *loghead) { @@ -514,6 +513,7 @@ __xfs_dir2_data_freescan( struct xfs_dir2_data_free *bf; char *endp; /* end of block's data */ char *p; /* current entry pointer */ + struct xfs_da_geometry *geo = dp->i_mount->m_dir_geo; ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) || @@ -523,13 +523,13 @@ __xfs_dir2_data_freescan( /* * Start by clearing the table. */ - bf = ops->data_bestfree_p(hdr); + bf = dp->d_ops->data_bestfree_p(hdr); memset(bf, 0, sizeof(*bf) * XFS_DIR2_DATA_FD_COUNT); *loghead = 1; /* * Set up pointers. */ - p = (char *)ops->data_entry_p(hdr); + p = (char *)dp->d_ops->data_entry_p(hdr); if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) || hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) { btp = xfs_dir2_block_tail_p(geo, hdr); @@ -556,8 +556,8 @@ __xfs_dir2_data_freescan( else { dep = (xfs_dir2_data_entry_t *)p; ASSERT((char *)dep - (char *)hdr == - be16_to_cpu(*ops->data_entry_tag_p(dep))); - p += ops->data_entsize(dep->namelen); + be16_to_cpu(*dp->d_ops->data_entry_tag_p(dep))); + p += dp->d_ops->data_entsize(dep->namelen); } } } diff --git a/libxfs/xfs_dquot_buf.c b/libxfs/xfs_dquot_buf.c index 7b7ea83..bfc6383 100644 --- a/libxfs/xfs_dquot_buf.c +++ b/libxfs/xfs_dquot_buf.c @@ -199,8 +199,8 @@ xfs_dquot_buf_verify_crc( if (mp->m_quotainfo) ndquots = mp->m_quotainfo->qi_dqperchunk; else - ndquots = xfs_calc_dquots_per_chunk(bp->b_length); -// XFS_BB_TO_FSB(mp, bp->b_length)); + ndquots = xfs_calc_dquots_per_chunk( + XFS_BB_TO_FSB(mp, bp->b_length)); for (i = 0; i < ndquots; i++, d++) { if (!xfs_verify_cksum((char *)d, sizeof(struct xfs_dqblk), diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c index a077635..0a7d985 100644 --- a/libxfs/xfs_ialloc_btree.c +++ b/libxfs/xfs_ialloc_btree.c @@ -227,8 +227,6 @@ xfs_inobt_verify( switch (block->bb_magic) { case cpu_to_be32(XFS_IBT_CRC_MAGIC): case cpu_to_be32(XFS_FIBT_CRC_MAGIC): - if (!xfs_sb_version_hascrc(&mp->m_sb)) - return false; if (!xfs_btree_sblock_v5hdr_verify(bp)) return false; /* fall through */ diff --git a/repair/dir2.c b/repair/dir2.c index 61912d1..a2fe5c6 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -921,8 +921,7 @@ _("bad bestfree table in block %u in directory inode %" PRIu64 ": "), da_bno, ino); if (!no_modify) { do_warn(_("repairing table\n")); - libxfs_dir2_data_freescan(mp->m_dir_geo, M_DIROPS(mp), - d, &i); + repair_dir2_data_freescan(mp, M_DIROPS(mp), d, &i); *dirty = 1; } else { do_warn(_("would repair table\n")); diff --git a/repair/dir2.h b/repair/dir2.h index e4d4eeb..a0d873e 100644 --- a/repair/dir2.h +++ b/repair/dir2.h @@ -43,4 +43,24 @@ int dir2_is_badino( xfs_ino_t ino); +/* + * Repair doesn't have a inode when it calls libxfs_dir2_data_freescan, + * so we to work around this internally for now. + */ +static inline void +repair_dir2_data_freescan( + struct xfs_mount *mp, + const struct xfs_dir_ops *d_ops, + struct xfs_dir2_data_hdr *hdr, + int *loghead) +{ + struct xfs_inode ino; + + ino.d_ops = d_ops; + ino.i_mount = mp; + return libxfs_dir2_data_freescan(&ino, hdr, loghead); +} + +extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); + #endif /* _XR_DIR2_H */ diff --git a/repair/phase6.c b/repair/phase6.c index 0a71164..7353c3a 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -1902,7 +1902,7 @@ _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 " } *num_illegal += nbad; if (needscan) - libxfs_dir2_data_freescan(mp->m_dir_geo, M_DIROPS(mp), d, &i); + repair_dir2_data_freescan(mp, M_DIROPS(mp), d, &i); if (needlog) libxfs_dir2_data_log_header(&da, bp); libxfs_bmap_finish(&tp, &flist, ip); From darrick.wong@oracle.com Thu Jun 16 20:31:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E044D7FA7 for ; Thu, 16 Jun 2016 20:31:20 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 77865AC001 for ; Thu, 16 Jun 2016 18:31:20 -0700 (PDT) X-ASG-Debug-ID: 1466127077-04bdf01e1395f00001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id iAaYGxuYe4XwmKNm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1VDjF014125 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:13 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VDT9019146 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:13 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VCrF022003; Fri, 17 Jun 2016 01:31:12 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:11 -0700 Subject: [PATCH 004/145] libxfs: backport kernel 4.6 changes From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 004/145] libxfs: backport kernel 4.6 changes To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:10 -0700 Message-ID: <146612707046.16048.7170232600634665075.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127078 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11860 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Backport the changes from kernel 4.5 -> 4.6. Signed-off-by: Darrick J. Wong --- include/xfs_trans.h | 1 libxfs/libxfs_priv.h | 2 - libxfs/trans.c | 1 libxfs/xfs_bmap.c | 170 +++++++++++++++++++++++++++++++++-------------- libxfs/xfs_bmap_btree.c | 4 + libxfs/xfs_dir2_node.c | 4 + libxfs/xfs_ialloc.c | 4 + 7 files changed, 129 insertions(+), 57 deletions(-) diff --git a/include/xfs_trans.h b/include/xfs_trans.h index 5467c7f..d7ee1fd 100644 --- a/include/xfs_trans.h +++ b/include/xfs_trans.h @@ -81,6 +81,7 @@ typedef struct xfs_trans { long t_fdblocks_delta; /* superblock fdblocks chg */ long t_frextents_delta; /* superblock freextents chg */ struct list_head t_items; /* first log item desc chunk */ + unsigned int t_blk_res; } xfs_trans_t; void xfs_trans_init(struct xfs_mount *); diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index ef9ff3b..ecd75e7 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -187,7 +187,7 @@ enum ce { CE_DEBUG, CE_CONT, CE_NOTE, CE_WARN, CE_ALERT, CE_PANIC }; */ #define prandom_u32() 0 -#define PAGE_CACHE_SIZE getpagesize() +#define PAGE_SIZE getpagesize() static inline int __do_div(unsigned long long *n, unsigned base) { diff --git a/libxfs/trans.c b/libxfs/trans.c index 0388950..18ea010 100644 --- a/libxfs/trans.c +++ b/libxfs/trans.c @@ -193,6 +193,7 @@ libxfs_trans_reserve( if (blocks > 0) { if (mpsb->sb_fdblocks < blocks) return -ENOSPC; + tp->t_blk_res += blocks; } /* user space, don't need log/RT stuff (preserve the API though) */ return 0; diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 40286e4..cbcfd72 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -469,10 +469,7 @@ xfs_bmap_check_leaf_extents( } block = XFS_BUF_TO_BLOCK(bp); } - if (bp_release) { - bp_release = 0; - xfs_trans_brelse(NULL, bp); - } + return; error0: @@ -3737,11 +3734,11 @@ xfs_bmap_btalloc( args.prod = align; if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod))) args.mod = (xfs_extlen_t)(args.prod - args.mod); - } else if (mp->m_sb.sb_blocksize >= PAGE_CACHE_SIZE) { + } else if (mp->m_sb.sb_blocksize >= PAGE_SIZE) { args.prod = 1; args.mod = 0; } else { - args.prod = PAGE_CACHE_SIZE >> mp->m_sb.sb_blocklog; + args.prod = PAGE_SIZE >> mp->m_sb.sb_blocklog; if ((args.mod = (xfs_extlen_t)(do_mod(ap->offset, args.prod)))) args.mod = (xfs_extlen_t)(args.prod - args.mod); } @@ -4713,6 +4710,66 @@ error0: } /* + * When a delalloc extent is split (e.g., due to a hole punch), the original + * indlen reservation must be shared across the two new extents that are left + * behind. + * + * Given the original reservation and the worst case indlen for the two new + * extents (as calculated by xfs_bmap_worst_indlen()), split the original + * reservation fairly across the two new extents. If necessary, steal available + * blocks from a deleted extent to make up a reservation deficiency (e.g., if + * ores == 1). The number of stolen blocks is returned. The availability and + * subsequent accounting of stolen blocks is the responsibility of the caller. + */ +static xfs_filblks_t +xfs_bmap_split_indlen( + xfs_filblks_t ores, /* original res. */ + xfs_filblks_t *indlen1, /* ext1 worst indlen */ + xfs_filblks_t *indlen2, /* ext2 worst indlen */ + xfs_filblks_t avail) /* stealable blocks */ +{ + xfs_filblks_t len1 = *indlen1; + xfs_filblks_t len2 = *indlen2; + xfs_filblks_t nres = len1 + len2; /* new total res. */ + xfs_filblks_t stolen = 0; + + /* + * Steal as many blocks as we can to try and satisfy the worst case + * indlen for both new extents. + */ + while (nres > ores && avail) { + nres--; + avail--; + stolen++; + } + + /* + * The only blocks available are those reserved for the original + * extent and what we can steal from the extent being removed. + * If this still isn't enough to satisfy the combined + * requirements for the two new extents, skim blocks off of each + * of the new reservations until they match what is available. + */ + while (nres > ores) { + if (len1) { + len1--; + nres--; + } + if (nres == ores) + break; + if (len2) { + len2--; + nres--; + } + } + + *indlen1 = len1; + *indlen2 = len2; + + return stolen; +} + +/* * Called by xfs_bmapi to update file extent records and the btree * after removing space (or undoing a delayed allocation). */ @@ -4976,28 +5033,29 @@ xfs_bmap_del_extent( XFS_IFORK_NEXT_SET(ip, whichfork, XFS_IFORK_NEXTENTS(ip, whichfork) + 1); } else { + xfs_filblks_t stolen; ASSERT(whichfork == XFS_DATA_FORK); - temp = xfs_bmap_worst_indlen(ip, temp); + + /* + * Distribute the original indlen reservation across the + * two new extents. Steal blocks from the deleted extent + * if necessary. Stealing blocks simply fudges the + * fdblocks accounting in xfs_bunmapi(). + */ + temp = xfs_bmap_worst_indlen(ip, got.br_blockcount); + temp2 = xfs_bmap_worst_indlen(ip, new.br_blockcount); + stolen = xfs_bmap_split_indlen(da_old, &temp, &temp2, + del->br_blockcount); + da_new = temp + temp2 - stolen; + del->br_blockcount -= stolen; + + /* + * Set the reservation for each extent. Warn if either + * is zero as this can lead to delalloc problems. + */ + WARN_ON_ONCE(!temp || !temp2); xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); - temp2 = xfs_bmap_worst_indlen(ip, temp2); new.br_startblock = nullstartblock((int)temp2); - da_new = temp + temp2; - while (da_new > da_old) { - if (temp) { - temp--; - da_new--; - xfs_bmbt_set_startblock(ep, - nullstartblock((int)temp)); - } - if (da_new == da_old) - break; - if (temp2) { - temp2--; - da_new--; - new.br_startblock = - nullstartblock((int)temp2); - } - } } trace_xfs_bmap_post_update(ip, *idx, state, _THIS_IP_); xfs_iext_insert(ip, *idx + 1, 1, &new, state); @@ -5202,7 +5260,7 @@ xfs_bunmapi( * This is better than zeroing it. */ ASSERT(del.br_state == XFS_EXT_NORM); - ASSERT(xfs_trans_get_block_res(tp) > 0); + ASSERT(tp->t_blk_res > 0); /* * If this spans a realtime extent boundary, * chop it back to the start of the one we end at. @@ -5233,7 +5291,7 @@ xfs_bunmapi( del.br_startblock += mod; } else if ((del.br_startoff == start && (del.br_state == XFS_EXT_UNWRITTEN || - xfs_trans_get_block_res(tp) == 0)) || + tp->t_blk_res == 0)) || !xfs_sb_version_hasextflgbit(&mp->m_sb)) { /* * Can't make it unwritten. There isn't @@ -5288,9 +5346,37 @@ xfs_bunmapi( goto nodelete; } } + + /* + * If it's the case where the directory code is running + * with no block reservation, and the deleted block is in + * the middle of its extent, and the resulting insert + * of an extent would cause transformation to btree format, + * then reject it. The calling code will then swap + * blocks around instead. + * We have to do this now, rather than waiting for the + * conversion to btree format, since the transaction + * will be dirty. + */ + if (!wasdel && tp->t_blk_res == 0 && + XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && + XFS_IFORK_NEXTENTS(ip, whichfork) >= /* Note the >= */ + XFS_IFORK_MAXEXT(ip, whichfork) && + del.br_startoff > got.br_startoff && + del.br_startoff + del.br_blockcount < + got.br_startoff + got.br_blockcount) { + error = -ENOSPC; + goto error0; + } + + /* + * Unreserve quota and update realtime free space, if + * appropriate. If delayed allocation, update the inode delalloc + * counter now and wait to update the sb counters as + * xfs_bmap_del_extent() might need to borrow some blocks. + */ if (wasdel) { ASSERT(startblockval(del.br_startblock) > 0); - /* Update realtime/data freespace, unreserve quota */ if (isrt) { xfs_filblks_t rtexts; @@ -5301,8 +5387,6 @@ xfs_bunmapi( ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_RTBLKS); } else { - xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount, - false); (void)xfs_trans_reserve_quota_nblks(NULL, ip, -((long)del.br_blockcount), 0, XFS_QMOPT_RES_REGBLKS); @@ -5313,32 +5397,16 @@ xfs_bunmapi( XFS_BTCUR_BPRV_WASDEL; } else if (cur) cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL; - /* - * If it's the case where the directory code is running - * with no block reservation, and the deleted block is in - * the middle of its extent, and the resulting insert - * of an extent would cause transformation to btree format, - * then reject it. The calling code will then swap - * blocks around instead. - * We have to do this now, rather than waiting for the - * conversion to btree format, since the transaction - * will be dirty. - */ - if (!wasdel && xfs_trans_get_block_res(tp) == 0 && - XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && - XFS_IFORK_NEXTENTS(ip, whichfork) >= /* Note the >= */ - XFS_IFORK_MAXEXT(ip, whichfork) && - del.br_startoff > got.br_startoff && - del.br_startoff + del.br_blockcount < - got.br_startoff + got.br_blockcount) { - error = -ENOSPC; - goto error0; - } + error = xfs_bmap_del_extent(ip, tp, &lastx, flist, cur, &del, &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) goto error0; + + if (!isrt && wasdel) + xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount, false); + bno = del.br_startoff - 1; nodelete: /* diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index a63379b..022d4b6 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -458,7 +458,7 @@ xfs_bmbt_alloc_block( * reservation amount is insufficient then we may fail a * block allocation here and corrupt the filesystem. */ - args.minleft = xfs_trans_get_block_res(args.tp); + args.minleft = args.tp->t_blk_res; } else if (cur->bc_private.b.flist->xbf_low) { args.type = XFS_ALLOCTYPE_START_BNO; } else { @@ -467,7 +467,7 @@ xfs_bmbt_alloc_block( args.minlen = args.maxlen = args.prod = 1; args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; - if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { + if (!args.wasdel && args.tp->t_blk_res == 0) { error = -ENOSPC; goto error0; } diff --git a/libxfs/xfs_dir2_node.c b/libxfs/xfs_dir2_node.c index 04fecf1..b75b432 100644 --- a/libxfs/xfs_dir2_node.c +++ b/libxfs/xfs_dir2_node.c @@ -2232,6 +2232,9 @@ xfs_dir2_node_trim_free( dp = args->dp; tp = args->trans; + + *rvalp = 0; + /* * Read the freespace block. */ @@ -2252,7 +2255,6 @@ xfs_dir2_node_trim_free( */ if (freehdr.nused > 0) { xfs_trans_brelse(tp, bp); - *rvalp = 0; return 0; } /* diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 72e9ff7..4f0e4ee 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -2396,8 +2396,8 @@ xfs_ialloc_compute_maxlevels( maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG; - minleafrecs = mp->m_alloc_mnr[0]; - minnoderecs = mp->m_alloc_mnr[1]; + minleafrecs = mp->m_inobt_mnr[0]; + minnoderecs = mp->m_inobt_mnr[1]; maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; for (level = 1; maxblocks > 1; level++) maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; From darrick.wong@oracle.com Thu Jun 16 20:31:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2E908803E for ; Thu, 16 Jun 2016 20:31:26 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id E3DCB304062 for ; Thu, 16 Jun 2016 18:31:25 -0700 (PDT) X-ASG-Debug-ID: 1466127080-04cbb01fec69d00001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 3SoQa2kLRzGVS5e0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1VJql001202 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:19 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VJoi019283 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:19 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VIRg022012; Fri, 17 Jun 2016 01:31:18 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:18 -0700 Subject: [PATCH 005/145] libxfs: backport kernel 4.7 changes From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 005/145] libxfs: backport kernel 4.7 changes To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:16 -0700 Message-ID: <146612707668.16048.8919087793316736149.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127080 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 37872 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Backport the changes from kernel 4.6 -> 4.7. Signed-off-by: Darrick J. Wong --- include/kmem.h | 2 - include/xfs_trans.h | 7 +-- libxfs/kmem.c | 2 - libxfs/libxfs_api_defs.h | 1 libxfs/trans.c | 63 ++++++++++++++++------------ libxfs/util.c | 5 +- libxfs/xfs_attr.c | 58 ++++++-------------------- libxfs/xfs_bmap.c | 22 ++++------ libxfs/xfs_dir2_sf.c | 9 +--- libxfs/xfs_inode_fork.c | 99 +++++++++++++++++++++++++++++--------------- libxfs/xfs_inode_fork.h | 1 libxfs/xfs_log_format.h | 5 ++ libxfs/xfs_sb.c | 8 +--- libxfs/xfs_shared.h | 102 +-------------------------------------------- libxlog/xfs_log_recover.c | 2 - mkfs/proto.c | 66 +++++++++++++++-------------- mkfs/xfs_mkfs.c | 5 +- repair/phase5.c | 13 ++++-- repair/phase6.c | 82 ++++++++++++++---------------------- repair/phase7.c | 4 -- 20 files changed, 224 insertions(+), 332 deletions(-) diff --git a/include/kmem.h b/include/kmem.h index 5484d32..65f0ade 100644 --- a/include/kmem.h +++ b/include/kmem.h @@ -49,6 +49,6 @@ kmem_free(void *ptr) { free(ptr); } -extern void *kmem_realloc(void *, size_t, size_t, int); +extern void *kmem_realloc(void *, size_t, int); #endif diff --git a/include/xfs_trans.h b/include/xfs_trans.h index d7ee1fd..a5e019d 100644 --- a/include/xfs_trans.h +++ b/include/xfs_trans.h @@ -71,7 +71,6 @@ typedef struct xfs_qoff_logitem { } xfs_qoff_logitem_t; typedef struct xfs_trans { - unsigned int t_type; /* transaction type */ unsigned int t_log_res; /* amt of log space resvd */ unsigned int t_log_count; /* count for perm log res */ struct xfs_mount *t_mountp; /* ptr to fs mount struct */ @@ -87,9 +86,9 @@ typedef struct xfs_trans { void xfs_trans_init(struct xfs_mount *); int xfs_trans_roll(struct xfs_trans **, struct xfs_inode *); -xfs_trans_t *libxfs_trans_alloc(struct xfs_mount *, int); -int libxfs_trans_reserve(struct xfs_trans *, struct xfs_trans_res *, - uint, uint); +int libxfs_trans_alloc(struct xfs_mount *mp, struct xfs_trans_res *resp, + uint blocks, uint rtextents, uint flags, + struct xfs_trans **tpp); int libxfs_trans_commit(struct xfs_trans *); void libxfs_trans_cancel(struct xfs_trans *); struct xfs_buf *libxfs_trans_getsb(struct xfs_trans *, struct xfs_mount *, int); diff --git a/libxfs/kmem.c b/libxfs/kmem.c index 4f3cd7e..c8bcb50 100644 --- a/libxfs/kmem.c +++ b/libxfs/kmem.c @@ -70,7 +70,7 @@ kmem_zalloc(size_t size, int flags) } void * -kmem_realloc(void *ptr, size_t new_size, size_t old_size, int flags) +kmem_realloc(void *ptr, size_t new_size, int flags) { ptr = realloc(ptr, new_size); if (ptr == NULL) { diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index bb502e0..611a849 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -55,7 +55,6 @@ #define xfs_trans_read_buf_map libxfs_trans_read_buf_map #define xfs_trans_roll libxfs_trans_roll #define xfs_trans_get_buf_map libxfs_trans_get_buf_map -#define xfs_trans_reserve libxfs_trans_reserve #define xfs_trans_resv_calc libxfs_trans_resv_calc #define xfs_attr_get libxfs_attr_get diff --git a/libxfs/trans.c b/libxfs/trans.c index 18ea010..97a29b9 100644 --- a/libxfs/trans.c +++ b/libxfs/trans.c @@ -119,7 +119,6 @@ libxfs_trans_roll( */ tres.tr_logres = trans->t_log_res; tres.tr_logcount = trans->t_log_count; - *tpp = libxfs_trans_alloc(trans->t_mountp, trans->t_type); /* * Commit the current transaction. @@ -132,8 +131,6 @@ libxfs_trans_roll( if (error) return error; - trans = *tpp; - /* * Reserve space in the log for th next transaction. * This also pushes items in the "AIL", the list of logged items, @@ -143,7 +140,7 @@ libxfs_trans_roll( * the prior and the next transactions. */ tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; - error = xfs_trans_reserve(trans, &tres, 0, 0); + error = libxfs_trans_alloc(trans->t_mountp, &tres, 0, 0, 0, tpp); /* * Ensure that the inode is in the new transaction and locked. */ @@ -151,32 +148,11 @@ libxfs_trans_roll( return error; if (dp) - xfs_trans_ijoin(trans, dp, 0); + xfs_trans_ijoin(*tpp, dp, 0); return 0; } -xfs_trans_t * -libxfs_trans_alloc( - xfs_mount_t *mp, - int type) -{ - xfs_trans_t *ptr; - - if ((ptr = calloc(sizeof(xfs_trans_t), 1)) == NULL) { - fprintf(stderr, _("%s: xact calloc failed (%d bytes): %s\n"), - progname, (int)sizeof(xfs_trans_t), strerror(errno)); - exit(1); - } - ptr->t_mountp = mp; - ptr->t_type = type; - INIT_LIST_HEAD(&ptr->t_items); -#ifdef XACT_DEBUG - fprintf(stderr, "allocated new transaction %p\n", ptr); -#endif - return ptr; -} - -int +static int libxfs_trans_reserve( struct xfs_trans *tp, struct xfs_trans_res *resp, @@ -199,6 +175,39 @@ libxfs_trans_reserve( return 0; } +int +libxfs_trans_alloc( + struct xfs_mount *mp, + struct xfs_trans_res *resp, + uint blocks, + uint rtextents, + uint flags, + struct xfs_trans **tpp) +{ + struct xfs_trans *ptr; + int error; + + if ((ptr = calloc(sizeof(xfs_trans_t), 1)) == NULL) { + fprintf(stderr, _("%s: xact calloc failed (%d bytes): %s\n"), + progname, (int)sizeof(xfs_trans_t), strerror(errno)); + exit(1); + } + ptr->t_mountp = mp; + INIT_LIST_HEAD(&ptr->t_items); +#ifdef XACT_DEBUG + fprintf(stderr, "allocated new transaction %p\n", ptr); +#endif + + error = libxfs_trans_reserve(ptr, resp, blocks, rtextents); + if (error) { + libxfs_trans_cancel(ptr); + return error; + } + + *tpp = ptr; + return 0; +} + void libxfs_trans_cancel( xfs_trans_t *tp) diff --git a/libxfs/util.c b/libxfs/util.c index f3b9895..b992ad0 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -541,10 +541,9 @@ libxfs_alloc_file_space( while (allocatesize_fsb && !error) { datablocks = allocatesize_fsb; - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); resblks = (uint)XFS_DIOSTRAT_SPACE_RES(mp, datablocks); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - resblks, 0); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, + resblks, 0, 0, &tp); /* * Check for running out of space */ diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 82a7c5e..0b05654 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -237,37 +237,21 @@ xfs_attr_set( return error; } - /* - * Start our first transaction of the day. - * - * All future transactions during this code must be "chained" off - * this one via the trans_dup() call. All transactions will contain - * the inode, and the inode will always be marked with trans_ihold(). - * Since the inode will be locked in all transactions, we must log - * the inode in every transaction to let it float upward through - * the log. - */ - args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_SET); + tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres + + M_RES(mp)->tr_attrsetrt.tr_logres * args.total; + tres.tr_logcount = XFS_ATTRSET_LOG_COUNT; + tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; /* * Root fork attributes can use reserved data blocks for this * operation if necessary */ - - if (rsvd) - args.trans->t_flags |= XFS_TRANS_RESERVE; - - tres.tr_logres = M_RES(mp)->tr_attrsetm.tr_logres + - M_RES(mp)->tr_attrsetrt.tr_logres * args.total; - tres.tr_logcount = XFS_ATTRSET_LOG_COUNT; - tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; - error = xfs_trans_reserve(args.trans, &tres, args.total, 0); - if (error) { - xfs_trans_cancel(args.trans); + error = xfs_trans_alloc(mp, &tres, args.total, 0, + rsvd ? XFS_TRANS_RESERVE : 0, &args.trans); + if (error) return error; - } - xfs_ilock(dp, XFS_ILOCK_EXCL); + xfs_ilock(dp, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(args.trans, dp, args.total, 0, rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : XFS_QMOPT_RES_REGBLKS); @@ -424,31 +408,15 @@ xfs_attr_remove( return error; /* - * Start our first transaction of the day. - * - * All future transactions during this code must be "chained" off - * this one via the trans_dup() call. All transactions will contain - * the inode, and the inode will always be marked with trans_ihold(). - * Since the inode will be locked in all transactions, we must log - * the inode in every transaction to let it float upward through - * the log. - */ - args.trans = xfs_trans_alloc(mp, XFS_TRANS_ATTR_RM); - - /* * Root fork attributes can use reserved data blocks for this * operation if necessary */ - - if (flags & ATTR_ROOT) - args.trans->t_flags |= XFS_TRANS_RESERVE; - - error = xfs_trans_reserve(args.trans, &M_RES(mp)->tr_attrrm, - XFS_ATTRRM_SPACE_RES(mp), 0); - if (error) { - xfs_trans_cancel(args.trans); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_attrrm, + XFS_ATTRRM_SPACE_RES(mp), 0, + (flags & ATTR_ROOT) ? XFS_TRANS_RESERVE : 0, + &args.trans); + if (error) return error; - } xfs_ilock(dp, XFS_ILOCK_EXCL); /* diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index cbcfd72..c2a2c53 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -1113,15 +1113,14 @@ xfs_bmap_add_attrfork( mp = ip->i_mount; ASSERT(!XFS_NOT_DQATTACHED(mp, ip)); - tp = xfs_trans_alloc(mp, XFS_TRANS_ADDAFORK); + blks = XFS_ADDAFORK_SPACE_RES(mp); - if (rsvd) - tp->t_flags |= XFS_TRANS_RESERVE; - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_addafork, blks, 0); - if (error) { - xfs_trans_cancel(tp); + + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_addafork, blks, 0, + rsvd ? XFS_TRANS_RESERVE : 0, &tp); + if (error) return error; - } + xfs_ilock(ip, XFS_ILOCK_EXCL); error = xfs_trans_reserve_quota_nblks(tp, ip, blks, 0, rsvd ? XFS_QMOPT_RES_REGBLKS | XFS_QMOPT_FORCE_RES : @@ -6018,13 +6017,10 @@ xfs_bmap_split_extent( xfs_fsblock_t firstfsb; int error; - tp = xfs_trans_alloc(mp, XFS_TRANS_DIOSTRAT); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_write, - XFS_DIOSTRAT_SPACE_RES(mp, 0), 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, + XFS_DIOSTRAT_SPACE_RES(mp, 0), 0, 0, &tp); + if (error) return error; - } xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); diff --git a/libxfs/xfs_dir2_sf.c b/libxfs/xfs_dir2_sf.c index e4b505b..90b07f7 100644 --- a/libxfs/xfs_dir2_sf.c +++ b/libxfs/xfs_dir2_sf.c @@ -255,15 +255,12 @@ xfs_dir2_block_to_sf( * * Convert the inode to local format and copy the data in. */ - dp->i_df.if_flags &= ~XFS_IFEXTENTS; - dp->i_df.if_flags |= XFS_IFINLINE; - dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; ASSERT(dp->i_df.if_bytes == 0); - xfs_idata_realloc(dp, size, XFS_DATA_FORK); + xfs_init_local_fork(dp, XFS_DATA_FORK, dst, size); + dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; + dp->i_d.di_size = size; logflags |= XFS_ILOG_DDATA; - memcpy(dp->i_df.if_u1.if_data, dst, size); - dp->i_d.di_size = size; xfs_dir2_sf_check(args); out: xfs_trans_log_inode(args->trans, dp, logflags); diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 2af1dba..799873a 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -227,6 +227,48 @@ xfs_iformat_fork( return error; } +void +xfs_init_local_fork( + struct xfs_inode *ip, + int whichfork, + const void *data, + int size) +{ + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + int mem_size = size, real_size = 0; + bool zero_terminate; + + /* + * If we are using the local fork to store a symlink body we need to + * zero-terminate it so that we can pass it back to the VFS directly. + * Overallocate the in-memory fork by one for that and add a zero + * to terminate it below. + */ + zero_terminate = S_ISLNK(VFS_I(ip)->i_mode); + if (zero_terminate) + mem_size++; + + if (size == 0) + ifp->if_u1.if_data = NULL; + else if (mem_size <= sizeof(ifp->if_u2.if_inline_data)) + ifp->if_u1.if_data = ifp->if_u2.if_inline_data; + else { + real_size = roundup(mem_size, 4); + ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); + } + + if (size) { + memcpy(ifp->if_u1.if_data, data, size); + if (zero_terminate) + ifp->if_u1.if_data[size] = '\0'; + } + + ifp->if_bytes = size; + ifp->if_real_bytes = real_size; + ifp->if_flags &= ~(XFS_IFEXTENTS | XFS_IFBROOT); + ifp->if_flags |= XFS_IFINLINE; +} + /* * The file is in-lined in the on-disk inode. * If it fits into if_inline_data, then copy @@ -244,8 +286,6 @@ xfs_iformat_local( int whichfork, int size) { - xfs_ifork_t *ifp; - int real_size; /* * If the size is unreasonable, then something @@ -261,22 +301,8 @@ xfs_iformat_local( ip->i_mount, dip); return -EFSCORRUPTED; } - ifp = XFS_IFORK_PTR(ip, whichfork); - real_size = 0; - if (size == 0) - ifp->if_u1.if_data = NULL; - else if (size <= sizeof(ifp->if_u2.if_inline_data)) - ifp->if_u1.if_data = ifp->if_u2.if_inline_data; - else { - real_size = roundup(size, 4); - ifp->if_u1.if_data = kmem_alloc(real_size, KM_SLEEP | KM_NOFS); - } - ifp->if_bytes = size; - ifp->if_real_bytes = real_size; - if (size) - memcpy(ifp->if_u1.if_data, XFS_DFORK_PTR(dip, whichfork), size); - ifp->if_flags &= ~XFS_IFEXTENTS; - ifp->if_flags |= XFS_IFINLINE; + + xfs_init_local_fork(ip, whichfork, XFS_DFORK_PTR(dip, whichfork), size); return 0; } @@ -512,7 +538,6 @@ xfs_iroot_realloc( new_max = cur_max + rec_diff; new_size = XFS_BMAP_BROOT_SPACE_CALC(mp, new_max); ifp->if_broot = kmem_realloc(ifp->if_broot, new_size, - XFS_BMAP_BROOT_SPACE_CALC(mp, cur_max), KM_SLEEP | KM_NOFS); op = (char *)XFS_BMAP_BROOT_PTR_ADDR(mp, ifp->if_broot, 1, ifp->if_broot_bytes); @@ -656,7 +681,6 @@ xfs_idata_realloc( ifp->if_u1.if_data = kmem_realloc(ifp->if_u1.if_data, real_size, - ifp->if_real_bytes, KM_SLEEP | KM_NOFS); } } else { @@ -1372,8 +1396,7 @@ xfs_iext_realloc_direct( if (rnew_size != ifp->if_real_bytes) { ifp->if_u1.if_extents = kmem_realloc(ifp->if_u1.if_extents, - rnew_size, - ifp->if_real_bytes, KM_NOFS); + rnew_size, KM_NOFS); } if (rnew_size > ifp->if_real_bytes) { memset(&ifp->if_u1.if_extents[ifp->if_bytes / @@ -1457,9 +1480,8 @@ xfs_iext_realloc_indirect( if (new_size == 0) { xfs_iext_destroy(ifp); } else { - ifp->if_u1.if_ext_irec = (xfs_ext_irec_t *) - kmem_realloc(ifp->if_u1.if_ext_irec, - new_size, size, KM_NOFS); + ifp->if_u1.if_ext_irec = + kmem_realloc(ifp->if_u1.if_ext_irec, new_size, KM_NOFS); } } @@ -1493,6 +1515,24 @@ 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++) + kmem_free(ifp->if_u1.if_ext_irec[i].er_extbuf); + kmem_free(ifp->if_u1.if_ext_irec); + ifp->if_flags &= ~XFS_IFEXTIREC; +} + +/* * Free incore file extents. */ void @@ -1500,14 +1540,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); - } - ifp->if_flags &= ~XFS_IFEXTIREC; + xfs_iext_irec_remove_all(ifp); } else if (ifp->if_real_bytes) { kmem_free(ifp->if_u1.if_extents); } else if (ifp->if_bytes) { diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h index 7d3b1ed..f95e072 100644 --- a/libxfs/xfs_inode_fork.h +++ b/libxfs/xfs_inode_fork.h @@ -134,6 +134,7 @@ void xfs_iroot_realloc(struct xfs_inode *, int, int); int xfs_iread_extents(struct xfs_trans *, struct xfs_inode *, int); int xfs_iextents_copy(struct xfs_inode *, struct xfs_bmbt_rec *, int); +void xfs_init_local_fork(struct xfs_inode *, int, const void *, int); struct xfs_bmbt_rec_host * xfs_iext_get_ext(struct xfs_ifork *, xfs_extnum_t); diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h index 40005bf..e5baba3 100644 --- a/libxfs/xfs_log_format.h +++ b/libxfs/xfs_log_format.h @@ -212,6 +212,11 @@ typedef struct xfs_trans_header { #define XFS_TRANS_HEADER_MAGIC 0x5452414e /* TRAN */ /* + * The only type valid for th_type in CIL-enabled file system logs: + */ +#define XFS_TRANS_CHECKPOINT 40 + +/* * Log item types. */ #define XFS_LI_EFI 0x1236 diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index 67c7a65..e2cc83e 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -839,12 +839,10 @@ xfs_sync_sb( struct xfs_trans *tp; int error; - tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_CHANGE, KM_SLEEP); - error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0); - if (error) { - xfs_trans_cancel(tp); + error = xfs_trans_alloc(mp, &M_RES(mp)->tr_sb, 0, 0, + XFS_TRANS_NO_WRITECOUNT, &tp); + if (error) return error; - } xfs_log_sb(tp); if (wait) diff --git a/libxfs/xfs_shared.h b/libxfs/xfs_shared.h index 81ac870..16002b5 100644 --- a/libxfs/xfs_shared.h +++ b/libxfs/xfs_shared.h @@ -56,103 +56,6 @@ extern const struct xfs_buf_ops xfs_symlink_buf_ops; extern const struct xfs_buf_ops xfs_rtbuf_ops; /* - * Transaction types. Used to distinguish types of buffers. These never reach - * the log. - */ -#define XFS_TRANS_SETATTR_NOT_SIZE 1 -#define XFS_TRANS_SETATTR_SIZE 2 -#define XFS_TRANS_INACTIVE 3 -#define XFS_TRANS_CREATE 4 -#define XFS_TRANS_CREATE_TRUNC 5 -#define XFS_TRANS_TRUNCATE_FILE 6 -#define XFS_TRANS_REMOVE 7 -#define XFS_TRANS_LINK 8 -#define XFS_TRANS_RENAME 9 -#define XFS_TRANS_MKDIR 10 -#define XFS_TRANS_RMDIR 11 -#define XFS_TRANS_SYMLINK 12 -#define XFS_TRANS_SET_DMATTRS 13 -#define XFS_TRANS_GROWFS 14 -#define XFS_TRANS_STRAT_WRITE 15 -#define XFS_TRANS_DIOSTRAT 16 -/* 17 was XFS_TRANS_WRITE_SYNC */ -#define XFS_TRANS_WRITEID 18 -#define XFS_TRANS_ADDAFORK 19 -#define XFS_TRANS_ATTRINVAL 20 -#define XFS_TRANS_ATRUNCATE 21 -#define XFS_TRANS_ATTR_SET 22 -#define XFS_TRANS_ATTR_RM 23 -#define XFS_TRANS_ATTR_FLAG 24 -#define XFS_TRANS_CLEAR_AGI_BUCKET 25 -#define XFS_TRANS_SB_CHANGE 26 -/* - * Dummy entries since we use the transaction type to index into the - * trans_type[] in xlog_recover_print_trans_head() - */ -#define XFS_TRANS_DUMMY1 27 -#define XFS_TRANS_DUMMY2 28 -#define XFS_TRANS_QM_QUOTAOFF 29 -#define XFS_TRANS_QM_DQALLOC 30 -#define XFS_TRANS_QM_SETQLIM 31 -#define XFS_TRANS_QM_DQCLUSTER 32 -#define XFS_TRANS_QM_QINOCREATE 33 -#define XFS_TRANS_QM_QUOTAOFF_END 34 -#define XFS_TRANS_FSYNC_TS 35 -#define XFS_TRANS_GROWFSRT_ALLOC 36 -#define XFS_TRANS_GROWFSRT_ZERO 37 -#define XFS_TRANS_GROWFSRT_FREE 38 -#define XFS_TRANS_SWAPEXT 39 -#define XFS_TRANS_CHECKPOINT 40 -#define XFS_TRANS_ICREATE 41 -#define XFS_TRANS_CREATE_TMPFILE 42 -#define XFS_TRANS_TYPE_MAX 43 -/* new transaction types need to be reflected in xfs_logprint(8) */ - -#define XFS_TRANS_TYPES \ - { XFS_TRANS_SETATTR_NOT_SIZE, "SETATTR_NOT_SIZE" }, \ - { XFS_TRANS_SETATTR_SIZE, "SETATTR_SIZE" }, \ - { XFS_TRANS_INACTIVE, "INACTIVE" }, \ - { XFS_TRANS_CREATE, "CREATE" }, \ - { XFS_TRANS_CREATE_TRUNC, "CREATE_TRUNC" }, \ - { XFS_TRANS_TRUNCATE_FILE, "TRUNCATE_FILE" }, \ - { XFS_TRANS_REMOVE, "REMOVE" }, \ - { XFS_TRANS_LINK, "LINK" }, \ - { XFS_TRANS_RENAME, "RENAME" }, \ - { XFS_TRANS_MKDIR, "MKDIR" }, \ - { XFS_TRANS_RMDIR, "RMDIR" }, \ - { XFS_TRANS_SYMLINK, "SYMLINK" }, \ - { XFS_TRANS_SET_DMATTRS, "SET_DMATTRS" }, \ - { XFS_TRANS_GROWFS, "GROWFS" }, \ - { XFS_TRANS_STRAT_WRITE, "STRAT_WRITE" }, \ - { XFS_TRANS_DIOSTRAT, "DIOSTRAT" }, \ - { XFS_TRANS_WRITEID, "WRITEID" }, \ - { XFS_TRANS_ADDAFORK, "ADDAFORK" }, \ - { XFS_TRANS_ATTRINVAL, "ATTRINVAL" }, \ - { XFS_TRANS_ATRUNCATE, "ATRUNCATE" }, \ - { XFS_TRANS_ATTR_SET, "ATTR_SET" }, \ - { XFS_TRANS_ATTR_RM, "ATTR_RM" }, \ - { XFS_TRANS_ATTR_FLAG, "ATTR_FLAG" }, \ - { XFS_TRANS_CLEAR_AGI_BUCKET, "CLEAR_AGI_BUCKET" }, \ - { XFS_TRANS_SB_CHANGE, "SBCHANGE" }, \ - { XFS_TRANS_DUMMY1, "DUMMY1" }, \ - { XFS_TRANS_DUMMY2, "DUMMY2" }, \ - { XFS_TRANS_QM_QUOTAOFF, "QM_QUOTAOFF" }, \ - { XFS_TRANS_QM_DQALLOC, "QM_DQALLOC" }, \ - { XFS_TRANS_QM_SETQLIM, "QM_SETQLIM" }, \ - { XFS_TRANS_QM_DQCLUSTER, "QM_DQCLUSTER" }, \ - { XFS_TRANS_QM_QINOCREATE, "QM_QINOCREATE" }, \ - { XFS_TRANS_QM_QUOTAOFF_END, "QM_QOFF_END" }, \ - { XFS_TRANS_FSYNC_TS, "FSYNC_TS" }, \ - { XFS_TRANS_GROWFSRT_ALLOC, "GROWFSRT_ALLOC" }, \ - { XFS_TRANS_GROWFSRT_ZERO, "GROWFSRT_ZERO" }, \ - { XFS_TRANS_GROWFSRT_FREE, "GROWFSRT_FREE" }, \ - { XFS_TRANS_SWAPEXT, "SWAPEXT" }, \ - { XFS_TRANS_CHECKPOINT, "CHECKPOINT" }, \ - { XFS_TRANS_ICREATE, "ICREATE" }, \ - { XFS_TRANS_CREATE_TMPFILE, "CREATE_TMPFILE" }, \ - { XLOG_UNMOUNT_REC_TYPE, "UNMOUNT" } - -/* * This structure is used to track log items associated with * a transaction. It points to the log item and keeps some * flags to track the state of the log item. It also tracks @@ -181,8 +84,9 @@ int xfs_log_calc_minimum_size(struct xfs_mount *); #define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ #define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ #define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ -#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer - count in superblock */ +#define XFS_TRANS_NO_WRITECOUNT 0x40 /* do not elevate SB writecount */ +#define XFS_TRANS_NOFS 0x80 /* pass KM_NOFS to kmem_alloc */ + /* * Field values for xfs_trans_mod_sb. */ diff --git a/libxlog/xfs_log_recover.c b/libxlog/xfs_log_recover.c index 6116ecd..6cd77d5 100644 --- a/libxlog/xfs_log_recover.c +++ b/libxlog/xfs_log_recover.c @@ -1062,7 +1062,7 @@ xlog_recover_add_to_cont_trans( old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; old_len = item->ri_buf[item->ri_cnt-1].i_len; - ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP); + ptr = kmem_realloc(old_ptr, len+old_len, KM_SLEEP); memcpy(&ptr[old_len], dp, len); /* d, s, l */ item->ri_buf[item->ri_cnt-1].i_len += len; item->ri_buf[item->ri_cnt-1].i_addr = ptr; diff --git a/mkfs/proto.c b/mkfs/proto.c index 09a9439..edbaa33 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -25,7 +25,7 @@ */ static char *getstr(char **pp); static void fail(char *msg, int i); -static void getres(xfs_trans_t *tp, uint blocks); +static void getres(struct xfs_mount *mp, uint blocks, struct xfs_trans **tpp); static void rsvfile(xfs_mount_t *mp, xfs_inode_t *ip, long long len); static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, xfs_bmap_free_t *flist, xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len); @@ -127,22 +127,23 @@ res_failed( static void getres( - xfs_trans_t *tp, - uint blocks) + struct xfs_mount *mp, + uint blocks, + struct xfs_trans **tpp) { - int i; - xfs_mount_t *mp; - uint r; - - mp = tp->t_mountp; - for (i = 0, r = MKFS_BLOCKRES(blocks); r >= blocks; r--) { - struct xfs_trans_res tres = {0}; - - i = -libxfs_trans_reserve(tp, &tres, r, 0); - if (i == 0) + struct xfs_trans *tp; + uint r; + int error = -ENOSPC; + + for (r = MKFS_BLOCKRES(blocks); r >= blocks; r--) { + error = libxfs_trans_alloc(mp, NULL, r, 0, 0, &tp); + if (!error) { + *tpp = tp; return; + } } - res_failed(i); + + res_failed(error); /* NOTREACHED */ } @@ -203,7 +204,11 @@ rsvfile( /* * update the inode timestamp, mode, and prealloc flag bits */ - tp = libxfs_trans_alloc(mp, 0); + error = -libxfs_trans_alloc(mp, NULL, 0, 0, 0, &tp); + if (error) { + fail(_("error reserving space for a file"), error); + exit(1); + } libxfs_trans_ijoin(tp, ip, 0); @@ -454,13 +459,12 @@ parseproto( xname.name = (unsigned char *)name; xname.len = name ? strlen(name) : 0; xname.type = 0; - tp = libxfs_trans_alloc(mp, 0); flags = XFS_ILOG_CORE; xfs_bmap_init(&flist, &first); switch (fmt) { case IF_REGULAR: buf = newregfile(pp, &len); - getres(tp, XFS_B_TO_FSB(mp, len)); + getres(mp, XFS_B_TO_FSB(mp, len), &tp); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) @@ -483,7 +487,7 @@ parseproto( progname, value, name); exit(1); } - getres(tp, XFS_B_TO_FSB(mp, llen)); + getres(mp, XFS_B_TO_FSB(mp, llen), &tp); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); @@ -505,7 +509,7 @@ parseproto( return; case IF_BLOCK: - getres(tp, 0); + getres(mp, 0, &tp); majdev = getnum(getstr(pp), 0, 0, false); mindev = getnum(getstr(pp), 0, 0, false); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFBLK, 1, @@ -520,7 +524,7 @@ parseproto( break; case IF_CHAR: - getres(tp, 0); + getres(mp, 0, &tp); majdev = getnum(getstr(pp), 0, 0, false); mindev = getnum(getstr(pp), 0, 0, false); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFCHR, 1, @@ -534,7 +538,7 @@ parseproto( break; case IF_FIFO: - getres(tp, 0); + getres(mp, 0, &tp); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFIFO, 1, 0, &creds, fsxp, &ip); if (error) @@ -546,7 +550,7 @@ parseproto( case IF_SYMLINK: buf = getstr(pp); len = (int)strlen(buf); - getres(tp, XFS_B_TO_FSB(mp, len)); + getres(mp, XFS_B_TO_FSB(mp, len), &tp); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFLNK, 1, 0, &creds, fsxp, &ip); if (error) @@ -557,7 +561,7 @@ parseproto( newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); break; case IF_DIRECTORY: - getres(tp, 0); + getres(mp, 0, &tp); error = -libxfs_inode_alloc(&tp, pip, mode|S_IFDIR, 1, 0, &creds, fsxp, &ip); if (error) @@ -649,8 +653,7 @@ rtinit( /* * First, allocate the inodes. */ - tp = libxfs_trans_alloc(mp, 0); - i = -libxfs_trans_reserve(tp, &tres, MKFS_BLOCKRES_INODE, 0); + i = -libxfs_trans_alloc(mp, &tres, MKFS_BLOCKRES_INODE, 0, 0, &tp); if (i) res_failed(i); @@ -687,9 +690,8 @@ rtinit( /* * Next, give the bitmap file some zero-filled blocks. */ - tp = libxfs_trans_alloc(mp, 0); - i = -libxfs_trans_reserve(tp, &tres, mp->m_sb.sb_rbmblocks + - (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0); + i = -libxfs_trans_alloc(mp, &tres, mp->m_sb.sb_rbmblocks + + (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0, 0, &tp); if (i) res_failed(i); @@ -723,10 +725,9 @@ rtinit( /* * Give the summary file some zero-filled blocks. */ - tp = libxfs_trans_alloc(mp, 0); nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; - i = -libxfs_trans_reserve(tp, &tres, nsumblocks + - (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0); + i = -libxfs_trans_alloc(mp, &tres, nsumblocks + + (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0, 0, &tp); if (i) res_failed(i); libxfs_trans_ijoin(tp, rsumip, 0); @@ -760,8 +761,7 @@ rtinit( * Do one transaction per bitmap block. */ for (bno = 0; bno < mp->m_sb.sb_rextents; bno = ebno) { - tp = libxfs_trans_alloc(mp, 0); - i = -libxfs_trans_reserve(tp, &tres, 0, 0); + i = -libxfs_trans_alloc(mp, &tres, 0, 0, 0, &tp); if (i) res_failed(i); libxfs_trans_ijoin(tp, rbmip, 0); diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 955dcfd..de00c8e 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -3451,14 +3451,15 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), struct xfs_trans_res tres = {0}; memset(&args, 0, sizeof(args)); - args.tp = tp = libxfs_trans_alloc(mp, 0); + args.mp = mp; args.agno = agno; args.alignment = 1; args.pag = xfs_perag_get(mp,agno); - c = -libxfs_trans_reserve(tp, &tres, worst_freelist, 0); + c = -libxfs_trans_alloc(mp, &tres, worst_freelist, 0, 0, &tp); if (c) res_failed(c); + args.tp = tp; libxfs_alloc_fix_freelist(&args, 0); xfs_perag_put(args.pag); diff --git a/repair/phase5.c b/repair/phase5.c index 5d48848..b58111b 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -1505,14 +1505,19 @@ build_agf_agfl(xfs_mount_t *mp, int error; memset(&args, 0, sizeof(args)); - args.tp = tp = libxfs_trans_alloc(mp, 0); args.mp = mp; args.agno = agno; args.alignment = 1; args.pag = xfs_perag_get(mp,agno); - libxfs_trans_reserve(tp, &tres, - xfs_alloc_min_freelist(mp, args.pag), 0); - error = libxfs_alloc_fix_freelist(&args, 0); + error = -libxfs_trans_alloc(mp, &tres, + xfs_alloc_min_freelist(mp, args.pag), + 0, 0, &tp); + if (error) { + do_error(_("failed to fix AGFL on AG %d, error %d\n"), + agno, error); + } + args.tp = tp; + error = -libxfs_alloc_fix_freelist(&args, 0); xfs_perag_put(args.pag); if (error) { do_error(_("failed to fix AGFL on AG %d, error %d\n"), diff --git a/repair/phase6.c b/repair/phase6.c index 7353c3a..d1acb68 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -494,9 +494,7 @@ mk_rbmino(xfs_mount_t *mp) /* * first set up inode */ - tp = libxfs_trans_alloc(mp, 0); - - i = -libxfs_trans_reserve(tp, &tres, 10, 0); + i = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp); if (i) res_failed(i); @@ -544,9 +542,9 @@ mk_rbmino(xfs_mount_t *mp) * then allocate blocks for file and fill with zeroes (stolen * from mkfs) */ - tp = libxfs_trans_alloc(mp, 0); - error = -libxfs_trans_reserve(tp, &tres, mp->m_sb.sb_rbmblocks + - (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0); + error = -libxfs_trans_alloc(mp, &tres, mp->m_sb.sb_rbmblocks + + (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), + 0, 0, &tp); if (error) res_failed(error); @@ -598,9 +596,7 @@ fill_rbmino(xfs_mount_t *mp) bmp = btmcompute; bno = 0; - tp = libxfs_trans_alloc(mp, 0); - - error = -libxfs_trans_reserve(tp, &tres, 10, 0); + error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp); if (error) res_failed(error); @@ -671,9 +667,7 @@ fill_rsumino(xfs_mount_t *mp) bno = 0; end_bno = mp->m_rsumsize >> mp->m_sb.sb_blocklog; - tp = libxfs_trans_alloc(mp, 0); - - error = -libxfs_trans_reserve(tp, &tres, 10, 0); + error = -libxfs_trans_alloc(mp, &tres, 10, 0, 0, &tp); if (error) res_failed(error); @@ -747,9 +741,7 @@ mk_rsumino(xfs_mount_t *mp) /* * first set up inode */ - tp = libxfs_trans_alloc(mp, 0); - - i = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 10, 0); + i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 10, 0, 0, &tp); if (i) res_failed(i); @@ -797,15 +789,15 @@ mk_rsumino(xfs_mount_t *mp) * then allocate blocks for file and fill with zeroes (stolen * from mkfs) */ - tp = libxfs_trans_alloc(mp, 0); xfs_bmap_init(&flist, &first); nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; tres.tr_logres = BBTOB(128); tres.tr_logcount = XFS_DEFAULT_PERM_LOG_COUNT; tres.tr_logflags = XFS_TRANS_PERM_LOG_RES; - error = -libxfs_trans_reserve(tp, &tres, mp->m_sb.sb_rbmblocks + - (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), 0); + error = -libxfs_trans_alloc(mp, &tres, mp->m_sb.sb_rbmblocks + + (XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) - 1), + 0, 0, &tp); if (error) res_failed(error); @@ -854,10 +846,9 @@ mk_root_dir(xfs_mount_t *mp) int vers; int times; - tp = libxfs_trans_alloc(mp, 0); ip = NULL; - i = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_ichange, 10, 0); + i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 10, 0, 0, &tp); if (i) res_failed(i); @@ -954,11 +945,10 @@ mk_orphanage(xfs_mount_t *mp) * could not be found, create it */ - tp = libxfs_trans_alloc(mp, 0); xfs_bmap_init(&flist, &first); nres = XFS_MKDIR_SPACE_RES(mp, xname.len); - i = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_mkdir, nres, 0); + i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); if (i) res_failed(i); @@ -1092,8 +1082,6 @@ mv_orphanage( xname.len = snprintf((char *)fname, sizeof(fname), "%llu.%d", (unsigned long long)ino, ++incr); - tp = libxfs_trans_alloc(mp, 0); - if ((err = -libxfs_iget(mp, NULL, ino, 0, &ino_p, 0))) do_error(_("%d - couldn't iget disconnected inode\n"), err); @@ -1112,8 +1100,8 @@ mv_orphanage( if (err) { ASSERT(err == ENOENT); - err = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_rename, - nres, 0); + err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename, + nres, 0, 0, &tp); if (err) do_error( _("space reservation failed (%d), filesystem may be out of space\n"), @@ -1154,8 +1142,8 @@ mv_orphanage( libxfs_trans_commit(tp); } else { - err = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_rename, - nres, 0); + err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_rename, + nres, 0, 0, &tp); if (err) do_error( _("space reservation failed (%d), filesystem may be out of space\n"), @@ -1210,8 +1198,8 @@ mv_orphanage( * also accounted for in the create */ nres = XFS_DIRENTER_SPACE_RES(mp, xname.len); - err = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, - nres, 0); + err = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, + nres, 0, 0, &tp); if (err) do_error( _("space reservation failed (%d), filesystem may be out of space\n"), @@ -1306,9 +1294,8 @@ longform_dir2_rebuild( xfs_bmap_init(&flist, &firstblock); - tp = libxfs_trans_alloc(mp, 0); nres = XFS_REMOVE_SPACE_RES(mp); - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, nres, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); @@ -1349,10 +1336,9 @@ longform_dir2_rebuild( p->name.name[1] == '.')))) continue; - tp = libxfs_trans_alloc(mp, 0); nres = XFS_CREATE_SPACE_RES(mp, p->name.len); - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_create, - nres, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_create, + nres, 0, 0, &tp); if (error) res_failed(error); @@ -1406,9 +1392,8 @@ dir2_kill_block( int nres; xfs_trans_t *tp; - tp = libxfs_trans_alloc(mp, 0); nres = XFS_REMOVE_SPACE_RES(mp); - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, nres, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); if (error) res_failed(error); libxfs_trans_ijoin(tp, ip, 0); @@ -1598,8 +1583,7 @@ longform_dir2_entry_check_data( if (freetab->nents < db + 1) freetab->nents = db + 1; - tp = libxfs_trans_alloc(mp, 0); - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, 0, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, 0, 0, 0, &tp); if (error) res_failed(error); da.trans = tp; @@ -2902,7 +2886,6 @@ process_dir_inode( break; case XFS_DINODE_FMT_LOCAL: - tp = libxfs_trans_alloc(mp, 0); /* * using the remove reservation is overkill * since at most we'll only need to log the @@ -2910,8 +2893,8 @@ process_dir_inode( * new define in ourselves. */ nres = no_modify ? 0 : XFS_REMOVE_SPACE_RES(mp); - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, - nres, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, + nres, 0, 0, &tp); if (error) res_failed(error); @@ -2951,13 +2934,12 @@ process_dir_inode( do_warn(_("recreating root directory .. entry\n")); - tp = libxfs_trans_alloc(mp, 0); - ASSERT(tp != NULL); - nres = XFS_MKDIR_SPACE_RES(mp, 2); - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_mkdir, nres, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, + nres, 0, 0, &tp); if (error) res_failed(error); + ASSERT(tp != NULL); libxfs_trans_ijoin(tp, ip, 0); @@ -3010,14 +2992,12 @@ process_dir_inode( do_warn( _("creating missing \".\" entry in dir ino %" PRIu64 "\n"), ino); - tp = libxfs_trans_alloc(mp, 0); - ASSERT(tp != NULL); - nres = XFS_MKDIR_SPACE_RES(mp, 1); - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_mkdir, - nres, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, + nres, 0, 0, &tp); if (error) res_failed(error); + ASSERT(tp != NULL); libxfs_trans_ijoin(tp, ip, 0); diff --git a/repair/phase7.c b/repair/phase7.c index 3e234b9..8bce117 100644 --- a/repair/phase7.c +++ b/repair/phase7.c @@ -40,10 +40,8 @@ update_inode_nlinks( int dirty; int nres; - tp = libxfs_trans_alloc(mp, XFS_TRANS_REMOVE); - nres = no_modify ? 0 : 10; - error = -libxfs_trans_reserve(tp, &M_RES(mp)->tr_remove, nres, 0); + error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); ASSERT(error == 0); error = -libxfs_trans_iget(mp, tp, ino, 0, 0, &ip); From darrick.wong@oracle.com Thu Jun 16 20:31:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 79F0E8048 for ; Thu, 16 Jun 2016 20:31:32 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3A8038F804C for ; Thu, 16 Jun 2016 18:31:32 -0700 (PDT) X-ASG-Debug-ID: 1466127090-04bdf01e1595f20001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id wp3KBSWNgTA0c4Wy (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1VR2S001248 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:27 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VP0m030656 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:27 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VOUM026630; Fri, 17 Jun 2016 01:31:25 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:24 -0700 Subject: [PATCH 006/145] xfs: make several functions static From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 006/145] xfs: make several functions static To: david@fromorbit.com, darrick.wong@oracle.com Cc: Eric Sandeen , Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:23 -0700 Message-ID: <146612708305.16048.5855007801575308944.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127090 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3222 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Eric Sandeen Al Viro noticed that xfs_lock_inodes should be static, and that led to ... a few more. These are just the easy ones, others require moving functions higher in source files, so that's not done here to keep this review simple. Signed-off-by: Eric Sandeen Reviewed-by: Christoph Hellwig Signed-off-by: Dave Chinner --- libxfs/xfs_alloc.c | 2 +- libxfs/xfs_alloc.h | 7 ------- libxfs/xfs_attr_leaf.h | 3 --- libxfs/xfs_rtbitmap.c | 2 +- 4 files changed, 2 insertions(+), 12 deletions(-) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 28b3fb9..8520f31 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -80,7 +80,7 @@ xfs_alloc_lookup_ge( * Lookup the first record less than or equal to [bno, len] * in the btree given by cur. */ -int /* error */ +static int /* error */ xfs_alloc_lookup_le( struct xfs_btree_cur *cur, /* btree cursor */ xfs_agblock_t bno, /* starting block of extent */ diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 135eb3d..92a66ba 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -212,13 +212,6 @@ xfs_free_extent( xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len); /* length of extent */ -int /* error */ -xfs_alloc_lookup_le( - struct xfs_btree_cur *cur, /* btree cursor */ - xfs_agblock_t bno, /* starting block of extent */ - xfs_extlen_t len, /* length of extent */ - int *stat); /* success/failure */ - int /* error */ xfs_alloc_lookup_ge( struct xfs_btree_cur *cur, /* btree cursor */ diff --git a/libxfs/xfs_attr_leaf.h b/libxfs/xfs_attr_leaf.h index 9d7e741..8ef420a 100644 --- a/libxfs/xfs_attr_leaf.h +++ b/libxfs/xfs_attr_leaf.h @@ -50,7 +50,6 @@ int xfs_attr_shortform_lookup(struct xfs_da_args *args); int xfs_attr_shortform_getvalue(struct xfs_da_args *args); int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); int xfs_attr_shortform_remove(struct xfs_da_args *args); -int xfs_attr_shortform_list(struct xfs_attr_list_context *context); int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); int xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes); void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp); @@ -88,8 +87,6 @@ int xfs_attr3_leaf_toosmall(struct xfs_da_state *state, int *retval); void xfs_attr3_leaf_unbalance(struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, struct xfs_da_state_blk *save_blk); -int xfs_attr3_root_inactive(struct xfs_trans **trans, struct xfs_inode *dp); - /* * Utility routines. */ diff --git a/libxfs/xfs_rtbitmap.c b/libxfs/xfs_rtbitmap.c index 70ea975..36fe323 100644 --- a/libxfs/xfs_rtbitmap.c +++ b/libxfs/xfs_rtbitmap.c @@ -65,7 +65,7 @@ const struct xfs_buf_ops xfs_rtbuf_ops = { * Get a buffer for the bitmap or summary file block specified. * The buffer is returned read and locked. */ -int +static int xfs_rtbuf_get( xfs_mount_t *mp, /* file system mount structure */ xfs_trans_t *tp, /* transaction pointer */ From darrick.wong@oracle.com Thu Jun 16 20:31:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B71418053 for ; Thu, 16 Jun 2016 20:31:40 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 873D6304048 for ; Thu, 16 Jun 2016 18:31:40 -0700 (PDT) X-ASG-Debug-ID: 1466127098-04cb6c542757cd0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id wByeBAlxzmoRRiei (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1VW8s014234 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:32 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VVVm019701 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:32 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VVtt026729; Fri, 17 Jun 2016 01:31:31 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:30 -0700 Subject: [PATCH 007/145] xfs: define XFS_IOC_FREEZE even if FIFREEZE is defined From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 007/145] xfs: define XFS_IOC_FREEZE even if FIFREEZE is defined To: david@fromorbit.com, darrick.wong@oracle.com Cc: Eric Sandeen , Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:29 -0700 Message-ID: <146612708926.16048.13122914973767530118.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127099 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1292 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Christoph Hellwig And the same for XFS_IOC_THAW. Just because we now have a common version of the ioctl we still need to provide the old name for it for anyone using those. Signed-off-by: Christoph Hellwig Reviewed-by: Eric Sandeen Signed-off-by: Dave Chinner --- libxfs/xfs_fs.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index b9622ba..1f17e1c 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -542,12 +542,8 @@ typedef struct xfs_swapext #define XFS_IOC_ERROR_CLEARALL _IOW ('X', 117, struct xfs_error_injection) /* XFS_IOC_ATTRCTL_BY_HANDLE -- deprecated 118 */ -/* XFS_IOC_FREEZE -- FIFREEZE 119 */ -/* XFS_IOC_THAW -- FITHAW 120 */ -#ifndef FIFREEZE -#define XFS_IOC_FREEZE _IOWR('X', 119, int) -#define XFS_IOC_THAW _IOWR('X', 120, int) -#endif +#define XFS_IOC_FREEZE _IOWR('X', 119, int) /* aka FIFREEZE */ +#define XFS_IOC_THAW _IOWR('X', 120, int) /* aka FITHAW */ #define XFS_IOC_FSSETDM_BY_HANDLE _IOW ('X', 121, struct xfs_fsop_setdm_handlereq) #define XFS_IOC_ATTRLIST_BY_HANDLE _IOW ('X', 122, struct xfs_fsop_attrlist_handlereq) From darrick.wong@oracle.com Thu Jun 16 20:31:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 816018053 for ; Thu, 16 Jun 2016 20:31:41 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 50D818F804C for ; Thu, 16 Jun 2016 18:31:41 -0700 (PDT) X-ASG-Debug-ID: 1466127099-04cb6c542657cd0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id IwGkGDww2qyAL5Mq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Vb7i001332 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:31:38 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Vbw3024679 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:37 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VbJj026756; Fri, 17 Jun 2016 01:31:37 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:36 -0700 Subject: [PATCH 008/145] libxfs: add more list operations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 008/145] libxfs: add more list operations To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:35 -0700 Message-ID: <146612709549.16048.6522744362673808871.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127099 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8174 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add some list operations that the deferred rmap code requires. Signed-off-by: Darrick J. Wong --- include/list.h | 76 ++++++++++++++++++++++++++++--- libxfs/rdwr.c | 2 - libxfs/util.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 206 insertions(+), 9 deletions(-) diff --git a/include/list.h b/include/list.h index f92faed..372cf06 100644 --- a/include/list.h +++ b/include/list.h @@ -111,30 +111,30 @@ static inline int list_empty(const struct list_head *head) } static inline void __list_splice(struct list_head *list, - struct list_head *head) + struct list_head *prev, + struct list_head *next) { struct list_head *first = list->next; struct list_head *last = list->prev; - struct list_head *at = head->next; - first->prev = head; - head->next = first; + first->prev = prev; + prev->next = first; - last->next = at; - at->prev = last; + last->next = next; + next->prev = last; } static inline void list_splice(struct list_head *list, struct list_head *head) { if (!list_empty(list)) - __list_splice(list, head); + __list_splice(list, head, head->next); } static inline void list_splice_init(struct list_head *list, struct list_head *head) { if (!list_empty(list)) { - __list_splice(list, head); + __list_splice(list, head, head->next); list_head_init(list); } } @@ -161,4 +161,64 @@ static inline void list_splice_init(struct list_head *list, &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +void list_sort(void *priv, struct list_head *head, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b)); + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_last_entry - get the last element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_last_entry(ptr, type, member) \ + list_entry((ptr)->prev, type, member) + +/** + * list_prev_entry - get the prev element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_prev_entry(pos, member) \ + list_entry((pos)->member.prev, typeof(*(pos)), member) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_last_entry(head, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_prev_entry(pos, member)) + #endif /* __LIST_H__ */ diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c index 0ec38c5..aa30522 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -1260,7 +1260,7 @@ libxfs_bulkrelse( } pthread_mutex_lock(&xfs_buf_freelist.cm_mutex); - __list_splice(list, &xfs_buf_freelist.cm_list); + list_splice(list, &xfs_buf_freelist.cm_list); pthread_mutex_unlock(&xfs_buf_freelist.cm_mutex); return count; diff --git a/libxfs/util.c b/libxfs/util.c index b992ad0..2e826c9 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -35,6 +35,7 @@ #include "xfs_ialloc.h" #include "xfs_alloc.h" #include "xfs_bit.h" +#include "list.h" /* * Calculate the worst case log unit reservation for a given superblock @@ -781,3 +782,139 @@ libxfs_zero_extent( return libxfs_device_zero(xfs_find_bdev_for_inode(ip), sector, size); } + +/* List sorting code from Linux. */ +#define MAX_LIST_LENGTH_BITS 20 + +/* + * Returns a list organized in an intermediate format suited + * to chaining of merge() calls: null-terminated, no reserved or + * sentinel head node, "prev" links not maintained. + */ +static struct list_head *merge(void *priv, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b), + struct list_head *a, struct list_head *b) +{ + struct list_head head, *tail = &head; + + while (a && b) { + /* if equal, take 'a' -- important for sort stability */ + if ((*cmp)(priv, a, b) <= 0) { + tail->next = a; + a = a->next; + } else { + tail->next = b; + b = b->next; + } + tail = tail->next; + } + tail->next = a?:b; + return head.next; +} + +/* + * Combine final list merge with restoration of standard doubly-linked + * list structure. This approach duplicates code from merge(), but + * runs faster than the tidier alternatives of either a separate final + * prev-link restoration pass, or maintaining the prev links + * throughout. + */ +static void merge_and_restore_back_links(void *priv, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b), + struct list_head *head, + struct list_head *a, struct list_head *b) +{ + struct list_head *tail = head; + unsigned count = 0; + + while (a && b) { + /* if equal, take 'a' -- important for sort stability */ + if ((*cmp)(priv, a, b) <= 0) { + tail->next = a; + a->prev = tail; + a = a->next; + } else { + tail->next = b; + b->prev = tail; + b = b->next; + } + tail = tail->next; + } + tail->next = a ? : b; + + do { + /* + * In worst cases this loop may run many iterations. + * Continue callbacks to the client even though no + * element comparison is needed, so the client's cmp() + * routine can invoke cond_resched() periodically. + */ + if (unlikely(!(++count))) + (*cmp)(priv, tail->next, tail->next); + + tail->next->prev = tail; + tail = tail->next; + } while (tail->next); + + tail->next = head; + head->prev = tail; +} + +/** + * list_sort - sort a list + * @priv: private data, opaque to list_sort(), passed to @cmp + * @head: the list to sort + * @cmp: the elements comparison function + * + * This function implements "merge sort", which has O(nlog(n)) + * complexity. + * + * The comparison function @cmp must return a negative value if @a + * should sort before @b, and a positive value if @a should sort after + * @b. If @a and @b are equivalent, and their original relative + * ordering is to be preserved, @cmp must return 0. + */ +void list_sort(void *priv, struct list_head *head, + int (*cmp)(void *priv, struct list_head *a, + struct list_head *b)) +{ + struct list_head *part[MAX_LIST_LENGTH_BITS+1]; /* sorted partial lists + -- last slot is a sentinel */ + int lev; /* index into part[] */ + int max_lev = 0; + struct list_head *list; + + if (list_empty(head)) + return; + + memset(part, 0, sizeof(part)); + + head->prev->next = NULL; + list = head->next; + + while (list) { + struct list_head *cur = list; + list = list->next; + cur->next = NULL; + + for (lev = 0; part[lev]; lev++) { + cur = merge(priv, cmp, part[lev], cur); + part[lev] = NULL; + } + if (lev > max_lev) { + if (unlikely(lev >= ARRAY_SIZE(part)-1)) { + lev--; + } + max_lev = lev; + } + part[lev] = cur; + } + + for (lev = 0; lev < max_lev; lev++) + if (part[lev]) + list = merge(priv, cmp, part[lev], list); + + merge_and_restore_back_links(priv, cmp, head, part[max_lev], list); +} From darrick.wong@oracle.com Thu Jun 16 20:31:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 798E58063 for ; Thu, 16 Jun 2016 20:31:49 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4B6168F804B for ; Thu, 16 Jun 2016 18:31:49 -0700 (PDT) X-ASG-Debug-ID: 1466127105-04cbb01fed69d70001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id qRJqGxLRQxcCYERo (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:45 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ViWI001393 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:44 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VhVs026308 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:43 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Vhc5026769; Fri, 17 Jun 2016 01:31:43 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:43 -0700 Subject: [PATCH 009/145] xfs_logprint: move the EFI copying/printing functions to a redo items file From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 009/145] xfs_logprint: move the EFI copying/printing functions to a redo items file To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:41 -0700 Message-ID: <146612710170.16048.15356139701108271924.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127105 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17300 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Move the functions that handle EFI items into a separate file to avoid cluttering up log_misc.c even more when we start adding the other redo item types. Signed-off-by: Darrick J. Wong --- logprint/Makefile | 2 logprint/log_misc.c | 144 ----------------------------- logprint/log_print_all.c | 60 ------------ logprint/log_redo.c | 226 ++++++++++++++++++++++++++++++++++++++++++++++ logprint/logprint.h | 6 + 5 files changed, 232 insertions(+), 206 deletions(-) create mode 100644 logprint/log_redo.c diff --git a/logprint/Makefile b/logprint/Makefile index 7bcf27f..534bf5b 100644 --- a/logprint/Makefile +++ b/logprint/Makefile @@ -10,7 +10,7 @@ LTCOMMAND = xfs_logprint HFILES = logprint.h CFILES = logprint.c \ log_copy.c log_dump.c log_misc.c \ - log_print_all.c log_print_trans.c + log_print_all.c log_print_trans.c log_redo.c LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) LTDEPENDENCIES = $(LIBXFS) $(LIBXLOG) diff --git a/logprint/log_misc.c b/logprint/log_misc.c index e6ee832..57d397c 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -475,100 +475,6 @@ xlog_print_trans_buffer(char **ptr, int len, int *i, int num_ops) int -xlog_print_trans_efd(char **ptr, uint len) -{ - xfs_efd_log_format_t *f; - xfs_efd_log_format_t lbuf; - /* size without extents at end */ - uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t); - - /* - * memmove to ensure 8-byte alignment for the long longs in - * xfs_efd_log_format_t structure - */ - memmove(&lbuf, *ptr, MIN(core_size, len)); - f = &lbuf; - *ptr += len; - if (len >= core_size) { - printf(_("EFD: #regs: %d num_extents: %d id: 0x%llx\n"), - f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); - - /* don't print extents as they are not used */ - - return 0; - } else { - printf(_("EFD: Not enough data to decode further\n")); - return 1; - } -} /* xlog_print_trans_efd */ - - -int -xlog_print_trans_efi( - char **ptr, - uint src_len, - int continued) -{ - xfs_efi_log_format_t *src_f, *f = NULL; - uint dst_len; - xfs_extent_t *ex; - int i; - int error = 0; - int core_size = offsetof(xfs_efi_log_format_t, efi_extents); - - /* - * memmove to ensure 8-byte alignment for the long longs in - * xfs_efi_log_format_t structure - */ - if ((src_f = (xfs_efi_log_format_t *)malloc(src_len)) == NULL) { - fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); - exit(1); - } - memmove((char*)src_f, *ptr, src_len); - *ptr += src_len; - - /* convert to native format */ - dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); - - if (continued && src_len < core_size) { - printf(_("EFI: Not enough data to decode further\n")); - error = 1; - goto error; - } - - if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { - fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); - exit(1); - } - if (xfs_efi_copy_format((char*)src_f, src_len, f, continued)) { - error = 1; - goto error; - } - - printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"), - f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); - - if (continued) { - printf(_("EFI free extent data skipped (CONTINUE set, no space)\n")); - goto error; - } - - ex = f->efi_extents; - for (i=0; i < f->efi_nextents; i++) { - printf("(s: 0x%llx, l: %d) ", - (unsigned long long)ex->ext_start, ex->ext_len); - if (i % 4 == 3) printf("\n"); - ex++; - } - if (i % 4 != 0) printf("\n"); -error: - free(src_f); - free(f); - return error; -} /* xlog_print_trans_efi */ - - -int xlog_print_trans_qoff(char **ptr, uint len) { xfs_qoff_logformat_t *f; @@ -1617,53 +1523,3 @@ xfs_inode_item_format_convert(char *src_buf, uint len, xfs_inode_log_format_t *i } return in_f; } - -int -xfs_efi_copy_format( - char *buf, - uint len, - struct xfs_efi_log_format *dst_efi_fmt, - int continued) -{ - uint i; - uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents; - uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t); - uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t); - uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t); - - if (len == dst_len || continued) { - memcpy((char *)dst_efi_fmt, buf, len); - return 0; - } else if (len == len32) { - xfs_efi_log_format_32_t *src_efi_fmt_32 = (xfs_efi_log_format_32_t *)buf; - - dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; - dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; - dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; - dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; - for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { - dst_efi_fmt->efi_extents[i].ext_start = - src_efi_fmt_32->efi_extents[i].ext_start; - dst_efi_fmt->efi_extents[i].ext_len = - src_efi_fmt_32->efi_extents[i].ext_len; - } - return 0; - } else if (len == len64) { - xfs_efi_log_format_64_t *src_efi_fmt_64 = (xfs_efi_log_format_64_t *)buf; - - dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; - dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; - dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; - dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; - for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { - dst_efi_fmt->efi_extents[i].ext_start = - src_efi_fmt_64->efi_extents[i].ext_start; - dst_efi_fmt->efi_extents[i].ext_len = - src_efi_fmt_64->efi_extents[i].ext_len; - } - return 0; - } - fprintf(stderr, _("%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n"), - progname, len, len32, len64, nextents); - return 1; -} diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index f95f4aa..4d92c3b 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -372,66 +372,6 @@ xlog_recover_print_inode( } } -STATIC void -xlog_recover_print_efd( - xlog_recover_item_t *item) -{ - xfs_efd_log_format_t *f; - - f = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; - /* - * An xfs_efd_log_format structure contains a variable length array - * as the last field. - * Each element is of size xfs_extent_32_t or xfs_extent_64_t. - * However, the extents are never used and won't be printed. - */ - printf(_(" EFD: #regs: %d num_extents: %d id: 0x%llx\n"), - f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); -} - - -STATIC void -xlog_recover_print_efi( - xlog_recover_item_t *item) -{ - xfs_efi_log_format_t *f, *src_f; - xfs_extent_t *ex; - int i; - uint src_len, dst_len; - - src_f = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; - src_len = item->ri_buf[0].i_len; - /* - * An xfs_efi_log_format structure contains a variable length array - * as the last field. - * Each element is of size xfs_extent_32_t or xfs_extent_64_t. - * Need to convert to native format. - */ - dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); - if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { - fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"), progname); - exit(1); - } - if (xfs_efi_copy_format((char*)src_f, src_len, f, 0)) { - free(f); - return; - } - - printf(_(" EFI: #regs:%d num_extents:%d id:0x%llx\n"), - f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); - ex = f->efi_extents; - printf(" "); - for (i=0; i< f->efi_nextents; i++) { - printf("(s: 0x%llx, l: %d) ", - (unsigned long long)ex->ext_start, ex->ext_len); - if (i % 4 == 3) - printf("\n"); - ex++; - } - if (i % 4 != 0) - printf("\n"); - free(f); -} STATIC void xlog_recover_print_icreate( diff --git a/logprint/log_redo.c b/logprint/log_redo.c new file mode 100644 index 0000000..a9608f0 --- /dev/null +++ b/logprint/log_redo.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. + * Copyright (c) 2016 Oracle, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libxfs.h" +#include "libxlog.h" + +#include "logprint.h" + +/* Extent Free Items */ + +int +xfs_efi_copy_format( + char *buf, + uint len, + struct xfs_efi_log_format *dst_efi_fmt, + int continued) +{ + uint i; + uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents; + uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t); + uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t); + uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t); + + if (len == dst_len || continued) { + memcpy((char *)dst_efi_fmt, buf, len); + return 0; + } else if (len == len32) { + xfs_efi_log_format_32_t *src_efi_fmt_32 = (xfs_efi_log_format_32_t *)buf; + + dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; + dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; + dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; + dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; + for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { + dst_efi_fmt->efi_extents[i].ext_start = + src_efi_fmt_32->efi_extents[i].ext_start; + dst_efi_fmt->efi_extents[i].ext_len = + src_efi_fmt_32->efi_extents[i].ext_len; + } + return 0; + } else if (len == len64) { + xfs_efi_log_format_64_t *src_efi_fmt_64 = (xfs_efi_log_format_64_t *)buf; + + dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; + dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; + dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; + dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; + for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { + dst_efi_fmt->efi_extents[i].ext_start = + src_efi_fmt_64->efi_extents[i].ext_start; + dst_efi_fmt->efi_extents[i].ext_len = + src_efi_fmt_64->efi_extents[i].ext_len; + } + return 0; + } + fprintf(stderr, _("%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n"), + progname, len, len32, len64, nextents); + return 1; +} + +int +xlog_print_trans_efi( + char **ptr, + uint src_len, + int continued) +{ + xfs_efi_log_format_t *src_f, *f = NULL; + uint dst_len; + xfs_extent_t *ex; + int i; + int error = 0; + int core_size = offsetof(xfs_efi_log_format_t, efi_extents); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * xfs_efi_log_format_t structure + */ + if ((src_f = (xfs_efi_log_format_t *)malloc(src_len)) == NULL) { + fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); + exit(1); + } + memmove((char*)src_f, *ptr, src_len); + *ptr += src_len; + + /* convert to native format */ + dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); + + if (continued && src_len < core_size) { + printf(_("EFI: Not enough data to decode further\n")); + error = 1; + goto error; + } + + if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { + fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); + exit(1); + } + if (xfs_efi_copy_format((char*)src_f, src_len, f, continued)) { + error = 1; + goto error; + } + + printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"), + f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); + + if (continued) { + printf(_("EFI free extent data skipped (CONTINUE set, no space)\n")); + goto error; + } + + ex = f->efi_extents; + for (i=0; i < f->efi_nextents; i++) { + printf("(s: 0x%llx, l: %d) ", + (unsigned long long)ex->ext_start, ex->ext_len); + if (i % 4 == 3) printf("\n"); + ex++; + } + if (i % 4 != 0) printf("\n"); +error: + free(src_f); + free(f); + return error; +} /* xlog_print_trans_efi */ + +void +xlog_recover_print_efi( + xlog_recover_item_t *item) +{ + xfs_efi_log_format_t *f, *src_f; + xfs_extent_t *ex; + int i; + uint src_len, dst_len; + + src_f = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; + src_len = item->ri_buf[0].i_len; + /* + * An xfs_efi_log_format structure contains a variable length array + * as the last field. + * Each element is of size xfs_extent_32_t or xfs_extent_64_t. + * Need to convert to native format. + */ + dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); + if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { + fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"), progname); + exit(1); + } + if (xfs_efi_copy_format((char*)src_f, src_len, f, 0)) { + free(f); + return; + } + + printf(_(" EFI: #regs:%d num_extents:%d id:0x%llx\n"), + f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); + ex = f->efi_extents; + printf(" "); + for (i=0; i< f->efi_nextents; i++) { + printf("(s: 0x%llx, l: %d) ", + (unsigned long long)ex->ext_start, ex->ext_len); + if (i % 4 == 3) + printf("\n"); + ex++; + } + if (i % 4 != 0) + printf("\n"); + free(f); +} + +int +xlog_print_trans_efd(char **ptr, uint len) +{ + xfs_efd_log_format_t *f; + xfs_efd_log_format_t lbuf; + /* size without extents at end */ + uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * xfs_efd_log_format_t structure + */ + memmove(&lbuf, *ptr, MIN(core_size, len)); + f = &lbuf; + *ptr += len; + if (len >= core_size) { + printf(_("EFD: #regs: %d num_extents: %d id: 0x%llx\n"), + f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); + + /* don't print extents as they are not used */ + + return 0; + } else { + printf(_("EFD: Not enough data to decode further\n")); + return 1; + } +} /* xlog_print_trans_efd */ + +void +xlog_recover_print_efd( + xlog_recover_item_t *item) +{ + xfs_efd_log_format_t *f; + + f = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; + /* + * An xfs_efd_log_format structure contains a variable length array + * as the last field. + * Each element is of size xfs_extent_32_t or xfs_extent_64_t. + * However, the extents are never used and won't be printed. + */ + printf(_(" EFD: #regs: %d num_extents: %d id: 0x%llx\n"), + f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); +} diff --git a/logprint/logprint.h b/logprint/logprint.h index 018af81..517e852 100644 --- a/logprint/logprint.h +++ b/logprint/logprint.h @@ -45,6 +45,10 @@ extern void print_stars(void); extern xfs_inode_log_format_t * xfs_inode_item_format_convert(char *, uint, xfs_inode_log_format_t *); -extern int xfs_efi_copy_format(char *, uint, xfs_efi_log_format_t *, int); + +extern int xlog_print_trans_efi(char **ptr, uint src_len, int continued); +extern void xlog_recover_print_efi(xlog_recover_item_t *item); +extern int xlog_print_trans_efd(char **ptr, uint len); +extern void xlog_recover_print_efd(xlog_recover_item_t *item); #endif /* LOGPRINT_H */ From darrick.wong@oracle.com Thu Jun 16 20:31:58 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B6C72806C for ; Thu, 16 Jun 2016 20:31:58 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 233E9AC002 for ; Thu, 16 Jun 2016 18:31:58 -0700 (PDT) X-ASG-Debug-ID: 1466127114-04cbb01fec69d90001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id VgvFyB4niMUjlGHy (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:31:55 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Voce014389 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:50 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VolS026490 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:50 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VnYl026794; Fri, 17 Jun 2016 01:31:49 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:49 -0700 Subject: [PATCH 010/145] xfs_logprint: fix formatting issues with the EFI printing code From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 010/145] xfs_logprint: fix formatting issues with the EFI printing code To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:47 -0700 Message-ID: <146612710794.16048.674906502840774962.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127115 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11185 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Fix some formatting issues with the EFI handling functions. This is a purely mechanical whitespace fix, no code changes aside from adding 'static'. Signed-off-by: Darrick J. Wong --- logprint/log_redo.c | 261 ++++++++++++++++++++++++++------------------------- 1 file changed, 133 insertions(+), 128 deletions(-) diff --git a/logprint/log_redo.c b/logprint/log_redo.c index a9608f0..d60cc1b 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -23,118 +23,119 @@ /* Extent Free Items */ -int +static int xfs_efi_copy_format( char *buf, uint len, struct xfs_efi_log_format *dst_efi_fmt, int continued) { - uint i; + uint i; uint nextents = ((xfs_efi_log_format_t *)buf)->efi_nextents; - uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t); - uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t); - uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t); - - if (len == dst_len || continued) { - memcpy((char *)dst_efi_fmt, buf, len); - return 0; - } else if (len == len32) { - xfs_efi_log_format_32_t *src_efi_fmt_32 = (xfs_efi_log_format_32_t *)buf; - - dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; - dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; - dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; - dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; - for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { - dst_efi_fmt->efi_extents[i].ext_start = - src_efi_fmt_32->efi_extents[i].ext_start; - dst_efi_fmt->efi_extents[i].ext_len = - src_efi_fmt_32->efi_extents[i].ext_len; - } - return 0; - } else if (len == len64) { - xfs_efi_log_format_64_t *src_efi_fmt_64 = (xfs_efi_log_format_64_t *)buf; - - dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; - dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; - dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; - dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; - for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { - dst_efi_fmt->efi_extents[i].ext_start = - src_efi_fmt_64->efi_extents[i].ext_start; - dst_efi_fmt->efi_extents[i].ext_len = - src_efi_fmt_64->efi_extents[i].ext_len; - } - return 0; - } + uint dst_len = sizeof(xfs_efi_log_format_t) + (nextents - 1) * sizeof(xfs_extent_t); + uint len32 = sizeof(xfs_efi_log_format_32_t) + (nextents - 1) * sizeof(xfs_extent_32_t); + uint len64 = sizeof(xfs_efi_log_format_64_t) + (nextents - 1) * sizeof(xfs_extent_64_t); + + if (len == dst_len || continued) { + memcpy((char *)dst_efi_fmt, buf, len); + return 0; + } else if (len == len32) { + xfs_efi_log_format_32_t *src_efi_fmt_32 = (xfs_efi_log_format_32_t *)buf; + + dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; + dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; + dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; + dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; + for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { + dst_efi_fmt->efi_extents[i].ext_start = + src_efi_fmt_32->efi_extents[i].ext_start; + dst_efi_fmt->efi_extents[i].ext_len = + src_efi_fmt_32->efi_extents[i].ext_len; + } + return 0; + } else if (len == len64) { + xfs_efi_log_format_64_t *src_efi_fmt_64 = (xfs_efi_log_format_64_t *)buf; + + dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; + dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; + dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; + dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; + for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { + dst_efi_fmt->efi_extents[i].ext_start = + src_efi_fmt_64->efi_extents[i].ext_start; + dst_efi_fmt->efi_extents[i].ext_len = + src_efi_fmt_64->efi_extents[i].ext_len; + } + return 0; + } fprintf(stderr, _("%s: bad size of efi format: %u; expected %u or %u; nextents = %u\n"), progname, len, len32, len64, nextents); - return 1; + return 1; } int xlog_print_trans_efi( - char **ptr, - uint src_len, - int continued) + char **ptr, + uint src_len, + int continued) { - xfs_efi_log_format_t *src_f, *f = NULL; - uint dst_len; - xfs_extent_t *ex; - int i; - int error = 0; - int core_size = offsetof(xfs_efi_log_format_t, efi_extents); - - /* - * memmove to ensure 8-byte alignment for the long longs in - * xfs_efi_log_format_t structure - */ - if ((src_f = (xfs_efi_log_format_t *)malloc(src_len)) == NULL) { - fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); - exit(1); - } - memmove((char*)src_f, *ptr, src_len); - *ptr += src_len; - - /* convert to native format */ - dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); - - if (continued && src_len < core_size) { - printf(_("EFI: Not enough data to decode further\n")); - error = 1; - goto error; - } - - if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { - fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); - exit(1); - } - if (xfs_efi_copy_format((char*)src_f, src_len, f, continued)) { - error = 1; - goto error; - } - - printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"), - f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); - - if (continued) { - printf(_("EFI free extent data skipped (CONTINUE set, no space)\n")); - goto error; - } - - ex = f->efi_extents; - for (i=0; i < f->efi_nextents; i++) { - printf("(s: 0x%llx, l: %d) ", - (unsigned long long)ex->ext_start, ex->ext_len); - if (i % 4 == 3) printf("\n"); - ex++; - } - if (i % 4 != 0) printf("\n"); + xfs_efi_log_format_t *src_f, *f = NULL; + uint dst_len; + xfs_extent_t *ex; + int i; + int error = 0; + int core_size = offsetof(xfs_efi_log_format_t, efi_extents); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * xfs_efi_log_format_t structure + */ + if ((src_f = (xfs_efi_log_format_t *)malloc(src_len)) == NULL) { + fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); + exit(1); + } + memmove((char*)src_f, *ptr, src_len); + *ptr += src_len; + + /* convert to native format */ + dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); + + if (continued && src_len < core_size) { + printf(_("EFI: Not enough data to decode further\n")); + error = 1; + goto error; + } + + if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { + fprintf(stderr, _("%s: xlog_print_trans_efi: malloc failed\n"), progname); + exit(1); + } + if (xfs_efi_copy_format((char*)src_f, src_len, f, continued)) { + error = 1; + goto error; + } + + printf(_("EFI: #regs: %d num_extents: %d id: 0x%llx\n"), + f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); + + if (continued) { + printf(_("EFI free extent data skipped (CONTINUE set, no space)\n")); + goto error; + } + + ex = f->efi_extents; + for (i=0; i < f->efi_nextents; i++) { + printf("(s: 0x%llx, l: %d) ", + (unsigned long long)ex->ext_start, ex->ext_len); + if (i % 4 == 3) printf("\n"); + ex++; + } + if (i % 4 != 0) + printf("\n"); error: - free(src_f); - free(f); - return error; + free(src_f); + free(f); + return error; } /* xlog_print_trans_efi */ void @@ -154,18 +155,20 @@ xlog_recover_print_efi( * Each element is of size xfs_extent_32_t or xfs_extent_64_t. * Need to convert to native format. */ - dst_len = sizeof(xfs_efi_log_format_t) + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); + dst_len = sizeof(xfs_efi_log_format_t) + + (src_f->efi_nextents - 1) * sizeof(xfs_extent_t); if ((f = (xfs_efi_log_format_t *)malloc(dst_len)) == NULL) { - fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"), progname); - exit(1); + fprintf(stderr, _("%s: xlog_recover_print_efi: malloc failed\n"), + progname); + exit(1); } if (xfs_efi_copy_format((char*)src_f, src_len, f, 0)) { - free(f); - return; + free(f); + return; } - printf(_(" EFI: #regs:%d num_extents:%d id:0x%llx\n"), - f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); + printf(_(" EFI: #regs:%d num_extents:%d id:0x%llx\n"), + f->efi_size, f->efi_nextents, (unsigned long long)f->efi_id); ex = f->efi_extents; printf(" "); for (i=0; i< f->efi_nextents; i++) { @@ -183,29 +186,30 @@ xlog_recover_print_efi( int xlog_print_trans_efd(char **ptr, uint len) { - xfs_efd_log_format_t *f; - xfs_efd_log_format_t lbuf; - /* size without extents at end */ - uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t); - - /* - * memmove to ensure 8-byte alignment for the long longs in - * xfs_efd_log_format_t structure - */ - memmove(&lbuf, *ptr, MIN(core_size, len)); - f = &lbuf; - *ptr += len; - if (len >= core_size) { - printf(_("EFD: #regs: %d num_extents: %d id: 0x%llx\n"), - f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); - - /* don't print extents as they are not used */ - - return 0; - } else { - printf(_("EFD: Not enough data to decode further\n")); + xfs_efd_log_format_t *f; + xfs_efd_log_format_t lbuf; + /* size without extents at end */ + uint core_size = sizeof(xfs_efd_log_format_t) - sizeof(xfs_extent_t); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * xfs_efd_log_format_t structure + */ + memmove(&lbuf, *ptr, MIN(core_size, len)); + f = &lbuf; + *ptr += len; + if (len >= core_size) { + printf(_("EFD: #regs: %d num_extents: %d id: 0x%llx\n"), + f->efd_size, f->efd_nextents, + (unsigned long long)f->efd_efi_id); + + /* don't print extents as they are not used */ + + return 0; + } else { + printf(_("EFD: Not enough data to decode further\n")); return 1; - } + } } /* xlog_print_trans_efd */ void @@ -221,6 +225,7 @@ xlog_recover_print_efd( * Each element is of size xfs_extent_32_t or xfs_extent_64_t. * However, the extents are never used and won't be printed. */ - printf(_(" EFD: #regs: %d num_extents: %d id: 0x%llx\n"), - f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); + printf(_(" EFD: #regs: %d num_extents: %d id: 0x%llx\n"), + f->efd_size, f->efd_nextents, + (unsigned long long)f->efd_efi_id); } From darrick.wong@oracle.com Thu Jun 16 20:32:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2EE6F8078 for ; Thu, 16 Jun 2016 20:32:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id E2C0E8F804B for ; Thu, 16 Jun 2016 18:32:04 -0700 (PDT) X-ASG-Debug-ID: 1466127122-04bdf01e1595f70001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 94ck3CRAGOnIeqTC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:02 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1VwMx014500 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:31:58 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Vwmd025300 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:31:58 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1VtbE009935; Fri, 17 Jun 2016 01:31:56 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:31:55 -0700 Subject: [PATCH 011/145] man: document the DAX fsxattr inode flag From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 011/145] man: document the DAX fsxattr inode flag To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:31:54 -0700 Message-ID: <146612711418.16048.15527594819477737762.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127122 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 865 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Document the new inode flag in struct fsxattr for DAX. Signed-off-by: Darrick J. Wong --- man/man3/xfsctl.3 | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/man/man3/xfsctl.3 b/man/man3/xfsctl.3 index e84b829..9e7f138 100644 --- a/man/man3/xfsctl.3 +++ b/man/man3/xfsctl.3 @@ -225,6 +225,11 @@ group and so files within different directories will not interleave extents on disk. The reservation is only active while files are being created and written into the directory. .TP +.SM "Bit 15 (0x8000) \- XFS_XFLAG_DAX" +If the filesystem lives on directly accessible persistent memory, reads and +writes to this file will go straight to the persistent memory, bypassing the +page cache. +.TP .SM "Bit 31 (0x80000000) \- XFS_XFLAG_HASATTR" The file has extended attributes associated with it. .RE From darrick.wong@oracle.com Thu Jun 16 20:32:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5E5E58080 for ; Thu, 16 Jun 2016 20:32:10 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2F0278F804C for ; Thu, 16 Jun 2016 18:32:10 -0700 (PDT) X-ASG-Debug-ID: 1466127127-04cb6c542557d10001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id OrXQr9DxezIaQxTw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:08 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1W32I014806 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:03 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1W27H031837 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:03 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1W1JL026826; Fri, 17 Jun 2016 01:32:02 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:01 -0700 Subject: [PATCH 012/145] xfs: separate freelist fixing into a separate helper From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 012/145] xfs: separate freelist fixing into a separate helper To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:00 -0700 Message-ID: <146612712023.16048.11958690424572913723.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127127 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4097 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Break up xfs_free_extent() into a helper that fixes the freelist. This helper will be used subsequently to ensure the freelist during deferred rmap processing. Signed-off-by: Dave Chinner [darrick: refactor to put this at the head of the patchset] Signed-off-by: Darrick J. Wong --- libxfs/xfs_alloc.c | 82 ++++++++++++++++++++++++++++++++++------------------ libxfs/xfs_alloc.h | 2 + 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 8520f31..2998af8 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2656,55 +2656,79 @@ error0: return error; } -/* - * Free an extent. - * Just break up the extent address and hand off to xfs_free_ag_extent - * after fixing up the freelist. - */ -int /* error */ -xfs_free_extent( - xfs_trans_t *tp, /* transaction pointer */ - xfs_fsblock_t bno, /* starting block number of extent */ - xfs_extlen_t len) /* length of extent */ +/* Ensure that the freelist is at full capacity. */ +int +xfs_free_extent_fix_freelist( + struct xfs_trans *tp, + xfs_agnumber_t agno, + struct xfs_buf **agbp) { - xfs_alloc_arg_t args; - int error; + xfs_alloc_arg_t args; + int error; - ASSERT(len != 0); memset(&args, 0, sizeof(xfs_alloc_arg_t)); args.tp = tp; args.mp = tp->t_mountp; + args.agno = agno; /* * validate that the block number is legal - the enables us to detect * and handle a silent filesystem corruption rather than crashing. */ - args.agno = XFS_FSB_TO_AGNO(args.mp, bno); if (args.agno >= args.mp->m_sb.sb_agcount) return -EFSCORRUPTED; - args.agbno = XFS_FSB_TO_AGBNO(args.mp, bno); - if (args.agbno >= args.mp->m_sb.sb_agblocks) - return -EFSCORRUPTED; - args.pag = xfs_perag_get(args.mp, args.agno); ASSERT(args.pag); error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); if (error) - goto error0; + goto out; + + *agbp = args.agbp; +out: + xfs_perag_put(args.pag); + return error; +} + +/* + * Free an extent. + * Just break up the extent address and hand off to xfs_free_ag_extent + * after fixing up the freelist. + */ +int /* error */ +xfs_free_extent( + struct xfs_trans *tp, /* transaction pointer */ + xfs_fsblock_t bno, /* starting block number of extent */ + xfs_extlen_t len) /* length of extent */ +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_buf *agbp; + xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno); + xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); + int error; + + ASSERT(len != 0); + + error = xfs_free_extent_fix_freelist(tp, agno, &agbp); + if (error) + return error; + + XFS_WANT_CORRUPTED_GOTO(mp, agbno < mp->m_sb.sb_agblocks, err); /* validate the extent size is legal now we have the agf locked */ - if (args.agbno + len > - be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) { - error = -EFSCORRUPTED; - goto error0; - } + XFS_WANT_CORRUPTED_GOTO(mp, + agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), + err); - error = xfs_free_ag_extent(tp, args.agbp, args.agno, args.agbno, len, 0); - if (!error) - xfs_extent_busy_insert(tp, args.agno, args.agbno, len, 0); -error0: - xfs_perag_put(args.pag); + error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0); + if (error) + goto err; + + xfs_extent_busy_insert(tp, agno, agbno, len, 0); + return 0; + +err: + xfs_trans_brelse(tp, agbp); return error; } diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 92a66ba..cf268b2 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -229,5 +229,7 @@ xfs_alloc_get_rec( int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, int flags, struct xfs_buf **bpp); int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); +int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, + struct xfs_buf **agbp); #endif /* __XFS_ALLOC_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:32:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4109E8089 for ; Thu, 16 Jun 2016 20:32:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C007BAC002 for ; Thu, 16 Jun 2016 18:32:12 -0700 (PDT) X-ASG-Debug-ID: 1466127130-04bdf01e1795f90001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id mcD9kusdpnRCXfbE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1W91h001885 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:09 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1W86w020746 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:08 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1W8m8022226; Fri, 17 Jun 2016 01:32:08 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:07 -0700 Subject: [PATCH 013/145] xfs: convert list of extents to free into a regular list From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 013/145] xfs: convert list of extents to free into a regular list To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:06 -0700 Message-ID: <146612712636.16048.4965436384661239506.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127130 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6274 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines In struct xfs_bmap_free, convert the open-coded free extent list to a regular list, then use list_sort to sort it prior to processing. Signed-off-by: Darrick J. Wong --- libxfs/init.c | 3 ++- libxfs/libxfs_priv.h | 3 +-- libxfs/util.c | 10 +++++----- libxfs/xfs_bmap.c | 39 +++++++++++---------------------------- libxfs/xfs_bmap.h | 14 ++++++++------ 5 files changed, 27 insertions(+), 42 deletions(-) diff --git a/libxfs/init.c b/libxfs/init.c index e04b6e0..67c3b30 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -417,7 +417,8 @@ manage_zones(int release) xfs_btree_cur_zone = kmem_zone_init( sizeof(xfs_btree_cur_t), "xfs_btree_cur"); xfs_bmap_free_item_zone = kmem_zone_init( - sizeof(xfs_bmap_free_item_t), "xfs_bmap_free_item"); + sizeof(struct xfs_bmap_free_item), + "xfs_bmap_free_item"); xfs_log_item_desc_zone = kmem_zone_init( sizeof(struct xfs_log_item_desc), "xfs_log_item_desc"); xfs_dir_startup(); diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index ecd75e7..ba16544 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -466,8 +466,7 @@ struct xfs_buftarg; int xfs_attr_rmtval_get(struct xfs_da_args *); /* xfs_bmap.c */ -void xfs_bmap_del_free(struct xfs_bmap_free *, struct xfs_bmap_free_item *, - struct xfs_bmap_free_item *); +void xfs_bmap_del_free(struct xfs_bmap_free *, struct xfs_bmap_free_item *); /* xfs_mount.c */ int xfs_initialize_perag_data(struct xfs_mount *, xfs_agnumber_t); diff --git a/libxfs/util.c b/libxfs/util.c index 2e826c9..f37b396 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -480,20 +480,20 @@ libxfs_bmap_finish( struct xfs_bmap_free *flist, struct xfs_inode *ip) { - xfs_bmap_free_item_t *free; /* free extent list item */ - xfs_bmap_free_item_t *next; /* next item on free list */ + struct xfs_bmap_free_item *free; /* free extent list item */ int error; if (flist->xbf_count == 0) return 0; - for (free = flist->xbf_first; free != NULL; free = next) { - next = free->xbfi_next; + while (!list_empty(&flist->xbf_flist)) { + free = list_first_entry(&flist->xbf_flist, + struct xfs_bmap_free_item, xbfi_list); error = xfs_free_extent(*tp, free->xbfi_startblock, free->xbfi_blockcount); if (error) return error; - xfs_bmap_del_free(flist, NULL, free); + xfs_bmap_del_free(flist, free); } return 0; } diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index c2a2c53..65de5ad 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -567,9 +567,7 @@ xfs_bmap_add_free( xfs_fsblock_t bno, /* fs block number of extent */ xfs_filblks_t len) /* length of extent */ { - xfs_bmap_free_item_t *cur; /* current (next) element */ - xfs_bmap_free_item_t *new; /* new element */ - xfs_bmap_free_item_t *prev; /* previous element */ + struct xfs_bmap_free_item *new; /* new element */ #ifdef DEBUG xfs_agnumber_t agno; xfs_agblock_t agbno; @@ -589,17 +587,7 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; - for (prev = NULL, cur = flist->xbf_first; - cur != NULL; - prev = cur, cur = cur->xbfi_next) { - if (cur->xbfi_startblock >= bno) - break; - } - if (prev) - prev->xbfi_next = new; - else - flist->xbf_first = new; - new->xbfi_next = cur; + list_add(&new->xbfi_list, &flist->xbf_flist); flist->xbf_count++; } @@ -609,14 +597,10 @@ xfs_bmap_add_free( */ void xfs_bmap_del_free( - xfs_bmap_free_t *flist, /* free item list header */ - xfs_bmap_free_item_t *prev, /* previous item on list, if any */ - xfs_bmap_free_item_t *free) /* list item to be freed */ + struct xfs_bmap_free *flist, /* free item list header */ + struct xfs_bmap_free_item *free) /* list item to be freed */ { - if (prev) - prev->xbfi_next = free->xbfi_next; - else - flist->xbf_first = free->xbfi_next; + list_del(&free->xbfi_list); flist->xbf_count--; kmem_zone_free(xfs_bmap_free_item_zone, free); } @@ -626,17 +610,16 @@ xfs_bmap_del_free( */ void xfs_bmap_cancel( - xfs_bmap_free_t *flist) /* list of bmap_free_items */ + struct xfs_bmap_free *flist) /* list of bmap_free_items */ { - xfs_bmap_free_item_t *free; /* free list item */ - xfs_bmap_free_item_t *next; + struct xfs_bmap_free_item *free; /* free list item */ if (flist->xbf_count == 0) return; - ASSERT(flist->xbf_first != NULL); - for (free = flist->xbf_first; free; free = next) { - next = free->xbfi_next; - xfs_bmap_del_free(flist, NULL, free); + while (!list_empty(&flist->xbf_flist)) { + free = list_first_entry(&flist->xbf_flist, + struct xfs_bmap_free_item, xbfi_list); + xfs_bmap_del_free(flist, free); } ASSERT(flist->xbf_count == 0); } diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index 6485403..c165b2d 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -62,12 +62,12 @@ struct xfs_bmalloca { * List of extents to be free "later". * The list is kept sorted on xbf_startblock. */ -typedef struct xfs_bmap_free_item +struct xfs_bmap_free_item { xfs_fsblock_t xbfi_startblock;/* starting fs block number */ xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */ - struct xfs_bmap_free_item *xbfi_next; /* link to next entry */ -} xfs_bmap_free_item_t; + struct list_head xbfi_list; +}; /* * Header for free extent list. @@ -85,7 +85,7 @@ typedef struct xfs_bmap_free_item */ typedef struct xfs_bmap_free { - xfs_bmap_free_item_t *xbf_first; /* list of to-be-free extents */ + struct list_head xbf_flist; /* list of to-be-free extents */ int xbf_count; /* count of items on list */ int xbf_low; /* alloc in low mode */ } xfs_bmap_free_t; @@ -141,8 +141,10 @@ static inline int xfs_bmapi_aflag(int w) static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp) { - ((flp)->xbf_first = NULL, (flp)->xbf_count = 0, \ - (flp)->xbf_low = 0, *(fbp) = NULLFSBLOCK); + INIT_LIST_HEAD(&flp->xbf_flist); + flp->xbf_count = 0; + flp->xbf_low = 0; + *fbp = NULLFSBLOCK; } /* From darrick.wong@oracle.com Thu Jun 16 20:32:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B04108091 for ; Thu, 16 Jun 2016 20:32:18 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3692EAC001 for ; Thu, 16 Jun 2016 18:32:18 -0700 (PDT) X-ASG-Debug-ID: 1466127136-04cb6c542457d20001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id j5RfEIUNt0uHRlpM (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:16 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1WEWq001922 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:32:15 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1WEQ3025892 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:32:14 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1WEXP031003; Fri, 17 Jun 2016 01:32:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:13 -0700 Subject: [PATCH 014/145] xfs: create a standard btree size calculator code From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 014/145] xfs: create a standard btree size calculator code To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:12 -0700 Message-ID: <146612713249.16048.10611335362447244031.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127136 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1969 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a helper to generate AG btree height calculator functions. This will be used (much) later when we get to the refcount btree. v2: Use a helper function instead of a macro. v3: We can (theoretically) store more than 2^32 records in a btree, so widen the fields to accept that. v4: Don't modify xfs_bmap_worst_indlen; the purpose of /that/ function is to estimate the worst-case number of blocks needed for a bmbt expansion, not to calculate the space required to store nr records. Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.c | 27 +++++++++++++++++++++++++++ libxfs/xfs_btree.h | 3 +++ 2 files changed, 30 insertions(+) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 1448fd6..27e58b2 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -4152,3 +4152,30 @@ xfs_btree_sblock_verify( return true; } + +/* + * Calculate the number of blocks needed to store a given number of records + * in a short-format (per-AG metadata) btree. + */ +xfs_extlen_t +xfs_btree_calc_size( + struct xfs_mount *mp, + uint *limits, + unsigned long long len) +{ + int level; + int maxrecs; + xfs_extlen_t rval; + + maxrecs = limits[0]; + for (level = 0, rval = 0; len > 0; level++) { + len += maxrecs - 1; + do_div(len, maxrecs); + rval += len; + if (len == 1) + return rval; + if (level == 0) + maxrecs = limits[1]; + } + return rval; +} diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 9a88839..b330f19 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -475,4 +475,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block) bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp); bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); +xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, + unsigned long long len); + #endif /* __XFS_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:32:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4C1C98095 for ; Thu, 16 Jun 2016 20:32:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id B8C20AC003 for ; Thu, 16 Jun 2016 18:32:24 -0700 (PDT) X-ASG-Debug-ID: 1466127142-04cbb01fee69e60001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ELGHDP6WYe4fpkFU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:22 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1WKf7001980 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:21 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WKZ9027506 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:20 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WKsA026962; Fri, 17 Jun 2016 01:32:20 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:19 -0700 Subject: [PATCH 015/145] xfs: refactor btree maxlevels computation From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 015/145] xfs: refactor btree maxlevels computation To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:18 -0700 Message-ID: <146612713862.16048.9572556591745823314.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127142 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3900 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a common function to calculate the maximum height of a per-AG btree. This will eventually be used by the rmapbt and refcountbt code to calculate appropriate maxlevels values for each. This is important because the verifiers and the transaction block reservations depend on accurate estimates of many blocks are needed to satisfy a btree split. We were mistakenly using the max bnobt height for all the btrees, which creates a dangerous situation since the larger records and keys in an rmapbt make it very possible that the rmapbt will be taller than the bnobt and so we can run out of transaction block reservation. Signed-off-by: Darrick J. Wong --- libxfs/xfs_alloc.c | 15 ++------------- libxfs/xfs_btree.c | 19 +++++++++++++++++++ libxfs/xfs_btree.h | 2 ++ libxfs/xfs_ialloc.c | 19 +++++-------------- 4 files changed, 28 insertions(+), 27 deletions(-) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 2998af8..7276419 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -1835,19 +1835,8 @@ void xfs_alloc_compute_maxlevels( xfs_mount_t *mp) /* file system mount structure */ { - int level; - uint maxblocks; - uint maxleafents; - int minleafrecs; - int minnoderecs; - - maxleafents = (mp->m_sb.sb_agblocks + 1) / 2; - minleafrecs = mp->m_alloc_mnr[0]; - minnoderecs = mp->m_alloc_mnr[1]; - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; - for (level = 1; maxblocks > 1; level++) - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; - mp->m_ag_maxlevels = level; + mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr, + (mp->m_sb.sb_agblocks + 1) / 2); } /* diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 27e58b2..623841f 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -4154,6 +4154,25 @@ xfs_btree_sblock_verify( } /* + * Calculate the number of btree levels needed to store a given number of + * records in a short-format btree. + */ +uint +xfs_btree_compute_maxlevels( + struct xfs_mount *mp, + uint *limits, + unsigned long len) +{ + uint level; + unsigned long maxblocks; + + maxblocks = (len + limits[0] - 1) / limits[0]; + for (level = 1; maxblocks > 1; level++) + maxblocks = (maxblocks + limits[1] - 1) / limits[1]; + return level; +} + +/* * Calculate the number of blocks needed to store a given number of records * in a short-format (per-AG metadata) btree. */ diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index b330f19..b955e5d 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -477,5 +477,7 @@ bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, unsigned long long len); +uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, + unsigned long len); #endif /* __XFS_BTREE_H__ */ diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 4f0e4ee..249512b 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -2388,20 +2388,11 @@ void xfs_ialloc_compute_maxlevels( xfs_mount_t *mp) /* file system mount structure */ { - int level; - uint maxblocks; - uint maxleafents; - int minleafrecs; - int minnoderecs; - - maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >> - XFS_INODES_PER_CHUNK_LOG; - minleafrecs = mp->m_inobt_mnr[0]; - minnoderecs = mp->m_inobt_mnr[1]; - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; - for (level = 1; maxblocks > 1; level++) - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; - mp->m_in_maxlevels = level; + uint inodes; + + inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG; + mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr, + inodes); } /* From darrick.wong@oracle.com Thu Jun 16 20:32:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8D25080A5 for ; Thu, 16 Jun 2016 20:32:34 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5EC008F804B for ; Thu, 16 Jun 2016 18:32:34 -0700 (PDT) X-ASG-Debug-ID: 1466127151-04cbb01fec69ec0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id k8FP0gZCDU0LtDW1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:31 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1WQwI014989 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:32:27 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1WQq7026120 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:32:26 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1WQXM031030; Fri, 17 Jun 2016 01:32:26 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:26 -0700 Subject: [PATCH 016/145] xfs: during btree split, save new block key & ptr for future insertion From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 016/145] xfs: during btree split, save new block key & ptr for future insertion To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:24 -0700 Message-ID: <146612714473.16048.8382772114027261883.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127151 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10748 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When a btree block has to be split, we pass the new block's ptr from xfs_btree_split() back to xfs_btree_insert() via a pointer parameter; however, we pass the block's key through the cursor's record. It is a little weird to "initialize" a record from a key since the non-key attributes will have garbage values. When we go to add support for interval queries, we have to be able to pass the lowest and highest keys accessible via a pointer. There's no clean way to pass this back through the cursor's record field. Therefore, pass the key directly back to xfs_btree_insert() the same way that we pass the btree_ptr. As a bonus, we no longer need init_rec_from_key and can drop it from the codebase. Signed-off-by: Darrick J. Wong --- libxfs/xfs_alloc_btree.c | 12 ------------ libxfs/xfs_bmap_btree.c | 12 ------------ libxfs/xfs_btree.c | 44 ++++++++++++++++++++++---------------------- libxfs/xfs_btree.h | 2 -- libxfs/xfs_ialloc_btree.c | 10 ---------- 5 files changed, 22 insertions(+), 58 deletions(-) diff --git a/libxfs/xfs_alloc_btree.c b/libxfs/xfs_alloc_btree.c index 094135f..ff4bae4 100644 --- a/libxfs/xfs_alloc_btree.c +++ b/libxfs/xfs_alloc_btree.c @@ -210,17 +210,6 @@ xfs_allocbt_init_key_from_rec( } STATIC void -xfs_allocbt_init_rec_from_key( - union xfs_btree_key *key, - union xfs_btree_rec *rec) -{ - ASSERT(key->alloc.ar_startblock != 0); - - rec->alloc.ar_startblock = key->alloc.ar_startblock; - rec->alloc.ar_blockcount = key->alloc.ar_blockcount; -} - -STATIC void xfs_allocbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -404,7 +393,6 @@ static const struct xfs_btree_ops xfs_allocbt_ops = { .get_minrecs = xfs_allocbt_get_minrecs, .get_maxrecs = xfs_allocbt_get_maxrecs, .init_key_from_rec = xfs_allocbt_init_key_from_rec, - .init_rec_from_key = xfs_allocbt_init_rec_from_key, .init_rec_from_cur = xfs_allocbt_init_rec_from_cur, .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, .key_diff = xfs_allocbt_key_diff, diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 022d4b6..2ae701e 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -597,17 +597,6 @@ xfs_bmbt_init_key_from_rec( } STATIC void -xfs_bmbt_init_rec_from_key( - union xfs_btree_key *key, - union xfs_btree_rec *rec) -{ - ASSERT(key->bmbt.br_startoff != 0); - - xfs_bmbt_disk_set_allf(&rec->bmbt, be64_to_cpu(key->bmbt.br_startoff), - 0, 0, XFS_EXT_NORM); -} - -STATIC void xfs_bmbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -757,7 +746,6 @@ static const struct xfs_btree_ops xfs_bmbt_ops = { .get_minrecs = xfs_bmbt_get_minrecs, .get_dmaxrecs = xfs_bmbt_get_dmaxrecs, .init_key_from_rec = xfs_bmbt_init_key_from_rec, - .init_rec_from_key = xfs_bmbt_init_rec_from_key, .init_rec_from_cur = xfs_bmbt_init_rec_from_cur, .init_ptr_from_cur = xfs_bmbt_init_ptr_from_cur, .key_diff = xfs_bmbt_key_diff, diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 623841f..9a92c65 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -2858,10 +2858,9 @@ xfs_btree_make_block_unfull( int *index, /* new tree index */ union xfs_btree_ptr *nptr, /* new btree ptr */ struct xfs_btree_cur **ncur, /* new btree cursor */ - union xfs_btree_rec *nrec, /* new record */ + union xfs_btree_key *key, /* key of new block */ int *stat) { - union xfs_btree_key key; /* new btree key value */ int error = 0; if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && @@ -2906,13 +2905,12 @@ xfs_btree_make_block_unfull( * If this works we have to re-set our variables because we * could be in a different block now. */ - error = xfs_btree_split(cur, level, nptr, &key, ncur, stat); + error = xfs_btree_split(cur, level, nptr, key, ncur, stat); if (error || *stat == 0) return error; *index = cur->bc_ptrs[level]; - cur->bc_ops->init_rec_from_key(&key, nrec); return 0; } @@ -2925,16 +2923,16 @@ xfs_btree_insrec( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level to insert record at */ union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ - union xfs_btree_rec *recp, /* i/o: record data inserted */ + union xfs_btree_key *key, /* i/o: block key for ptrp */ struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ int *stat) /* success/failure */ { struct xfs_btree_block *block; /* btree block */ struct xfs_buf *bp; /* buffer for block */ - union xfs_btree_key key; /* btree key */ union xfs_btree_ptr nptr; /* new block ptr */ struct xfs_btree_cur *ncur; /* new btree cursor */ - union xfs_btree_rec nrec; /* new record count */ + union xfs_btree_key nkey; /* new block key */ + union xfs_btree_rec rec; /* record to insert */ int optr; /* old key/record index */ int ptr; /* key/record index */ int numrecs;/* number of records */ @@ -2943,8 +2941,14 @@ xfs_btree_insrec( int i; #endif + /* Make a key out of the record data to be inserted, and save it. */ + if (level == 0) { + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(key, &rec); + } + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); - XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp); + XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, &rec); ncur = NULL; @@ -2969,9 +2973,6 @@ xfs_btree_insrec( return 0; } - /* Make a key out of the record data to be inserted, and save it. */ - cur->bc_ops->init_key_from_rec(&key, recp); - optr = ptr; XFS_BTREE_STATS_INC(cur, insrec); @@ -2988,10 +2989,10 @@ xfs_btree_insrec( /* Check that the new entry is being inserted in the right place. */ if (ptr <= numrecs) { if (level == 0) { - ASSERT(cur->bc_ops->recs_inorder(cur, recp, + ASSERT(cur->bc_ops->recs_inorder(cur, &rec, xfs_btree_rec_addr(cur, ptr, block))); } else { - ASSERT(cur->bc_ops->keys_inorder(cur, &key, + ASSERT(cur->bc_ops->keys_inorder(cur, key, xfs_btree_key_addr(cur, ptr, block))); } } @@ -3004,7 +3005,7 @@ xfs_btree_insrec( xfs_btree_set_ptr_null(cur, &nptr); if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) { error = xfs_btree_make_block_unfull(cur, level, numrecs, - &optr, &ptr, &nptr, &ncur, &nrec, stat); + &optr, &ptr, &nptr, &ncur, &nkey, stat); if (error || *stat == 0) goto error0; } @@ -3054,7 +3055,7 @@ xfs_btree_insrec( #endif /* Now put the new data in, bump numrecs and log it. */ - xfs_btree_copy_keys(cur, kp, &key, 1); + xfs_btree_copy_keys(cur, kp, key, 1); xfs_btree_copy_ptrs(cur, pp, ptrp, 1); numrecs++; xfs_btree_set_numrecs(block, numrecs); @@ -3075,7 +3076,7 @@ xfs_btree_insrec( xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1); /* Now put the new data in, bump numrecs and log it. */ - xfs_btree_copy_recs(cur, rp, recp, 1); + xfs_btree_copy_recs(cur, rp, &rec, 1); xfs_btree_set_numrecs(block, ++numrecs); xfs_btree_log_recs(cur, bp, ptr, numrecs); #ifdef DEBUG @@ -3091,7 +3092,7 @@ xfs_btree_insrec( /* If we inserted at the start of a block, update the parents' keys. */ if (optr == 1) { - error = xfs_btree_updkey(cur, &key, level + 1); + error = xfs_btree_updkey(cur, key, level + 1); if (error) goto error0; } @@ -3101,7 +3102,7 @@ xfs_btree_insrec( * we are at the far right edge of the tree, update it. */ if (xfs_btree_is_lastrec(cur, block, level)) { - cur->bc_ops->update_lastrec(cur, block, recp, + cur->bc_ops->update_lastrec(cur, block, &rec, ptr, LASTREC_INSREC); } @@ -3111,7 +3112,7 @@ xfs_btree_insrec( */ *ptrp = nptr; if (!xfs_btree_ptr_is_null(cur, &nptr)) { - *recp = nrec; + *key = nkey; *curp = ncur; } @@ -3142,14 +3143,13 @@ xfs_btree_insert( union xfs_btree_ptr nptr; /* new block number (split result) */ struct xfs_btree_cur *ncur; /* new cursor (split result) */ struct xfs_btree_cur *pcur; /* previous level's cursor */ - union xfs_btree_rec rec; /* record to insert */ + union xfs_btree_key key; /* key of block to insert */ level = 0; ncur = NULL; pcur = cur; xfs_btree_set_ptr_null(cur, &nptr); - cur->bc_ops->init_rec_from_cur(cur, &rec); /* * Loop going up the tree, starting at the leaf level. @@ -3161,7 +3161,7 @@ xfs_btree_insert( * Insert nrec/nptr into this level of the tree. * Note if we fail, nptr will be null. */ - error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i); + error = xfs_btree_insrec(pcur, level, &nptr, &key, &ncur, &i); if (error) { if (pcur != cur) xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index b955e5d..b99c018 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -158,8 +158,6 @@ struct xfs_btree_ops { /* init values of btree structures */ void (*init_key_from_rec)(union xfs_btree_key *key, union xfs_btree_rec *rec); - void (*init_rec_from_key)(union xfs_btree_key *key, - union xfs_btree_rec *rec); void (*init_rec_from_cur)(struct xfs_btree_cur *cur, union xfs_btree_rec *rec); void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c index 0a7d985..cd61419 100644 --- a/libxfs/xfs_ialloc_btree.c +++ b/libxfs/xfs_ialloc_btree.c @@ -145,14 +145,6 @@ xfs_inobt_init_key_from_rec( } STATIC void -xfs_inobt_init_rec_from_key( - union xfs_btree_key *key, - union xfs_btree_rec *rec) -{ - rec->inobt.ir_startino = key->inobt.ir_startino; -} - -STATIC void xfs_inobt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -313,7 +305,6 @@ static const struct xfs_btree_ops xfs_inobt_ops = { .get_minrecs = xfs_inobt_get_minrecs, .get_maxrecs = xfs_inobt_get_maxrecs, .init_key_from_rec = xfs_inobt_init_key_from_rec, - .init_rec_from_key = xfs_inobt_init_rec_from_key, .init_rec_from_cur = xfs_inobt_init_rec_from_cur, .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, @@ -335,7 +326,6 @@ static const struct xfs_btree_ops xfs_finobt_ops = { .get_minrecs = xfs_inobt_get_minrecs, .get_maxrecs = xfs_inobt_get_maxrecs, .init_key_from_rec = xfs_inobt_init_key_from_rec, - .init_rec_from_key = xfs_inobt_init_rec_from_key, .init_rec_from_cur = xfs_inobt_init_rec_from_cur, .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, From darrick.wong@oracle.com Thu Jun 16 20:32:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 954048029 for ; Thu, 16 Jun 2016 20:32:39 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 474DB8F804B for ; Thu, 16 Jun 2016 18:32:39 -0700 (PDT) X-ASG-Debug-ID: 1466127154-04bdf01e1595fd0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id cB8Fl9XL8ro9R3Zu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:35 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1WXaG002027 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:34 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WXgm000331 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:33 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WWbS022297; Fri, 17 Jun 2016 01:32:33 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:32 -0700 Subject: [PATCH 017/145] xfs: support btrees with overlapping intervals for keys From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 017/145] xfs: support btrees with overlapping intervals for keys To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:30 -0700 Message-ID: <146612715094.16048.7140890681695021236.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127155 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 24791 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On a filesystem with both reflink and reverse mapping enabled, it's possible to have multiple rmap records referring to the same blocks on disk. When overlapping intervals are possible, querying a classic btree to find all records intersecting a given interval is inefficient because we cannot use the left side of the search interval to filter out non-matching records the same way that we can use the existing btree key to filter out records coming after the right side of the search interval. This will become important once we want to use the rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl. (For the non-overlapping case, we can perform such queries trivially by starting at the left side of the interval and walking the tree until we pass the right side.) Therefore, extend the btree code to come closer to supporting intervals as a first-class record attribute. This involves widening the btree node's key space to store both the lowest key reachable via the node pointer (as the btree does now) and the highest key reachable via the same pointer and teaching the btree modifying functions to keep the highest-key records up to date. This behavior can be turned on via a new btree ops flag so that btrees that cannot store overlapping intervals don't pay the overhead costs in terms of extra code and disk format changes. v2: When we're deleting a record in a btree that supports overlapped interval records and the deletion results in two btree blocks being joined, we defer updating the high/low keys until after all possible joining (at higher levels in the tree) have finished. At this point, the btree pointers at all levels have been updated to remove the empty blocks and we can update the low and high keys. When we're doing this, we must be careful to update the keys of all node pointers up to the root instead of stopping at the first set of keys that don't need updating. This is because it's possible for a single deletion to cause joining of multiple levels of tree, and so we need to update everything going back to the root. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 2 libxfs/xfs_btree.c | 379 ++++++++++++++++++++++++++++++++++++++++++++++----- libxfs/xfs_btree.h | 16 ++ 3 files changed, 361 insertions(+), 36 deletions(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 423772f..aea41bc 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -166,6 +166,8 @@ #define trace_xfs_extlist(a,b,c,d) ((void) 0) #define trace_xfs_bunmap(a,b,c,d,e) ((void) 0) +#define trace_xfs_btree_updkeys(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 9a92c65..7fa0226 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -48,6 +48,11 @@ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] +struct xfs_btree_double_key { + union xfs_btree_key low; + union xfs_btree_key high; +}; + STATIC int /* error (0 or EFSCORRUPTED) */ xfs_btree_check_lblock( struct xfs_btree_cur *cur, /* btree cursor */ @@ -424,6 +429,30 @@ xfs_btree_dup_cursor( * into a btree block (xfs_btree_*_offset) or return a pointer to the given * record, key or pointer (xfs_btree_*_addr). Note that all addressing * inside the btree block is done using indices starting at one, not zero! + * + * If XFS_BTREE_OVERLAPPING is set, then this btree supports keys containing + * overlapping intervals. In such a tree, records are still sorted lowest to + * highest and indexed by the smallest key value that refers to the record. + * However, nodes are different: each pointer has two associated keys -- one + * indexing the lowest key available in the block(s) below (the same behavior + * as the key in a regular btree) and another indexing the highest key + * available in the block(s) below. Because records are /not/ sorted by the + * highest key, all leaf block updates require us to compute the highest key + * that matches any record in the leaf and to recursively update the high keys + * in the nodes going further up in the tree, if necessary. Nodes look like + * this: + * + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ + * Non-Leaf: | header | lo1 | hi1 | lo2 | hi2 | ... | ptr 1 | ptr 2 | ... | + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ + * + * To perform an interval query on an overlapped tree, perform the usual + * depth-first search and use the low and high keys to decide if we can skip + * that particular node. If a leaf node is reached, return the records that + * intersect the interval. Note that an interval query may return numerous + * entries. For a non-overlapped tree, simply search for the record associated + * with the lowest key and iterate forward until a non-matching record is + * found. */ /* @@ -441,6 +470,17 @@ static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur) return XFS_BTREE_SBLOCK_LEN; } +/* Return size of btree block keys for this btree instance. */ +static inline size_t xfs_btree_key_len(struct xfs_btree_cur *cur) +{ + size_t len; + + len = cur->bc_ops->key_len; + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) + len *= 2; + return len; +} + /* * Return size of btree block pointers for this btree instance. */ @@ -471,7 +511,19 @@ xfs_btree_key_offset( int n) { return xfs_btree_block_len(cur) + - (n - 1) * cur->bc_ops->key_len; + (n - 1) * xfs_btree_key_len(cur); +} + +/* + * Calculate offset of the n-th high key in a btree block. + */ +STATIC size_t +xfs_btree_high_key_offset( + struct xfs_btree_cur *cur, + int n) +{ + return xfs_btree_block_len(cur) + + (n - 1) * xfs_btree_key_len(cur) + cur->bc_ops->key_len; } /* @@ -484,7 +536,7 @@ xfs_btree_ptr_offset( int level) { return xfs_btree_block_len(cur) + - cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len + + cur->bc_ops->get_maxrecs(cur, level) * xfs_btree_key_len(cur) + (n - 1) * xfs_btree_ptr_len(cur); } @@ -515,6 +567,19 @@ xfs_btree_key_addr( } /* + * Return a pointer to the n-th high key in the btree block. + */ +STATIC union xfs_btree_key * +xfs_btree_high_key_addr( + struct xfs_btree_cur *cur, + int n, + struct xfs_btree_block *block) +{ + return (union xfs_btree_key *) + ((char *)block + xfs_btree_high_key_offset(cur, n)); +} + +/* * Return a pointer to the n-th block pointer in the btree block. */ STATIC union xfs_btree_ptr * @@ -1213,7 +1278,7 @@ xfs_btree_copy_keys( int numkeys) { ASSERT(numkeys >= 0); - memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len); + memcpy(dst_key, src_key, numkeys * xfs_btree_key_len(cur)); } /* @@ -1259,8 +1324,8 @@ xfs_btree_shift_keys( ASSERT(numkeys >= 0); ASSERT(dir == 1 || dir == -1); - dst_key = (char *)key + (dir * cur->bc_ops->key_len); - memmove(dst_key, key, numkeys * cur->bc_ops->key_len); + dst_key = (char *)key + (dir * xfs_btree_key_len(cur)); + memmove(dst_key, key, numkeys * xfs_btree_key_len(cur)); } /* @@ -1875,6 +1940,180 @@ error0: return error; } +/* Determine the low and high keys of a leaf block */ +STATIC void +xfs_btree_find_leaf_keys( + struct xfs_btree_cur *cur, + struct xfs_btree_block *block, + union xfs_btree_key *low, + union xfs_btree_key *high) +{ + int n; + union xfs_btree_rec *rec; + union xfs_btree_key max_hkey; + union xfs_btree_key hkey; + + rec = xfs_btree_rec_addr(cur, 1, block); + cur->bc_ops->init_key_from_rec(low, rec); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return; + + cur->bc_ops->init_high_key_from_rec(&max_hkey, rec); + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { + rec = xfs_btree_rec_addr(cur, n, block); + cur->bc_ops->init_high_key_from_rec(&hkey, rec); + if (cur->bc_ops->diff_two_keys(cur, &max_hkey, &hkey) > 0) + max_hkey = hkey; + } + + *high = max_hkey; +} + +/* Determine the low and high keys of a node block */ +STATIC void +xfs_btree_find_node_keys( + struct xfs_btree_cur *cur, + struct xfs_btree_block *block, + union xfs_btree_key *low, + union xfs_btree_key *high) +{ + int n; + union xfs_btree_key *hkey; + union xfs_btree_key *max_hkey; + + *low = *xfs_btree_key_addr(cur, 1, block); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return; + + max_hkey = xfs_btree_high_key_addr(cur, 1, block); + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { + hkey = xfs_btree_high_key_addr(cur, n, block); + if (cur->bc_ops->diff_two_keys(cur, max_hkey, hkey) > 0) + max_hkey = hkey; + } + + *high = *max_hkey; +} + +/* + * Update parental low & high keys from some block all the way back to the + * root of the btree. + */ +STATIC int +__xfs_btree_updkeys( + struct xfs_btree_cur *cur, + int level, + struct xfs_btree_block *block, + struct xfs_buf *bp0, + bool force_all) +{ + union xfs_btree_key lkey; /* keys from current level */ + union xfs_btree_key hkey; + union xfs_btree_key *nlkey; /* keys from the next level up */ + union xfs_btree_key *nhkey; + struct xfs_buf *bp; + int ptr = -1; + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return 0; + + if (level + 1 >= cur->bc_nlevels) + return 0; + + trace_xfs_btree_updkeys(cur, level, bp0); + + if (level == 0) + xfs_btree_find_leaf_keys(cur, block, &lkey, &hkey); + else + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); + for (level++; level < cur->bc_nlevels; level++) { + block = xfs_btree_get_block(cur, level, &bp); + trace_xfs_btree_updkeys(cur, level, bp); + ptr = cur->bc_ptrs[level]; + nlkey = xfs_btree_key_addr(cur, ptr, block); + nhkey = xfs_btree_high_key_addr(cur, ptr, block); + if (!(cur->bc_ops->diff_two_keys(cur, nlkey, &lkey) != 0 || + cur->bc_ops->diff_two_keys(cur, nhkey, &hkey) != 0) && + !force_all) + break; + memcpy(nlkey, &lkey, cur->bc_ops->key_len); + memcpy(nhkey, &hkey, cur->bc_ops->key_len); + xfs_btree_log_keys(cur, bp, ptr, ptr); + if (level + 1 >= cur->bc_nlevels) + break; + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); + } + + return 0; +} + +/* + * Update all the keys from a sibling block at some level in the cursor back + * to the root, stopping when we find a key pair that doesn't need updating. + */ +STATIC int +xfs_btree_sibling_updkeys( + struct xfs_btree_cur *cur, + int level, + int ptr, + struct xfs_btree_block *block, + struct xfs_buf *bp0) +{ + struct xfs_btree_cur *ncur; + int stat; + int error; + + error = xfs_btree_dup_cursor(cur, &ncur); + if (error) + return error; + + if (level + 1 >= ncur->bc_nlevels) + error = -EDOM; + else if (ptr == XFS_BB_RIGHTSIB) + error = xfs_btree_increment(ncur, level + 1, &stat); + else if (ptr == XFS_BB_LEFTSIB) + error = xfs_btree_decrement(ncur, level + 1, &stat); + else + error = -EBADE; + if (error || !stat) + return error; + + error = __xfs_btree_updkeys(ncur, level, block, bp0, false); + xfs_btree_del_cursor(ncur, XFS_BTREE_NOERROR); + return error; +} + +/* + * Update all the keys from some level in cursor back to the root, stopping + * when we find a key pair that don't need updating. + */ +STATIC int +xfs_btree_updkeys( + struct xfs_btree_cur *cur, + int level) +{ + struct xfs_buf *bp; + struct xfs_btree_block *block; + + block = xfs_btree_get_block(cur, level, &bp); + return __xfs_btree_updkeys(cur, level, block, bp, false); +} + +/* Update all the keys from some level in cursor back to the root. */ +STATIC int +xfs_btree_updkeys_force( + struct xfs_btree_cur *cur, + int level) +{ + struct xfs_buf *bp; + struct xfs_btree_block *block; + + block = xfs_btree_get_block(cur, level, &bp); + return __xfs_btree_updkeys(cur, level, block, bp, true); +} + /* * Update keys at all levels from here to the root along the cursor's path. */ @@ -1889,6 +2128,9 @@ xfs_btree_updkey( union xfs_btree_key *kp; int ptr; + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) + return 0; + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); XFS_BTREE_TRACE_ARGIK(cur, level, keyp); @@ -1966,7 +2208,8 @@ xfs_btree_update( ptr, LASTREC_UPDATE); } - /* Updating first rec in leaf. Pass new key value up to our parent. */ + /* Pass new key value up to our parent. */ + xfs_btree_updkeys(cur, 0); if (ptr == 1) { union xfs_btree_key key; @@ -2145,7 +2388,9 @@ xfs_btree_lshift( rkp = &key; } - /* Update the parent key values of right. */ + /* Update the parent key values of left and right. */ + xfs_btree_sibling_updkeys(cur, level, XFS_BB_LEFTSIB, left, lbp); + xfs_btree_updkeys(cur, level); error = xfs_btree_updkey(cur, rkp, level + 1); if (error) goto error0; @@ -2317,6 +2562,9 @@ xfs_btree_rshift( if (error) goto error1; + /* Update left and right parent pointers */ + xfs_btree_updkeys(cur, level); + xfs_btree_updkeys(tcur, level); error = xfs_btree_updkey(tcur, rkp, level + 1); if (error) goto error1; @@ -2352,7 +2600,7 @@ __xfs_btree_split( struct xfs_btree_cur *cur, int level, union xfs_btree_ptr *ptrp, - union xfs_btree_key *key, + struct xfs_btree_double_key *key, struct xfs_btree_cur **curp, int *stat) /* success/failure */ { @@ -2448,9 +2696,6 @@ __xfs_btree_split( xfs_btree_log_keys(cur, rbp, 1, rrecs); xfs_btree_log_ptrs(cur, rbp, 1, rrecs); - - /* Grab the keys to the entries moved to the right block */ - xfs_btree_copy_keys(cur, key, rkp, 1); } else { /* It's a leaf. Move records. */ union xfs_btree_rec *lrp; /* left record pointer */ @@ -2461,12 +2706,8 @@ __xfs_btree_split( xfs_btree_copy_recs(cur, rrp, lrp, rrecs); xfs_btree_log_recs(cur, rbp, 1, rrecs); - - cur->bc_ops->init_key_from_rec(key, - xfs_btree_rec_addr(cur, 1, right)); } - /* * Find the left block number by looking in the buffer. * Adjust numrecs, sibling pointers. @@ -2480,6 +2721,12 @@ __xfs_btree_split( xfs_btree_set_numrecs(left, lrecs); xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs); + /* Find the low & high keys for the new block. */ + if (level > 0) + xfs_btree_find_node_keys(cur, right, &key->low, &key->high); + else + xfs_btree_find_leaf_keys(cur, right, &key->low, &key->high); + xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS); xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); @@ -2495,6 +2742,10 @@ __xfs_btree_split( xfs_btree_set_sibling(cur, rrblock, &rptr, XFS_BB_LEFTSIB); xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB); } + + /* Update the left block's keys... */ + xfs_btree_updkeys(cur, level); + /* * If the cursor is really in the right block, move it there. * If it's just pointing past the last entry in left, then we'll @@ -2533,7 +2784,7 @@ struct xfs_btree_split_args { struct xfs_btree_cur *cur; int level; union xfs_btree_ptr *ptrp; - union xfs_btree_key *key; + struct xfs_btree_double_key *key; struct xfs_btree_cur **curp; int *stat; /* success/failure */ int result; @@ -2582,7 +2833,7 @@ xfs_btree_split( struct xfs_btree_cur *cur, int level, union xfs_btree_ptr *ptrp, - union xfs_btree_key *key, + struct xfs_btree_double_key *key, struct xfs_btree_cur **curp, int *stat) /* success/failure */ { @@ -2802,27 +3053,27 @@ xfs_btree_new_root( bp = lbp; nptr = 2; } + /* Fill in the new block's btree header and log it. */ xfs_btree_init_block_cur(cur, nbp, cur->bc_nlevels, 2); xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS); ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) && !xfs_btree_ptr_is_null(cur, &rptr)); - /* Fill in the key data in the new root. */ if (xfs_btree_get_level(left) > 0) { - xfs_btree_copy_keys(cur, + xfs_btree_find_node_keys(cur, left, xfs_btree_key_addr(cur, 1, new), - xfs_btree_key_addr(cur, 1, left), 1); - xfs_btree_copy_keys(cur, + xfs_btree_high_key_addr(cur, 1, new)); + xfs_btree_find_node_keys(cur, right, xfs_btree_key_addr(cur, 2, new), - xfs_btree_key_addr(cur, 1, right), 1); + xfs_btree_high_key_addr(cur, 2, new)); } else { - cur->bc_ops->init_key_from_rec( - xfs_btree_key_addr(cur, 1, new), - xfs_btree_rec_addr(cur, 1, left)); - cur->bc_ops->init_key_from_rec( - xfs_btree_key_addr(cur, 2, new), - xfs_btree_rec_addr(cur, 1, right)); + xfs_btree_find_leaf_keys(cur, left, + xfs_btree_key_addr(cur, 1, new), + xfs_btree_high_key_addr(cur, 1, new)); + xfs_btree_find_leaf_keys(cur, right, + xfs_btree_key_addr(cur, 2, new), + xfs_btree_high_key_addr(cur, 2, new)); } xfs_btree_log_keys(cur, nbp, 1, 2); @@ -2833,6 +3084,7 @@ xfs_btree_new_root( xfs_btree_ptr_addr(cur, 2, new), &rptr, 1); xfs_btree_log_ptrs(cur, nbp, 1, 2); + /* Fix up the cursor. */ xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); cur->bc_ptrs[cur->bc_nlevels] = nptr; @@ -2858,7 +3110,7 @@ xfs_btree_make_block_unfull( int *index, /* new tree index */ union xfs_btree_ptr *nptr, /* new btree ptr */ struct xfs_btree_cur **ncur, /* new btree cursor */ - union xfs_btree_key *key, /* key of new block */ + struct xfs_btree_double_key *key, /* key of new block */ int *stat) { int error = 0; @@ -2914,6 +3166,22 @@ xfs_btree_make_block_unfull( return 0; } +/* Copy a double key into a btree block. */ +static void +xfs_btree_copy_double_keys( + struct xfs_btree_cur *cur, + int ptr, + struct xfs_btree_block *block, + struct xfs_btree_double_key *key) +{ + memcpy(xfs_btree_key_addr(cur, ptr, block), &key->low, + cur->bc_ops->key_len); + + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) + memcpy(xfs_btree_high_key_addr(cur, ptr, block), &key->high, + cur->bc_ops->key_len); +} + /* * Insert one record/level. Return information to the caller * allowing the next level up to proceed if necessary. @@ -2923,7 +3191,7 @@ xfs_btree_insrec( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level to insert record at */ union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ - union xfs_btree_key *key, /* i/o: block key for ptrp */ + struct xfs_btree_double_key *key, /* i/o: block key for ptrp */ struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ int *stat) /* success/failure */ { @@ -2931,7 +3199,7 @@ xfs_btree_insrec( struct xfs_buf *bp; /* buffer for block */ union xfs_btree_ptr nptr; /* new block ptr */ struct xfs_btree_cur *ncur; /* new btree cursor */ - union xfs_btree_key nkey; /* new block key */ + struct xfs_btree_double_key nkey; /* new block key */ union xfs_btree_rec rec; /* record to insert */ int optr; /* old key/record index */ int ptr; /* key/record index */ @@ -2940,11 +3208,12 @@ xfs_btree_insrec( #ifdef DEBUG int i; #endif + xfs_daddr_t old_bn; /* Make a key out of the record data to be inserted, and save it. */ if (level == 0) { cur->bc_ops->init_rec_from_cur(cur, &rec); - cur->bc_ops->init_key_from_rec(key, &rec); + cur->bc_ops->init_key_from_rec(&key->low, &rec); } XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); @@ -2979,6 +3248,7 @@ xfs_btree_insrec( /* Get pointers to the btree buffer and block. */ block = xfs_btree_get_block(cur, level, &bp); + old_bn = bp ? bp->b_bn : XFS_BUF_DADDR_NULL; numrecs = xfs_btree_get_numrecs(block); #ifdef DEBUG @@ -2992,7 +3262,7 @@ xfs_btree_insrec( ASSERT(cur->bc_ops->recs_inorder(cur, &rec, xfs_btree_rec_addr(cur, ptr, block))); } else { - ASSERT(cur->bc_ops->keys_inorder(cur, key, + ASSERT(cur->bc_ops->keys_inorder(cur, &key->low, xfs_btree_key_addr(cur, ptr, block))); } } @@ -3055,7 +3325,7 @@ xfs_btree_insrec( #endif /* Now put the new data in, bump numrecs and log it. */ - xfs_btree_copy_keys(cur, kp, key, 1); + xfs_btree_copy_double_keys(cur, ptr, block, key); xfs_btree_copy_ptrs(cur, pp, ptrp, 1); numrecs++; xfs_btree_set_numrecs(block, numrecs); @@ -3091,8 +3361,24 @@ xfs_btree_insrec( xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); /* If we inserted at the start of a block, update the parents' keys. */ + if (ncur && bp->b_bn != old_bn) { + /* + * We just inserted into a new tree block, which means that + * the key for the block is in nkey, not the tree. + */ + if (level == 0) + xfs_btree_find_leaf_keys(cur, block, &nkey.low, + &nkey.high); + else + xfs_btree_find_node_keys(cur, block, &nkey.low, + &nkey.high); + } else { + /* Updating the left block, do it the standard way. */ + xfs_btree_updkeys(cur, level); + } + if (optr == 1) { - error = xfs_btree_updkey(cur, key, level + 1); + error = xfs_btree_updkey(cur, &key->low, level + 1); if (error) goto error0; } @@ -3143,7 +3429,7 @@ xfs_btree_insert( union xfs_btree_ptr nptr; /* new block number (split result) */ struct xfs_btree_cur *ncur; /* new cursor (split result) */ struct xfs_btree_cur *pcur; /* previous level's cursor */ - union xfs_btree_key key; /* key of block to insert */ + struct xfs_btree_double_key key; /* key of block to insert */ level = 0; ncur = NULL; @@ -3548,6 +3834,7 @@ xfs_btree_delrec( * If we deleted the leftmost entry in the block, update the * key values above us in the tree. */ + xfs_btree_updkeys(cur, level); if (ptr == 1) { error = xfs_btree_updkey(cur, keyp, level + 1); if (error) @@ -3878,6 +4165,16 @@ xfs_btree_delrec( if (level > 0) cur->bc_ptrs[level]--; + /* + * We combined blocks, so we have to update the parent keys if the + * btree supports overlapped intervals. However, bc_ptrs[level + 1] + * points to the old block so that the caller knows which record to + * delete. Therefore, the caller must be savvy enough to call updkeys + * for us if we return stat == 2. The other exit points from this + * function don't require deletions further up the tree, so they can + * call updkeys directly. + */ + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); /* Return value means the next level up has something to do. */ *stat = 2; @@ -3903,6 +4200,7 @@ xfs_btree_delete( int error; /* error return value */ int level; int i; + bool joined = false; XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); @@ -3916,8 +4214,17 @@ xfs_btree_delete( error = xfs_btree_delrec(cur, level, &i); if (error) goto error0; + if (i == 2) + joined = true; } + /* + * If we combined blocks as part of deleting the record, delrec won't + * have updated the parent keys so we have to do that here. + */ + if (joined) + xfs_btree_updkeys_force(cur, 0); + if (i == 0) { for (level = 1; level < cur->bc_nlevels; level++) { if (cur->bc_ptrs[level] == 0) { diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index b99c018..a5ec6c7 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -126,6 +126,9 @@ struct xfs_btree_ops { size_t key_len; size_t rec_len; + /* flags */ + uint flags; + /* cursor operations */ struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); void (*update_cursor)(struct xfs_btree_cur *src, @@ -162,11 +165,21 @@ struct xfs_btree_ops { union xfs_btree_rec *rec); void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, union xfs_btree_ptr *ptr); + void (*init_high_key_from_rec)(union xfs_btree_key *key, + union xfs_btree_rec *rec); /* difference between key value and cursor value */ __int64_t (*key_diff)(struct xfs_btree_cur *cur, union xfs_btree_key *key); + /* + * Difference between key2 and key1 -- positive if key2 > key1, + * negative if key2 < key1, and zero if equal. + */ + __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur, + union xfs_btree_key *key1, + union xfs_btree_key *key2); + const struct xfs_buf_ops *buf_ops; #if defined(DEBUG) || defined(XFS_WARN) @@ -182,6 +195,9 @@ struct xfs_btree_ops { #endif }; +/* btree ops flags */ +#define XFS_BTREE_OPS_OVERLAPPING (1<<0) /* overlapping intervals */ + /* * Reasons for the update_lastrec method to be called. */ From darrick.wong@oracle.com Thu Jun 16 20:32:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 153358028 for ; Thu, 16 Jun 2016 20:32:47 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id B9961304051 for ; Thu, 16 Jun 2016 18:32:46 -0700 (PDT) X-ASG-Debug-ID: 1466127164-04bdf01e1595fe0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 8FNK1vYKd8qdVixu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:44 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1We9X015098 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:40 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WdmZ000406 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:39 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WcPK022304; Fri, 17 Jun 2016 01:32:39 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:38 -0700 Subject: [PATCH 018/145] xfs: introduce interval queries on btrees From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 018/145] xfs: introduce interval queries on btrees To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:37 -0700 Message-ID: <146612715724.16048.14399268311501387097.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127164 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10068 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a function to enable querying of btree records mapping to a range of keys. This will be used in subsequent patches to allow querying the reverse mapping btree to find the extents mapped to a range of physical blocks, though the generic code can be used for any range query. v2: add some shortcuts so that we can jump out of processing once we know there won't be any more records to find. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 1 libxfs/xfs_btree.c | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_btree.h | 22 +++-- 3 files changed, 267 insertions(+), 5 deletions(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index aea41bc..56c4533 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -167,6 +167,7 @@ #define trace_xfs_bunmap(a,b,c,d,e) ((void) 0) #define trace_xfs_btree_updkeys(...) ((void) 0) +#define trace_xfs_btree_overlapped_query_range(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 7fa0226..7a34aa1 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -4505,3 +4505,252 @@ xfs_btree_calc_size( } return rval; } + +/* Query a regular btree for all records overlapping a given interval. */ +STATIC int +xfs_btree_simple_query_range( + struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, + union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, + void *priv) +{ + union xfs_btree_rec *recp; + union xfs_btree_rec rec; + union xfs_btree_key low_key; + union xfs_btree_key high_key; + union xfs_btree_key rec_key; + __int64_t diff; + int stat; + bool firstrec = true; + int error; + + ASSERT(cur->bc_ops->init_high_key_from_rec); + + /* Find the keys of both ends of the interval. */ + cur->bc_rec = *high_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&high_key, &rec); + + cur->bc_rec = *low_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&low_key, &rec); + + /* Find the leftmost record. */ + stat = 0; + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat); + if (error) + goto out; + + while (stat) { + /* Find the record. */ + error = xfs_btree_get_rec(cur, &recp, &stat); + if (error || !stat) + break; + + /* Can we tell if this record is too low? */ + if (firstrec) { + cur->bc_rec = *low_rec; + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); + diff = cur->bc_ops->key_diff(cur, &rec_key); + if (diff < 0) + goto advloop; + } + firstrec = false; + + /* Have we gone past the end? */ + cur->bc_rec = *high_rec; + cur->bc_ops->init_key_from_rec(&rec_key, recp); + diff = cur->bc_ops->key_diff(cur, &rec_key); + if (diff > 0) + break; + + /* Callback */ + error = fn(cur, recp, priv); + if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) + break; + +advloop: + /* Move on to the next record. */ + error = xfs_btree_increment(cur, 0, &stat); + if (error) + break; + } + +out: + return error; +} + +/* + * Query an overlapped interval btree for all records overlapping a given + * interval. + */ +STATIC int +xfs_btree_overlapped_query_range( + struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, + union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, + void *priv) +{ + union xfs_btree_ptr ptr; + union xfs_btree_ptr *pp; + union xfs_btree_key rec_key; + union xfs_btree_key low_key; + union xfs_btree_key high_key; + union xfs_btree_key *lkp; + union xfs_btree_key *hkp; + union xfs_btree_rec rec; + union xfs_btree_rec *recp; + struct xfs_btree_block *block; + __int64_t ldiff; + __int64_t hdiff; + int level; + struct xfs_buf *bp; + int i; + int error; + + /* Find the keys of both ends of the interval. */ + cur->bc_rec = *high_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&high_key, &rec); + + cur->bc_rec = *low_rec; + cur->bc_ops->init_rec_from_cur(cur, &rec); + cur->bc_ops->init_key_from_rec(&low_key, &rec); + + /* Load the root of the btree. */ + level = cur->bc_nlevels - 1; + cur->bc_ops->init_ptr_from_cur(cur, &ptr); + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); + if (error) + return error; + xfs_btree_get_block(cur, level, &bp); + trace_xfs_btree_overlapped_query_range(cur, level, bp); +#ifdef DEBUG + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; +#endif + cur->bc_ptrs[level] = 1; + + while (level < cur->bc_nlevels) { + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); + + if (level == 0) { + /* End of leaf, pop back towards the root. */ + if (cur->bc_ptrs[level] > + be16_to_cpu(block->bb_numrecs)) { +leaf_pop_up: + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); + + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, + &rec_key); + + cur->bc_ops->init_key_from_rec(&rec_key, recp); + hdiff = cur->bc_ops->diff_two_keys(cur, &rec_key, + &high_key); + + /* If the record matches, callback */ + if (ldiff >= 0 && hdiff >= 0) { + error = fn(cur, recp, priv); + if (error < 0 || + error == XFS_BTREE_QUERY_RANGE_ABORT) + break; + } else if (hdiff < 0) { + /* Record is larger than high key; pop. */ + goto leaf_pop_up; + } + cur->bc_ptrs[level]++; + continue; + } + + /* End of node, pop back towards the root. */ + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { +node_pop_up: + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); + hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); + + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, hkp); + hdiff = cur->bc_ops->diff_two_keys(cur, lkp, &high_key); + + /* If the key matches, drill another level deeper. */ + if (ldiff >= 0 && hdiff >= 0) { + level--; + error = xfs_btree_lookup_get_block(cur, level, pp, + &block); + if (error) + goto out; + xfs_btree_get_block(cur, level, &bp); + trace_xfs_btree_overlapped_query_range(cur, level, bp); +#ifdef DEBUG + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; +#endif + cur->bc_ptrs[level] = 1; + continue; + } else if (hdiff < 0) { + /* The low key is larger than the upper range; pop. */ + goto node_pop_up; + } + cur->bc_ptrs[level]++; + } + +out: + /* + * If we don't end this function with the cursor pointing at a record + * block, a subsequent non-error cursor deletion will not release + * node-level buffers, causing a buffer leak. This is quite possible + * with a zero-results range query, so release the buffers if we + * failed to return any results. + */ + if (cur->bc_bufs[0] == NULL) { + for (i = 0; i < cur->bc_nlevels; i++) { + if (cur->bc_bufs[i]) { + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); + cur->bc_bufs[i] = NULL; + cur->bc_ptrs[i] = 0; + cur->bc_ra[i] = 0; + } + } + } + + return error; +} + +/* + * Query a btree for all records overlapping a given interval of keys. The + * supplied function will be called with each record found; return one of the + * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error + * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a + * negative error code. + */ +int +xfs_btree_query_range( + struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, + union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, + void *priv) +{ + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return xfs_btree_simple_query_range(cur, low_rec, + high_rec, fn, priv); + return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, + fn, priv); +} diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index a5ec6c7..898fee5 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -206,6 +206,12 @@ struct xfs_btree_ops { #define LASTREC_DELREC 2 +union xfs_btree_irec { + xfs_alloc_rec_incore_t a; + xfs_bmbt_irec_t b; + xfs_inobt_rec_incore_t i; +}; + /* * Btree cursor structure. * This collects all information needed by the btree code in one place. @@ -216,11 +222,7 @@ typedef struct xfs_btree_cur struct xfs_mount *bc_mp; /* file system mount struct */ const struct xfs_btree_ops *bc_ops; uint bc_flags; /* btree features - below */ - union { - xfs_alloc_rec_incore_t a; - xfs_bmbt_irec_t b; - xfs_inobt_rec_incore_t i; - } bc_rec; /* current insert/search record value */ + union xfs_btree_irec bc_rec; /* current insert/search record value */ struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ @@ -494,4 +496,14 @@ xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, unsigned long len); +/* return codes */ +#define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */ +#define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */ +typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur, + union xfs_btree_rec *rec, void *priv); + +int xfs_btree_query_range(struct xfs_btree_cur *cur, + union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, + xfs_btree_query_range_fn fn, void *priv); + #endif /* __XFS_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:32:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8782A8036 for ; Thu, 16 Jun 2016 20:32:53 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id F3789AC001 for ; Thu, 16 Jun 2016 18:32:52 -0700 (PDT) X-ASG-Debug-ID: 1466127170-04cb6c542757d70001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id C7yz8j4Ql9tGvEUW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:51 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1WkGM015130 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:32:46 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1WkiH026628 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:46 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WjUA022321; Fri, 17 Jun 2016 01:32:45 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:44 -0700 Subject: [PATCH 019/145] xfs: refactor btree owner change into a separate visit-blocks function From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 019/145] xfs: refactor btree owner change into a separate visit-blocks function To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:43 -0700 Message-ID: <146612716346.16048.14016377411947580027.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127170 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6107 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Refactor the btree_change_owner function into a more generic apparatus which visits all blocks in a btree. We'll use this in a subsequent patch for counting btree blocks for AG reservations. Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.c | 141 ++++++++++++++++++++++++++++++++++------------------ libxfs/xfs_btree.h | 5 ++ 2 files changed, 96 insertions(+), 50 deletions(-) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 7a34aa1..4f48878 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -4285,6 +4285,81 @@ xfs_btree_get_rec( return 0; } +/* Visit a block in a btree. */ +STATIC int +xfs_btree_visit_block( + struct xfs_btree_cur *cur, + int level, + xfs_btree_visit_blocks_fn fn, + void *data) +{ + struct xfs_btree_block *block; + struct xfs_buf *bp; + union xfs_btree_ptr rptr; + int error; + + /* do right sibling readahead */ + xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); + block = xfs_btree_get_block(cur, level, &bp); + + /* process the block */ + error = fn(cur, level, data); + if (error) + return error; + + /* now read rh sibling block for next iteration */ + xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); + if (xfs_btree_ptr_is_null(cur, &rptr)) + return -ENOENT; + + return xfs_btree_lookup_get_block(cur, level, &rptr, &block); +} + + +/* Visit every block in a btree. */ +int +xfs_btree_visit_blocks( + struct xfs_btree_cur *cur, + xfs_btree_visit_blocks_fn fn, + void *data) +{ + union xfs_btree_ptr lptr; + int level; + struct xfs_btree_block *block = NULL; + int error = 0; + + cur->bc_ops->init_ptr_from_cur(cur, &lptr); + + /* for each level */ + for (level = cur->bc_nlevels - 1; level >= 0; level--) { + /* grab the left hand block */ + error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); + if (error) + return error; + + /* readahead the left most block for the next level down */ + if (level > 0) { + union xfs_btree_ptr *ptr; + + ptr = xfs_btree_ptr_addr(cur, 1, block); + xfs_btree_readahead_ptr(cur, ptr, 1); + + /* save for the next iteration of the loop */ + lptr = *ptr; + } + + /* for each buffer in the level */ + do { + error = xfs_btree_visit_block(cur, level, fn, data); + } while (!error); + + if (error != -ENOENT) + return error; + } + + return 0; +} + /* * Change the owner of a btree. * @@ -4309,26 +4384,27 @@ xfs_btree_get_rec( * just queue the modified buffer as delayed write buffer so the transaction * recovery completion writes the changes to disk. */ +struct xfs_btree_block_change_owner_info { + __uint64_t new_owner; + struct list_head *buffer_list; +}; + static int xfs_btree_block_change_owner( struct xfs_btree_cur *cur, int level, - __uint64_t new_owner, - struct list_head *buffer_list) + void *data) { + struct xfs_btree_block_change_owner_info *bbcoi = data; struct xfs_btree_block *block; struct xfs_buf *bp; - union xfs_btree_ptr rptr; - - /* do right sibling readahead */ - xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); /* modify the owner */ block = xfs_btree_get_block(cur, level, &bp); if (cur->bc_flags & XFS_BTREE_LONG_PTRS) - block->bb_u.l.bb_owner = cpu_to_be64(new_owner); + block->bb_u.l.bb_owner = cpu_to_be64(bbcoi->new_owner); else - block->bb_u.s.bb_owner = cpu_to_be32(new_owner); + block->bb_u.s.bb_owner = cpu_to_be32(bbcoi->new_owner); /* * If the block is a root block hosted in an inode, we might not have a @@ -4342,19 +4418,14 @@ xfs_btree_block_change_owner( xfs_trans_ordered_buf(cur->bc_tp, bp); xfs_btree_log_block(cur, bp, XFS_BB_OWNER); } else { - xfs_buf_delwri_queue(bp, buffer_list); + xfs_buf_delwri_queue(bp, bbcoi->buffer_list); } } else { ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); ASSERT(level == cur->bc_nlevels - 1); } - /* now read rh sibling block for next iteration */ - xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); - if (xfs_btree_ptr_is_null(cur, &rptr)) - return -ENOENT; - - return xfs_btree_lookup_get_block(cur, level, &rptr, &block); + return 0; } int @@ -4363,43 +4434,13 @@ xfs_btree_change_owner( __uint64_t new_owner, struct list_head *buffer_list) { - union xfs_btree_ptr lptr; - int level; - struct xfs_btree_block *block = NULL; - int error = 0; + struct xfs_btree_block_change_owner_info bbcoi; - cur->bc_ops->init_ptr_from_cur(cur, &lptr); + bbcoi.new_owner = new_owner; + bbcoi.buffer_list = buffer_list; - /* for each level */ - for (level = cur->bc_nlevels - 1; level >= 0; level--) { - /* grab the left hand block */ - error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); - if (error) - return error; - - /* readahead the left most block for the next level down */ - if (level > 0) { - union xfs_btree_ptr *ptr; - - ptr = xfs_btree_ptr_addr(cur, 1, block); - xfs_btree_readahead_ptr(cur, ptr, 1); - - /* save for the next iteration of the loop */ - lptr = *ptr; - } - - /* for each buffer in the level */ - do { - error = xfs_btree_block_change_owner(cur, level, - new_owner, - buffer_list); - } while (!error); - - if (error != -ENOENT) - return error; - } - - return 0; + return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner, + &bbcoi); } /** diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 898fee5..0ec3055 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -506,4 +506,9 @@ int xfs_btree_query_range(struct xfs_btree_cur *cur, union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, xfs_btree_query_range_fn fn, void *priv); +typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level, + void *data); +int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, + xfs_btree_visit_blocks_fn fn, void *data); + #endif /* __XFS_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:33:00 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id DA9868044 for ; Thu, 16 Jun 2016 20:33:00 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id A9D1730404E for ; Thu, 16 Jun 2016 18:33:00 -0700 (PDT) X-ASG-Debug-ID: 1466127176-04cb6c542657d80001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id xRmdOQB25QCc5mCB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:32:56 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1WsmF002238 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:32:55 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1WrEj026800 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:32:54 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WprB010165; Fri, 17 Jun 2016 01:32:52 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:50 -0700 Subject: [PATCH 020/145] xfs: move deferred operations into a separate file From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 020/145] xfs: move deferred operations into a separate file To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:49 -0700 Message-ID: <146612716961.16048.16304750413154183604.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127176 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 23887 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines All the code around struct xfs_bmap_free basically implements a deferred operation framework through which we can roll transactions (to unlock buffers and avoid violating lock order rules) while managing all the necessary log redo items. Previously we only used this code to free extents after some sort of mapping operation, but with the advent of rmap and reflink, we suddenly need to do more than that. With that in mind, xfs_bmap_free really becomes a deferred ops control structure. Rename the structure and move the deferred ops into their own file to avoid further bloating of the bmap code. v2: actually sort the work items by AG to avoid deadlocks Signed-off-by: Darrick J. Wong --- libxfs/Makefile | 3 libxfs/defer_item.c | 36 ++++ libxfs/init.c | 2 libxfs/xfs_defer.c | 471 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_defer.h | 96 ++++++++++ 5 files changed, 608 insertions(+) create mode 100644 libxfs/defer_item.c create mode 100644 libxfs/xfs_defer.c create mode 100644 libxfs/xfs_defer.h diff --git a/libxfs/Makefile b/libxfs/Makefile index ca1a5ee..0073cd1 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -29,6 +29,7 @@ HFILES = \ xfs_attr_remote.h \ xfs_cksum.h \ xfs_da_btree.h \ + xfs_defer.h \ xfs_dir2.h \ xfs_ialloc.h \ xfs_ialloc_btree.h \ @@ -49,6 +50,7 @@ HFILES = \ CFILES = cache.c \ crc32.c \ + defer_item.c \ init.c \ kmem.c \ logitem.c \ @@ -67,6 +69,7 @@ CFILES = cache.c \ xfs_btree.c \ xfs_da_btree.c \ xfs_da_format.c \ + xfs_defer.c \ xfs_dir2.c \ xfs_dir2_block.c \ xfs_dir2_data.c \ diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c new file mode 100644 index 0000000..06d294f --- /dev/null +++ b/libxfs/defer_item.c @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_trans.h" + +/* Initialize the deferred operation types. */ +void +xfs_defer_init_types(void) +{ +} diff --git a/libxfs/init.c b/libxfs/init.c index 67c3b30..553da7b 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -26,6 +26,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_inode.h" @@ -262,6 +263,7 @@ libxfs_init(libxfs_init_t *a) flags = (a->isreadonly | a->isdirect); radix_tree_init(); + xfs_defer_init_types(); if (a->volname) { if(!check_open(a->volname,flags,&rawfile,&blockfile)) diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c new file mode 100644 index 0000000..5ae5e0d --- /dev/null +++ b/libxfs/xfs_defer.c @@ -0,0 +1,471 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_trans.h" +#include "xfs_trace.h" + +/* + * Deferred Operations in XFS + * + * Due to the way locking rules work in XFS, certain transactions (block + * mapping and unmapping, typically) have permanent reservations so that + * we can roll the transaction to adhere to AG locking order rules and + * to unlock buffers between metadata updates. Prior to rmap/reflink, + * the mapping code had a mechanism to perform these deferrals for + * extents that were going to be freed; this code makes that facility + * more generic. + * + * When adding the reverse mapping and reflink features, it became + * necessary to perform complex remapping multi-transactions to comply + * with AG locking order rules, and to be able to spread a single + * refcount update operation (an operation on an n-block extent can + * update as many as n records!) among multiple transactions. XFS can + * roll a transaction to facilitate this, but using this facility + * requires us to log "intent" items in case log recovery needs to + * redo the operation, and to log "done" items to indicate that redo + * is not necessary. + * + * The xfs_defer_ops structure tracks incoming deferred work (which is + * work that has not yet had an intent logged) in xfs_defer_intake. + * There is one xfs_defer_intake for each type of deferrable + * operation. Each new deferral is placed in the op's intake list, + * where it waits for the caller to finish the deferred operations. + * + * Finishing a set of deferred operations is an involved process. To + * start, we define "rolling a deferred-op transaction" as follows: + * + * > For each xfs_defer_intake, + * - Sort the items on the intake list in AG order. + * - Create a log intent item for that type. + * - Attach to it the items on the intake list. + * - Stash the intent+items for later in an xfs_defer_pending. + * - Attach the xfs_defer_pending to the xfs_defer_ops work list. + * > Roll the transaction. + * + * NOTE: To avoid exceeding the transaction reservation, we limit the + * number of items that we attach to a given xfs_defer_pending. + * + * The actual finishing process looks like this: + * + * > For each xfs_defer_pending in the xfs_defer_ops work list, + * - Roll the deferred-op transaction as above. + * - Create a log done item for that type, and attach it to the + * intent item. + * - For each work item attached to the intent item, + * * Perform the described action. + * * Attach the work item to the log done item. + * * If the result of doing the work was -EAGAIN, log a fresh + * intent item and attach all remaining work items to it. Put + * the xfs_defer_pending item back on the work list, and repeat + * the loop. This allows us to make partial progress even if + * the transaction is too full to finish the job. + * + * The key here is that we must log an intent item for all pending + * work items every time we roll the transaction, and that we must log + * a done item as soon as the work is completed. With this mechanism + * we can perform complex remapping operations, chaining intent items + * as needed. + * + * This is an example of remapping the extent (E, E+B) into file X at + * offset A and dealing with the extent (C, C+B) already being mapped + * there: + * +-------------------------------------------------+ + * | Unmap file X startblock C offset A length B | t0 + * | Intent to reduce refcount for extent (C, B) | + * | Intent to remove rmap (X, C, A, B) | + * | Intent to free extent (D, 1) (bmbt block) | + * | Intent to map (X, A, B) at startblock E | + * +-------------------------------------------------+ + * | Map file X startblock E offset A length B | t1 + * | Done mapping (X, E, A, B) | + * | Intent to increase refcount for extent (E, B) | + * | Intent to add rmap (X, E, A, B) | + * +-------------------------------------------------+ + * | Reduce refcount for extent (C, B) | t2 + * | Done reducing refcount for extent (C, B) | + * | Increase refcount for extent (E, B) | + * | Done increasing refcount for extent (E, B) | + * | Intent to free extent (C, B) | + * | Intent to free extent (F, 1) (refcountbt block) | + * | Intent to remove rmap (F, 1, REFC) | + * +-------------------------------------------------+ + * | Remove rmap (X, C, A, B) | t3 + * | Done removing rmap (X, C, A, B) | + * | Add rmap (X, E, A, B) | + * | Done adding rmap (X, E, A, B) | + * | Remove rmap (F, 1, REFC) | + * | Done removing rmap (F, 1, REFC) | + * +-------------------------------------------------+ + * | Free extent (C, B) | t4 + * | Done freeing extent (C, B) | + * | Free extent (D, 1) | + * | Done freeing extent (D, 1) | + * | Free extent (F, 1) | + * | Done freeing extent (F, 1) | + * +-------------------------------------------------+ + * + * If we should crash before t2 commits, log recovery replays + * the following intent items: + * + * - Intent to reduce refcount for extent (C, B) + * - Intent to remove rmap (X, C, A, B) + * - Intent to free extent (D, 1) (bmbt block) + * - Intent to increase refcount for extent (E, B) + * - Intent to add rmap (X, E, A, B) + * + * In the process of recovering, it should also generate and take care + * of these intent items: + * + * - Intent to free extent (C, B) + * - Intent to free extent (F, 1) (refcountbt block) + * - Intent to remove rmap (F, 1, REFC) + */ + +static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; + +/* + * For each pending item in the intake list, log its intent item and the + * associated extents, then add the entire intake list to the end of + * the pending list. + */ +STATIC void +xfs_defer_intake_work( + struct xfs_trans *tp, + struct xfs_defer_ops *dop) +{ + struct list_head *li; + struct xfs_defer_pending *dfp; + + list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { + dfp->dfp_intent = dfp->dfp_type->create_intent(tp, + dfp->dfp_count); + list_sort(tp->t_mountp, &dfp->dfp_work, + dfp->dfp_type->diff_items); + list_for_each(li, &dfp->dfp_work) + dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); + } + + list_splice_tail_init(&dop->dop_intake, &dop->dop_pending); +} + +/* Abort all the intents that were committed. */ +STATIC void +xfs_defer_trans_abort( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + int error) +{ + struct xfs_defer_pending *dfp; + + /* + * If the transaction was committed, drop the intent reference + * since we're bailing out of here. The other reference is + * dropped when the intent hits the AIL. If the transaction + * was not committed, the intent is freed by the intent item + * unlock handler on abort. + */ + if (!dop->dop_committed) + return; + + /* Abort intent items. */ + list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { + if (dfp->dfp_committed) + dfp->dfp_type->abort_intent(dfp->dfp_intent); + } + + /* Shut down FS. */ + xfs_force_shutdown(tp->t_mountp, (error == -EFSCORRUPTED) ? + SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR); +} + +/* Roll a transaction so we can do some deferred op processing. */ +STATIC int +xfs_defer_trans_roll( + struct xfs_trans **tp, + struct xfs_defer_ops *dop, + struct xfs_inode *ip) +{ + int i; + int error; + + /* Log all the joined inodes except the one we passed in. */ + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { + if (dop->dop_inodes[i] == ip) + continue; + xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); + } + + /* Roll the transaction. */ + error = xfs_trans_roll(tp, ip); + if (error) { + xfs_defer_trans_abort(*tp, dop, error); + return error; + } + dop->dop_committed = true; + + /* Log all the joined inodes except the one we passed in. */ + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { + if (dop->dop_inodes[i] == ip) + continue; + xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); + } + + return error; +} + +/* Do we have any work items to finish? */ +bool +xfs_defer_has_unfinished_work( + struct xfs_defer_ops *dop) +{ + return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake); +} + +/* + * Add this inode to the deferred op. Each joined inode is relogged + * each time we roll the transaction, in addition to any inode passed + * to xfs_defer_finish(). + */ +int +xfs_defer_join( + struct xfs_defer_ops *dop, + struct xfs_inode *ip) +{ + int i; + + for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) { + if (dop->dop_inodes[i] == ip) + return 0; + else if (dop->dop_inodes[i] == NULL) { + dop->dop_inodes[i] = ip; + return 0; + } + } + + return -EFSCORRUPTED; +} + +/* + * Finish all the pending work. This involves logging intent items for + * any work items that wandered in since the last transaction roll (if + * one has even happened), rolling the transaction, and finishing the + * work items in the first item on the logged-and-pending list. + * + * If an inode is provided, relog it to the new transaction. + */ +int +xfs_defer_finish( + struct xfs_trans **tp, + struct xfs_defer_ops *dop, + struct xfs_inode *ip) +{ + struct xfs_defer_pending *dfp; + struct list_head *li; + struct list_head *n; + void *done_item = NULL; + void *state; + int error = 0; + void (*cleanup_fn)(struct xfs_trans *, void *, int); + + ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); + + /* Until we run out of pending work to finish... */ + while (xfs_defer_has_unfinished_work(dop)) { + /* Log intents for work items sitting in the intake. */ + xfs_defer_intake_work(*tp, dop); + + /* Roll the transaction. */ + error = xfs_defer_trans_roll(tp, dop, ip); + if (error) + goto out; + + /* Mark all pending intents as committed. */ + list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { + if (dfp->dfp_committed) + break; + dfp->dfp_committed = true; + } + + /* Log an intent-done item for the first pending item. */ + dfp = list_first_entry(&dop->dop_pending, + struct xfs_defer_pending, dfp_list); + done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, + dfp->dfp_count); + cleanup_fn = dfp->dfp_type->finish_cleanup; + + /* Finish the work items. */ + state = NULL; + list_for_each_safe(li, n, &dfp->dfp_work) { + list_del(li); + dfp->dfp_count--; + error = dfp->dfp_type->finish_item(*tp, dop, li, + done_item, &state); + if (error == -EAGAIN) { + /* + * If the caller needs to try again, put the + * item back on the pending list and jump out + * for further processing. + */ + list_add(li, &dfp->dfp_work); + dfp->dfp_count++; + break; + } else if (error) { + /* + * Clean up after ourselves and jump out. + * xfs_defer_cancel will take care of freeing + * all these lists and stuff. + */ + if (cleanup_fn) + cleanup_fn(*tp, state, error); + xfs_defer_trans_abort(*tp, dop, error); + goto out; + } + } + if (error == -EAGAIN) { + /* + * Log a new intent, relog all the remaining work + * item to the new intent, attach the new intent to + * the dfp, and leave the dfp at the head of the list + * for further processing. + */ + dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, + dfp->dfp_count); + list_for_each(li, &dfp->dfp_work) + dfp->dfp_type->log_item(*tp, dfp->dfp_intent, + li); + } else { + /* Done with the dfp, free it. */ + list_del(&dfp->dfp_list); + kmem_free(dfp); + } + + if (cleanup_fn) + cleanup_fn(*tp, state, error); + } + +out: + return error; +} + +/* + * Free up any items left in the list. + */ +void +xfs_defer_cancel( + struct xfs_defer_ops *dop) +{ + struct xfs_defer_pending *dfp; + struct xfs_defer_pending *pli; + struct list_head *pwi; + struct list_head *n; + + /* + * Free the pending items. Caller should already have arranged + * for the intent items to be released. + */ + list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { + list_del(&dfp->dfp_list); + list_for_each_safe(pwi, n, &dfp->dfp_work) { + list_del(pwi); + dfp->dfp_count--; + dfp->dfp_type->cancel_item(pwi); + } + ASSERT(dfp->dfp_count == 0); + kmem_free(dfp); + } + list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { + list_del(&dfp->dfp_list); + list_for_each_safe(pwi, n, &dfp->dfp_work) { + list_del(pwi); + dfp->dfp_count--; + dfp->dfp_type->cancel_item(pwi); + } + ASSERT(dfp->dfp_count == 0); + kmem_free(dfp); + } +} + +/* Add an item for later deferred processing. */ +void +xfs_defer_add( + struct xfs_defer_ops *dop, + enum xfs_defer_ops_type type, + struct list_head *li) +{ + struct xfs_defer_pending *dfp = NULL; + + /* + * Add the item to a pending item at the end of the intake list. + * If the last pending item has the same type, reuse it. Else, + * create a new pending item at the end of the intake list. + */ + if (!list_empty(&dop->dop_intake)) { + dfp = list_last_entry(&dop->dop_intake, + struct xfs_defer_pending, dfp_list); + if (dfp->dfp_type->type != type || + (dfp->dfp_type->max_items && + dfp->dfp_count >= dfp->dfp_type->max_items)) + dfp = NULL; + } + if (!dfp) { + dfp = kmem_alloc(sizeof(struct xfs_defer_pending), + KM_SLEEP | KM_NOFS); + dfp->dfp_type = defer_op_types[type]; + dfp->dfp_committed = false; + dfp->dfp_intent = NULL; + dfp->dfp_count = 0; + INIT_LIST_HEAD(&dfp->dfp_work); + list_add_tail(&dfp->dfp_list, &dop->dop_intake); + } + + list_add_tail(li, &dfp->dfp_work); + dfp->dfp_count++; +} + +/* Initialize a deferred operation list. */ +void +xfs_defer_init_op_type( + const struct xfs_defer_op_type *type) +{ + defer_op_types[type->type] = type; +} + +/* Initialize a deferred operation. */ +void +xfs_defer_init( + struct xfs_defer_ops *dop, + xfs_fsblock_t *fbp) +{ + dop->dop_committed = false; + dop->dop_low = false; + memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); + *fbp = NULLFSBLOCK; + INIT_LIST_HEAD(&dop->dop_intake); + INIT_LIST_HEAD(&dop->dop_pending); +} diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h new file mode 100644 index 0000000..85c7a3a --- /dev/null +++ b/libxfs/xfs_defer.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_DEFER_H__ +#define __XFS_DEFER_H__ + +struct xfs_defer_op_type; + +/* + * Save a log intent item and a list of extents, so that we can replay + * whatever action had to happen to the extent list and file the log done + * item. + */ +struct xfs_defer_pending { + const struct xfs_defer_op_type *dfp_type; /* function pointers */ + struct list_head dfp_list; /* pending items */ + bool dfp_committed; /* committed trans? */ + void *dfp_intent; /* log intent item */ + struct list_head dfp_work; /* work items */ + unsigned int dfp_count; /* # extent items */ +}; + +/* + * Header for deferred operation list. + * + * dop_low is used by the allocator to activate the lowspace algorithm - + * when free space is running low the extent allocator may choose to + * allocate an extent from an AG without leaving sufficient space for + * a btree split when inserting the new extent. In this case the allocator + * will enable the lowspace algorithm which is supposed to allow further + * allocations (such as btree splits and newroots) to allocate from + * sequential AGs. In order to avoid locking AGs out of order the lowspace + * algorithm will start searching for free space from AG 0. If the correct + * transaction reservations have been made then this algorithm will eventually + * find all the space it needs. + */ +enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_MAX, +}; + +#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ + +struct xfs_defer_ops { + bool dop_committed; /* did any trans commit? */ + bool dop_low; /* alloc in low mode */ + struct list_head dop_intake; /* unlogged pending work */ + struct list_head dop_pending; /* logged pending work */ + + /* relog these inodes with each roll */ + struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; +}; + +void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, + struct list_head *h); +int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop, + struct xfs_inode *ip); +void xfs_defer_cancel(struct xfs_defer_ops *dop); +void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); +bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); +int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip); + +/* Description of a deferred type. */ +struct xfs_defer_op_type { + enum xfs_defer_ops_type type; + unsigned int max_items; + void (*abort_intent)(void *); + void *(*create_done)(struct xfs_trans *, void *, unsigned int); + int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, + struct list_head *, void *, void **); + void (*finish_cleanup)(struct xfs_trans *, void *, int); + void (*cancel_item)(struct list_head *); + int (*diff_items)(void *, struct list_head *, struct list_head *); + void *(*create_intent)(struct xfs_trans *, uint); + void (*log_item)(struct xfs_trans *, void *, struct list_head *); +}; + +void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); +void xfs_defer_init_types(void); + +#endif /* __XFS_DEFER_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:33:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AF94380C4 for ; Thu, 16 Jun 2016 20:33:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 812318F804B for ; Thu, 16 Jun 2016 18:33:03 -0700 (PDT) X-ASG-Debug-ID: 1466127181-04cbb01fec69f30001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id zHxBQt8G3kbbsekA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1X0PB002310 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:00 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1X0Ve000864 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:00 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1WvNF022388; Fri, 17 Jun 2016 01:32:59 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:32:57 -0700 Subject: [PATCH 021/145] xfs: add tracepoints for the deferred ops mechanism From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 021/145] xfs: add tracepoints for the deferred ops mechanism To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:32:55 -0700 Message-ID: <146612717592.16048.7184368661724183008.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127181 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4834 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 15 +++++++++++++++ libxfs/xfs_defer.c | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 56c4533..dd0d46f 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -169,6 +169,21 @@ #define trace_xfs_btree_updkeys(...) ((void) 0) #define trace_xfs_btree_overlapped_query_range(...) ((void) 0) +#define trace_xfs_defer_intake_work(...) ((void) 0) +#define trace_xfs_defer_trans_abort(...) ((void) 0) +#define trace_xfs_defer_pending_abort(...) ((void) 0) +#define trace_xfs_defer_trans_roll(...) ((void) 0) +#define trace_xfs_defer_trans_roll_error(...) ((void) 0) +#define trace_xfs_defer_finish(...) ((void) 0) +#define trace_xfs_defer_pending_commit(...) ((void) 0) +#define trace_xfs_defer_pending_finish(...) ((void) 0) +#define trace_xfs_defer_finish_error(...) ((void) 0) +#define trace_xfs_defer_finish_done(...) ((void) 0) +#define trace_xfs_defer_cancel(...) ((void) 0) +#define trace_xfs_defer_intake_cancel(...) ((void) 0) +#define trace_xfs_defer_pending_cancel(...) ((void) 0) +#define trace_xfs_defer_init(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_defer.c b/libxfs/xfs_defer.c index 5ae5e0d..069b7bb 100644 --- a/libxfs/xfs_defer.c +++ b/libxfs/xfs_defer.c @@ -163,6 +163,7 @@ xfs_defer_intake_work( struct xfs_defer_pending *dfp; list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { + trace_xfs_defer_intake_work(tp->t_mountp, dfp); dfp->dfp_intent = dfp->dfp_type->create_intent(tp, dfp->dfp_count); list_sort(tp->t_mountp, &dfp->dfp_work, @@ -183,6 +184,7 @@ xfs_defer_trans_abort( { struct xfs_defer_pending *dfp; + trace_xfs_defer_trans_abort(tp->t_mountp, dop); /* * If the transaction was committed, drop the intent reference * since we're bailing out of here. The other reference is @@ -195,6 +197,7 @@ xfs_defer_trans_abort( /* Abort intent items. */ list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { + trace_xfs_defer_pending_abort(tp->t_mountp, dfp); if (dfp->dfp_committed) dfp->dfp_type->abort_intent(dfp->dfp_intent); } @@ -221,9 +224,12 @@ xfs_defer_trans_roll( xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); } + trace_xfs_defer_trans_roll((*tp)->t_mountp, dop); + /* Roll the transaction. */ error = xfs_trans_roll(tp, ip); if (error) { + trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error); xfs_defer_trans_abort(*tp, dop, error); return error; } @@ -295,6 +301,8 @@ xfs_defer_finish( ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); + trace_xfs_defer_finish((*tp)->t_mountp, dop); + /* Until we run out of pending work to finish... */ while (xfs_defer_has_unfinished_work(dop)) { /* Log intents for work items sitting in the intake. */ @@ -309,12 +317,14 @@ xfs_defer_finish( list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { if (dfp->dfp_committed) break; + trace_xfs_defer_pending_commit((*tp)->t_mountp, dfp); dfp->dfp_committed = true; } /* Log an intent-done item for the first pending item. */ dfp = list_first_entry(&dop->dop_pending, struct xfs_defer_pending, dfp_list); + trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, dfp->dfp_count); cleanup_fn = dfp->dfp_type->finish_cleanup; @@ -370,6 +380,10 @@ xfs_defer_finish( } out: + if (error) + trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); + else + trace_xfs_defer_finish_done((*tp)->t_mountp, dop); return error; } @@ -385,11 +399,14 @@ xfs_defer_cancel( struct list_head *pwi; struct list_head *n; + trace_xfs_defer_cancel(NULL, dop); + /* * Free the pending items. Caller should already have arranged * for the intent items to be released. */ list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { + trace_xfs_defer_intake_cancel(NULL, dfp); list_del(&dfp->dfp_list); list_for_each_safe(pwi, n, &dfp->dfp_work) { list_del(pwi); @@ -400,6 +417,7 @@ xfs_defer_cancel( kmem_free(dfp); } list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { + trace_xfs_defer_pending_cancel(NULL, dfp); list_del(&dfp->dfp_list); list_for_each_safe(pwi, n, &dfp->dfp_work) { list_del(pwi); @@ -468,4 +486,5 @@ xfs_defer_init( *fbp = NULLFSBLOCK; INIT_LIST_HEAD(&dop->dop_intake); INIT_LIST_HEAD(&dop->dop_pending); + trace_xfs_defer_init(NULL, dop); } From darrick.wong@oracle.com Thu Jun 16 20:33:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 377378051 for ; Thu, 16 Jun 2016 20:33:09 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id DD18A30404E for ; Thu, 16 Jun 2016 18:33:08 -0700 (PDT) X-ASG-Debug-ID: 1466127186-04bdf01e1796000001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 4va3BwPr73bCOH3R (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1X5gu002577 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:33:05 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1X45M027150 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:05 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1X3OC022484; Fri, 17 Jun 2016 01:33:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:03 -0700 Subject: [PATCH 022/145] xfs: enable the xfs_defer mechanism to process extents to free From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 022/145] xfs: enable the xfs_defer mechanism to process extents to free To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:33:02 -0700 Message-ID: <146612718210.16048.5959888533223391397.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127187 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3433 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.60 X-Barracuda-Spam-Status: No, SCORE=2.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_MV0249, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 2.00 BSF_SC0_MV0249 Custom rule MV0249 Connect the xfs_defer mechanism with the pieces that we'll need to handle deferred extent freeing. We'll wire up the existing code to our new deferred mechanism later. Signed-off-by: Darrick J. Wong --- libxfs/defer_item.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_defer.h | 1 + 2 files changed, 101 insertions(+) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index 06d294f..72c28f8 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -28,9 +28,109 @@ #include "xfs_mount.h" #include "xfs_defer.h" #include "xfs_trans.h" +#include "xfs_bmap.h" +#include "xfs_alloc.h" + +/* Extent Freeing */ + +/* Sort bmap items by AG. */ +static int +xfs_bmap_free_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_mount *mp = priv; + struct xfs_bmap_free_item *ra; + struct xfs_bmap_free_item *rb; + + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); +} + +/* Get an EFI. */ +STATIC void * +xfs_bmap_free_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return NULL; +} + +/* Log a free extent to the intent item. */ +STATIC void +xfs_bmap_free_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ +} + +/* Get an EFD so we can process all the free extents. */ +STATIC void * +xfs_bmap_free_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return NULL; +} + +/* Process a free extent. */ +STATIC int +xfs_bmap_free_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + struct xfs_bmap_free_item *free; + int error; + + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); + error = xfs_free_extent(tp, free->xbfi_startblock, + free->xbfi_blockcount); + kmem_free(free); + return error; +} + +/* Abort all pending EFIs. */ +STATIC void +xfs_bmap_free_abort_intent( + void *intent) +{ +} + +/* Cancel a free extent. */ +STATIC void +xfs_bmap_free_cancel_item( + struct list_head *item) +{ + struct xfs_bmap_free_item *free; + + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); + kmem_free(free); +} + +const struct xfs_defer_op_type xfs_extent_free_defer_type = { + .type = XFS_DEFER_OPS_TYPE_FREE, + .diff_items = xfs_bmap_free_diff_items, + .create_intent = xfs_bmap_free_create_intent, + .abort_intent = xfs_bmap_free_abort_intent, + .log_item = xfs_bmap_free_log_item, + .create_done = xfs_bmap_free_create_done, + .finish_item = xfs_bmap_free_finish_item, + .cancel_item = xfs_bmap_free_cancel_item, +}; + +/* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_extent_free_defer_type); } diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h index 85c7a3a..743fc32 100644 --- a/libxfs/xfs_defer.h +++ b/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_FREE, XFS_DEFER_OPS_TYPE_MAX, }; From darrick.wong@oracle.com Thu Jun 16 20:33:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B273180D7 for ; Thu, 16 Jun 2016 20:33:15 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 75DA78F804B for ; Thu, 16 Jun 2016 18:33:15 -0700 (PDT) X-ASG-Debug-ID: 1466127192-04cb6c542457da0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Vqf31AyYTskyz6r1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:12 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1XBmi002705 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:11 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XA8i022013 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:10 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1XAXT031364; Fri, 17 Jun 2016 01:33:10 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:09 -0700 Subject: [PATCH 023/145] xfs: rework xfs_bmap_free callers to use xfs_defer_ops From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 023/145] xfs: rework xfs_bmap_free callers to use xfs_defer_ops To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:33:08 -0700 Message-ID: <146612718828.16048.16763151461118598547.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127192 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14612 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Rework everything that used xfs_bmap_free to use xfs_defer_ops instead. For now we'll just remove the old symbols and play some cpp magic to make it work; in the next patch we'll actually rename everything. Signed-off-by: Darrick J. Wong --- include/libxfs.h | 5 +++- libxfs/libxfs_api_defs.h | 2 -- libxfs/util.c | 25 +-------------------- libxfs/xfs_alloc.c | 1 + libxfs/xfs_attr.c | 1 + libxfs/xfs_attr_remote.c | 1 + libxfs/xfs_bmap.c | 55 +++++++++------------------------------------- libxfs/xfs_bmap.h | 32 --------------------------- libxfs/xfs_bmap_btree.c | 5 +++- libxfs/xfs_btree.c | 1 + libxfs/xfs_defer.h | 7 ++++++ libxfs/xfs_dir2.c | 1 + libxfs/xfs_ialloc.c | 1 + libxfs/xfs_inode_buf.c | 1 + libxfs/xfs_sb.c | 1 + 15 files changed, 34 insertions(+), 105 deletions(-) diff --git a/include/libxfs.h b/include/libxfs.h index a34a3a9..71e758b 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -60,6 +60,7 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len); #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" @@ -163,7 +164,9 @@ extern unsigned int libxfs_log2_roundup(unsigned int i); extern int libxfs_alloc_file_space (struct xfs_inode *, xfs_off_t, xfs_off_t, int, int); -extern int libxfs_bmap_finish(xfs_trans_t **, xfs_bmap_free_t *, struct xfs_inode *); +#define libxfs_bmap_finish xfs_defer_finish +#define libxfs_bmap_cancel xfs_defer_cancel +#define xfs_bmap_free_t struct xfs_defer_ops extern void libxfs_fs_repair_cmn_err(int, struct xfs_mount *, char *, ...); extern void libxfs_fs_cmn_err(int, struct xfs_mount *, char *, ...); diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 611a849..84b86bc 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -63,10 +63,8 @@ #define xfs_attr_leaf_newentsize libxfs_attr_leaf_newentsize #define xfs_alloc_fix_freelist libxfs_alloc_fix_freelist -#define xfs_bmap_cancel libxfs_bmap_cancel #define xfs_bmap_last_offset libxfs_bmap_last_offset #define xfs_bmap_search_extents libxfs_bmap_search_extents -#define xfs_bmap_finish libxfs_bmap_finish #define xfs_bmapi_write libxfs_bmapi_write #define xfs_bmapi_read libxfs_bmapi_read #define xfs_bunmapi libxfs_bunmapi diff --git a/libxfs/util.c b/libxfs/util.c index f37b396..ab007b0 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -25,6 +25,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode_buf.h" #include "xfs_inode_fork.h" #include "xfs_inode.h" @@ -474,30 +475,6 @@ libxfs_mod_incore_sb( } } -int -libxfs_bmap_finish( - struct xfs_trans **tp, - struct xfs_bmap_free *flist, - struct xfs_inode *ip) -{ - struct xfs_bmap_free_item *free; /* free extent list item */ - int error; - - if (flist->xbf_count == 0) - return 0; - - while (!list_empty(&flist->xbf_flist)) { - free = list_first_entry(&flist->xbf_flist, - struct xfs_bmap_free_item, xbfi_list); - error = xfs_free_extent(*tp, free->xbfi_startblock, - free->xbfi_blockcount); - if (error) - return error; - xfs_bmap_del_free(flist, free); - } - return 0; -} - /* * This routine allocates disk space for the given file. * Originally derived from xfs_alloc_file_space(). diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 7276419..8454816 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_alloc_btree.h" diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 0b05654..ee370dc 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_attr_sf.h" diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c index 79d663e..ed4cc94 100644 --- a/libxfs/xfs_attr_remote.c +++ b/libxfs/xfs_attr_remote.c @@ -24,6 +24,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 65de5ad..a2d8268 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_dir2.h" @@ -587,41 +588,7 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; - list_add(&new->xbfi_list, &flist->xbf_flist); - flist->xbf_count++; -} - -/* - * Remove the entry "free" from the free item list. Prev points to the - * previous entry, unless "free" is the head of the list. - */ -void -xfs_bmap_del_free( - struct xfs_bmap_free *flist, /* free item list header */ - struct xfs_bmap_free_item *free) /* list item to be freed */ -{ - list_del(&free->xbfi_list); - flist->xbf_count--; - kmem_zone_free(xfs_bmap_free_item_zone, free); -} - -/* - * Free up any items left in the list. - */ -void -xfs_bmap_cancel( - struct xfs_bmap_free *flist) /* list of bmap_free_items */ -{ - struct xfs_bmap_free_item *free; /* free list item */ - - if (flist->xbf_count == 0) - return; - while (!list_empty(&flist->xbf_flist)) { - free = list_first_entry(&flist->xbf_flist, - struct xfs_bmap_free_item, xbfi_list); - xfs_bmap_del_free(flist, free); - } - ASSERT(flist->xbf_count == 0); + xfs_defer_add(flist, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); } /* @@ -759,7 +726,7 @@ xfs_bmap_extents_to_btree( if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); - } else if (flist->xbf_low) { + } else if (flist->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = *firstblock; } else { @@ -780,7 +747,7 @@ xfs_bmap_extents_to_btree( ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(*firstblock == NULLFSBLOCK || args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) || - (flist->xbf_low && + (flist->dop_low && args.agno > XFS_FSB_TO_AGNO(mp, *firstblock))); *firstblock = cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; @@ -3700,7 +3667,7 @@ xfs_bmap_btalloc( error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; - } else if (ap->flist->xbf_low) { + } else if (ap->flist->dop_low) { if (xfs_inode_is_filestream(ap->ip)) args.type = XFS_ALLOCTYPE_FIRST_AG; else @@ -3733,7 +3700,7 @@ xfs_bmap_btalloc( * is >= the stripe unit and the allocation offset is * at the end of file. */ - if (!ap->flist->xbf_low && ap->aeof) { + if (!ap->flist->dop_low && ap->aeof) { if (!ap->offset) { args.alignment = stripe_align; atype = args.type; @@ -3826,7 +3793,7 @@ xfs_bmap_btalloc( args.minleft = 0; if ((error = xfs_alloc_vextent(&args))) return error; - ap->flist->xbf_low = 1; + ap->flist->dop_low = true; } if (args.fsbno != NULLFSBLOCK) { /* @@ -3836,7 +3803,7 @@ xfs_bmap_btalloc( ASSERT(*ap->firstblock == NULLFSBLOCK || XFS_FSB_TO_AGNO(mp, *ap->firstblock) == XFS_FSB_TO_AGNO(mp, args.fsbno) || - (ap->flist->xbf_low && + (ap->flist->dop_low && XFS_FSB_TO_AGNO(mp, *ap->firstblock) < XFS_FSB_TO_AGNO(mp, args.fsbno))); @@ -3844,7 +3811,7 @@ xfs_bmap_btalloc( if (*ap->firstblock == NULLFSBLOCK) *ap->firstblock = args.fsbno; ASSERT(nullfb || fb_agno == args.agno || - (ap->flist->xbf_low && fb_agno < args.agno)); + (ap->flist->dop_low && fb_agno < args.agno)); ap->length = args.len; ap->ip->i_d.di_nblocks += args.len; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); @@ -4311,7 +4278,7 @@ xfs_bmapi_allocate( if (error) return error; - if (bma->flist->xbf_low) + if (bma->flist->dop_low) bma->minleft = 0; if (bma->cur) bma->cur->bc_private.b.firstblock = *bma->firstblock; @@ -4676,7 +4643,7 @@ error0: XFS_FSB_TO_AGNO(mp, *firstblock) == XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock) || - (flist->xbf_low && + (flist->dop_low && XFS_FSB_TO_AGNO(mp, *firstblock) < XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock))); diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index c165b2d..9a74610 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -69,27 +69,6 @@ struct xfs_bmap_free_item struct list_head xbfi_list; }; -/* - * Header for free extent list. - * - * xbf_low is used by the allocator to activate the lowspace algorithm - - * when free space is running low the extent allocator may choose to - * allocate an extent from an AG without leaving sufficient space for - * a btree split when inserting the new extent. In this case the allocator - * will enable the lowspace algorithm which is supposed to allow further - * allocations (such as btree splits and newroots) to allocate from - * sequential AGs. In order to avoid locking AGs out of order the lowspace - * algorithm will start searching for free space from AG 0. If the correct - * transaction reservations have been made then this algorithm will eventually - * find all the space it needs. - */ -typedef struct xfs_bmap_free -{ - struct list_head xbf_flist; /* list of to-be-free extents */ - int xbf_count; /* count of items on list */ - int xbf_low; /* alloc in low mode */ -} xfs_bmap_free_t; - #define XFS_BMAP_MAX_NMAP 4 /* @@ -139,14 +118,6 @@ static inline int xfs_bmapi_aflag(int w) #define DELAYSTARTBLOCK ((xfs_fsblock_t)-1LL) #define HOLESTARTBLOCK ((xfs_fsblock_t)-2LL) -static inline void xfs_bmap_init(xfs_bmap_free_t *flp, xfs_fsblock_t *fbp) -{ - INIT_LIST_HEAD(&flp->xbf_flist); - flp->xbf_count = 0; - flp->xbf_low = 0; - *fbp = NULLFSBLOCK; -} - /* * Flags for xfs_bmap_add_extent*. */ @@ -195,9 +166,6 @@ int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist, xfs_fsblock_t bno, xfs_filblks_t len); -void xfs_bmap_cancel(struct xfs_bmap_free *flist); -int xfs_bmap_finish(struct xfs_trans **tp, struct xfs_bmap_free *flist, - struct xfs_inode *ip); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 2ae701e..8d4d4b0 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_alloc.h" @@ -459,7 +460,7 @@ xfs_bmbt_alloc_block( * block allocation here and corrupt the filesystem. */ args.minleft = args.tp->t_blk_res; - } else if (cur->bc_private.b.flist->xbf_low) { + } else if (cur->bc_private.b.flist->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; @@ -487,7 +488,7 @@ xfs_bmbt_alloc_block( error = xfs_alloc_vextent(&args); if (error) goto error0; - cur->bc_private.b.flist->xbf_low = 1; + cur->bc_private.b.flist->dop_low = true; } if (args.fsbno == NULLFSBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 4f48878..c5a475f 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -23,6 +23,7 @@ #include "xfs_trans_resv.h" #include "xfs_bit.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_btree.h" diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h index 743fc32..4c05ba6 100644 --- a/libxfs/xfs_defer.h +++ b/libxfs/xfs_defer.h @@ -94,4 +94,11 @@ struct xfs_defer_op_type { void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); void xfs_defer_init_types(void); +/* XXX: compatibility shims, will go away in the next patch */ +#define xfs_bmap_finish xfs_defer_finish +#define xfs_bmap_cancel xfs_defer_cancel +#define xfs_bmap_init xfs_defer_init +#define xfs_bmap_free xfs_defer_ops +typedef struct xfs_defer_ops xfs_bmap_free_t; + #endif /* __XFS_DEFER_H__ */ diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c index 723b267..402611f 100644 --- a/libxfs/xfs_dir2.c +++ b/libxfs/xfs_dir2.c @@ -21,6 +21,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_da_format.h" #include "xfs_da_btree.h" #include "xfs_inode.h" diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 249512b..44d5e76 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" #include "xfs_ialloc.h" diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index c21a4e6..572c101 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -22,6 +22,7 @@ #include "xfs_log_format.h" #include "xfs_trans_resv.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_cksum.h" #include "xfs_trans.h" diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index e2cc83e..a4ee48e 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -24,6 +24,7 @@ #include "xfs_bit.h" #include "xfs_sb.h" #include "xfs_mount.h" +#include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_ialloc.h" #include "xfs_alloc.h" From darrick.wong@oracle.com Thu Jun 16 20:33:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C66E080AD for ; Thu, 16 Jun 2016 20:33:29 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 961A930404E for ; Thu, 16 Jun 2016 18:33:29 -0700 (PDT) X-ASG-Debug-ID: 1466127203-04cbb01fec69f70001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id mhGapm6kVpbNl6Ab (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:23 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1XHXx015662 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:18 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XHwJ022116 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:17 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XGJb027326; Fri, 17 Jun 2016 01:33:16 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:15 -0700 Subject: [PATCH 024/145] xfs: change xfs_bmap_{finish, cancel, init, free} -> xfs_defer_* From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 024/145] xfs: change xfs_bmap_{finish, cancel, init, free} -> xfs_defer_* To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:33:14 -0700 Message-ID: <146612719455.16048.11674455237736983086.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127203 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 41084 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.60 X-Barracuda-Spam-Status: No, SCORE=2.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_MV0249, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 2.00 BSF_SC0_MV0249 Custom rule MV0249 Drop the compatibility shims that we were using to integrate the new deferred operation mechanism into the existing code. No new code. Signed-off-by: Darrick J. Wong --- include/libxfs.h | 3 -- libxfs/util.c | 8 +++-- libxfs/xfs_attr.c | 58 ++++++++++++++++++++------------------- libxfs/xfs_attr_remote.c | 14 +++++---- libxfs/xfs_bmap.c | 38 +++++++++++++------------- libxfs/xfs_bmap.h | 10 +++---- libxfs/xfs_btree.h | 5 ++- libxfs/xfs_da_btree.h | 4 +-- libxfs/xfs_defer.h | 7 ----- libxfs/xfs_dir2.c | 6 ++-- libxfs/xfs_dir2.h | 8 +++-- libxfs/xfs_ialloc.c | 6 ++-- libxfs/xfs_ialloc.h | 2 + libxfs/xfs_trans_resv.c | 4 +-- mkfs/proto.c | 30 ++++++++++---------- repair/phase6.c | 68 +++++++++++++++++++++++----------------------- 16 files changed, 131 insertions(+), 140 deletions(-) diff --git a/include/libxfs.h b/include/libxfs.h index 71e758b..863b0e3 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -164,9 +164,6 @@ extern unsigned int libxfs_log2_roundup(unsigned int i); extern int libxfs_alloc_file_space (struct xfs_inode *, xfs_off_t, xfs_off_t, int, int); -#define libxfs_bmap_finish xfs_defer_finish -#define libxfs_bmap_cancel xfs_defer_cancel -#define xfs_bmap_free_t struct xfs_defer_ops extern void libxfs_fs_repair_cmn_err(int, struct xfs_mount *, char *, ...); extern void libxfs_fs_cmn_err(int, struct xfs_mount *, char *, ...); diff --git a/libxfs/util.c b/libxfs/util.c index ab007b0..4b81818 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -493,7 +493,7 @@ libxfs_alloc_file_space( xfs_filblks_t allocated_fsb; xfs_filblks_t allocatesize_fsb; xfs_fsblock_t firstfsb; - xfs_bmap_free_t free_list; + struct xfs_defer_ops free_list; xfs_bmbt_irec_t *imapp; xfs_bmbt_irec_t imaps[1]; int reccount; @@ -535,7 +535,7 @@ libxfs_alloc_file_space( } xfs_trans_ijoin(tp, ip, 0); - xfs_bmap_init(&free_list, &firstfsb); + xfs_defer_init(&free_list, &firstfsb); error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb, xfs_bmapi_flags, &firstfsb, 0, imapp, &reccount, &free_list); @@ -544,7 +544,7 @@ libxfs_alloc_file_space( goto error0; /* complete the transaction */ - error = xfs_bmap_finish(&tp, &free_list, ip); + error = xfs_defer_finish(&tp, &free_list, ip); if (error) goto error0; @@ -562,7 +562,7 @@ libxfs_alloc_file_space( return error; error0: /* Cancel bmap, cancel trans */ - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); xfs_trans_cancel(tp); return error; } diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index ee370dc..06b3c5d 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -199,7 +199,7 @@ xfs_attr_set( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_bmap_free flist; + struct xfs_defer_ops flist; struct xfs_trans_res tres; xfs_fsblock_t firstblock; int rsvd = (flags & ATTR_ROOT) != 0; @@ -312,13 +312,13 @@ xfs_attr_set( * It won't fit in the shortform, transform to a leaf block. * GROT: another possible req'mt for a double-split btree op. */ - xfs_bmap_init(args.flist, args.firstblock); + xfs_defer_init(args.flist, args.firstblock); error = xfs_attr_shortform_to_leaf(&args); if (!error) - error = xfs_bmap_finish(&args.trans, args.flist, dp); + error = xfs_defer_finish(&args.trans, args.flist, dp); if (error) { args.trans = NULL; - xfs_bmap_cancel(&flist); + xfs_defer_cancel(&flist); goto out; } @@ -378,7 +378,7 @@ xfs_attr_remove( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_bmap_free flist; + struct xfs_defer_ops flist; xfs_fsblock_t firstblock; int error; @@ -580,13 +580,13 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit that transaction so that the node_addname() call * can manage its own transactions. */ - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } @@ -670,15 +670,15 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } } @@ -733,14 +733,14 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } } @@ -859,14 +859,14 @@ restart: */ xfs_da_state_free(state); state = NULL; - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } @@ -887,13 +887,13 @@ restart: * in the index/blkno/rmtblkno/rmtblkcnt fields and * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_da3_split(state); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } } else { @@ -986,14 +986,14 @@ restart: * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_da3_join(state); if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } } @@ -1109,13 +1109,13 @@ xfs_attr_node_removename(xfs_da_args_t *args) * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_da3_join(state); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } /* @@ -1142,15 +1142,15 @@ xfs_attr_node_removename(xfs_da_args_t *args) goto out; if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_bmap_finish(&args->trans, + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); goto out; } } else diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c index ed4cc94..dc545f0 100644 --- a/libxfs/xfs_attr_remote.c +++ b/libxfs/xfs_attr_remote.c @@ -456,16 +456,16 @@ xfs_attr_rmtval_set( * extent and then crash then the block may not contain the * correct metadata after log recovery occurs. */ - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); nmap = 1; error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, args->total, &map, &nmap, args->flist); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->flist, dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } @@ -499,7 +499,7 @@ xfs_attr_rmtval_set( ASSERT(blkcnt > 0); - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); nmap = 1; error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, @@ -599,16 +599,16 @@ xfs_attr_rmtval_remove( blkcnt = args->rmtblkcnt; done = 0; while (!done) { - xfs_bmap_init(args->flist, args->firstblock); + xfs_defer_init(args->flist, args->firstblock); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, args->firstblock, args->flist, &done); if (!error) - error = xfs_bmap_finish(&args->trans, args->flist, + error = xfs_defer_finish(&args->trans, args->flist, args->dp); if (error) { args->trans = NULL; - xfs_bmap_cancel(args->flist); + xfs_defer_cancel(args->flist); return error; } diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index a2d8268..0faa0a9 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -564,7 +564,7 @@ xfs_bmap_validate_ret( void xfs_bmap_add_free( struct xfs_mount *mp, /* mount point structure */ - struct xfs_bmap_free *flist, /* list of extents */ + struct xfs_defer_ops *flist, /* list of extents */ xfs_fsblock_t bno, /* fs block number of extent */ xfs_filblks_t len) /* length of extent */ { @@ -664,7 +664,7 @@ xfs_bmap_extents_to_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first-block-allocated */ - xfs_bmap_free_t *flist, /* blocks freed in xaction */ + struct xfs_defer_ops *flist, /* blocks freed in xaction */ xfs_btree_cur_t **curp, /* cursor returned to caller */ int wasdel, /* converting a delayed alloc */ int *logflagsp, /* inode logging flags */ @@ -932,7 +932,7 @@ xfs_bmap_add_attrfork_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - xfs_bmap_free_t *flist, /* blocks to free at commit */ + struct xfs_defer_ops *flist, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -975,7 +975,7 @@ xfs_bmap_add_attrfork_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - xfs_bmap_free_t *flist, /* blocks to free at commit */ + struct xfs_defer_ops *flist, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -1010,7 +1010,7 @@ xfs_bmap_add_attrfork_local( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - xfs_bmap_free_t *flist, /* blocks to free at commit */ + struct xfs_defer_ops *flist, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_da_args_t dargs; /* args for dir/attr code */ @@ -1051,7 +1051,7 @@ xfs_bmap_add_attrfork( int rsvd) /* xact may use reserved blks */ { xfs_fsblock_t firstblock; /* 1st block/ag allocated */ - xfs_bmap_free_t flist; /* freed extent records */ + struct xfs_defer_ops flist; /* freed extent records */ xfs_mount_t *mp; /* mount structure */ xfs_trans_t *tp; /* transaction pointer */ int blks; /* space reservation */ @@ -1117,7 +1117,7 @@ xfs_bmap_add_attrfork( ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); ip->i_afp->if_flags = XFS_IFEXTENTS; logflags = 0; - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); switch (ip->i_d.di_format) { case XFS_DINODE_FMT_LOCAL: error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist, @@ -1157,7 +1157,7 @@ xfs_bmap_add_attrfork( xfs_log_sb(tp); } - error = xfs_bmap_finish(&tp, &flist, NULL); + error = xfs_defer_finish(&tp, &flist, NULL); if (error) goto bmap_cancel; error = xfs_trans_commit(tp); @@ -1165,7 +1165,7 @@ xfs_bmap_add_attrfork( return error; bmap_cancel: - xfs_bmap_cancel(&flist); + xfs_defer_cancel(&flist); trans_cancel: xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -2206,7 +2206,7 @@ xfs_bmap_add_extent_unwritten_real( xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ - xfs_bmap_free_t *flist, /* list of extents to be freed */ + struct xfs_defer_ops *flist, /* list of extents to be freed */ int *logflagsp) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -4439,7 +4439,7 @@ xfs_bmapi_write( xfs_extlen_t total, /* total blocks needed */ struct xfs_bmbt_irec *mval, /* output: map values */ int *nmap, /* i/o: mval size/count */ - struct xfs_bmap_free *flist) /* i/o: list extents to free */ + struct xfs_defer_ops *flist) /* i/o: list extents to free */ { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; @@ -4727,7 +4727,7 @@ xfs_bmap_del_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current transaction pointer */ xfs_extnum_t *idx, /* extent number to update/delete */ - xfs_bmap_free_t *flist, /* list of extents to be freed */ + struct xfs_defer_ops *flist, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ @@ -5056,7 +5056,7 @@ xfs_bunmapi( xfs_extnum_t nexts, /* number of extents max */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ - xfs_bmap_free_t *flist, /* i/o: list extents to free */ + struct xfs_defer_ops *flist, /* i/o: list extents to free */ int *done) /* set if not done yet */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -5670,7 +5670,7 @@ xfs_bmap_shift_extents( int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_bmap_free *flist, + struct xfs_defer_ops *flist, enum shift_direction direction, int num_exts) { @@ -5824,7 +5824,7 @@ xfs_bmap_split_extent_at( struct xfs_inode *ip, xfs_fileoff_t split_fsb, xfs_fsblock_t *firstfsb, - struct xfs_bmap_free *free_list) + struct xfs_defer_ops *free_list) { int whichfork = XFS_DATA_FORK; struct xfs_btree_cur *cur = NULL; @@ -5963,7 +5963,7 @@ xfs_bmap_split_extent( { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; - struct xfs_bmap_free free_list; + struct xfs_defer_ops free_list; xfs_fsblock_t firstfsb; int error; @@ -5975,21 +5975,21 @@ xfs_bmap_split_extent( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_bmap_init(&free_list, &firstfsb); + xfs_defer_init(&free_list, &firstfsb); error = xfs_bmap_split_extent_at(tp, ip, split_fsb, &firstfsb, &free_list); if (error) goto out; - error = xfs_bmap_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &free_list, NULL); if (error) goto out; return xfs_trans_commit(tp); out: - xfs_bmap_cancel(&free_list); + xfs_defer_cancel(&free_list); xfs_trans_cancel(tp); return error; } diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index 9a74610..a779cc5 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -32,7 +32,7 @@ extern kmem_zone_t *xfs_bmap_free_item_zone; */ struct xfs_bmalloca { xfs_fsblock_t *firstblock; /* i/o first block allocated */ - struct xfs_bmap_free *flist; /* bmap freelist */ + struct xfs_defer_ops *flist; /* bmap freelist */ struct xfs_trans *tp; /* transaction pointer */ struct xfs_inode *ip; /* incore inode pointer */ struct xfs_bmbt_irec prev; /* extent before the new one */ @@ -164,7 +164,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); -void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist, +void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *flist, xfs_fsblock_t bno, xfs_filblks_t len); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, @@ -186,18 +186,18 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_fsblock_t *firstblock, xfs_extlen_t total, struct xfs_bmbt_irec *mval, int *nmap, - struct xfs_bmap_free *flist); + struct xfs_defer_ops *flist); int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, - struct xfs_bmap_free *flist, int *done); + struct xfs_defer_ops *flist, int *done); int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, xfs_extnum_t num); uint xfs_default_attroffset(struct xfs_inode *ip); int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_bmap_free *flist, enum shift_direction direction, + struct xfs_defer_ops *flist, enum shift_direction direction, int num_exts); int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 0ec3055..ae714a8 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -19,7 +19,7 @@ #define __XFS_BTREE_H__ struct xfs_buf; -struct xfs_bmap_free; +struct xfs_defer_ops; struct xfs_inode; struct xfs_mount; struct xfs_trans; @@ -234,11 +234,12 @@ typedef struct xfs_btree_cur union { struct { /* needed for BNO, CNT, INO */ struct xfs_buf *agbp; /* agf/agi buffer pointer */ + struct xfs_defer_ops *flist; /* deferred updates */ xfs_agnumber_t agno; /* ag number */ } a; struct { /* needed for BMAP */ struct xfs_inode *ip; /* pointer to our inode */ - struct xfs_bmap_free *flist; /* list to free after */ + struct xfs_defer_ops *flist; /* deferred updates */ xfs_fsblock_t firstblock; /* 1st blk allocated */ int allocated; /* count of alloced */ short forksize; /* fork's inode space */ diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h index 6e153e3..249813a 100644 --- a/libxfs/xfs_da_btree.h +++ b/libxfs/xfs_da_btree.h @@ -19,7 +19,7 @@ #ifndef __XFS_DA_BTREE_H__ #define __XFS_DA_BTREE_H__ -struct xfs_bmap_free; +struct xfs_defer_ops; struct xfs_inode; struct xfs_trans; struct zone; @@ -70,7 +70,7 @@ typedef struct xfs_da_args { xfs_ino_t inumber; /* input/output inode number */ struct xfs_inode *dp; /* directory inode to manipulate */ xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */ - struct xfs_bmap_free *flist; /* ptr to freelist for bmap_finish */ + struct xfs_defer_ops *flist; /* ptr to freelist for bmap_finish */ struct xfs_trans *trans; /* current trans (changes over time) */ xfs_extlen_t total; /* total blocks needed, for 1st bmap */ int whichfork; /* data or attribute fork */ diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h index 4c05ba6..743fc32 100644 --- a/libxfs/xfs_defer.h +++ b/libxfs/xfs_defer.h @@ -94,11 +94,4 @@ struct xfs_defer_op_type { void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); void xfs_defer_init_types(void); -/* XXX: compatibility shims, will go away in the next patch */ -#define xfs_bmap_finish xfs_defer_finish -#define xfs_bmap_cancel xfs_defer_cancel -#define xfs_bmap_init xfs_defer_init -#define xfs_bmap_free xfs_defer_ops -typedef struct xfs_defer_ops xfs_bmap_free_t; - #endif /* __XFS_DEFER_H__ */ diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c index 402611f..6edaa8e 100644 --- a/libxfs/xfs_dir2.c +++ b/libxfs/xfs_dir2.c @@ -258,7 +258,7 @@ xfs_dir_createname( struct xfs_name *name, xfs_ino_t inum, /* new entry inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - xfs_bmap_free_t *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -435,7 +435,7 @@ xfs_dir_removename( struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, /* bmap's firstblock */ - xfs_bmap_free_t *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -497,7 +497,7 @@ xfs_dir_replace( struct xfs_name *name, /* name of entry to replace */ xfs_ino_t inum, /* new inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - xfs_bmap_free_t *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *flist, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h index 0a62e73..5737d85 100644 --- a/libxfs/xfs_dir2.h +++ b/libxfs/xfs_dir2.h @@ -18,7 +18,7 @@ #ifndef __XFS_DIR2_H__ #define __XFS_DIR2_H__ -struct xfs_bmap_free; +struct xfs_defer_ops; struct xfs_da_args; struct xfs_inode; struct xfs_mount; @@ -129,18 +129,18 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_bmap_free *flist, xfs_extlen_t tot); + struct xfs_defer_ops *flist, xfs_extlen_t tot); extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t *inum, struct xfs_name *ci_name); extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, - struct xfs_bmap_free *flist, xfs_extlen_t tot); + struct xfs_defer_ops *flist, xfs_extlen_t tot); extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_bmap_free *flist, xfs_extlen_t tot); + struct xfs_defer_ops *flist, xfs_extlen_t tot); extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name); diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 44d5e76..d03570c 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -1812,7 +1812,7 @@ xfs_difree_inode_chunk( struct xfs_mount *mp, xfs_agnumber_t agno, struct xfs_inobt_rec_incore *rec, - struct xfs_bmap_free *flist) + struct xfs_defer_ops *flist) { xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); int startidx, endidx; @@ -1884,7 +1884,7 @@ xfs_difree_inobt( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agino_t agino, - struct xfs_bmap_free *flist, + struct xfs_defer_ops *flist, struct xfs_icluster *xic, struct xfs_inobt_rec_incore *orec) { @@ -2116,7 +2116,7 @@ int xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_bmap_free *flist, /* extents to free */ + struct xfs_defer_ops *flist, /* extents to free */ struct xfs_icluster *xic) /* cluster info if deleted */ { /* REFERENCED */ diff --git a/libxfs/xfs_ialloc.h b/libxfs/xfs_ialloc.h index 6e450df..2e06b67 100644 --- a/libxfs/xfs_ialloc.h +++ b/libxfs/xfs_ialloc.h @@ -95,7 +95,7 @@ int /* error */ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_bmap_free *flist, /* extents to free */ + struct xfs_defer_ops *flist, /* extents to free */ struct xfs_icluster *ifree); /* cluster info if deleted */ /* diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c index 9e519a5..c55220f 100644 --- a/libxfs/xfs_trans_resv.c +++ b/libxfs/xfs_trans_resv.c @@ -152,9 +152,9 @@ xfs_calc_finobt_res( * item logged to try to account for the overhead of the transaction mechanism. * * Note: Most of the reservations underestimate the number of allocation - * groups into which they could free extents in the xfs_bmap_finish() call. + * groups into which they could free extents in the xfs_defer_finish() call. * This is because the number in the worst case is quite high and quite - * unusual. In order to fix this we need to change xfs_bmap_finish() to free + * unusual. In order to fix this we need to change xfs_defer_finish() to free * extents in only a single AG at a time. This will require changes to the * EFI code as well, however, so that the EFI for the extents not freed is * logged again in each transaction. See SGI PV #261917. diff --git a/mkfs/proto.c b/mkfs/proto.c index edbaa33..f0c33e4 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -27,7 +27,7 @@ static char *getstr(char **pp); static void fail(char *msg, int i); static void getres(struct xfs_mount *mp, uint blocks, struct xfs_trans **tpp); static void rsvfile(xfs_mount_t *mp, xfs_inode_t *ip, long long len); -static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, xfs_bmap_free_t *flist, +static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, struct xfs_defer_ops *flist, xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len); static char *newregfile(char **pp, int *len); static void rtinit(xfs_mount_t *mp); @@ -236,7 +236,7 @@ static int newfile( xfs_trans_t *tp, xfs_inode_t *ip, - xfs_bmap_free_t *flist, + struct xfs_defer_ops *flist, xfs_fsblock_t *first, int dolocal, int logit, @@ -329,7 +329,7 @@ newdirent( struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - xfs_bmap_free_t *flist) + struct xfs_defer_ops *flist) { int error; int rsv; @@ -375,7 +375,7 @@ parseproto( int error; xfs_fsblock_t first; int flags; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; int fmt; int i; xfs_inode_t *ip; @@ -460,7 +460,7 @@ parseproto( xname.len = name ? strlen(name) : 0; xname.type = 0; flags = XFS_ILOG_CORE; - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); switch (fmt) { case IF_REGULAR: buf = newregfile(pp, &len); @@ -500,7 +500,7 @@ parseproto( newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); libxfs_trans_log_inode(tp, ip, flags); - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); if (error) fail(_("Pre-allocated file creation failed"), error); libxfs_trans_commit(tp); @@ -582,7 +582,7 @@ parseproto( } newdirectory(mp, tp, ip, pip); libxfs_trans_log_inode(tp, ip, flags); - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); if (error) fail(_("Directory creation failed"), error); libxfs_trans_commit(tp); @@ -608,7 +608,7 @@ parseproto( fail(_("Unknown format"), EINVAL); } libxfs_trans_log_inode(tp, ip, flags); - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); if (error) { fail(_("Error encountered creating file from prototype file"), error); @@ -638,7 +638,7 @@ rtinit( xfs_bmbt_irec_t *ep; int error; xfs_fsblock_t first; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; int i; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; xfs_extlen_t nsumblocks; @@ -697,7 +697,7 @@ rtinit( libxfs_trans_ijoin(tp, rbmip, 0); bno = 0; - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); while (bno < mp->m_sb.sb_rbmblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, rbmip, bno, @@ -716,7 +716,7 @@ rtinit( } } - error = -libxfs_bmap_finish(&tp, &flist, rbmip); + error = -xfs_defer_finish(&tp, &flist, rbmip); if (error) { fail(_("Completion of the realtime bitmap failed"), error); } @@ -732,7 +732,7 @@ rtinit( res_failed(i); libxfs_trans_ijoin(tp, rsumip, 0); bno = 0; - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); while (bno < nsumblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, rsumip, bno, @@ -750,7 +750,7 @@ rtinit( bno += ep->br_blockcount; } } - error = -libxfs_bmap_finish(&tp, &flist, rsumip); + error = -xfs_defer_finish(&tp, &flist, rsumip); if (error) { fail(_("Completion of the realtime summary failed"), error); } @@ -765,7 +765,7 @@ rtinit( if (i) res_failed(i); libxfs_trans_ijoin(tp, rbmip, 0); - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); ebno = XFS_RTMIN(mp->m_sb.sb_rextents, bno + NBBY * mp->m_sb.sb_blocksize); error = -libxfs_rtfree_extent(tp, bno, (xfs_extlen_t)(ebno-bno)); @@ -773,7 +773,7 @@ rtinit( fail(_("Error initializing the realtime space"), error); } - error = -libxfs_bmap_finish(&tp, &flist, rbmip); + error = -xfs_defer_finish(&tp, &flist, rbmip); if (error) { fail(_("Error completing the realtime space"), error); } diff --git a/repair/phase6.c b/repair/phase6.c index d1acb68..961f7bc 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -484,7 +484,7 @@ mk_rbmino(xfs_mount_t *mp) int i; int nmap; int error; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; xfs_fileoff_t bno; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; int vers; @@ -550,7 +550,7 @@ mk_rbmino(xfs_mount_t *mp) libxfs_trans_ijoin(tp, ip, 0); bno = 0; - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); while (bno < mp->m_sb.sb_rbmblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, ip, bno, @@ -569,7 +569,7 @@ mk_rbmino(xfs_mount_t *mp) bno += ep->br_blockcount; } } - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); if (error) { do_error( _("allocation of the realtime bitmap failed, error = %d\n"), @@ -731,7 +731,7 @@ mk_rsumino(xfs_mount_t *mp) int nmap; int error; int nsumblocks; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; xfs_fileoff_t bno; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; int vers; @@ -789,7 +789,7 @@ mk_rsumino(xfs_mount_t *mp) * then allocate blocks for file and fill with zeroes (stolen * from mkfs) */ - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; tres.tr_logres = BBTOB(128); @@ -803,7 +803,7 @@ mk_rsumino(xfs_mount_t *mp) libxfs_trans_ijoin(tp, ip, 0); bno = 0; - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); while (bno < nsumblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, ip, bno, @@ -821,7 +821,7 @@ mk_rsumino(xfs_mount_t *mp) bno += ep->br_blockcount; } } - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); if (error) { do_error( _("allocation of the realtime summary ino failed, error = %d\n"), @@ -919,7 +919,7 @@ mk_orphanage(xfs_mount_t *mp) int ino_offset = 0; int i; int error; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; const int mode = 0755; int nres; struct xfs_name xname; @@ -945,7 +945,7 @@ mk_orphanage(xfs_mount_t *mp) * could not be found, create it */ - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); nres = XFS_MKDIR_SPACE_RES(mp, xname.len); i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); @@ -1028,7 +1028,7 @@ mk_orphanage(xfs_mount_t *mp) libxfs_dir_init(tp, ip, pip); libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); if (error) { do_error(_("%s directory creation failed -- bmapf error %d\n"), ORPHANAGE, error); @@ -1057,7 +1057,7 @@ mv_orphanage( xfs_inode_t *ino_p; xfs_trans_t *tp; xfs_fsblock_t first; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; int err; unsigned char fname[MAXPATHLEN + 1]; int nres; @@ -1110,7 +1110,7 @@ mv_orphanage( libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino, &first, &flist, nres); if (err) @@ -1134,7 +1134,7 @@ mv_orphanage( inc_nlink(VFS_I(ino_p)); libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE); - err = -libxfs_bmap_finish(&tp, &flist, ino_p); + err = -xfs_defer_finish(&tp, &flist, ino_p); if (err) do_error( _("bmap finish failed (err - %d), filesystem may be out of space\n"), @@ -1152,7 +1152,7 @@ mv_orphanage( libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino, &first, &flist, nres); @@ -1181,7 +1181,7 @@ mv_orphanage( err); } - err = -libxfs_bmap_finish(&tp, &flist, ino_p); + err = -xfs_defer_finish(&tp, &flist, ino_p); if (err) do_error( _("bmap finish failed (%d), filesystem may be out of space\n"), @@ -1208,7 +1208,7 @@ mv_orphanage( libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino, &first, &flist, nres); if (err) @@ -1220,7 +1220,7 @@ mv_orphanage( set_nlink(VFS_I(ino_p), 1); libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE); - err = -libxfs_bmap_finish(&tp, &flist, ino_p); + err = -xfs_defer_finish(&tp, &flist, ino_p); if (err) do_error( _("bmap finish failed (%d), filesystem may be out of space\n"), @@ -1269,7 +1269,7 @@ longform_dir2_rebuild( xfs_trans_t *tp; xfs_fileoff_t lastblock; xfs_fsblock_t firstblock; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; xfs_inode_t pip; dir_hash_ent_t *p; int done; @@ -1292,7 +1292,7 @@ longform_dir2_rebuild( xfs_dir_ino_validate(mp, pip.i_ino)) pip.i_ino = mp->m_sb.sb_rootino; - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); nres = XFS_REMOVE_SPACE_RES(mp); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); @@ -1320,7 +1320,7 @@ longform_dir2_rebuild( goto out_bmap_cancel; } - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); libxfs_trans_commit(tp); @@ -1344,7 +1344,7 @@ longform_dir2_rebuild( libxfs_trans_ijoin(tp, ip, 0); - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); error = -libxfs_dir_createname(tp, ip, &p->name, p->inum, &firstblock, &flist, nres); if (error) { @@ -1354,7 +1354,7 @@ _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n" goto out_bmap_cancel; } - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); if (error) { do_warn( _("bmap finish failed (%d), filesystem may be out of space\n"), @@ -1368,7 +1368,7 @@ _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n" return; out_bmap_cancel: - libxfs_bmap_cancel(&flist); + xfs_defer_cancel(&flist); libxfs_trans_cancel(tp); return; } @@ -1388,7 +1388,7 @@ dir2_kill_block( xfs_da_args_t args; int error; xfs_fsblock_t firstblock; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; int nres; xfs_trans_t *tp; @@ -1399,7 +1399,7 @@ dir2_kill_block( libxfs_trans_ijoin(tp, ip, 0); libxfs_trans_bjoin(tp, bp); memset(&args, 0, sizeof(args)); - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); args.dp = ip; args.trans = tp; args.firstblock = &firstblock; @@ -1414,7 +1414,7 @@ dir2_kill_block( if (error) do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"), ip->i_ino, da_bno); - libxfs_bmap_finish(&tp, &flist, ip); + xfs_defer_finish(&tp, &flist, ip); libxfs_trans_commit(tp); } @@ -1448,7 +1448,7 @@ longform_dir2_entry_check_data( char *endptr; int error; xfs_fsblock_t firstblock; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; char fname[MAXNAMELEN + 1]; freetab_t *freetab; int i; @@ -1590,7 +1590,7 @@ longform_dir2_entry_check_data( libxfs_trans_ijoin(tp, ip, 0); libxfs_trans_bjoin(tp, bp); libxfs_trans_bhold(tp, bp); - xfs_bmap_init(&flist, &firstblock); + xfs_defer_init(&flist, &firstblock); if (be32_to_cpu(d->magic) != wantmagic) { do_warn( _("bad directory block magic # %#x for directory inode %" PRIu64 " block %d: "), @@ -1889,7 +1889,7 @@ _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 " repair_dir2_data_freescan(mp, M_DIROPS(mp), d, &i); if (needlog) libxfs_dir2_data_log_header(&da, bp); - libxfs_bmap_finish(&tp, &flist, ip); + xfs_defer_finish(&tp, &flist, ip); libxfs_trans_commit(tp); /* record the largest free space in the freetab for later checking */ @@ -2805,7 +2805,7 @@ process_dir_inode( int ino_offset) { xfs_ino_t ino; - xfs_bmap_free_t flist; + struct xfs_defer_ops flist; xfs_fsblock_t first; xfs_inode_t *ip; xfs_trans_t *tp; @@ -2943,7 +2943,7 @@ process_dir_inode( libxfs_trans_ijoin(tp, ip, 0); - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot, ip->i_ino, &first, &flist, nres); @@ -2953,7 +2953,7 @@ process_dir_inode( libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); ASSERT(error == 0); libxfs_trans_commit(tp); @@ -3001,7 +3001,7 @@ process_dir_inode( libxfs_trans_ijoin(tp, ip, 0); - xfs_bmap_init(&flist, &first); + xfs_defer_init(&flist, &first); error = -libxfs_dir_createname(tp, ip, &xfs_name_dot, ip->i_ino, &first, &flist, nres); @@ -3012,7 +3012,7 @@ process_dir_inode( libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = -libxfs_bmap_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &flist, ip); ASSERT(error == 0); libxfs_trans_commit(tp); } From darrick.wong@oracle.com Thu Jun 16 20:33:37 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4768E80E5 for ; Thu, 16 Jun 2016 20:33:37 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id B3380AC001 for ; Thu, 16 Jun 2016 18:33:36 -0700 (PDT) X-ASG-Debug-ID: 1466127214-04cb6c542757de0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id UQz22uCkfYCZUdOT (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:34 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1XUbk015768 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:30 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XT3H001645 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:30 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XTHP022557; Fri, 17 Jun 2016 01:33:29 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:28 -0700 Subject: [PATCH 026/145] xfs: add tracepoints and error injection for deferred extent freeing From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 026/145] xfs: add tracepoints and error injection for deferred extent freeing To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:33:27 -0700 Message-ID: <146612720745.16048.11281695022246629048.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127214 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1891 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add a couple of tracepoints for the deferred extent free operation and a site for injecting errors while finishing the operation. This makes it easier to debug deferred ops and test log redo. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 3 +++ libxfs/xfs_alloc.c | 7 +++++++ libxfs/xfs_bmap.c | 2 ++ 3 files changed, 12 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index dd0d46f..cdabd18 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -184,6 +184,9 @@ #define trace_xfs_defer_pending_cancel(...) ((void) 0) #define trace_xfs_defer_init(...) ((void) 0) +#define trace_xfs_bmap_free_deferred(...) ((void) 0) +#define trace_xfs_bmap_free_defer(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 8454816..06133c0 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2700,6 +2700,13 @@ xfs_free_extent( ASSERT(len != 0); + trace_xfs_bmap_free_deferred(mp, agno, 0, agbno, len); + + if (XFS_TEST_ERROR(false, mp, + XFS_ERRTAG_FREE_EXTENT, + XFS_RANDOM_FREE_EXTENT)) + return -EIO; + error = xfs_free_extent_fix_freelist(tp, agno, &agbp); if (error) return error; diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 5385800..33e181c 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -588,6 +588,8 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; + trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0, + XFS_FSB_TO_AGBNO(mp, bno), len); xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); } From darrick.wong@oracle.com Thu Jun 16 20:33:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id AAB8D80E4 for ; Thu, 16 Jun 2016 20:33:36 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 4AA8430404E for ; Thu, 16 Jun 2016 18:33:36 -0700 (PDT) X-ASG-Debug-ID: 1466127208-04bdf01e1596020001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id MFZYRI1OGqQNHdLy (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:28 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1XN0j015703 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:23 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XNIA029012 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:23 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XM5L027343; Fri, 17 Jun 2016 01:33:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:22 -0700 Subject: [PATCH 025/145] xfs: rename flist/free_list to dfops From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 025/145] xfs: rename flist/free_list to dfops To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:33:21 -0700 Message-ID: <146612720098.16048.4119801736083912091.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127208 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 64709 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Mechanical change of flist/free_list to dfops, since they're now deferred ops, not just a freeing list. Signed-off-by: Darrick J. Wong --- libxfs/util.c | 10 ++-- libxfs/xfs_attr.c | 62 ++++++++++++------------- libxfs/xfs_attr_leaf.c | 4 +- libxfs/xfs_attr_remote.c | 18 ++++--- libxfs/xfs_bmap.c | 116 +++++++++++++++++++++++----------------------- libxfs/xfs_bmap.h | 10 ++-- libxfs/xfs_bmap_btree.c | 14 +++--- libxfs/xfs_btree.h | 4 +- libxfs/xfs_da_btree.c | 6 +- libxfs/xfs_da_btree.h | 2 - libxfs/xfs_dir2.c | 14 +++--- libxfs/xfs_dir2.h | 6 +- libxfs/xfs_ialloc.c | 14 +++--- libxfs/xfs_ialloc.h | 2 - mkfs/proto.c | 56 +++++++++++----------- repair/phase6.c | 94 +++++++++++++++++++------------------ repair/sb.c | 10 ++-- 17 files changed, 221 insertions(+), 221 deletions(-) diff --git a/libxfs/util.c b/libxfs/util.c index 4b81818..5b277c2 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -493,7 +493,7 @@ libxfs_alloc_file_space( xfs_filblks_t allocated_fsb; xfs_filblks_t allocatesize_fsb; xfs_fsblock_t firstfsb; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_bmbt_irec_t *imapp; xfs_bmbt_irec_t imaps[1]; int reccount; @@ -535,16 +535,16 @@ libxfs_alloc_file_space( } xfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&free_list, &firstfsb); + xfs_defer_init(&dfops, &firstfsb); error = xfs_bmapi_write(tp, ip, startoffset_fsb, allocatesize_fsb, xfs_bmapi_flags, &firstfsb, 0, imapp, - &reccount, &free_list); + &reccount, &dfops); if (error) goto error0; /* complete the transaction */ - error = xfs_defer_finish(&tp, &free_list, ip); + error = xfs_defer_finish(&tp, &dfops, ip); if (error) goto error0; @@ -562,7 +562,7 @@ libxfs_alloc_file_space( return error; error0: /* Cancel bmap, cancel trans */ - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); xfs_trans_cancel(tp); return error; } diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 06b3c5d..60513f9 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -199,7 +199,7 @@ xfs_attr_set( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; struct xfs_trans_res tres; xfs_fsblock_t firstblock; int rsvd = (flags & ATTR_ROOT) != 0; @@ -217,7 +217,7 @@ xfs_attr_set( args.value = value; args.valuelen = valuelen; args.firstblock = &firstblock; - args.flist = &flist; + args.dfops = &dfops; args.op_flags = XFS_DA_OP_ADDNAME | XFS_DA_OP_OKNOENT; args.total = xfs_attr_calc_size(&args, &local); @@ -312,13 +312,13 @@ xfs_attr_set( * It won't fit in the shortform, transform to a leaf block. * GROT: another possible req'mt for a double-split btree op. */ - xfs_defer_init(args.flist, args.firstblock); + xfs_defer_init(args.dfops, args.firstblock); error = xfs_attr_shortform_to_leaf(&args); if (!error) - error = xfs_defer_finish(&args.trans, args.flist, dp); + error = xfs_defer_finish(&args.trans, args.dfops, dp); if (error) { args.trans = NULL; - xfs_defer_cancel(&flist); + xfs_defer_cancel(&dfops); goto out; } @@ -378,7 +378,7 @@ xfs_attr_remove( { struct xfs_mount *mp = dp->i_mount; struct xfs_da_args args; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; xfs_fsblock_t firstblock; int error; @@ -395,7 +395,7 @@ xfs_attr_remove( return error; args.firstblock = &firstblock; - args.flist = &flist; + args.dfops = &dfops; /* * we have no control over the attribute names that userspace passes us @@ -580,13 +580,13 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * Commit that transaction so that the node_addname() call * can manage its own transactions. */ - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } @@ -670,15 +670,15 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } } @@ -733,14 +733,14 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) * If the result is small enough, shrink it all into the inode. */ if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } } @@ -859,14 +859,14 @@ restart: */ xfs_da_state_free(state); state = NULL; - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_node(args); if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } @@ -887,13 +887,13 @@ restart: * in the index/blkno/rmtblkno/rmtblkcnt fields and * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. */ - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_split(state); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } } else { @@ -986,14 +986,14 @@ restart: * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_join(state); if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } } @@ -1109,13 +1109,13 @@ xfs_attr_node_removename(xfs_da_args_t *args) * Check to see if the tree needs to be collapsed. */ if (retval && (state->path.active > 1)) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_da3_join(state); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } /* @@ -1142,15 +1142,15 @@ xfs_attr_node_removename(xfs_da_args_t *args) goto out; if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); /* bp is gone due to xfs_da_shrink_inode */ if (!error) error = xfs_defer_finish(&args->trans, - args->flist, dp); + args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); goto out; } } else diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c index d0eb0a7..0ca0347 100644 --- a/libxfs/xfs_attr_leaf.c +++ b/libxfs/xfs_attr_leaf.c @@ -787,7 +787,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args) nargs.dp = dp; nargs.geo = args->geo; nargs.firstblock = args->firstblock; - nargs.flist = args->flist; + nargs.dfops = args->dfops; nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; @@ -917,7 +917,7 @@ xfs_attr3_leaf_to_shortform( nargs.geo = args->geo; nargs.dp = dp; nargs.firstblock = args->firstblock; - nargs.flist = args->flist; + nargs.dfops = args->dfops; nargs.total = args->total; nargs.whichfork = XFS_ATTR_FORK; nargs.trans = args->trans; diff --git a/libxfs/xfs_attr_remote.c b/libxfs/xfs_attr_remote.c index dc545f0..abe1705 100644 --- a/libxfs/xfs_attr_remote.c +++ b/libxfs/xfs_attr_remote.c @@ -456,16 +456,16 @@ xfs_attr_rmtval_set( * extent and then crash then the block may not contain the * correct metadata after log recovery occurs. */ - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); nmap = 1; error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, - args->total, &map, &nmap, args->flist); + args->total, &map, &nmap, args->dfops); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, dp); + error = xfs_defer_finish(&args->trans, args->dfops, dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } @@ -499,7 +499,7 @@ xfs_attr_rmtval_set( ASSERT(blkcnt > 0); - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); nmap = 1; error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, blkcnt, &map, &nmap, @@ -599,16 +599,16 @@ xfs_attr_rmtval_remove( blkcnt = args->rmtblkcnt; done = 0; while (!done) { - xfs_defer_init(args->flist, args->firstblock); + xfs_defer_init(args->dfops, args->firstblock); error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, XFS_BMAPI_ATTRFORK, 1, args->firstblock, - args->flist, &done); + args->dfops, &done); if (!error) - error = xfs_defer_finish(&args->trans, args->flist, + error = xfs_defer_finish(&args->trans, args->dfops, args->dp); if (error) { args->trans = NULL; - xfs_defer_cancel(args->flist); + xfs_defer_cancel(args->dfops); return error; } diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 0faa0a9..5385800 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -564,7 +564,7 @@ xfs_bmap_validate_ret( void xfs_bmap_add_free( struct xfs_mount *mp, /* mount point structure */ - struct xfs_defer_ops *flist, /* list of extents */ + struct xfs_defer_ops *dfops, /* list of extents */ xfs_fsblock_t bno, /* fs block number of extent */ xfs_filblks_t len) /* length of extent */ { @@ -588,7 +588,7 @@ xfs_bmap_add_free( new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; - xfs_defer_add(flist, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); } /* @@ -641,7 +641,7 @@ xfs_bmap_btree_to_extents( cblock = XFS_BUF_TO_BLOCK(cbp); if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) return error; - xfs_bmap_add_free(mp, cur->bc_private.b.flist, cbno, 1); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1); ip->i_d.di_nblocks--; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); @@ -664,7 +664,7 @@ xfs_bmap_extents_to_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first-block-allocated */ - struct xfs_defer_ops *flist, /* blocks freed in xaction */ + struct xfs_defer_ops *dfops, /* blocks freed in xaction */ xfs_btree_cur_t **curp, /* cursor returned to caller */ int wasdel, /* converting a delayed alloc */ int *logflagsp, /* inode logging flags */ @@ -713,7 +713,7 @@ xfs_bmap_extents_to_btree( */ cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0; /* * Convert to a btree with two levels, one record in root. @@ -726,7 +726,7 @@ xfs_bmap_extents_to_btree( if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); - } else if (flist->dop_low) { + } else if (dfops->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = *firstblock; } else { @@ -747,7 +747,7 @@ xfs_bmap_extents_to_btree( ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(*firstblock == NULLFSBLOCK || args.agno == XFS_FSB_TO_AGNO(mp, *firstblock) || - (flist->dop_low && + (dfops->dop_low && args.agno > XFS_FSB_TO_AGNO(mp, *firstblock))); *firstblock = cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; @@ -932,7 +932,7 @@ xfs_bmap_add_attrfork_btree( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - struct xfs_defer_ops *flist, /* blocks to free at commit */ + struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -945,7 +945,7 @@ xfs_bmap_add_attrfork_btree( *flags |= XFS_ILOG_DBROOT; else { cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK); - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.firstblock = *firstblock; if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat))) goto error0; @@ -975,7 +975,7 @@ xfs_bmap_add_attrfork_extents( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - struct xfs_defer_ops *flist, /* blocks to free at commit */ + struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -984,7 +984,7 @@ xfs_bmap_add_attrfork_extents( if (ip->i_d.di_nextents * sizeof(xfs_bmbt_rec_t) <= XFS_IFORK_DSIZE(ip)) return 0; cur = NULL; - error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, &cur, 0, + error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops, &cur, 0, flags, XFS_DATA_FORK); if (cur) { cur->bc_private.b.allocated = 0; @@ -1010,7 +1010,7 @@ xfs_bmap_add_attrfork_local( xfs_trans_t *tp, /* transaction pointer */ xfs_inode_t *ip, /* incore inode pointer */ xfs_fsblock_t *firstblock, /* first block allocated */ - struct xfs_defer_ops *flist, /* blocks to free at commit */ + struct xfs_defer_ops *dfops, /* blocks to free at commit */ int *flags) /* inode logging flags */ { xfs_da_args_t dargs; /* args for dir/attr code */ @@ -1023,7 +1023,7 @@ xfs_bmap_add_attrfork_local( dargs.geo = ip->i_mount->m_dir_geo; dargs.dp = ip; dargs.firstblock = firstblock; - dargs.flist = flist; + dargs.dfops = dfops; dargs.total = dargs.geo->fsbcount; dargs.whichfork = XFS_DATA_FORK; dargs.trans = tp; @@ -1051,7 +1051,7 @@ xfs_bmap_add_attrfork( int rsvd) /* xact may use reserved blks */ { xfs_fsblock_t firstblock; /* 1st block/ag allocated */ - struct xfs_defer_ops flist; /* freed extent records */ + struct xfs_defer_ops dfops; /* freed extent records */ xfs_mount_t *mp; /* mount structure */ xfs_trans_t *tp; /* transaction pointer */ int blks; /* space reservation */ @@ -1117,18 +1117,18 @@ xfs_bmap_add_attrfork( ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); ip->i_afp->if_flags = XFS_IFEXTENTS; logflags = 0; - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); switch (ip->i_d.di_format) { case XFS_DINODE_FMT_LOCAL: - error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist, + error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &dfops, &logflags); break; case XFS_DINODE_FMT_EXTENTS: error = xfs_bmap_add_attrfork_extents(tp, ip, &firstblock, - &flist, &logflags); + &dfops, &logflags); break; case XFS_DINODE_FMT_BTREE: - error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &flist, + error = xfs_bmap_add_attrfork_btree(tp, ip, &firstblock, &dfops, &logflags); break; default: @@ -1157,7 +1157,7 @@ xfs_bmap_add_attrfork( xfs_log_sb(tp); } - error = xfs_defer_finish(&tp, &flist, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto bmap_cancel; error = xfs_trans_commit(tp); @@ -1165,7 +1165,7 @@ xfs_bmap_add_attrfork( return error; bmap_cancel: - xfs_defer_cancel(&flist); + xfs_defer_cancel(&dfops); trans_cancel: xfs_trans_cancel(tp); xfs_iunlock(ip, XFS_ILOCK_EXCL); @@ -1962,7 +1962,7 @@ xfs_bmap_add_extent_delay_real( if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, + bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) @@ -2046,7 +2046,7 @@ xfs_bmap_add_extent_delay_real( if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, 1, + bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) @@ -2115,7 +2115,7 @@ xfs_bmap_add_extent_delay_real( if (xfs_bmap_needs_btree(bma->ip, whichfork)) { error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, + bma->firstblock, bma->dfops, &bma->cur, 1, &tmp_rval, whichfork); rval |= tmp_rval; if (error) @@ -2164,7 +2164,7 @@ xfs_bmap_add_extent_delay_real( ASSERT(bma->cur == NULL); error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, + bma->firstblock, bma->dfops, &bma->cur, da_old > 0, &tmp_logflags, whichfork); bma->logflags |= tmp_logflags; if (error) @@ -2206,7 +2206,7 @@ xfs_bmap_add_extent_unwritten_real( xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ xfs_bmbt_irec_t *new, /* new data to add to file extents */ xfs_fsblock_t *first, /* pointer to firstblock variable */ - struct xfs_defer_ops *flist, /* list of extents to be freed */ + struct xfs_defer_ops *dfops, /* list of extents to be freed */ int *logflagsp) /* inode logging flags */ { xfs_btree_cur_t *cur; /* btree cursor */ @@ -2699,7 +2699,7 @@ xfs_bmap_add_extent_unwritten_real( int tmp_logflags; /* partial log flag return val */ ASSERT(cur == NULL); - error = xfs_bmap_extents_to_btree(tp, ip, first, flist, &cur, + error = xfs_bmap_extents_to_btree(tp, ip, first, dfops, &cur, 0, &tmp_logflags, XFS_DATA_FORK); *logflagsp |= tmp_logflags; if (error) @@ -3092,7 +3092,7 @@ xfs_bmap_add_extent_hole_real( ASSERT(bma->cur == NULL); error = xfs_bmap_extents_to_btree(bma->tp, bma->ip, - bma->firstblock, bma->flist, &bma->cur, + bma->firstblock, bma->dfops, &bma->cur, 0, &tmp_logflags, whichfork); bma->logflags |= tmp_logflags; if (error) @@ -3667,7 +3667,7 @@ xfs_bmap_btalloc( error = xfs_bmap_btalloc_nullfb(ap, &args, &blen); if (error) return error; - } else if (ap->flist->dop_low) { + } else if (ap->dfops->dop_low) { if (xfs_inode_is_filestream(ap->ip)) args.type = XFS_ALLOCTYPE_FIRST_AG; else @@ -3700,7 +3700,7 @@ xfs_bmap_btalloc( * is >= the stripe unit and the allocation offset is * at the end of file. */ - if (!ap->flist->dop_low && ap->aeof) { + if (!ap->dfops->dop_low && ap->aeof) { if (!ap->offset) { args.alignment = stripe_align; atype = args.type; @@ -3793,7 +3793,7 @@ xfs_bmap_btalloc( args.minleft = 0; if ((error = xfs_alloc_vextent(&args))) return error; - ap->flist->dop_low = true; + ap->dfops->dop_low = true; } if (args.fsbno != NULLFSBLOCK) { /* @@ -3803,7 +3803,7 @@ xfs_bmap_btalloc( ASSERT(*ap->firstblock == NULLFSBLOCK || XFS_FSB_TO_AGNO(mp, *ap->firstblock) == XFS_FSB_TO_AGNO(mp, args.fsbno) || - (ap->flist->dop_low && + (ap->dfops->dop_low && XFS_FSB_TO_AGNO(mp, *ap->firstblock) < XFS_FSB_TO_AGNO(mp, args.fsbno))); @@ -3811,7 +3811,7 @@ xfs_bmap_btalloc( if (*ap->firstblock == NULLFSBLOCK) *ap->firstblock = args.fsbno; ASSERT(nullfb || fb_agno == args.agno || - (ap->flist->dop_low && fb_agno < args.agno)); + (ap->dfops->dop_low && fb_agno < args.agno)); ap->length = args.len; ap->ip->i_d.di_nblocks += args.len; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); @@ -4278,7 +4278,7 @@ xfs_bmapi_allocate( if (error) return error; - if (bma->flist->dop_low) + if (bma->dfops->dop_low) bma->minleft = 0; if (bma->cur) bma->cur->bc_private.b.firstblock = *bma->firstblock; @@ -4287,7 +4287,7 @@ xfs_bmapi_allocate( if ((ifp->if_flags & XFS_IFBROOT) && !bma->cur) { bma->cur = xfs_bmbt_init_cursor(mp, bma->tp, bma->ip, whichfork); bma->cur->bc_private.b.firstblock = *bma->firstblock; - bma->cur->bc_private.b.flist = bma->flist; + bma->cur->bc_private.b.dfops = bma->dfops; } /* * Bump the number of extents we've allocated @@ -4368,7 +4368,7 @@ xfs_bmapi_convert_unwritten( bma->cur = xfs_bmbt_init_cursor(bma->ip->i_mount, bma->tp, bma->ip, whichfork); bma->cur->bc_private.b.firstblock = *bma->firstblock; - bma->cur->bc_private.b.flist = bma->flist; + bma->cur->bc_private.b.dfops = bma->dfops; } mval->br_state = (mval->br_state == XFS_EXT_UNWRITTEN) ? XFS_EXT_NORM : XFS_EXT_UNWRITTEN; @@ -4385,7 +4385,7 @@ xfs_bmapi_convert_unwritten( } error = xfs_bmap_add_extent_unwritten_real(bma->tp, bma->ip, &bma->idx, - &bma->cur, mval, bma->firstblock, bma->flist, + &bma->cur, mval, bma->firstblock, bma->dfops, &tmp_logflags); /* * Log the inode core unconditionally in the unwritten extent conversion @@ -4439,7 +4439,7 @@ xfs_bmapi_write( xfs_extlen_t total, /* total blocks needed */ struct xfs_bmbt_irec *mval, /* output: map values */ int *nmap, /* i/o: mval size/count */ - struct xfs_defer_ops *flist) /* i/o: list extents to free */ + struct xfs_defer_ops *dfops) /* i/o: list extents to free */ { struct xfs_mount *mp = ip->i_mount; struct xfs_ifork *ifp; @@ -4529,7 +4529,7 @@ xfs_bmapi_write( bma.ip = ip; bma.total = total; bma.userdata = 0; - bma.flist = flist; + bma.dfops = dfops; bma.firstblock = firstblock; while (bno < end && n < *nmap) { @@ -4643,7 +4643,7 @@ error0: XFS_FSB_TO_AGNO(mp, *firstblock) == XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock) || - (flist->dop_low && + (dfops->dop_low && XFS_FSB_TO_AGNO(mp, *firstblock) < XFS_FSB_TO_AGNO(mp, bma.cur->bc_private.b.firstblock))); @@ -4727,7 +4727,7 @@ xfs_bmap_del_extent( xfs_inode_t *ip, /* incore inode pointer */ xfs_trans_t *tp, /* current transaction pointer */ xfs_extnum_t *idx, /* extent number to update/delete */ - struct xfs_defer_ops *flist, /* list of extents to be freed */ + struct xfs_defer_ops *dfops, /* list of extents to be freed */ xfs_btree_cur_t *cur, /* if null, not a btree */ xfs_bmbt_irec_t *del, /* data to remove from extents */ int *logflagsp, /* inode logging flags */ @@ -5015,7 +5015,7 @@ xfs_bmap_del_extent( * If we need to, add to list of extents to delete. */ if (do_fx) - xfs_bmap_add_free(mp, flist, del->br_startblock, + xfs_bmap_add_free(mp, dfops, del->br_startblock, del->br_blockcount); /* * Adjust inode # blocks in the file. @@ -5056,7 +5056,7 @@ xfs_bunmapi( xfs_extnum_t nexts, /* number of extents max */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ - struct xfs_defer_ops *flist, /* i/o: list extents to free */ + struct xfs_defer_ops *dfops, /* i/o: list extents to free */ int *done) /* set if not done yet */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ @@ -5129,7 +5129,7 @@ xfs_bunmapi( ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE); cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; } else cur = NULL; @@ -5221,7 +5221,7 @@ xfs_bunmapi( } del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, ip, - &lastx, &cur, &del, firstblock, flist, + &lastx, &cur, &del, firstblock, dfops, &logflags); if (error) goto error0; @@ -5280,7 +5280,7 @@ xfs_bunmapi( lastx--; error = xfs_bmap_add_extent_unwritten_real(tp, ip, &lastx, &cur, &prev, - firstblock, flist, &logflags); + firstblock, dfops, &logflags); if (error) goto error0; goto nodelete; @@ -5289,7 +5289,7 @@ xfs_bunmapi( del.br_state = XFS_EXT_UNWRITTEN; error = xfs_bmap_add_extent_unwritten_real(tp, ip, &lastx, &cur, &del, - firstblock, flist, &logflags); + firstblock, dfops, &logflags); if (error) goto error0; goto nodelete; @@ -5347,7 +5347,7 @@ xfs_bunmapi( } else if (cur) cur->bc_private.b.flags &= ~XFS_BTCUR_BPRV_WASDEL; - error = xfs_bmap_del_extent(ip, tp, &lastx, flist, cur, &del, + error = xfs_bmap_del_extent(ip, tp, &lastx, dfops, cur, &del, &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) @@ -5381,7 +5381,7 @@ nodelete: */ if (xfs_bmap_needs_btree(ip, whichfork)) { ASSERT(cur == NULL); - error = xfs_bmap_extents_to_btree(tp, ip, firstblock, flist, + error = xfs_bmap_extents_to_btree(tp, ip, firstblock, dfops, &cur, 0, &tmp_logflags, whichfork); logflags |= tmp_logflags; if (error) @@ -5670,7 +5670,7 @@ xfs_bmap_shift_extents( int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *flist, + struct xfs_defer_ops *dfops, enum shift_direction direction, int num_exts) { @@ -5715,7 +5715,7 @@ xfs_bmap_shift_extents( if (ifp->if_flags & XFS_IFBROOT) { cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstblock; - cur->bc_private.b.flist = flist; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; } @@ -5824,7 +5824,7 @@ xfs_bmap_split_extent_at( struct xfs_inode *ip, xfs_fileoff_t split_fsb, xfs_fsblock_t *firstfsb, - struct xfs_defer_ops *free_list) + struct xfs_defer_ops *dfops) { int whichfork = XFS_DATA_FORK; struct xfs_btree_cur *cur = NULL; @@ -5886,7 +5886,7 @@ xfs_bmap_split_extent_at( if (ifp->if_flags & XFS_IFBROOT) { cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork); cur->bc_private.b.firstblock = *firstfsb; - cur->bc_private.b.flist = free_list; + cur->bc_private.b.dfops = dfops; cur->bc_private.b.flags = 0; error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, @@ -5939,7 +5939,7 @@ xfs_bmap_split_extent_at( int tmp_logflags; /* partial log flag return val */ ASSERT(cur == NULL); - error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, free_list, + error = xfs_bmap_extents_to_btree(tp, ip, firstfsb, dfops, &cur, 0, &tmp_logflags, whichfork); logflags |= tmp_logflags; } @@ -5963,7 +5963,7 @@ xfs_bmap_split_extent( { struct xfs_mount *mp = ip->i_mount; struct xfs_trans *tp; - struct xfs_defer_ops free_list; + struct xfs_defer_ops dfops; xfs_fsblock_t firstfsb; int error; @@ -5975,21 +5975,21 @@ xfs_bmap_split_extent( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); - xfs_defer_init(&free_list, &firstfsb); + xfs_defer_init(&dfops, &firstfsb); error = xfs_bmap_split_extent_at(tp, ip, split_fsb, - &firstfsb, &free_list); + &firstfsb, &dfops); if (error) goto out; - error = xfs_defer_finish(&tp, &free_list, NULL); + error = xfs_defer_finish(&tp, &dfops, NULL); if (error) goto out; return xfs_trans_commit(tp); out: - xfs_defer_cancel(&free_list); + xfs_defer_cancel(&dfops); xfs_trans_cancel(tp); return error; } diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index a779cc5..6854e61 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -32,7 +32,7 @@ extern kmem_zone_t *xfs_bmap_free_item_zone; */ struct xfs_bmalloca { xfs_fsblock_t *firstblock; /* i/o first block allocated */ - struct xfs_defer_ops *flist; /* bmap freelist */ + struct xfs_defer_ops *dfops; /* bmap freelist */ struct xfs_trans *tp; /* transaction pointer */ struct xfs_inode *ip; /* incore inode pointer */ struct xfs_bmbt_irec prev; /* extent before the new one */ @@ -164,7 +164,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); -void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *flist, +void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t bno, xfs_filblks_t len); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, @@ -186,18 +186,18 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_fsblock_t *firstblock, xfs_extlen_t total, struct xfs_bmbt_irec *mval, int *nmap, - struct xfs_defer_ops *flist); + struct xfs_defer_ops *dfops); int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *flist, int *done); + struct xfs_defer_ops *dfops, int *done); int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, xfs_extnum_t num); uint xfs_default_attroffset(struct xfs_inode *ip); int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, - struct xfs_defer_ops *flist, enum shift_direction direction, + struct xfs_defer_ops *dfops, enum shift_direction direction, int num_exts); int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 8d4d4b0..d290769 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -404,11 +404,11 @@ xfs_bmbt_dup_cursor( cur->bc_private.b.ip, cur->bc_private.b.whichfork); /* - * Copy the firstblock, flist, and flags values, + * Copy the firstblock, dfops, and flags values, * since init cursor doesn't get them. */ new->bc_private.b.firstblock = cur->bc_private.b.firstblock; - new->bc_private.b.flist = cur->bc_private.b.flist; + new->bc_private.b.dfops = cur->bc_private.b.dfops; new->bc_private.b.flags = cur->bc_private.b.flags; return new; @@ -421,7 +421,7 @@ xfs_bmbt_update_cursor( { ASSERT((dst->bc_private.b.firstblock != NULLFSBLOCK) || (dst->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME)); - ASSERT(dst->bc_private.b.flist == src->bc_private.b.flist); + ASSERT(dst->bc_private.b.dfops == src->bc_private.b.dfops); dst->bc_private.b.allocated += src->bc_private.b.allocated; dst->bc_private.b.firstblock = src->bc_private.b.firstblock; @@ -460,7 +460,7 @@ xfs_bmbt_alloc_block( * block allocation here and corrupt the filesystem. */ args.minleft = args.tp->t_blk_res; - } else if (cur->bc_private.b.flist->dop_low) { + } else if (cur->bc_private.b.dfops->dop_low) { args.type = XFS_ALLOCTYPE_START_BNO; } else { args.type = XFS_ALLOCTYPE_NEAR_BNO; @@ -488,7 +488,7 @@ xfs_bmbt_alloc_block( error = xfs_alloc_vextent(&args); if (error) goto error0; - cur->bc_private.b.flist->dop_low = true; + cur->bc_private.b.dfops->dop_low = true; } if (args.fsbno == NULLFSBLOCK) { XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); @@ -524,7 +524,7 @@ xfs_bmbt_free_block( struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); - xfs_bmap_add_free(mp, cur->bc_private.b.flist, fsbno, 1); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1); ip->i_d.di_nblocks--; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); @@ -786,7 +786,7 @@ xfs_bmbt_init_cursor( cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork); cur->bc_private.b.ip = ip; cur->bc_private.b.firstblock = NULLFSBLOCK; - cur->bc_private.b.flist = NULL; + cur->bc_private.b.dfops = NULL; cur->bc_private.b.allocated = 0; cur->bc_private.b.flags = 0; cur->bc_private.b.whichfork = whichfork; diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index ae714a8..7483cac 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -234,12 +234,12 @@ typedef struct xfs_btree_cur union { struct { /* needed for BNO, CNT, INO */ struct xfs_buf *agbp; /* agf/agi buffer pointer */ - struct xfs_defer_ops *flist; /* deferred updates */ + struct xfs_defer_ops *dfops; /* deferred updates */ xfs_agnumber_t agno; /* ag number */ } a; struct { /* needed for BMAP */ struct xfs_inode *ip; /* pointer to our inode */ - struct xfs_defer_ops *flist; /* deferred updates */ + struct xfs_defer_ops *dfops; /* deferred updates */ xfs_fsblock_t firstblock; /* 1st blk allocated */ int allocated; /* count of alloced */ short forksize; /* fork's inode space */ diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c index 298252e..bf24ade 100644 --- a/libxfs/xfs_da_btree.c +++ b/libxfs/xfs_da_btree.c @@ -2025,7 +2025,7 @@ xfs_da_grow_inode_int( error = xfs_bmapi_write(tp, dp, *bno, count, xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, args->firstblock, args->total, &map, &nmap, - args->flist); + args->dfops); if (error) return error; @@ -2048,7 +2048,7 @@ xfs_da_grow_inode_int( error = xfs_bmapi_write(tp, dp, b, c, xfs_bmapi_aflag(w)|XFS_BMAPI_METADATA, args->firstblock, args->total, - &mapp[mapi], &nmap, args->flist); + &mapp[mapi], &nmap, args->dfops); if (error) goto out_free_map; if (nmap < 1) @@ -2358,7 +2358,7 @@ xfs_da_shrink_inode( */ error = xfs_bunmapi(tp, dp, dead_blkno, count, xfs_bmapi_aflag(w), 0, args->firstblock, - args->flist, &done); + args->dfops, &done); if (error == -ENOSPC) { if (w != XFS_DATA_FORK) break; diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h index 249813a..98c75cb 100644 --- a/libxfs/xfs_da_btree.h +++ b/libxfs/xfs_da_btree.h @@ -70,7 +70,7 @@ typedef struct xfs_da_args { xfs_ino_t inumber; /* input/output inode number */ struct xfs_inode *dp; /* directory inode to manipulate */ xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */ - struct xfs_defer_ops *flist; /* ptr to freelist for bmap_finish */ + struct xfs_defer_ops *dfops; /* ptr to freelist for bmap_finish */ struct xfs_trans *trans; /* current trans (changes over time) */ xfs_extlen_t total; /* total blocks needed, for 1st bmap */ int whichfork; /* data or attribute fork */ diff --git a/libxfs/xfs_dir2.c b/libxfs/xfs_dir2.c index 6edaa8e..4180a93 100644 --- a/libxfs/xfs_dir2.c +++ b/libxfs/xfs_dir2.c @@ -258,7 +258,7 @@ xfs_dir_createname( struct xfs_name *name, xfs_ino_t inum, /* new entry inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - struct xfs_defer_ops *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -285,7 +285,7 @@ xfs_dir_createname( args->inumber = inum; args->dp = dp; args->firstblock = first; - args->flist = flist; + args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; @@ -435,7 +435,7 @@ xfs_dir_removename( struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, /* bmap's firstblock */ - struct xfs_defer_ops *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -457,7 +457,7 @@ xfs_dir_removename( args->inumber = ino; args->dp = dp; args->firstblock = first; - args->flist = flist; + args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; @@ -497,7 +497,7 @@ xfs_dir_replace( struct xfs_name *name, /* name of entry to replace */ xfs_ino_t inum, /* new inode number */ xfs_fsblock_t *first, /* bmap's firstblock */ - struct xfs_defer_ops *flist, /* bmap's freeblock list */ + struct xfs_defer_ops *dfops, /* bmap's freeblock list */ xfs_extlen_t total) /* bmap's total block count */ { struct xfs_da_args *args; @@ -522,7 +522,7 @@ xfs_dir_replace( args->inumber = inum; args->dp = dp; args->firstblock = first; - args->flist = flist; + args->dfops = dfops; args->total = total; args->whichfork = XFS_DATA_FORK; args->trans = tp; @@ -679,7 +679,7 @@ xfs_dir2_shrink_inode( /* Unmap the fsblock(s). */ error = xfs_bunmapi(tp, dp, da, args->geo->fsbcount, 0, 0, - args->firstblock, args->flist, &done); + args->firstblock, args->dfops, &done); if (error) { /* * ENOSPC actually can happen if we're in a removename with no diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h index 5737d85..a9bab0e 100644 --- a/libxfs/xfs_dir2.h +++ b/libxfs/xfs_dir2.h @@ -129,18 +129,18 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_defer_ops *flist, xfs_extlen_t tot); + struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t *inum, struct xfs_name *ci_name); extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t ino, xfs_fsblock_t *first, - struct xfs_defer_ops *flist, xfs_extlen_t tot); + struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_defer_ops *flist, xfs_extlen_t tot); + struct xfs_defer_ops *dfops, xfs_extlen_t tot); extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_name *name); diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index d03570c..1545338 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -1812,7 +1812,7 @@ xfs_difree_inode_chunk( struct xfs_mount *mp, xfs_agnumber_t agno, struct xfs_inobt_rec_incore *rec, - struct xfs_defer_ops *flist) + struct xfs_defer_ops *dfops) { xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); int startidx, endidx; @@ -1823,7 +1823,7 @@ xfs_difree_inode_chunk( if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ - xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, sagbno), + xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno), mp->m_ialloc_blks); return; } @@ -1867,7 +1867,7 @@ xfs_difree_inode_chunk( ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); - xfs_bmap_add_free(mp, flist, XFS_AGB_TO_FSB(mp, agno, agbno), + xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno), contigblk); /* reset range to current bit and carry on... */ @@ -1884,7 +1884,7 @@ xfs_difree_inobt( struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agino_t agino, - struct xfs_defer_ops *flist, + struct xfs_defer_ops *dfops, struct xfs_icluster *xic, struct xfs_inobt_rec_incore *orec) { @@ -1971,7 +1971,7 @@ xfs_difree_inobt( goto error0; } - xfs_difree_inode_chunk(mp, agno, &rec, flist); + xfs_difree_inode_chunk(mp, agno, &rec, dfops); } else { xic->deleted = 0; @@ -2116,7 +2116,7 @@ int xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_defer_ops *flist, /* extents to free */ + struct xfs_defer_ops *dfops, /* extents to free */ struct xfs_icluster *xic) /* cluster info if deleted */ { /* REFERENCED */ @@ -2168,7 +2168,7 @@ xfs_difree( /* * Fix up the inode allocation btree. */ - error = xfs_difree_inobt(mp, tp, agbp, agino, flist, xic, &rec); + error = xfs_difree_inobt(mp, tp, agbp, agino, dfops, xic, &rec); if (error) goto error0; diff --git a/libxfs/xfs_ialloc.h b/libxfs/xfs_ialloc.h index 2e06b67..0bb8966 100644 --- a/libxfs/xfs_ialloc.h +++ b/libxfs/xfs_ialloc.h @@ -95,7 +95,7 @@ int /* error */ xfs_difree( struct xfs_trans *tp, /* transaction pointer */ xfs_ino_t inode, /* inode to be freed */ - struct xfs_defer_ops *flist, /* extents to free */ + struct xfs_defer_ops *dfops, /* extents to free */ struct xfs_icluster *ifree); /* cluster info if deleted */ /* diff --git a/mkfs/proto.c b/mkfs/proto.c index f0c33e4..cf9ed77 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -27,7 +27,7 @@ static char *getstr(char **pp); static void fail(char *msg, int i); static void getres(struct xfs_mount *mp, uint blocks, struct xfs_trans **tpp); static void rsvfile(xfs_mount_t *mp, xfs_inode_t *ip, long long len); -static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, struct xfs_defer_ops *flist, +static int newfile(xfs_trans_t *tp, xfs_inode_t *ip, struct xfs_defer_ops *dfops, xfs_fsblock_t *first, int dolocal, int logit, char *buf, int len); static char *newregfile(char **pp, int *len); static void rtinit(xfs_mount_t *mp); @@ -236,7 +236,7 @@ static int newfile( xfs_trans_t *tp, xfs_inode_t *ip, - struct xfs_defer_ops *flist, + struct xfs_defer_ops *dfops, xfs_fsblock_t *first, int dolocal, int logit, @@ -267,7 +267,7 @@ newfile( nb = XFS_B_TO_FSB(mp, len); nmap = 1; error = -libxfs_bmapi_write(tp, ip, 0, nb, 0, first, nb, - &map, &nmap, flist); + &map, &nmap, dfops); if (error) { fail(_("error allocating space for a file"), error); } @@ -329,14 +329,14 @@ newdirent( struct xfs_name *name, xfs_ino_t inum, xfs_fsblock_t *first, - struct xfs_defer_ops *flist) + struct xfs_defer_ops *dfops) { int error; int rsv; rsv = XFS_DIRENTER_SPACE_RES(mp, name->len); - error = -libxfs_dir_createname(tp, pip, name, inum, first, flist, rsv); + error = -libxfs_dir_createname(tp, pip, name, inum, first, dfops, rsv); if (error) fail(_("directory createname error"), error); } @@ -375,7 +375,7 @@ parseproto( int error; xfs_fsblock_t first; int flags; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; int fmt; int i; xfs_inode_t *ip; @@ -460,7 +460,7 @@ parseproto( xname.len = name ? strlen(name) : 0; xname.type = 0; flags = XFS_ILOG_CORE; - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); switch (fmt) { case IF_REGULAR: buf = newregfile(pp, &len); @@ -469,12 +469,12 @@ parseproto( &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); - flags |= newfile(tp, ip, &flist, &first, 0, 0, buf, len); + flags |= newfile(tp, ip, &dfops, &first, 0, 0, buf, len); if (buf) free(buf); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_REG_FILE; - newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); + newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); break; case IF_RESERVED: /* pre-allocated space only */ @@ -497,10 +497,10 @@ parseproto( libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_REG_FILE; - newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); + newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); libxfs_trans_log_inode(tp, ip, flags); - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); if (error) fail(_("Pre-allocated file creation failed"), error); libxfs_trans_commit(tp); @@ -519,7 +519,7 @@ parseproto( } libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_BLKDEV; - newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); + newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); flags |= XFS_ILOG_DEV; break; @@ -533,7 +533,7 @@ parseproto( fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_CHRDEV; - newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); + newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); flags |= XFS_ILOG_DEV; break; @@ -545,7 +545,7 @@ parseproto( fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_FIFO; - newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); + newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); break; case IF_SYMLINK: buf = getstr(pp); @@ -555,10 +555,10 @@ parseproto( &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); - flags |= newfile(tp, ip, &flist, &first, 1, 1, buf, len); + flags |= newfile(tp, ip, &dfops, &first, 1, 1, buf, len); libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_SYMLINK; - newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist); + newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &dfops); break; case IF_DIRECTORY: getres(mp, 0, &tp); @@ -576,13 +576,13 @@ parseproto( libxfs_trans_ijoin(tp, pip, 0); xname.type = XFS_DIR3_FT_DIR; newdirent(mp, tp, pip, &xname, ip->i_ino, - &first, &flist); + &first, &dfops); inc_nlink(VFS_I(pip)); libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); } newdirectory(mp, tp, ip, pip); libxfs_trans_log_inode(tp, ip, flags); - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); if (error) fail(_("Directory creation failed"), error); libxfs_trans_commit(tp); @@ -608,7 +608,7 @@ parseproto( fail(_("Unknown format"), EINVAL); } libxfs_trans_log_inode(tp, ip, flags); - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); if (error) { fail(_("Error encountered creating file from prototype file"), error); @@ -638,7 +638,7 @@ rtinit( xfs_bmbt_irec_t *ep; int error; xfs_fsblock_t first; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; int i; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; xfs_extlen_t nsumblocks; @@ -697,13 +697,13 @@ rtinit( libxfs_trans_ijoin(tp, rbmip, 0); bno = 0; - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); while (bno < mp->m_sb.sb_rbmblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, rbmip, bno, (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno), 0, &first, mp->m_sb.sb_rbmblocks, - map, &nmap, &flist); + map, &nmap, &dfops); if (error) { fail(_("Allocation of the realtime bitmap failed"), error); @@ -716,7 +716,7 @@ rtinit( } } - error = -xfs_defer_finish(&tp, &flist, rbmip); + error = -xfs_defer_finish(&tp, &dfops, rbmip); if (error) { fail(_("Completion of the realtime bitmap failed"), error); } @@ -732,13 +732,13 @@ rtinit( res_failed(i); libxfs_trans_ijoin(tp, rsumip, 0); bno = 0; - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); while (bno < nsumblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, rsumip, bno, (xfs_extlen_t)(nsumblocks - bno), 0, &first, nsumblocks, - map, &nmap, &flist); + map, &nmap, &dfops); if (error) { fail(_("Allocation of the realtime summary failed"), error); @@ -750,7 +750,7 @@ rtinit( bno += ep->br_blockcount; } } - error = -xfs_defer_finish(&tp, &flist, rsumip); + error = -xfs_defer_finish(&tp, &dfops, rsumip); if (error) { fail(_("Completion of the realtime summary failed"), error); } @@ -765,7 +765,7 @@ rtinit( if (i) res_failed(i); libxfs_trans_ijoin(tp, rbmip, 0); - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); ebno = XFS_RTMIN(mp->m_sb.sb_rextents, bno + NBBY * mp->m_sb.sb_blocksize); error = -libxfs_rtfree_extent(tp, bno, (xfs_extlen_t)(ebno-bno)); @@ -773,7 +773,7 @@ rtinit( fail(_("Error initializing the realtime space"), error); } - error = -xfs_defer_finish(&tp, &flist, rbmip); + error = -xfs_defer_finish(&tp, &dfops, rbmip); if (error) { fail(_("Error completing the realtime space"), error); } diff --git a/repair/phase6.c b/repair/phase6.c index 961f7bc..0194580 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -484,7 +484,7 @@ mk_rbmino(xfs_mount_t *mp) int i; int nmap; int error; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; xfs_fileoff_t bno; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; int vers; @@ -550,13 +550,13 @@ mk_rbmino(xfs_mount_t *mp) libxfs_trans_ijoin(tp, ip, 0); bno = 0; - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); while (bno < mp->m_sb.sb_rbmblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, ip, bno, (xfs_extlen_t)(mp->m_sb.sb_rbmblocks - bno), 0, &first, mp->m_sb.sb_rbmblocks, - map, &nmap, &flist); + map, &nmap, &dfops); if (error) { do_error( _("couldn't allocate realtime bitmap, error = %d\n"), @@ -569,7 +569,7 @@ mk_rbmino(xfs_mount_t *mp) bno += ep->br_blockcount; } } - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); if (error) { do_error( _("allocation of the realtime bitmap failed, error = %d\n"), @@ -731,7 +731,7 @@ mk_rsumino(xfs_mount_t *mp) int nmap; int error; int nsumblocks; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; xfs_fileoff_t bno; xfs_bmbt_irec_t map[XFS_BMAP_MAX_NMAP]; int vers; @@ -789,7 +789,7 @@ mk_rsumino(xfs_mount_t *mp) * then allocate blocks for file and fill with zeroes (stolen * from mkfs) */ - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); nsumblocks = mp->m_rsumsize >> mp->m_sb.sb_blocklog; tres.tr_logres = BBTOB(128); @@ -803,12 +803,12 @@ mk_rsumino(xfs_mount_t *mp) libxfs_trans_ijoin(tp, ip, 0); bno = 0; - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); while (bno < nsumblocks) { nmap = XFS_BMAP_MAX_NMAP; error = -libxfs_bmapi_write(tp, ip, bno, (xfs_extlen_t)(nsumblocks - bno), - 0, &first, nsumblocks, map, &nmap, &flist); + 0, &first, nsumblocks, map, &nmap, &dfops); if (error) { do_error( _("couldn't allocate realtime summary inode, error = %d\n"), @@ -821,7 +821,7 @@ mk_rsumino(xfs_mount_t *mp) bno += ep->br_blockcount; } } - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); if (error) { do_error( _("allocation of the realtime summary ino failed, error = %d\n"), @@ -919,7 +919,7 @@ mk_orphanage(xfs_mount_t *mp) int ino_offset = 0; int i; int error; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; const int mode = 0755; int nres; struct xfs_name xname; @@ -945,7 +945,7 @@ mk_orphanage(xfs_mount_t *mp) * could not be found, create it */ - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); nres = XFS_MKDIR_SPACE_RES(mp, xname.len); i = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp); @@ -1007,7 +1007,7 @@ mk_orphanage(xfs_mount_t *mp) * create the actual entry */ error = -libxfs_dir_createname(tp, pip, &xname, ip->i_ino, &first, - &flist, nres); + &dfops, nres); if (error) do_error( _("can't make %s, createname error %d\n"), @@ -1028,7 +1028,7 @@ mk_orphanage(xfs_mount_t *mp) libxfs_dir_init(tp, ip, pip); libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); if (error) { do_error(_("%s directory creation failed -- bmapf error %d\n"), ORPHANAGE, error); @@ -1057,7 +1057,7 @@ mv_orphanage( xfs_inode_t *ino_p; xfs_trans_t *tp; xfs_fsblock_t first; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; int err; unsigned char fname[MAXPATHLEN + 1]; int nres; @@ -1110,9 +1110,9 @@ mv_orphanage( libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, - ino, &first, &flist, nres); + ino, &first, &dfops, nres); if (err) do_error( _("name create failed in %s (%d), filesystem may be out of space\n"), @@ -1125,7 +1125,7 @@ mv_orphanage( libxfs_trans_log_inode(tp, orphanage_ip, XFS_ILOG_CORE); err = -libxfs_dir_createname(tp, ino_p, &xfs_name_dotdot, - orphanage_ino, &first, &flist, nres); + orphanage_ino, &first, &dfops, nres); if (err) do_error( _("creation of .. entry failed (%d), filesystem may be out of space\n"), @@ -1134,7 +1134,7 @@ mv_orphanage( inc_nlink(VFS_I(ino_p)); libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE); - err = -xfs_defer_finish(&tp, &flist, ino_p); + err = -xfs_defer_finish(&tp, &dfops, ino_p); if (err) do_error( _("bmap finish failed (err - %d), filesystem may be out of space\n"), @@ -1152,10 +1152,10 @@ mv_orphanage( libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, - ino, &first, &flist, nres); + ino, &first, &dfops, nres); if (err) do_error( _("name create failed in %s (%d), filesystem may be out of space\n"), @@ -1174,14 +1174,14 @@ mv_orphanage( if (entry_ino_num != orphanage_ino) { err = -libxfs_dir_replace(tp, ino_p, &xfs_name_dotdot, orphanage_ino, - &first, &flist, nres); + &first, &dfops, nres); if (err) do_error( _("name replace op failed (%d), filesystem may be out of space\n"), err); } - err = -xfs_defer_finish(&tp, &flist, ino_p); + err = -xfs_defer_finish(&tp, &dfops, ino_p); if (err) do_error( _("bmap finish failed (%d), filesystem may be out of space\n"), @@ -1208,9 +1208,9 @@ mv_orphanage( libxfs_trans_ijoin(tp, orphanage_ip, 0); libxfs_trans_ijoin(tp, ino_p, 0); - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); err = -libxfs_dir_createname(tp, orphanage_ip, &xname, ino, - &first, &flist, nres); + &first, &dfops, nres); if (err) do_error( _("name create failed in %s (%d), filesystem may be out of space\n"), @@ -1220,7 +1220,7 @@ mv_orphanage( set_nlink(VFS_I(ino_p), 1); libxfs_trans_log_inode(tp, ino_p, XFS_ILOG_CORE); - err = -xfs_defer_finish(&tp, &flist, ino_p); + err = -xfs_defer_finish(&tp, &dfops, ino_p); if (err) do_error( _("bmap finish failed (%d), filesystem may be out of space\n"), @@ -1269,7 +1269,7 @@ longform_dir2_rebuild( xfs_trans_t *tp; xfs_fileoff_t lastblock; xfs_fsblock_t firstblock; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; xfs_inode_t pip; dir_hash_ent_t *p; int done; @@ -1292,7 +1292,7 @@ longform_dir2_rebuild( xfs_dir_ino_validate(mp, pip.i_ino)) pip.i_ino = mp->m_sb.sb_rootino; - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); nres = XFS_REMOVE_SPACE_RES(mp); error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_remove, nres, 0, 0, &tp); @@ -1306,7 +1306,7 @@ longform_dir2_rebuild( /* free all data, leaf, node and freespace blocks */ error = -libxfs_bunmapi(tp, ip, 0, lastblock, XFS_BMAPI_METADATA, 0, - &firstblock, &flist, &done); + &firstblock, &dfops, &done); if (error) { do_warn(_("xfs_bunmapi failed -- error - %d\n"), error); goto out_bmap_cancel; @@ -1320,7 +1320,7 @@ longform_dir2_rebuild( goto out_bmap_cancel; } - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); libxfs_trans_commit(tp); @@ -1344,9 +1344,9 @@ longform_dir2_rebuild( libxfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); error = -libxfs_dir_createname(tp, ip, &p->name, p->inum, - &firstblock, &flist, nres); + &firstblock, &dfops, nres); if (error) { do_warn( _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n"), @@ -1354,7 +1354,7 @@ _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n" goto out_bmap_cancel; } - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); if (error) { do_warn( _("bmap finish failed (%d), filesystem may be out of space\n"), @@ -1368,7 +1368,7 @@ _("name create failed in ino %" PRIu64 " (%d), filesystem may be out of space\n" return; out_bmap_cancel: - xfs_defer_cancel(&flist); + xfs_defer_cancel(&dfops); libxfs_trans_cancel(tp); return; } @@ -1388,7 +1388,7 @@ dir2_kill_block( xfs_da_args_t args; int error; xfs_fsblock_t firstblock; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; int nres; xfs_trans_t *tp; @@ -1399,11 +1399,11 @@ dir2_kill_block( libxfs_trans_ijoin(tp, ip, 0); libxfs_trans_bjoin(tp, bp); memset(&args, 0, sizeof(args)); - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); args.dp = ip; args.trans = tp; args.firstblock = &firstblock; - args.flist = &flist; + args.dfops = &dfops; args.whichfork = XFS_DATA_FORK; args.geo = mp->m_dir_geo; if (da_bno >= mp->m_dir_geo->leafblk && da_bno < mp->m_dir_geo->freeblk) @@ -1414,7 +1414,7 @@ dir2_kill_block( if (error) do_error(_("shrink_inode failed inode %" PRIu64 " block %u\n"), ip->i_ino, da_bno); - xfs_defer_finish(&tp, &flist, ip); + xfs_defer_finish(&tp, &dfops, ip); libxfs_trans_commit(tp); } @@ -1448,7 +1448,7 @@ longform_dir2_entry_check_data( char *endptr; int error; xfs_fsblock_t firstblock; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; char fname[MAXNAMELEN + 1]; freetab_t *freetab; int i; @@ -1590,7 +1590,7 @@ longform_dir2_entry_check_data( libxfs_trans_ijoin(tp, ip, 0); libxfs_trans_bjoin(tp, bp); libxfs_trans_bhold(tp, bp); - xfs_defer_init(&flist, &firstblock); + xfs_defer_init(&dfops, &firstblock); if (be32_to_cpu(d->magic) != wantmagic) { do_warn( _("bad directory block magic # %#x for directory inode %" PRIu64 " block %d: "), @@ -1889,7 +1889,7 @@ _("entry \"%s\" in dir inode %" PRIu64 " inconsistent with .. value (%" PRIu64 " repair_dir2_data_freescan(mp, M_DIROPS(mp), d, &i); if (needlog) libxfs_dir2_data_log_header(&da, bp); - xfs_defer_finish(&tp, &flist, ip); + xfs_defer_finish(&tp, &dfops, ip); libxfs_trans_commit(tp); /* record the largest free space in the freetab for later checking */ @@ -2805,7 +2805,7 @@ process_dir_inode( int ino_offset) { xfs_ino_t ino; - struct xfs_defer_ops flist; + struct xfs_defer_ops dfops; xfs_fsblock_t first; xfs_inode_t *ip; xfs_trans_t *tp; @@ -2943,17 +2943,17 @@ process_dir_inode( libxfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot, - ip->i_ino, &first, &flist, nres); + ip->i_ino, &first, &dfops, nres); if (error) do_error( _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error); libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); ASSERT(error == 0); libxfs_trans_commit(tp); @@ -3001,10 +3001,10 @@ process_dir_inode( libxfs_trans_ijoin(tp, ip, 0); - xfs_defer_init(&flist, &first); + xfs_defer_init(&dfops, &first); error = -libxfs_dir_createname(tp, ip, &xfs_name_dot, - ip->i_ino, &first, &flist, nres); + ip->i_ino, &first, &dfops, nres); if (error) do_error( _("can't make \".\" entry in dir ino %" PRIu64 ", createname error %d\n"), @@ -3012,7 +3012,7 @@ process_dir_inode( libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); - error = -xfs_defer_finish(&tp, &flist, ip); + error = -xfs_defer_finish(&tp, &dfops, ip); ASSERT(error == 0); libxfs_trans_commit(tp); } diff --git a/repair/sb.c b/repair/sb.c index 4eef14a..803125c 100644 --- a/repair/sb.c +++ b/repair/sb.c @@ -653,7 +653,7 @@ verify_set_primary_sb(xfs_sb_t *rsb, retval = get_sb(sb, off, size, agno); if (retval == XR_EOF) - goto out_free_list; + goto out_dfops; if (retval == XR_OK) { /* @@ -675,7 +675,7 @@ verify_set_primary_sb(xfs_sb_t *rsb, retval = 0; if (num_ok < num_sbs / 2) { retval = XR_INSUFF_SEC_SB; - goto out_free_list; + goto out_dfops; } current = get_best_geo(list); @@ -703,7 +703,7 @@ verify_set_primary_sb(xfs_sb_t *rsb, exit(1); } } - goto out_free_list; + goto out_dfops; case 1: /* * If we only have a single allocation group there is no @@ -718,7 +718,7 @@ verify_set_primary_sb(xfs_sb_t *rsb, "Use the -o force_geometry option to proceed.\n")); exit(1); } - goto out_free_list; + goto out_dfops; default: /* * at least half of the probed superblocks have @@ -758,7 +758,7 @@ verify_set_primary_sb(xfs_sb_t *rsb, sb_width = sb->sb_width; } -out_free_list: +out_dfops: free_geo(list); free(sb); return retval; From darrick.wong@oracle.com Thu Jun 16 20:33:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 032C37DC3 for ; Thu, 16 Jun 2016 20:33:40 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6E985AC002 for ; Thu, 16 Jun 2016 18:33:39 -0700 (PDT) X-ASG-Debug-ID: 1466127217-04cbb01fef69fb0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id UurCHjcsIg5q3lNr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:37 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1XZfU002888 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:36 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XZ8m001756 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:35 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1XZS1031720; Fri, 17 Jun 2016 01:33:35 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:34 -0700 Subject: [PATCH 027/145] xfs_io: add free-extent error injection type From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 027/145] xfs_io: add free-extent error injection type To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:33:33 -0700 Message-ID: <146612721357.16048.1495184945471967839.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127217 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 776 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.60 X-Barracuda-Spam-Status: No, SCORE=2.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_MV0249, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 2.00 BSF_SC0_MV0249 Custom rule MV0249 Add XFS_ERRTAG_FREE_EXTENT to the types of errors we can inject. Signed-off-by: Darrick J. Wong --- io/inject.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/io/inject.c b/io/inject.c index 90ccda8..12e0fb3 100644 --- a/io/inject.c +++ b/io/inject.c @@ -74,7 +74,9 @@ error_tag(char *name) { XFS_ERRTAG_DIOWRITE_IOERR, "diowrite" }, #define XFS_ERRTAG_BMAPIFORMAT 21 { XFS_ERRTAG_BMAPIFORMAT, "bmapifmt" }, -#define XFS_ERRTAG_MAX 22 +#define XFS_ERRTAG_FREE_EXTENT 22 + { XFS_ERRTAG_FREE_EXTENT, "free_extent" }, +#define XFS_ERRTAG_MAX 23 { XFS_ERRTAG_MAX, NULL } }; int count; From darrick.wong@oracle.com Thu Jun 16 20:33:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id F0CDE8105 for ; Thu, 16 Jun 2016 20:33:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id B33678F804C for ; Thu, 16 Jun 2016 18:33:48 -0700 (PDT) X-ASG-Debug-ID: 1466127226-04cbb01fec69fc0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 30dRulnXMKooNPz8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:46 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1XglP015902 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:42 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Xf9d029373 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:42 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Xfu9027440; Fri, 17 Jun 2016 01:33:41 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:41 -0700 Subject: [PATCH 028/145] xfs: introduce rmap btree definitions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 028/145] xfs: introduce rmap btree definitions To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:33:39 -0700 Message-ID: <146612721967.16048.14762057042303707100.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127226 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6314 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Add new per-ag rmap btree definitions to the per-ag structures. The rmap btree will sit in the empty slots on disk after the free space btrees, and hence form a part of the array of space management btrees. This requires the definition of the btree to be contiguous with the free space btrees. Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner --- libxfs/xfs_alloc.c | 6 ++++++ libxfs/xfs_btree.c | 4 ++-- libxfs/xfs_btree.h | 3 +++ libxfs/xfs_format.h | 22 +++++++++++++++++----- libxfs/xfs_types.h | 4 ++-- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 06133c0..675151d 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2268,6 +2268,10 @@ xfs_agf_verify( be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS) return false; + if (xfs_sb_version_hasrmapbt(&mp->m_sb) && + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS) + return false; + /* * during growfs operations, the perag is not fully initialised, * so we can't use it for any useful checking. growfs ensures we can't @@ -2399,6 +2403,8 @@ xfs_alloc_read_agf( be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]); pag->pagf_levels[XFS_BTNUM_CNTi] = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); + pag->pagf_levels[XFS_BTNUM_RMAPi] = + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); spin_lock_init(&pag->pagb_lock); pag->pagb_count = 0; #ifdef __KERNEL__ diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index c5a475f..8f66e14 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -40,9 +40,9 @@ kmem_zone_t *xfs_btree_cur_zone; * Btree magic numbers. */ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { - { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, + { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, XFS_FIBT_MAGIC }, - { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, + { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC, XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC } }; #define xfs_btree_magic(cur) \ diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 7483cac..202fdd3 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -63,6 +63,7 @@ union xfs_btree_rec { #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) +#define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi) /* * For logging record fields. @@ -95,6 +96,7 @@ do { \ case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ + case XFS_BTNUM_RMAP: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -115,6 +117,7 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ case XFS_BTNUM_FINO: \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ + case XFS_BTNUM_RMAP: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 825fa0c..cb30a25 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -455,6 +455,7 @@ xfs_sb_has_compat_feature( } #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ +#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL @@ -538,6 +539,12 @@ static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp) (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID); } +static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp) +{ + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && + (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT); +} + /* * end of superblock version macros */ @@ -598,10 +605,10 @@ xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino) #define XFS_AGI_GOOD_VERSION(v) ((v) == XFS_AGI_VERSION) /* - * Btree number 0 is bno, 1 is cnt. This value gives the size of the + * Btree number 0 is bno, 1 is cnt, 2 is rmap. This value gives the size of the * arrays below. */ -#define XFS_BTNUM_AGF ((int)XFS_BTNUM_CNTi + 1) +#define XFS_BTNUM_AGF ((int)XFS_BTNUM_RMAPi + 1) /* * The second word of agf_levels in the first a.g. overlaps the EFS @@ -618,12 +625,10 @@ typedef struct xfs_agf { __be32 agf_seqno; /* sequence # starting from 0 */ __be32 agf_length; /* size in blocks of a.g. */ /* - * Freespace information + * Freespace and rmap information */ __be32 agf_roots[XFS_BTNUM_AGF]; /* root blocks */ - __be32 agf_spare0; /* spare field */ __be32 agf_levels[XFS_BTNUM_AGF]; /* btree levels */ - __be32 agf_spare1; /* spare field */ __be32 agf_flfirst; /* first freelist block's index */ __be32 agf_fllast; /* last freelist block's index */ @@ -1307,6 +1312,13 @@ typedef __be32 xfs_inobt_ptr_t; #define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) /* + * Reverse mapping btree format definitions + * + * There is a btree for the reverse map per allocation group + */ +#define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ + +/* * The first data block of an AG depends on whether the filesystem was formatted * with the finobt feature. If so, account for the finobt reserved root btree * block. diff --git a/libxfs/xfs_types.h b/libxfs/xfs_types.h index f0d145a..da87796 100644 --- a/libxfs/xfs_types.h +++ b/libxfs/xfs_types.h @@ -111,8 +111,8 @@ typedef enum { } xfs_lookup_t; typedef enum { - XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, - XFS_BTNUM_FINOi, XFS_BTNUM_MAX + XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi, + XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_MAX } xfs_btnum_t; struct xfs_name { From darrick.wong@oracle.com Thu Jun 16 20:33:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id CADD87E47 for ; Thu, 16 Jun 2016 20:33:56 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 633C4AC002 for ; Thu, 16 Jun 2016 18:33:56 -0700 (PDT) X-ASG-Debug-ID: 1466127234-04bdf01e1796060001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 1kzq4o9jBGFiD0yh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:33:55 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Xo7X003022 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:50 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XnWc029464 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:50 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Xmmf022615; Fri, 17 Jun 2016 01:33:49 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:48 -0700 Subject: [PATCH 029/145] xfs: add rmap btree stats infrastructure From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 029/145] xfs: add rmap btree stats infrastructure To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:33:45 -0700 Message-ID: <146612722590.16048.12188344261083410845.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127235 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1343 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner The rmap btree will require the same stats as all the other generic btrees, so add al the code for that now. Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner --- libxfs/xfs_btree.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 202fdd3..a29067c 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -96,7 +96,7 @@ do { \ case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ - case XFS_BTNUM_RMAP: break; \ + case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -117,7 +117,8 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ case XFS_BTNUM_FINO: \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ - case XFS_BTNUM_RMAP: break; \ + case XFS_BTNUM_RMAP: \ + __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) From darrick.wong@oracle.com Thu Jun 16 20:34:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E4B9E7E4F for ; Thu, 16 Jun 2016 20:34:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id A3F558F8050 for ; Thu, 16 Jun 2016 18:34:02 -0700 (PDT) X-ASG-Debug-ID: 1466127240-04bdf01e1096070001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id dXWgXHqZz5B37izf (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:00 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1XuRF015942 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:56 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1XtEY002008 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:33:55 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1XttY032255; Fri, 17 Jun 2016 01:33:55 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:33:54 -0700 Subject: [PATCH 030/145] xfs: rmap btree add more reserved blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 030/145] xfs: rmap btree add more reserved blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:33:53 -0700 Message-ID: <146612723321.16048.10346293125851584186.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127240 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6567 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner XFS reserves a small amount of space in each AG for the minimum number of free blocks needed for operation. Adding the rmap btree increases the number of reserved blocks, but it also increases the complexity of the calculation as the free inode btree is optional (like the rmbt). Rather than calculate the prealloc blocks every time we need to check it, add a function to calculate it at mount time and store it in the struct xfs_mount, and convert the XFS_PREALLOC_BLOCKS macro just to use the xfs-mount variable directly. Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner --- include/xfs_mount.h | 1 + libxfs/init.c | 2 ++ libxfs/xfs_alloc.c | 11 +++++++++++ libxfs/xfs_alloc.h | 2 ++ libxfs/xfs_format.h | 9 +-------- mkfs/xfs_mkfs.c | 14 +++++++------- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/include/xfs_mount.h b/include/xfs_mount.h index 14b05a6..2c7c72e 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -67,6 +67,7 @@ typedef struct xfs_mount { uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */ + xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ struct radix_tree_root m_perag_tree; uint m_flags; /* global mount flags */ uint m_qflags; /* quota status flags */ diff --git a/libxfs/init.c b/libxfs/init.c index 553da7b..7b618da 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -572,6 +572,8 @@ libxfs_initialize_perag( if (maxagi) *maxagi = index; + + mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp); return 0; out_unwind: diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 675151d..738275f 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -46,6 +46,17 @@ STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); +xfs_extlen_t +xfs_prealloc_blocks( + struct xfs_mount *mp) +{ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + return XFS_RMAP_BLOCK(mp) + 1; + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + return XFS_FIBT_BLOCK(mp) + 1; + return XFS_IBT_BLOCK(mp) + 1; +} + /* * Lookup the record equal to [bno, len] in the btree given by cur. */ diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index cf268b2..20b54aa 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -232,4 +232,6 @@ int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **agbp); +xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); + #endif /* __XFS_ALLOC_H__ */ diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index cb30a25..12048fa 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -1318,18 +1318,11 @@ typedef __be32 xfs_inobt_ptr_t; */ #define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ -/* - * The first data block of an AG depends on whether the filesystem was formatted - * with the finobt feature. If so, account for the finobt reserved root btree - * block. - */ -#define XFS_PREALLOC_BLOCKS(mp) \ +#define XFS_RMAP_BLOCK(mp) \ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ XFS_FIBT_BLOCK(mp) + 1 : \ XFS_IBT_BLOCK(mp) + 1) - - /* * BMAP Btree format definitions * diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index de00c8e..e9d2851 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2965,7 +2965,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), /* * sb_versionnum and finobt flags must be set before we use - * XFS_PREALLOC_BLOCKS(). + * xfs_prealloc_blocks(). */ sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit); @@ -2982,7 +2982,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), /* revalidate the log size is valid if we changed it */ validate_log_size(logblocks, blocklog, min_logblocks); } - if (logblocks > agsize - XFS_PREALLOC_BLOCKS(mp)) { + if (logblocks > agsize - xfs_prealloc_blocks(mp)) { fprintf(stderr, _("internal log size %lld too large, must fit in allocation group\n"), (long long)logblocks); @@ -2999,7 +2999,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), } else logagno = (xfs_agnumber_t)(agcount / 2); - logstart = XFS_AGB_TO_FSB(mp, logagno, XFS_PREALLOC_BLOCKS(mp)); + logstart = XFS_AGB_TO_FSB(mp, logagno, xfs_prealloc_blocks(mp)); /* * Align the logstart at stripe unit boundary. */ @@ -3077,7 +3077,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), sbp->sb_imax_pct = imaxpct; sbp->sb_icount = 0; sbp->sb_ifree = 0; - sbp->sb_fdblocks = dblocks - agcount * XFS_PREALLOC_BLOCKS(mp) - + sbp->sb_fdblocks = dblocks - agcount * xfs_prealloc_blocks(mp) - (loginternal ? logblocks : 0); sbp->sb_frextents = 0; /* will do a free later */ sbp->sb_uquotino = sbp->sb_gquotino = sbp->sb_pquotino = 0; @@ -3219,7 +3219,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); agf->agf_flcount = 0; - nbmblocks = (xfs_extlen_t)(agsize - XFS_PREALLOC_BLOCKS(mp)); + nbmblocks = (xfs_extlen_t)(agsize - xfs_prealloc_blocks(mp)); agf->agf_freeblks = cpu_to_be32(nbmblocks); agf->agf_longest = cpu_to_be32(nbmblocks); if (xfs_sb_version_hascrc(&mp->m_sb)) @@ -3300,7 +3300,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), agno, 0); arec = XFS_ALLOC_REC_ADDR(mp, block, 1); - arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); + arec->ar_startblock = cpu_to_be32(xfs_prealloc_blocks(mp)); if (loginternal && agno == logagno) { if (lalign) { /* @@ -3355,7 +3355,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), agno, 0); arec = XFS_ALLOC_REC_ADDR(mp, block, 1); - arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); + arec->ar_startblock = cpu_to_be32(xfs_prealloc_blocks(mp)); if (loginternal && agno == logagno) { if (lalign) { arec->ar_blockcount = cpu_to_be32( From darrick.wong@oracle.com Thu Jun 16 20:34:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 3BA2B806B for ; Thu, 16 Jun 2016 20:34:10 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0C5218F804B for ; Thu, 16 Jun 2016 18:34:09 -0700 (PDT) X-ASG-Debug-ID: 1466127246-04cbb01fee6a020001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id gozjZ8XFkhJXPAwI (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Y2kY003316 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:02 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Y2PN002341 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:02 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Y1vq022694; Fri, 17 Jun 2016 01:34:01 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:00 -0700 Subject: [PATCH 031/145] xfs: add owner field to extent allocation and freeing From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 031/145] xfs: add owner field to extent allocation and freeing To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:33:59 -0700 Message-ID: <146612723948.16048.17689566761161440372.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127246 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15055 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines For the rmap btree to work, we have to feed the extent owner information to the the allocation and freeing functions. This information is what will end up in the rmap btree that tracks allocated extents. While we technically don't need the owner information when freeing extents, passing it allows us to validate that the extent we are removing from the rmap btree actually belonged to the owner we expected it to belong to. We also define a special set of owner values for internal metadata that would otherwise have no owner. This allows us to tell the difference between metadata owned by different per-ag btrees, as well as static fs metadata (e.g. AG headers) and internal journal blocks. There are also a couple of special cases we need to take care of - during EFI recovery, we don't actually know who the original owner was, so we need to pass a wildcard to indicate that we aren't checking the owner for validity. We also need special handling in growfs, as we "free" the space in the last AG when extending it, but because it's new space it has no actual owner... While touching the xfs_bmap_add_free() function, re-order the parameters to put the struct xfs_mount first. Extend the owner field to include both the owner type and some sort of index within the owner. The index field will be used to support reverse mappings when reflink is enabled. This is based upon a patch originally from Dave Chinner. It has been extended to add more owner information with the intent of helping recovery operations when things go wrong (e.g. offset of user data block in a file). [dchinner: de-shout the xfs_rmap_*_owner helpers] [darrick: minor style fixes suggested by Christoph Hellwig] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- libxfs/defer_item.c | 2 + libxfs/xfs_alloc.c | 11 ++++++-- libxfs/xfs_alloc.h | 4 ++- libxfs/xfs_bmap.c | 17 ++++++++++-- libxfs/xfs_bmap.h | 4 ++- libxfs/xfs_bmap_btree.c | 6 +++- libxfs/xfs_format.h | 65 +++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_ialloc.c | 7 +++-- libxfs/xfs_ialloc_btree.c | 7 ++++- 9 files changed, 110 insertions(+), 13 deletions(-) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index 72c28f8..777875c 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -92,7 +92,7 @@ xfs_bmap_free_finish_item( free = container_of(item, struct xfs_bmap_free_item, xbfi_list); error = xfs_free_extent(tp, free->xbfi_startblock, - free->xbfi_blockcount); + free->xbfi_blockcount, &free->xbfi_oinfo); kmem_free(free); return error; } diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 738275f..e3442a3 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -1592,6 +1592,7 @@ xfs_free_ag_extent( xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t bno, /* starting block number */ xfs_extlen_t len, /* length of extent */ + struct xfs_owner_info *oinfo, /* extent owner */ int isfl) /* set if is freelist blocks - no sb acctg */ { xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ @@ -2001,13 +2002,15 @@ xfs_alloc_fix_freelist( * back on the free list? Maybe we should only do this when space is * getting low or the AGFL is more than half full? */ + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); while (pag->pagf_flcount > need) { struct xfs_buf *bp; error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); if (error) goto out_agbp_relse; - error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, 1); + error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, + &targs.oinfo, 1); if (error) goto out_agbp_relse; bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); @@ -2017,6 +2020,7 @@ xfs_alloc_fix_freelist( memset(&targs, 0, sizeof(targs)); targs.tp = tp; targs.mp = mp; + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); targs.agbp = agbp; targs.agno = args->agno; targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; @@ -2707,7 +2711,8 @@ int /* error */ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ - xfs_extlen_t len) /* length of extent */ + xfs_extlen_t len, /* length of extent */ + struct xfs_owner_info *oinfo) /* extent owner */ { struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *agbp; @@ -2735,7 +2740,7 @@ xfs_free_extent( agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), err); - error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, 0); + error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, 0); if (error) goto err; diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 20b54aa..0721a48 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -123,6 +123,7 @@ typedef struct xfs_alloc_arg { char isfl; /* set if is freelist blocks - !acctg */ char userdata; /* mask defining userdata treatment */ xfs_fsblock_t firstblock; /* io first block allocated */ + struct xfs_owner_info oinfo; /* owner of blocks being allocated */ } xfs_alloc_arg_t; /* @@ -210,7 +211,8 @@ int /* error */ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ - xfs_extlen_t len); /* length of extent */ + xfs_extlen_t len, /* length of extent */ + struct xfs_owner_info *oinfo); /* extent owner */ int /* error */ xfs_alloc_lookup_ge( diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 33e181c..de1c759 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -566,7 +566,8 @@ xfs_bmap_add_free( struct xfs_mount *mp, /* mount point structure */ struct xfs_defer_ops *dfops, /* list of extents */ xfs_fsblock_t bno, /* fs block number of extent */ - xfs_filblks_t len) /* length of extent */ + xfs_filblks_t len, /* length of extent */ + struct xfs_owner_info *oinfo) /* extent owner */ { struct xfs_bmap_free_item *new; /* new element */ #ifdef DEBUG @@ -585,9 +586,14 @@ xfs_bmap_add_free( ASSERT(agbno + len <= mp->m_sb.sb_agblocks); #endif ASSERT(xfs_bmap_free_item_zone != NULL); + new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); new->xbfi_startblock = bno; new->xbfi_blockcount = (xfs_extlen_t)len; + if (oinfo) + memcpy(&new->xbfi_oinfo, oinfo, sizeof(struct xfs_owner_info)); + else + memset(&new->xbfi_oinfo, 0, sizeof(struct xfs_owner_info)); trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0, XFS_FSB_TO_AGBNO(mp, bno), len); xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xbfi_list); @@ -620,6 +626,7 @@ xfs_bmap_btree_to_extents( xfs_mount_t *mp; /* mount point structure */ __be64 *pp; /* ptr to block address */ struct xfs_btree_block *rblock;/* root btree block */ + struct xfs_owner_info oinfo; mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); @@ -643,7 +650,8 @@ xfs_bmap_btree_to_extents( cblock = XFS_BUF_TO_BLOCK(cbp); if ((error = xfs_btree_check_block(cur, cblock, 0, cbp))) return error; - xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1); + xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, cbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_mod_dquot_byino(tp, ip, XFS_TRANS_DQ_BCOUNT, -1L); xfs_trans_binval(tp, cbp); @@ -724,6 +732,7 @@ xfs_bmap_extents_to_btree( memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = mp; + xfs_rmap_ino_bmbt_owner(&args.oinfo, ip->i_ino, whichfork); args.firstblock = *firstblock; if (*firstblock == NULLFSBLOCK) { args.type = XFS_ALLOCTYPE_START_BNO; @@ -870,6 +879,7 @@ xfs_bmap_local_to_extents( memset(&args, 0, sizeof(args)); args.tp = tp; args.mp = ip->i_mount; + xfs_rmap_ino_owner(&args.oinfo, ip->i_ino, whichfork, 0); args.firstblock = *firstblock; /* * Allocate a block. We know we need only one, since the @@ -4831,6 +4841,7 @@ xfs_bmap_del_extent( nblks = 0; do_fx = 0; } + /* * Set flag value to use in switch statement. * Left-contig is 2, right-contig is 1. @@ -5018,7 +5029,7 @@ xfs_bmap_del_extent( */ if (do_fx) xfs_bmap_add_free(mp, dfops, del->br_startblock, - del->br_blockcount); + del->br_blockcount, NULL); /* * Adjust inode # blocks in the file. */ diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index 6854e61..41f7ef2 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -67,6 +67,7 @@ struct xfs_bmap_free_item xfs_fsblock_t xbfi_startblock;/* starting fs block number */ xfs_extlen_t xbfi_blockcount;/* number of blocks in extent */ struct list_head xbfi_list; + struct xfs_owner_info xbfi_oinfo; /* extent owner */ }; #define XFS_BMAP_MAX_NMAP 4 @@ -165,7 +166,8 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops, - xfs_fsblock_t bno, xfs_filblks_t len); + xfs_fsblock_t bno, xfs_filblks_t len, + struct xfs_owner_info *oinfo); void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork); diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index d290769..404e321 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -444,6 +444,8 @@ xfs_bmbt_alloc_block( args.mp = cur->bc_mp; args.fsbno = cur->bc_private.b.firstblock; args.firstblock = args.fsbno; + xfs_rmap_ino_bmbt_owner(&args.oinfo, cur->bc_private.b.ip->i_ino, + cur->bc_private.b.whichfork); if (args.fsbno == NULLFSBLOCK) { args.fsbno = be64_to_cpu(start->l); @@ -523,8 +525,10 @@ xfs_bmbt_free_block( struct xfs_inode *ip = cur->bc_private.b.ip; struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); + struct xfs_owner_info oinfo; - xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1); + xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, cur->bc_private.b.whichfork); + xfs_bmap_add_free(mp, cur->bc_private.b.dfops, fsbno, 1, &oinfo); ip->i_d.di_nblocks--; xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 12048fa..1b63315 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -1318,6 +1318,71 @@ typedef __be32 xfs_inobt_ptr_t; */ #define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ +/* + * Ownership info for an extent. This is used to create reverse-mapping + * entries. + */ +#define XFS_OWNER_INFO_ATTR_FORK (1 << 0) +#define XFS_OWNER_INFO_BMBT_BLOCK (1 << 1) +struct xfs_owner_info { + uint64_t oi_owner; + xfs_fileoff_t oi_offset; + unsigned int oi_flags; +}; + +static inline void +xfs_rmap_ag_owner( + struct xfs_owner_info *oi, + uint64_t owner) +{ + oi->oi_owner = owner; + oi->oi_offset = 0; + oi->oi_flags = 0; +} + +static inline void +xfs_rmap_ino_bmbt_owner( + struct xfs_owner_info *oi, + xfs_ino_t ino, + int whichfork) +{ + oi->oi_owner = ino; + oi->oi_offset = 0; + oi->oi_flags = XFS_OWNER_INFO_BMBT_BLOCK; + if (whichfork == XFS_ATTR_FORK) + oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; +} + +static inline void +xfs_rmap_ino_owner( + struct xfs_owner_info *oi, + xfs_ino_t ino, + int whichfork, + xfs_fileoff_t offset) +{ + oi->oi_owner = ino; + oi->oi_offset = offset; + oi->oi_flags = 0; + if (whichfork == XFS_ATTR_FORK) + oi->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; +} + +/* + * Special owner types. + * + * Seeing as we only support up to 8EB, we have the upper bit of the owner field + * to tell us we have a special owner value. We use these for static metadata + * allocated at mkfs/growfs time, as well as for freespace management metadata. + */ +#define XFS_RMAP_OWN_NULL (-1ULL) /* No owner, for growfs */ +#define XFS_RMAP_OWN_UNKNOWN (-2ULL) /* Unknown owner, for EFI recovery */ +#define XFS_RMAP_OWN_FS (-3ULL) /* static fs metadata */ +#define XFS_RMAP_OWN_LOG (-4ULL) /* static fs metadata */ +#define XFS_RMAP_OWN_AG (-5ULL) /* AG freespace btree blocks */ +#define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */ +#define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ +#define XFS_RMAP_OWN_MIN (-8ULL) /* guard */ + #define XFS_RMAP_BLOCK(mp) \ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ XFS_FIBT_BLOCK(mp) + 1 : \ diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 1545338..8c2344c 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -609,6 +609,7 @@ xfs_ialloc_ag_alloc( args.tp = tp; args.mp = tp->t_mountp; args.fsbno = NULLFSBLOCK; + xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INODES); #ifdef DEBUG /* randomly do sparse inode allocations */ @@ -1819,12 +1820,14 @@ xfs_difree_inode_chunk( int nextbit; xfs_agblock_t agbno; int contigblk; + struct xfs_owner_info oinfo; DECLARE_BITMAP(holemask, XFS_INOBT_HOLEMASK_BITS); + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); if (!xfs_inobt_issparse(rec->ir_holemask)) { /* not sparse, calculate extent info directly */ xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, sagbno), - mp->m_ialloc_blks); + mp->m_ialloc_blks, &oinfo); return; } @@ -1868,7 +1871,7 @@ xfs_difree_inode_chunk( ASSERT(agbno % mp->m_sb.sb_spino_align == 0); ASSERT(contigblk % mp->m_sb.sb_spino_align == 0); xfs_bmap_add_free(mp, dfops, XFS_AGB_TO_FSB(mp, agno, agbno), - contigblk); + contigblk, &oinfo); /* reset range to current bit and carry on... */ startidx = endidx = nextbit; diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c index cd61419..d79ddfe 100644 --- a/libxfs/xfs_ialloc_btree.c +++ b/libxfs/xfs_ialloc_btree.c @@ -95,6 +95,7 @@ xfs_inobt_alloc_block( memset(&args, 0, sizeof(args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; + xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_INOBT); args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.a.agno, sbno); args.minlen = 1; args.maxlen = 1; @@ -124,8 +125,12 @@ xfs_inobt_free_block( struct xfs_btree_cur *cur, struct xfs_buf *bp) { + struct xfs_owner_info oinfo; + + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT); return xfs_free_extent(cur->bc_tp, - XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1); + XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1, + &oinfo); } STATIC int From darrick.wong@oracle.com Thu Jun 16 20:34:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 3607A811A for ; Thu, 16 Jun 2016 20:34:15 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id E9F308F804B for ; Thu, 16 Jun 2016 18:34:14 -0700 (PDT) X-ASG-Debug-ID: 1466127252-04bdf01e10960a0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ZSNOPEBLUR8jhU5k (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:12 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Y8Ag003354 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:08 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Y8oa002496 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:08 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Y7dl032383; Fri, 17 Jun 2016 01:34:07 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:07 -0700 Subject: [PATCH 032/145] xfs: introduce rmap extent operation stubs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 032/145] xfs: introduce rmap extent operation stubs To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:34:05 -0700 Message-ID: <146612724583.16048.2052256322968130910.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127252 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7981 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Add the stubs into the extent allocation and freeing paths that the rmap btree implementation will hook into. While doing this, add the trace points that will be used to track rmap btree extent manipulations. [darrick.wong@oracle.com: Extend the stubs to take full owner info.] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- include/libxfs.h | 1 + include/xfs_trace.h | 6 +++ libxfs/Makefile | 2 + libxfs/xfs_alloc.c | 18 +++++++++- libxfs/xfs_rmap.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.h | 30 ++++++++++++++++ 6 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 libxfs/xfs_rmap.c create mode 100644 libxfs/xfs_rmap_btree.h diff --git a/include/libxfs.h b/include/libxfs.h index 863b0e3..5e76263 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -77,6 +77,7 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len); #include "xfs_bmap.h" #include "xfs_trace.h" #include "xfs_trans.h" +#include "xfs_rmap_btree.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index cdabd18..b4174a3 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -186,6 +186,12 @@ #define trace_xfs_bmap_free_deferred(...) ((void) 0) #define trace_xfs_bmap_free_defer(...) ((void) 0) +#define trace_xfs_rmap_free_extent(...) ((void) 0) +#define trace_xfs_rmap_free_extent_error(...) ((void) 0) +#define trace_xfs_rmap_alloc_extent(...) ((void) 0) +#define trace_xfs_rmap_alloc_extent_error(...) ((void) 0) +#define trace_xfs_rmap_alloc_extent_done(...) ((void) 0) +#define trace_xfs_rmap_free_extent_done(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/Makefile b/libxfs/Makefile index 0073cd1..d7a3e57 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -36,6 +36,7 @@ HFILES = \ xfs_inode_buf.h \ xfs_inode_fork.h \ xfs_quota_defs.h \ + xfs_rmap_btree.h \ xfs_sb.h \ xfs_shared.h \ xfs_trans_resv.h \ @@ -82,6 +83,7 @@ CFILES = cache.c \ xfs_inode_fork.c \ xfs_ialloc_btree.c \ xfs_log_rlimit.c \ + xfs_rmap.c \ xfs_rtbitmap.c \ xfs_sb.c \ xfs_symlink_remote.c \ diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index e3442a3..0f35e96 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -27,6 +27,7 @@ #include "xfs_defer.h" #include "xfs_inode.h" #include "xfs_btree.h" +#include "xfs_rmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_alloc.h" #include "xfs_cksum.h" @@ -644,6 +645,14 @@ xfs_alloc_ag_vextent( ASSERT(!args->wasfromfl || !args->isfl); ASSERT(args->agbno % args->alignment == 0); + /* if not file data, insert new block into the reverse map btree */ + if (args->oinfo.oi_owner) { + error = xfs_rmap_alloc(args->tp, args->agbp, args->agno, + args->agbno, args->len, &args->oinfo); + if (error) + return error; + } + if (!args->wasfromfl) { error = xfs_alloc_update_counters(args->tp, args->pag, args->agbp, @@ -1610,12 +1619,19 @@ xfs_free_ag_extent( xfs_extlen_t nlen; /* new length of freespace */ xfs_perag_t *pag; /* per allocation group data */ + bno_cur = cnt_cur = NULL; mp = tp->t_mountp; + + if (oinfo->oi_owner) { + error = xfs_rmap_free(tp, agbp, agno, bno, len, oinfo); + if (error) + goto error0; + } + /* * Allocate and initialize a cursor for the by-block btree. */ bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO); - cnt_cur = NULL; /* * Look for a neighboring block on the left (lower block numbers) * that is contiguous with this space. diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c new file mode 100644 index 0000000..31c6336 --- /dev/null +++ b/libxfs/xfs_rmap.c @@ -0,0 +1,88 @@ + +/* + * Copyright (c) 2014 Red Hat, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_da_format.h" +#include "xfs_da_btree.h" +#include "xfs_btree.h" +#include "xfs_trans.h" +#include "xfs_alloc.h" +#include "xfs_rmap_btree.h" +#include "xfs_trans_space.h" +#include "xfs_trace.h" + +int +xfs_rmap_free( + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = tp->t_mountp; + int error = 0; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + trace_xfs_rmap_free_extent(mp, agno, bno, len, false, oinfo); + if (1) + goto out_error; + trace_xfs_rmap_free_extent_done(mp, agno, bno, len, false, oinfo); + return 0; + +out_error: + trace_xfs_rmap_free_extent_error(mp, agno, bno, len, false, oinfo); + return error; +} + +int +xfs_rmap_alloc( + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = tp->t_mountp; + int error = 0; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + trace_xfs_rmap_alloc_extent(mp, agno, bno, len, false, oinfo); + if (1) + goto out_error; + trace_xfs_rmap_alloc_extent_done(mp, agno, bno, len, false, oinfo); + return 0; + +out_error: + trace_xfs_rmap_alloc_extent_error(mp, agno, bno, len, false, oinfo); + return error; +} diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h new file mode 100644 index 0000000..a3b8f90 --- /dev/null +++ b/libxfs/xfs_rmap_btree.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef __XFS_RMAP_BTREE_H__ +#define __XFS_RMAP_BTREE_H__ + +struct xfs_buf; + +int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + struct xfs_owner_info *oinfo); +int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + struct xfs_owner_info *oinfo); + +#endif /* __XFS_RMAP_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:34:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E60438129 for ; Thu, 16 Jun 2016 20:34:23 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5FDB6AC001 for ; Thu, 16 Jun 2016 18:34:23 -0700 (PDT) X-ASG-Debug-ID: 1466127259-04cb6c542457e70001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id pr28hD1nF43aHK6f (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1YEjj003458 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:15 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YEaO030111 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:14 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YE6F027625; Fri, 17 Jun 2016 01:34:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:13 -0700 Subject: [PATCH 033/145] xfs: define the on-disk rmap btree format From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 033/145] xfs: define the on-disk rmap btree format To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:34:12 -0700 Message-ID: <146612725229.16048.7815813365704135602.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127260 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17394 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Now we have all the surrounding call infrastructure in place, we can start filling out the rmap btree implementation. Start with the on-disk btree format; add everything needed to read, write and manipulate rmap btree blocks. This prepares the way for adding the btree operations implementation. [darrick: record owner and offset info in rmap btree] [darrick: fork, bmbt and unwritten state in rmap btree] [darrick: flags are a separate field in xfs_rmap_irec] [darrick: calculate maxlevels separately] [darrick: move 'unwritten' bit to rm_offset] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- include/xfs_mount.h | 3 + libxfs/Makefile | 1 libxfs/init.c | 2 + libxfs/xfs_btree.c | 3 + libxfs/xfs_btree.h | 18 +++-- libxfs/xfs_format.h | 140 +++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.c | 178 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.h | 32 ++++++++ libxfs/xfs_sb.c | 6 ++ libxfs/xfs_shared.h | 2 + 10 files changed, 377 insertions(+), 8 deletions(-) create mode 100644 libxfs/xfs_rmap_btree.c diff --git a/include/xfs_mount.h b/include/xfs_mount.h index 2c7c72e..7d63c93 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -64,9 +64,12 @@ typedef struct xfs_mount { uint m_bmap_dmnr[2]; /* XFS_BMAP_BLOCK_DMINRECS */ uint m_inobt_mxr[2]; /* XFS_INOBT_BLOCK_MAXRECS */ uint m_inobt_mnr[2]; /* XFS_INOBT_BLOCK_MINRECS */ + uint m_rmap_mxr[2]; /* max rmap btree records */ + uint m_rmap_mnr[2]; /* min rmap btree records */ uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */ + uint m_rmap_maxlevels; /* max rmap btree levels */ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ struct radix_tree_root m_perag_tree; uint m_flags; /* global mount flags */ diff --git a/libxfs/Makefile b/libxfs/Makefile index d7a3e57..df47da2 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -84,6 +84,7 @@ CFILES = cache.c \ xfs_ialloc_btree.c \ xfs_log_rlimit.c \ xfs_rmap.c \ + xfs_rmap_btree.c \ xfs_rtbitmap.c \ xfs_sb.c \ xfs_symlink_remote.c \ diff --git a/libxfs/init.c b/libxfs/init.c index 7b618da..c56d123 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -31,6 +31,7 @@ #include "xfs_inode_fork.h" #include "xfs_inode.h" #include "xfs_trans.h" +#include "xfs_rmap_btree.h" #include "libxfs.h" /* for now */ @@ -683,6 +684,7 @@ libxfs_mount( xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); xfs_ialloc_compute_maxlevels(mp); + xfs_rmapbt_compute_maxlevels(mp); if (sbp->sb_imax_pct) { /* Make sure the maximum inode count is a multiple of the diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 8f66e14..db0267a 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -1206,6 +1206,9 @@ xfs_btree_set_refs( case XFS_BTNUM_BMAP: xfs_buf_set_ref(bp, XFS_BMAP_BTREE_REF); break; + case XFS_BTNUM_RMAP: + xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF); + break; default: ASSERT(0); } diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index a29067c..90ea2a7 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -38,17 +38,19 @@ union xfs_btree_ptr { }; union xfs_btree_key { - xfs_bmbt_key_t bmbt; - xfs_bmdr_key_t bmbr; /* bmbt root block */ - xfs_alloc_key_t alloc; - xfs_inobt_key_t inobt; + struct xfs_bmbt_key bmbt; + xfs_bmdr_key_t bmbr; /* bmbt root block */ + xfs_alloc_key_t alloc; + struct xfs_inobt_key inobt; + struct xfs_rmap_key rmap; }; union xfs_btree_rec { - xfs_bmbt_rec_t bmbt; - xfs_bmdr_rec_t bmbr; /* bmbt root block */ - xfs_alloc_rec_t alloc; - xfs_inobt_rec_t inobt; + struct xfs_bmbt_rec bmbt; + xfs_bmdr_rec_t bmbr; /* bmbt root block */ + struct xfs_alloc_rec alloc; + struct xfs_inobt_rec inobt; + struct xfs_rmap_rec rmap; }; /* diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 1b63315..2525004 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -1383,11 +1383,151 @@ xfs_rmap_ino_owner( #define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ #define XFS_RMAP_OWN_MIN (-8ULL) /* guard */ +#define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63))) + +/* + * Data record structure + */ +struct xfs_rmap_rec { + __be32 rm_startblock; /* extent start block */ + __be32 rm_blockcount; /* extent length */ + __be64 rm_owner; /* extent owner */ + __be64 rm_offset; /* offset within the owner */ +}; + +/* + * rmap btree record + * rm_offset:63 is the attribute fork flag + * rm_offset:62 is the bmbt block flag + * rm_offset:61 is the unwritten extent flag (same as l0:63 in bmbt) + * rm_offset:54-60 aren't used and should be zero + * rm_offset:0-53 is the block offset within the inode + */ +#define XFS_RMAP_OFF_ATTR_FORK ((__uint64_t)1ULL << 63) +#define XFS_RMAP_OFF_BMBT_BLOCK ((__uint64_t)1ULL << 62) +#define XFS_RMAP_OFF_UNWRITTEN ((__uint64_t)1ULL << 61) + +#define XFS_RMAP_LEN_MAX ((__uint32_t)~0U) +#define XFS_RMAP_OFF_FLAGS (XFS_RMAP_OFF_ATTR_FORK | \ + XFS_RMAP_OFF_BMBT_BLOCK | \ + XFS_RMAP_OFF_UNWRITTEN) +#define XFS_RMAP_OFF_MASK ((__uint64_t)0x3FFFFFFFFFFFFFULL) + +#define XFS_RMAP_OFF(off) ((off) & XFS_RMAP_OFF_MASK) + +#define XFS_RMAP_IS_BMBT_BLOCK(off) (!!((off) & XFS_RMAP_OFF_BMBT_BLOCK)) +#define XFS_RMAP_IS_ATTR_FORK(off) (!!((off) & XFS_RMAP_OFF_ATTR_FORK)) +#define XFS_RMAP_IS_UNWRITTEN(len) (!!((off) & XFS_RMAP_OFF_UNWRITTEN)) + +#define RMAPBT_STARTBLOCK_BITLEN 32 +#define RMAPBT_BLOCKCOUNT_BITLEN 32 +#define RMAPBT_OWNER_BITLEN 64 +#define RMAPBT_ATTRFLAG_BITLEN 1 +#define RMAPBT_BMBTFLAG_BITLEN 1 +#define RMAPBT_EXNTFLAG_BITLEN 1 +#define RMAPBT_UNUSED_OFFSET_BITLEN 7 +#define RMAPBT_OFFSET_BITLEN 54 + +#define XFS_RMAP_ATTR_FORK (1 << 0) +#define XFS_RMAP_BMBT_BLOCK (1 << 1) +#define XFS_RMAP_UNWRITTEN (1 << 2) +#define XFS_RMAP_KEY_FLAGS (XFS_RMAP_ATTR_FORK | \ + XFS_RMAP_BMBT_BLOCK) +#define XFS_RMAP_REC_FLAGS (XFS_RMAP_UNWRITTEN) +struct xfs_rmap_irec { + xfs_agblock_t rm_startblock; /* extent start block */ + xfs_extlen_t rm_blockcount; /* extent length */ + __uint64_t rm_owner; /* extent owner */ + __uint64_t rm_offset; /* offset within the owner */ + unsigned int rm_flags; /* state flags */ +}; + +static inline __u64 +xfs_rmap_irec_offset_pack( + const struct xfs_rmap_irec *irec) +{ + __u64 x; + + x = XFS_RMAP_OFF(irec->rm_offset); + if (irec->rm_flags & XFS_RMAP_ATTR_FORK) + x |= XFS_RMAP_OFF_ATTR_FORK; + if (irec->rm_flags & XFS_RMAP_BMBT_BLOCK) + x |= XFS_RMAP_OFF_BMBT_BLOCK; + if (irec->rm_flags & XFS_RMAP_UNWRITTEN) + x |= XFS_RMAP_OFF_UNWRITTEN; + return x; +} + +static inline int +xfs_rmap_irec_offset_unpack( + __u64 offset, + struct xfs_rmap_irec *irec) +{ + if (offset & ~(XFS_RMAP_OFF_MASK | XFS_RMAP_OFF_FLAGS)) + return -EFSCORRUPTED; + irec->rm_offset = XFS_RMAP_OFF(offset); + if (offset & XFS_RMAP_OFF_ATTR_FORK) + irec->rm_flags |= XFS_RMAP_ATTR_FORK; + if (offset & XFS_RMAP_OFF_BMBT_BLOCK) + irec->rm_flags |= XFS_RMAP_BMBT_BLOCK; + if (offset & XFS_RMAP_OFF_UNWRITTEN) + irec->rm_flags |= XFS_RMAP_UNWRITTEN; + return 0; +} + +/* + * Key structure + * + * We don't use the length for lookups + */ +struct xfs_rmap_key { + __be32 rm_startblock; /* extent start block */ + __be64 rm_owner; /* extent owner */ + __be64 rm_offset; /* offset within the owner */ +} __attribute__((packed)); + +/* btree pointer type */ +typedef __be32 xfs_rmap_ptr_t; + #define XFS_RMAP_BLOCK(mp) \ (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ XFS_FIBT_BLOCK(mp) + 1 : \ XFS_IBT_BLOCK(mp) + 1) +static inline void +xfs_owner_info_unpack( + struct xfs_owner_info *oinfo, + uint64_t *owner, + uint64_t *offset, + unsigned int *flags) +{ + unsigned int r = 0; + + *owner = oinfo->oi_owner; + *offset = oinfo->oi_offset; + if (oinfo->oi_flags & XFS_OWNER_INFO_ATTR_FORK) + r |= XFS_RMAP_ATTR_FORK; + if (oinfo->oi_flags & XFS_OWNER_INFO_BMBT_BLOCK) + r |= XFS_RMAP_BMBT_BLOCK; + *flags = r; +} + +static inline void +xfs_owner_info_pack( + struct xfs_owner_info *oinfo, + uint64_t owner, + uint64_t offset, + unsigned int flags) +{ + oinfo->oi_owner = owner; + oinfo->oi_offset = XFS_RMAP_OFF(offset); + oinfo->oi_flags = 0; + if (flags & XFS_RMAP_ATTR_FORK) + oinfo->oi_flags |= XFS_OWNER_INFO_ATTR_FORK; + if (flags & XFS_RMAP_BMBT_BLOCK) + oinfo->oi_flags |= XFS_OWNER_INFO_BMBT_BLOCK; +} + /* * BMAP Btree format definitions * diff --git a/libxfs/xfs_rmap_btree.c b/libxfs/xfs_rmap_btree.c new file mode 100644 index 0000000..02636f6 --- /dev/null +++ b/libxfs/xfs_rmap_btree.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_bit.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_inode.h" +#include "xfs_trans.h" +#include "xfs_alloc.h" +#include "xfs_btree.h" +#include "xfs_rmap_btree.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" + +static struct xfs_btree_cur * +xfs_rmapbt_dup_cursor( + struct xfs_btree_cur *cur) +{ + return xfs_rmapbt_init_cursor(cur->bc_mp, cur->bc_tp, + cur->bc_private.a.agbp, cur->bc_private.a.agno); +} + +static bool +xfs_rmapbt_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); + struct xfs_perag *pag = bp->b_pag; + unsigned int level; + + /* + * magic number and level verification + * + * During growfs operations, we can't verify the exact level or owner as + * the perag is not fully initialised and hence not attached to the + * buffer. In this case, check against the maximum tree depth. + * + * Similarly, during log recovery we will have a perag structure + * attached, but the agf information will not yet have been initialised + * from the on disk AGF. Again, we can only check against maximum limits + * in this case. + */ + if (block->bb_magic != cpu_to_be32(XFS_RMAP_CRC_MAGIC)) + return false; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return false; + if (!xfs_btree_sblock_v5hdr_verify(bp)) + return false; + + level = be16_to_cpu(block->bb_level); + if (pag && pag->pagf_init) { + if (level >= pag->pagf_levels[XFS_BTNUM_RMAPi]) + return false; + } else if (level >= mp->m_rmap_maxlevels) + return false; + + return xfs_btree_sblock_verify(bp, mp->m_rmap_mxr[level != 0]); +} + +static void +xfs_rmapbt_read_verify( + struct xfs_buf *bp) +{ + if (!xfs_btree_sblock_verify_crc(bp)) + xfs_buf_ioerror(bp, -EFSBADCRC); + else if (!xfs_rmapbt_verify(bp)) + xfs_buf_ioerror(bp, -EFSCORRUPTED); + + if (bp->b_error) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_verifier_error(bp); + } +} + +static void +xfs_rmapbt_write_verify( + struct xfs_buf *bp) +{ + if (!xfs_rmapbt_verify(bp)) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_buf_ioerror(bp, -EFSCORRUPTED); + xfs_verifier_error(bp); + return; + } + xfs_btree_sblock_calc_crc(bp); + +} + +const struct xfs_buf_ops xfs_rmapbt_buf_ops = { + .name = "xfs_rmapbt", + .verify_read = xfs_rmapbt_read_verify, + .verify_write = xfs_rmapbt_write_verify, +}; + +static const struct xfs_btree_ops xfs_rmapbt_ops = { + .rec_len = sizeof(struct xfs_rmap_rec), + .key_len = sizeof(struct xfs_rmap_key), + + .dup_cursor = xfs_rmapbt_dup_cursor, + .buf_ops = &xfs_rmapbt_buf_ops, +}; + +/* + * Allocate a new allocation btree cursor. + */ +struct xfs_btree_cur * +xfs_rmapbt_init_cursor( + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + struct xfs_btree_cur *cur; + + cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); + cur->bc_tp = tp; + cur->bc_mp = mp; + cur->bc_btnum = XFS_BTNUM_RMAP; + cur->bc_flags = XFS_BTREE_CRC_BLOCKS; + cur->bc_blocklog = mp->m_sb.sb_blocklog; + cur->bc_ops = &xfs_rmapbt_ops; + cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); + + cur->bc_private.a.agbp = agbp; + cur->bc_private.a.agno = agno; + + return cur; +} + +/* + * Calculate number of records in an rmap btree block. + */ +int +xfs_rmapbt_maxrecs( + struct xfs_mount *mp, + int blocklen, + int leaf) +{ + blocklen -= XFS_RMAP_BLOCK_LEN; + + if (leaf) + return blocklen / sizeof(struct xfs_rmap_rec); + return blocklen / + (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); +} + +/* Compute the maximum height of an rmap btree. */ +void +xfs_rmapbt_compute_maxlevels( + struct xfs_mount *mp) +{ + mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, + mp->m_rmap_mnr, mp->m_sb.sb_agblocks); +} diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index a3b8f90..462767f 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -19,6 +19,38 @@ #define __XFS_RMAP_BTREE_H__ struct xfs_buf; +struct xfs_btree_cur; +struct xfs_mount; + +/* rmaps only exist on crc enabled filesystems */ +#define XFS_RMAP_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN + +/* + * Record, key, and pointer address macros for btree blocks. + * + * (note that some of these may appear unused, but they are used in userspace) + */ +#define XFS_RMAP_REC_ADDR(block, index) \ + ((struct xfs_rmap_rec *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + (((index) - 1) * sizeof(struct xfs_rmap_rec)))) + +#define XFS_RMAP_KEY_ADDR(block, index) \ + ((struct xfs_rmap_key *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + ((index) - 1) * sizeof(struct xfs_rmap_key))) + +#define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \ + ((xfs_rmap_ptr_t *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + (maxrecs) * sizeof(struct xfs_rmap_key) + \ + ((index) - 1) * sizeof(xfs_rmap_ptr_t))) + +struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, + struct xfs_trans *tp, struct xfs_buf *bp, + xfs_agnumber_t agno); +int xfs_rmapbt_maxrecs(struct xfs_mount *mp, int blocklen, int leaf); +extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp); int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index a4ee48e..0dfa179 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -34,6 +34,7 @@ #include "xfs_bmap_btree.h" #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" +#include "xfs_rmap_btree.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. @@ -731,6 +732,11 @@ xfs_sb_mount_common( mp->m_bmap_dmnr[0] = mp->m_bmap_dmxr[0] / 2; mp->m_bmap_dmnr[1] = mp->m_bmap_dmxr[1] / 2; + mp->m_rmap_mxr[0] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 1); + mp->m_rmap_mxr[1] = xfs_rmapbt_maxrecs(mp, sbp->sb_blocksize, 0); + mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2; + mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2; + mp->m_bsize = XFS_FSB_TO_BB(mp, 1); mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK, sbp->sb_inopblock); diff --git a/libxfs/xfs_shared.h b/libxfs/xfs_shared.h index 16002b5..0c5b30b 100644 --- a/libxfs/xfs_shared.h +++ b/libxfs/xfs_shared.h @@ -38,6 +38,7 @@ extern const struct xfs_buf_ops xfs_agi_buf_ops; extern const struct xfs_buf_ops xfs_agf_buf_ops; extern const struct xfs_buf_ops xfs_agfl_buf_ops; extern const struct xfs_buf_ops xfs_allocbt_buf_ops; +extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; extern const struct xfs_buf_ops xfs_bmbt_buf_ops; @@ -116,6 +117,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *); #define XFS_INO_BTREE_REF 3 #define XFS_ALLOC_BTREE_REF 2 #define XFS_BMAP_BTREE_REF 2 +#define XFS_RMAP_BTREE_REF 2 #define XFS_DIR_BTREE_REF 2 #define XFS_INO_REF 2 #define XFS_ATTR_BTREE_REF 1 From darrick.wong@oracle.com Thu Jun 16 20:34:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D02BA8137 for ; Thu, 16 Jun 2016 20:34:28 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 47F0FAC001 for ; Thu, 16 Jun 2016 18:34:28 -0700 (PDT) X-ASG-Debug-ID: 1466127265-04cbb01fee6a070001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id dhE2atXGbq1HLyIo (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:26 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1YKhK003558 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:34:21 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1YKCT028784 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:20 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YKLE027665; Fri, 17 Jun 2016 01:34:20 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:20 -0700 Subject: [PATCH 034/145] xfs: rmap btree transaction reservations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 034/145] xfs: rmap btree transaction reservations To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:34:18 -0700 Message-ID: <146612725864.16048.5510258305657258555.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127266 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8369 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines The rmap btrees will use the AGFL as the block allocation source, so we need to ensure that the transaction reservations reflect the fact this tree is modified by allocation and freeing. Hence we need to extend all the extent allocation/free reservations used in transactions to handle this. Note that this also gets rid of the unused XFS_ALLOCFREE_LOG_RES macro, as we now do buffer reservations based on the number of buffers logged via xfs_calc_buf_res(). Hence we only need the buffer count calculation now. [darrick: use rmap_maxlevels when calculating log block resv] Signed-off-by: Dave Chinner Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong --- libxfs/xfs_trans_resv.c | 58 +++++++++++++++++++++++++++++++++-------------- libxfs/xfs_trans_resv.h | 10 -------- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c index c55220f..2ed80a5 100644 --- a/libxfs/xfs_trans_resv.c +++ b/libxfs/xfs_trans_resv.c @@ -63,6 +63,30 @@ xfs_calc_buf_res( } /* + * Per-extent log reservation for the btree changes involved in freeing or + * allocating an extent. In classic XFS there were two trees that will be + * modified (bnobt + cntbt). With rmap enabled, there are three trees + * (rmapbt). The number of blocks reserved is based on the formula: + * + * num trees * ((2 blocks/level * max depth) - 1) + * + * Keep in mind that max depth is calculated separately for each type of tree. + */ +static uint +xfs_allocfree_log_count( + struct xfs_mount *mp, + uint num_ops) +{ + uint blocks; + + blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1); + + return blocks; +} + +/* * Logging inodes is really tricksy. They are logged in memory format, * which means that what we write into the log doesn't directly translate into * the amount of space they use on disk. @@ -125,7 +149,7 @@ xfs_calc_inode_res( */ STATIC uint xfs_calc_finobt_res( - struct xfs_mount *mp, + struct xfs_mount *mp, int alloc, int modify) { @@ -136,7 +160,7 @@ xfs_calc_finobt_res( res = xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)); if (alloc) - res += xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + res += xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); if (modify) res += (uint)XFS_FSB_TO_B(mp, 1); @@ -187,10 +211,10 @@ xfs_calc_write_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } @@ -216,10 +240,10 @@ xfs_calc_itruncate_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(5, 0) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(2 + mp->m_ialloc_blks + mp->m_in_maxlevels, 0))); @@ -246,7 +270,7 @@ xfs_calc_rename_reservation( xfs_calc_buf_res(2 * XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(7, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 3), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 3), XFS_FSB_TO_B(mp, 1)))); } @@ -285,7 +309,7 @@ xfs_calc_link_reservation( xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)))); } @@ -323,7 +347,7 @@ xfs_calc_remove_reservation( xfs_calc_buf_res(XFS_DIROP_LOG_COUNT(mp), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(4, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } @@ -370,7 +394,7 @@ xfs_calc_create_resv_alloc( mp->m_sb.sb_sectsize + xfs_calc_buf_res(mp->m_ialloc_blks, XFS_FSB_TO_B(mp, 1)) + xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -398,7 +422,7 @@ xfs_calc_icreate_resv_alloc( return xfs_calc_buf_res(2, mp->m_sb.sb_sectsize) + mp->m_sb.sb_sectsize + xfs_calc_buf_res(mp->m_in_maxlevels, XFS_FSB_TO_B(mp, 1)) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_finobt_res(mp, 0, 0); } @@ -482,7 +506,7 @@ xfs_calc_ifree_reservation( xfs_calc_buf_res(1, 0) + xfs_calc_buf_res(2 + mp->m_ialloc_blks + mp->m_in_maxlevels, 0) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)) + xfs_calc_finobt_res(mp, 0, 1); } @@ -512,7 +536,7 @@ xfs_calc_growdata_reservation( struct xfs_mount *mp) { return xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -534,7 +558,7 @@ xfs_calc_growrtalloc_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), XFS_FSB_TO_B(mp, 1)) + xfs_calc_inode_res(mp, 1) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -610,7 +634,7 @@ xfs_calc_addafork_reservation( xfs_calc_buf_res(1, mp->m_dir_geo->blksize) + xfs_calc_buf_res(XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1, XFS_FSB_TO_B(mp, 1)) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 1), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), XFS_FSB_TO_B(mp, 1)); } @@ -633,7 +657,7 @@ xfs_calc_attrinval_reservation( xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK), XFS_FSB_TO_B(mp, 1))), (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 4), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), XFS_FSB_TO_B(mp, 1)))); } @@ -700,7 +724,7 @@ xfs_calc_attrrm_reservation( XFS_BM_MAXLEVELS(mp, XFS_ATTR_FORK)) + xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), 0)), (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) + - xfs_calc_buf_res(XFS_ALLOCFREE_LOG_COUNT(mp, 2), + xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), XFS_FSB_TO_B(mp, 1)))); } diff --git a/libxfs/xfs_trans_resv.h b/libxfs/xfs_trans_resv.h index 7978150..0eb46ed 100644 --- a/libxfs/xfs_trans_resv.h +++ b/libxfs/xfs_trans_resv.h @@ -68,16 +68,6 @@ struct xfs_trans_resv { #define M_RES(mp) (&(mp)->m_resv) /* - * Per-extent log reservation for the allocation btree changes - * involved in freeing or allocating an extent. - * 2 trees * (2 blocks/level * max depth - 1) * block size - */ -#define XFS_ALLOCFREE_LOG_RES(mp,nx) \ - ((nx) * (2 * XFS_FSB_TO_B((mp), 2 * (mp)->m_ag_maxlevels - 1))) -#define XFS_ALLOCFREE_LOG_COUNT(mp,nx) \ - ((nx) * (2 * (2 * (mp)->m_ag_maxlevels - 1))) - -/* * Per-directory log reservation for any directory change. * dir blocks: (1 btree block per level + data block + free block) * dblock size * bmap btree: (levels + 2) * max depth * block size From darrick.wong@oracle.com Thu Jun 16 20:34:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E96BA813D for ; Thu, 16 Jun 2016 20:34:35 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id A8468304048 for ; Thu, 16 Jun 2016 18:34:35 -0700 (PDT) X-ASG-Debug-ID: 1466127273-04bdf01e13960e0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id IVTxz9spotoCD142 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:33 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1YShP003586 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:28 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YRvn030438 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:28 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YQcV022770; Fri, 17 Jun 2016 01:34:27 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:26 -0700 Subject: [PATCH 035/145] xfs: rmap btree requires more reserved free space From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 035/145] xfs: rmap btree requires more reserved free space To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:34:24 -0700 Message-ID: <146612726489.16048.15166686813025455661.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127273 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10001 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner The rmap btree is allocated from the AGFL, which means we have to ensure ENOSPC is reported to userspace before we run out of free space in each AG. The last allocation in an AG can cause a full height rmap btree split, and that means we have to reserve at least this many blocks *in each AG* to be placed on the AGFL at ENOSPC. Update the various space calculation functiosn to handle this. Also, because the macros are now executing conditional code and are called quite frequently, convert them to functions that initialise varaibles in the struct xfs_mount, use the new variables everywhere and document the calculations better. v2: If rmapbt is disabled, it is incorrect to require 1 extra AGFL block for the rmapbt (due to the + 1); the entire clause needs to be gated on the feature flag. v3: Use m_rmap_maxlevels to determine min_free. [darrick.wong@oracle.com: don't reserve blocks if !rmap] [dchinner@redhat.com: update m_ag_max_usable after growfs] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- include/xfs_mount.h | 2 + libxfs/xfs_alloc.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_alloc.h | 41 ++++------------------------- libxfs/xfs_bmap.c | 2 + libxfs/xfs_sb.c | 2 + mkfs/xfs_mkfs.c | 2 + 6 files changed, 82 insertions(+), 38 deletions(-) diff --git a/include/xfs_mount.h b/include/xfs_mount.h index 7d63c93..5cd9464 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -71,6 +71,8 @@ typedef struct xfs_mount { uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */ uint m_rmap_maxlevels; /* max rmap btree levels */ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ + uint m_alloc_set_aside; /* space we can't use */ + uint m_ag_max_usable; /* max space per AG */ struct radix_tree_root m_perag_tree; uint m_flags; /* global mount flags */ uint m_qflags; /* quota status flags */ diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 0f35e96..7d680da 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -59,6 +59,72 @@ xfs_prealloc_blocks( } /* + * In order to avoid ENOSPC-related deadlock caused by out-of-order locking of + * AGF buffer (PV 947395), we place constraints on the relationship among + * actual allocations for data blocks, freelist blocks, and potential file data + * bmap btree blocks. However, these restrictions may result in no actual space + * allocated for a delayed extent, for example, a data block in a certain AG is + * allocated but there is no additional block for the additional bmap btree + * block due to a split of the bmap btree of the file. The result of this may + * lead to an infinite loop when the file gets flushed to disk and all delayed + * extents need to be actually allocated. To get around this, we explicitly set + * aside a few blocks which will not be reserved in delayed allocation. + * + * The minimum number of needed freelist blocks is 4 fsbs _per AG_ when we are + * not using rmap btrees a potential split of file's bmap btree requires 1 fsb, + * so we set the number of set-aside blocks to 4 + 4*agcount when not using + * rmap btrees. + * + * When rmap btrees are active, we have to consider that using the last block + * in the AG can cause a full height rmap btree split and we need enough blocks + * on the AGFL to be able to handle this. That means we have, in addition to + * the above consideration, another (2 * mp->m_rmap_levels) - 1 blocks required + * to be available to the free list. + */ +unsigned int +xfs_alloc_set_aside( + struct xfs_mount *mp) +{ + unsigned int blocks; + + blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE); + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return blocks; + return blocks + (mp->m_sb.sb_agcount * (2 * mp->m_rmap_maxlevels) - 1); +} + +/* + * When deciding how much space to allocate out of an AG, we limit the + * allocation maximum size to the size the AG. However, we cannot use all the + * blocks in the AG - some are permanently used by metadata. These + * blocks are generally: + * - the AG superblock, AGF, AGI and AGFL + * - the AGF (bno and cnt) and AGI btree root blocks, and optionally + * the AGI free inode and rmap btree root blocks. + * - blocks on the AGFL according to xfs_alloc_set_aside() limits + * + * The AG headers are sector sized, so the amount of space they take up is + * dependent on filesystem geometry. The others are all single blocks. + */ +unsigned int +xfs_alloc_ag_max_usable(struct xfs_mount *mp) +{ + unsigned int blocks; + + blocks = XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)); /* ag headers */ + blocks += XFS_ALLOC_AGFL_RESERVE; + blocks += 3; /* AGF, AGI btree root blocks */ + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + blocks++; /* finobt root block */ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + /* rmap root block + full tree split on full AG */ + blocks += 1 + (2 * mp->m_ag_maxlevels) - 1; + } + + return mp->m_sb.sb_agblocks - blocks; +} + +/* * Lookup the record equal to [bno, len] in the btree given by cur. */ STATIC int /* error */ @@ -1900,6 +1966,11 @@ xfs_alloc_min_freelist( /* space needed by-size freespace btree */ min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1, mp->m_ag_maxlevels); + /* space needed reverse mapping used space btree */ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + min_free += min_t(unsigned int, + pag->pagf_levels[XFS_BTNUM_RMAPi] + 1, + mp->m_rmap_maxlevels); return min_free; } diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 0721a48..7b6c66b 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -56,42 +56,6 @@ typedef unsigned int xfs_alloctype_t; #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ /* - * In order to avoid ENOSPC-related deadlock caused by - * out-of-order locking of AGF buffer (PV 947395), we place - * constraints on the relationship among actual allocations for - * data blocks, freelist blocks, and potential file data bmap - * btree blocks. However, these restrictions may result in no - * actual space allocated for a delayed extent, for example, a data - * block in a certain AG is allocated but there is no additional - * block for the additional bmap btree block due to a split of the - * bmap btree of the file. The result of this may lead to an - * infinite loop in xfssyncd when the file gets flushed to disk and - * all delayed extents need to be actually allocated. To get around - * this, we explicitly set aside a few blocks which will not be - * reserved in delayed allocation. Considering the minimum number of - * needed freelist blocks is 4 fsbs _per AG_, a potential split of file's bmap - * btree requires 1 fsb, so we set the number of set-aside blocks - * to 4 + 4*agcount. - */ -#define XFS_ALLOC_SET_ASIDE(mp) (4 + ((mp)->m_sb.sb_agcount * 4)) - -/* - * When deciding how much space to allocate out of an AG, we limit the - * allocation maximum size to the size the AG. However, we cannot use all the - * blocks in the AG - some are permanently used by metadata. These - * blocks are generally: - * - the AG superblock, AGF, AGI and AGFL - * - the AGF (bno and cnt) and AGI btree root blocks - * - 4 blocks on the AGFL according to XFS_ALLOC_SET_ASIDE() limits - * - * The AG headers are sector sized, so the amount of space they take up is - * dependent on filesystem geometry. The others are all single blocks. - */ -#define XFS_ALLOC_AG_MAX_USABLE(mp) \ - ((mp)->m_sb.sb_agblocks - XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)) - 7) - - -/* * Argument structure for xfs_alloc routines. * This is turned into a structure to avoid having 20 arguments passed * down several levels of the stack. @@ -133,6 +97,11 @@ typedef struct xfs_alloc_arg { #define XFS_ALLOC_INITIAL_USER_DATA (1 << 1)/* special case start of file */ #define XFS_ALLOC_USERDATA_ZERO (1 << 2)/* zero extent on allocation */ +/* freespace limit calculations */ +#define XFS_ALLOC_AGFL_RESERVE 4 +unsigned int xfs_alloc_set_aside(struct xfs_mount *mp); +unsigned int xfs_alloc_ag_max_usable(struct xfs_mount *mp); + xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp, struct xfs_perag *pag, xfs_extlen_t need); unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp, diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index de1c759..453d073 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -3664,7 +3664,7 @@ xfs_bmap_btalloc( args.fsbno = ap->blkno; /* Trim the allocation back to the maximum an AG can fit. */ - args.maxlen = MIN(ap->length, XFS_ALLOC_AG_MAX_USABLE(mp)); + args.maxlen = MIN(ap->length, mp->m_ag_max_usable); args.firstblock = *ap->firstblock; blen = 0; if (nullfb) { diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index 0dfa179..26c29ea 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -746,6 +746,8 @@ xfs_sb_mount_common( mp->m_ialloc_min_blks = sbp->sb_spino_align; else mp->m_ialloc_min_blks = mp->m_ialloc_blks; + mp->m_alloc_set_aside = xfs_alloc_set_aside(mp); + mp->m_ag_max_usable = xfs_alloc_ag_max_usable(mp); } /* diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index e9d2851..4b5df98 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2977,7 +2977,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), */ if (!logsize) { logblocks = MIN(logblocks, - XFS_ALLOC_AG_MAX_USABLE(mp)); + xfs_alloc_ag_max_usable(mp)); /* revalidate the log size is valid if we changed it */ validate_log_size(logblocks, blocklog, min_logblocks); From darrick.wong@oracle.com Thu Jun 16 20:34:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 55654810B for ; Thu, 16 Jun 2016 20:34:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 25CEC304039 for ; Thu, 16 Jun 2016 18:34:42 -0700 (PDT) X-ASG-Debug-ID: 1466127278-04cb6c542757ec0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id YbmrWiU5qiW247FU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1YYMo016557 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:34 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YXua003023 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:33 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1YXb2032479; Fri, 17 Jun 2016 01:34:33 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:32 -0700 Subject: [PATCH 036/145] xfs: add rmap btree operations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 036/145] xfs: add rmap btree operations To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:34:31 -0700 Message-ID: <146612727120.16048.13165169801894764616.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127279 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13572 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Implement the generic btree operations needed to manipulate rmap btree blocks. This is very similar to the per-ag freespace btree implementation, and uses the AGFL for allocation and freeing of blocks. Adapt the rmap btree to store owner offsets within each rmap record, and to handle the primary key being redefined as the tuple [agblk, owner, offset]. The expansion of the primary key is crucial to allowing multiple owners per extent. [darrick: adapt the btree ops to deal with offsets] [darrick: remove init_rec_from_key] [darrick: move unwritten bit to rm_offset] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- include/xfs_trace.h | 2 libxfs/xfs_btree.h | 1 libxfs/xfs_rmap.c | 96 +++++++++++++++++++ libxfs/xfs_rmap_btree.c | 243 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.h | 9 ++ 5 files changed, 351 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index b4174a3..af3f68b 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -192,6 +192,8 @@ #define trace_xfs_rmap_alloc_extent_error(...) ((void) 0) #define trace_xfs_rmap_alloc_extent_done(...) ((void) 0) #define trace_xfs_rmap_free_extent_done(...) ((void) 0) +#define trace_xfs_rmapbt_free_block(...) ((void) 0) +#define trace_xfs_rmapbt_alloc_block(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 90ea2a7..9963c48 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -216,6 +216,7 @@ union xfs_btree_irec { xfs_alloc_rec_incore_t a; xfs_bmbt_irec_t b; xfs_inobt_rec_incore_t i; + struct xfs_rmap_irec r; }; /* diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 31c6336..5034fd3 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -35,6 +35,102 @@ #include "xfs_trans_space.h" #include "xfs_trace.h" +/* + * Lookup the first record less than or equal to [bno, len, owner, offset] + * in the btree given by cur. + */ +int +xfs_rmap_lookup_le( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags, + int *stat) +{ + cur->bc_rec.r.rm_startblock = bno; + cur->bc_rec.r.rm_blockcount = len; + cur->bc_rec.r.rm_owner = owner; + cur->bc_rec.r.rm_offset = offset; + cur->bc_rec.r.rm_flags = flags; + return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); +} + +/* + * Lookup the record exactly matching [bno, len, owner, offset] + * in the btree given by cur. + */ +int +xfs_rmap_lookup_eq( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags, + int *stat) +{ + cur->bc_rec.r.rm_startblock = bno; + cur->bc_rec.r.rm_blockcount = len; + cur->bc_rec.r.rm_owner = owner; + cur->bc_rec.r.rm_offset = offset; + cur->bc_rec.r.rm_flags = flags; + return xfs_btree_lookup(cur, XFS_LOOKUP_EQ, stat); +} + +/* + * Update the record referred to by cur to the value given + * by [bno, len, owner, offset]. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_rmap_update( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *irec) +{ + union xfs_btree_rec rec; + + rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock); + rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount); + rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner); + rec.rmap.rm_offset = cpu_to_be64( + xfs_rmap_irec_offset_pack(irec)); + return xfs_btree_update(cur, &rec); +} + +static int +xfs_rmapbt_btrec_to_irec( + union xfs_btree_rec *rec, + struct xfs_rmap_irec *irec) +{ + irec->rm_flags = 0; + irec->rm_startblock = be32_to_cpu(rec->rmap.rm_startblock); + irec->rm_blockcount = be32_to_cpu(rec->rmap.rm_blockcount); + irec->rm_owner = be64_to_cpu(rec->rmap.rm_owner); + return xfs_rmap_irec_offset_unpack(be64_to_cpu(rec->rmap.rm_offset), + irec); +} + +/* + * Get the data from the pointed-to record. + */ +int +xfs_rmap_get_rec( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *irec, + int *stat) +{ + union xfs_btree_rec *rec; + int error; + + error = xfs_btree_get_rec(cur, &rec, stat); + if (error || !*stat) + return error; + + return xfs_rmapbt_btrec_to_irec(rec, irec); +} + int xfs_rmap_free( struct xfs_trans *tp, diff --git a/libxfs/xfs_rmap_btree.c b/libxfs/xfs_rmap_btree.c index 02636f6..c8fd99e 100644 --- a/libxfs/xfs_rmap_btree.c +++ b/libxfs/xfs_rmap_btree.c @@ -33,6 +33,31 @@ #include "xfs_trace.h" #include "xfs_cksum.h" +/* + * Reverse map btree. + * + * This is a per-ag tree used to track the owner(s) of a given extent. With + * reflink it is possible for there to be multiple owners, which is a departure + * from classic XFS. Owner records for data extents are inserted when the + * extent is mapped and removed when an extent is unmapped. Owner records for + * all other block types (i.e. metadata) are inserted when an extent is + * allocated and removed when an extent is freed. There can only be one owner + * of a metadata extent, usually an inode or some other metadata structure like + * an AG btree. + * + * The rmap btree is part of the free space management, so blocks for the tree + * are sourced from the agfl. Hence we need transaction reservation support for + * this tree so that the freelist is always large enough. This also impacts on + * the minimum space we need to leave free in the AG. + * + * The tree is ordered by [ag block, owner, offset]. This is a large key size, + * but it is the only way to enforce unique keys when a block can be owned by + * multiple files at any offset. There's no need to order/search by extent + * size for online updating/management of the tree. It is intended that most + * reverse lookups will be to find the owner(s) of a particular block, or to + * try to recover tree and file data from corrupt primary metadata. + */ + static struct xfs_btree_cur * xfs_rmapbt_dup_cursor( struct xfs_btree_cur *cur) @@ -41,6 +66,173 @@ xfs_rmapbt_dup_cursor( cur->bc_private.a.agbp, cur->bc_private.a.agno); } +STATIC void +xfs_rmapbt_set_root( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr, + int inc) +{ + struct xfs_buf *agbp = cur->bc_private.a.agbp; + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); + int btnum = cur->bc_btnum; + struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); + + ASSERT(ptr->s != 0); + + agf->agf_roots[btnum] = ptr->s; + be32_add_cpu(&agf->agf_levels[btnum], inc); + pag->pagf_levels[btnum] += inc; + xfs_perag_put(pag); + + xfs_alloc_log_agf(cur->bc_tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); +} + +STATIC int +xfs_rmapbt_alloc_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *start, + union xfs_btree_ptr *new, + int *stat) +{ + int error; + xfs_agblock_t bno; + + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); + + /* Allocate the new block from the freelist. If we can't, give up. */ + error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp, + &bno, 1); + if (error) { + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); + return error; + } + + trace_xfs_rmapbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, + bno, 1); + if (bno == NULLAGBLOCK) { + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 0; + return 0; + } + + xfs_extent_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1, + false); + + xfs_trans_agbtree_delta(cur->bc_tp, 1); + new->s = cpu_to_be32(bno); + + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 1; + return 0; +} + +STATIC int +xfs_rmapbt_free_block( + struct xfs_btree_cur *cur, + struct xfs_buf *bp) +{ + struct xfs_buf *agbp = cur->bc_private.a.agbp; + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + xfs_agblock_t bno; + int error; + + bno = xfs_daddr_to_agbno(cur->bc_mp, XFS_BUF_ADDR(bp)); + trace_xfs_rmapbt_free_block(cur->bc_mp, cur->bc_private.a.agno, + bno, 1); + error = xfs_alloc_put_freelist(cur->bc_tp, agbp, NULL, bno, 1); + if (error) + return error; + + xfs_extent_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1, + XFS_EXTENT_BUSY_SKIP_DISCARD); + xfs_trans_agbtree_delta(cur->bc_tp, -1); + + xfs_trans_binval(cur->bc_tp, bp); + return 0; +} + +STATIC int +xfs_rmapbt_get_minrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_rmap_mnr[level != 0]; +} + +STATIC int +xfs_rmapbt_get_maxrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_rmap_mxr[level != 0]; +} + +STATIC void +xfs_rmapbt_init_key_from_rec( + union xfs_btree_key *key, + union xfs_btree_rec *rec) +{ + key->rmap.rm_startblock = rec->rmap.rm_startblock; + key->rmap.rm_owner = rec->rmap.rm_owner; + key->rmap.rm_offset = rec->rmap.rm_offset; +} + +STATIC void +xfs_rmapbt_init_rec_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_rec *rec) +{ + rec->rmap.rm_startblock = cpu_to_be32(cur->bc_rec.r.rm_startblock); + rec->rmap.rm_blockcount = cpu_to_be32(cur->bc_rec.r.rm_blockcount); + rec->rmap.rm_owner = cpu_to_be64(cur->bc_rec.r.rm_owner); + rec->rmap.rm_offset = cpu_to_be64( + xfs_rmap_irec_offset_pack(&cur->bc_rec.r)); +} + +STATIC void +xfs_rmapbt_init_ptr_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); + + ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); + ASSERT(agf->agf_roots[cur->bc_btnum] != 0); + + ptr->s = agf->agf_roots[cur->bc_btnum]; +} + +STATIC __int64_t +xfs_rmapbt_key_diff( + struct xfs_btree_cur *cur, + union xfs_btree_key *key) +{ + struct xfs_rmap_irec *rec = &cur->bc_rec.r; + struct xfs_rmap_key *kp = &key->rmap; + __u64 x, y; + __int64_t d; + + d = (__int64_t)be32_to_cpu(kp->rm_startblock) - rec->rm_startblock; + if (d) + return d; + + x = be64_to_cpu(kp->rm_owner); + y = rec->rm_owner; + if (x > y) + return 1; + else if (y > x) + return -1; + + x = XFS_RMAP_OFF(be64_to_cpu(kp->rm_offset)); + y = rec->rm_offset; + if (x > y) + return 1; + else if (y > x) + return -1; + return 0; +} + static bool xfs_rmapbt_verify( struct xfs_buf *bp) @@ -115,12 +307,63 @@ const struct xfs_buf_ops xfs_rmapbt_buf_ops = { .verify_write = xfs_rmapbt_write_verify, }; +#if defined(DEBUG) || defined(XFS_WARN) +STATIC int +xfs_rmapbt_keys_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + if (be32_to_cpu(k1->rmap.rm_startblock) < + be32_to_cpu(k2->rmap.rm_startblock)) + return 1; + if (be64_to_cpu(k1->rmap.rm_owner) < + be64_to_cpu(k2->rmap.rm_owner)) + return 1; + if (XFS_RMAP_OFF(be64_to_cpu(k1->rmap.rm_offset)) <= + XFS_RMAP_OFF(be64_to_cpu(k2->rmap.rm_offset))) + return 1; + return 0; +} + +STATIC int +xfs_rmapbt_recs_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_rec *r1, + union xfs_btree_rec *r2) +{ + if (be32_to_cpu(r1->rmap.rm_startblock) < + be32_to_cpu(r2->rmap.rm_startblock)) + return 1; + if (XFS_RMAP_OFF(be64_to_cpu(r1->rmap.rm_offset)) < + XFS_RMAP_OFF(be64_to_cpu(r2->rmap.rm_offset))) + return 1; + if (be64_to_cpu(r1->rmap.rm_owner) <= + be64_to_cpu(r2->rmap.rm_owner)) + return 1; + return 0; +} +#endif /* DEBUG */ + static const struct xfs_btree_ops xfs_rmapbt_ops = { .rec_len = sizeof(struct xfs_rmap_rec), .key_len = sizeof(struct xfs_rmap_key), .dup_cursor = xfs_rmapbt_dup_cursor, + .set_root = xfs_rmapbt_set_root, + .alloc_block = xfs_rmapbt_alloc_block, + .free_block = xfs_rmapbt_free_block, + .get_minrecs = xfs_rmapbt_get_minrecs, + .get_maxrecs = xfs_rmapbt_get_maxrecs, + .init_key_from_rec = xfs_rmapbt_init_key_from_rec, + .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur, + .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur, + .key_diff = xfs_rmapbt_key_diff, .buf_ops = &xfs_rmapbt_buf_ops, +#if defined(DEBUG) || defined(XFS_WARN) + .keys_inorder = xfs_rmapbt_keys_inorder, + .recs_inorder = xfs_rmapbt_recs_inorder, +#endif }; /* diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 462767f..17fa383 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -52,6 +52,15 @@ struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, int xfs_rmapbt_maxrecs(struct xfs_mount *mp, int blocklen, int leaf); extern void xfs_rmapbt_compute_maxlevels(struct xfs_mount *mp); +int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, uint64_t owner, uint64_t offset, + unsigned int flags, int *stat); +int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, uint64_t owner, uint64_t offset, + unsigned int flags, int *stat); +int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, + int *stat); + int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); From darrick.wong@oracle.com Thu Jun 16 20:34:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 593967E54 for ; Thu, 16 Jun 2016 20:34:49 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 16DD0304039 for ; Thu, 16 Jun 2016 18:34:49 -0700 (PDT) X-ASG-Debug-ID: 1466127286-04bdf01e1796100001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id kqBixMsXHWfJ0GsW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:47 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1YgjC003750 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:34:43 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1YfaA029114 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:42 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Yd2a010679; Fri, 17 Jun 2016 01:34:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:38 -0700 Subject: [PATCH 037/145] xfs: support overlapping intervals in the rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 037/145] xfs: support overlapping intervals in the rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:34:37 -0700 Message-ID: <146612727752.16048.15487987947678173213.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127287 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4652 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Now that the generic btree code supports overlapping intervals, plug in the rmap btree to this functionality. We will need it to find potential left neighbors in xfs_rmap_{alloc,free} later in the patch set. v2: Fix bit manipulation bug when generating high key offset. v3: Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- libxfs/xfs_rmap_btree.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++- libxfs/xfs_rmap_btree.h | 10 ++++++-- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/libxfs/xfs_rmap_btree.c b/libxfs/xfs_rmap_btree.c index c8fd99e..b5c3c21 100644 --- a/libxfs/xfs_rmap_btree.c +++ b/libxfs/xfs_rmap_btree.c @@ -179,6 +179,28 @@ xfs_rmapbt_init_key_from_rec( } STATIC void +xfs_rmapbt_init_high_key_from_rec( + union xfs_btree_key *key, + union xfs_btree_rec *rec) +{ + __uint64_t off; + int adj; + + adj = be32_to_cpu(rec->rmap.rm_blockcount) - 1; + + key->rmap.rm_startblock = rec->rmap.rm_startblock; + be32_add_cpu(&key->rmap.rm_startblock, adj); + key->rmap.rm_owner = rec->rmap.rm_owner; + key->rmap.rm_offset = rec->rmap.rm_offset; + if (XFS_RMAP_NON_INODE_OWNER(be64_to_cpu(rec->rmap.rm_owner)) || + XFS_RMAP_IS_BMBT_BLOCK(be64_to_cpu(rec->rmap.rm_offset))) + return; + off = be64_to_cpu(key->rmap.rm_offset); + off = (XFS_RMAP_OFF(off) + adj) | (off & ~XFS_RMAP_OFF_MASK); + key->rmap.rm_offset = cpu_to_be64(off); +} + +STATIC void xfs_rmapbt_init_rec_from_cur( struct xfs_btree_cur *cur, union xfs_btree_rec *rec) @@ -233,6 +255,38 @@ xfs_rmapbt_key_diff( return 0; } +STATIC __int64_t +xfs_rmapbt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + struct xfs_rmap_key *kp1 = &k1->rmap; + struct xfs_rmap_key *kp2 = &k2->rmap; + __int64_t d; + __u64 x, y; + + d = (__int64_t)be32_to_cpu(kp2->rm_startblock) - + be32_to_cpu(kp1->rm_startblock); + if (d) + return d; + + x = be64_to_cpu(kp2->rm_owner); + y = be64_to_cpu(kp1->rm_owner); + if (x > y) + return 1; + else if (y > x) + return -1; + + x = XFS_RMAP_OFF(be64_to_cpu(kp2->rm_offset)); + y = XFS_RMAP_OFF(be64_to_cpu(kp1->rm_offset)); + if (x > y) + return 1; + else if (y > x) + return -1; + return 0; +} + static bool xfs_rmapbt_verify( struct xfs_buf *bp) @@ -348,6 +402,7 @@ xfs_rmapbt_recs_inorder( static const struct xfs_btree_ops xfs_rmapbt_ops = { .rec_len = sizeof(struct xfs_rmap_rec), .key_len = sizeof(struct xfs_rmap_key), + .flags = XFS_BTREE_OPS_OVERLAPPING, .dup_cursor = xfs_rmapbt_dup_cursor, .set_root = xfs_rmapbt_set_root, @@ -356,10 +411,12 @@ static const struct xfs_btree_ops xfs_rmapbt_ops = { .get_minrecs = xfs_rmapbt_get_minrecs, .get_maxrecs = xfs_rmapbt_get_maxrecs, .init_key_from_rec = xfs_rmapbt_init_key_from_rec, + .init_high_key_from_rec = xfs_rmapbt_init_high_key_from_rec, .init_rec_from_cur = xfs_rmapbt_init_rec_from_cur, .init_ptr_from_cur = xfs_rmapbt_init_ptr_from_cur, .key_diff = xfs_rmapbt_key_diff, .buf_ops = &xfs_rmapbt_buf_ops, + .diff_two_keys = xfs_rmapbt_diff_two_keys, #if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_rmapbt_keys_inorder, .recs_inorder = xfs_rmapbt_recs_inorder, @@ -408,7 +465,7 @@ xfs_rmapbt_maxrecs( if (leaf) return blocklen / sizeof(struct xfs_rmap_rec); return blocklen / - (sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); + (2 * sizeof(struct xfs_rmap_key) + sizeof(xfs_rmap_ptr_t)); } /* Compute the maximum height of an rmap btree. */ diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 17fa383..796071c 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -38,12 +38,18 @@ struct xfs_mount; #define XFS_RMAP_KEY_ADDR(block, index) \ ((struct xfs_rmap_key *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ - ((index) - 1) * sizeof(struct xfs_rmap_key))) + ((index) - 1) * 2 * sizeof(struct xfs_rmap_key))) + +#define XFS_RMAP_HIGH_KEY_ADDR(block, index) \ + ((struct xfs_rmap_key *) \ + ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ + sizeof(struct xfs_rmap_key) + \ + ((index) - 1) * 2 * sizeof(struct xfs_rmap_key))) #define XFS_RMAP_PTR_ADDR(block, index, maxrecs) \ ((xfs_rmap_ptr_t *) \ ((char *)(block) + XFS_RMAP_BLOCK_LEN + \ - (maxrecs) * sizeof(struct xfs_rmap_key) + \ + (maxrecs) * 2 * sizeof(struct xfs_rmap_key) + \ ((index) - 1) * sizeof(xfs_rmap_ptr_t))) struct xfs_btree_cur *xfs_rmapbt_init_cursor(struct xfs_mount *mp, From darrick.wong@oracle.com Thu Jun 16 20:34:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 289E68157 for ; Thu, 16 Jun 2016 20:34:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 95B3DAC001 for ; Thu, 16 Jun 2016 18:34:52 -0700 (PDT) X-ASG-Debug-ID: 1466127290-04cbb01fee6a0c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id L6TVVSnXKLhZ6kHB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:50 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Yjtt003776 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:46 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Yjdr030938 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:45 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1YjBu032586; Fri, 17 Jun 2016 01:34:45 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:45 -0700 Subject: [PATCH 038/145] xfs: teach rmapbt to support interval queries From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 038/145] xfs: teach rmapbt to support interval queries To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:34:43 -0700 Message-ID: <146612728370.16048.5124604381084390901.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127290 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2465 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Now that the generic btree code supports querying all records within a range of keys, use that functionality to allow us to ask for all the extents mapped to a range of physical blocks. v2: Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- libxfs/xfs_rmap.c | 43 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.h | 9 +++++++++ 2 files changed, 52 insertions(+) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 5034fd3..390ddde 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -182,3 +182,46 @@ out_error: trace_xfs_rmap_alloc_extent_error(mp, agno, bno, len, false, oinfo); return error; } + +struct xfs_rmapbt_query_range_info { + xfs_rmapbt_query_range_fn fn; + void *priv; +}; + +/* Format btree record and pass to our callback. */ +STATIC int +xfs_rmapbt_query_range_helper( + struct xfs_btree_cur *cur, + union xfs_btree_rec *rec, + void *priv) +{ + struct xfs_rmapbt_query_range_info *query = priv; + struct xfs_rmap_irec irec; + int error; + + error = xfs_rmapbt_btrec_to_irec(rec, &irec); + if (error) + return error; + return query->fn(cur, &irec, query->priv); +} + +/* Find all rmaps between two keys. */ +int +xfs_rmapbt_query_range( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *low_rec, + struct xfs_rmap_irec *high_rec, + xfs_rmapbt_query_range_fn fn, + void *priv) +{ + union xfs_btree_irec low_brec; + union xfs_btree_irec high_brec; + struct xfs_rmapbt_query_range_info query; + + low_brec.r = *low_rec; + high_brec.r = *high_rec; + query.priv = priv; + query.fn = fn; + return xfs_btree_query_range(cur, &low_brec, &high_brec, + xfs_rmapbt_query_range_helper, &query); +} diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 796071c..e926c6e 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -74,4 +74,13 @@ int xfs_rmap_free(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); +typedef int (*xfs_rmapbt_query_range_fn)( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv); + +int xfs_rmapbt_query_range(struct xfs_btree_cur *cur, + struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec, + xfs_rmapbt_query_range_fn fn, void *priv); + #endif /* __XFS_RMAP_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:34:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D49628161 for ; Thu, 16 Jun 2016 20:34:59 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 923648F804C for ; Thu, 16 Jun 2016 18:34:59 -0700 (PDT) X-ASG-Debug-ID: 1466127296-04bdf01e1396120001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id CCNwHTNcVs4jFb2Z (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:34:57 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Yq2b003878 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:52 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YqBq003522 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:52 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1YpWA032601; Fri, 17 Jun 2016 01:34:51 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:51 -0700 Subject: [PATCH 039/145] xfs: add an extent to the rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 039/145] xfs: add an extent to the rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:34:49 -0700 Message-ID: <146612728981.16048.1586030726685850460.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127297 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10055 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Now all the btree, free space and transaction infrastructure is in place, we can finally add the code to insert reverse mappings to the rmap btree. Freeing will be done in a separate patch, so just the addition operation can be focussed on here. v2: Update alloc function to handle non-shared file data. Isolate the part that makes changes from the part that initializes the rmap cursor; this will be useful for deferred updates. [darrick: handle owner offsets when adding rmaps] [dchinner: remove remaining debug printk statements] [darrick: move unwritten bit to rm_offset] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- include/xfs_trace.h | 9 ++ libxfs/xfs_rmap.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++- libxfs/xfs_rmap_btree.h | 1 3 files changed, 230 insertions(+), 5 deletions(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index af3f68b..45b5284 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -194,6 +194,15 @@ #define trace_xfs_rmap_free_extent_done(...) ((void) 0) #define trace_xfs_rmapbt_free_block(...) ((void) 0) #define trace_xfs_rmapbt_alloc_block(...) ((void) 0) +#define trace_xfs_rmapbt_update(...) ((void) 0) +#define trace_xfs_rmapbt_update_error(...) ((void) 0) +#define trace_xfs_rmapbt_insert(...) ((void) 0) +#define trace_xfs_rmapbt_insert_error(...) ((void) 0) +#define trace_xfs_rmapbt_delete(...) ((void) 0) +#define trace_xfs_rmapbt_delete_error(...) ((void) 0) + +#define trace_xfs_rmap_lookup_le_range_result(...) ((void) 0) +#define trace_xfs_rmap_map_gtrec(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 390ddde..fc3522b 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -157,6 +157,218 @@ out_error: return error; } +/* + * A mergeable rmap should have the same owner, cannot be unwritten, and + * must be a bmbt rmap if we're asking about a bmbt rmap. + */ +static bool +xfs_rmap_is_mergeable( + struct xfs_rmap_irec *irec, + uint64_t owner, + uint64_t offset, + xfs_extlen_t len, + unsigned int flags) +{ + if (irec->rm_owner == XFS_RMAP_OWN_NULL) + return false; + if (irec->rm_owner != owner) + return false; + if ((flags & XFS_RMAP_UNWRITTEN) ^ + (irec->rm_flags & XFS_RMAP_UNWRITTEN)) + return false; + if ((flags & XFS_RMAP_ATTR_FORK) ^ + (irec->rm_flags & XFS_RMAP_ATTR_FORK)) + return false; + if ((flags & XFS_RMAP_BMBT_BLOCK) ^ + (irec->rm_flags & XFS_RMAP_BMBT_BLOCK)) + return false; + return true; +} + +/* + * When we allocate a new block, the first thing we do is add a reference to + * the extent in the rmap btree. This takes the form of a [agbno, length, + * owner, offset] record. Flags are encoded in the high bits of the offset + * field. + */ +STATIC int +__xfs_rmap_alloc( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + struct xfs_rmap_irec gtrec; + int have_gt; + int have_lt; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags = 0; + bool ignore_off; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & XFS_RMAP_BMBT_BLOCK); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_alloc_extent(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * For the initial lookup, look for and exact match or the left-adjacent + * record for our insertion point. This will also give us the record for + * start block contiguity tests. + */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, + &have_lt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); + + error = xfs_rmap_get_rec(cur, <rec, &have_lt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_lt == 1, out_error); + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + + if (!xfs_rmap_is_mergeable(<rec, owner, offset, len, flags)) + have_lt = 0; + + XFS_WANT_CORRUPTED_GOTO(mp, + have_lt == 0 || + ltrec.rm_startblock + ltrec.rm_blockcount <= bno, out_error); + + /* + * Increment the cursor to see if we have a right-adjacent record to our + * insertion point. This will give us the record for end block + * contiguity tests. + */ + error = xfs_btree_increment(cur, 0, &have_gt); + if (error) + goto out_error; + if (have_gt) { + error = xfs_rmap_get_rec(cur, >rec, &have_gt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); + XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= gtrec.rm_startblock, + out_error); + trace_xfs_rmap_map_gtrec(cur->bc_mp, + cur->bc_private.a.agno, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (!xfs_rmap_is_mergeable(>rec, owner, offset, len, flags)) + have_gt = 0; + } + + /* + * Note: cursor currently points one record to the right of ltrec, even + * if there is no record in the tree to the right. + */ + if (have_lt && + ltrec.rm_startblock + ltrec.rm_blockcount == bno && + (ignore_off || ltrec.rm_offset + ltrec.rm_blockcount == offset)) { + /* + * left edge contiguous, merge into left record. + * + * ltbno ltlen + * orig: |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + ltrec.rm_blockcount += len; + if (have_gt && + bno + len == gtrec.rm_startblock && + (ignore_off || offset + len == gtrec.rm_offset) && + (unsigned long)ltrec.rm_blockcount + len + + gtrec.rm_blockcount <= XFS_RMAP_LEN_MAX) { + /* + * right edge also contiguous, delete right record + * and merge into left record. + * + * ltbno ltlen gtbno gtlen + * orig: |ooooooooo| |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| + */ + ltrec.rm_blockcount += gtrec.rm_blockcount; + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + gtrec.rm_startblock, + gtrec.rm_blockcount, + gtrec.rm_owner, + gtrec.rm_offset, + gtrec.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } + + /* point the cursor back to the left record and update */ + error = xfs_btree_decrement(cur, 0, &have_gt); + if (error) + goto out_error; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else if (have_gt && + bno + len == gtrec.rm_startblock && + (ignore_off || offset + len == gtrec.rm_offset)) { + /* + * right edge contiguous, merge into right record. + * + * gtbno gtlen + * Orig: |ooooooooo| + * adding: |aaaaaaaaa| + * Result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + gtrec.rm_startblock = bno; + gtrec.rm_blockcount += len; + if (!ignore_off) + gtrec.rm_offset = offset; + error = xfs_rmap_update(cur, >rec); + if (error) + goto out_error; + } else { + /* + * no contiguous edge with identical owner, insert + * new record at current cursor position. + */ + cur->bc_rec.r.rm_startblock = bno; + cur->bc_rec.r.rm_blockcount = len; + cur->bc_rec.r.rm_owner = owner; + cur->bc_rec.r.rm_offset = offset; + cur->bc_rec.r.rm_flags = flags; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, len, + owner, offset, flags); + error = xfs_btree_insert(cur, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } + + trace_xfs_rmap_alloc_extent_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_alloc_extent_error(mp, cur->bc_private.a.agno, + bno, len, unwritten, oinfo); + return error; +} + +/* + * Add a reference to an extent in the rmap btree. + */ int xfs_rmap_alloc( struct xfs_trans *tp, @@ -167,19 +379,22 @@ xfs_rmap_alloc( struct xfs_owner_info *oinfo) { struct xfs_mount *mp = tp->t_mountp; - int error = 0; + struct xfs_btree_cur *cur; + int error; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; - trace_xfs_rmap_alloc_extent(mp, agno, bno, len, false, oinfo); - if (1) + cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); + error = __xfs_rmap_alloc(cur, bno, len, false, oinfo); + if (error) goto out_error; - trace_xfs_rmap_alloc_extent_done(mp, agno, bno, len, false, oinfo); + + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; out_error: - trace_xfs_rmap_alloc_extent_error(mp, agno, bno, len, false, oinfo); + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index e926c6e..9d92da5 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -67,6 +67,7 @@ int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat); +/* functions for updating the rmapbt for bmbt blocks and AG btree blocks */ int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo); From darrick.wong@oracle.com Thu Jun 16 20:35:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9322D8168 for ; Thu, 16 Jun 2016 20:35:06 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 16BB6AC001 for ; Thu, 16 Jun 2016 18:35:06 -0700 (PDT) X-ASG-Debug-ID: 1466127303-04cbb01fee6a0f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id vc5lomk4YT0H8PlQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:03 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Ywcl016838 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:34:58 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1YwsG029664 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:34:58 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1YvSf027896; Fri, 17 Jun 2016 01:34:58 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:34:57 -0700 Subject: [PATCH 040/145] xfs: remove an extent from the rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 040/145] xfs: remove an extent from the rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:34:56 -0700 Message-ID: <146612729610.16048.6640772609600442182.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127303 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8987 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Now that we have records in the rmap btree, we need to remove them when extents are freed. This needs to find the relevant record in the btree and remove/trim/split it accordingly. v2: Update the free function to deal with non-shared file data, and isolate the part that does the rmap update from the part that deals with cursors. This will be useful for deferred ops. [darrick.wong@oracle.com: make rmap routines handle the enlarged keyspace] [dchinner: remove remaining unused debug printks] [darrick: fix a bug when growfs in an AG with an rmap ending at EOFS] Signed-off-by: Dave Chinner Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- libxfs/xfs_rmap.c | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 215 insertions(+), 5 deletions(-) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index fc3522b..cc82824 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -131,6 +131,212 @@ xfs_rmap_get_rec( return xfs_rmapbt_btrec_to_irec(rec, irec); } +/* + * Find the extent in the rmap btree and remove it. + * + * The record we find should always be an exact match for the extent that we're + * looking for, since we insert them into the btree without modification. + * + * Special Case #1: when growing the filesystem, we "free" an extent when + * growing the last AG. This extent is new space and so it is not tracked as + * used space in the btree. The growfs code will pass in an owner of + * XFS_RMAP_OWN_NULL to indicate that it expected that there is no owner of this + * extent. We verify that - the extent lookup result in a record that does not + * overlap. + * + * Special Case #2: EFIs do not record the owner of the extent, so when + * recovering EFIs from the log we pass in XFS_RMAP_OWN_UNKNOWN to tell the rmap + * btree to ignore the owner (i.e. wildcard match) so we don't trigger + * corruption checks during log recovery. + */ +STATIC int +__xfs_rmap_free( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + uint64_t ltoff; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags; + bool ignore_off; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ignore_off = XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & XFS_RMAP_BMBT_BLOCK); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_free_extent(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * We should always have a left record because there's a static record + * for the AG headers at rm_startblock == 0 created by mkfs/growfs that + * will not ever be removed from the tree. + */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + error = xfs_rmap_get_rec(cur, <rec, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + ltoff = ltrec.rm_offset; + + /* + * For growfs, the incoming extent must be beyond the left record we + * just found as it is new space and won't be used by anyone. This is + * just a corruption check as we don't actually do anything with this + * extent. Note that we need to use >= instead of > because it might + * be the case that the "left" extent goes all the way to EOFS. + */ + if (owner == XFS_RMAP_OWN_NULL) { + XFS_WANT_CORRUPTED_GOTO(mp, bno >= ltrec.rm_startblock + + ltrec.rm_blockcount, out_error); + goto out_done; + } + + /* Make sure the unwritten flag matches. */ + XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == + (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); + + /* Make sure the extent we found covers the entire freeing range. */ + XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && + ltrec.rm_startblock + ltrec.rm_blockcount >= + bno + len, out_error); + + /* Make sure the owner matches what we expect to find in the tree. */ + XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner || + XFS_RMAP_NON_INODE_OWNER(owner), out_error); + + /* Check the offset, if necessary. */ + if (!XFS_RMAP_NON_INODE_OWNER(owner)) { + if (flags & XFS_RMAP_BMBT_BLOCK) { + XFS_WANT_CORRUPTED_GOTO(mp, + ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK, + out_error); + } else { + XFS_WANT_CORRUPTED_GOTO(mp, + ltrec.rm_offset <= offset, out_error); + XFS_WANT_CORRUPTED_GOTO(mp, + ltoff + ltrec.rm_blockcount >= offset + len, + out_error); + } + } + + if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { + /* exact match, simply remove the record from rmap tree */ + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + ltrec.rm_startblock, ltrec.rm_blockcount, + ltrec.rm_owner, ltrec.rm_offset, + ltrec.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } else if (ltrec.rm_startblock == bno) { + /* + * overlap left hand side of extent: move the start, trim the + * length and update the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + ltrec.rm_startblock += len; + ltrec.rm_blockcount -= len; + if (!ignore_off) + ltrec.rm_offset += len; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { + /* + * overlap right hand side of extent: trim the length and update + * the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + ltrec.rm_blockcount -= len; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else { + + /* + * overlap middle of extent: trim the length of the existing + * record to the length of the new left-extent size, increment + * the insertion position so we can insert a new record + * containing the remaining right-extent space. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrr| |rrrr| + * bno len + */ + xfs_extlen_t orig_len = ltrec.rm_blockcount; + + ltrec.rm_blockcount = bno - ltrec.rm_startblock; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto out_error; + + cur->bc_rec.r.rm_startblock = bno + len; + cur->bc_rec.r.rm_blockcount = orig_len - len - + ltrec.rm_blockcount; + cur->bc_rec.r.rm_owner = ltrec.rm_owner; + if (ignore_off) + cur->bc_rec.r.rm_offset = 0; + else + cur->bc_rec.r.rm_offset = offset + len; + cur->bc_rec.r.rm_flags = flags; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, + cur->bc_rec.r.rm_startblock, + cur->bc_rec.r.rm_blockcount, + cur->bc_rec.r.rm_owner, + cur->bc_rec.r.rm_offset, + cur->bc_rec.r.rm_flags); + error = xfs_btree_insert(cur, &i); + if (error) + goto out_error; + } + +out_done: + trace_xfs_rmap_free_extent_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_free_extent_error(mp, cur->bc_private.a.agno, + bno, len, unwritten, oinfo); + return error; +} + +/* + * Remove a reference to an extent in the rmap btree. + */ int xfs_rmap_free( struct xfs_trans *tp, @@ -141,19 +347,23 @@ xfs_rmap_free( struct xfs_owner_info *oinfo) { struct xfs_mount *mp = tp->t_mountp; - int error = 0; + struct xfs_btree_cur *cur; + int error; if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; - trace_xfs_rmap_free_extent(mp, agno, bno, len, false, oinfo); - if (1) + cur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); + + error = __xfs_rmap_free(cur, bno, len, false, oinfo); + if (error) goto out_error; - trace_xfs_rmap_free_extent_done(mp, agno, bno, len, false, oinfo); + + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); return 0; out_error: - trace_xfs_rmap_free_extent_error(mp, agno, bno, len, false, oinfo); + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } From darrick.wong@oracle.com Thu Jun 16 20:35:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5E2838128 for ; Thu, 16 Jun 2016 20:35:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0F98930404E for ; Thu, 16 Jun 2016 18:35:13 -0700 (PDT) X-ASG-Debug-ID: 1466127309-04bdf01e1096140001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 008VChNq4SBPYjq8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Z5v1017130 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:35:05 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1Z5F3029830 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:35:05 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1Z4EC000311; Fri, 17 Jun 2016 01:35:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:04 -0700 Subject: [PATCH 041/145] xfs: convert unwritten status of reverse mappings From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 041/145] xfs: convert unwritten status of reverse mappings To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:35:02 -0700 Message-ID: <146612730237.16048.4507175801680173913.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127309 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14811 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a function to convert an unwritten extent to a real one and vice versa. v2: Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 6 + libxfs/xfs_rmap.c | 442 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 448 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 45b5284..55df410 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -203,6 +203,12 @@ #define trace_xfs_rmap_lookup_le_range_result(...) ((void) 0) #define trace_xfs_rmap_map_gtrec(...) ((void) 0) +#define trace_xfs_rmap_convert(...) ((void) 0) +#define trace_xfs_rmap_convert_gtrec(...) ((void) 0) +#define trace_xfs_rmap_convert_state(...) ((void) 0) +#define trace_xfs_rmap_convert_done(...) ((void) 0) +#define trace_xfs_rmap_convert_error(...) ((void) 0) +#define trace_xfs_rmap_find_left_neighbor_result(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index cc82824..1e25285 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -608,6 +608,448 @@ out_error: return error; } +#define RMAP_LEFT_CONTIG (1 << 0) +#define RMAP_RIGHT_CONTIG (1 << 1) +#define RMAP_LEFT_FILLING (1 << 2) +#define RMAP_RIGHT_FILLING (1 << 3) +#define RMAP_LEFT_VALID (1 << 6) +#define RMAP_RIGHT_VALID (1 << 7) + +#define LEFT r[0] +#define RIGHT r[1] +#define PREV r[2] +#define NEW r[3] + +/* + * Convert an unwritten extent to a real extent or vice versa. + * Does not handle overlapping extents. + */ +STATIC int +__xfs_rmap_convert( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec r[4]; /* neighbor extent entries */ + /* left is 0, right is 1, prev is 2 */ + /* new is 3 */ + uint64_t owner; + uint64_t offset; + uint64_t new_endoff; + unsigned int oldext; + unsigned int newext; + unsigned int flags = 0; + int i; + int state = 0; + int error; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); + oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; + new_endoff = offset + len; + trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * For the initial lookup, look for and exact match or the left-adjacent + * record for our insertion point. This will also give us the record for + * start block contiguity tests. + */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + + error = xfs_rmap_get_rec(cur, &PREV, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, PREV.rm_startblock, + PREV.rm_blockcount, PREV.rm_owner, + PREV.rm_offset, PREV.rm_flags); + + ASSERT(PREV.rm_offset <= offset); + ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); + ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); + newext = ~oldext & XFS_RMAP_UNWRITTEN; + + /* + * Set flags determining what part of the previous oldext allocation + * extent is being replaced by a newext allocation. + */ + if (PREV.rm_offset == offset) + state |= RMAP_LEFT_FILLING; + if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) + state |= RMAP_RIGHT_FILLING; + + /* + * Decrement the cursor to see if we have a left-adjacent record to our + * insertion point. This will give us the record for end block + * contiguity tests. + */ + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + if (i) { + state |= RMAP_LEFT_VALID; + error = xfs_rmap_get_rec(cur, &LEFT, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + XFS_WANT_CORRUPTED_GOTO(mp, + LEFT.rm_startblock + LEFT.rm_blockcount <= bno, + done); + trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, + cur->bc_private.a.agno, LEFT.rm_startblock, + LEFT.rm_blockcount, LEFT.rm_owner, + LEFT.rm_offset, LEFT.rm_flags); + if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && + LEFT.rm_offset + LEFT.rm_blockcount == offset && + xfs_rmap_is_mergeable(&LEFT, owner, offset, len, newext)) + state |= RMAP_LEFT_CONTIG; + } + + /* + * Increment the cursor to see if we have a right-adjacent record to our + * insertion point. This will give us the record for end block + * contiguity tests. + */ + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + if (i) { + state |= RMAP_RIGHT_VALID; + error = xfs_rmap_get_rec(cur, &RIGHT, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, + done); + trace_xfs_rmap_convert_gtrec(cur->bc_mp, + cur->bc_private.a.agno, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (bno + len == RIGHT.rm_startblock && + offset + len == RIGHT.rm_offset && + xfs_rmap_is_mergeable(&RIGHT, owner, offset, len, newext)) + state |= RMAP_RIGHT_CONTIG; + } + + /* check that left + prev + right is not too long */ + if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == + (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && + (unsigned long)LEFT.rm_blockcount + len + + RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) + state &= ~RMAP_RIGHT_CONTIG; + + trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, + _RET_IP_); + + /* reset the cursor back to PREV */ + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + + /* + * Switch out based on the FILLING and CONTIG state bits. + */ + switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left and right neighbors are both contiguous with new. + */ + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + RIGHT.rm_startblock, RIGHT.rm_blockcount, + RIGHT.rm_owner, RIGHT.rm_offset, + RIGHT.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + PREV.rm_startblock, PREV.rm_blockcount, + PREV.rm_owner, PREV.rm_offset, + PREV.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW = LEFT; + NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left neighbor is contiguous, the right is not. + */ + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + PREV.rm_startblock, PREV.rm_blockcount, + PREV.rm_owner, PREV.rm_offset, + PREV.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW = LEFT; + NEW.rm_blockcount += PREV.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The right neighbor is contiguous, the left is not. + */ + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, + RIGHT.rm_startblock, RIGHT.rm_blockcount, + RIGHT.rm_owner, RIGHT.rm_offset, + RIGHT.rm_flags); + error = xfs_btree_delete(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_startblock = bno; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_blockcount = len + RIGHT.rm_blockcount; + NEW.rm_flags = newext; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: + /* + * Setting all of a previous oldext extent to newext. + * Neither the left nor right neighbors are contiguous with + * the new one. + */ + NEW = PREV; + NEW.rm_flags = newext; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is contiguous. + */ + NEW = PREV; + NEW.rm_offset += len; + NEW.rm_startblock += len; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_btree_decrement(cur, 0, &i); + if (error) + goto done; + NEW = LEFT; + NEW.rm_blockcount += len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is not contiguous. + */ + NEW = PREV; + NEW.rm_startblock += len; + NEW.rm_offset += len; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + NEW.rm_startblock = bno; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_blockcount = len; + NEW.rm_flags = newext; + cur->bc_rec.r = NEW; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, + len, owner, offset, newext); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + break; + + case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is contiguous with the new allocation. + */ + NEW = PREV; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_btree_increment(cur, 0, &i); + if (error) + goto done; + NEW = RIGHT; + NEW.rm_offset = offset; + NEW.rm_startblock = bno; + NEW.rm_blockcount += len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_RIGHT_FILLING: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is not contiguous. + */ + NEW = PREV; + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, + oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + NEW.rm_startblock = bno; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_blockcount = len; + NEW.rm_flags = newext; + cur->bc_rec.r = NEW; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, + len, owner, offset, newext); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + break; + + case 0: + /* + * Setting the middle part of a previous oldext extent to + * newext. Contiguity is impossible here. + * One extent becomes three extents. + */ + /* new right extent - oldext */ + NEW.rm_startblock = bno + len; + NEW.rm_owner = owner; + NEW.rm_offset = new_endoff; + NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - + new_endoff; + NEW.rm_flags = PREV.rm_flags; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + /* new left extent - oldext */ + NEW = PREV; + NEW.rm_blockcount = offset - PREV.rm_offset; + cur->bc_rec.r = NEW; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, + NEW.rm_startblock, NEW.rm_blockcount, + NEW.rm_owner, NEW.rm_offset, + NEW.rm_flags); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + /* + * Reset the cursor to the position of the new extent + * we are about to insert as we can't trust it after + * the previous insert. + */ + error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, + oldext, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); + /* new middle extent - newext */ + cur->bc_rec.b.br_state = newext; + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, len, + owner, offset, newext); + error = xfs_btree_insert(cur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_CONTIG: + case RMAP_RIGHT_CONTIG: + /* + * These cases are all impossible. + */ + ASSERT(0); + } + + trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +done: + if (error) + trace_xfs_rmap_convert_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +#undef NEW +#undef LEFT +#undef RIGHT +#undef PREV + struct xfs_rmapbt_query_range_info { xfs_rmapbt_query_range_fn fn; void *priv; From darrick.wong@oracle.com Thu Jun 16 20:35:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E6D698179 for ; Thu, 16 Jun 2016 20:35:18 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6B7D1AC002 for ; Thu, 16 Jun 2016 18:35:18 -0700 (PDT) X-ASG-Debug-ID: 1466127316-04cb6c542457f00001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id ch2ngX4JFGvdHVqk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:16 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ZBH5017237 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:12 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZB1Q031724 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:11 GMT Received: from abhmp0006.oracle.com (abhmp0006.oracle.com [141.146.116.12]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZBgd028035; Fri, 17 Jun 2016 01:35:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:11 -0700 Subject: [PATCH 042/145] xfs: add rmap btree insert and delete helpers From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 042/145] xfs: add rmap btree insert and delete helpers To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:35:09 -0700 Message-ID: <146612730957.16048.16764461721448398257.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127316 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3702 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add a couple of helper functions to encapsulate rmap btree insert and delete operations. Add tracepoints to the update function. Signed-off-by: Darrick J. Wong Reviewed-by: Dave Chinner Signed-off-by: Dave Chinner --- libxfs/xfs_rmap.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++- libxfs/xfs_rmap_btree.h | 3 ++ 2 files changed, 80 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 1e25285..3c13fac 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -90,13 +90,89 @@ xfs_rmap_update( struct xfs_rmap_irec *irec) { union xfs_btree_rec rec; + int error; + + trace_xfs_rmapbt_update(cur->bc_mp, cur->bc_private.a.agno, + irec->rm_startblock, irec->rm_blockcount, + irec->rm_owner, irec->rm_offset, irec->rm_flags); rec.rmap.rm_startblock = cpu_to_be32(irec->rm_startblock); rec.rmap.rm_blockcount = cpu_to_be32(irec->rm_blockcount); rec.rmap.rm_owner = cpu_to_be64(irec->rm_owner); rec.rmap.rm_offset = cpu_to_be64( xfs_rmap_irec_offset_pack(irec)); - return xfs_btree_update(cur, &rec); + error = xfs_btree_update(cur, &rec); + if (error) + trace_xfs_rmapbt_update_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +int +xfs_rmapbt_insert( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags) +{ + int i; + int error; + + trace_xfs_rmapbt_insert(rcur->bc_mp, rcur->bc_private.a.agno, agbno, + len, owner, offset, flags); + + error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 0, done); + + rcur->bc_rec.r.rm_startblock = agbno; + rcur->bc_rec.r.rm_blockcount = len; + rcur->bc_rec.r.rm_owner = owner; + rcur->bc_rec.r.rm_offset = offset; + rcur->bc_rec.r.rm_flags = flags; + error = xfs_btree_insert(rcur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); +done: + if (error) + trace_xfs_rmapbt_insert_error(rcur->bc_mp, + rcur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +STATIC int +xfs_rmapbt_delete( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t len, + uint64_t owner, + uint64_t offset, + unsigned int flags) +{ + int i; + int error; + + trace_xfs_rmapbt_delete(rcur->bc_mp, rcur->bc_private.a.agno, agbno, + len, owner, offset, flags); + + error = xfs_rmap_lookup_eq(rcur, agbno, len, owner, offset, flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); + + error = xfs_btree_delete(rcur, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(rcur->bc_mp, i == 1, done); +done: + if (error) + trace_xfs_rmapbt_delete_error(rcur->bc_mp, + rcur->bc_private.a.agno, error, _RET_IP_); + return error; } static int diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 9d92da5..6674340 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -64,6 +64,9 @@ int xfs_rmap_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno, int xfs_rmap_lookup_eq(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, uint64_t owner, uint64_t offset, unsigned int flags, int *stat); +int xfs_rmapbt_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno, + xfs_extlen_t len, uint64_t owner, uint64_t offset, + unsigned int flags); int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat); From darrick.wong@oracle.com Thu Jun 16 20:35:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 00DE48181 for ; Thu, 16 Jun 2016 20:35:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id C7EFE304048 for ; Thu, 16 Jun 2016 18:35:26 -0700 (PDT) X-ASG-Debug-ID: 1466127324-04cb6c542657f20001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 1CnhPHzuN8W5x95G (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ZKHV004476 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:20 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZKkG031903 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:20 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZHdT010791; Fri, 17 Jun 2016 01:35:18 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:17 -0700 Subject: [PATCH 043/145] xfs: create helpers for mapping, unmapping, and converting file fork extents From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 043/145] xfs: create helpers for mapping, unmapping, and converting file fork extents To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:35:15 -0700 Message-ID: <146612731576.16048.5963316524847608377.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127325 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1703 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create two helper functions to assist with mapping, unmapping, and converting flag status of extents in a file's data/attr forks. For non-shared files we can use the _alloc, _free, and _convert functions; when reflink comes these functions will be augmented to deal with shared extents. Signed-off-by: Darrick J. Wong --- libxfs/xfs_rmap.c | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 3c13fac..47f37d7 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -1121,11 +1121,53 @@ done: return error; } +/* + * Convert an unwritten extent to a real extent or vice versa. + */ +STATIC int +xfs_rmap_convert( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + return __xfs_rmap_convert(cur, bno, len, unwritten, oinfo); +} + #undef NEW #undef LEFT #undef RIGHT #undef PREV +/* + * Find an extent in the rmap btree and unmap it. + */ +STATIC int +xfs_rmap_unmap( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + return __xfs_rmap_free(cur, bno, len, unwritten, oinfo); +} + +/* + * Find an extent in the rmap btree and map it. + */ +STATIC int +xfs_rmap_map( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + return __xfs_rmap_alloc(cur, bno, len, unwritten, oinfo); +} + struct xfs_rmapbt_query_range_info { xfs_rmapbt_query_range_fn fn; void *priv; From darrick.wong@oracle.com Thu Jun 16 20:35:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 05E0F8189 for ; Thu, 16 Jun 2016 20:35:32 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 7E54EAC002 for ; Thu, 16 Jun 2016 18:35:31 -0700 (PDT) X-ASG-Debug-ID: 1466127329-04cbb01fee6a130001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Tt2btjvfHf89LtYE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:29 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ZPnc004546 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:25 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZOgO004620 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:25 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1ZO7O000367; Fri, 17 Jun 2016 01:35:24 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:24 -0700 Subject: [PATCH 044/145] xfs: create rmap update intent log items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 044/145] xfs: create rmap update intent log items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:35:22 -0700 Message-ID: <146612732200.16048.15503614314390802694.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127329 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4816 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create rmap update intent/done log items to record redo information in the log. Because we need to roll transactions between updating the bmbt mapping and updating the reverse mapping, we also have to track the status of the metadata updates that will be recorded in the post-roll transactions, just in case we crash before committing the final transaction. This mechanism enables log recovery to finish what was already started. Signed-off-by: Darrick J. Wong --- libxfs/xfs_log_format.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++- libxfs/xfs_rmap_btree.h | 19 +++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h index e5baba3..b9627b7 100644 --- a/libxfs/xfs_log_format.h +++ b/libxfs/xfs_log_format.h @@ -110,7 +110,9 @@ static inline uint xlog_get_cycle(char *ptr) #define XLOG_REG_TYPE_COMMIT 18 #define XLOG_REG_TYPE_TRANSHDR 19 #define XLOG_REG_TYPE_ICREATE 20 -#define XLOG_REG_TYPE_MAX 20 +#define XLOG_REG_TYPE_RUI_FORMAT 21 +#define XLOG_REG_TYPE_RUD_FORMAT 22 +#define XLOG_REG_TYPE_MAX 22 /* * Flags to log operation header @@ -227,6 +229,8 @@ typedef struct xfs_trans_header { #define XFS_LI_DQUOT 0x123d #define XFS_LI_QUOTAOFF 0x123e #define XFS_LI_ICREATE 0x123f +#define XFS_LI_RUI 0x1240 /* rmap update intent */ +#define XFS_LI_RUD 0x1241 #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ @@ -236,7 +240,9 @@ typedef struct xfs_trans_header { { XFS_LI_BUF, "XFS_LI_BUF" }, \ { XFS_LI_DQUOT, "XFS_LI_DQUOT" }, \ { XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \ - { XFS_LI_ICREATE, "XFS_LI_ICREATE" } + { XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \ + { XFS_LI_RUI, "XFS_LI_RUI" }, \ + { XFS_LI_RUD, "XFS_LI_RUD" } /* * Inode Log Item Format definitions. @@ -604,6 +610,63 @@ typedef struct xfs_efd_log_format_64 { } xfs_efd_log_format_64_t; /* + * RUI/RUD (reverse mapping) log format definitions + */ +struct xfs_map_extent { + __uint64_t me_owner; + __uint64_t me_startblock; + __uint64_t me_startoff; + __uint32_t me_len; + __uint32_t me_flags; +}; + +/* rmap me_flags: upper bits are flags, lower byte is type code */ +#define XFS_RMAP_EXTENT_MAP 1 +#define XFS_RMAP_EXTENT_MAP_SHARED 2 +#define XFS_RMAP_EXTENT_UNMAP 3 +#define XFS_RMAP_EXTENT_UNMAP_SHARED 4 +#define XFS_RMAP_EXTENT_CONVERT 5 +#define XFS_RMAP_EXTENT_CONVERT_SHARED 6 +#define XFS_RMAP_EXTENT_ALLOC 7 +#define XFS_RMAP_EXTENT_FREE 8 +#define XFS_RMAP_EXTENT_TYPE_MASK 0xFF + +#define XFS_RMAP_EXTENT_ATTR_FORK (1U << 31) +#define XFS_RMAP_EXTENT_BMBT_BLOCK (1U << 30) +#define XFS_RMAP_EXTENT_UNWRITTEN (1U << 29) + +#define XFS_RMAP_EXTENT_FLAGS (XFS_RMAP_EXTENT_TYPE_MASK | \ + XFS_RMAP_EXTENT_ATTR_FORK | \ + XFS_RMAP_EXTENT_BMBT_BLOCK | \ + XFS_RMAP_EXTENT_UNWRITTEN) + +/* + * This is the structure used to lay out an rui log item in the + * log. The rui_extents field is a variable size array whose + * size is given by rui_nextents. + */ +struct xfs_rui_log_format { + __uint16_t rui_type; /* rui log item type */ + __uint16_t rui_size; /* size of this item */ + __uint32_t rui_nextents; /* # extents to free */ + __uint64_t rui_id; /* rui identifier */ + struct xfs_map_extent rui_extents[1]; /* array of extents to rmap */ +}; + +/* + * This is the structure used to lay out an rud log item in the + * log. The rud_extents array is a variable size array whose + * size is given by rud_nextents; + */ +struct xfs_rud_log_format { + __uint16_t rud_type; /* rud log item type */ + __uint16_t rud_size; /* size of this item */ + __uint32_t rud_nextents; /* # of extents freed */ + __uint64_t rud_rui_id; /* id of corresponding rui */ + struct xfs_map_extent rud_extents[1]; /* array of extents rmapped */ +}; + +/* * Dquot Log format definitions. * * The first two fields must be the type and size fitting into diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 6674340..aff60dc 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -87,4 +87,23 @@ int xfs_rmapbt_query_range(struct xfs_btree_cur *cur, struct xfs_rmap_irec *low_rec, struct xfs_rmap_irec *high_rec, xfs_rmapbt_query_range_fn fn, void *priv); +enum xfs_rmap_intent_type { + XFS_RMAP_MAP, + XFS_RMAP_MAP_SHARED, + XFS_RMAP_UNMAP, + XFS_RMAP_UNMAP_SHARED, + XFS_RMAP_CONVERT, + XFS_RMAP_CONVERT_SHARED, + XFS_RMAP_ALLOC, + XFS_RMAP_FREE, +}; + +struct xfs_rmap_intent { + struct list_head ri_list; + enum xfs_rmap_intent_type ri_type; + __uint64_t ri_owner; + int ri_whichfork; + struct xfs_bmbt_irec ri_bmap; +}; + #endif /* __XFS_RMAP_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:35:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F2CC08152 for ; Thu, 16 Jun 2016 20:35:38 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 7C4CEAC001 for ; Thu, 16 Jun 2016 18:35:38 -0700 (PDT) X-ASG-Debug-ID: 1466127336-04bdf01e13961a0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ozjmMWjjkAWa4Tir (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:36 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ZW1Q004568 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:32 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZVFn032157 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:31 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZUNm023072; Fri, 17 Jun 2016 01:35:31 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:30 -0700 Subject: [PATCH 045/145] xfs: enable the xfs_defer mechanism to process rmaps to update From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 045/145] xfs: enable the xfs_defer mechanism to process rmaps to update To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:35:29 -0700 Message-ID: <146612732898.16048.12128402877492848247.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127336 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3705 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Connect the xfs_defer mechanism with the pieces that we'll need to handle deferred rmap updates. We'll wire up the existing code to our new deferred mechanism later. Signed-off-by: Darrick J. Wong --- libxfs/defer_item.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_defer.h | 1 + 2 files changed, 101 insertions(+) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index 777875c..cd88cfd 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -30,6 +30,7 @@ #include "xfs_trans.h" #include "xfs_bmap.h" #include "xfs_alloc.h" +#include "xfs_rmap_btree.h" /* Extent Freeing */ @@ -126,11 +127,110 @@ const struct xfs_defer_op_type xfs_extent_free_defer_type = { .cancel_item = xfs_bmap_free_cancel_item, }; +/* Reverse Mapping */ + +/* Sort rmap intents by AG. */ +static int +xfs_rmap_update_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_mount *mp = priv; + struct xfs_rmap_intent *ra; + struct xfs_rmap_intent *rb; + + ra = container_of(a, struct xfs_rmap_intent, ri_list); + rb = container_of(b, struct xfs_rmap_intent, ri_list); + return XFS_FSB_TO_AGNO(mp, ra->ri_bmap.br_startblock) - + XFS_FSB_TO_AGNO(mp, rb->ri_bmap.br_startblock); +} + +/* Get an RUI. */ +STATIC void * +xfs_rmap_update_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return NULL; +} + +/* Log rmap updates in the intent item. */ +STATIC void +xfs_rmap_update_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ +} + +/* Get an RUD so we can process all the deferred rmap updates. */ +STATIC void * +xfs_rmap_update_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return NULL; +} + +/* Process a deferred rmap update. */ +STATIC int +xfs_rmap_update_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + return -EFSCORRUPTED; +} + +/* Clean up after processing deferred rmaps. */ +STATIC void +xfs_rmap_update_finish_cleanup( + struct xfs_trans *tp, + void *state, + int error) +{ +} + +/* Abort all pending RUIs. */ +STATIC void +xfs_rmap_update_abort_intent( + void *intent) +{ +} + +/* Cancel a deferred rmap update. */ +STATIC void +xfs_rmap_update_cancel_item( + struct list_head *item) +{ + struct xfs_rmap_intent *rmap; + + rmap = container_of(item, struct xfs_rmap_intent, ri_list); + kmem_free(rmap); +} + +const struct xfs_defer_op_type xfs_rmap_update_defer_type = { + .type = XFS_DEFER_OPS_TYPE_RMAP, + .diff_items = xfs_rmap_update_diff_items, + .create_intent = xfs_rmap_update_create_intent, + .abort_intent = xfs_rmap_update_abort_intent, + .log_item = xfs_rmap_update_log_item, + .create_done = xfs_rmap_update_create_done, + .finish_item = xfs_rmap_update_finish_item, + .finish_cleanup = xfs_rmap_update_finish_cleanup, + .cancel_item = xfs_rmap_update_cancel_item, +}; + /* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_rmap_update_defer_type); xfs_defer_init_op_type(&xfs_extent_free_defer_type); } diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h index 743fc32..920642e 100644 --- a/libxfs/xfs_defer.h +++ b/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_RMAP, XFS_DEFER_OPS_TYPE_FREE, XFS_DEFER_OPS_TYPE_MAX, }; From darrick.wong@oracle.com Thu Jun 16 20:35:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 274A5819A for ; Thu, 16 Jun 2016 20:35:47 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 92C5FAC001 for ; Thu, 16 Jun 2016 18:35:46 -0700 (PDT) X-ASG-Debug-ID: 1466127342-04cbb01fee6a150001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 7eRmhdvPJr5iVCYG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:43 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1Zb51017418 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:38 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Zb1h004843 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:37 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZaTq023094; Fri, 17 Jun 2016 01:35:37 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:36 -0700 Subject: [PATCH 046/145] xfs: propagate bmap updates to rmapbt From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 046/145] xfs: propagate bmap updates to rmapbt To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:35:35 -0700 Message-ID: <146612733514.16048.2625675620980385531.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127342 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15024 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we map, unmap, or convert an extent in a file's data or attr fork, schedule a respective update in the rmapbt. Previous versions of this patch required a 1:1 correspondence between bmap and rmap, but this is no longer true. v2: Remove the 1:1 correspondence requirement now that we have the ability to make interval queries against the rmapbt. Update the commit message to reflect the broad restructuring of this patch. Fix the bmap shift code to adjust the rmaps correctly. v3: Use the deferred operations code to handle redo operations atomically and deadlock free. Plumb in all five rmap actions (map, unmap, convert extent, alloc, free); we'll use the first three now for file data, and reflink will want the last two. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 2 libxfs/defer_item.c | 18 +++ libxfs/util.c | 1 libxfs/xfs_bmap.c | 56 +++++++++- libxfs/xfs_rmap.c | 252 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.h | 24 ++++ 6 files changed, 344 insertions(+), 9 deletions(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 55df410..00c2ccb 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -200,6 +200,8 @@ #define trace_xfs_rmapbt_insert_error(...) ((void) 0) #define trace_xfs_rmapbt_delete(...) ((void) 0) #define trace_xfs_rmapbt_delete_error(...) ((void) 0) +#define trace_xfs_rmap_defer(...) ((void) 0) +#define trace_xfs_rmap_deferred(...) ((void) 0) #define trace_xfs_rmap_lookup_le_range_result(...) ((void) 0) #define trace_xfs_rmap_map_gtrec(...) ((void) 0) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index cd88cfd..381c969 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -183,7 +183,20 @@ xfs_rmap_update_finish_item( void *done_item, void **state) { - return -EFSCORRUPTED; + struct xfs_rmap_intent *rmap; + int error; + + rmap = container_of(item, struct xfs_rmap_intent, ri_list); + error = xfs_rmap_finish_one(tp, + rmap->ri_type, + rmap->ri_owner, rmap->ri_whichfork, + rmap->ri_bmap.br_startoff, + rmap->ri_bmap.br_startblock, + rmap->ri_bmap.br_blockcount, + rmap->ri_bmap.br_state, + (struct xfs_btree_cur **)state); + kmem_free(rmap); + return error; } /* Clean up after processing deferred rmaps. */ @@ -193,6 +206,9 @@ xfs_rmap_update_finish_cleanup( void *state, int error) { + struct xfs_btree_cur *rcur = state; + + xfs_rmap_finish_one_cleanup(tp, rcur, error); } /* Abort all pending RUIs. */ diff --git a/libxfs/util.c b/libxfs/util.c index 5b277c2..2ba6510 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -37,6 +37,7 @@ #include "xfs_alloc.h" #include "xfs_bit.h" #include "list.h" +#include "xfs_rmap_btree.h" /* * Calculate the worst case log unit reservation for a given superblock diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 453d073..e9ccec5 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -38,6 +38,7 @@ #include "xfs_trace.h" #include "xfs_attr_leaf.h" #include "xfs_quota_defs.h" +#include "xfs_rmap_btree.h" kmem_zone_t *xfs_bmap_free_item_zone; @@ -2170,6 +2171,11 @@ xfs_bmap_add_extent_delay_real( ASSERT(0); } + /* add reverse mapping */ + error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new); + if (error) + goto done; + /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(bma->ip, whichfork)) { int tmp_logflags; /* partial log flag return val */ @@ -2706,6 +2712,11 @@ xfs_bmap_add_extent_unwritten_real( ASSERT(0); } + /* update reverse mappings */ + error = xfs_rmap_convert_extent(mp, dfops, ip, XFS_DATA_FORK, new); + if (error) + goto done; + /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(ip, XFS_DATA_FORK)) { int tmp_logflags; /* partial log flag return val */ @@ -3098,6 +3109,11 @@ xfs_bmap_add_extent_hole_real( break; } + /* add reverse mapping */ + error = xfs_rmap_map_extent(mp, bma->dfops, bma->ip, whichfork, new); + if (error) + goto done; + /* convert to a btree if necessary */ if (xfs_bmap_needs_btree(bma->ip, whichfork)) { int tmp_logflags; /* partial log flag return val */ @@ -5024,6 +5040,14 @@ xfs_bmap_del_extent( ++*idx; break; } + + /* remove reverse mapping */ + if (!delay) { + error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, del); + if (error) + goto done; + } + /* * If we need to, add to list of extents to delete. */ @@ -5561,7 +5585,8 @@ xfs_bmse_shift_one( struct xfs_bmbt_rec_host *gotp, struct xfs_btree_cur *cur, int *logflags, - enum shift_direction direction) + enum shift_direction direction, + struct xfs_defer_ops *dfops) { struct xfs_ifork *ifp; struct xfs_mount *mp; @@ -5609,9 +5634,13 @@ xfs_bmse_shift_one( /* check whether to merge the extent or shift it down */ if (xfs_bmse_can_merge(&adj_irec, &got, offset_shift_fsb)) { - return xfs_bmse_merge(ip, whichfork, offset_shift_fsb, - *current_ext, gotp, adj_irecp, - cur, logflags); + error = xfs_bmse_merge(ip, whichfork, offset_shift_fsb, + *current_ext, gotp, adj_irecp, + cur, logflags); + if (error) + return error; + adj_irec = got; + goto update_rmap; } } else { startoff = got.br_startoff + offset_shift_fsb; @@ -5648,9 +5677,10 @@ update_current_ext: (*current_ext)--; xfs_bmbt_set_startoff(gotp, startoff); *logflags |= XFS_ILOG_CORE; + adj_irec = got; if (!cur) { *logflags |= XFS_ILOG_DEXT; - return 0; + goto update_rmap; } error = xfs_bmbt_lookup_eq(cur, got.br_startoff, got.br_startblock, @@ -5660,8 +5690,18 @@ update_current_ext: XFS_WANT_CORRUPTED_RETURN(mp, i == 1); got.br_startoff = startoff; - return xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, - got.br_blockcount, got.br_state); + error = xfs_bmbt_update(cur, got.br_startoff, got.br_startblock, + got.br_blockcount, got.br_state); + if (error) + return error; + +update_rmap: + /* update reverse mapping */ + error = xfs_rmap_unmap_extent(mp, dfops, ip, whichfork, &adj_irec); + if (error) + return error; + adj_irec.br_startoff = startoff; + return xfs_rmap_map_extent(mp, dfops, ip, whichfork, &adj_irec); } /* @@ -5789,7 +5829,7 @@ xfs_bmap_shift_extents( while (nexts++ < num_exts) { error = xfs_bmse_shift_one(ip, whichfork, offset_shift_fsb, ¤t_ext, gotp, cur, &logflags, - direction); + direction, dfops); if (error) goto del_cursor; /* diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 47f37d7..7637903 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -34,6 +34,8 @@ #include "xfs_rmap_btree.h" #include "xfs_trans_space.h" #include "xfs_trace.h" +#include "xfs_bmap.h" +#include "xfs_inode.h" /* * Lookup the first record less than or equal to [bno, len, owner, offset] @@ -1210,3 +1212,253 @@ xfs_rmapbt_query_range( return xfs_btree_query_range(cur, &low_brec, &high_brec, xfs_rmapbt_query_range_helper, &query); } + +/* Clean up after calling xfs_rmap_finish_one. */ +void +xfs_rmap_finish_one_cleanup( + struct xfs_trans *tp, + struct xfs_btree_cur *rcur, + int error) +{ + struct xfs_buf *agbp; + + if (rcur == NULL) + return; + agbp = rcur->bc_private.a.agbp; + xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(tp, agbp); +} + +/* + * Process one of the deferred rmap operations. We pass back the + * btree cursor to maintain our lock on the rmapbt between calls. + * This saves time and eliminates a buffer deadlock between the + * superblock and the AGF because we'll always grab them in the same + * order. + */ +int +xfs_rmap_finish_one( + struct xfs_trans *tp, + enum xfs_rmap_intent_type type, + __uint64_t owner, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state, + struct xfs_btree_cur **pcur) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_btree_cur *rcur; + struct xfs_buf *agbp = NULL; + int error = 0; + xfs_agnumber_t agno; + struct xfs_owner_info oinfo; + xfs_agblock_t bno; + bool unwritten; + + agno = XFS_FSB_TO_AGNO(mp, startblock); + ASSERT(agno != NULLAGNUMBER); + bno = XFS_FSB_TO_AGBNO(mp, startblock); + + trace_xfs_rmap_deferred(mp, agno, type, bno, owner, whichfork, + startoff, blockcount, state); + + if (XFS_TEST_ERROR(false, mp, + XFS_ERRTAG_RMAP_FINISH_ONE, + XFS_RANDOM_RMAP_FINISH_ONE)) + return -EIO; + + /* + * If we haven't gotten a cursor or the cursor AG doesn't match + * the startblock, get one now. + */ + rcur = *pcur; + if (rcur != NULL && rcur->bc_private.a.agno != agno) { + xfs_rmap_finish_one_cleanup(tp, rcur, 0); + rcur = NULL; + *pcur = NULL; + } + if (rcur == NULL) { + error = xfs_free_extent_fix_freelist(tp, agno, &agbp); + if (error) + return error; + if (!agbp) + return -EFSCORRUPTED; + + rcur = xfs_rmapbt_init_cursor(mp, tp, agbp, agno); + if (!rcur) { + error = -ENOMEM; + goto out_cur; + } + } + *pcur = rcur; + + xfs_rmap_ino_owner(&oinfo, owner, whichfork, startoff); + unwritten = state == XFS_EXT_UNWRITTEN; + bno = XFS_FSB_TO_AGBNO(rcur->bc_mp, startblock); + + switch (type) { + case XFS_RMAP_MAP: + error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); + break; + case XFS_RMAP_UNMAP: + error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, + &oinfo); + break; + case XFS_RMAP_CONVERT: + error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, + &oinfo); + break; + case XFS_RMAP_ALLOC: + error = __xfs_rmap_alloc(rcur, bno, blockcount, unwritten, + &oinfo); + break; + case XFS_RMAP_FREE: + error = __xfs_rmap_free(rcur, bno, blockcount, unwritten, + &oinfo); + break; + default: + ASSERT(0); + error = -EFSCORRUPTED; + } + return error; + +out_cur: + xfs_trans_brelse(tp, agbp); + + return error; +} + +/* + * Record a rmap intent; the list is kept sorted first by AG and then by + * increasing age. + */ +static int +__xfs_rmap_add( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_rmap_intent *ri) +{ + struct xfs_rmap_intent *new; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock), + ri->ri_type, + XFS_FSB_TO_AGBNO(mp, ri->ri_bmap.br_startblock), + ri->ri_owner, ri->ri_whichfork, + ri->ri_bmap.br_startoff, + ri->ri_bmap.br_blockcount, + ri->ri_bmap.br_state); + + new = kmem_zalloc(sizeof(struct xfs_rmap_intent), KM_SLEEP | KM_NOFS); + *new = *ri; + + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_RMAP, &new->ri_list); + return 0; +} + +/* Map an extent into a file. */ +int +xfs_rmap_map_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_MAP; + ri.ri_owner = ip->i_ino; + ri.ri_whichfork = whichfork; + ri.ri_bmap = *PREV; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Unmap an extent out of a file. */ +int +xfs_rmap_unmap_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_UNMAP; + ri.ri_owner = ip->i_ino; + ri.ri_whichfork = whichfork; + ri.ri_bmap = *PREV; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Convert a data fork extent from unwritten to real or vice versa. */ +int +xfs_rmap_convert_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_CONVERT; + ri.ri_owner = ip->i_ino; + ri.ri_whichfork = whichfork; + ri.ri_bmap = *PREV; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Schedule the creation of an rmap for non-file data. */ +int +xfs_rmap_alloc_defer( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + __uint64_t owner) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_ALLOC; + ri.ri_owner = owner; + ri.ri_whichfork = XFS_DATA_FORK; + ri.ri_bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); + ri.ri_bmap.br_blockcount = len; + ri.ri_bmap.br_startoff = 0; + ri.ri_bmap.br_state = XFS_EXT_NORM; + + return __xfs_rmap_add(mp, dfops, &ri); +} + +/* Schedule the deletion of an rmap for non-file data. */ +int +xfs_rmap_free_defer( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, + xfs_agblock_t bno, + xfs_extlen_t len, + __uint64_t owner) +{ + struct xfs_rmap_intent ri; + + ri.ri_type = XFS_RMAP_FREE; + ri.ri_owner = owner; + ri.ri_whichfork = XFS_DATA_FORK; + ri.ri_bmap.br_startblock = XFS_AGB_TO_FSB(mp, agno, bno); + ri.ri_bmap.br_blockcount = len; + ri.ri_bmap.br_startoff = 0; + ri.ri_bmap.br_state = XFS_EXT_NORM; + + return __xfs_rmap_add(mp, dfops, &ri); +} diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index aff60dc..5df406e 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -106,4 +106,28 @@ struct xfs_rmap_intent { struct xfs_bmbt_irec ri_bmap; }; +/* functions for updating the rmapbt based on bmbt map/unmap operations */ +int xfs_rmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_rmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_rmap_convert_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_rmap_alloc_defer(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + __uint64_t owner); +int xfs_rmap_free_defer(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, + __uint64_t owner); + +void xfs_rmap_finish_one_cleanup(struct xfs_trans *tp, + struct xfs_btree_cur *rcur, int error); +int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type, + __uint64_t owner, int whichfork, xfs_fileoff_t startoff, + xfs_fsblock_t startblock, xfs_filblks_t blockcount, + xfs_exntst_t state, struct xfs_btree_cur **pcur); + #endif /* __XFS_RMAP_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:35:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1583281A3 for ; Thu, 16 Jun 2016 20:35:52 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id D9CCE304048 for ; Thu, 16 Jun 2016 18:35:51 -0700 (PDT) X-ASG-Debug-ID: 1466127350-04cb6c542557f40001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 70M8EaXWNQrBtSSF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:50 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ZkRH004730 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:46 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZjLU032444 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:45 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZhDC010942; Fri, 17 Jun 2016 01:35:44 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:42 -0700 Subject: [PATCH 047/145] xfs: add rmap btree geometry feature flag From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 047/145] xfs: add rmap btree geometry feature flag To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:35:41 -0700 Message-ID: <146612734137.16048.1164157172789537615.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127350 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 784 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner So xfs_info and other userspace utilities know the filesystem is using this feature. Signed-off-by: Dave Chinner --- libxfs/xfs_fs.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index 1f17e1c..085ea6f 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -230,6 +230,7 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */ +#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* Reverse mapping btree */ /* * Minimum and maximum sizes need for growth checks. From darrick.wong@oracle.com Thu Jun 16 20:35:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B439F81A5 for ; Thu, 16 Jun 2016 20:35:56 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 81A61304048 for ; Thu, 16 Jun 2016 18:35:56 -0700 (PDT) X-ASG-Debug-ID: 1466127354-04cbb01fec6a170001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id F556fwLhUp16NOI3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:35:55 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ZoNf004778 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:50 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZnWg005054 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:50 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1Zn3q028164; Fri, 17 Jun 2016 01:35:49 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:48 -0700 Subject: [PATCH 048/145] xfs: don't update rmapbt when fixing agfl From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 048/145] xfs: don't update rmapbt when fixing agfl To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:35:47 -0700 Message-ID: <146612734754.16048.4355394142113008748.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127354 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3339 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Allow a caller of xfs_alloc_fix_freelist to disable rmapbt updates when fixing the AG freelist. xfs_repair needs this during phase 5 to be able to adjust the freelist while it's reconstructing the rmap btree; the missing entries will be added back at the very end of phase 5 once the AGFL contents settle down. Signed-off-by: Darrick J. Wong --- libxfs/xfs_alloc.c | 40 ++++++++++++++++++++++++++-------------- libxfs/xfs_alloc.h | 3 +++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 7d680da..2f943db 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2088,26 +2088,38 @@ xfs_alloc_fix_freelist( * anything other than extra overhead when we need to put more blocks * back on the free list? Maybe we should only do this when space is * getting low or the AGFL is more than half full? + * + * The NOSHRINK flag prevents the AGFL from being shrunk if it's too + * big; the NORMAP flag prevents AGFL expand/shrink operations from + * updating the rmapbt. Both flags are used in xfs_repair while we're + * rebuilding the rmapbt, and neither are used by the kernel. They're + * both required to ensure that rmaps are correctly recorded for the + * regenerated AGFL, bnobt, and cntbt. See repair/phase5.c and + * repair/rmap.c in xfsprogs for details. */ - xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); - while (pag->pagf_flcount > need) { - struct xfs_buf *bp; + memset(&targs, 0, sizeof(targs)); + if (!(flags & XFS_ALLOC_FLAG_NOSHRINK)) { + if (!(flags & XFS_ALLOC_FLAG_NORMAP)) + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); + while (pag->pagf_flcount > need) { + struct xfs_buf *bp; - error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); - if (error) - goto out_agbp_relse; - error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, - &targs.oinfo, 1); - if (error) - goto out_agbp_relse; - bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); - xfs_trans_binval(tp, bp); + error = xfs_alloc_get_freelist(tp, agbp, &bno, 0); + if (error) + goto out_agbp_relse; + error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, + &targs.oinfo, 1); + if (error) + goto out_agbp_relse; + bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); + xfs_trans_binval(tp, bp); + } } - memset(&targs, 0, sizeof(targs)); targs.tp = tp; targs.mp = mp; - xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); + if (!(flags & XFS_ALLOC_FLAG_NORMAP)) + xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); targs.agbp = agbp; targs.agno = args->agno; targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 7b6c66b..7b9e67e 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -54,6 +54,9 @@ typedef unsigned int xfs_alloctype_t; */ #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ +#define XFS_ALLOC_FLAG_NORMAP 0x00000004 /* don't modify the rmapbt */ +#define XFS_ALLOC_FLAG_NOSHRINK 0x00000008 /* don't shrink the freelist */ + /* * Argument structure for xfs_alloc routines. From darrick.wong@oracle.com Thu Jun 16 20:36:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0FEC881B5 for ; Thu, 16 Jun 2016 20:36:06 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8B69AAC002 for ; Thu, 16 Jun 2016 18:36:05 -0700 (PDT) X-ASG-Debug-ID: 1466127363-04bdf01e1396200001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id o3LU0dHbCHa9PFLo (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ZxCj017530 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:59 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZxOK032625 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:35:59 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ZuDL010960; Fri, 17 Jun 2016 01:35:57 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:35:56 -0700 Subject: [PATCH 049/145] xfs: enable the rmap btree functionality From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 049/145] xfs: enable the rmap btree functionality To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:35:53 -0700 Message-ID: <146612735364.16048.10084233974535786999.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127364 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1096 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Add the feature flag to the supported matrix so that the kernel can mount and use rmap btree enabled filesystems v2: Move the EXPERIMENTAL message to fill_super so it only prints once. Signed-off-by: Dave Chinner [darrick.wong@oracle.com: move the experimental tag] Signed-off-by: Darrick J. Wong --- libxfs/xfs_format.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 2525004..7205806 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -457,7 +457,8 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ - (XFS_SB_FEAT_RO_COMPAT_FINOBT) + (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ + XFS_SB_FEAT_RO_COMPAT_RMAPBT) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool xfs_sb_has_ro_compat_feature( From darrick.wong@oracle.com Thu Jun 16 20:36:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 01F9981BD for ; Thu, 16 Jun 2016 20:36:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id CECEF304048 for ; Thu, 16 Jun 2016 18:36:11 -0700 (PDT) X-ASG-Debug-ID: 1466127368-04cb6c542457f60001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id AjAK14nA6cKtusyQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:09 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1a4Y2017788 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:04 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1a3H3005523 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:03 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1a37g000572; Fri, 17 Jun 2016 01:36:03 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:02 -0700 Subject: [PATCH 050/145] xfs_db: display rmap btree contents From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 050/145] xfs_db: display rmap btree contents To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:36:01 -0700 Message-ID: <146612736121.16048.14772876071545022810.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127369 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14130 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Teach the debugger how to dump the reverse-mapping btree contents. Decode the extra fields in the rmapbt records and keys now that we support reflink. Signed-off-by: Dave Chinner [darrick: split patch, add commit message, decode extra fields] [darrick: support overlapped interval btree fields] [darrick: move unwritten bit to rm_offset] Signed-off-by: Darrick J. Wong --- db/agf.c | 6 +++ db/btblock.c | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++ db/btblock.h | 5 +++ db/field.c | 19 ++++++++++ db/field.h | 9 +++++ db/type.c | 5 +++ db/type.h | 2 + man/man8/xfs_db.8 | 56 +++++++++++++++++++++++++++++- 8 files changed, 200 insertions(+), 2 deletions(-) diff --git a/db/agf.c b/db/agf.c index e10526d..f4c4269 100644 --- a/db/agf.c +++ b/db/agf.c @@ -55,6 +55,9 @@ const field_t agf_flds[] = { { "cntroot", FLDT_AGBLOCK, OI(OFF(roots) + XFS_BTNUM_CNT * SZ(roots[XFS_BTNUM_CNT])), C1, 0, TYP_CNTBT }, + { "rmaproot", FLDT_AGBLOCKNZ, + OI(OFF(roots) + XFS_BTNUM_RMAP * SZ(roots[XFS_BTNUM_RMAP])), C1, 0, + TYP_RMAPBT }, { "levels", FLDT_UINT32D, OI(OFF(levels)), CI(XFS_BTNUM_AGF), FLD_ARRAY|FLD_SKIPALL, TYP_NONE }, { "bnolevel", FLDT_UINT32D, @@ -63,6 +66,9 @@ const field_t agf_flds[] = { { "cntlevel", FLDT_UINT32D, OI(OFF(levels) + XFS_BTNUM_CNT * SZ(levels[XFS_BTNUM_CNT])), C1, 0, TYP_NONE }, + { "rmaplevel", FLDT_UINT32D, + OI(OFF(levels) + XFS_BTNUM_RMAP * SZ(levels[XFS_BTNUM_RMAP])), C1, 0, + TYP_NONE }, { "flfirst", FLDT_UINT32D, OI(OFF(flfirst)), C1, 0, TYP_NONE }, { "fllast", FLDT_UINT32D, OI(OFF(fllast)), C1, 0, TYP_NONE }, { "flcount", FLDT_UINT32D, OI(OFF(flcount)), C1, 0, TYP_NONE }, diff --git a/db/btblock.c b/db/btblock.c index 46140fc..ce59d18 100644 --- a/db/btblock.c +++ b/db/btblock.c @@ -96,6 +96,12 @@ struct xfs_db_btree { sizeof(xfs_inobt_rec_t), sizeof(__be32), }, + { XFS_RMAP_CRC_MAGIC, + XFS_BTREE_SBLOCK_CRC_LEN, + 2 * sizeof(struct xfs_rmap_key), + sizeof(struct xfs_rmap_rec), + sizeof(__be32), + }, { 0, }, }; @@ -607,3 +613,97 @@ const field_t cntbt_rec_flds[] = { { NULL } }; #undef ROFF + +/* RMAP btree blocks */ +const field_t rmapbt_crc_hfld[] = { + { "", FLDT_RMAPBT_CRC, OI(0), C1, 0, TYP_NONE }, + { NULL } +}; + +#define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) +const field_t rmapbt_crc_flds[] = { + { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, + { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, + { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, + { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_RMAPBT }, + { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_RMAPBT }, + { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_RMAPBT }, + { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, + { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, + { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, + { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, + { "recs", FLDT_RMAPBTREC, btblock_rec_offset, btblock_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_RMAPBTKEY, btblock_key_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_RMAPBTPTR, btblock_ptr_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_RMAPBT }, + { NULL } +}; +#undef OFF + +#define KOFF(f) bitize(offsetof(struct xfs_rmap_key, rm_ ## f)) + +#define RMAPBK_STARTBLOCK_BITOFF 0 +#define RMAPBK_OWNER_BITOFF (RMAPBK_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN) +#define RMAPBK_ATTRFLAG_BITOFF (RMAPBK_OWNER_BITOFF + RMAPBT_OWNER_BITLEN) +#define RMAPBK_BMBTFLAG_BITOFF (RMAPBK_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN) +#define RMAPBK_EXNTFLAG_BITOFF (RMAPBK_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN) +#define RMAPBK_UNUSED_OFFSET_BITOFF (RMAPBK_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN) +#define RMAPBK_OFFSET_BITOFF (RMAPBK_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) + +#define HI_KOFF(f) bitize(sizeof(struct xfs_rmap_key) + offsetof(struct xfs_rmap_key, rm_ ## f)) + +#define RMAPBK_STARTBLOCKHI_BITOFF (bitize(sizeof(struct xfs_rmap_key))) +#define RMAPBK_OWNERHI_BITOFF (RMAPBK_STARTBLOCKHI_BITOFF + RMAPBT_STARTBLOCK_BITLEN) +#define RMAPBK_ATTRFLAGHI_BITOFF (RMAPBK_OWNERHI_BITOFF + RMAPBT_OWNER_BITLEN) +#define RMAPBK_BMBTFLAGHI_BITOFF (RMAPBK_ATTRFLAGHI_BITOFF + RMAPBT_ATTRFLAG_BITLEN) +#define RMAPBK_EXNTFLAGHI_BITOFF (RMAPBK_BMBTFLAGHI_BITOFF + RMAPBT_BMBTFLAG_BITLEN) +#define RMAPBK_UNUSED_OFFSETHI_BITOFF (RMAPBK_EXNTFLAGHI_BITOFF + RMAPBT_EXNTFLAG_BITLEN) +#define RMAPBK_OFFSETHI_BITOFF (RMAPBK_UNUSED_OFFSETHI_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) + +const field_t rmapbt_key_flds[] = { + { "startblock", FLDT_AGBLOCK, OI(KOFF(startblock)), C1, 0, TYP_DATA }, + { "owner", FLDT_INT64D, OI(KOFF(owner)), C1, 0, TYP_NONE }, + { "offset", FLDT_RFILEOFFD, OI(RMAPBK_OFFSET_BITOFF), C1, 0, TYP_NONE }, + { "attrfork", FLDT_RATTRFORKFLG, OI(RMAPBK_ATTRFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "bmbtblock", FLDT_RBMBTFLG, OI(RMAPBK_BMBTFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "startblock_hi", FLDT_AGBLOCK, OI(HI_KOFF(startblock)), C1, 0, TYP_DATA }, + { "owner_hi", FLDT_INT64D, OI(HI_KOFF(owner)), C1, 0, TYP_NONE }, + { "offset_hi", FLDT_RFILEOFFD, OI(RMAPBK_OFFSETHI_BITOFF), C1, 0, TYP_NONE }, + { "attrfork_hi", FLDT_RATTRFORKFLG, OI(RMAPBK_ATTRFLAGHI_BITOFF), C1, 0, + TYP_NONE }, + { "bmbtblock_hi", FLDT_RBMBTFLG, OI(RMAPBK_BMBTFLAGHI_BITOFF), C1, 0, + TYP_NONE }, + { NULL } +}; +#undef HI_KOFF +#undef KOFF + +#define ROFF(f) bitize(offsetof(struct xfs_rmap_rec, rm_ ## f)) + +#define RMAPBT_STARTBLOCK_BITOFF 0 +#define RMAPBT_BLOCKCOUNT_BITOFF (RMAPBT_STARTBLOCK_BITOFF + RMAPBT_STARTBLOCK_BITLEN) +#define RMAPBT_OWNER_BITOFF (RMAPBT_BLOCKCOUNT_BITOFF + RMAPBT_BLOCKCOUNT_BITLEN) +#define RMAPBT_ATTRFLAG_BITOFF (RMAPBT_OWNER_BITOFF + RMAPBT_OWNER_BITLEN) +#define RMAPBT_BMBTFLAG_BITOFF (RMAPBT_ATTRFLAG_BITOFF + RMAPBT_ATTRFLAG_BITLEN) +#define RMAPBT_EXNTFLAG_BITOFF (RMAPBT_BMBTFLAG_BITOFF + RMAPBT_BMBTFLAG_BITLEN) +#define RMAPBT_UNUSED_OFFSET_BITOFF (RMAPBT_EXNTFLAG_BITOFF + RMAPBT_EXNTFLAG_BITLEN) +#define RMAPBT_OFFSET_BITOFF (RMAPBT_UNUSED_OFFSET_BITOFF + RMAPBT_UNUSED_OFFSET_BITLEN) + +const field_t rmapbt_rec_flds[] = { + { "startblock", FLDT_AGBLOCK, OI(RMAPBT_STARTBLOCK_BITOFF), C1, 0, TYP_DATA }, + { "blockcount", FLDT_REXTLEN, OI(RMAPBT_BLOCKCOUNT_BITOFF), C1, 0, TYP_NONE }, + { "owner", FLDT_INT64D, OI(RMAPBT_OWNER_BITOFF), C1, 0, TYP_NONE }, + { "offset", FLDT_RFILEOFFD, OI(RMAPBT_OFFSET_BITOFF), C1, 0, TYP_NONE }, + { "extentflag", FLDT_REXTFLG, OI(RMAPBT_EXNTFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "attrfork", FLDT_RATTRFORKFLG, OI(RMAPBT_ATTRFLAG_BITOFF), C1, 0, + TYP_NONE }, + { "bmbtblock", FLDT_RBMBTFLG, OI(RMAPBT_BMBTFLAG_BITOFF), C1, 0, + TYP_NONE }, + { NULL } +}; +#undef ROFF diff --git a/db/btblock.h b/db/btblock.h index 228eb36..35299b4 100644 --- a/db/btblock.h +++ b/db/btblock.h @@ -54,4 +54,9 @@ extern const struct field cntbt_crc_hfld[]; extern const struct field cntbt_key_flds[]; extern const struct field cntbt_rec_flds[]; +extern const struct field rmapbt_crc_flds[]; +extern const struct field rmapbt_crc_hfld[]; +extern const struct field rmapbt_key_flds[]; +extern const struct field rmapbt_rec_flds[]; + extern int btblock_size(void *obj, int startoff, int idx); diff --git a/db/field.c b/db/field.c index 843c385..58728a9 100644 --- a/db/field.c +++ b/db/field.c @@ -153,6 +153,16 @@ const ftattr_t ftattrtab[] = { { FLDT_CHARNS, "charns", fp_charns, NULL, SI(bitsz(char)), 0, NULL, NULL }, { FLDT_CHARS, "chars", fp_num, "%c", SI(bitsz(char)), 0, NULL, NULL }, + { FLDT_REXTLEN, "rextlen", fp_num, "%u", SI(RMAPBT_BLOCKCOUNT_BITLEN), + 0, NULL, NULL }, + { FLDT_RFILEOFFD, "rfileoffd", fp_num, "%llu", SI(RMAPBT_OFFSET_BITLEN), + 0, NULL, NULL }, + { FLDT_REXTFLG, "rextflag", fp_num, "%u", SI(RMAPBT_EXNTFLAG_BITLEN), 0, + NULL, NULL }, + { FLDT_RATTRFORKFLG, "rattrforkflag", fp_num, "%u", SI(RMAPBT_ATTRFLAG_BITLEN), 0, + NULL, NULL }, + { FLDT_RBMBTFLG, "rbmbtflag", fp_num, "%u", SI(RMAPBT_BMBTFLAG_BITLEN), 0, + NULL, NULL }, { FLDT_CNTBT, "cntbt", NULL, (char *)cntbt_flds, btblock_size, FTARG_SIZE, NULL, cntbt_flds }, { FLDT_CNTBT_CRC, "cntbt", NULL, (char *)cntbt_crc_flds, btblock_size, @@ -164,6 +174,15 @@ const ftattr_t ftattrtab[] = { { FLDT_CNTBTREC, "cntbtrec", fp_sarray, (char *)cntbt_rec_flds, SI(bitsz(xfs_alloc_rec_t)), 0, NULL, cntbt_rec_flds }, + { FLDT_RMAPBT_CRC, "rmapbt", NULL, (char *)rmapbt_crc_flds, btblock_size, + FTARG_SIZE, NULL, rmapbt_crc_flds }, + { FLDT_RMAPBTKEY, "rmapbtkey", fp_sarray, (char *)rmapbt_key_flds, + SI(bitize(2 * sizeof(struct xfs_rmap_key))), 0, NULL, rmapbt_key_flds }, + { FLDT_RMAPBTPTR, "rmapbtptr", fp_num, "%u", + SI(bitsz(xfs_rmap_ptr_t)), 0, fa_agblock, NULL }, + { FLDT_RMAPBTREC, "rmapbtrec", fp_sarray, (char *)rmapbt_rec_flds, + SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rmapbt_rec_flds }, + /* CRC field */ { FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(__uint32_t)), 0, NULL, NULL }, diff --git a/db/field.h b/db/field.h index 11aebc3..47f562a 100644 --- a/db/field.h +++ b/db/field.h @@ -75,11 +75,20 @@ typedef enum fldt { FLDT_CFSBLOCK, FLDT_CHARNS, FLDT_CHARS, + FLDT_REXTLEN, + FLDT_RFILEOFFD, + FLDT_REXTFLG, + FLDT_RATTRFORKFLG, + FLDT_RBMBTFLG, FLDT_CNTBT, FLDT_CNTBT_CRC, FLDT_CNTBTKEY, FLDT_CNTBTPTR, FLDT_CNTBTREC, + FLDT_RMAPBT_CRC, + FLDT_RMAPBTKEY, + FLDT_RMAPBTPTR, + FLDT_RMAPBTREC, /* CRC field type */ FLDT_CRC, diff --git a/db/type.c b/db/type.c index 1da7ee1..dd192a1 100644 --- a/db/type.c +++ b/db/type.c @@ -58,6 +58,7 @@ static const typ_t __typtab[] = { { TYP_BMAPBTD, "bmapbtd", handle_struct, bmapbtd_hfld, NULL }, { TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld, NULL }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld, NULL }, + { TYP_RMAPBT, NULL }, { TYP_DATA, "data", handle_block, NULL, NULL }, { TYP_DIR2, "dir2", handle_struct, dir2_hfld, NULL }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, NULL }, @@ -88,6 +89,8 @@ static const typ_t __typtab_crc[] = { &xfs_allocbt_buf_ops }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_crc_hfld, &xfs_allocbt_buf_ops }, + { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, + &xfs_rmapbt_buf_ops }, { TYP_DATA, "data", handle_block, NULL, NULL }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops }, @@ -124,6 +127,8 @@ static const typ_t __typtab_spcrc[] = { &xfs_allocbt_buf_ops }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_crc_hfld, &xfs_allocbt_buf_ops }, + { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, + &xfs_rmapbt_buf_ops }, { TYP_DATA, "data", handle_block, NULL, NULL }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops }, diff --git a/db/type.h b/db/type.h index d9583e5..1bef8e6 100644 --- a/db/type.h +++ b/db/type.h @@ -24,7 +24,7 @@ struct field; typedef enum typnm { TYP_AGF, TYP_AGFL, TYP_AGI, TYP_ATTR, TYP_BMAPBTA, - TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_DATA, + TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_RMAPBT, TYP_DATA, TYP_DIR2, TYP_DQBLK, TYP_INOBT, TYP_INODATA, TYP_INODE, TYP_LOG, TYP_RTBITMAP, TYP_RTSUMMARY, TYP_SB, TYP_SYMLINK, TYP_TEXT, TYP_FINOBT, TYP_NONE diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index ff8f862..a380f78 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -673,7 +673,7 @@ If no argument is given, show the current data type. The possible data types are: .BR agf ", " agfl ", " agi ", " attr ", " bmapbta ", " bmapbtd , .BR bnobt ", " cntbt ", " data ", " dir ", " dir2 ", " dqblk , -.BR inobt ", " inode ", " log ", " rtbitmap ", " rtsummary , +.BR inobt ", " inode ", " log ", " rmapbt ", " rtbitmap ", " rtsummary , .BR sb ", " symlink " and " text . See the TYPES section below for more information on these data types. .TP @@ -1658,6 +1658,60 @@ use .BR xfs_logprint (8) instead. .TP +.B rmapbt +There is one set of filesystem blocks forming the reverse mapping Btree for +each allocation group. The root block of this Btree is designated by the +.B rmaproot +field in the corresponding AGF block. The blocks are linked to sibling left +and right blocks at each level, as well as by pointers from parent to child +blocks. Each block has the following fields: +.RS 1.4i +.PD 0 +.TP 1.2i +.B magic +RMAP block magic number, 0x524d4233 ('RMB3'). +.TP +.B level +level number of this block, 0 is a leaf. +.TP +.B numrecs +number of data entries in the block. +.TP +.B leftsib +left (logically lower) sibling block, 0 if none. +.TP +.B rightsib +right (logically higher) sibling block, 0 if none. +.TP +.B recs +[leaf blocks only] array of reference count records. Each record contains +.BR startblock , +.BR blockcount , +.BR owner , +.BR offset , +.BR attr_fork , +.BR bmbt_block , +and +.BR unwritten . +.TP +.B keys +[non-leaf blocks only] array of double-key records. The first ("low") key +contains the first value of each block in the level below this one. The second +("high") key contains the largest key that can be used to identify any record +in the subtree. Each record contains +.BR startblock , +.BR owner , +.BR offset , +.BR attr_fork , +and +.BR bmbt_block . +.TP +.B ptrs +[non-leaf blocks only] array of child block pointers. Each pointer is a +block number within the allocation group to the next level in the Btree. +.PD +.RE +.TP .B rtbitmap If the filesystem has a realtime subvolume, then the .B rbmino From darrick.wong@oracle.com Thu Jun 16 20:36:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E6C3E81C5 for ; Thu, 16 Jun 2016 20:36:21 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id A440D8F804B for ; Thu, 16 Jun 2016 18:36:21 -0700 (PDT) X-ASG-Debug-ID: 1466127379-04bdf01e1596230001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 53mdAHJVtFXRtbFK (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:19 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1aFlA017923 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:15 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1aFGo000656 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:15 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1aFaK000611; Fri, 17 Jun 2016 01:36:15 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:15 -0700 Subject: [PATCH 052/145] xfs_db: copy the rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 052/145] xfs_db: copy the rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:13 -0700 Message-ID: <146612737369.16048.1024235351152229608.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127379 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2599 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Copy the rmapbt when we're metadumping the filesystem. Signed-off-by: Darrick J. Wong --- db/metadump.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/db/metadump.c b/db/metadump.c index d7ff6e5..609a5d7 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -543,6 +543,78 @@ copy_free_cnt_btree( return scan_btree(agno, root, levels, TYP_CNTBT, agf, scanfunc_freesp); } +static int +scanfunc_rmapbt( + struct xfs_btree_block *block, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + int level, + typnm_t btype, + void *arg) +{ + xfs_rmap_ptr_t *pp; + int i; + int numrecs; + + if (level == 0) + return 1; + + numrecs = be16_to_cpu(block->bb_numrecs); + if (numrecs > mp->m_rmap_mxr[1]) { + if (show_warnings) + print_warning("invalid numrecs (%u) in %s block %u/%u", + numrecs, typtab[btype].name, agno, agbno); + return 1; + } + + pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]); + for (i = 0; i < numrecs; i++) { + if (!valid_bno(agno, be32_to_cpu(pp[i]))) { + if (show_warnings) + print_warning("invalid block number (%u/%u) " + "in %s block %u/%u", + agno, be32_to_cpu(pp[i]), + typtab[btype].name, agno, agbno); + continue; + } + if (!scan_btree(agno, be32_to_cpu(pp[i]), level, btype, arg, + scanfunc_rmapbt)) + return 0; + } + return 1; +} + +static int +copy_rmap_btree( + xfs_agnumber_t agno, + struct xfs_agf *agf) +{ + xfs_agblock_t root; + int levels; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 1; + + root = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); + levels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]); + + /* validate root and levels before processing the tree */ + if (root == 0 || root > mp->m_sb.sb_agblocks) { + if (show_warnings) + print_warning("invalid block number (%u) in rmapbt " + "root in agf %u", root, agno); + return 1; + } + if (levels >= XFS_BTREE_MAXLEVELS) { + if (show_warnings) + print_warning("invalid level (%u) in rmapbt root " + "in agf %u", levels, agno); + return 1; + } + + return scan_btree(agno, root, levels, TYP_RMAPBT, agf, scanfunc_rmapbt); +} + /* filename and extended attribute obfuscation routines */ struct name_ent { @@ -2451,6 +2523,8 @@ scan_ag( goto pop_out; if (!copy_free_cnt_btree(agno, agf)) goto pop_out; + if (!copy_rmap_btree(agno, agf)) + goto pop_out; } /* copy inode btrees and the inodes and their associated metadata */ From darrick.wong@oracle.com Thu Jun 16 20:36:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 811F581C7 for ; Thu, 16 Jun 2016 20:36:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 41F4F304039 for ; Thu, 16 Jun 2016 18:36:25 -0700 (PDT) X-ASG-Debug-ID: 1466127374-04cbb01fee6a1b0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id vV2Jgmbp6FKYmFb9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1a9RT017853 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:10 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1a9uX025919 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:09 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1a9uO000584; Fri, 17 Jun 2016 01:36:09 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:08 -0700 Subject: [PATCH 051/145] xfs_db: spot check rmapbt From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 051/145] xfs_db: spot check rmapbt To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:07 -0700 Message-ID: <146612736753.16048.10847740420522557364.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127374 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4527 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Check the rmapbt for obvious errors. We're leaving thorough checks such as comparing the primary metadata against the rmapbt contents for newer things like xfs_repair. Signed-off-by: Darrick J. Wong --- db/check.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) diff --git a/db/check.c b/db/check.c index 0871ed7..2964b5f 100644 --- a/db/check.c +++ b/db/check.c @@ -44,7 +44,7 @@ typedef enum { DBM_FREE1, DBM_FREE2, DBM_FREELIST, DBM_INODE, DBM_LOG, DBM_MISSING, DBM_QUOTA, DBM_RTBITMAP, DBM_RTDATA, DBM_RTFREE, DBM_RTSUM, DBM_SB, - DBM_SYMLINK, DBM_BTFINO, + DBM_SYMLINK, DBM_BTFINO, DBM_BTRMAP, DBM_NDBM } dbm_t; @@ -171,6 +171,7 @@ static const char *typename[] = { "sb", "symlink", "btfino", + "btrmap", NULL }; static int verbose; @@ -349,6 +350,9 @@ static void scanfunc_ino(struct xfs_btree_block *block, int level, static void scanfunc_fino(struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot); +static void scanfunc_rmap(struct xfs_btree_block *block, int level, + struct xfs_agf *agf, xfs_agblock_t bno, + int isroot); static void set_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type, xfs_agnumber_t c_agno, xfs_agblock_t c_agbno); @@ -1050,6 +1054,7 @@ blocktrash_f( (1 << DBM_RTSUM) | (1 << DBM_SYMLINK) | (1 << DBM_BTFINO) | + (1 << DBM_BTRMAP) | (1 << DBM_SB); while ((c = getopt(argc, argv, "0123n:o:s:t:x:y:z")) != EOF) { switch (c) { @@ -3899,6 +3904,12 @@ scan_ag( be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]), be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]), 1, scanfunc_cnt, TYP_CNTBT); + if (agf->agf_roots[XFS_BTNUM_RMAP]) { + scan_sbtree(agf, + be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]), + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]), + 1, scanfunc_rmap, TYP_RMAPBT); + } scan_sbtree(agf, be32_to_cpu(agi->agi_root), be32_to_cpu(agi->agi_level), @@ -4650,6 +4661,78 @@ scanfunc_fino( } static void +scanfunc_rmap( + struct xfs_btree_block *block, + int level, + struct xfs_agf *agf, + xfs_agblock_t bno, + int isroot) +{ + xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); + int i; + xfs_rmap_ptr_t *pp; + struct xfs_rmap_rec *rp; + xfs_agblock_t lastblock; + + if (be32_to_cpu(block->bb_magic) != XFS_RMAP_CRC_MAGIC) { + dbprintf(_("bad magic # %#x in rmapbt block %u/%u\n"), + be32_to_cpu(block->bb_magic), seqno, bno); + serious_error++; + return; + } + if (be16_to_cpu(block->bb_level) != level) { + if (!sflag) + dbprintf(_("expected level %d got %d in rmapbt block " + "%u/%u\n"), + level, be16_to_cpu(block->bb_level), seqno, bno); + error++; + } + if (!isroot) { + fdblocks++; + agfbtreeblks++; + } + set_dbmap(seqno, bno, 1, DBM_BTRMAP, seqno, bno); + if (level == 0) { + if (be16_to_cpu(block->bb_numrecs) > mp->m_rmap_mxr[0] || + (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_rmap_mnr[0])) { + dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " + "rmapbt block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), mp->m_rmap_mnr[0], + mp->m_rmap_mxr[0], seqno, bno); + serious_error++; + return; + } + rp = XFS_RMAP_REC_ADDR(block, 1); + lastblock = 0; + for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { + if (be32_to_cpu(rp[i].rm_startblock) < lastblock) { + dbprintf(_( + "out-of-order rmap btree record %d (%u %u) block %u/%u\n"), + i, be32_to_cpu(rp[i].rm_startblock), + be32_to_cpu(rp[i].rm_startblock), + be32_to_cpu(agf->agf_seqno), bno); + } else { + lastblock = be32_to_cpu(rp[i].rm_startblock); + } + } + return; + } + if (be16_to_cpu(block->bb_numrecs) > mp->m_rmap_mxr[1] || + (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_rmap_mnr[1])) { + dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in rmapbt " + "block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), mp->m_rmap_mnr[1], + mp->m_rmap_mxr[1], seqno, bno); + serious_error++; + return; + } + pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]); + for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) + scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_rmap, + TYP_RMAPBT); +} + +static void set_dbmap( xfs_agnumber_t agno, xfs_agblock_t agbno, From darrick.wong@oracle.com Thu Jun 16 20:36:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 382CC819B for ; Thu, 16 Jun 2016 20:36:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 07EA78F804B for ; Thu, 16 Jun 2016 18:36:30 -0700 (PDT) X-ASG-Debug-ID: 1466127389-04cb6c542757fa0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id in5rmwg6WP8jFqUr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:29 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1aOUD017970 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:25 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1aNsH005981 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:23 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1aLNb011075; Fri, 17 Jun 2016 01:36:22 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:21 -0700 Subject: [PATCH 053/145] xfs_growfs: report rmapbt presence From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 053/145] xfs_growfs: report rmapbt presence To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:19 -0700 Message-ID: <146612737977.16048.15630789762971566149.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127389 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2471 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- growfs/xfs_growfs.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c index 56315f9..2b46480 100644 --- a/growfs/xfs_growfs.c +++ b/growfs/xfs_growfs.c @@ -58,12 +58,13 @@ report_info( int cimode, int ftype_enabled, int finobt_enabled, - int spinodes) + int spinodes, + int rmapbt_enabled) { printf(_( "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" - " =%-22s crc=%-8u finobt=%u spinodes=%u\n" + " =%-22s crc=%-8u finobt=%u spinodes=%u rmapbt=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" @@ -73,7 +74,7 @@ report_info( mntpoint, geo.inodesize, geo.agcount, geo.agblocks, "", geo.sectsize, attrversion, projid32bit, - "", crcs_enabled, finobt_enabled, spinodes, + "", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled, "", geo.blocksize, (unsigned long long)geo.datablocks, geo.imaxpct, "", geo.sunit, geo.swidth, @@ -127,6 +128,7 @@ main(int argc, char **argv) int ftype_enabled = 0; int finobt_enabled; /* free inode btree */ int spinodes; + int rmapbt_enabled; progname = basename(argv[0]); setlocale(LC_ALL, ""); @@ -250,11 +252,13 @@ main(int argc, char **argv) ftype_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_FTYPE ? 1 : 0; finobt_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_FINOBT ? 1 : 0; spinodes = geo.flags & XFS_FSOP_GEOM_FLAGS_SPINODES ? 1 : 0; + rmapbt_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_RMAPBT ? 1 : 0; if (nflag) { report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, attrversion, projid32bit, crcs_enabled, ci, - ftype_enabled, finobt_enabled, spinodes); + ftype_enabled, finobt_enabled, spinodes, + rmapbt_enabled); exit(0); } @@ -292,7 +296,7 @@ main(int argc, char **argv) report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, attrversion, projid32bit, crcs_enabled, ci, ftype_enabled, - finobt_enabled, spinodes); + finobt_enabled, spinodes, rmapbt_enabled); ddsize = xi.dsize; dlsize = ( xi.logBBsize? xi.logBBsize : From darrick.wong@oracle.com Thu Jun 16 20:36:37 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 211E181DF for ; Thu, 16 Jun 2016 20:36:37 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8C11DAC002 for ; Thu, 16 Jun 2016 18:36:36 -0700 (PDT) X-ASG-Debug-ID: 1466127394-04cbb01fee6a1d0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id PfWlaSZGJhFBZADD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:34 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1aUgr017987 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:36:30 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1aTNL031623 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:30 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1aRSo011089; Fri, 17 Jun 2016 01:36:28 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:27 -0700 Subject: [PATCH 054/145] xfs_io: add rmap-finish error injection type From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 054/145] xfs_io: add rmap-finish error injection type To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:25 -0700 Message-ID: <146612738585.16048.10795156252841536265.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127394 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 769 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add XFS_ERRTAG_RMAP_FINISH_ONE to the types of errors we can inject. Signed-off-by: Darrick J. Wong --- io/inject.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/io/inject.c b/io/inject.c index 12e0fb3..16ac925 100644 --- a/io/inject.c +++ b/io/inject.c @@ -76,7 +76,9 @@ error_tag(char *name) { XFS_ERRTAG_BMAPIFORMAT, "bmapifmt" }, #define XFS_ERRTAG_FREE_EXTENT 22 { XFS_ERRTAG_FREE_EXTENT, "free_extent" }, -#define XFS_ERRTAG_MAX 23 +#define XFS_ERRTAG_RMAP_FINISH_ONE 23 + { XFS_ERRTAG_RMAP_FINISH_ONE, "rmap_finish_one" }, +#define XFS_ERRTAG_MAX 24 { XFS_ERRTAG_MAX, NULL } }; int count; From darrick.wong@oracle.com Thu Jun 16 20:36:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6C38681E7 for ; Thu, 16 Jun 2016 20:36:41 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 1EF5F8F804B for ; Thu, 16 Jun 2016 18:36:41 -0700 (PDT) X-ASG-Debug-ID: 1466127398-04bdf01e1396260001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 90vJC7iElASJiK4l (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:38 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1aYed018008 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:35 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1aY2c026412 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:34 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1aXeU000701; Fri, 17 Jun 2016 01:36:33 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:33 -0700 Subject: [PATCH 055/145] xfs_logprint: support rmap redo items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 055/145] xfs_logprint: support rmap redo items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:31 -0700 Message-ID: <146612739193.16048.6796354307999659114.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127398 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6257 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Print reverse mapping update redo items. Signed-off-by: Darrick J. Wong --- logprint/log_misc.c | 11 +++ logprint/log_print_all.c | 12 ++++ logprint/log_redo.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++ logprint/logprint.h | 5 ++ 4 files changed, 180 insertions(+) diff --git a/logprint/log_misc.c b/logprint/log_misc.c index 57d397c..479fc14 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -993,6 +993,17 @@ xlog_print_record( be32_to_cpu(op_head->oh_len)); break; } + case XFS_LI_RUI: { + skip = xlog_print_trans_rui(&ptr, + be32_to_cpu(op_head->oh_len), + continued); + break; + } + case XFS_LI_RUD: { + skip = xlog_print_trans_rud(&ptr, + be32_to_cpu(op_head->oh_len)); + break; + } case XFS_LI_QUOTAOFF: { skip = xlog_print_trans_qoff(&ptr, be32_to_cpu(op_head->oh_len)); diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index 4d92c3b..0fe354b 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -408,6 +408,12 @@ xlog_recover_print_logitem( case XFS_LI_EFI: xlog_recover_print_efi(item); break; + case XFS_LI_RUD: + xlog_recover_print_rud(item); + break; + case XFS_LI_RUI: + xlog_recover_print_rui(item); + break; case XFS_LI_DQUOT: xlog_recover_print_dquot(item); break; @@ -442,6 +448,12 @@ xlog_recover_print_item( case XFS_LI_EFI: printf("EFI"); break; + case XFS_LI_RUD: + printf("RUD"); + break; + case XFS_LI_RUI: + printf("RUI"); + break; case XFS_LI_DQUOT: printf("DQ "); break; diff --git a/logprint/log_redo.c b/logprint/log_redo.c index d60cc1b..717dccd 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -229,3 +229,155 @@ xlog_recover_print_efd( f->efd_size, f->efd_nextents, (unsigned long long)f->efd_efi_id); } + +/* Reverse Mapping Update Items */ + +static int +xfs_rui_copy_format( + char *buf, + uint len, + struct xfs_rui_log_format *dst_fmt, + int continued) +{ + uint nextents = ((struct xfs_rui_log_format *)buf)->rui_nextents; + uint dst_len = sizeof(struct xfs_rui_log_format) + + (nextents - 1) * sizeof(struct xfs_map_extent); + + if (len == dst_len || continued) { + memcpy((char *)dst_fmt, buf, len); + return 0; + } + fprintf(stderr, _("%s: bad size of RUI format: %u; expected %u; nextents = %u\n"), + progname, len, dst_len, nextents); + return 1; +} + +int +xlog_print_trans_rui( + char **ptr, + uint src_len, + int continued) +{ + struct xfs_rui_log_format *src_f, *f = NULL; + uint dst_len; + uint nextents; + struct xfs_map_extent *ex; + int i; + int error = 0; + int core_size; + + core_size = offsetof(struct xfs_rui_log_format, rui_extents); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * struct xfs_rui_log_format structure + */ + src_f = malloc(src_len); + if (src_f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + memmove((char*)src_f, *ptr, src_len); + *ptr += src_len; + + /* convert to native format */ + nextents = src_f->rui_nextents; + dst_len = sizeof(struct xfs_rui_log_format) + + (nextents - 1) * sizeof(struct xfs_map_extent); + + if (continued && src_len < core_size) { + printf(_("RUI: Not enough data to decode further\n")); + error = 1; + goto error; + } + + f = malloc(dst_len); + if (f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + if (xfs_rui_copy_format((char *)src_f, src_len, f, continued)) { + error = 1; + goto error; + } + + printf(_("RUI: #regs: %d num_extents: %d id: 0x%llx\n"), + f->rui_size, f->rui_nextents, (unsigned long long)f->rui_id); + + if (continued) { + printf(_("RUI extent data skipped (CONTINUE set, no space)\n")); + goto error; + } + + ex = f->rui_extents; + for (i=0; i < f->rui_nextents; i++) { + printf("(s: 0x%llx, l: %d, own: %lld, off: %llu, f: 0x%x) ", + (unsigned long long)ex->me_startblock, ex->me_len, + (long long)ex->me_owner, + (unsigned long long)ex->me_startoff, ex->me_flags); + printf("\n"); + ex++; + } +error: + free(src_f); + free(f); + return error; +} + +void +xlog_recover_print_rui( + struct xlog_recover_item *item) +{ + char *src_f; + uint src_len; + + src_f = item->ri_buf[0].i_addr; + src_len = item->ri_buf[0].i_len; + + xlog_print_trans_rui(&src_f, src_len, 0); +} + +int +xlog_print_trans_rud( + char **ptr, + uint len) +{ + struct xfs_rud_log_format *f; + struct xfs_rud_log_format lbuf; + + /* size without extents at end */ + uint core_size = sizeof(struct xfs_rud_log_format) - + sizeof(struct xfs_map_extent); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * xfs_efd_log_format_t structure + */ + memmove(&lbuf, *ptr, MIN(core_size, len)); + f = &lbuf; + *ptr += len; + if (len >= core_size) { + printf(_("RUD: #regs: %d num_extents: %d id: 0x%llx\n"), + f->rud_size, f->rud_nextents, + (unsigned long long)f->rud_rui_id); + + /* don't print extents as they are not used */ + + return 0; + } else { + printf(_("RUD: Not enough data to decode further\n")); + return 1; + } +} + +void +xlog_recover_print_rud( + struct xlog_recover_item *item) +{ + char *f; + + f = item->ri_buf[0].i_addr; + xlog_print_trans_rud(&f, sizeof(struct xfs_rud_log_format)); +} diff --git a/logprint/logprint.h b/logprint/logprint.h index 517e852..0c03c08 100644 --- a/logprint/logprint.h +++ b/logprint/logprint.h @@ -51,4 +51,9 @@ extern void xlog_recover_print_efi(xlog_recover_item_t *item); extern int xlog_print_trans_efd(char **ptr, uint len); extern void xlog_recover_print_efd(xlog_recover_item_t *item); +extern int xlog_print_trans_rui(char **ptr, uint src_len, int continued); +extern void xlog_recover_print_rui(struct xlog_recover_item *item); +extern int xlog_print_trans_rud(char **ptr, uint len); +extern void xlog_recover_print_rud(struct xlog_recover_item *item); + #endif /* LOGPRINT_H */ From darrick.wong@oracle.com Thu Jun 16 20:36:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FILL_THIS_FORM_SHORT, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D6D0981EF for ; Thu, 16 Jun 2016 20:36:49 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 61C4AAC001 for ; Thu, 16 Jun 2016 18:36:49 -0700 (PDT) X-ASG-Debug-ID: 1466127405-04bdf01e1396270001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id BU02LTlNu960HGim (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:46 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1afkk005407 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:41 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1afv9006286 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:41 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1aeP9028484; Fri, 17 Jun 2016 01:36:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:39 -0700 Subject: [PATCH 056/145] xfs_repair: use rmap btree data to check block types From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 056/145] xfs_repair: use rmap btree data to check block types To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:36:38 -0700 Message-ID: <146612739837.16048.298748241780582843.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127406 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 16063 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Dave Chinner Use the rmap btree to pre-populate the block type information so that when repair iterates the primary metadata, we can confirm the block type. Ensure that we remove the flag bits from blockcount before using the length field. Signed-off-by: Dave Chinner [darrick.wong@oracle.com: split patch, strip flag bits from blockcount] Signed-off-by: Darrick J. Wong --- repair/dinode.c | 6 + repair/incore.h | 16 +- repair/scan.c | 356 ++++++++++++++++++++++++++++++++++++++++++++++++--- repair/xfs_repair.c | 2 4 files changed, 351 insertions(+), 29 deletions(-) diff --git a/repair/dinode.c b/repair/dinode.c index cbd4305..c1e60ff 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -744,6 +744,7 @@ _("%s fork in ino %" PRIu64 " claims dup extent, " _("%s fork in ino %" PRIu64 " claims free block %" PRIu64 "\n"), forkname, ino, (__uint64_t) b); /* fall through ... */ + case XR_E_INUSE1: /* seen by rmap */ case XR_E_UNKNOWN: set_bmap_ext(agno, agbno, blen, XR_E_INUSE); break; @@ -751,6 +752,11 @@ _("%s fork in ino %" PRIu64 " claims free block %" PRIu64 "\n"), case XR_E_BAD_STATE: do_error(_("bad state in block map %" PRIu64 "\n"), b); + case XR_E_FS_MAP1: + case XR_E_INO1: + case XR_E_INUSE_FS1: + do_warn(_("rmap claims metadata use!\n")); + /* fall through */ case XR_E_FS_MAP: case XR_E_INO: case XR_E_INUSE_FS: diff --git a/repair/incore.h b/repair/incore.h index c92475e..bc0810b 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -102,17 +102,11 @@ typedef struct rt_extent_tree_node { #define XR_E_MULT 5 /* extent is multiply referenced */ #define XR_E_INO 6 /* extent used by inodes (inode blocks) */ #define XR_E_FS_MAP 7 /* extent used by fs space/inode maps */ -#define XR_E_BAD_STATE 8 - -/* extent states, in 64 bit word chunks */ -#define XR_E_UNKNOWN_LL 0x0000000000000000LL -#define XR_E_FREE1_LL 0x1111111111111111LL -#define XR_E_FREE_LL 0x2222222222222222LL -#define XR_E_INUSE_LL 0x3333333333333333LL -#define XR_E_INUSE_FS_LL 0x4444444444444444LL -#define XR_E_MULT_LL 0x5555555555555555LL -#define XR_E_INO_LL 0x6666666666666666LL -#define XR_E_FS_MAP_LL 0x7777777777777777LL +#define XR_E_INUSE1 8 /* used block (marked by rmap btree) */ +#define XR_E_INUSE_FS1 9 /* used by fs ag header or log (rmap btree) */ +#define XR_E_INO1 10 /* used by inodes (marked by rmap btree) */ +#define XR_E_FS_MAP1 11 /* used by fs space/inode maps (rmap btree) */ +#define XR_E_BAD_STATE 12 /* separate state bit, OR'ed into high (4th) bit of ex_state field */ diff --git a/repair/scan.c b/repair/scan.c index 964ff06..eb23685 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -44,6 +44,7 @@ struct aghdr_cnts { __uint32_t agicount; __uint32_t agifreecount; __uint64_t fdblocks; + __uint64_t usedblocks; __uint64_t ifreecount; __uint32_t fibtfreecount; }; @@ -308,6 +309,13 @@ _("bad back (left) sibling pointer (saw %llu should be NULL (0))\n" pthread_mutex_lock(&ag_locks[agno].lock); state = get_bmap(agno, agbno); switch (state) { + case XR_E_INUSE1: + /* + * block was claimed as in use data by the rmap + * btree, but has not been found in the data extent + * map for the inode. That means this bmbt block hasn't + * yet been claimed as in use, which means -it's ours- + */ case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: @@ -764,6 +772,272 @@ ino_issparse( return xfs_inobt_is_sparse_disk(rp, offset); } +static void +scan_rmapbt( + struct xfs_btree_block *block, + int level, + xfs_agblock_t bno, + xfs_agnumber_t agno, + int suspect, + int isroot, + __uint32_t magic, + void *priv) +{ + struct aghdr_cnts *agcnts = priv; + const char *name = "rmap"; + int i; + xfs_rmap_ptr_t *pp; + struct xfs_rmap_rec *rp; + int hdr_errors = 0; + int numrecs; + int state; + xfs_agblock_t lastblock = 0; + int64_t lastowner = 0; + int64_t lastoffset = 0; + + if (magic != XFS_RMAP_CRC_MAGIC) { + name = "(unknown)"; + assert(0); + } + + if (be32_to_cpu(block->bb_magic) != magic) { + do_warn(_("bad magic # %#x in bt%s block %d/%d\n"), + be32_to_cpu(block->bb_magic), name, agno, bno); + hdr_errors++; + if (suspect) + return; + } + + /* + * All RMAP btree blocks except the roots are freed for a + * fully empty filesystem, thus they are counted towards the + * free data block counter. + */ + if (!isroot) { + agcnts->agfbtreeblks++; + agcnts->fdblocks++; + } + + if (be16_to_cpu(block->bb_level) != level) { + do_warn(_("expected level %d got %d in bt%s block %d/%d\n"), + level, be16_to_cpu(block->bb_level), name, agno, bno); + hdr_errors++; + if (suspect) + return; + } + + /* check for btree blocks multiply claimed */ + state = get_bmap(agno, bno); + if (!(state == XR_E_UNKNOWN || state == XR_E_FS_MAP1)) { + set_bmap(agno, bno, XR_E_MULT); + do_warn( +_("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), + name, state, agno, bno, suspect); + return; + } + set_bmap(agno, bno, XR_E_FS_MAP); + + numrecs = be16_to_cpu(block->bb_numrecs); + if (level == 0) { + if (numrecs > mp->m_rmap_mxr[0]) { + numrecs = mp->m_rmap_mxr[0]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_rmap_mnr[0]) { + numrecs = mp->m_rmap_mnr[0]; + hdr_errors++; + } + + if (hdr_errors) { + do_warn( + _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_rmap_mnr[0], mp->m_rmap_mxr[0], + name, agno, bno); + suspect++; + } + + rp = XFS_RMAP_REC_ADDR(block, 1); + for (i = 0; i < numrecs; i++) { + xfs_agblock_t b, end; + xfs_extlen_t len, blen; + int64_t owner, offset; + + b = be32_to_cpu(rp[i].rm_startblock); + len = be32_to_cpu(rp[i].rm_blockcount); + owner = be64_to_cpu(rp[i].rm_owner); + offset = be64_to_cpu(rp[i].rm_offset); + end = b + len; + + /* Make sure agbno & len make sense. */ + if (!verify_agbno(mp, agno, b)) { + do_warn( + _("invalid start block %u in record %u of %s btree block %u/%u\n"), + b, i, name, agno, bno); + continue; + } + if (len == 0 || !verify_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); + continue; + } + + /* Look for impossible owners. */ + if (!(owner > 0 || (owner > XFS_RMAP_OWN_MIN && + owner <= XFS_RMAP_OWN_FS))) + do_warn( + _("invalid owner in rmap btree record %d (%"PRId64" %u) block %u/%u\n"), + i, owner, len, agno, bno); + + /* Check for out of order records. */ + if (i == 0) { +advance: + lastblock = b; + lastowner = owner; + lastoffset = offset; + } else { + bool bad; + + bad = b <= lastblock; + if (bad) + do_warn( + _("out-of-order rmap btree record %d (%u %"PRId64" %"PRIx64" %u) block %u/%u\n"), + i, b, owner, offset, len, agno, bno); + else + goto advance; + } + + /* Check for block owner collisions. */ + for ( ; b < end; b += blen) { + state = get_bmap_ext(agno, b, end, &blen); + switch (state) { + case XR_E_UNKNOWN: + switch (owner) { + case XFS_RMAP_OWN_FS: + case XFS_RMAP_OWN_LOG: + set_bmap(agno, b, XR_E_INUSE_FS1); + break; + case XFS_RMAP_OWN_AG: + case XFS_RMAP_OWN_INOBT: + set_bmap(agno, b, XR_E_FS_MAP1); + break; + case XFS_RMAP_OWN_INODES: + set_bmap(agno, b, XR_E_INO1); + break; + case XFS_RMAP_OWN_NULL: + /* still unknown */ + break; + default: + /* file data */ + set_bmap(agno, b, XR_E_INUSE1); + break; + } + break; + case XR_E_INUSE_FS: + if (owner == XFS_RMAP_OWN_FS || + owner == XFS_RMAP_OWN_LOG) + break; + do_warn( +_("Static meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), + agno, b, b + blen - 1, + name, state, owner); + break; + case XR_E_FS_MAP: + if (owner == XFS_RMAP_OWN_AG || + owner == XFS_RMAP_OWN_INOBT) + break; + do_warn( +_("AG meta block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), + agno, b, b + blen - 1, + name, state, owner); + break; + case XR_E_INO: + if (owner == XFS_RMAP_OWN_INODES) + break; + do_warn( +_("inode block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), + agno, b, b + blen - 1, + name, state, owner); + break; + case XR_E_INUSE: + if (owner >= 0 && + owner < mp->m_sb.sb_dblocks) + break; + do_warn( +_("in use block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), + agno, b, b + blen - 1, + name, state, owner); + break; + case XR_E_FREE1: + case XR_E_FREE: + /* + * May be on the AGFL. If not, they'll + * be caught later. + */ + break; + default: + do_warn( +_("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), + agno, b, b + blen - 1, + name, state, owner); + break; + } + } + } + return; + } + + /* + * interior record + */ + pp = XFS_RMAP_PTR_ADDR(block, 1, mp->m_rmap_mxr[1]); + + if (numrecs > mp->m_rmap_mxr[1]) { + numrecs = mp->m_rmap_mxr[1]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_rmap_mnr[1]) { + numrecs = mp->m_rmap_mnr[1]; + hdr_errors++; + } + + /* + * don't pass bogus tree flag down further if this block + * looked ok. bail out if two levels in a row look bad. + */ + if (hdr_errors) { + do_warn( + _("bad btree nrecs (%u, min=%u, max=%u) in bt%s block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_rmap_mnr[1], mp->m_rmap_mxr[1], + name, agno, bno); + if (suspect) + return; + suspect++; + } else if (suspect) { + suspect = 0; + } + + for (i = 0; i < numrecs; i++) { + xfs_agblock_t bno = be32_to_cpu(pp[i]); + + /* + * XXX - put sibling detection right here. + * we know our sibling chain is good. So as we go, + * we check the entry before and after each entry. + * If either of the entries references a different block, + * check the sibling pointer. If there's a sibling + * pointer mismatch, try and extract as much data + * as possible. + */ + if (bno != 0 && verify_agbno(mp, agno, bno)) { + scan_sbtree(bno, level, agno, suspect, scan_rmapbt, 0, + magic, priv, &xfs_rmapbt_buf_ops); + } + } +} + /* * The following helpers are to help process and validate individual on-disk * inode btree records. We have two possible inode btrees with slightly @@ -976,20 +1250,27 @@ scan_single_ino_chunk( agbno = XFS_AGINO_TO_AGBNO(mp, ino + j); state = get_bmap(agno, agbno); - if (state == XR_E_UNKNOWN) { - set_bmap(agno, agbno, XR_E_INO); - } else if (state == XR_E_INUSE_FS && agno == 0 && - ino + j >= first_prealloc_ino && - ino + j < last_prealloc_ino) { + switch (state) { + case XR_E_INO: + break; + case XR_E_UNKNOWN: + case XR_E_INO1: /* seen by rmap */ set_bmap(agno, agbno, XR_E_INO); - } else { + break; + case XR_E_INUSE_FS: + case XR_E_INUSE_FS1: + if (agno == 0 && + ino + j >= first_prealloc_ino && + ino + j < last_prealloc_ino) { + set_bmap(agno, agbno, XR_E_INO); + break; + } + /* fall through */ + default: + /* XXX - maybe should mark block a duplicate */ do_warn( _("inode chunk claims used block, inobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); - /* - * XXX - maybe should mark - * block a duplicate - */ return ++suspect; } } @@ -1099,19 +1380,35 @@ _("sparse inode chunk claims inode block, finobt block - agno %d, bno %d, inopb continue; } - if (state == XR_E_INO) { - continue; - } else if ((state == XR_E_UNKNOWN) || - (state == XR_E_INUSE_FS && agno == 0 && - ino + j >= first_prealloc_ino && - ino + j < last_prealloc_ino)) { + switch (state) { + case XR_E_INO: + break; + case XR_E_INO1: /* seen by rmap */ + set_bmap(agno, agbno, XR_E_INO); + break; + case XR_E_UNKNOWN: do_warn( _("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); set_bmap(agno, agbno, XR_E_INO); suspect++; - } else { + break; + case XR_E_INUSE_FS: + case XR_E_INUSE_FS1: + if (agno == 0 && + ino + j >= first_prealloc_ino && + ino + j < last_prealloc_ino) { + do_warn( +_("inode chunk claims untracked block, finobt block - agno %d, bno %d, inopb %d\n"), + agno, agbno, mp->m_sb.sb_inopblock); + + set_bmap(agno, agbno, XR_E_INO); + suspect++; + break; + } + /* fall through */ + default: do_warn( _("inode chunk claims used block, finobt block - agno %d, bno %d, inopb %d\n"), agno, agbno, mp->m_sb.sb_inopblock); @@ -1280,6 +1577,7 @@ scan_inobt( */ state = get_bmap(agno, bno); switch (state) { + case XR_E_FS_MAP1: /* already been seen by an rmap scan */ case XR_E_UNKNOWN: case XR_E_FREE1: case XR_E_FREE: @@ -1420,7 +1718,7 @@ scan_freelist( if (XFS_SB_BLOCK(mp) != XFS_AGFL_BLOCK(mp) && XFS_AGF_BLOCK(mp) != XFS_AGFL_BLOCK(mp) && XFS_AGI_BLOCK(mp) != XFS_AGFL_BLOCK(mp)) - set_bmap(agno, XFS_AGFL_BLOCK(mp), XR_E_FS_MAP); + set_bmap(agno, XFS_AGFL_BLOCK(mp), XR_E_INUSE_FS); if (be32_to_cpu(agf->agf_flcount) == 0) return; @@ -1505,6 +1803,19 @@ validate_agf( bno, agno); } + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); + if (bno != 0 && verify_agbno(mp, agno, bno)) { + scan_sbtree(bno, + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]), + agno, 0, scan_rmapbt, 1, XFS_RMAP_CRC_MAGIC, + agcnts, &xfs_rmapbt_buf_ops); + } else { + do_warn(_("bad agbno %u for rmapbt root, agno %d\n"), + bno, agno); + } + } + if (be32_to_cpu(agf->agf_freeblks) != agcnts->agffreeblks) { do_warn(_("agf_freeblks %u, counted %u in ag %u\n"), be32_to_cpu(agf->agf_freeblks), agcnts->agffreeblks, agno); @@ -1520,6 +1831,7 @@ validate_agf( do_warn(_("agf_btreeblks %u, counted %" PRIu64 " in ag %u\n"), be32_to_cpu(agf->agf_btreeblks), agcnts->agfbtreeblks, agno); } + } static void @@ -1759,6 +2071,7 @@ scan_ags( __uint64_t fdblocks = 0; __uint64_t icount = 0; __uint64_t ifreecount = 0; + __uint64_t usedblocks = 0; xfs_agnumber_t i; work_queue_t wq; @@ -1781,6 +2094,7 @@ scan_ags( fdblocks += agcnts[i].fdblocks; icount += agcnts[i].agicount; ifreecount += agcnts[i].ifreecount; + usedblocks += agcnts[i].usedblocks; } free(agcnts); @@ -1802,4 +2116,10 @@ scan_ags( do_warn(_("sb_fdblocks %" PRIu64 ", counted %" PRIu64 "\n"), mp->m_sb.sb_fdblocks, fdblocks); } + + if (usedblocks && + usedblocks != mp->m_sb.sb_dblocks - fdblocks) { + do_warn(_("used blocks %" PRIu64 ", counted %" PRIu64 "\n"), + mp->m_sb.sb_dblocks - fdblocks, usedblocks); + } } diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 9d91f2d..709c0c3 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -417,6 +417,8 @@ calc_mkfs(xfs_mount_t *mp) fino_bno = inobt_root + (2 * min(2, mp->m_ag_maxlevels)) + 1; if (xfs_sb_version_hasfinobt(&mp->m_sb)) fino_bno++; + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + fino_bno++; /* * If the log is allocated in the first allocation group we need to From darrick.wong@oracle.com Thu Jun 16 20:36:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9F4B481BA for ; Thu, 16 Jun 2016 20:36:55 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 633E48F804B for ; Thu, 16 Jun 2016 18:36:55 -0700 (PDT) X-ASG-Debug-ID: 1466127413-04cb6c542557fe0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id uImDyEgrKaLK1vQc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:54 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1anwe005473 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:36:50 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1amFp032072 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:49 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1akDG011236; Fri, 17 Jun 2016 01:36:47 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:46 -0700 Subject: [PATCH 057/145] xfs_repair: fix fino_bno calculation when rmapbt is enabled From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 057/145] xfs_repair: fix fino_bno calculation when rmapbt is enabled To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:44 -0700 Message-ID: <146612740486.16048.16298066777909039562.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127414 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1042 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines In xfs_repair, we calculate where we think mkfs put the root inode block. However, the rmapbt component doesn't account for the fact that mkfs reserved 2 AGFL blocks for the rmapbt, so its calculation is off by a bit. This leads to it complaining (incorrectly) about the root inode block being in the wrong place and blowing up. Signed-off-by: Darrick J. Wong --- repair/xfs_repair.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 709c0c3..3b63754 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -417,8 +417,10 @@ calc_mkfs(xfs_mount_t *mp) fino_bno = inobt_root + (2 * min(2, mp->m_ag_maxlevels)) + 1; if (xfs_sb_version_hasfinobt(&mp->m_sb)) fino_bno++; - if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + fino_bno += min(2, mp->m_rmap_maxlevels); fino_bno++; + } /* * If the log is allocated in the first allocation group we need to From darrick.wong@oracle.com Thu Jun 16 20:37:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1B4EB8201 for ; Thu, 16 Jun 2016 20:37:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 78399AC001 for ; Thu, 16 Jun 2016 18:37:02 -0700 (PDT) X-ASG-Debug-ID: 1466127419-04cbb01fee6a210001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id nv04VHDhzHuGZ57v (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:36:59 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1asSD005549 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:54 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1arw7001819 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:36:54 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1aqIQ023466; Fri, 17 Jun 2016 01:36:53 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:52 -0700 Subject: [PATCH 058/145] xfs_repair: create a slab API for allocating arrays in large chunks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 058/145] xfs_repair: create a slab API for allocating arrays in large chunks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:51 -0700 Message-ID: <146612741099.16048.10004724516227132773.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127419 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14676 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a slab-based array and a bag-of-pointers data structure to facilitate rapid linear scans of reverse-mapping data for later reconstruction of the refcount and rmap btrees. Signed-off-by: Darrick J. Wong --- repair/Makefile | 4 repair/slab.c | 456 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/slab.h | 60 +++++++ 3 files changed, 518 insertions(+), 2 deletions(-) create mode 100644 repair/slab.c create mode 100644 repair/slab.h diff --git a/repair/Makefile b/repair/Makefile index 251722b..756ba95 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -11,13 +11,13 @@ LTCOMMAND = xfs_repair HFILES = agheader.h attr_repair.h avl.h avl64.h bmap.h btree.h \ da_util.h dinode.h dir2.h err_protos.h globals.h incore.h protos.h \ - rt.h progress.h scan.h versions.h prefetch.h threads.h + rt.h progress.h scan.h versions.h prefetch.h slab.h threads.h CFILES = agheader.c attr_repair.c avl.c avl64.c bmap.c btree.c \ da_util.c dino_chunks.c dinode.c dir2.c globals.c incore.c \ incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c \ - progress.c prefetch.c rt.c sb.c scan.c threads.c \ + progress.c prefetch.c rt.c sb.c scan.c slab.c threads.c \ versions.c xfs_repair.c LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) diff --git a/repair/slab.c b/repair/slab.c new file mode 100644 index 0000000..97c13d3 --- /dev/null +++ b/repair/slab.c @@ -0,0 +1,456 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include "slab.h" + +#undef SLAB_DEBUG + +#ifdef SLAB_DEBUG +# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0) +#else +# define dbg_printf(f, a...) +#endif + +/* + * Slab Arrays and Bags + * + * The slab array is a dynamically growable linear array. Internally it + * maintains a list of slabs of increasing size; when a slab fills up, another + * is allocated. Each slab is sorted individually, which means that one must + * use an iterator to walk the entire logical array, sorted order or otherwise. + * Array items can neither be removed nor accessed randomly, since (at the + * moment) the only user of them (storing reverse mappings) doesn't need either + * piece. Pointers are not stable across sort operations. + * + * A bag is a collection of pointers. The bag can be added to or removed from + * arbitrarily, and the bag items can be iterated. Bags are used to process + * rmaps into refcount btree entries. + */ + +/* + * Slabs -- each slab_hdr holds an array of items; when a slab_hdr fills up, we + * allocate a new one and add to that one. The slab object coordinates the + * slab_hdrs. + */ + +/* Each slab holds at least 4096 items */ +#define MIN_SLAB_NR 4096 +/* and cannot be larger than 128M */ +#define MAX_SLAB_SIZE (128 * 1048576) +struct xfs_slab_hdr { + size_t sh_nr; + size_t sh_inuse; /* items in use */ + struct xfs_slab_hdr *sh_next; /* next slab hdr */ + /* objects follow */ +}; + +struct xfs_slab { + size_t s_item_sz; /* item size */ + size_t s_nr_slabs; /* # of slabs */ + size_t s_nr_items; /* # of items */ + struct xfs_slab_hdr *s_first; /* first slab header */ + struct xfs_slab_hdr *s_last; /* last sh_next pointer */ +}; + +/* + * Slab cursors -- each slab_hdr_cursor tracks a slab_hdr; the slab_cursor + * tracks the slab_hdr_cursors. If a compare_fn is specified, the cursor + * returns objects in increasing order (if you've previously sorted the + * slabs with qsort_slab()). If compare_fn == NULL, it returns slab items + * in order. + */ +struct xfs_slab_hdr_cursor { + struct xfs_slab_hdr *hdr; /* a slab header */ + size_t loc; /* where we are in the slab */ +}; + +typedef int (*xfs_slab_compare_fn)(const void *, const void *); + +struct xfs_slab_cursor { + size_t nr; /* # of per-slab cursors */ + struct xfs_slab *slab; /* pointer to the slab */ + struct xfs_slab_hdr_cursor *last_hcur; /* last header we took from */ + xfs_slab_compare_fn compare_fn; /* compare items */ + struct xfs_slab_hdr_cursor hcur[0]; /* per-slab cursors */ +}; + +/* + * Bags -- each bag is an array of pointers items; when a bag fills up, we + * resize it. + */ +#define MIN_BAG_SIZE 4096 +struct xfs_bag { + size_t bg_nr; /* number of pointers */ + size_t bg_inuse; /* number of slots in use */ + void **bg_ptrs; /* pointers */ +}; +#define BAG_SIZE(nr) (sizeof(struct xfs_bag) + ((nr) * sizeof(void *))) +#define BAG_END(bag) (&(bag)->bg_ptrs[(bag)->bg_nr]) + +/* + * Create a slab to hold some objects of a particular size. + */ +int +init_slab( + struct xfs_slab **slab, + size_t item_size) +{ + struct xfs_slab *ptr; + + ptr = calloc(1, sizeof(struct xfs_slab)); + if (!ptr) + return -ENOMEM; + ptr->s_item_sz = item_size; + ptr->s_last = NULL; + *slab = ptr; + + return 0; +} + +/* + * Frees a slab. + */ +void +free_slab( + struct xfs_slab **slab) +{ + struct xfs_slab *ptr; + struct xfs_slab_hdr *hdr; + struct xfs_slab_hdr *nhdr; + + ptr = *slab; + if (!ptr) + return; + hdr = ptr->s_first; + while (hdr) { + nhdr = hdr->sh_next; + free(hdr); + hdr = nhdr; + } + free(ptr); + *slab = NULL; +} + +static void * +slab_ptr( + struct xfs_slab *slab, + struct xfs_slab_hdr *hdr, + size_t idx) +{ + char *p; + + ASSERT(idx < hdr->sh_inuse); + p = (char *)(hdr + 1); + p += slab->s_item_sz * idx; + return p; +} + +/* + * Add an item to the slab. + */ +int +slab_add( + struct xfs_slab *slab, + void *item) +{ + struct xfs_slab_hdr *hdr; + void *p; + + hdr = slab->s_last; + if (!hdr || hdr->sh_inuse == hdr->sh_nr) { + size_t n; + + n = (hdr ? hdr->sh_nr * 2 : MIN_SLAB_NR); + if (n * slab->s_item_sz > MAX_SLAB_SIZE) + n = MAX_SLAB_SIZE / slab->s_item_sz; + hdr = malloc(sizeof(struct xfs_slab_hdr) + (n * slab->s_item_sz)); + if (!hdr) + return -ENOMEM; + hdr->sh_nr = n; + hdr->sh_inuse = 0; + hdr->sh_next = NULL; + if (slab->s_last) + slab->s_last->sh_next = hdr; + if (!slab->s_first) + slab->s_first = hdr; + slab->s_last = hdr; + slab->s_nr_slabs++; + } + hdr->sh_inuse++; + p = slab_ptr(slab, hdr, hdr->sh_inuse - 1); + memcpy(p, item, slab->s_item_sz); + slab->s_nr_items++; + + return 0; +} + +/* + * Sort the items in the slab. Do not run this method if there are any + * cursors holding on to the slab. + */ +void +qsort_slab( + struct xfs_slab *slab, + int (*compare_fn)(const void *, const void *)) +{ + struct xfs_slab_hdr *hdr; + + hdr = slab->s_first; + while (hdr) { + qsort(slab_ptr(slab, hdr, 0), hdr->sh_inuse, slab->s_item_sz, + compare_fn); + hdr = hdr->sh_next; + } +} + +/* + * init_slab_cursor() -- Create a slab cursor to iterate the slab items. + * + * @slab: The slab. + * @compare_fn: If specified, use this function to return items in ascending order. + * @cur: The new cursor. + */ +int +init_slab_cursor( + struct xfs_slab *slab, + int (*compare_fn)(const void *, const void *), + struct xfs_slab_cursor **cur) +{ + struct xfs_slab_cursor *c; + struct xfs_slab_hdr_cursor *hcur; + struct xfs_slab_hdr *hdr; + + c = malloc(sizeof(struct xfs_slab_cursor) + + (sizeof(struct xfs_slab_hdr_cursor) * slab->s_nr_slabs)); + if (!c) + return -ENOMEM; + c->nr = slab->s_nr_slabs; + c->slab = slab; + c->compare_fn = compare_fn; + c->last_hcur = NULL; + hcur = (struct xfs_slab_hdr_cursor *)(c + 1); + hdr = slab->s_first; + while (hdr) { + hcur->hdr = hdr; + hcur->loc = 0; + hcur++; + hdr = hdr->sh_next; + } + *cur = c; + return 0; +} + +/* + * Free the slab cursor. + */ +void +free_slab_cursor( + struct xfs_slab_cursor **cur) +{ + if (!*cur) + return; + free(*cur); + *cur = NULL; +} + +/* + * Return the smallest item in the slab, without advancing the iterator. + * The slabs must be sorted prior to the creation of the cursor. + */ +void * +peek_slab_cursor( + struct xfs_slab_cursor *cur) +{ + struct xfs_slab_hdr_cursor *hcur; + void *p = NULL; + void *q; + size_t i; + + cur->last_hcur = NULL; + + /* no compare function; inorder traversal */ + if (!cur->compare_fn) { + if (!cur->last_hcur) + cur->last_hcur = &cur->hcur[0]; + hcur = cur->last_hcur; + while (hcur < &cur->hcur[cur->nr] && + hcur->loc >= hcur->hdr->sh_inuse) + hcur++; + if (hcur == &cur->hcur[cur->nr]) + return NULL; + p = slab_ptr(cur->slab, hcur->hdr, hcur->loc); + cur->last_hcur = hcur; + return p; + } + + /* otherwise return things in increasing order */ + for (i = 0, hcur = &cur->hcur[i]; i < cur->nr; i++, hcur++) { + if (hcur->loc >= hcur->hdr->sh_inuse) + continue; + q = slab_ptr(cur->slab, hcur->hdr, hcur->loc); + if (!p || cur->compare_fn(p, q) > 0) { + p = q; + cur->last_hcur = hcur; + } + } + + return p; +} + +/* + * After a peek operation, advance the cursor. + */ +void +advance_slab_cursor( + struct xfs_slab_cursor *cur) +{ + ASSERT(cur->last_hcur); + cur->last_hcur->loc++; +} + +/* + * Retrieve the next item in the slab and advance the cursor. + */ +void * +pop_slab_cursor( + struct xfs_slab_cursor *cur) +{ + void *p; + + p = peek_slab_cursor(cur); + if (p) + advance_slab_cursor(cur); + return p; +} + +/* + * Return the number of items in the slab. + */ +size_t +slab_count( + struct xfs_slab *slab) +{ + return slab->s_nr_items; +} + +/* + * Create a bag to point to some objects. + */ +int +init_bag( + struct xfs_bag **bag) +{ + struct xfs_bag *ptr; + + ptr = calloc(1, sizeof(struct xfs_bag)); + if (!ptr) + return -ENOMEM; + ptr->bg_ptrs = calloc(MIN_BAG_SIZE, sizeof(void *)); + if (!ptr->bg_ptrs) { + free(ptr); + return -ENOMEM; + } + ptr->bg_nr = MIN_BAG_SIZE; + *bag = ptr; + return 0; +} + +/* + * Free a bag of pointers. + */ +void +free_bag( + struct xfs_bag **bag) +{ + struct xfs_bag *ptr; + + ptr = *bag; + if (!ptr) + return; + free(ptr->bg_ptrs); + free(ptr); + *bag = NULL; +} + +/* + * Add an object to the pointer bag. + */ +int +bag_add( + struct xfs_bag *bag, + void *ptr) +{ + void **p, **x; + + p = &bag->bg_ptrs[bag->bg_inuse]; + if (p == BAG_END(bag)) { + /* No free space, alloc more pointers */ + size_t nr; + + nr = bag->bg_nr * 2; + x = realloc(bag->bg_ptrs, nr * sizeof(void *)); + if (!x) + return -ENOMEM; + bag->bg_ptrs = x; + memset(BAG_END(bag), 0, bag->bg_nr * sizeof(void *)); + bag->bg_nr = nr; + } + bag->bg_ptrs[bag->bg_inuse] = ptr; + bag->bg_inuse++; + return 0; +} + +/* + * Remove a pointer from a bag. + */ +int +bag_remove( + struct xfs_bag *bag, + size_t nr) +{ + ASSERT(nr < bag->bg_inuse); + memmove(&bag->bg_ptrs[nr], &bag->bg_ptrs[nr + 1], + (bag->bg_inuse - nr) * sizeof(void *)); + bag->bg_inuse--; + return 0; +} + +/* + * Return the number of items in a bag. + */ +size_t +bag_count( + struct xfs_bag *bag) +{ + return bag->bg_inuse; +} + +/* + * Return the nth item in a bag. + */ +void * +bag_item( + struct xfs_bag *bag, + size_t nr) +{ + if (nr >= bag->bg_inuse) + return NULL; + return bag->bg_ptrs[nr]; +} diff --git a/repair/slab.h b/repair/slab.h new file mode 100644 index 0000000..4aa5512 --- /dev/null +++ b/repair/slab.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef SLAB_H_ +#define SLAB_H_ + +struct xfs_slab; +struct xfs_slab_cursor; + +extern int init_slab(struct xfs_slab **, size_t); +extern void free_slab(struct xfs_slab **); + +extern int slab_add(struct xfs_slab *, void *); +extern void qsort_slab(struct xfs_slab *, int (*)(const void *, const void *)); +extern size_t slab_count(struct xfs_slab *); + +extern int init_slab_cursor(struct xfs_slab *, + int (*)(const void *, const void *), struct xfs_slab_cursor **); +extern void free_slab_cursor(struct xfs_slab_cursor **); + +extern void *peek_slab_cursor(struct xfs_slab_cursor *); +extern void advance_slab_cursor(struct xfs_slab_cursor *); +extern void *pop_slab_cursor(struct xfs_slab_cursor *); + +struct xfs_bag; + +extern int init_bag(struct xfs_bag **); +extern void free_bag(struct xfs_bag **); +extern int bag_add(struct xfs_bag *, void *); +extern int bag_remove(struct xfs_bag *, size_t); +extern size_t bag_count(struct xfs_bag *); +extern void *bag_item(struct xfs_bag *, size_t); + +#define foreach_bag_ptr(bag, idx, ptr) \ + for ((idx) = 0, (ptr) = bag_item((bag), (idx)); \ + (idx) < bag_count(bag); \ + (idx)++, (ptr) = bag_item((bag), (idx))) + +#define foreach_bag_ptr_reverse(bag, idx, ptr) \ + for ((idx) = bag_count(bag) - 1, (ptr) = bag_item((bag), (idx)); \ + (idx) >= 0 && (ptr) != NULL; \ + (idx)--, (ptr) = bag_item((bag), (idx))) + +#endif /* SLAB_H_ */ From darrick.wong@oracle.com Thu Jun 16 20:37:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A62A4820A for ; Thu, 16 Jun 2016 20:37:07 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 670BD8F804C for ; Thu, 16 Jun 2016 18:37:07 -0700 (PDT) X-ASG-Debug-ID: 1466127424-04bdf01e17962b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id mI65Ot2MiscU8qxL (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1b0fJ005646 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:00 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1axrC026775 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:00 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1awpR028521; Fri, 17 Jun 2016 01:36:59 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:36:58 -0700 Subject: [PATCH 059/145] xfs_repair: collect reverse-mapping data for refcount/rmap tree rebuilding From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 059/145] xfs_repair: collect reverse-mapping data for refcount/rmap tree rebuilding To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:36:57 -0700 Message-ID: <146612741720.16048.10495862880874161170.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127424 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9888 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Collect reverse-mapping data for the entire filesystem so that we can later check and rebuild the reference count tree and the reverse mapping tree. Signed-off-by: Darrick J. Wong --- repair/Makefile | 4 + repair/dinode.c | 9 ++ repair/phase4.c | 5 + repair/rmap.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 32 +++++++++ repair/xfs_repair.c | 4 + 6 files changed, 243 insertions(+), 2 deletions(-) create mode 100644 repair/rmap.c create mode 100644 repair/rmap.h diff --git a/repair/Makefile b/repair/Makefile index 756ba95..81c2b9f 100644 --- a/repair/Makefile +++ b/repair/Makefile @@ -11,13 +11,13 @@ LTCOMMAND = xfs_repair HFILES = agheader.h attr_repair.h avl.h avl64.h bmap.h btree.h \ da_util.h dinode.h dir2.h err_protos.h globals.h incore.h protos.h \ - rt.h progress.h scan.h versions.h prefetch.h slab.h threads.h + rt.h progress.h scan.h versions.h prefetch.h rmap.h slab.h threads.h CFILES = agheader.c attr_repair.c avl.c avl64.c bmap.c btree.c \ da_util.c dino_chunks.c dinode.c dir2.c globals.c incore.c \ incore_bmc.c init.c incore_ext.c incore_ino.c phase1.c \ phase2.c phase3.c phase4.c phase5.c phase6.c phase7.c \ - progress.c prefetch.c rt.c sb.c scan.c slab.c threads.c \ + progress.c prefetch.c rmap.c rt.c sb.c scan.c slab.c threads.c \ versions.c xfs_repair.c LLDLIBS = $(LIBXFS) $(LIBXLOG) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) diff --git a/repair/dinode.c b/repair/dinode.c index c1e60ff..89163b1 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -30,6 +30,8 @@ #include "attr_repair.h" #include "bmap.h" #include "threads.h" +#include "slab.h" +#include "rmap.h" /* * gettext lookups for translations of strings use mutexes internally to @@ -779,6 +781,13 @@ _("illegal state %d in block map %" PRIu64 "\n"), state, b); } } + if (collect_rmaps) { /* && !check_dups */ + error = add_rmap(mp, ino, whichfork, &irec); + if (error) + do_error( +_("couldn't add reverse mapping\n") + ); + } *tot += irec.br_blockcount; } error = 0; diff --git a/repair/phase4.c b/repair/phase4.c index 1a7d7b5..b4264df 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -30,7 +30,10 @@ #include "versions.h" #include "dir2.h" #include "progress.h" +#include "slab.h" +#include "rmap.h" +bool collect_rmaps; /* * null out quota inode fields in sb if they point to non-existent inodes. @@ -170,6 +173,8 @@ phase4(xfs_mount_t *mp) int ag_hdr_block; int bstate; + if (needs_rmap_work(mp)) + collect_rmaps = true; ag_hdr_block = howmany(ag_hdr_len, mp->m_sb.sb_blocksize); do_log(_("Phase 4 - check for duplicate blocks...\n")); diff --git a/repair/rmap.c b/repair/rmap.c new file mode 100644 index 0000000..e78115e --- /dev/null +++ b/repair/rmap.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include "btree.h" +#include "err_protos.h" +#include "libxlog.h" +#include "incore.h" +#include "globals.h" +#include "dinode.h" +#include "slab.h" +#include "rmap.h" + +#undef RMAP_DEBUG + +#ifdef RMAP_DEBUG +# define dbg_printf(f, a...) do {printf(f, ## a); fflush(stdout); } while (0) +#else +# define dbg_printf(f, a...) +#endif + +/* per-AG rmap object anchor */ +struct xfs_ag_rmap { + struct xfs_slab *ar_rmaps; /* rmap observations, p4 */ +}; + +static struct xfs_ag_rmap *ag_rmaps; + +/* + * Compare rmap observations for array sorting. + */ +static int +rmap_compare( + const void *a, + const void *b) +{ + const struct xfs_rmap_irec *pa; + const struct xfs_rmap_irec *pb; + __u64 oa; + __u64 ob; + + pa = a; pb = b; + oa = xfs_rmap_irec_offset_pack(pa); + ob = xfs_rmap_irec_offset_pack(pb); + + if (pa->rm_startblock < pb->rm_startblock) + return -1; + else if (pa->rm_startblock > pb->rm_startblock) + return 1; + else if (pa->rm_owner < pb->rm_owner) + return -1; + else if (pa->rm_owner > pb->rm_owner) + return 1; + else if (oa < ob) + return -1; + else if (oa > ob) + return 1; + else + return 0; +} + +/* + * Returns true if we must reconstruct either the reference count or reverse + * mapping trees. + */ +bool +needs_rmap_work( + struct xfs_mount *mp) +{ + return xfs_sb_version_hasrmapbt(&mp->m_sb); +} + +/* + * Initialize per-AG reverse map data. + */ +void +init_rmaps( + struct xfs_mount *mp) +{ + xfs_agnumber_t i; + int error; + + if (!needs_rmap_work(mp)) + return; + + ag_rmaps = calloc(mp->m_sb.sb_agcount, sizeof(struct xfs_ag_rmap)); + if (!ag_rmaps) + do_error(_("couldn't allocate per-AG reverse map roots\n")); + + for (i = 0; i < mp->m_sb.sb_agcount; i++) { + error = init_slab(&ag_rmaps[i].ar_rmaps, + sizeof(struct xfs_rmap_irec)); + if (error) + do_error( +_("Insufficient memory while allocating reverse mapping slabs.")); + } +} + +/* + * Free the per-AG reverse-mapping data. + */ +void +free_rmaps( + struct xfs_mount *mp) +{ + xfs_agnumber_t i; + + if (!needs_rmap_work(mp)) + return; + + for (i = 0; i < mp->m_sb.sb_agcount; i++) + free_slab(&ag_rmaps[i].ar_rmaps); + free(ag_rmaps); + ag_rmaps = NULL; +} + +/* + * Add an observation about a block mapping in an inode's data or attribute + * fork for later btree reconstruction. + */ +int +add_rmap( + struct xfs_mount *mp, + xfs_ino_t ino, + int whichfork, + struct xfs_bmbt_irec *irec) +{ + struct xfs_slab *rmaps; + struct xfs_rmap_irec rmap; + xfs_agnumber_t agno; + xfs_agblock_t agbno; + + if (!needs_rmap_work(mp)) + return 0; + + agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock); + agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock); + ASSERT(agno != NULLAGNUMBER); + ASSERT(agno < mp->m_sb.sb_agcount); + ASSERT(agbno + irec->br_blockcount <= mp->m_sb.sb_agblocks); + ASSERT(ino != NULLFSINO); + ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK); + + rmaps = ag_rmaps[agno].ar_rmaps; + rmap.rm_owner = ino; + rmap.rm_offset = irec->br_startoff; + rmap.rm_flags = 0; + if (whichfork == XFS_ATTR_FORK) + rmap.rm_flags |= XFS_RMAP_ATTR_FORK; + rmap.rm_startblock = agbno; + rmap.rm_blockcount = irec->br_blockcount; + if (irec->br_state == XFS_EXT_UNWRITTEN) + rmap.rm_flags |= XFS_RMAP_UNWRITTEN; + return slab_add(rmaps, &rmap); +} + +#ifdef RMAP_DEBUG +static void +dump_rmap( + const char *msg, + xfs_agnumber_t agno, + struct xfs_rmap_irec *rmap) +{ + printf("%s: %p agno=%u pblk=%llu own=%lld lblk=%llu len=%u flags=0x%x\n", + msg, rmap, + (unsigned int)agno, + (unsigned long long)rmap->rm_startblock, + (unsigned long long)rmap->rm_owner, + (unsigned long long)rmap->rm_offset, + (unsigned int)rmap->rm_blockcount, + (unsigned int)rmap->rm_flags); +} +#else +# define dump_rmap(m, a, r) +#endif diff --git a/repair/rmap.h b/repair/rmap.h new file mode 100644 index 0000000..0832790 --- /dev/null +++ b/repair/rmap.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef RMAP_H_ +#define RMAP_H_ + +extern bool collect_rmaps; + +extern bool needs_rmap_work(struct xfs_mount *); + +extern void init_rmaps(struct xfs_mount *); +extern void free_rmaps(struct xfs_mount *); + +extern int add_rmap(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *); + +#endif /* RMAP_H_ */ diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 3b63754..2ecd81d 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -32,6 +32,8 @@ #include "threads.h" #include "progress.h" #include "dinode.h" +#include "slab.h" +#include "rmap.h" #define rounddown(x, y) (((x)/(y))*(y)) @@ -898,6 +900,7 @@ main(int argc, char **argv) init_bmaps(mp); incore_ino_init(mp); incore_ext_init(mp); + init_rmaps(mp); /* initialize random globals now that we know the fs geometry */ inodes_per_block = mp->m_sb.sb_inopblock; @@ -931,6 +934,7 @@ main(int argc, char **argv) /* * Done with the block usage maps, toss them... */ + free_rmaps(mp); free_bmaps(mp); if (!bad_ino_btree) { From darrick.wong@oracle.com Thu Jun 16 20:37:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6DA2281C7 for ; Thu, 16 Jun 2016 20:37:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3D55C304048 for ; Thu, 16 Jun 2016 18:37:13 -0700 (PDT) X-ASG-Debug-ID: 1466127430-04cb6c542558000001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 5egZY8jLDAwZBB5D (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1b6cL018504 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:06 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1b5fd027060 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:06 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1b5wl023571; Fri, 17 Jun 2016 01:37:05 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:04 -0700 Subject: [PATCH 060/145] xfs_repair: record and merge raw rmap data From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 060/145] xfs_repair: record and merge raw rmap data To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:03 -0700 Message-ID: <146612742343.16048.8981147515226574112.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127430 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5466 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since we still allow merging of BMBT block, AG metadata, and AG btree block rmaps, provide a facility to collect these raw observations and merge them (with maximal length) into the main rmap list. Signed-off-by: Darrick J. Wong --- repair/rmap.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 4 ++ 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/repair/rmap.c b/repair/rmap.c index e78115e..1851742 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -38,6 +38,7 @@ /* per-AG rmap object anchor */ struct xfs_ag_rmap { struct xfs_slab *ar_rmaps; /* rmap observations, p4 */ + struct xfs_slab *ar_raw_rmaps; /* unmerged rmaps */ }; static struct xfs_ag_rmap *ag_rmaps; @@ -109,6 +110,11 @@ init_rmaps( if (error) do_error( _("Insufficient memory while allocating reverse mapping slabs.")); + error = init_slab(&ag_rmaps[i].ar_raw_rmaps, + sizeof(struct xfs_rmap_irec)); + if (error) + do_error( +_("Insufficient memory while allocating raw metadata reverse mapping slabs.")); } } @@ -124,13 +130,40 @@ free_rmaps( if (!needs_rmap_work(mp)) return; - for (i = 0; i < mp->m_sb.sb_agcount; i++) + for (i = 0; i < mp->m_sb.sb_agcount; i++) { free_slab(&ag_rmaps[i].ar_rmaps); + free_slab(&ag_rmaps[i].ar_raw_rmaps); + } free(ag_rmaps); ag_rmaps = NULL; } /* + * Decide if two reverse-mapping records can be merged. + */ +bool +mergeable_rmaps( + struct xfs_rmap_irec *r1, + struct xfs_rmap_irec *r2) +{ + if (r1->rm_owner != r2->rm_owner) + return false; + if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock) + return false; + if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount > + XFS_RMAP_LEN_MAX) + return false; + if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner)) + return true; + /* must be an inode owner below here */ + if (r1->rm_flags != r2->rm_flags) + return false; + if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK) + return true; + return r1->rm_offset + r1->rm_blockcount == r2->rm_offset; +} + +/* * Add an observation about a block mapping in an inode's data or attribute * fork for later btree reconstruction. */ @@ -170,6 +203,108 @@ add_rmap( return slab_add(rmaps, &rmap); } +/* add a raw rmap; these will be merged later */ +static int +__add_raw_rmap( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + xfs_extlen_t len, + uint64_t owner, + bool is_attr, + bool is_bmbt) +{ + struct xfs_rmap_irec rmap; + + ASSERT(len != 0); + rmap.rm_owner = owner; + rmap.rm_offset = 0; + rmap.rm_flags = 0; + if (is_attr) + rmap.rm_flags |= XFS_RMAP_ATTR_FORK; + if (is_bmbt) + rmap.rm_flags |= XFS_RMAP_BMBT_BLOCK; + rmap.rm_startblock = agbno; + rmap.rm_blockcount = len; + return slab_add(ag_rmaps[agno].ar_raw_rmaps, &rmap); +} + +/* + * Add a reverse mapping for a per-AG fixed metadata extent. + */ +int +add_ag_rmap( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + xfs_extlen_t len, + uint64_t owner) +{ + if (!needs_rmap_work(mp)) + return 0; + + ASSERT(agno != NULLAGNUMBER); + ASSERT(agno < mp->m_sb.sb_agcount); + ASSERT(agbno + len <= mp->m_sb.sb_agblocks); + + return __add_raw_rmap(mp, agno, agbno, len, owner, false, false); +} + +/* + * Merge adjacent raw rmaps and add them to the main rmap list. + */ +int +fold_raw_rmaps( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_slab_cursor *cur = NULL; + struct xfs_rmap_irec *prev, *rec; + size_t old_sz; + int error; + + old_sz = slab_count(ag_rmaps[agno].ar_rmaps); + if (slab_count(ag_rmaps[agno].ar_raw_rmaps) == 0) + goto no_raw; + qsort_slab(ag_rmaps[agno].ar_raw_rmaps, rmap_compare); + error = init_slab_cursor(ag_rmaps[agno].ar_raw_rmaps, rmap_compare, + &cur); + if (error) + goto err; + + prev = pop_slab_cursor(cur); + rec = pop_slab_cursor(cur); + while (rec) { + if (mergeable_rmaps(prev, rec)) { + prev->rm_blockcount += rec->rm_blockcount; + rec = pop_slab_cursor(cur); + continue; + } + error = slab_add(ag_rmaps[agno].ar_rmaps, prev); + if (error) + goto err; + prev = rec; + rec = pop_slab_cursor(cur); + } + if (prev) { + error = slab_add(ag_rmaps[agno].ar_rmaps, prev); + if (error) + goto err; + } + free_slab(&ag_rmaps[agno].ar_raw_rmaps); + error = init_slab(&ag_rmaps[agno].ar_raw_rmaps, + sizeof(struct xfs_rmap_irec)); + if (error) + do_error( +_("Insufficient memory while allocating raw metadata reverse mapping slabs.")); +no_raw: + if (old_sz) + qsort_slab(ag_rmaps[agno].ar_rmaps, rmap_compare); +err: + free_slab_cursor(&cur); + return error; +} + #ifdef RMAP_DEBUG static void dump_rmap( diff --git a/repair/rmap.h b/repair/rmap.h index 0832790..ca92623 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -28,5 +28,9 @@ extern void init_rmaps(struct xfs_mount *); extern void free_rmaps(struct xfs_mount *); extern int add_rmap(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *); +extern int add_ag_rmap(struct xfs_mount *, xfs_agnumber_t agno, + xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner); +extern int fold_raw_rmaps(struct xfs_mount *mp, xfs_agnumber_t agno); +extern bool mergeable_rmaps(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); #endif /* RMAP_H_ */ From darrick.wong@oracle.com Thu Jun 16 20:37:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6C7CC821B for ; Thu, 16 Jun 2016 20:37:20 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 30422304039 for ; Thu, 16 Jun 2016 18:37:20 -0700 (PDT) X-ASG-Debug-ID: 1466127438-04cb6c542758020001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id fuGfpuKC3iJS7zdD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1bDXM006183 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:14 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bDdr027209 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:13 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bBll011399; Fri, 17 Jun 2016 01:37:12 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:10 -0700 Subject: [PATCH 061/145] xfs_repair: add inode bmbt block rmaps From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 061/145] xfs_repair: add inode bmbt block rmaps To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:09 -0700 Message-ID: <146612742957.16048.6189985332126150626.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127438 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2721 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Record BMBT blocks in the raw rmap list. Signed-off-by: Darrick J. Wong --- repair/rmap.c | 26 ++++++++++++++++++++++++++ repair/rmap.h | 1 + repair/scan.c | 11 +++++++++++ 3 files changed, 38 insertions(+) diff --git a/repair/rmap.c b/repair/rmap.c index 1851742..e30e99b 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -230,6 +230,32 @@ __add_raw_rmap( } /* + * Add a reverse mapping for an inode fork's block mapping btree block. + */ +int +add_bmbt_rmap( + struct xfs_mount *mp, + xfs_ino_t ino, + int whichfork, + xfs_fsblock_t fsbno) +{ + xfs_agnumber_t agno; + xfs_agblock_t agbno; + + if (!needs_rmap_work(mp)) + return 0; + + agno = XFS_FSB_TO_AGNO(mp, fsbno); + agbno = XFS_FSB_TO_AGBNO(mp, fsbno); + ASSERT(agno != NULLAGNUMBER); + ASSERT(agno < mp->m_sb.sb_agcount); + ASSERT(agbno + 1 <= mp->m_sb.sb_agblocks); + + return __add_raw_rmap(mp, agno, agbno, 1, ino, + whichfork == XFS_ATTR_FORK, true); +} + +/* * Add a reverse mapping for a per-AG fixed metadata extent. */ int diff --git a/repair/rmap.h b/repair/rmap.h index ca92623..6a3a0a4 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -30,6 +30,7 @@ extern void free_rmaps(struct xfs_mount *); extern int add_rmap(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *); extern int add_ag_rmap(struct xfs_mount *, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner); +extern int add_bmbt_rmap(struct xfs_mount *, xfs_ino_t, int, xfs_fsblock_t); extern int fold_raw_rmaps(struct xfs_mount *mp, xfs_agnumber_t agno); extern bool mergeable_rmaps(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); diff --git a/repair/scan.c b/repair/scan.c index eb23685..6157d71 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -29,6 +29,7 @@ #include "bmap.h" #include "progress.h" #include "threads.h" +#include "rmap.h" static xfs_mount_t *mp = NULL; @@ -197,6 +198,7 @@ scan_bmapbt( xfs_agnumber_t agno; xfs_agblock_t agbno; int state; + int error; /* * unlike the ag freeblock btrees, if anything looks wrong @@ -378,6 +380,15 @@ _("bad state %d, inode %" PRIu64 " bmap block 0x%" PRIx64 "\n"), (*tot)++; numrecs = be16_to_cpu(block->bb_numrecs); + /* Record BMBT blocks in the reverse-mapping data. */ + if (check_dups && collect_rmaps) { + error = add_bmbt_rmap(mp, ino, whichfork, bno); + if (error) + do_error( +_("couldn't add inode %"PRIu64" bmbt block %"PRIu64" reverse-mapping data."), + ino, bno); + } + if (level == 0) { if (numrecs > mp->m_bmap_dmxr[0] || (isroot == 0 && numrecs < mp->m_bmap_dmnr[0])) { From darrick.wong@oracle.com Thu Jun 16 20:37:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id B9A338223 for ; Thu, 16 Jun 2016 20:37:29 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 7D047304039 for ; Thu, 16 Jun 2016 18:37:29 -0700 (PDT) X-ASG-Debug-ID: 1466127447-04cbb01fee6a260001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 2LaxOjQLynZurXAm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:27 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1bNu0006227 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:23 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bMen002732 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:22 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bMLO028794; Fri, 17 Jun 2016 01:37:22 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:21 -0700 Subject: [PATCH 062/145] xfs_repair: add fixed-location per-AG rmaps From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 062/145] xfs_repair: add fixed-location per-AG rmaps To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:15 -0700 Message-ID: <146612743563.16048.12801958251253451303.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127447 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4489 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add reverse-mappings for fixed-location per-AG metadata such as inode chunks, superblocks, and the log to the raw rmap list, then merge the raw rmap data (which also has the BMBT data) into the main rmap list. v2: Support sparse inode chunks. Signed-off-by: Darrick J. Wong --- repair/phase4.c | 41 +++++++++++++++++++++++++ repair/rmap.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 2 + 3 files changed, 135 insertions(+) diff --git a/repair/phase4.c b/repair/phase4.c index b4264df..8880c91 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -157,6 +157,40 @@ process_ags( do_inode_prefetch(mp, ag_stride, process_ag_func, true, false); } +static void +check_rmap_btrees( + work_queue_t *wq, + xfs_agnumber_t agno, + void *arg) +{ + int error; + + error = add_fixed_ag_rmap_data(wq->mp, agno); + if (error) + do_error( +_("unable to add AG %u metadata reverse-mapping data.\n"), agno); + + error = fold_raw_rmaps(wq->mp, agno); + if (error) + do_error( +_("unable to merge AG %u metadata reverse-mapping data.\n"), agno); +} + +static void +process_rmap_data( + struct xfs_mount *mp) +{ + struct work_queue wq; + xfs_agnumber_t i; + + if (!needs_rmap_work(mp)) + return; + + create_work_queue(&wq, mp, libxfs_nproc()); + for (i = 0; i < mp->m_sb.sb_agcount; i++) + queue_work(&wq, check_rmap_btrees, i, NULL); + destroy_work_queue(&wq); +} void phase4(xfs_mount_t *mp) @@ -306,6 +340,13 @@ phase4(xfs_mount_t *mp) * already in phase 3. */ process_ags(mp); + + /* + * Process all the reverse-mapping data that we collected. This + * involves checking the rmap data against the btree. + */ + process_rmap_data(mp); + print_final_rpt(); /* diff --git a/repair/rmap.c b/repair/rmap.c index e30e99b..8f532fb 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -331,6 +331,98 @@ err: return error; } +static int +find_first_zero_bit( + __uint64_t mask) +{ + int n; + int b = 0; + + for (n = 0; n < sizeof(mask) * NBBY && (mask & 1); n++, mask >>= 1) + b++; + + return b; +} + +static int +popcnt( + __uint64_t mask) +{ + int n; + int b = 0; + + if (mask == 0) + return 0; + + for (n = 0; n < sizeof(mask) * NBBY; n++, mask >>= 1) + if (mask & 1) + b++; + + return b; +} + +/* + * Add an allocation group's fixed metadata to the rmap list. This includes + * sb/agi/agf/agfl headers, inode chunks, and the log. + */ +int +add_fixed_ag_rmap_data( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + xfs_fsblock_t fsbno; + xfs_agblock_t agbno; + ino_tree_node_t *ino_rec; + xfs_agino_t agino; + int error; + int startidx; + int nr; + + if (!needs_rmap_work(mp)) + return 0; + + /* sb/agi/agf/agfl headers */ + error = add_ag_rmap(mp, agno, 0, XFS_BNO_BLOCK(mp), + XFS_RMAP_OWN_FS); + if (error) + goto out; + + /* inodes */ + ino_rec = findfirst_inode_rec(agno); + for (; ino_rec != NULL; ino_rec = next_ino_rec(ino_rec)) { + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) { + startidx = find_first_zero_bit(ino_rec->ir_sparse); + nr = XFS_INODES_PER_CHUNK - popcnt(ino_rec->ir_sparse); + } else { + startidx = 0; + nr = XFS_INODES_PER_CHUNK; + } + nr /= mp->m_sb.sb_inopblock; + if (nr == 0) + nr = 1; + agino = ino_rec->ino_startnum + startidx; + agbno = XFS_AGINO_TO_AGBNO(mp, agino); + if (XFS_AGINO_TO_OFFSET(mp, agino) == 0) { + error = add_ag_rmap(mp, agno, agbno, nr, + XFS_RMAP_OWN_INODES); + if (error) + goto out; + } + } + + /* log */ + fsbno = mp->m_sb.sb_logstart; + if (fsbno && XFS_FSB_TO_AGNO(mp, fsbno) == agno) { + agbno = XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart); + error = add_ag_rmap(mp, agno, agbno, mp->m_sb.sb_logblocks, + XFS_RMAP_OWN_LOG); + if (error) + goto out; + } +out: + return error; +} + #ifdef RMAP_DEBUG static void dump_rmap( diff --git a/repair/rmap.h b/repair/rmap.h index 6a3a0a4..f948f25 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -34,4 +34,6 @@ extern int add_bmbt_rmap(struct xfs_mount *, xfs_ino_t, int, xfs_fsblock_t); extern int fold_raw_rmaps(struct xfs_mount *mp, xfs_agnumber_t agno); extern bool mergeable_rmaps(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); +extern int add_fixed_ag_rmap_data(struct xfs_mount *, xfs_agnumber_t); + #endif /* RMAP_H_ */ From darrick.wong@oracle.com Thu Jun 16 20:37:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5065F8128 for ; Thu, 16 Jun 2016 20:37:39 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0E551304048 for ; Thu, 16 Jun 2016 18:37:38 -0700 (PDT) X-ASG-Debug-ID: 1466127455-04bdf01e13962e0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id fJNjmbGLxcxHAwBg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:35 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1bVRA006289 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:31 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bUpT007378 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:31 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bSW5011446; Fri, 17 Jun 2016 01:37:29 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:28 -0700 Subject: [PATCH 063/145] xfs_repair: check existing rmapbt entries against observed rmaps From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 063/145] xfs_repair: check existing rmapbt entries against observed rmaps To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:26 -0700 Message-ID: <146612744678.16048.13958545888765262883.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127455 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14900 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Once we've finished collecting reverse mapping observations from the metadata scan, check those observations against the rmap btree (particularly if we're in -n mode) to detect rmapbt problems. v2: Restructure after moving rmap_irec flags to separate field. v3: Refactor code to prepare to do range queries for reflink. Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- repair/phase4.c | 6 + repair/rmap.c | 253 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 10 ++ repair/scan.c | 104 ++++++++++++++++++++--- 4 files changed, 362 insertions(+), 11 deletions(-) diff --git a/repair/phase4.c b/repair/phase4.c index 8880c91..e234d92 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -174,6 +174,12 @@ _("unable to add AG %u metadata reverse-mapping data.\n"), agno); if (error) do_error( _("unable to merge AG %u metadata reverse-mapping data.\n"), agno); + + error = check_rmaps(wq->mp, agno); + if (error) + do_error( +_("%s while checking reverse-mappings"), + strerror(-error)); } static void diff --git a/repair/rmap.c b/repair/rmap.c index 8f532fb..4648425 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -42,6 +42,7 @@ struct xfs_ag_rmap { }; static struct xfs_ag_rmap *ag_rmaps; +static bool rmapbt_suspect; /* * Compare rmap observations for array sorting. @@ -442,3 +443,255 @@ dump_rmap( #else # define dump_rmap(m, a, r) #endif + +/* + * Return the number of rmap objects for an AG. + */ +size_t +rmap_record_count( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return slab_count(ag_rmaps[agno].ar_rmaps); +} + +/* + * Return a slab cursor that will return rmap objects in order. + */ +int +init_rmap_cursor( + xfs_agnumber_t agno, + struct xfs_slab_cursor **cur) +{ + return init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare, cur); +} + +/* + * Disable the refcount btree check. + */ +void +rmap_avoid_check(void) +{ + rmapbt_suspect = true; +} + +/* Look for an rmap in the rmapbt that matches a given rmap. */ +static int +lookup_rmap( + struct xfs_btree_cur *bt_cur, + struct xfs_rmap_irec *rm_rec, + struct xfs_rmap_irec *tmp, + int *have) +{ + int error; + + /* Use the regular btree retrieval routine. */ + error = xfs_rmap_lookup_le(bt_cur, rm_rec->rm_startblock, + rm_rec->rm_blockcount, + rm_rec->rm_owner, rm_rec->rm_offset, + rm_rec->rm_flags, have); + if (error) + return error; + if (*have == 0) + return error; + return xfs_rmap_get_rec(bt_cur, tmp, have); +} + +/* Does the btree rmap cover the observed rmap? */ +#define NEXTP(x) ((x)->rm_startblock + (x)->rm_blockcount) +#define NEXTL(x) ((x)->rm_offset + (x)->rm_blockcount) +static bool +is_good_rmap( + struct xfs_rmap_irec *observed, + struct xfs_rmap_irec *btree) +{ + /* Can't have mismatches in the flags or the owner. */ + if (btree->rm_flags != observed->rm_flags || + btree->rm_owner != observed->rm_owner) + return false; + + /* + * Btree record can't physically start after the observed + * record, nor can it end before the observed record. + */ + if (btree->rm_startblock > observed->rm_startblock || + NEXTP(btree) < NEXTP(observed)) + return false; + + /* If this is metadata or bmbt, we're done. */ + if (XFS_RMAP_NON_INODE_OWNER(observed->rm_owner) || + (observed->rm_flags & XFS_RMAP_BMBT_BLOCK)) + return true; + /* + * Btree record can't logically start after the observed + * record, nor can it end before the observed record. + */ + if (btree->rm_offset > observed->rm_offset || + NEXTL(btree) < NEXTL(observed)) + return false; + + return true; +} +#undef NEXTP +#undef NEXTL + +/* + * Compare the observed reverse mappings against what's in the ag btree. + */ +int +check_rmaps( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_slab_cursor *rm_cur; + struct xfs_btree_cur *bt_cur = NULL; + int error; + int have; + struct xfs_buf *agbp = NULL; + struct xfs_rmap_irec *rm_rec; + struct xfs_rmap_irec tmp; + struct xfs_perag *pag; /* per allocation group data */ + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + if (rmapbt_suspect) { + if (no_modify && agno == 0) + do_warn(_("would rebuild corrupt rmap btrees.\n")); + return 0; + } + + /* Create cursors to refcount structures */ + error = init_rmap_cursor(agno, &rm_cur); + if (error) + return error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + goto err; + + /* Leave the per-ag data "uninitialized" since we rewrite it later */ + pag = xfs_perag_get(mp, agno); + pag->pagf_init = 0; + xfs_perag_put(pag); + + bt_cur = xfs_rmapbt_init_cursor(mp, NULL, agbp, agno); + if (!bt_cur) { + error = -ENOMEM; + goto err; + } + + rm_rec = pop_slab_cursor(rm_cur); + while (rm_rec) { + error = lookup_rmap(bt_cur, rm_rec, &tmp, &have); + if (error) + goto err; + if (!have) { + do_warn( +_("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \ +%s%soff %"PRIu64"\n"), + agno, rm_rec->rm_startblock, + (rm_rec->rm_flags & XFS_RMAP_UNWRITTEN) ? + _("unwritten ") : "", + rm_rec->rm_blockcount, + rm_rec->rm_owner, + (rm_rec->rm_flags & XFS_RMAP_ATTR_FORK) ? + _("attr ") : "", + (rm_rec->rm_flags & XFS_RMAP_BMBT_BLOCK) ? + _("bmbt ") : "", + rm_rec->rm_offset); + goto next_loop; + } + + /* Compare each refcount observation against the btree's */ + if (!is_good_rmap(rm_rec, &tmp)) { + do_warn( +_("Incorrect reverse-mapping: saw (%u/%u) %slen %u owner %"PRId64" %s%soff \ +%"PRIu64"; should be (%u/%u) %slen %u owner %"PRId64" %s%soff %"PRIu64"\n"), + agno, tmp.rm_startblock, + (tmp.rm_flags & XFS_RMAP_UNWRITTEN) ? + _("unwritten ") : "", + tmp.rm_blockcount, + tmp.rm_owner, + (tmp.rm_flags & XFS_RMAP_ATTR_FORK) ? + _("attr ") : "", + (tmp.rm_flags & XFS_RMAP_BMBT_BLOCK) ? + _("bmbt ") : "", + tmp.rm_offset, + agno, rm_rec->rm_startblock, + (rm_rec->rm_flags & XFS_RMAP_UNWRITTEN) ? + _("unwritten ") : "", + rm_rec->rm_blockcount, + rm_rec->rm_owner, + (rm_rec->rm_flags & XFS_RMAP_ATTR_FORK) ? + _("attr ") : "", + (rm_rec->rm_flags & XFS_RMAP_BMBT_BLOCK) ? + _("bmbt ") : "", + rm_rec->rm_offset); + goto next_loop; + } +next_loop: + rm_rec = pop_slab_cursor(rm_cur); + } + +err: + if (bt_cur) + xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); + if (agbp) + libxfs_putbuf(agbp); + free_slab_cursor(&rm_cur); + return 0; +} + +/* Compare the key fields of two rmap records. */ +__int64_t +rmap_diffkeys( + struct xfs_rmap_irec *kp1, + struct xfs_rmap_irec *kp2) +{ + __u64 oa; + __u64 ob; + __int64_t d; + struct xfs_rmap_irec tmp; + + tmp = *kp1; + tmp.rm_flags &= ~XFS_RMAP_REC_FLAGS; + oa = xfs_rmap_irec_offset_pack(&tmp); + tmp = *kp2; + tmp.rm_flags &= ~XFS_RMAP_REC_FLAGS; + ob = xfs_rmap_irec_offset_pack(&tmp); + + d = (__int64_t)kp2->rm_startblock - kp1->rm_startblock; + if (d) + return d; + + if (kp2->rm_owner > kp1->rm_owner) + return 1; + else if (kp1->rm_owner > kp2->rm_owner) + return -1; + + if (ob > oa) + return 1; + else if (oa > ob) + return -1; + return 0; +} + +/* Compute the high key of an rmap record. */ +void +rmap_high_key_from_rec( + struct xfs_rmap_irec *rec, + struct xfs_rmap_irec *key) +{ + int adj; + + adj = rec->rm_blockcount - 1; + + key->rm_startblock = rec->rm_startblock + adj; + key->rm_owner = rec->rm_owner; + key->rm_offset = rec->rm_offset; + key->rm_flags = rec->rm_flags & XFS_RMAP_KEY_FLAGS; + if (XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) || + (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)) + return; + key->rm_offset += adj; +} diff --git a/repair/rmap.h b/repair/rmap.h index f948f25..d9d08d4 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -36,4 +36,14 @@ extern bool mergeable_rmaps(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); extern int add_fixed_ag_rmap_data(struct xfs_mount *, xfs_agnumber_t); +extern size_t rmap_record_count(struct xfs_mount *, xfs_agnumber_t); +extern int init_rmap_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); +extern void rmap_avoid_check(void); +extern int check_rmaps(struct xfs_mount *, xfs_agnumber_t); + +extern __int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1, + struct xfs_rmap_irec *kp2); +extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, + struct xfs_rmap_irec *key); + #endif /* RMAP_H_ */ diff --git a/repair/scan.c b/repair/scan.c index 6157d71..6106d93 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -29,6 +29,7 @@ #include "bmap.h" #include "progress.h" #include "threads.h" +#include "slab.h" #include "rmap.h" static xfs_mount_t *mp = NULL; @@ -783,6 +784,11 @@ ino_issparse( return xfs_inobt_is_sparse_disk(rp, offset); } +struct rmap_priv { + struct aghdr_cnts *agcnts; + struct xfs_rmap_irec high_key; +}; + static void scan_rmapbt( struct xfs_btree_block *block, @@ -794,21 +800,26 @@ scan_rmapbt( __uint32_t magic, void *priv) { - struct aghdr_cnts *agcnts = priv; const char *name = "rmap"; int i; xfs_rmap_ptr_t *pp; struct xfs_rmap_rec *rp; + struct rmap_priv *rmap_priv = priv; int hdr_errors = 0; int numrecs; int state; xfs_agblock_t lastblock = 0; int64_t lastowner = 0; int64_t lastoffset = 0; + struct xfs_rmap_key *kp; + struct xfs_rmap_irec key; + if (magic != XFS_RMAP_CRC_MAGIC) { name = "(unknown)"; - assert(0); + hdr_errors++; + suspect++; + goto out; } if (be32_to_cpu(block->bb_magic) != magic) { @@ -816,7 +827,7 @@ scan_rmapbt( be32_to_cpu(block->bb_magic), name, agno, bno); hdr_errors++; if (suspect) - return; + goto out; } /* @@ -825,8 +836,8 @@ scan_rmapbt( * free data block counter. */ if (!isroot) { - agcnts->agfbtreeblks++; - agcnts->fdblocks++; + rmap_priv->agcnts->agfbtreeblks++; + rmap_priv->agcnts->fdblocks++; } if (be16_to_cpu(block->bb_level) != level) { @@ -834,7 +845,7 @@ scan_rmapbt( level, be16_to_cpu(block->bb_level), name, agno, bno); hdr_errors++; if (suspect) - return; + goto out; } /* check for btree blocks multiply claimed */ @@ -844,7 +855,7 @@ scan_rmapbt( do_warn( _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), name, state, agno, bno, suspect); - return; + goto out; } set_bmap(agno, bno, XR_E_FS_MAP); @@ -878,7 +889,20 @@ _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), len = be32_to_cpu(rp[i].rm_blockcount); owner = be64_to_cpu(rp[i].rm_owner); offset = be64_to_cpu(rp[i].rm_offset); - end = b + len; + + key.rm_flags = 0; + key.rm_startblock = b; + key.rm_blockcount = len; + key.rm_owner = owner; + if (xfs_rmap_irec_offset_unpack(offset, &key)) { + /* Look for impossible flags. */ + do_warn( + _("invalid flags in record %u of %s btree block %u/%u\n"), + i, name, agno, bno); + continue; + } + + end = key.rm_startblock + key.rm_blockcount; /* Make sure agbno & len make sense. */ if (!verify_agbno(mp, agno, b)) { @@ -919,6 +943,18 @@ advance: goto advance; } + /* Check that we don't go past the high key. */ + key.rm_startblock += key.rm_blockcount - 1; + if (!XFS_RMAP_NON_INODE_OWNER(key.rm_owner) && + !(key.rm_flags & XFS_RMAP_BMBT_BLOCK)) + key.rm_offset += key.rm_blockcount - 1; + key.rm_blockcount = 0; + if (rmap_diffkeys(&rmap_priv->high_key, &key) > 0) { + do_warn( + _("record %d greater than high key of block (%u/%u) in %s tree\n"), + i, agno, bno, name); + } + /* Check for block owner collisions. */ for ( ; b < end; b += blen) { state = get_bmap_ext(agno, b, end, &blen); @@ -996,7 +1032,7 @@ _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), } } } - return; + goto out; } /* @@ -1024,12 +1060,33 @@ _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), mp->m_rmap_mnr[1], mp->m_rmap_mxr[1], name, agno, bno); if (suspect) - return; + goto out; suspect++; } else if (suspect) { suspect = 0; } + /* check the node's high keys */ + for (i = 0; !isroot && i < numrecs; i++) { + kp = XFS_RMAP_HIGH_KEY_ADDR(block, i + 1); + + key.rm_flags = 0; + key.rm_startblock = be32_to_cpu(kp->rm_startblock); + key.rm_owner = be64_to_cpu(kp->rm_owner); + if (xfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), + &key)) { + /* Look for impossible flags. */ + do_warn( + _("invalid flags in key %u of %s btree block %u/%u\n"), + i, name, agno, bno); + continue; + } + if (rmap_diffkeys(&rmap_priv->high_key, &key) > 0) + do_warn( + _("key %d greater than high key of block (%u/%u) in %s tree\n"), + i, agno, bno, name); + } + for (i = 0; i < numrecs; i++) { xfs_agblock_t bno = be32_to_cpu(pp[i]); @@ -1042,11 +1099,30 @@ _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), * pointer mismatch, try and extract as much data * as possible. */ + kp = XFS_RMAP_HIGH_KEY_ADDR(block, i + 1); + rmap_priv->high_key.rm_flags = 0; + rmap_priv->high_key.rm_startblock = + be32_to_cpu(kp->rm_startblock); + rmap_priv->high_key.rm_owner = + be64_to_cpu(kp->rm_owner); + if (xfs_rmap_irec_offset_unpack(be64_to_cpu(kp->rm_offset), + &rmap_priv->high_key)) { + /* Look for impossible flags. */ + do_warn( + _("invalid flags in high key %u of %s btree block %u/%u\n"), + i, name, agno, bno); + continue; + } + if (bno != 0 && verify_agbno(mp, agno, bno)) { scan_sbtree(bno, level, agno, suspect, scan_rmapbt, 0, magic, priv, &xfs_rmapbt_buf_ops); } } + +out: + if (suspect) + rmap_avoid_check(); } /* @@ -1815,15 +1891,21 @@ validate_agf( } if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + struct rmap_priv priv; + + memset(&priv.high_key, 0xFF, sizeof(priv.high_key)); + priv.high_key.rm_blockcount = 0; + priv.agcnts = agcnts; bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); if (bno != 0 && verify_agbno(mp, agno, bno)) { scan_sbtree(bno, be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]), agno, 0, scan_rmapbt, 1, XFS_RMAP_CRC_MAGIC, - agcnts, &xfs_rmapbt_buf_ops); + &priv, &xfs_rmapbt_buf_ops); } else { do_warn(_("bad agbno %u for rmapbt root, agno %d\n"), bno, agno); + rmap_avoid_check(); } } From darrick.wong@oracle.com Thu Jun 16 20:37:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id DC882814B for ; Thu, 16 Jun 2016 20:37:48 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id AD92B304048 for ; Thu, 16 Jun 2016 18:37:48 -0700 (PDT) X-ASG-Debug-ID: 1466127465-04cb6c542658060001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id wVOAlA1K2pVhaa0C (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:45 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1beJB006378 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:40 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bceu003101 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:38 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bYB2011488; Fri, 17 Jun 2016 01:37:35 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:34 -0700 Subject: [PATCH 064/145] xfs_repair: rebuild reverse-mapping btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 064/145] xfs_repair: rebuild reverse-mapping btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:33 -0700 Message-ID: <146612745300.16048.6139548481884641087.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127465 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15062 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Rebuild the reverse-mapping btree with the rmap observations corresponding to file extents, bmbt blocks, and fixed per-AG metadata. v2: Update to use the flags in rm_flags and to support high key updates for the rmapbt. v3: Initialize rm_flags to zero so as to avoid corruption problems later when we stash non-key flags in the offset field. v4: Leave a few empty slots in each rmapbt leaf when we're rebuilding the rmapbt so that we can insert records for the AG metadata blocks without causing too many btree splits. This (hopefully) prevents the situation where running xfs_repair greatly increases the size of the btree. Signed-off-by: Darrick J. Wong --- repair/phase5.c | 407 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 393 insertions(+), 14 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index b58111b..bb065ec 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -28,6 +28,8 @@ #include "versions.h" #include "threads.h" #include "progress.h" +#include "slab.h" +#include "rmap.h" /* * we maintain the current slice (path from root to leaf) @@ -1326,6 +1328,359 @@ nextrec: } } +/* rebuild the rmap tree */ + +/* + * we don't have to worry here about how chewing up free extents + * may perturb things because rmap tree building happens before + * freespace tree building. + */ +static void +init_rmapbt_cursor( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *btree_curs) +{ + size_t num_recs; + int level; + struct bt_stat_level *lptr; + struct bt_stat_level *p_lptr; + xfs_extlen_t blocks_allocated; + int maxrecs; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) { + memset(btree_curs, 0, sizeof(struct bt_status)); + return; + } + + lptr = &btree_curs->level[0]; + btree_curs->init = 1; + + /* + * build up statistics + */ + num_recs = rmap_record_count(mp, agno); + if (num_recs == 0) { + /* + * easy corner-case -- no rmap records + */ + lptr->num_blocks = 1; + lptr->modulo = 0; + lptr->num_recs_pb = 0; + lptr->num_recs_tot = 0; + + btree_curs->num_levels = 1; + btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; + + setup_cursor(mp, agno, btree_curs); + + return; + } + + /* + * Leave enough slack in the rmapbt that we can insert the + * metadata AG entries without too many splits. + */ + maxrecs = mp->m_rmap_mxr[0]; + if (num_recs > maxrecs) + maxrecs -= 10; + blocks_allocated = lptr->num_blocks = howmany(num_recs, maxrecs); + + lptr->modulo = num_recs % lptr->num_blocks; + lptr->num_recs_pb = num_recs / lptr->num_blocks; + lptr->num_recs_tot = num_recs; + level = 1; + + if (lptr->num_blocks > 1) { + for (; btree_curs->level[level-1].num_blocks > 1 + && level < XFS_BTREE_MAXLEVELS; + level++) { + lptr = &btree_curs->level[level]; + p_lptr = &btree_curs->level[level - 1]; + lptr->num_blocks = howmany(p_lptr->num_blocks, + mp->m_rmap_mxr[1]); + lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; + lptr->num_recs_pb = p_lptr->num_blocks + / lptr->num_blocks; + lptr->num_recs_tot = p_lptr->num_blocks; + + blocks_allocated += lptr->num_blocks; + } + } + ASSERT(lptr->num_blocks == 1); + btree_curs->num_levels = level; + + btree_curs->num_tot_blocks = btree_curs->num_free_blocks + = blocks_allocated; + + setup_cursor(mp, agno, btree_curs); +} + +static void +prop_rmap_cursor( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *btree_curs, + struct xfs_rmap_irec *rm_rec, + int level) +{ + struct xfs_btree_block *bt_hdr; + struct xfs_rmap_key *bt_key; + xfs_rmap_ptr_t *bt_ptr; + xfs_agblock_t agbno; + struct bt_stat_level *lptr; + + level++; + + if (level >= btree_curs->num_levels) + return; + + lptr = &btree_curs->level[level]; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + + if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { + /* + * this only happens once to initialize the + * first path up the left side of the tree + * where the agbno's are already set up + */ + prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level); + } + + if (be16_to_cpu(bt_hdr->bb_numrecs) == + lptr->num_recs_pb + (lptr->modulo > 0)) { + /* + * write out current prev block, grab us a new block, + * and set the rightsib pointer of current block + */ +#ifdef XR_BLD_INO_TRACE + fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno); +#endif + if (lptr->prev_agbno != NULLAGBLOCK) { + ASSERT(lptr->prev_buf_p != NULL); + libxfs_writebuf(lptr->prev_buf_p, 0); + } + lptr->prev_agbno = lptr->agbno; + lptr->prev_buf_p = lptr->buf_p; + agbno = get_next_blockaddr(agno, level, btree_curs); + + bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); + + lptr->buf_p = libxfs_getbuf(mp->m_dev, + XFS_AGB_TO_DADDR(mp, agno, agbno), + XFS_FSB_TO_BB(mp, 1)); + lptr->agbno = agbno; + + if (lptr->modulo) + lptr->modulo--; + + /* + * initialize block header + */ + lptr->buf_p->b_ops = &xfs_rmapbt_buf_ops; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + memset(bt_hdr, 0, mp->m_sb.sb_blocksize); + xfs_btree_init_block(mp, lptr->buf_p, XFS_RMAP_CRC_MAGIC, + level, 0, agno, + XFS_BTREE_CRC_BLOCKS); + + bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); + + /* + * propagate extent record for first extent in new block up + */ + prop_rmap_cursor(mp, agno, btree_curs, rm_rec, level); + } + /* + * add inode info to current block + */ + be16_add_cpu(&bt_hdr->bb_numrecs, 1); + + bt_key = XFS_RMAP_KEY_ADDR(bt_hdr, + be16_to_cpu(bt_hdr->bb_numrecs)); + bt_ptr = XFS_RMAP_PTR_ADDR(bt_hdr, + be16_to_cpu(bt_hdr->bb_numrecs), + mp->m_rmap_mxr[1]); + + bt_key->rm_startblock = cpu_to_be32(rm_rec->rm_startblock); + bt_key->rm_owner = cpu_to_be64(rm_rec->rm_owner); + bt_key->rm_offset = cpu_to_be64(rm_rec->rm_offset); + + *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); +} + +static void +prop_rmap_highkey( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *btree_curs, + struct xfs_rmap_irec *rm_highkey) +{ + struct xfs_btree_block *bt_hdr; + struct xfs_rmap_key *bt_key; + struct bt_stat_level *lptr; + struct xfs_rmap_irec key; + struct xfs_rmap_irec high_key; + int level; + int i; + int numrecs; + + key.rm_flags = 0; + high_key = *rm_highkey; + for (level = 1; level < btree_curs->num_levels; level++) { + lptr = &btree_curs->level[level]; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + numrecs = be16_to_cpu(bt_hdr->bb_numrecs); + bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, numrecs); + + bt_key->rm_startblock = cpu_to_be32(high_key.rm_startblock); + bt_key->rm_owner = cpu_to_be64(high_key.rm_owner); + bt_key->rm_offset = cpu_to_be64( + xfs_rmap_irec_offset_pack(&high_key)); + + for (i = 1; i < numrecs - 1; i++) { + bt_key = XFS_RMAP_HIGH_KEY_ADDR(bt_hdr, i); + key.rm_startblock = be32_to_cpu(bt_key->rm_startblock); + key.rm_owner = be64_to_cpu(bt_key->rm_owner); + key.rm_offset = be64_to_cpu(bt_key->rm_offset); + if (rmap_diffkeys(&high_key, &key) > 0) + high_key = key; + } + } +} + +/* + * rebuilds a rmap btree given a cursor. + */ +static void +build_rmap_tree( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *btree_curs) +{ + xfs_agnumber_t i; + xfs_agblock_t j; + xfs_agblock_t agbno; + struct xfs_btree_block *bt_hdr; + struct xfs_rmap_irec *rm_rec; + struct xfs_slab_cursor *rmap_cur; + struct xfs_rmap_rec *bt_rec; + struct xfs_rmap_irec highest_key; + struct xfs_rmap_irec hi_key; + struct bt_stat_level *lptr; + int level = btree_curs->num_levels; + int error; + + highest_key.rm_flags = 0; + for (i = 0; i < level; i++) { + lptr = &btree_curs->level[i]; + + agbno = get_next_blockaddr(agno, i, btree_curs); + lptr->buf_p = libxfs_getbuf(mp->m_dev, + XFS_AGB_TO_DADDR(mp, agno, agbno), + XFS_FSB_TO_BB(mp, 1)); + + if (i == btree_curs->num_levels - 1) + btree_curs->root = agbno; + + lptr->agbno = agbno; + lptr->prev_agbno = NULLAGBLOCK; + lptr->prev_buf_p = NULL; + /* + * initialize block header + */ + + lptr->buf_p->b_ops = &xfs_rmapbt_buf_ops; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + memset(bt_hdr, 0, mp->m_sb.sb_blocksize); + xfs_btree_init_block(mp, lptr->buf_p, XFS_RMAP_CRC_MAGIC, + i, 0, agno, + XFS_BTREE_CRC_BLOCKS); + } + + /* + * run along leaf, setting up records. as we have to switch + * blocks, call the prop_rmap_cursor routine to set up the new + * pointers for the parent. that can recurse up to the root + * if required. set the sibling pointers for leaf level here. + */ + error = init_rmap_cursor(agno, &rmap_cur); + if (error) + do_error( +_("Insufficient memory to construct reverse-map cursor.")); + rm_rec = pop_slab_cursor(rmap_cur); + lptr = &btree_curs->level[0]; + + for (i = 0; i < lptr->num_blocks; i++) { + /* + * block initialization, lay in block header + */ + lptr->buf_p->b_ops = &xfs_rmapbt_buf_ops; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + memset(bt_hdr, 0, mp->m_sb.sb_blocksize); + xfs_btree_init_block(mp, lptr->buf_p, XFS_RMAP_CRC_MAGIC, + 0, 0, agno, + XFS_BTREE_CRC_BLOCKS); + + bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); + bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb + + (lptr->modulo > 0)); + + if (lptr->modulo > 0) + lptr->modulo--; + + if (lptr->num_recs_pb > 0) + prop_rmap_cursor(mp, agno, btree_curs, rm_rec, 0); + + bt_rec = (struct xfs_rmap_rec *) + ((char *)bt_hdr + XFS_RMAP_BLOCK_LEN); + highest_key.rm_startblock = 0; + highest_key.rm_owner = 0; + highest_key.rm_offset = 0; + for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { + ASSERT(rm_rec != NULL); + bt_rec[j].rm_startblock = + cpu_to_be32(rm_rec->rm_startblock); + bt_rec[j].rm_blockcount = + cpu_to_be32(rm_rec->rm_blockcount); + bt_rec[j].rm_owner = cpu_to_be64(rm_rec->rm_owner); + bt_rec[j].rm_offset = cpu_to_be64( + xfs_rmap_irec_offset_pack(rm_rec)); + rmap_high_key_from_rec(rm_rec, &hi_key); + if (rmap_diffkeys(&highest_key, &hi_key) > 0) + highest_key = hi_key; + + rm_rec = pop_slab_cursor(rmap_cur); + } + + /* Now go set the parent key */ + prop_rmap_highkey(mp, agno, btree_curs, &highest_key); + + if (rm_rec != NULL) { + /* + * get next leaf level block + */ + if (lptr->prev_buf_p != NULL) { +#ifdef XR_BLD_RL_TRACE + fprintf(stderr, "writing rmapbt agbno %u\n", + lptr->prev_agbno); +#endif + ASSERT(lptr->prev_agbno != NULLAGBLOCK); + libxfs_writebuf(lptr->prev_buf_p, 0); + } + lptr->prev_buf_p = lptr->buf_p; + lptr->prev_agbno = lptr->agbno; + lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); + bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); + + lptr->buf_p = libxfs_getbuf(mp->m_dev, + XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), + XFS_FSB_TO_BB(mp, 1)); + } + } + free_slab_cursor(&rmap_cur); +} + /* * build both the agf and the agfl for an agno given both * btree cursors. @@ -1333,19 +1688,21 @@ nextrec: * XXX: yet more common code that can be shared with mkfs/growfs. */ static void -build_agf_agfl(xfs_mount_t *mp, - xfs_agnumber_t agno, - bt_status_t *bno_bt, - bt_status_t *bcnt_bt, - xfs_extlen_t freeblks, /* # free blocks in tree */ - int lostblocks) /* # blocks that will be lost */ +build_agf_agfl( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *bno_bt, + struct bt_status *bcnt_bt, + xfs_extlen_t freeblks, /* # free blocks in tree */ + int lostblocks, /* # blocks that will be lost */ + struct bt_status *rmap_bt) { - extent_tree_node_t *ext_ptr; - xfs_buf_t *agf_buf, *agfl_buf; + struct extent_tree_node *ext_ptr; + struct xfs_buf *agf_buf, *agfl_buf; int i; int j; - xfs_agfl_t *agfl; - xfs_agf_t *agf; + struct xfs_agfl *agfl; + struct xfs_agf *agf; __be32 *freelist; agf_buf = libxfs_getbuf(mp->m_dev, @@ -1377,20 +1734,25 @@ build_agf_agfl(xfs_mount_t *mp, agf->agf_levels[XFS_BTNUM_BNO] = cpu_to_be32(bno_bt->num_levels); agf->agf_roots[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->root); agf->agf_levels[XFS_BTNUM_CNT] = cpu_to_be32(bcnt_bt->num_levels); + agf->agf_roots[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->root); + agf->agf_levels[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->num_levels); agf->agf_freeblks = cpu_to_be32(freeblks); /* * Count and record the number of btree blocks consumed if required. */ if (xfs_sb_version_haslazysbcount(&mp->m_sb)) { + unsigned int blks; /* * Don't count the root blocks as they are already * accounted for. */ - agf->agf_btreeblks = cpu_to_be32( - (bno_bt->num_tot_blocks - bno_bt->num_free_blocks) + + blks = (bno_bt->num_tot_blocks - bno_bt->num_free_blocks) + (bcnt_bt->num_tot_blocks - bcnt_bt->num_free_blocks) - - 2); + 2; + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + blks += rmap_bt->num_tot_blocks - rmap_bt->num_free_blocks - 1; + agf->agf_btreeblks = cpu_to_be32(blks); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "agf->agf_btreeblks = %u\n", be32_to_cpu(agf->agf_btreeblks)); @@ -1586,6 +1948,7 @@ phase5_func( bt_status_t bcnt_btree_curs; bt_status_t ino_btree_curs; bt_status_t fino_btree_curs; + bt_status_t rmap_btree_curs; int extra_blocks = 0; uint num_freeblocks; xfs_extlen_t freeblks1; @@ -1641,6 +2004,12 @@ phase5_func( sb_icount_ag[agno] += num_inos; sb_ifree_ag[agno] += num_free_inos; + /* + * Set up the btree cursors for the on-disk rmap btrees, + * which includes pre-allocating all required blocks. + */ + init_rmapbt_cursor(mp, agno, &rmap_btree_curs); + num_extents = count_bno_extents_blocks(agno, &num_freeblocks); /* * lose two blocks per AG -- the space tree roots @@ -1725,11 +2094,19 @@ phase5_func( ASSERT(freeblks1 == freeblks2); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + build_rmap_tree(mp, agno, &rmap_btree_curs); + write_cursor(&rmap_btree_curs); + sb_fdblocks_ag[agno] += (rmap_btree_curs.num_tot_blocks - + rmap_btree_curs.num_free_blocks) - 1; + } + /* * set up agf and agfl */ build_agf_agfl(mp, agno, &bno_btree_curs, - &bcnt_btree_curs, freeblks1, extra_blocks); + &bcnt_btree_curs, freeblks1, extra_blocks, + &rmap_btree_curs); /* * build inode allocation tree. */ @@ -1758,6 +2135,8 @@ phase5_func( */ finish_cursor(&bno_btree_curs); finish_cursor(&ino_btree_curs); + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + finish_cursor(&rmap_btree_curs); if (xfs_sb_version_hasfinobt(&mp->m_sb)) finish_cursor(&fino_btree_curs); finish_cursor(&bcnt_btree_curs); From darrick.wong@oracle.com Thu Jun 16 20:37:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id F1D378235 for ; Thu, 16 Jun 2016 20:37:49 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id B412B8F804C for ; Thu, 16 Jun 2016 18:37:49 -0700 (PDT) X-ASG-Debug-ID: 1466127466-04cbb01fec6a2a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id aSJZyinT5X0Z067m (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:47 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1bfo3018924 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:42 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bfIN027650 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:41 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1beNi028884; Fri, 17 Jun 2016 01:37:41 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:40 -0700 Subject: [PATCH 065/145] xfs_repair: add per-AG btree blocks to rmap data and add to rmapbt From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 065/145] xfs_repair: add per-AG btree blocks to rmap data and add to rmapbt To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:39 -0700 Message-ID: <146612745922.16048.15574181384571390206.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127466 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12475 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since we can't know the location of the new per-AG btree blocks prior to constructing the rmapbt, we must record raw reverse-mapping data for btree blocks while the new btrees are under construction. After the rmapbt has been rebuilt, merge the btree rmap entries into the rmapbt with the libxfs code. Also refactor the freelist fixing code since we need it to tidy up the AGFL after each rmapbt allocation. v2: Use xfs_rmap_alloc to add rmap records for AG metadata blocks because it knows how to merge adjacent rmaps. This particular bug was discovered while running xfs_repair twice on generic/175 wherein block X was originally allocated to the rmapbt, then X+1 got allocated to the rmapbt when we expanded it to hold all the entries for the rmapbt blocks. Signed-off-by: Darrick J. Wong --- repair/phase5.c | 52 +++++++------- repair/rmap.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 4 + 3 files changed, 226 insertions(+), 28 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index bb065ec..db84440 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -74,6 +74,7 @@ typedef struct bt_status { * per-level status info */ bt_stat_level_t level[XFS_BTREE_MAXLEVELS]; + uint64_t owner; /* owner */ } bt_status_t; /* @@ -205,6 +206,7 @@ setup_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *curs) extent_tree_node_t *bno_ext_ptr; xfs_extlen_t blocks_allocated; xfs_agblock_t *agb_ptr; + int error; /* * get the number of blocks we need to allocate, then @@ -249,6 +251,12 @@ setup_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *curs) blocks_allocated++; } + error = add_ag_rmap(mp, agno, ext_ptr->ex_startblock, u, + curs->owner); + if (error) + do_error(_("could not set up btree rmaps: %s\n"), + strerror(-error)); + /* * if we only used part of this last extent, then we * need only to reset the extent in the extent @@ -916,6 +924,7 @@ init_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, lptr = &btree_curs->level[0]; btree_curs->init = 1; + btree_curs->owner = XFS_RMAP_OWN_INOBT; /* * build up statistics @@ -1355,6 +1364,7 @@ init_rmapbt_cursor( lptr = &btree_curs->level[0]; btree_curs->init = 1; + btree_curs->owner = XFS_RMAP_OWN_AG; /* * build up statistics @@ -1834,6 +1844,7 @@ build_agf_agfl( agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(i - 1); agf->agf_flcount = cpu_to_be32(i); + rmap_store_agflcount(mp, agno, i); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "writing agfl for ag %u\n", agno); @@ -1858,35 +1869,8 @@ build_agf_agfl( /* * now fix up the free list appropriately - * XXX: code lifted from mkfs, should be shared. */ - { - xfs_alloc_arg_t args; - xfs_trans_t *tp; - struct xfs_trans_res tres = {0}; - int error; - - memset(&args, 0, sizeof(args)); - args.mp = mp; - args.agno = agno; - args.alignment = 1; - args.pag = xfs_perag_get(mp,agno); - error = -libxfs_trans_alloc(mp, &tres, - xfs_alloc_min_freelist(mp, args.pag), - 0, 0, &tp); - if (error) { - do_error(_("failed to fix AGFL on AG %d, error %d\n"), - agno, error); - } - args.tp = tp; - error = -libxfs_alloc_fix_freelist(&args, 0); - xfs_perag_put(args.pag); - if (error) { - do_error(_("failed to fix AGFL on AG %d, error %d\n"), - agno, error); - } - libxfs_trans_commit(tp); - } + fix_freelist(mp, agno, true); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "wrote agf for ag %u\n", agno); @@ -1958,6 +1942,7 @@ phase5_func( xfs_agblock_t num_extents; __uint32_t magic; struct agi_stat agi_stat = {0,}; + int error; if (verbose) do_log(_(" - agno = %d\n"), agno); @@ -2063,6 +2048,8 @@ phase5_func( bcnt_btree_curs = bno_btree_curs; + bno_btree_curs.owner = XFS_RMAP_OWN_AG; + bcnt_btree_curs.owner = XFS_RMAP_OWN_AG; setup_cursor(mp, agno, &bno_btree_curs); setup_cursor(mp, agno, &bcnt_btree_curs); @@ -2140,6 +2127,15 @@ phase5_func( if (xfs_sb_version_hasfinobt(&mp->m_sb)) finish_cursor(&fino_btree_curs); finish_cursor(&bcnt_btree_curs); + + /* + * Put the per-AG btree rmap data into the rmapbt + */ + error = store_ag_btree_rmap_data(mp, agno); + if (error) + do_error( +_("unable to add AG %u reverse-mapping data to btree.\n"), agno); + /* * release the incore per-AG bno/bcnt trees so * the extent nodes can be recycled diff --git a/repair/rmap.c b/repair/rmap.c index 4648425..9c17ee8 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -39,6 +39,8 @@ struct xfs_ag_rmap { struct xfs_slab *ar_rmaps; /* rmap observations, p4 */ struct xfs_slab *ar_raw_rmaps; /* unmerged rmaps */ + int ar_flcount; /* agfl entries from leftover */ + /* agbt allocations */ }; static struct xfs_ag_rmap *ag_rmaps; @@ -424,6 +426,124 @@ out: return error; } +/* + * Copy the per-AG btree reverse-mapping data into the rmapbt. + * + * At rmapbt reconstruction time, the rmapbt will be populated _only_ with + * rmaps for file extents, inode chunks, AG headers, and bmbt blocks. While + * building the AG btrees we can record all the blocks allocated for each + * btree, but we cannot resolve the conflict between the fact that one has to + * finish allocating the space for the rmapbt before building the bnobt and the + * fact that allocating blocks for the bnobt requires adding rmapbt entries. + * Therefore we record in-core the rmaps for each btree and here use the + * libxfs rmap functions to finish building the rmap btree. + * + * During AGF/AGFL reconstruction in phase 5, rmaps for the AG btrees are + * recorded in memory. The rmapbt has not been set up yet, so we need to be + * able to "expand" the AGFL without updating the rmapbt. After we've written + * out the new AGF header the new rmapbt is available, so this function reads + * each AGFL to generate rmap entries. These entries are merged with the AG + * btree rmap entries, and then we use libxfs' rmap functions to add them to + * the rmapbt, after which it is fully regenerated. + */ +int +store_ag_btree_rmap_data( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_slab_cursor *rm_cur; + struct xfs_rmap_irec *rm_rec = NULL; + struct xfs_buf *agbp = NULL; + struct xfs_buf *agflbp = NULL; + struct xfs_trans *tp; + struct xfs_trans_res tres = {0}; + __be32 *agfl_bno, *b; + int error = 0; + struct xfs_owner_info oinfo; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) + return 0; + + /* Release the ar_rmaps; they were put into the rmapbt during p5. */ + free_slab(&ag_rmaps[agno].ar_rmaps); + error = init_slab(&ag_rmaps[agno].ar_rmaps, + sizeof(struct xfs_rmap_irec)); + if (error) + goto err; + + /* Add the AGFL blocks to the rmap list */ + error = xfs_trans_read_buf( + mp, NULL, mp->m_ddev_targp, + XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)), + XFS_FSS_TO_BB(mp, 1), 0, &agflbp, &xfs_agfl_buf_ops); + if (error) + goto err; + + agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, agflbp); + agfl_bno += ag_rmaps[agno].ar_flcount; + b = agfl_bno; + while (*b != NULLAGBLOCK && b - agfl_bno <= XFS_AGFL_SIZE(mp)) { + error = add_ag_rmap(mp, agno, be32_to_cpu(*b), 1, + XFS_RMAP_OWN_AG); + if (error) + goto err; + b++; + } + libxfs_putbuf(agflbp); + agflbp = NULL; + + /* Merge all the raw rmaps into the main list */ + error = fold_raw_rmaps(mp, agno); + if (error) + goto err; + + /* Create cursors to refcount structures */ + error = init_slab_cursor(ag_rmaps[agno].ar_rmaps, rmap_compare, + &rm_cur); + if (error) + goto err; + + /* Insert rmaps into the btree one at a time */ + rm_rec = pop_slab_cursor(rm_cur); + while (rm_rec) { + error = -libxfs_trans_alloc(mp, &tres, 16, 0, 0, &tp); + if (error) + goto err_slab; + + error = xfs_alloc_read_agf(mp, tp, agno, 0, &agbp); + if (error) + goto err_trans; + + ASSERT(XFS_RMAP_NON_INODE_OWNER(rm_rec->rm_owner)); + xfs_rmap_ag_owner(&oinfo, rm_rec->rm_owner); + error = xfs_rmap_alloc(tp, agbp, agno, rm_rec->rm_startblock, + rm_rec->rm_blockcount, &oinfo); + if (error) + goto err_trans; + + error = -libxfs_trans_commit(tp); + if (error) + goto err_slab; + + fix_freelist(mp, agno, false); + + rm_rec = pop_slab_cursor(rm_cur); + } + + free_slab_cursor(&rm_cur); + return 0; + +err_trans: + libxfs_trans_cancel(tp); +err_slab: + free_slab_cursor(&rm_cur); +err: + if (agflbp) + libxfs_putbuf(agflbp); + printf("FAIL err %d\n", error); + return error; +} + #ifdef RMAP_DEBUG static void dump_rmap( @@ -695,3 +815,81 @@ rmap_high_key_from_rec( return; key->rm_offset += adj; } + +/* + * Regenerate the AGFL so that we don't run out of it while rebuilding the + * rmap btree. If skip_rmapbt is true, don't update the rmapbt (most probably + * because we're updating the rmapbt). + */ +void +fix_freelist( + struct xfs_mount *mp, + xfs_agnumber_t agno, + bool skip_rmapbt) +{ + xfs_alloc_arg_t args; + xfs_trans_t *tp; + struct xfs_trans_res tres = {0}; + int flags; + int error; + + memset(&args, 0, sizeof(args)); + args.mp = mp; + args.agno = agno; + args.alignment = 1; + args.pag = xfs_perag_get(mp, agno); + error = -libxfs_trans_alloc(mp, &tres, + xfs_alloc_min_freelist(mp, args.pag), 0, 0, &tp); + if (error) + do_error(_("failed to fix AGFL on AG %d, error %d\n"), + agno, error); + args.tp = tp; + + /* + * Prior to rmapbt, all we had to do to fix the freelist is "expand" + * the fresh AGFL header from empty to full. That hasn't changed. For + * rmapbt, however, things change a bit. + * + * When we're stuffing the rmapbt with the AG btree rmaps the tree can + * expand, so we need to keep the AGFL well-stocked for the expansion. + * However, this expansion can cause the bnobt/cntbt to shrink, which + * can make the AGFL eligible for shrinking. Shrinking involves + * freeing rmapbt entries, but since we haven't finished loading the + * rmapbt with the btree rmaps it's possible for the remove operation + * to fail. The AGFL block is large enough at this point to absorb any + * blocks freed from the bnobt/cntbt, so we can disable shrinking. + * + * During the initial AGFL regeneration during AGF generation in phase5 + * we must also disable rmapbt modifications because the AGF that + * libxfs reads does not yet point to the new rmapbt. These initial + * AGFL entries are added just prior to adding the AG btree block rmaps + * to the rmapbt. It's ok to pass NOSHRINK here too, since the AGFL is + * empty and cannot shrink. + */ + flags = XFS_ALLOC_FLAG_NOSHRINK; + if (skip_rmapbt) + flags |= XFS_ALLOC_FLAG_NORMAP; + error = libxfs_alloc_fix_freelist(&args, flags); + xfs_perag_put(args.pag); + if (error) { + do_error(_("failed to fix AGFL on AG %d, error %d\n"), + agno, error); + } + libxfs_trans_commit(tp); +} + +/* + * Remember how many AGFL entries came from excess AG btree allocations and + * therefore already have rmap entries. + */ +void +rmap_store_agflcount( + struct xfs_mount *mp, + xfs_agnumber_t agno, + int count) +{ + if (!needs_rmap_work(mp)) + return; + + ag_rmaps[agno].ar_flcount = count; +} diff --git a/repair/rmap.h b/repair/rmap.h index d9d08d4..4722266 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -35,6 +35,7 @@ extern int fold_raw_rmaps(struct xfs_mount *mp, xfs_agnumber_t agno); extern bool mergeable_rmaps(struct xfs_rmap_irec *r1, struct xfs_rmap_irec *r2); extern int add_fixed_ag_rmap_data(struct xfs_mount *, xfs_agnumber_t); +extern int store_ag_btree_rmap_data(struct xfs_mount *, xfs_agnumber_t); extern size_t rmap_record_count(struct xfs_mount *, xfs_agnumber_t); extern int init_rmap_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); @@ -46,4 +47,7 @@ extern __int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1, extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key); +extern void fix_freelist(struct xfs_mount *, xfs_agnumber_t, bool); +extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int); + #endif /* RMAP_H_ */ From darrick.wong@oracle.com Thu Jun 16 20:37:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9B5398249 for ; Thu, 16 Jun 2016 20:37:54 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 254B1AC003 for ; Thu, 16 Jun 2016 18:37:54 -0700 (PDT) X-ASG-Debug-ID: 1466127472-04bdf01e1396300001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Lp70H8SKcbj18Xj4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1bmAB018947 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:48 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1blxd007537 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:47 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1bltJ001153; Fri, 17 Jun 2016 01:37:47 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:46 -0700 Subject: [PATCH 066/145] xfs_repair: merge data & attr fork reverse mappings From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 066/145] xfs_repair: merge data & attr fork reverse mappings To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:45 -0700 Message-ID: <146612746543.16048.15290406733335696865.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127472 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3645 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Merge data and attribute fork reverse mappings. Signed-off-by: Darrick J. Wong --- repair/phase4.c | 10 ++++++++++ repair/rmap.c | 32 +++++++++++++++++++++++++++++--- repair/rmap.h | 2 ++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/repair/phase4.c b/repair/phase4.c index e234d92..3be3786 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -154,7 +154,17 @@ static void process_ags( xfs_mount_t *mp) { + xfs_agnumber_t i; + int error; + do_inode_prefetch(mp, ag_stride, process_ag_func, true, false); + for (i = 0; i < mp->m_sb.sb_agcount; i++) { + error = finish_collecting_fork_rmaps(mp, i); + if (error) + do_error( +_("unable to finish adding attr/data fork reverse-mapping data for AG %u.\n"), + i); + } } static void diff --git a/repair/rmap.c b/repair/rmap.c index 9c17ee8..e39df5a 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -41,6 +41,7 @@ struct xfs_ag_rmap { struct xfs_slab *ar_raw_rmaps; /* unmerged rmaps */ int ar_flcount; /* agfl entries from leftover */ /* agbt allocations */ + struct xfs_rmap_irec ar_last_rmap; /* last rmap seen */ }; static struct xfs_ag_rmap *ag_rmaps; @@ -118,6 +119,7 @@ _("Insufficient memory while allocating reverse mapping slabs.")); if (error) do_error( _("Insufficient memory while allocating raw metadata reverse mapping slabs.")); + ag_rmaps[i].ar_last_rmap.rm_owner = XFS_RMAP_OWN_UNKNOWN; } } @@ -177,10 +179,11 @@ add_rmap( int whichfork, struct xfs_bmbt_irec *irec) { - struct xfs_slab *rmaps; struct xfs_rmap_irec rmap; xfs_agnumber_t agno; xfs_agblock_t agbno; + struct xfs_rmap_irec *last_rmap; + int error = 0; if (!needs_rmap_work(mp)) return 0; @@ -193,7 +196,6 @@ add_rmap( ASSERT(ino != NULLFSINO); ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK); - rmaps = ag_rmaps[agno].ar_rmaps; rmap.rm_owner = ino; rmap.rm_offset = irec->br_startoff; rmap.rm_flags = 0; @@ -203,7 +205,31 @@ add_rmap( rmap.rm_blockcount = irec->br_blockcount; if (irec->br_state == XFS_EXT_UNWRITTEN) rmap.rm_flags |= XFS_RMAP_UNWRITTEN; - return slab_add(rmaps, &rmap); + last_rmap = &ag_rmaps[agno].ar_last_rmap; + if (last_rmap->rm_owner == XFS_RMAP_OWN_UNKNOWN) + *last_rmap = rmap; + else if (mergeable_rmaps(last_rmap, &rmap)) + last_rmap->rm_blockcount += rmap.rm_blockcount; + else { + error = slab_add(ag_rmaps[agno].ar_rmaps, last_rmap); + if (error) + return error; + *last_rmap = rmap; + } + + return error; +} + +/* Finish collecting inode data/attr fork rmaps. */ +int +finish_collecting_fork_rmaps( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + if (!needs_rmap_work(mp) || + ag_rmaps[agno].ar_last_rmap.rm_owner == XFS_RMAP_OWN_UNKNOWN) + return 0; + return slab_add(ag_rmaps[agno].ar_rmaps, &ag_rmaps[agno].ar_last_rmap); } /* add a raw rmap; these will be merged later */ diff --git a/repair/rmap.h b/repair/rmap.h index 4722266..69215e8 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -28,6 +28,8 @@ extern void init_rmaps(struct xfs_mount *); extern void free_rmaps(struct xfs_mount *); extern int add_rmap(struct xfs_mount *, xfs_ino_t, int, struct xfs_bmbt_irec *); +extern int finish_collecting_fork_rmaps(struct xfs_mount *mp, + xfs_agnumber_t agno); extern int add_ag_rmap(struct xfs_mount *, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, uint64_t owner); extern int add_bmbt_rmap(struct xfs_mount *, xfs_ino_t, int, xfs_fsblock_t); From darrick.wong@oracle.com Thu Jun 16 20:37:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 92F718241 for ; Thu, 16 Jun 2016 20:37:57 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1B433AC002 for ; Thu, 16 Jun 2016 18:37:56 -0700 (PDT) X-ASG-Debug-ID: 1466127475-04cbb01fec6a2b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 8wOAJYhbQGAhuTdi (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:37:55 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1bsLd006445 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:54 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1brAl003515 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:37:54 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1br9X028904; Fri, 17 Jun 2016 01:37:53 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:52 -0700 Subject: [PATCH 067/145] xfs_repair: look for mergeable rmaps From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 067/145] xfs_repair: look for mergeable rmaps To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:51 -0700 Message-ID: <146612747153.16048.4165884380771843048.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127475 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1430 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Check for adjacent mergeable rmaps; this is a sign that we've screwed up somehow. Signed-off-by: Darrick J. Wong --- repair/scan.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/repair/scan.c b/repair/scan.c index 6106d93..d72b257 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -787,6 +787,7 @@ ino_issparse( struct rmap_priv { struct aghdr_cnts *agcnts; struct xfs_rmap_irec high_key; + struct xfs_rmap_irec last_rec; }; static void @@ -943,6 +944,16 @@ advance: goto advance; } + /* Is this mergeable with the previous record? */ + if (mergeable_rmaps(&rmap_priv->last_rec, &key)) { + do_warn( + _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"), + i, agno, bno, name); + rmap_priv->last_rec.rm_blockcount += + key.rm_blockcount; + } else + rmap_priv->last_rec = key; + /* Check that we don't go past the high key. */ key.rm_startblock += key.rm_blockcount - 1; if (!XFS_RMAP_NON_INODE_OWNER(key.rm_owner) && @@ -1896,6 +1907,7 @@ validate_agf( memset(&priv.high_key, 0xFF, sizeof(priv.high_key)); priv.high_key.rm_blockcount = 0; priv.agcnts = agcnts; + priv.last_rec.rm_owner = XFS_RMAP_OWN_UNKNOWN; bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]); if (bno != 0 && verify_agbno(mp, agno, bno)) { scan_sbtree(bno, From darrick.wong@oracle.com Thu Jun 16 20:38:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B4F3F81DE for ; Thu, 16 Jun 2016 20:38:04 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 41E2DAC003 for ; Thu, 16 Jun 2016 18:38:04 -0700 (PDT) X-ASG-Debug-ID: 1466127482-04bdf01e1396310001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id OOGkVBAAgrBsoQui (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:02 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1c19U006746 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:02 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1c10W028255 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:01 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1bx7W011653; Fri, 17 Jun 2016 01:38:00 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:37:58 -0700 Subject: [PATCH 068/145] xfs_repair: check for impossible rmap record field combinations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 068/145] xfs_repair: check for impossible rmap record field combinations To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:37:57 -0700 Message-ID: <146612747761.16048.15516327575501310985.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127482 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1107 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Make sure there are no records or keys with impossible field combinations, such as non-inode records with offsets or flags. Signed-off-by: Darrick J. Wong --- repair/scan.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/repair/scan.c b/repair/scan.c index d72b257..ec41ba6 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -926,6 +926,18 @@ _("%s rmap btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), _("invalid owner in rmap btree record %d (%"PRId64" %u) block %u/%u\n"), i, owner, len, agno, bno); + /* Look for impossible record field combinations. */ + if (XFS_RMAP_NON_INODE_OWNER(key.rm_owner)) { + if (key.rm_flags) + do_warn( + _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with flags\n"), + i, agno, bno, name); + if (key.rm_offset) + do_warn( + _("record %d of block (%u/%u) in %s btree cannot have non-inode owner with offset\n"), + i, agno, bno, name); + } + /* Check for out of order records. */ if (i == 0) { advance: From darrick.wong@oracle.com Thu Jun 16 20:38:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 473FC825F for ; Thu, 16 Jun 2016 20:38:13 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id B2D2DAC001 for ; Thu, 16 Jun 2016 18:38:12 -0700 (PDT) X-ASG-Debug-ID: 1466127490-04cb6c542758090001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Np8Fij3utN5jbOkF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1c6kt019263 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:06 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1c5aq008165 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:05 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1c5uH001286; Fri, 17 Jun 2016 01:38:05 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:05 -0700 Subject: [PATCH 069/145] mkfs: set agsize prior to calculating minimum log size From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 069/145] mkfs: set agsize prior to calculating minimum log size To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:03 -0700 Message-ID: <146612748368.16048.1300674297898667346.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127490 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2331 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Each btree has its own maxlevels variable. Since the level count of certain btrees depend on agblocks, it's necessary to know the AG size prior to calculating the log reservations. These reservations are needed to calculate the log size and the kernel will refuse to mount if we guess too low, so stuff in the real agsize when we're formatting the log. Signed-off-by: Darrick J. Wong --- include/xfs_multidisk.h | 2 +- mkfs/maxtrres.c | 3 ++- mkfs/xfs_mkfs.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h index fe3e98f..4429dab 100644 --- a/include/xfs_multidisk.h +++ b/include/xfs_multidisk.h @@ -66,7 +66,7 @@ extern void parse_proto (xfs_mount_t *mp, struct fsxattr *fsx, char **pp); extern void res_failed (int err); /* maxtrres.c */ -extern int max_trans_res (int crcs_enabled, int dirversion, +extern int max_trans_res(unsigned long agsize, int crcs_enabled, int dirversion, int sectorlog, int blocklog, int inodelog, int dirblocklog, int logversion, int log_sunit, int finobt); diff --git a/mkfs/maxtrres.c b/mkfs/maxtrres.c index f48a0f7..c0b1b5d 100644 --- a/mkfs/maxtrres.c +++ b/mkfs/maxtrres.c @@ -29,6 +29,7 @@ int max_trans_res( + unsigned long agsize, int crcs_enabled, int dirversion, int sectorlog, @@ -50,7 +51,7 @@ max_trans_res( sbp->sb_sectsize = 1 << sbp->sb_sectlog; sbp->sb_blocklog = blocklog; sbp->sb_blocksize = 1 << blocklog; - sbp->sb_agblocks = XFS_AG_MIN_BYTES / (1 << blocklog); + sbp->sb_agblocks = agsize; sbp->sb_inodelog = inodelog; sbp->sb_inopblog = blocklog - inodelog; sbp->sb_inodesize = 1 << inodelog; diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 4b5df98..8b3cad8 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -2887,7 +2887,8 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), lsunit = (32 * 1024) >> blocklog; } - min_logblocks = max_trans_res(sb_feat.crcs_enabled, sb_feat.dir_version, + min_logblocks = max_trans_res(agsize, + sb_feat.crcs_enabled, sb_feat.dir_version, sectorlog, blocklog, inodelog, dirblocklog, sb_feat.log_version, lsunit, sb_feat.finobt); ASSERT(min_logblocks); From darrick.wong@oracle.com Thu Jun 16 20:38:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5EDD48269 for ; Thu, 16 Jun 2016 20:38:20 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2F5DC8F804B for ; Thu, 16 Jun 2016 18:38:20 -0700 (PDT) X-ASG-Debug-ID: 1466127497-04cbb01fec6a2f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id lq6MTDDUZBd8IQEI (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:17 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1cClS019352 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:13 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cCXG028476 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:12 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cBto029043; Fri, 17 Jun 2016 01:38:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:11 -0700 Subject: [PATCH 070/145] mkfs.xfs: create filesystems with reverse-mappings From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 070/145] mkfs.xfs: create filesystems with reverse-mappings To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, Dave Chinner Date: Thu, 16 Jun 2016 18:38:09 -0700 Message-ID: <146612748977.16048.8951256729197337882.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127497 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11450 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.75 X-Barracuda-Spam-Status: No, SCORE=0.75 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_RULE_7580D, BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.75 BSF_RULE_7580D Custom Rule 7580D From: Dave Chinner Create v5 filesystems with rmapbt turned on. Document the rmapbt options to mkfs, and initialize the extra field we added for reflink support. v2: Turn on the rmapbt feature when calculating the minimum log size. Signed-off-by: Dave Chinner [darrick.wong@oracle.com: split patch, add commit message and extra fields] Signed-off-by: Darrick J. Wong --- include/xfs_multidisk.h | 2 - man/man8/mkfs.xfs.8 | 20 +++++++ mkfs/maxtrres.c | 5 +- mkfs/xfs_mkfs.c | 138 +++++++++++++++++++++++++++++++++++++++++------ 4 files changed, 145 insertions(+), 20 deletions(-) diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h index 4429dab..8dc3027 100644 --- a/include/xfs_multidisk.h +++ b/include/xfs_multidisk.h @@ -68,6 +68,6 @@ extern void res_failed (int err); /* maxtrres.c */ extern int max_trans_res(unsigned long agsize, int crcs_enabled, int dirversion, int sectorlog, int blocklog, int inodelog, int dirblocklog, - int logversion, int log_sunit, int finobt); + int logversion, int log_sunit, int finobt, int rmapbt); #endif /* __XFS_MULTIDISK_H__ */ diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8 index 980b0e1..d88d314 100644 --- a/man/man8/mkfs.xfs.8 +++ b/man/man8/mkfs.xfs.8 @@ -193,6 +193,26 @@ is used, the free inode btree feature is not supported and is disabled. .BI uuid= value Use the given value as the filesystem UUID for the newly created filesystem. The default is to generate a random UUID. +.TP +.BI rmapbt= value +This option enables the creation of a reverse-mapping btree index in each +allocation group. The value is either 0 to disable the feature, or 1 to +create the btree. +.IP +The reverse mapping btree maps filesystem blocks to the owner of the +filesystem block. Most of the mappings will be to an inode number and an +offset, though there will also be mappings to filesystem metadata. This +secondary metadata can be used to validate the primary metadata or to +pinpoint exactly which data has been lost when a disk error occurs. +.IP +By default, +.B mkfs.xfs +will not create reverse mapping btrees. This feature is only available +for filesystems created with the (default) +.B \-m crc=1 +option set. When the option +.B \-m crc=0 +is used, the reverse mapping btree feature is not supported and is disabled. .RE .TP .BI \-d " data_section_options" diff --git a/mkfs/maxtrres.c b/mkfs/maxtrres.c index c0b1b5d..fc24eac 100644 --- a/mkfs/maxtrres.c +++ b/mkfs/maxtrres.c @@ -38,7 +38,8 @@ max_trans_res( int dirblocklog, int logversion, int log_sunit, - int finobt) + int finobt, + int rmapbt) { xfs_sb_t *sbp; xfs_mount_t mount; @@ -72,6 +73,8 @@ max_trans_res( XFS_DFL_SB_VERSION_BITS; if (finobt) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_FINOBT; + if (rmapbt) + sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT; libxfs_mount(&mount, sbp, 0,0,0,0); maxfsb = xfs_log_calc_minimum_size(&mount); diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 8b3cad8..634dcfd 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -680,6 +680,8 @@ struct opt_params mopts = { "finobt", #define M_UUID 2 "uuid", +#define M_RMAPBT 3 + "rmapbt", NULL }, .subopt_params = { @@ -699,6 +701,12 @@ struct opt_params mopts = { .conflicts = { LAST_CONFLICT }, .defaultval = SUBOPT_NEEDS_VAL, }, + { .index = M_RMAPBT, + .conflicts = { LAST_CONFLICT }, + .minval = 0, + .maxval = 1, + .defaultval = 0, + }, }, }; @@ -1454,6 +1462,7 @@ struct sb_feat_args { bool crcs_enabled; bool dirftype; bool parent_pointers; + bool rmapbt; }; static void @@ -1524,6 +1533,8 @@ sb_set_features( if (fp->finobt) sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT; + if (fp->rmapbt) + sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT; /* * Sparse inode chunk support has two main inode alignment requirements. @@ -1784,6 +1795,7 @@ main( .crcs_enabled = true, .dirftype = true, .parent_pointers = false, + .rmapbt = false, }; platform_uuid_generate(&uuid); @@ -2073,6 +2085,10 @@ main( if (platform_uuid_parse(value, &uuid)) illegal(optarg, "m uuid"); break; + case M_RMAPBT: + sb_feat.rmapbt = getnum( + value, &mopts, M_RMAPBT); + break; default: unknown('m', value); } @@ -2409,6 +2425,20 @@ _("sparse inodes not supported without CRC support\n")); } sb_feat.spinodes = 0; + if (sb_feat.rmapbt) { + fprintf(stderr, +_("rmapbt not supported without CRC support\n")); + usage(); + } + sb_feat.rmapbt = false; + } + + + if (sb_feat.rmapbt && xi.rtname) { + fprintf(stderr, +_("rmapbt not supported with realtime devices\n")); + usage(); + sb_feat.rmapbt = false; } if (nsflag || nlflag) { @@ -2890,7 +2920,8 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), min_logblocks = max_trans_res(agsize, sb_feat.crcs_enabled, sb_feat.dir_version, sectorlog, blocklog, inodelog, dirblocklog, - sb_feat.log_version, lsunit, sb_feat.finobt); + sb_feat.log_version, lsunit, sb_feat.finobt, + sb_feat.rmapbt); ASSERT(min_logblocks); min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks); if (!logsize && dblocks >= (1024*1024*1024) >> blocklog) @@ -2965,7 +2996,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; /* - * sb_versionnum and finobt flags must be set before we use + * sb_versionnum, finobt and rmapbt flags must be set before we use * xfs_prealloc_blocks(). */ sb_set_features(&mp->m_sb, &sb_feat, sectorsize, lsectorsize, dsunit); @@ -3025,7 +3056,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), printf(_( "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" - " =%-22s crc=%-8u finobt=%u, sparse=%u\n" + " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" @@ -3036,6 +3067,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), "", sectorsize, sb_feat.attr_version, !sb_feat.projid16bit, "", sb_feat.crcs_enabled, sb_feat.finobt, sb_feat.spinodes, + sb_feat.rmapbt, "", blocksize, (long long)dblocks, imaxpct, "", dsunit, dswidth, sb_feat.dir_version, dirblocksize, sb_feat.nci, @@ -3217,6 +3249,12 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), agf->agf_levels[XFS_BTNUM_CNTi] = cpu_to_be32(1); pag->pagf_levels[XFS_BTNUM_BNOi] = 1; pag->pagf_levels[XFS_BTNUM_CNTi] = 1; + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + agf->agf_roots[XFS_BTNUM_RMAPi] = + cpu_to_be32(XFS_RMAP_BLOCK(mp)); + agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1); + } + agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); agf->agf_flcount = 0; @@ -3404,24 +3442,88 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), /* * Free INO btree root block */ - if (!sb_feat.finobt) { - xfs_perag_put(pag); - continue; + if (sb_feat.finobt) { + buf = libxfs_getbuf(mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)), + bsize); + buf->b_ops = &xfs_inobt_buf_ops; + block = XFS_BUF_TO_BLOCK(buf); + memset(block, 0, blocksize); + if (xfs_sb_version_hascrc(&mp->m_sb)) + xfs_btree_init_block(mp, buf, XFS_FIBT_CRC_MAGIC, 0, 0, + agno, XFS_BTREE_CRC_BLOCKS); + else + xfs_btree_init_block(mp, buf, XFS_FIBT_MAGIC, 0, 0, + agno, 0); + libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); } - buf = libxfs_getbuf(mp->m_ddev_targp, - XFS_AGB_TO_DADDR(mp, agno, XFS_FIBT_BLOCK(mp)), + /* RMAP btree root block */ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) { + struct xfs_rmap_rec *rrec; + + buf = libxfs_getbuf(mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, XFS_RMAP_BLOCK(mp)), bsize); - buf->b_ops = &xfs_inobt_buf_ops; - block = XFS_BUF_TO_BLOCK(buf); - memset(block, 0, blocksize); - if (xfs_sb_version_hascrc(&mp->m_sb)) - xfs_btree_init_block(mp, buf, XFS_FIBT_CRC_MAGIC, 0, 0, + buf->b_ops = &xfs_rmapbt_buf_ops; + block = XFS_BUF_TO_BLOCK(buf); + memset(block, 0, blocksize); + + xfs_btree_init_block(mp, buf, XFS_RMAP_CRC_MAGIC, 0, 0, agno, XFS_BTREE_CRC_BLOCKS); - else - xfs_btree_init_block(mp, buf, XFS_FIBT_MAGIC, 0, 0, - agno, 0); - libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); + + /* + * mark the AG header regions as static metadata + * The BNO btree block is the first block after the + * headers, so it's location defines the size of region + * the static metadata consumes. + */ + rrec = XFS_RMAP_REC_ADDR(block, 1); + rrec->rm_startblock = 0; + rrec->rm_blockcount = cpu_to_be32(XFS_BNO_BLOCK(mp)); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_FS); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + /* account freespace btree root blocks */ + rrec = XFS_RMAP_REC_ADDR(block, 2); + rrec->rm_startblock = cpu_to_be32(XFS_BNO_BLOCK(mp)); + rrec->rm_blockcount = cpu_to_be32(2); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + /* account inode btree root blocks */ + rrec = XFS_RMAP_REC_ADDR(block, 3); + rrec->rm_startblock = cpu_to_be32(XFS_IBT_BLOCK(mp)); + rrec->rm_blockcount = cpu_to_be32(XFS_RMAP_BLOCK(mp) - + XFS_IBT_BLOCK(mp)); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_INOBT); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + /* account for rmap btree root */ + rrec = XFS_RMAP_REC_ADDR(block, 4); + rrec->rm_startblock = cpu_to_be32(XFS_RMAP_BLOCK(mp)); + rrec->rm_blockcount = cpu_to_be32(1); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_AG); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + + /* account for the log space */ + if (loginternal && agno == logagno) { + rrec = XFS_RMAP_REC_ADDR(block, 5); + rrec->rm_startblock = cpu_to_be32( + XFS_FSB_TO_AGBNO(mp, logstart)); + rrec->rm_blockcount = cpu_to_be32(logblocks); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_LOG); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + } + + libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); + } + xfs_perag_put(pag); } @@ -3646,7 +3748,7 @@ usage( void ) { fprintf(stderr, _("Usage: %s\n\ /* blocksize */ [-b log=n|size=num]\n\ -/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx]\n\ +/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1]\n\ /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\ (sunit=value,swidth=value|su=num,sw=num|noalign),\n\ sectlog=n|sectsize=num\n\ From darrick.wong@oracle.com Thu Jun 16 20:38:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B5D6F8271 for ; Thu, 16 Jun 2016 20:38:22 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2F17BAC001 for ; Thu, 16 Jun 2016 18:38:22 -0700 (PDT) X-ASG-Debug-ID: 1466127499-04cb6c5426580b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id mwl7ayhAq3QS1bcT (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1cION006865 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:18 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cH5X028563 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:18 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1cHxW001309; Fri, 17 Jun 2016 01:38:17 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:17 -0700 Subject: [PATCH 071/145] xfs: count the blocks in a btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 071/145] xfs: count the blocks in a btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:16 -0700 Message-ID: <146612749607.16048.847098109670912569.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127500 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1642 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a helper method to count the number of blocks in a short form btree. The refcount and rmap btrees need to know the number of blocks already in use to set up their per-AG block reservations during mount. v2: Use btree_visit_blocks instead of open-coding our own traversal routine. Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.c | 22 ++++++++++++++++++++++ libxfs/xfs_btree.h | 2 ++ 2 files changed, 24 insertions(+) diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index db0267a..1e547f8 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -4799,3 +4799,25 @@ xfs_btree_query_range( return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, fn, priv); } + +int +xfs_btree_count_blocks_helper( + struct xfs_btree_cur *cur, + int level, + void *data) +{ + xfs_extlen_t *blocks = data; + (*blocks)++; + + return 0; +} + +/* Count the blocks in a btree and return the result in *blocks. */ +int +xfs_btree_count_blocks( + struct xfs_btree_cur *cur, + xfs_extlen_t *blocks) +{ + return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper, + blocks); +} diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 9963c48..6fa13a9 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -519,4 +519,6 @@ typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level, int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, xfs_btree_visit_blocks_fn fn, void *data); +int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks); + #endif /* __XFS_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:38:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 7487E8234 for ; Thu, 16 Jun 2016 20:38:34 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 269FF30404E for ; Thu, 16 Jun 2016 18:38:34 -0700 (PDT) X-ASG-Debug-ID: 1466127509-04bdf01e1796360001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id kQz5ew8FGRLwU3R8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1cOaV019417 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:24 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cO4l004542 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:24 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cNan029062; Fri, 17 Jun 2016 01:38:24 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:23 -0700 Subject: [PATCH 072/145] xfs: set up per-AG free space reservations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 072/145] xfs: set up per-AG free space reservations To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:22 -0700 Message-ID: <146612750213.16048.14582215552508681042.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127509 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 27586 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines One unfortunate quirk of the reference count btree -- it can expand in size when blocks are written to *other* allocation groups if, say, one large extent becomes a lot of tiny extents. Since we don't want to start throwing errors in the middle of CoWing, we need to reserve some blocks to handle future expansion. Use the count of how many reserved blocks we need to have on hand to create a virtual reservation in the AG. Through selective clamping of the maximum length of allocation requests and of the length of the longest free extent, we can make it look like there's less free space in the AG unless the reservation owner is asking for blocks. In other words, play some accounting tricks in-core to make sure that we always have blocks available. On the plus side, there's nothing to clean up if we crash, which is contrast to the strategy that the rough draft used (actually removing extents from the freespace btrees). v2: There's really only two kinds of per-AG reservation pools -- one to feed the AGFL (rmapbt), and one to feed everything else (refcountbt). Bearing that in mind, we can embed the reservation controls in xfs_perag and greatly simplify the block accounting. Furthermore, fix some longstanding accounting bugs that were a direct result of the goofy "allocate a block and later fix up the accounting" strategy by integrating the reservation accounting code more tightly with the allocator. This eliminates the ENOSPC complaints resulting from refcount btree splits during truncate operations. Signed-off-by: Darrick J. Wong --- include/xfs_mount.h | 34 +++++ include/xfs_trace.h | 9 + libxfs/Makefile | 2 libxfs/defer_item.c | 3 libxfs/xfs_ag_resv.c | 317 +++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_ag_resv.h | 35 +++++ libxfs/xfs_alloc.c | 93 ++++++++++--- libxfs/xfs_alloc.h | 8 + libxfs/xfs_bmap.c | 6 + libxfs/xfs_ialloc_btree.c | 2 10 files changed, 479 insertions(+), 30 deletions(-) create mode 100644 libxfs/xfs_ag_resv.c create mode 100644 libxfs/xfs_ag_resv.h diff --git a/include/xfs_mount.h b/include/xfs_mount.h index 5cd9464..c452de2 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -112,6 +112,20 @@ typedef struct xfs_mount { struct xlog *m_log; } xfs_mount_t; +/* per-AG block reservation data structures*/ +enum xfs_ag_resv_type { + XFS_AG_RESV_NONE = 0, + XFS_AG_RESV_METADATA, + XFS_AG_RESV_AGFL, +}; + +struct xfs_ag_resv { + /* number of block reserved here */ + xfs_extlen_t ar_reserved; + /* number of blocks originally asked for */ + xfs_extlen_t ar_asked; +}; + /* * Per-ag incore structure, copies of information in agf and agi, * to improve the performance of allocation group selection. @@ -142,8 +156,28 @@ typedef struct xfs_perag { xfs_agino_t pagl_leftrec; xfs_agino_t pagl_rightrec; int pagb_count; /* pagb slots in use */ + + /* Blocks reserved for all kinds of metadata. */ + struct xfs_ag_resv pag_meta_resv; + /* Blocks reserved for just AGFL-based metadata. */ + struct xfs_ag_resv pag_agfl_resv; } xfs_perag_t; +static inline struct xfs_ag_resv * +xfs_perag_resv( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + switch (type) { + case XFS_AG_RESV_METADATA: + return &pag->pag_meta_resv; + case XFS_AG_RESV_AGFL: + return &pag->pag_agfl_resv; + default: + return NULL; + } +} + #define LIBXFS_MOUNT_DEBUGGER 0x0001 #define LIBXFS_MOUNT_32BITINODES 0x0002 #define LIBXFS_MOUNT_32BITINOOPT 0x0004 diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 00c2ccb..040f2f0 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -212,6 +212,15 @@ #define trace_xfs_rmap_convert_error(...) ((void) 0) #define trace_xfs_rmap_find_left_neighbor_result(...) ((void) 0) +#define trace_xfs_ag_resv_critical(...) ((void) 0) +#define trace_xfs_ag_resv_needed(...) ((void) 0) +#define trace_xfs_ag_resv_free(...) ((void) 0) +#define trace_xfs_ag_resv_free_error(...) ((void) 0) +#define trace_xfs_ag_resv_init(...) ((void) 0) +#define trace_xfs_ag_resv_init_error(...) ((void) 0) +#define trace_xfs_ag_resv_alloc_extent(...) ((void) 0) +#define trace_xfs_ag_resv_free_extent(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/Makefile b/libxfs/Makefile index df47da2..588c663 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -18,6 +18,7 @@ PKGHFILES = xfs_fs.h \ xfs_log_format.h HFILES = \ + xfs_ag_resv.h \ xfs_alloc.h \ xfs_alloc_btree.h \ xfs_attr_leaf.h \ @@ -59,6 +60,7 @@ CFILES = cache.c \ rdwr.c \ trans.c \ util.c \ + xfs_ag_resv.c \ xfs_alloc.c \ xfs_alloc_btree.c \ xfs_attr.c \ diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index 381c969..d2e4ad0 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -93,7 +93,8 @@ xfs_bmap_free_finish_item( free = container_of(item, struct xfs_bmap_free_item, xbfi_list); error = xfs_free_extent(tp, free->xbfi_startblock, - free->xbfi_blockcount, &free->xbfi_oinfo); + free->xbfi_blockcount, &free->xbfi_oinfo, + XFS_AG_RESV_NONE); kmem_free(free); return error; } diff --git a/libxfs/xfs_ag_resv.c b/libxfs/xfs_ag_resv.c new file mode 100644 index 0000000..03413e4 --- /dev/null +++ b/libxfs/xfs_ag_resv.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_alloc.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" +#include "xfs_trans.h" +#include "xfs_bit.h" +#include "xfs_bmap.h" +#include "xfs_bmap_btree.h" +#include "xfs_ag_resv.h" +#include "xfs_trans_space.h" +#include "xfs_rmap_btree.h" +#include "xfs_btree.h" + +/* + * Per-AG Block Reservations + * + * For some kinds of allocation group metadata structures, it is advantageous + * to reserve a small number of blocks in each AG so that future expansions of + * that data structure do not encounter ENOSPC because errors during a btree + * split cause the filesystem to go offline. + * + * Prior to the introduction of reflink, this wasn't an issue because the free + * space btrees maintain a reserve of space (the AGFL) to handle any expansion + * that may be necessary; and allocations of other metadata (inodes, BMBT, + * dir/attr) aren't restricted to a single AG. However, with reflink it is + * possible to allocate all the space in an AG, have subsequent reflink/CoW + * activity expand the refcount btree, and discover that there's no space left + * to handle that expansion. Since we can calculate the maximum size of the + * refcount btree, we can reserve space for it and avoid ENOSPC. + * + * Handling per-AG reservations consists of three changes to the allocator's + * behavior: First, because these reservations are always needed, we decrease + * the ag_max_usable counter to reflect the size of the AG after the reserved + * blocks are taken. Second, the reservations must be reflected in the + * fdblocks count to maintain proper accounting. Third, each AG must maintain + * its own reserved block counter so that we can calculate the amount of space + * that must remain free to maintain the reservations. Fourth, the "remaining + * reserved blocks" count must be used when calculating the length of the + * longest free extent in an AG and to clamp maxlen in the per-AG allocation + * functions. In other words, we maintain a virtual allocation via in-core + * accounting tricks so that we don't have to clean up after a crash. :) + * + * Reserved blocks can be managed by passing one of the enum xfs_ag_resv_type + * values via struct xfs_alloc_arg or directly to the xfs_free_extent + * function. It might seem a little funny to maintain a reservoir of blocks + * to feed another reservoir, but the AGFL only holds enough blocks to get + * through the next transaction. The per-AG reservation is to ensure (we + * hope) that each AG never runs out of blocks. Each data structure wanting + * to use the reservation system should update ask/used in xfs_ag_resv_init. + */ + +/* + * Are we critically low on blocks? For now we'll define that as the number + * of blocks we can get our hands on being less than 10% of what we reserved + * or less than some arbitrary number (eight). + */ +bool +xfs_ag_resv_critical( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + xfs_extlen_t avail; + xfs_extlen_t orig; + + switch (type) { + case XFS_AG_RESV_METADATA: + avail = pag->pagf_freeblks - pag->pag_agfl_resv.ar_reserved; + orig = pag->pag_meta_resv.ar_asked; + break; + case XFS_AG_RESV_AGFL: + avail = pag->pagf_freeblks + pag->pagf_flcount - + pag->pag_meta_resv.ar_reserved; + orig = pag->pag_agfl_resv.ar_asked; + break; + default: + ASSERT(0); + return false; + } + + trace_xfs_ag_resv_critical(pag, type, avail); + + return avail < orig / 10 || avail < XFS_BTREE_MAXLEVELS; +} + +/* + * How many blocks are reserved but not used, and therefore must not be + * allocated away? + */ +xfs_extlen_t +xfs_ag_resv_needed( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + xfs_extlen_t len; + + len = pag->pag_meta_resv.ar_reserved + pag->pag_agfl_resv.ar_reserved; + switch (type) { + case XFS_AG_RESV_METADATA: + case XFS_AG_RESV_AGFL: + len -= xfs_perag_resv(pag, type)->ar_reserved; + break; + case XFS_AG_RESV_NONE: + /* empty */ + break; + default: + ASSERT(0); + } + + trace_xfs_ag_resv_needed(pag, type, len); + + return len; +} + +/* Clean out a reservation */ +static int +__xfs_ag_resv_free( + struct xfs_perag *pag, + enum xfs_ag_resv_type type) +{ + struct xfs_ag_resv *resv; + struct xfs_ag_resv t; + int error; + + trace_xfs_ag_resv_free(pag, type, 0); + + resv = xfs_perag_resv(pag, type); + t = *resv; + resv->ar_reserved = 0; + resv->ar_asked = 0; + pag->pag_mount->m_ag_max_usable += t.ar_asked; + + error = xfs_mod_fdblocks(pag->pag_mount, t.ar_reserved, true); + if (error) + trace_xfs_ag_resv_free_error(pag->pag_mount, pag->pag_agno, + error, _RET_IP_); + return error; +} + +/* Free a per-AG reservation. */ +int +xfs_ag_resv_free( + struct xfs_perag *pag) +{ + int error = 0; + int err2; + + err2 = __xfs_ag_resv_free(pag, XFS_AG_RESV_AGFL); + if (err2 && !error) + error = err2; + err2 = __xfs_ag_resv_free(pag, XFS_AG_RESV_METADATA); + if (err2 && !error) + error = err2; + return error; +} + +static int +__xfs_ag_resv_init( + struct xfs_perag *pag, + enum xfs_ag_resv_type type, + xfs_extlen_t ask, + xfs_extlen_t used) +{ + struct xfs_mount *mp = pag->pag_mount; + struct xfs_ag_resv *resv; + int error; + + resv = xfs_perag_resv(pag, type); + if (used > ask) + ask = used; + resv->ar_asked = ask; + resv->ar_reserved = ask - used; + mp->m_ag_max_usable -= ask; + + trace_xfs_ag_resv_init(pag, type, ask); + + error = xfs_mod_fdblocks(mp, -(int64_t)resv->ar_reserved, true); + if (error) + trace_xfs_ag_resv_init_error(pag->pag_mount, pag->pag_agno, + error, _RET_IP_); + + return error; +} + +/* Create a per-AG block reservation. */ +int +xfs_ag_resv_init( + struct xfs_perag *pag) +{ + xfs_extlen_t ask; + xfs_extlen_t used; + int error = 0; + int err2; + + if (pag->pag_meta_resv.ar_asked) + goto init_agfl; + + /* Create the metadata reservation. */ + ask = used = 0; + + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, ask, used); + if (err2 && !error) + error = err2; + +init_agfl: + if (pag->pag_agfl_resv.ar_asked) + return error; + + /* Create the AGFL metadata reservation */ + ask = used = 0; + + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_AGFL, ask, used); + if (err2 && !error) + error = err2; + + return error; +} + +/* Allocate a block from the reservation. */ +void +xfs_ag_resv_alloc_extent( + struct xfs_perag *pag, + enum xfs_ag_resv_type type, + struct xfs_alloc_arg *args) +{ + struct xfs_ag_resv *resv; + xfs_extlen_t leftover; + uint field; + + trace_xfs_ag_resv_alloc_extent(pag, type, args->len); + + switch (type) { + case XFS_AG_RESV_METADATA: + case XFS_AG_RESV_AGFL: + resv = xfs_perag_resv(pag, type); + break; + default: + ASSERT(0); + /* fall through */ + case XFS_AG_RESV_NONE: + field = args->wasdel ? XFS_TRANS_SB_RES_FDBLOCKS : + XFS_TRANS_SB_FDBLOCKS; + xfs_trans_mod_sb(args->tp, field, -(int64_t)args->len); + return; + } + + if (args->len > resv->ar_reserved) { + leftover = args->len - resv->ar_reserved; + if (type != XFS_AG_RESV_AGFL) + xfs_trans_mod_sb(args->tp, XFS_TRANS_SB_FDBLOCKS, + -(int64_t)leftover); + resv->ar_reserved = 0; + } else + resv->ar_reserved -= args->len; +} + +/* Free a block to the reservation. */ +void +xfs_ag_resv_free_extent( + struct xfs_perag *pag, + enum xfs_ag_resv_type type, + struct xfs_trans *tp, + xfs_extlen_t len) +{ + xfs_extlen_t leftover; + struct xfs_ag_resv *resv; + + trace_xfs_ag_resv_free_extent(pag, type, len); + + switch (type) { + case XFS_AG_RESV_METADATA: + case XFS_AG_RESV_AGFL: + resv = xfs_perag_resv(pag, type); + break; + default: + ASSERT(0); + /* fall through */ + case XFS_AG_RESV_NONE: + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (int64_t)len); + return; + } + + if (resv->ar_reserved + len > resv->ar_asked) { + leftover = resv->ar_reserved + len - resv->ar_asked; + if (type != XFS_AG_RESV_AGFL) + xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, + (int64_t)leftover); + resv->ar_reserved = resv->ar_asked; + } else + resv->ar_reserved += len; +} diff --git a/libxfs/xfs_ag_resv.h b/libxfs/xfs_ag_resv.h new file mode 100644 index 0000000..8d6c687 --- /dev/null +++ b/libxfs/xfs_ag_resv.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_AG_RESV_H__ +#define __XFS_AG_RESV_H__ + +int xfs_ag_resv_free(struct xfs_perag *pag); +int xfs_ag_resv_init(struct xfs_perag *pag); + +bool xfs_ag_resv_critical(struct xfs_perag *pag, enum xfs_ag_resv_type type); +xfs_extlen_t xfs_ag_resv_needed(struct xfs_perag *pag, + enum xfs_ag_resv_type type); + +void xfs_ag_resv_alloc_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, + struct xfs_alloc_arg *args); +void xfs_ag_resv_free_extent(struct xfs_perag *pag, enum xfs_ag_resv_type type, + struct xfs_trans *tp, xfs_extlen_t len); + +#endif /* __XFS_AG_RESV_H__ */ diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 2f943db..7b9040e 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -33,6 +33,7 @@ #include "xfs_cksum.h" #include "xfs_trace.h" #include "xfs_trans.h" +#include "xfs_ag_resv.h" struct workqueue_struct *xfs_alloc_wq; @@ -678,12 +679,29 @@ xfs_alloc_ag_vextent( xfs_alloc_arg_t *args) /* argument structure for allocation */ { int error=0; + xfs_extlen_t reservation; + xfs_extlen_t oldmax; ASSERT(args->minlen > 0); ASSERT(args->maxlen > 0); ASSERT(args->minlen <= args->maxlen); ASSERT(args->mod < args->prod); ASSERT(args->alignment > 0); + + /* + * Clamp maxlen to the amount of free space minus any reservations + * that have been made. + */ + oldmax = args->maxlen; + reservation = xfs_ag_resv_needed(args->pag, args->resv); + if (args->maxlen > args->pag->pagf_freeblks - reservation) + args->maxlen = args->pag->pagf_freeblks - reservation; + if (args->maxlen == 0) { + args->agbno = NULLAGBLOCK; + args->maxlen = oldmax; + return 0; + } + /* * Branch to correct routine based on the type. */ @@ -703,12 +721,14 @@ xfs_alloc_ag_vextent( /* NOTREACHED */ } + args->maxlen = oldmax; + if (error || args->agbno == NULLAGBLOCK) return error; ASSERT(args->len >= args->minlen); ASSERT(args->len <= args->maxlen); - ASSERT(!args->wasfromfl || !args->isfl); + ASSERT(!args->wasfromfl || args->resv != XFS_AG_RESV_AGFL); ASSERT(args->agbno % args->alignment == 0); /* if not file data, insert new block into the reverse map btree */ @@ -730,12 +750,7 @@ xfs_alloc_ag_vextent( args->agbno, args->len)); } - if (!args->isfl) { - xfs_trans_mod_sb(args->tp, args->wasdel ? - XFS_TRANS_SB_RES_FDBLOCKS : - XFS_TRANS_SB_FDBLOCKS, - -((long)(args->len))); - } + xfs_ag_resv_alloc_extent(args->pag, args->resv, args); XFS_STATS_INC(args->mp, xs_allocx); XFS_STATS_ADD(args->mp, xs_allocb, args->len); @@ -1597,7 +1612,8 @@ xfs_alloc_ag_vextent_small( * to respect minleft even when pulling from the * freelist. */ - else if (args->minlen == 1 && args->alignment == 1 && !args->isfl && + else if (args->minlen == 1 && args->alignment == 1 && + args->resv != XFS_AG_RESV_AGFL && (be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_flcount) > args->minleft)) { error = xfs_alloc_get_freelist(args->tp, args->agbp, &fbno, 0); @@ -1668,7 +1684,7 @@ xfs_free_ag_extent( xfs_agblock_t bno, /* starting block number */ xfs_extlen_t len, /* length of extent */ struct xfs_owner_info *oinfo, /* extent owner */ - int isfl) /* set if is freelist blocks - no sb acctg */ + enum xfs_ag_resv_type type) /* extent reservation type */ { xfs_btree_cur_t *bno_cur; /* cursor for by-block btree */ xfs_btree_cur_t *cnt_cur; /* cursor for by-size btree */ @@ -1896,21 +1912,22 @@ xfs_free_ag_extent( */ pag = xfs_perag_get(mp, agno); error = xfs_alloc_update_counters(tp, pag, agbp, len); + xfs_ag_resv_free_extent(pag, type, tp, len); xfs_perag_put(pag); if (error) goto error0; - if (!isfl) - xfs_trans_mod_sb(tp, XFS_TRANS_SB_FDBLOCKS, (long)len); XFS_STATS_INC(mp, xs_freex); XFS_STATS_ADD(mp, xs_freeb, len); - trace_xfs_free_extent(mp, agno, bno, len, isfl, haveleft, haveright); + trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL, + haveleft, haveright); return 0; error0: - trace_xfs_free_extent(mp, agno, bno, len, isfl, -1, -1); + trace_xfs_free_extent(mp, agno, bno, len, type == XFS_AG_RESV_AGFL, + -1, -1); if (bno_cur) xfs_btree_del_cursor(bno_cur, XFS_BTREE_ERROR); if (cnt_cur) @@ -1935,21 +1952,43 @@ xfs_alloc_compute_maxlevels( } /* - * Find the length of the longest extent in an AG. + * Find the length of the longest extent in an AG. The 'need' parameter + * specifies how much space we're going to need for the AGFL and the + * 'reserved' parameter tells us how many blocks in this AG are reserved for + * other callers. */ xfs_extlen_t xfs_alloc_longest_free_extent( struct xfs_mount *mp, struct xfs_perag *pag, - xfs_extlen_t need) + xfs_extlen_t need, + xfs_extlen_t reserved) { xfs_extlen_t delta = 0; + /* + * If the AGFL needs a recharge, we'll have to subtract that from the + * longest extent. + */ if (need > pag->pagf_flcount) delta = need - pag->pagf_flcount; + /* + * If we cannot maintain others' reservations with space from the + * not-longest freesp extents, we'll have to subtract /that/ from + * the longest extent too. + */ + if (pag->pagf_freeblks - pag->pagf_longest < reserved) + delta += reserved - (pag->pagf_freeblks - pag->pagf_longest); + + /* + * If the longest extent is long enough to satisfy all the + * reservations and AGFL rules in place, we can return this extent. + */ if (pag->pagf_longest > delta) return pag->pagf_longest - delta; + + /* Otherwise, let the caller try for 1 block if there's space. */ return pag->pagf_flcount > 0 || pag->pagf_longest > 0; } @@ -1989,20 +2028,24 @@ xfs_alloc_space_available( { struct xfs_perag *pag = args->pag; xfs_extlen_t longest; + xfs_extlen_t reservation; /* blocks that are still reserved */ int available; if (flags & XFS_ALLOC_FLAG_FREEING) return true; + reservation = xfs_ag_resv_needed(pag, args->resv); + /* do we have enough contiguous free space for the allocation? */ - longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free); + longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free, + reservation); if ((args->minlen + args->alignment + args->minalignslop - 1) > longest) return false; - /* do have enough free space remaining for the allocation? */ + /* do we have enough free space remaining for the allocation? */ available = (int)(pag->pagf_freeblks + pag->pagf_flcount - - min_free - args->total); - if (available < (int)args->minleft) + reservation - min_free - args->total); + if (available < (int)args->minleft || available <= 0) return false; return true; @@ -2108,7 +2151,8 @@ xfs_alloc_fix_freelist( if (error) goto out_agbp_relse; error = xfs_free_ag_extent(tp, agbp, args->agno, bno, 1, - &targs.oinfo, 1); + &targs.oinfo, + XFS_AG_RESV_AGFL); if (error) goto out_agbp_relse; bp = xfs_btree_get_bufs(mp, tp, args->agno, bno, 0); @@ -2122,7 +2166,7 @@ xfs_alloc_fix_freelist( xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG); targs.agbp = agbp; targs.agno = args->agno; - targs.alignment = targs.minlen = targs.prod = targs.isfl = 1; + targs.alignment = targs.minlen = targs.prod = 1; targs.type = XFS_ALLOCTYPE_THIS_AG; targs.pag = pag; error = xfs_alloc_read_agfl(mp, tp, targs.agno, &agflbp); @@ -2133,6 +2177,7 @@ xfs_alloc_fix_freelist( while (pag->pagf_flcount < need) { targs.agbno = 0; targs.maxlen = need - pag->pagf_flcount; + targs.resv = XFS_AG_RESV_AGFL; /* Allocate as many blocks as possible at once. */ error = xfs_alloc_ag_vextent(&targs); @@ -2811,7 +2856,8 @@ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ - struct xfs_owner_info *oinfo) /* extent owner */ + struct xfs_owner_info *oinfo, /* extent owner */ + enum xfs_ag_resv_type type) /* block reservation type */ { struct xfs_mount *mp = tp->t_mountp; struct xfs_buf *agbp; @@ -2820,6 +2866,7 @@ xfs_free_extent( int error; ASSERT(len != 0); + ASSERT(type != XFS_AG_RESV_AGFL); trace_xfs_bmap_free_deferred(mp, agno, 0, agbno, len); @@ -2839,7 +2886,7 @@ xfs_free_extent( agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), err); - error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, 0); + error = xfs_free_ag_extent(tp, agbp, agno, agbno, len, oinfo, type); if (error) goto err; diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 7b9e67e..9f6373a 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -87,10 +87,10 @@ typedef struct xfs_alloc_arg { xfs_alloctype_t otype; /* original allocation type */ char wasdel; /* set if allocation was prev delayed */ char wasfromfl; /* set if allocation is from freelist */ - char isfl; /* set if is freelist blocks - !acctg */ char userdata; /* mask defining userdata treatment */ xfs_fsblock_t firstblock; /* io first block allocated */ struct xfs_owner_info oinfo; /* owner of blocks being allocated */ + enum xfs_ag_resv_type resv; /* block reservation to use */ } xfs_alloc_arg_t; /* @@ -106,7 +106,8 @@ unsigned int xfs_alloc_set_aside(struct xfs_mount *mp); unsigned int xfs_alloc_ag_max_usable(struct xfs_mount *mp); xfs_extlen_t xfs_alloc_longest_free_extent(struct xfs_mount *mp, - struct xfs_perag *pag, xfs_extlen_t need); + struct xfs_perag *pag, xfs_extlen_t need, + xfs_extlen_t reserved); unsigned int xfs_alloc_min_freelist(struct xfs_mount *mp, struct xfs_perag *pag); @@ -184,7 +185,8 @@ xfs_free_extent( struct xfs_trans *tp, /* transaction pointer */ xfs_fsblock_t bno, /* starting block number of extent */ xfs_extlen_t len, /* length of extent */ - struct xfs_owner_info *oinfo); /* extent owner */ + struct xfs_owner_info *oinfo, /* extent owner */ + enum xfs_ag_resv_type type); /* block reservation type */ int /* error */ xfs_alloc_lookup_ge( diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index e9ccec5..50faacd 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -39,6 +39,7 @@ #include "xfs_attr_leaf.h" #include "xfs_quota_defs.h" #include "xfs_rmap_btree.h" +#include "xfs_ag_resv.h" kmem_zone_t *xfs_bmap_free_item_zone; @@ -3493,7 +3494,8 @@ xfs_bmap_longest_free_extent( } longest = xfs_alloc_longest_free_extent(mp, pag, - xfs_alloc_min_freelist(mp, pag)); + xfs_alloc_min_freelist(mp, pag), + xfs_ag_resv_needed(pag, XFS_AG_RESV_NONE)); if (*blen < longest) *blen = longest; @@ -3772,7 +3774,7 @@ xfs_bmap_btalloc( } args.minleft = ap->minleft; args.wasdel = ap->wasdel; - args.isfl = 0; + args.resv = XFS_AG_RESV_NONE; args.userdata = ap->userdata; if (ap->userdata & XFS_ALLOC_USERDATA_ZERO) args.ip = ap->ip; diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c index d79ddfe..36d09eb 100644 --- a/libxfs/xfs_ialloc_btree.c +++ b/libxfs/xfs_ialloc_btree.c @@ -130,7 +130,7 @@ xfs_inobt_free_block( xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INOBT); return xfs_free_extent(cur->bc_tp, XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(bp)), 1, - &oinfo); + &oinfo, XFS_AG_RESV_NONE); } STATIC int From darrick.wong@oracle.com Thu Jun 16 20:38:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6E62680D1 for ; Thu, 16 Jun 2016 20:38:39 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id DC70FAC002 for ; Thu, 16 Jun 2016 18:38:38 -0700 (PDT) X-ASG-Debug-ID: 1466127515-04cbb01fed6a330001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id bQfcRaYWbiUkgMfv (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:36 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1cW2J006912 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:33 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cWSe008849 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:32 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cUkF011720; Fri, 17 Jun 2016 01:38:31 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:29 -0700 Subject: [PATCH 073/145] xfs: introduce refcount btree definitions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 073/145] xfs: introduce refcount btree definitions To: david@fromorbit.com, darrick.wong@oracle.com Cc: Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:28 -0700 Message-ID: <146612750843.16048.17316621525217517837.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127516 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8430 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add new per-AG refcount btree definitions to the per-AG structures. v2: Move the reflink inode flag out of the way of the DAX flag, and add the new cowextsize flag. v3: Don't allow pNFS to export reflinked files; this will be removed some day when the Linux pNFS server supports it. [hch: don't allow pNFS export of reflinked files] [darrick: fix the feature test in hch's patch] Signed-off-by: Darrick J. Wong Signed-off-by: Christoph Hellwig --- include/xfs_inode.h | 5 +++++ include/xfs_mount.h | 3 +++ libxfs/xfs_alloc.c | 5 +++++ libxfs/xfs_btree.c | 5 +++-- libxfs/xfs_btree.h | 3 +++ libxfs/xfs_format.h | 29 ++++++++++++++++++++++++++--- libxfs/xfs_rmap_btree.c | 7 +++++-- libxfs/xfs_types.h | 2 +- 8 files changed, 51 insertions(+), 8 deletions(-) diff --git a/include/xfs_inode.h b/include/xfs_inode.h index 8141d97..3876fa6 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -122,6 +122,11 @@ xfs_set_projid(struct xfs_icdinode *id, prid_t projid) id->di_projid_lo = (__uint16_t) (projid & 0xffff); } +static inline bool xfs_is_reflink_inode(struct xfs_inode *ip) +{ + return ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK; +} + typedef struct cred { uid_t cr_uid; gid_t cr_gid; diff --git a/include/xfs_mount.h b/include/xfs_mount.h index c452de2..c5db4d8 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -161,6 +161,9 @@ typedef struct xfs_perag { struct xfs_ag_resv pag_meta_resv; /* Blocks reserved for just AGFL-based metadata. */ struct xfs_ag_resv pag_agfl_resv; + + /* reference count */ + __uint8_t pagf_refcount_level; } xfs_perag_t; static inline struct xfs_ag_resv * diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 7b9040e..c4d001f 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2444,6 +2444,10 @@ xfs_agf_verify( be32_to_cpu(agf->agf_btreeblks) > be32_to_cpu(agf->agf_length)) return false; + if (xfs_sb_version_hasreflink(&mp->m_sb) && + be32_to_cpu(agf->agf_refcount_level) > XFS_BTREE_MAXLEVELS) + return false; + return true;; } @@ -2564,6 +2568,7 @@ xfs_alloc_read_agf( be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); pag->pagf_levels[XFS_BTNUM_RMAPi] = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); + pag->pagf_refcount_level = be32_to_cpu(agf->agf_refcount_level); spin_lock_init(&pag->pagb_lock); pag->pagb_count = 0; #ifdef __KERNEL__ diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 1e547f8..f4b1780 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -41,9 +41,10 @@ kmem_zone_t *xfs_btree_cur_zone; */ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, - XFS_FIBT_MAGIC }, + XFS_FIBT_MAGIC, 0 }, { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC, - XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC } + XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC, + XFS_REFC_CRC_MAGIC } }; #define xfs_btree_magic(cur) \ xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 6fa13a9..85506a9 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -66,6 +66,7 @@ union xfs_btree_rec { #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) #define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi) +#define XFS_BTNUM_REFC ((xfs_btnum_t)XFS_BTNUM_REFCi) /* * For logging record fields. @@ -99,6 +100,7 @@ do { \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ + case XFS_BTNUM_REFC: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -121,6 +123,7 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ case XFS_BTNUM_RMAP: \ __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ + case XFS_BTNUM_REFC: break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 7205806..865ce0f 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -456,6 +456,7 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ +#define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ XFS_SB_FEAT_RO_COMPAT_RMAPBT) @@ -546,6 +547,12 @@ static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp) (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT); } +static inline bool xfs_sb_version_hasreflink(struct xfs_sb *sbp) +{ + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && + (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_REFLINK); +} + /* * end of superblock version macros */ @@ -640,12 +647,15 @@ typedef struct xfs_agf { __be32 agf_btreeblks; /* # of blocks held in AGF btrees */ uuid_t agf_uuid; /* uuid of filesystem */ + __be32 agf_refcount_root; /* refcount tree root block */ + __be32 agf_refcount_level; /* refcount btree levels */ + /* * reserve some contiguous space for future logged fields before we add * the unlogged fields. This makes the range logging via flags and * structure offsets much simpler. */ - __be64 agf_spare64[16]; + __be64 agf_spare64[15]; /* unlogged fields, written during buffer writeback. */ __be64 agf_lsn; /* last write sequence */ @@ -1033,9 +1043,14 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) * 16 bits of the XFS_XFLAG_s range. */ #define XFS_DIFLAG2_DAX_BIT 0 /* use DAX for this inode */ +#define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */ +#define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */ #define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT) +#define XFS_DIFLAG2_REFLINK (1 << XFS_DIFLAG2_REFLINK_BIT) +#define XFS_DIFLAG2_COWEXTSIZE (1 << XFS_DIFLAG2_COWEXTSIZE_BIT) -#define XFS_DIFLAG2_ANY (XFS_DIFLAG2_DAX) +#define XFS_DIFLAG2_ANY \ + (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE) /* * Inode number format: @@ -1382,7 +1397,8 @@ xfs_rmap_ino_owner( #define XFS_RMAP_OWN_AG (-5ULL) /* AG freespace btree blocks */ #define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */ #define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ -#define XFS_RMAP_OWN_MIN (-8ULL) /* guard */ +#define XFS_RMAP_OWN_REFC (-8ULL) /* refcount tree */ +#define XFS_RMAP_OWN_MIN (-9ULL) /* guard */ #define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63))) @@ -1530,6 +1546,13 @@ xfs_owner_info_pack( } /* + * Reference Count Btree format definitions + * + */ +#define XFS_REFC_CRC_MAGIC 0x52334643 /* 'R3FC' */ + + +/* * BMAP Btree format definitions * * This includes both the root block definition that sits inside an inode fork diff --git a/libxfs/xfs_rmap_btree.c b/libxfs/xfs_rmap_btree.c index b5c3c21..3fedfd7 100644 --- a/libxfs/xfs_rmap_btree.c +++ b/libxfs/xfs_rmap_btree.c @@ -473,6 +473,9 @@ void xfs_rmapbt_compute_maxlevels( struct xfs_mount *mp) { - mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, - mp->m_rmap_mnr, mp->m_sb.sb_agblocks); + if (xfs_sb_version_hasreflink(&mp->m_sb)) + mp->m_rmap_maxlevels = XFS_BTREE_MAXLEVELS; + else + mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, + mp->m_rmap_mnr, mp->m_sb.sb_agblocks); } diff --git a/libxfs/xfs_types.h b/libxfs/xfs_types.h index da87796..690d616 100644 --- a/libxfs/xfs_types.h +++ b/libxfs/xfs_types.h @@ -112,7 +112,7 @@ typedef enum { typedef enum { XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi, - XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_MAX + XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_REFCi, XFS_BTNUM_MAX } xfs_btnum_t; struct xfs_name { From darrick.wong@oracle.com Thu Jun 16 20:38:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E0542828B for ; Thu, 16 Jun 2016 20:38:43 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6B19FAC003 for ; Thu, 16 Jun 2016 18:38:43 -0700 (PDT) X-ASG-Debug-ID: 1466127521-04bdf01e1596370001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id z7XeoC1Xu8y9l3Tc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:42 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1cehf007020 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:41 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ceiE004816 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:40 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ca5H011770; Fri, 17 Jun 2016 01:38:37 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:36 -0700 Subject: [PATCH 074/145] xfs: add refcount btree stats infrastructure From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 074/145] xfs: add refcount btree stats infrastructure To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:34 -0700 Message-ID: <146612751467.16048.6269075439585017233.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127522 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1251 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines The refcount btree presents the same stats as the other btrees, so add all the code for that now. Signed-off-by: Darrick J. Wong --- libxfs/xfs_btree.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 85506a9..93e761e 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -100,7 +100,7 @@ do { \ case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ - case XFS_BTNUM_REFC: break; \ + case XFS_BTNUM_REFC: __XFS_BTREE_STATS_INC(__mp, refcbt, stat); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) @@ -123,7 +123,8 @@ do { \ __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ case XFS_BTNUM_RMAP: \ __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ - case XFS_BTNUM_REFC: break; \ + case XFS_BTNUM_REFC: \ + __XFS_BTREE_STATS_ADD(__mp, refcbt, stat, val); break; \ case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ } \ } while (0) From darrick.wong@oracle.com Thu Jun 16 20:38:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 406B98241 for ; Thu, 16 Jun 2016 20:38:49 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 04814304039 for ; Thu, 16 Jun 2016 18:38:48 -0700 (PDT) X-ASG-Debug-ID: 1466127527-04cb6c5427580f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Voj3ysNVLDxd2dYq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:47 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1cgBr019551 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:43 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cgxM004890 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:42 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cgPd029150; Fri, 17 Jun 2016 01:38:42 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:42 -0700 Subject: [PATCH 075/145] xfs: refcount btree add more reserved blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 075/145] xfs: refcount btree add more reserved blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:40 -0700 Message-ID: <146612752077.16048.15295030283603772885.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127527 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1565 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since XFS reserves a small amount of space in each AG as the minimum free space needed for an operation, save some more space in case we touch the refcount btree. Signed-off-by: Darrick J. Wong --- libxfs/xfs_alloc.c | 13 +++++++++++++ libxfs/xfs_format.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index c4d001f..6e6ada8 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -48,10 +48,23 @@ STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); +unsigned int +xfs_refc_block( + struct xfs_mount *mp) +{ + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) + return XFS_RMAP_BLOCK(mp) + 1; + if (xfs_sb_version_hasfinobt(&mp->m_sb)) + return XFS_FIBT_BLOCK(mp) + 1; + return XFS_IBT_BLOCK(mp) + 1; +} + xfs_extlen_t xfs_prealloc_blocks( struct xfs_mount *mp) { + if (xfs_sb_version_hasreflink(&mp->m_sb)) + return xfs_refc_block(mp) + 1; if (xfs_sb_version_hasrmapbt(&mp->m_sb)) return XFS_RMAP_BLOCK(mp) + 1; if (xfs_sb_version_hasfinobt(&mp->m_sb)) diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 865ce0f..54fbe2b 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -1551,6 +1551,8 @@ xfs_owner_info_pack( */ #define XFS_REFC_CRC_MAGIC 0x52334643 /* 'R3FC' */ +unsigned int xfs_refc_block(struct xfs_mount *mp); + /* * BMAP Btree format definitions From darrick.wong@oracle.com Thu Jun 16 20:39:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 21ABF80DC for ; Thu, 16 Jun 2016 20:39:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id E7540304039 for ; Thu, 16 Jun 2016 18:39:00 -0700 (PDT) X-ASG-Debug-ID: 1466127536-04cbb01fee6a380001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id vcQZNvTC2l9LMlgV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:38:57 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1coYq019628 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:50 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cnZv004990 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:50 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cm3f023972; Fri, 17 Jun 2016 01:38:49 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:48 -0700 Subject: [PATCH 076/145] xfs: define the on-disk refcount btree format From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 076/145] xfs: define the on-disk refcount btree format To: david@fromorbit.com, darrick.wong@oracle.com Cc: Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:46 -0700 Message-ID: <146612752686.16048.9338808799544236814.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127537 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19076 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Start constructing the refcount btree implementation by establishing the on-disk format and everything needed to read, write, and manipulate the refcount btree blocks. v2: Calculate a separate maxlevels for the refcount btree. v3: Enable the tracking of per-cursor stats for refcount btrees. The refcount update code will use this to guess if it's time to split a refcountbt update across two transactions to avoid exhausing the transaction reservation. xfs_refcountbt_init_cursor can be called under the ilock, so use KM_NOFS to prevent fs activity with a lock held. This should shut up some of the lockdep warnings. Signed-off-by: Darrick J. Wong [hch: allocate the cursor with KM_NOFS to quiet lockdep] Signed-off-by: Christoph Hellwig --- include/darwin.h | 1 include/freebsd.h | 1 include/gnukfreebsd.h | 1 include/irix.h | 1 include/libxfs.h | 1 include/linux.h | 1 include/xfs_mount.h | 3 + libxfs/Makefile | 2 libxfs/init.c | 2 libxfs/xfs_btree.c | 3 + libxfs/xfs_btree.h | 12 +++ libxfs/xfs_format.h | 32 ++++++++ libxfs/xfs_refcount_btree.c | 177 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_refcount_btree.h | 67 ++++++++++++++++ libxfs/xfs_sb.c | 9 ++ libxfs/xfs_shared.h | 2 libxfs/xfs_trans_resv.c | 2 libxfs/xfs_trans_resv.h | 1 18 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 libxfs/xfs_refcount_btree.c create mode 100644 libxfs/xfs_refcount_btree.h diff --git a/include/darwin.h b/include/darwin.h index a52030d..2935b4c 100644 --- a/include/darwin.h +++ b/include/darwin.h @@ -140,6 +140,7 @@ typedef off_t xfs_off_t; typedef u_int64_t xfs_ino_t; typedef u_int32_t xfs_dev_t; typedef int64_t xfs_daddr_t; +typedef u_int32_t xfs_nlink_t; #define stat64 stat #define fstat64 fstat diff --git a/include/freebsd.h b/include/freebsd.h index f7e0c75..3feca07 100644 --- a/include/freebsd.h +++ b/include/freebsd.h @@ -53,6 +53,7 @@ typedef off_t off64_t; typedef __uint64_t xfs_ino_t; typedef __uint32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; +typedef __uint32_t xfs_nlink_t; typedef unsigned char __u8; typedef signed char __s8; diff --git a/include/gnukfreebsd.h b/include/gnukfreebsd.h index 64167b2..a62789e 100644 --- a/include/gnukfreebsd.h +++ b/include/gnukfreebsd.h @@ -42,6 +42,7 @@ typedef off_t xfs_off_t; typedef __uint64_t xfs_ino_t; typedef __uint32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; +typedef __uint32_t xfs_nlink_t; typedef unsigned char __u8; typedef signed char __s8; diff --git a/include/irix.h b/include/irix.h index c2191ee..45c8594 100644 --- a/include/irix.h +++ b/include/irix.h @@ -47,6 +47,7 @@ typedef off64_t xfs_off_t; typedef __int64_t xfs_ino_t; typedef __int32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; +typedef __int32_t xfs_nlink_t; typedef unsigned char __u8; typedef signed char __s8; diff --git a/include/libxfs.h b/include/libxfs.h index 5e76263..bec4ee6 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -78,6 +78,7 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len); #include "xfs_trace.h" #include "xfs_trans.h" #include "xfs_rmap_btree.h" +#include "xfs_refcount_btree.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/include/linux.h b/include/linux.h index cc0f70c..cd4b3eb 100644 --- a/include/linux.h +++ b/include/linux.h @@ -146,6 +146,7 @@ typedef off64_t xfs_off_t; typedef __uint64_t xfs_ino_t; typedef __uint32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; +typedef __uint32_t xfs_nlink_t; /** * Abstraction of mountpoints. diff --git a/include/xfs_mount.h b/include/xfs_mount.h index c5db4d8..d47efa0 100644 --- a/include/xfs_mount.h +++ b/include/xfs_mount.h @@ -66,10 +66,13 @@ typedef struct xfs_mount { uint m_inobt_mnr[2]; /* XFS_INOBT_BLOCK_MINRECS */ uint m_rmap_mxr[2]; /* max rmap btree records */ uint m_rmap_mnr[2]; /* min rmap btree records */ + uint m_refc_mxr[2]; /* max refc btree records */ + uint m_refc_mnr[2]; /* min refc btree records */ uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */ uint m_rmap_maxlevels; /* max rmap btree levels */ + uint m_refc_maxlevels; /* max refcount btree level */ xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ uint m_alloc_set_aside; /* space we can't use */ uint m_ag_max_usable; /* max space per AG */ diff --git a/libxfs/Makefile b/libxfs/Makefile index 588c663..c31a2e9 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -37,6 +37,7 @@ HFILES = \ xfs_inode_buf.h \ xfs_inode_fork.h \ xfs_quota_defs.h \ + xfs_refcount_btree.h \ xfs_rmap_btree.h \ xfs_sb.h \ xfs_shared.h \ @@ -85,6 +86,7 @@ CFILES = cache.c \ xfs_inode_fork.c \ xfs_ialloc_btree.c \ xfs_log_rlimit.c \ + xfs_refcount_btree.c \ xfs_rmap.c \ xfs_rmap_btree.c \ xfs_rtbitmap.c \ diff --git a/libxfs/init.c b/libxfs/init.c index c56d123..66bfbd8 100644 --- a/libxfs/init.c +++ b/libxfs/init.c @@ -32,6 +32,7 @@ #include "xfs_inode.h" #include "xfs_trans.h" #include "xfs_rmap_btree.h" +#include "xfs_refcount_btree.h" #include "libxfs.h" /* for now */ @@ -685,6 +686,7 @@ libxfs_mount( xfs_bmap_compute_maxlevels(mp, XFS_ATTR_FORK); xfs_ialloc_compute_maxlevels(mp); xfs_rmapbt_compute_maxlevels(mp); + xfs_refcountbt_compute_maxlevels(mp); if (sbp->sb_imax_pct) { /* Make sure the maximum inode count is a multiple of the diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index f4b1780..89fb2fe 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -1210,6 +1210,9 @@ xfs_btree_set_refs( case XFS_BTNUM_RMAP: xfs_buf_set_ref(bp, XFS_RMAP_BTREE_REF); break; + case XFS_BTNUM_REFC: + xfs_buf_set_ref(bp, XFS_REFC_BTREE_REF); + break; default: ASSERT(0); } diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index 93e761e..dbf299f 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -43,6 +43,7 @@ union xfs_btree_key { xfs_alloc_key_t alloc; struct xfs_inobt_key inobt; struct xfs_rmap_key rmap; + struct xfs_refcount_key refc; }; union xfs_btree_rec { @@ -51,6 +52,7 @@ union xfs_btree_rec { struct xfs_alloc_rec alloc; struct xfs_inobt_rec inobt; struct xfs_rmap_rec rmap; + struct xfs_refcount_rec refc; }; /* @@ -221,6 +223,15 @@ union xfs_btree_irec { xfs_bmbt_irec_t b; xfs_inobt_rec_incore_t i; struct xfs_rmap_irec r; + struct xfs_refcount_irec rc; +}; + +/* Per-AG btree private information. */ +union xfs_btree_cur_private { + struct { + unsigned long nr_ops; /* # record updates */ + int shape_changes; /* # of extent splits */ + } refc; }; /* @@ -247,6 +258,7 @@ typedef struct xfs_btree_cur struct xfs_buf *agbp; /* agf/agi buffer pointer */ struct xfs_defer_ops *dfops; /* deferred updates */ xfs_agnumber_t agno; /* ag number */ + union xfs_btree_cur_private priv; } a; struct { /* needed for BMAP */ struct xfs_inode *ip; /* pointer to our inode */ diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 54fbe2b..916d92b 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -1553,6 +1553,38 @@ xfs_owner_info_pack( unsigned int xfs_refc_block(struct xfs_mount *mp); +/* + * Data record/key structure + * + * Each record associates a range of physical blocks (starting at + * rc_startblock and ending rc_blockcount blocks later) with a + * reference count (rc_refcount). A record is only stored in the + * btree if the refcount is > 2. An entry in the free block btree + * means that the refcount is 0, and no entries anywhere means that + * the refcount is 1, as was true in XFS before reflinking. + */ +struct xfs_refcount_rec { + __be32 rc_startblock; /* starting block number */ + __be32 rc_blockcount; /* count of blocks */ + __be32 rc_refcount; /* number of inodes linked here */ +}; + +struct xfs_refcount_key { + __be32 rc_startblock; /* starting block number */ +}; + +struct xfs_refcount_irec { + xfs_agblock_t rc_startblock; /* starting block number */ + xfs_extlen_t rc_blockcount; /* count of free blocks */ + xfs_nlink_t rc_refcount; /* number of inodes linked here */ +}; + +#define MAXREFCOUNT ((xfs_nlink_t)~0U) +#define MAXREFCEXTLEN ((xfs_extlen_t)~0U) + +/* btree pointer type */ +typedef __be32 xfs_refcount_ptr_t; + /* * BMAP Btree format definitions diff --git a/libxfs/xfs_refcount_btree.c b/libxfs/xfs_refcount_btree.c new file mode 100644 index 0000000..a7b99e4 --- /dev/null +++ b/libxfs/xfs_refcount_btree.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_btree.h" +#include "xfs_bmap.h" +#include "xfs_refcount_btree.h" +#include "xfs_alloc.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" +#include "xfs_trans.h" +#include "xfs_bit.h" + +static struct xfs_btree_cur * +xfs_refcountbt_dup_cursor( + struct xfs_btree_cur *cur) +{ + return xfs_refcountbt_init_cursor(cur->bc_mp, cur->bc_tp, + cur->bc_private.a.agbp, cur->bc_private.a.agno, + cur->bc_private.a.dfops); +} + +STATIC bool +xfs_refcountbt_verify( + struct xfs_buf *bp) +{ + struct xfs_mount *mp = bp->b_target->bt_mount; + struct xfs_btree_block *block = XFS_BUF_TO_BLOCK(bp); + struct xfs_perag *pag = bp->b_pag; + unsigned int level; + + if (block->bb_magic != cpu_to_be32(XFS_REFC_CRC_MAGIC)) + return false; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return false; + if (!xfs_btree_sblock_v5hdr_verify(bp)) + return false; + + level = be16_to_cpu(block->bb_level); + if (pag && pag->pagf_init) { + if (level >= pag->pagf_refcount_level) + return false; + } else if (level >= mp->m_refc_maxlevels) + return false; + + return xfs_btree_sblock_verify(bp, mp->m_refc_mxr[level != 0]); +} + +STATIC void +xfs_refcountbt_read_verify( + struct xfs_buf *bp) +{ + if (!xfs_btree_sblock_verify_crc(bp)) + xfs_buf_ioerror(bp, -EFSBADCRC); + else if (!xfs_refcountbt_verify(bp)) + xfs_buf_ioerror(bp, -EFSCORRUPTED); + + if (bp->b_error) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_verifier_error(bp); + } +} + +STATIC void +xfs_refcountbt_write_verify( + struct xfs_buf *bp) +{ + if (!xfs_refcountbt_verify(bp)) { + trace_xfs_btree_corrupt(bp, _RET_IP_); + xfs_buf_ioerror(bp, -EFSCORRUPTED); + xfs_verifier_error(bp); + return; + } + xfs_btree_sblock_calc_crc(bp); + +} + +const struct xfs_buf_ops xfs_refcountbt_buf_ops = { + .name = "xfs_refcountbt", + .verify_read = xfs_refcountbt_read_verify, + .verify_write = xfs_refcountbt_write_verify, +}; + +static const struct xfs_btree_ops xfs_refcountbt_ops = { + .rec_len = sizeof(struct xfs_refcount_rec), + .key_len = sizeof(struct xfs_refcount_key), + + .dup_cursor = xfs_refcountbt_dup_cursor, + .buf_ops = &xfs_refcountbt_buf_ops, +}; + +/* + * Allocate a new refcount btree cursor. + */ +struct xfs_btree_cur * +xfs_refcountbt_init_cursor( + struct xfs_mount *mp, + struct xfs_trans *tp, + struct xfs_buf *agbp, + xfs_agnumber_t agno, + struct xfs_defer_ops *dfops) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + struct xfs_btree_cur *cur; + + ASSERT(agno != NULLAGNUMBER); + ASSERT(agno < mp->m_sb.sb_agcount); + cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS); + + cur->bc_tp = tp; + cur->bc_mp = mp; + cur->bc_btnum = XFS_BTNUM_REFC; + cur->bc_blocklog = mp->m_sb.sb_blocklog; + cur->bc_ops = &xfs_refcountbt_ops; + + cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level); + + cur->bc_private.a.agbp = agbp; + cur->bc_private.a.agno = agno; + cur->bc_private.a.dfops = dfops; + cur->bc_flags |= XFS_BTREE_CRC_BLOCKS; + + cur->bc_private.a.priv.refc.nr_ops = 0; + cur->bc_private.a.priv.refc.shape_changes = 0; + + return cur; +} + +/* + * Calculate the number of records in a refcount btree block. + */ +int +xfs_refcountbt_maxrecs( + struct xfs_mount *mp, + int blocklen, + bool leaf) +{ + blocklen -= XFS_REFCOUNT_BLOCK_LEN; + + if (leaf) + return blocklen / sizeof(struct xfs_refcount_rec); + return blocklen / (sizeof(struct xfs_refcount_key) + + sizeof(xfs_refcount_ptr_t)); +} + +/* Compute the maximum height of a refcount btree. */ +void +xfs_refcountbt_compute_maxlevels( + struct xfs_mount *mp) +{ + mp->m_refc_maxlevels = xfs_btree_compute_maxlevels(mp, + mp->m_refc_mnr, mp->m_sb.sb_agblocks); +} diff --git a/libxfs/xfs_refcount_btree.h b/libxfs/xfs_refcount_btree.h new file mode 100644 index 0000000..9e9ad7c --- /dev/null +++ b/libxfs/xfs_refcount_btree.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_REFCOUNT_BTREE_H__ +#define __XFS_REFCOUNT_BTREE_H__ + +/* + * Reference Count Btree on-disk structures + */ + +struct xfs_buf; +struct xfs_btree_cur; +struct xfs_mount; + +/* + * Btree block header size + */ +#define XFS_REFCOUNT_BLOCK_LEN XFS_BTREE_SBLOCK_CRC_LEN + +/* + * Record, key, and pointer address macros for btree blocks. + * + * (note that some of these may appear unused, but they are used in userspace) + */ +#define XFS_REFCOUNT_REC_ADDR(block, index) \ + ((struct xfs_refcount_rec *) \ + ((char *)(block) + \ + XFS_REFCOUNT_BLOCK_LEN + \ + (((index) - 1) * sizeof(struct xfs_refcount_rec)))) + +#define XFS_REFCOUNT_KEY_ADDR(block, index) \ + ((struct xfs_refcount_key *) \ + ((char *)(block) + \ + XFS_REFCOUNT_BLOCK_LEN + \ + ((index) - 1) * sizeof(struct xfs_refcount_key))) + +#define XFS_REFCOUNT_PTR_ADDR(block, index, maxrecs) \ + ((xfs_refcount_ptr_t *) \ + ((char *)(block) + \ + XFS_REFCOUNT_BLOCK_LEN + \ + (maxrecs) * sizeof(struct xfs_refcount_key) + \ + ((index) - 1) * sizeof(xfs_refcount_ptr_t))) + +extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp, + struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, + struct xfs_defer_ops *dfops); +extern int xfs_refcountbt_maxrecs(struct xfs_mount *mp, int blocklen, + bool leaf); +extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); + +#endif /* __XFS_REFCOUNT_BTREE_H__ */ diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index 26c29ea..bb54bc2 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -35,6 +35,8 @@ #include "xfs_alloc_btree.h" #include "xfs_ialloc_btree.h" #include "xfs_rmap_btree.h" +#include "xfs_bmap.h" +#include "xfs_refcount_btree.h" /* * Physical superblock buffer manipulations. Shared with libxfs in userspace. @@ -737,6 +739,13 @@ xfs_sb_mount_common( mp->m_rmap_mnr[0] = mp->m_rmap_mxr[0] / 2; mp->m_rmap_mnr[1] = mp->m_rmap_mxr[1] / 2; + mp->m_refc_mxr[0] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, + true); + mp->m_refc_mxr[1] = xfs_refcountbt_maxrecs(mp, sbp->sb_blocksize, + false); + mp->m_refc_mnr[0] = mp->m_refc_mxr[0] / 2; + mp->m_refc_mnr[1] = mp->m_refc_mxr[1] / 2; + mp->m_bsize = XFS_FSB_TO_BB(mp, 1); mp->m_ialloc_inos = (int)MAX((__uint16_t)XFS_INODES_PER_CHUNK, sbp->sb_inopblock); diff --git a/libxfs/xfs_shared.h b/libxfs/xfs_shared.h index 0c5b30b..c6f4eb4 100644 --- a/libxfs/xfs_shared.h +++ b/libxfs/xfs_shared.h @@ -39,6 +39,7 @@ extern const struct xfs_buf_ops xfs_agf_buf_ops; extern const struct xfs_buf_ops xfs_agfl_buf_ops; extern const struct xfs_buf_ops xfs_allocbt_buf_ops; extern const struct xfs_buf_ops xfs_rmapbt_buf_ops; +extern const struct xfs_buf_ops xfs_refcountbt_buf_ops; extern const struct xfs_buf_ops xfs_attr3_leaf_buf_ops; extern const struct xfs_buf_ops xfs_attr3_rmt_buf_ops; extern const struct xfs_buf_ops xfs_bmbt_buf_ops; @@ -122,6 +123,7 @@ int xfs_log_calc_minimum_size(struct xfs_mount *); #define XFS_INO_REF 2 #define XFS_ATTR_BTREE_REF 1 #define XFS_DQUOT_REF 1 +#define XFS_REFC_BTREE_REF 1 /* * Flags for xfs_trans_ichgtime(). diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c index 2ed80a5..10234bb 100644 --- a/libxfs/xfs_trans_resv.c +++ b/libxfs/xfs_trans_resv.c @@ -72,7 +72,7 @@ xfs_calc_buf_res( * * Keep in mind that max depth is calculated separately for each type of tree. */ -static uint +uint xfs_allocfree_log_count( struct xfs_mount *mp, uint num_ops) diff --git a/libxfs/xfs_trans_resv.h b/libxfs/xfs_trans_resv.h index 0eb46ed..36a1511 100644 --- a/libxfs/xfs_trans_resv.h +++ b/libxfs/xfs_trans_resv.h @@ -102,5 +102,6 @@ struct xfs_trans_resv { #define XFS_ATTRRM_LOG_COUNT 3 void xfs_trans_resv_calc(struct xfs_mount *mp, struct xfs_trans_resv *resp); +uint xfs_allocfree_log_count(struct xfs_mount *mp, uint num_ops); #endif /* __XFS_TRANS_RESV_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:39:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0A72780DC for ; Thu, 16 Jun 2016 20:39:03 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id C66D98F8052 for ; Thu, 16 Jun 2016 18:39:02 -0700 (PDT) X-ASG-Debug-ID: 1466127541-04cb6c542658110001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id FeK5kCmLz5AARuNM (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1cwan007163 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:59 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1cwfc005169 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:38:58 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1csHs011902; Fri, 17 Jun 2016 01:38:56 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:38:54 -0700 Subject: [PATCH 077/145] xfs: account for the refcount btree in the alloc/free log reservation From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 077/145] xfs: account for the refcount btree in the alloc/free log reservation To: david@fromorbit.com, darrick.wong@oracle.com Cc: Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:53 -0700 Message-ID: <146612753324.16048.2863648366596319776.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127541 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1464 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Every time we allocate or free an extent, we might need to split the refcount btree. Reserve some blocks in the transaction to handle this possibility. (Reproduced by generic/167 over NFS atop XFS) Signed-off-by: Christoph Hellwig [darrick.wong@oracle.com: add commit message] Signed-off-by: Darrick J. Wong --- libxfs/xfs_trans_resv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c index 10234bb..5b6bbcd 100644 --- a/libxfs/xfs_trans_resv.c +++ b/libxfs/xfs_trans_resv.c @@ -66,7 +66,8 @@ xfs_calc_buf_res( * Per-extent log reservation for the btree changes involved in freeing or * allocating an extent. In classic XFS there were two trees that will be * modified (bnobt + cntbt). With rmap enabled, there are three trees - * (rmapbt). The number of blocks reserved is based on the formula: + * (rmapbt). With reflink, there are four trees (refcountbt). The number of + * blocks reserved is based on the formula: * * num trees * ((2 blocks/level * max depth) - 1) * @@ -82,6 +83,8 @@ xfs_allocfree_log_count( blocks = num_ops * 2 * (2 * mp->m_ag_maxlevels - 1); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) blocks += num_ops * (2 * mp->m_rmap_maxlevels - 1); + if (xfs_sb_version_hasreflink(&mp->m_sb)) + blocks += num_ops * (2 * mp->m_refc_maxlevels - 1); return blocks; } From darrick.wong@oracle.com Thu Jun 16 20:39:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 937F68279 for ; Thu, 16 Jun 2016 20:39:08 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 643B18F8052 for ; Thu, 16 Jun 2016 18:39:08 -0700 (PDT) X-ASG-Debug-ID: 1466127544-04cbb01fef6a3c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id qdZHTQFMT451GFGC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:05 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1d218007398 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:02 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1d25e009358 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:02 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1d1k3024090; Fri, 17 Jun 2016 01:39:01 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:00 -0700 Subject: [PATCH 078/145] xfs: add refcount btree operations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 078/145] xfs: add refcount btree operations To: david@fromorbit.com, darrick.wong@oracle.com Cc: Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:38:59 -0700 Message-ID: <146612753939.16048.2766379346085634076.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127545 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17436 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Implement the generic btree operations required to manipulate refcount btree blocks. The implementation is similar to the bmapbt, though it will only allocate and free blocks from the AG. v2: Remove init_rec_from_key since we no longer need it, and add tracepoints when refcount btree operations fail. Since the refcount root and level fields are separate from the existing roots and levels array, they need a separate logging flag. Signed-off-by: Darrick J. Wong [hch: fix logging of AGF refcount btree fields] Signed-off-by: Christoph Hellwig --- include/libxfs.h | 1 include/xfs_trace.h | 12 +++ libxfs/Makefile | 2 libxfs/xfs_alloc.c | 4 + libxfs/xfs_format.h | 5 + libxfs/xfs_refcount.c | 176 ++++++++++++++++++++++++++++++++++++++ libxfs/xfs_refcount.h | 30 +++++++ libxfs/xfs_refcount_btree.c | 197 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 426 insertions(+), 1 deletion(-) create mode 100644 libxfs/xfs_refcount.c create mode 100644 libxfs/xfs_refcount.h diff --git a/include/libxfs.h b/include/libxfs.h index bec4ee6..cc6a877 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -79,6 +79,7 @@ extern uint32_t crc32c_le(uint32_t crc, unsigned char const *p, size_t len); #include "xfs_trans.h" #include "xfs_rmap_btree.h" #include "xfs_refcount_btree.h" +#include "xfs_refcount.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 040f2f0..cb5fa89 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -221,6 +221,18 @@ #define trace_xfs_ag_resv_alloc_extent(...) ((void) 0) #define trace_xfs_ag_resv_free_extent(...) ((void) 0) +#define trace_xfs_refcountbt_lookup(...) ((void) 0) +#define trace_xfs_refcountbt_get(...) ((void) 0) +#define trace_xfs_refcountbt_update(...) ((void) 0) +#define trace_xfs_refcountbt_update_error(...) ((void) 0) +#define trace_xfs_refcountbt_insert(...) ((void) 0) +#define trace_xfs_refcountbt_insert_error(...) ((void) 0) +#define trace_xfs_refcountbt_delete(...) ((void) 0) +#define trace_xfs_refcountbt_delete_error(...) ((void) 0) +#define trace_xfs_refcountbt_free_block(...) ((void) 0) +#define trace_xfs_refcountbt_alloc_block(...) ((void) 0) +#define trace_xfs_refcount_rec_order_error(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/Makefile b/libxfs/Makefile index c31a2e9..4b1ada0 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -37,6 +37,7 @@ HFILES = \ xfs_inode_buf.h \ xfs_inode_fork.h \ xfs_quota_defs.h \ + xfs_refcount.h \ xfs_refcount_btree.h \ xfs_rmap_btree.h \ xfs_sb.h \ @@ -86,6 +87,7 @@ CFILES = cache.c \ xfs_inode_fork.c \ xfs_ialloc_btree.c \ xfs_log_rlimit.c \ + xfs_refcount.c \ xfs_refcount_btree.c \ xfs_rmap.c \ xfs_rmap_btree.c \ diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 6e6ada8..6554ce7 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2322,6 +2322,10 @@ xfs_alloc_log_agf( offsetof(xfs_agf_t, agf_longest), offsetof(xfs_agf_t, agf_btreeblks), offsetof(xfs_agf_t, agf_uuid), + offsetof(xfs_agf_t, agf_refcount_root), + offsetof(xfs_agf_t, agf_refcount_level), + /* needed so that we don't log the whole rest of the structure: */ + offsetof(xfs_agf_t, agf_spare64), sizeof(xfs_agf_t) }; diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 916d92b..fdeaf53 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -680,7 +680,10 @@ typedef struct xfs_agf { #define XFS_AGF_LONGEST 0x00000400 #define XFS_AGF_BTREEBLKS 0x00000800 #define XFS_AGF_UUID 0x00001000 -#define XFS_AGF_NUM_BITS 13 +#define XFS_AGF_REFCOUNT_ROOT 0x00002000 +#define XFS_AGF_REFCOUNT_LEVEL 0x00004000 +#define XFS_AGF_SPARE64 0x00008000 +#define XFS_AGF_NUM_BITS 16 #define XFS_AGF_ALL_BITS ((1 << XFS_AGF_NUM_BITS) - 1) #define XFS_AGF_FLAGS \ diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c new file mode 100644 index 0000000..0eda933 --- /dev/null +++ b/libxfs/xfs_refcount.c @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_log_format.h" +#include "xfs_trans_resv.h" +#include "xfs_sb.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_btree.h" +#include "xfs_bmap.h" +#include "xfs_refcount_btree.h" +#include "xfs_alloc.h" +#include "xfs_trace.h" +#include "xfs_cksum.h" +#include "xfs_trans.h" +#include "xfs_bit.h" +#include "xfs_refcount.h" + +/* + * Look up the first record less than or equal to [bno, len] in the btree + * given by cur. + */ +int +xfs_refcountbt_lookup_le( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + int *stat) +{ + trace_xfs_refcountbt_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, + XFS_LOOKUP_LE); + cur->bc_rec.rc.rc_startblock = bno; + cur->bc_rec.rc.rc_blockcount = 0; + return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); +} + +/* + * Look up the first record greater than or equal to [bno, len] in the btree + * given by cur. + */ +int +xfs_refcountbt_lookup_ge( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + int *stat) +{ + trace_xfs_refcountbt_lookup(cur->bc_mp, cur->bc_private.a.agno, bno, + XFS_LOOKUP_GE); + cur->bc_rec.rc.rc_startblock = bno; + cur->bc_rec.rc.rc_blockcount = 0; + return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); +} + +/* + * Get the data from the pointed-to record. + */ +int +xfs_refcountbt_get_rec( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec, + int *stat) +{ + union xfs_btree_rec *rec; + int error; + + error = xfs_btree_get_rec(cur, &rec, stat); + if (!error && *stat == 1) { + irec->rc_startblock = be32_to_cpu(rec->refc.rc_startblock); + irec->rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount); + irec->rc_refcount = be32_to_cpu(rec->refc.rc_refcount); + trace_xfs_refcountbt_get(cur->bc_mp, cur->bc_private.a.agno, + irec); + } + return error; +} + +/* + * Update the record referred to by cur to the value given + * by [bno, len, refcount]. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_refcountbt_update( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec) +{ + union xfs_btree_rec rec; + int error; + + trace_xfs_refcountbt_update(cur->bc_mp, cur->bc_private.a.agno, irec); + rec.refc.rc_startblock = cpu_to_be32(irec->rc_startblock); + rec.refc.rc_blockcount = cpu_to_be32(irec->rc_blockcount); + rec.refc.rc_refcount = cpu_to_be32(irec->rc_refcount); + error = xfs_btree_update(cur, &rec); + if (error) + trace_xfs_refcountbt_update_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Insert the record referred to by cur to the value given + * by [bno, len, refcount]. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_refcountbt_insert( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec, + int *i) +{ + int error; + + trace_xfs_refcountbt_insert(cur->bc_mp, cur->bc_private.a.agno, irec); + cur->bc_rec.rc.rc_startblock = irec->rc_startblock; + cur->bc_rec.rc.rc_blockcount = irec->rc_blockcount; + cur->bc_rec.rc.rc_refcount = irec->rc_refcount; + error = xfs_btree_insert(cur, i); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); +out_error: + if (error) + trace_xfs_refcountbt_insert_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Remove the record referred to by cur, then set the pointer to the spot + * where the record could be re-inserted, in case we want to increment or + * decrement the cursor. + * This either works (return 0) or gets an EFSCORRUPTED error. + */ +STATIC int +xfs_refcountbt_delete( + struct xfs_btree_cur *cur, + int *i) +{ + struct xfs_refcount_irec irec; + int found_rec; + int error; + + error = xfs_refcountbt_get_rec(cur, &irec, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + trace_xfs_refcountbt_delete(cur->bc_mp, cur->bc_private.a.agno, &irec); + error = xfs_btree_delete(cur, i); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, *i == 1, out_error); + if (error) + goto out_error; + error = xfs_refcountbt_lookup_ge(cur, irec.rc_startblock, &found_rec); +out_error: + if (error) + trace_xfs_refcountbt_delete_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} diff --git a/libxfs/xfs_refcount.h b/libxfs/xfs_refcount.h new file mode 100644 index 0000000..8ea65c6 --- /dev/null +++ b/libxfs/xfs_refcount.h @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_REFCOUNT_H__ +#define __XFS_REFCOUNT_H__ + +extern int xfs_refcountbt_lookup_le(struct xfs_btree_cur *cur, + xfs_agblock_t bno, int *stat); +extern int xfs_refcountbt_lookup_ge(struct xfs_btree_cur *cur, + xfs_agblock_t bno, int *stat); +extern int xfs_refcountbt_get_rec(struct xfs_btree_cur *cur, + struct xfs_refcount_irec *irec, int *stat); + +#endif /* __XFS_REFCOUNT_H__ */ diff --git a/libxfs/xfs_refcount_btree.c b/libxfs/xfs_refcount_btree.c index a7b99e4..8c53e71 100644 --- a/libxfs/xfs_refcount_btree.c +++ b/libxfs/xfs_refcount_btree.c @@ -43,6 +43,153 @@ xfs_refcountbt_dup_cursor( cur->bc_private.a.dfops); } +STATIC void +xfs_refcountbt_set_root( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr, + int inc) +{ + struct xfs_buf *agbp = cur->bc_private.a.agbp; + struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp); + xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); + struct xfs_perag *pag = xfs_perag_get(cur->bc_mp, seqno); + + ASSERT(ptr->s != 0); + + agf->agf_refcount_root = ptr->s; + be32_add_cpu(&agf->agf_refcount_level, inc); + pag->pagf_refcount_level += inc; + xfs_perag_put(pag); + + xfs_alloc_log_agf(cur->bc_tp, agbp, + XFS_AGF_REFCOUNT_ROOT | XFS_AGF_REFCOUNT_LEVEL); +} + +STATIC int +xfs_refcountbt_alloc_block( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *start, + union xfs_btree_ptr *new, + int *stat) +{ + struct xfs_alloc_arg args; /* block allocation args */ + int error; /* error return value */ + + memset(&args, 0, sizeof(args)); + args.tp = cur->bc_tp; + args.mp = cur->bc_mp; + args.type = XFS_ALLOCTYPE_NEAR_BNO; + args.fsbno = XFS_AGB_TO_FSB(cur->bc_mp, cur->bc_private.a.agno, + xfs_refc_block(args.mp)); + args.firstblock = args.fsbno; + xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); + args.minlen = args.maxlen = args.prod = 1; + + error = xfs_alloc_vextent(&args); + if (error) + goto out_error; + trace_xfs_refcountbt_alloc_block(cur->bc_mp, cur->bc_private.a.agno, + args.agbno, 1); + if (args.fsbno == NULLFSBLOCK) { + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 0; + return 0; + } + ASSERT(args.agno == cur->bc_private.a.agno); + ASSERT(args.len == 1); + + new->s = cpu_to_be32(args.agbno); + + XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); + *stat = 1; + return 0; + +out_error: + XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR); + return error; +} + +STATIC int +xfs_refcountbt_free_block( + struct xfs_btree_cur *cur, + struct xfs_buf *bp) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_trans *tp = cur->bc_tp; + xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); + struct xfs_owner_info oinfo; + + trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, + XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); + xfs_bmap_add_free(mp, cur->bc_private.a.dfops, fsbno, 1, + &oinfo); + xfs_trans_binval(tp, bp); + return 0; +} + +STATIC int +xfs_refcountbt_get_minrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_refc_mnr[level != 0]; +} + +STATIC int +xfs_refcountbt_get_maxrecs( + struct xfs_btree_cur *cur, + int level) +{ + return cur->bc_mp->m_refc_mxr[level != 0]; +} + +STATIC void +xfs_refcountbt_init_key_from_rec( + union xfs_btree_key *key, + union xfs_btree_rec *rec) +{ + ASSERT(rec->refc.rc_startblock != 0); + + key->refc.rc_startblock = rec->refc.rc_startblock; +} + +STATIC void +xfs_refcountbt_init_rec_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_rec *rec) +{ + ASSERT(cur->bc_rec.rc.rc_startblock != 0); + + rec->refc.rc_startblock = cpu_to_be32(cur->bc_rec.rc.rc_startblock); + rec->refc.rc_blockcount = cpu_to_be32(cur->bc_rec.rc.rc_blockcount); + rec->refc.rc_refcount = cpu_to_be32(cur->bc_rec.rc.rc_refcount); +} + +STATIC void +xfs_refcountbt_init_ptr_from_cur( + struct xfs_btree_cur *cur, + union xfs_btree_ptr *ptr) +{ + struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); + + ASSERT(cur->bc_private.a.agno == be32_to_cpu(agf->agf_seqno)); + ASSERT(agf->agf_refcount_root != 0); + + ptr->s = agf->agf_refcount_root; +} + +STATIC __int64_t +xfs_refcountbt_key_diff( + struct xfs_btree_cur *cur, + union xfs_btree_key *key) +{ + struct xfs_refcount_irec *rec = &cur->bc_rec.rc; + struct xfs_refcount_key *kp = &key->refc; + + return (__int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock; +} + STATIC bool xfs_refcountbt_verify( struct xfs_buf *bp) @@ -105,12 +252,62 @@ const struct xfs_buf_ops xfs_refcountbt_buf_ops = { .verify_write = xfs_refcountbt_write_verify, }; +#if defined(DEBUG) || defined(XFS_WARN) +STATIC int +xfs_refcountbt_keys_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return be32_to_cpu(k1->refc.rc_startblock) < + be32_to_cpu(k2->refc.rc_startblock); +} + +STATIC int +xfs_refcountbt_recs_inorder( + struct xfs_btree_cur *cur, + union xfs_btree_rec *r1, + union xfs_btree_rec *r2) +{ + struct xfs_refcount_irec a, b; + + int ret = be32_to_cpu(r1->refc.rc_startblock) + + be32_to_cpu(r1->refc.rc_blockcount) <= + be32_to_cpu(r2->refc.rc_startblock); + if (!ret) { + a.rc_startblock = be32_to_cpu(r1->refc.rc_startblock); + a.rc_blockcount = be32_to_cpu(r1->refc.rc_blockcount); + a.rc_refcount = be32_to_cpu(r1->refc.rc_refcount); + b.rc_startblock = be32_to_cpu(r2->refc.rc_startblock); + b.rc_blockcount = be32_to_cpu(r2->refc.rc_blockcount); + b.rc_refcount = be32_to_cpu(r2->refc.rc_refcount); + trace_xfs_refcount_rec_order_error(cur->bc_mp, + cur->bc_private.a.agno, &a, &b); + } + + return ret; +} +#endif /* DEBUG */ + static const struct xfs_btree_ops xfs_refcountbt_ops = { .rec_len = sizeof(struct xfs_refcount_rec), .key_len = sizeof(struct xfs_refcount_key), .dup_cursor = xfs_refcountbt_dup_cursor, + .set_root = xfs_refcountbt_set_root, + .alloc_block = xfs_refcountbt_alloc_block, + .free_block = xfs_refcountbt_free_block, + .get_minrecs = xfs_refcountbt_get_minrecs, + .get_maxrecs = xfs_refcountbt_get_maxrecs, + .init_key_from_rec = xfs_refcountbt_init_key_from_rec, + .init_rec_from_cur = xfs_refcountbt_init_rec_from_cur, + .init_ptr_from_cur = xfs_refcountbt_init_ptr_from_cur, + .key_diff = xfs_refcountbt_key_diff, .buf_ops = &xfs_refcountbt_buf_ops, +#if defined(DEBUG) || defined(XFS_WARN) + .keys_inorder = xfs_refcountbt_keys_inorder, + .recs_inorder = xfs_refcountbt_recs_inorder, +#endif }; /* From darrick.wong@oracle.com Thu Jun 16 20:39:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8F88882A8 for ; Thu, 16 Jun 2016 20:39:18 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 4F134304048 for ; Thu, 16 Jun 2016 18:39:18 -0700 (PDT) X-ASG-Debug-ID: 1466127556-04bdf01e17963c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id pVGX7CHGuQ3lCjIQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:16 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1dCH8020083 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:39:12 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1dCR1002790 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:12 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1d9M5011939; Fri, 17 Jun 2016 01:39:10 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:07 -0700 Subject: [PATCH 079/145] xfs: create refcount update intent log items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 079/145] xfs: create refcount update intent log items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:05 -0700 Message-ID: <146612754567.16048.14742882191402291990.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127556 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3521 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create refcount update intent/done log items to record redo information in the log. Because we need to roll transactions between updating the bmbt mapping and updating the reverse mapping, we also have to track the status of the metadata updates that will be recorded in the post-roll transactions, just in case we crash before committing the final transaction. This mechanism enables log recovery to finish what was already started. Signed-off-by: Darrick J. Wong --- libxfs/xfs_log_format.h | 54 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h index b9627b7..923b08f 100644 --- a/libxfs/xfs_log_format.h +++ b/libxfs/xfs_log_format.h @@ -112,7 +112,9 @@ static inline uint xlog_get_cycle(char *ptr) #define XLOG_REG_TYPE_ICREATE 20 #define XLOG_REG_TYPE_RUI_FORMAT 21 #define XLOG_REG_TYPE_RUD_FORMAT 22 -#define XLOG_REG_TYPE_MAX 22 +#define XLOG_REG_TYPE_CUI_FORMAT 23 +#define XLOG_REG_TYPE_CUD_FORMAT 24 +#define XLOG_REG_TYPE_MAX 24 /* * Flags to log operation header @@ -231,6 +233,8 @@ typedef struct xfs_trans_header { #define XFS_LI_ICREATE 0x123f #define XFS_LI_RUI 0x1240 /* rmap update intent */ #define XFS_LI_RUD 0x1241 +#define XFS_LI_CUI 0x1242 /* refcount update intent */ +#define XFS_LI_CUD 0x1243 #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ @@ -242,7 +246,9 @@ typedef struct xfs_trans_header { { XFS_LI_QUOTAOFF, "XFS_LI_QUOTAOFF" }, \ { XFS_LI_ICREATE, "XFS_LI_ICREATE" }, \ { XFS_LI_RUI, "XFS_LI_RUI" }, \ - { XFS_LI_RUD, "XFS_LI_RUD" } + { XFS_LI_RUD, "XFS_LI_RUD" }, \ + { XFS_LI_CUI, "XFS_LI_CUI" }, \ + { XFS_LI_CUD, "XFS_LI_CUD" } /* * Inode Log Item Format definitions. @@ -667,6 +673,50 @@ struct xfs_rud_log_format { }; /* + * CUI/CUD (refcount update) log format definitions + */ +struct xfs_phys_extent { + __uint64_t pe_startblock; + __uint32_t pe_len; + __uint32_t pe_flags; +}; + +/* refcount pe_flags: upper bits are flags, lower byte is type code */ +#define XFS_REFCOUNT_EXTENT_INCREASE 1 +#define XFS_REFCOUNT_EXTENT_DECREASE 2 +#define XFS_REFCOUNT_EXTENT_ALLOC_COW 3 +#define XFS_REFCOUNT_EXTENT_FREE_COW 4 +#define XFS_REFCOUNT_EXTENT_TYPE_MASK 0xFF + +#define XFS_REFCOUNT_EXTENT_FLAGS (XFS_REFCOUNT_EXTENT_TYPE_MASK) + +/* + * This is the structure used to lay out a cui log item in the + * log. The cui_extents field is a variable size array whose + * size is given by cui_nextents. + */ +struct xfs_cui_log_format { + __uint16_t cui_type; /* cui log item type */ + __uint16_t cui_size; /* size of this item */ + __uint32_t cui_nextents; /* # extents to free */ + __uint64_t cui_id; /* cui identifier */ + struct xfs_phys_extent cui_extents[1]; /* array of extents */ +}; + +/* + * This is the structure used to lay out a cud log item in the + * log. The cud_extents array is a variable size array whose + * size is given by cud_nextents; + */ +struct xfs_cud_log_format { + __uint16_t cud_type; /* cud log item type */ + __uint16_t cud_size; /* size of this item */ + __uint32_t cud_nextents; /* # of extents freed */ + __uint64_t cud_cui_id; /* id of corresponding cui */ + struct xfs_phys_extent cud_extents[1]; /* array of extents */ +}; + +/* * Dquot Log format definitions. * * The first two fields must be the type and size fitting into From darrick.wong@oracle.com Thu Jun 16 20:39:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9D68482B2 for ; Thu, 16 Jun 2016 20:39:22 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5D595304039 for ; Thu, 16 Jun 2016 18:39:22 -0700 (PDT) X-ASG-Debug-ID: 1466127560-04bdf01e10963c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id XdAVgvYTDCEyQEtD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1dIq2007619 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:39:19 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1dIdQ002964 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:18 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1dFEN011955; Fri, 17 Jun 2016 01:39:16 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:15 -0700 Subject: [PATCH 080/145] xfs: log refcount intent items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 080/145] xfs: log refcount intent items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:14 -0700 Message-ID: <146612755414.16048.15708229067581853.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127560 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1071 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a mechanism for higher levels to create CUI/CUD items, submit them to the log, and a stub function to deal with recovered CUI items. These parts will be connected to the refcountbt in a later patch. Signed-off-by: Darrick J. Wong --- libxfs/xfs_refcount.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/libxfs/xfs_refcount.h b/libxfs/xfs_refcount.h index 8ea65c6..0b36c1d 100644 --- a/libxfs/xfs_refcount.h +++ b/libxfs/xfs_refcount.h @@ -27,4 +27,18 @@ extern int xfs_refcountbt_lookup_ge(struct xfs_btree_cur *cur, extern int xfs_refcountbt_get_rec(struct xfs_btree_cur *cur, struct xfs_refcount_irec *irec, int *stat); +enum xfs_refcount_intent_type { + XFS_REFCOUNT_INCREASE, + XFS_REFCOUNT_DECREASE, + XFS_REFCOUNT_ALLOC_COW, + XFS_REFCOUNT_FREE_COW, +}; + +struct xfs_refcount_intent { + struct list_head ri_list; + enum xfs_refcount_intent_type ri_type; + xfs_fsblock_t ri_startblock; + xfs_extlen_t ri_blockcount; +}; + #endif /* __XFS_REFCOUNT_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:39:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 762A482B1 for ; Thu, 16 Jun 2016 20:39:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 45B678F804B for ; Thu, 16 Jun 2016 18:39:34 -0700 (PDT) X-ASG-Debug-ID: 1466127569-04cb6c542658170001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 9vBuJW9HVSeccYvQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:29 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1dOTZ020238 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:25 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1dOG7009888 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:24 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1dM9c012001; Fri, 17 Jun 2016 01:39:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:21 -0700 Subject: [PATCH 081/145] xfs: adjust refcount of an extent of blocks in refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 081/145] xfs: adjust refcount of an extent of blocks in refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:20 -0700 Message-ID: <146612756022.16048.618610283366394250.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127569 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 26045 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide functions to adjust the reference counts for an extent of physical blocks stored in the refcount btree. v2: Refactor the left/right split code into a single function. Track the number of btree shape changes and record updates during a refcount update so that we can decide if we need to get a fresh transaction to continue. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 20 + libxfs/xfs_refcount.c | 783 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 803 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index cb5fa89..0b167e9 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -232,6 +232,26 @@ #define trace_xfs_refcountbt_free_block(...) ((void) 0) #define trace_xfs_refcountbt_alloc_block(...) ((void) 0) #define trace_xfs_refcount_rec_order_error(...) ((void) 0) +#define trace_xfs_refcount_split_extent(...) ((void) 0) +#define trace_xfs_refcount_split_extent_error(...) ((void) 0) +#define trace_xfs_refcount_merge_center_extents_error(...) ((void) 0) +#define trace_xfs_refcount_merge_left_extent_error(...) ((void) 0) +#define trace_xfs_refcount_merge_right_extent_error(...) ((void) 0) +#define trace_xfs_refcount_find_left_extent(...) ((void) 0) +#define trace_xfs_refcount_find_left_extent_error(...) ((void) 0) +#define trace_xfs_refcount_find_right_extent(...) ((void) 0) +#define trace_xfs_refcount_find_right_extent_error(...) ((void) 0) +#define trace_xfs_refcount_merge_center_extents(...) ((void) 0) +#define trace_xfs_refcount_merge_left_extent(...) ((void) 0) +#define trace_xfs_refcount_merge_right_extent(...) ((void) 0) +#define trace_xfs_refcount_modify_extent(...) ((void) 0) +#define trace_xfs_refcount_modify_extent_error(...) ((void) 0) +#define trace_xfs_refcount_adjust_error(...) ((void) 0) +#define trace_xfs_refcount_increase(...) ((void) 0) +#define trace_xfs_refcount_decrease(...) ((void) 0) +#define trace_xfs_refcount_deferred(...) ((void) 0) +#define trace_xfs_refcount_defer(...) ((void) 0) +#define trace_xfs_refcount_finish_one_leftover(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index 0eda933..cd68c1e 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -36,6 +36,12 @@ #include "xfs_bit.h" #include "xfs_refcount.h" +/* Allowable refcount adjustment amounts. */ +enum xfs_refc_adjust_op { + XFS_REFCOUNT_ADJUST_INCREASE = 1, + XFS_REFCOUNT_ADJUST_DECREASE = -1, +}; + /* * Look up the first record less than or equal to [bno, len] in the btree * given by cur. @@ -174,3 +180,780 @@ out_error: cur->bc_private.a.agno, error, _RET_IP_); return error; } + +/* + * Adjusting the Reference Count + * + * As stated elsewhere, the reference count btree (refcbt) stores + * >1 reference counts for extents of physical blocks. In this + * operation, we're either raising or lowering the reference count of + * some subrange stored in the tree: + * + * <------ adjustment range ------> + * ----+ +---+-----+ +--+--------+--------- + * 2 | | 3 | 4 | |17| 55 | 10 + * ----+ +---+-----+ +--+--------+--------- + * X axis is physical blocks number; + * reference counts are the numbers inside the rectangles + * + * The first thing we need to do is to ensure that there are no + * refcount extents crossing either boundary of the range to be + * adjusted. For any extent that does cross a boundary, split it into + * two extents so that we can increment the refcount of one of the + * pieces later: + * + * <------ adjustment range ------> + * ----+ +---+-----+ +--+--------+----+---- + * 2 | | 3 | 2 | |17| 55 | 10 | 10 + * ----+ +---+-----+ +--+--------+----+---- + * + * For this next step, let's assume that all the physical blocks in + * the adjustment range are mapped to a file and are therefore in use + * at least once. Therefore, we can infer that any gap in the + * refcount tree within the adjustment range represents a physical + * extent with refcount == 1: + * + * <------ adjustment range ------> + * ----+---+---+-----+-+--+--------+----+---- + * 2 |"1"| 3 | 2 |1|17| 55 | 10 | 10 + * ----+---+---+-----+-+--+--------+----+---- + * ^ + * + * For each extent that falls within the interval range, figure out + * which extent is to the left or the right of that extent. Now we + * have a left, current, and right extent. If the new reference count + * of the center extent enables us to merge left, center, and right + * into one record covering all three, do so. If the center extent is + * at the left end of the range, abuts the left extent, and its new + * reference count matches the left extent's record, then merge them. + * If the center extent is at the right end of the range, abuts the + * right extent, and the reference counts match, merge those. In the + * example, we can left merge (assuming an increment operation): + * + * <------ adjustment range ------> + * --------+---+-----+-+--+--------+----+---- + * 2 | 3 | 2 |1|17| 55 | 10 | 10 + * --------+---+-----+-+--+--------+----+---- + * ^ + * + * For all other extents within the range, adjust the reference count + * or delete it if the refcount falls below 2. If we were + * incrementing, the end result looks like this: + * + * <------ adjustment range ------> + * --------+---+-----+-+--+--------+----+---- + * 2 | 4 | 3 |2|18| 56 | 11 | 10 + * --------+---+-----+-+--+--------+----+---- + * + * The result of a decrement operation looks as such: + * + * <------ adjustment range ------> + * ----+ +---+ +--+--------+----+---- + * 2 | | 2 | |16| 54 | 9 | 10 + * ----+ +---+ +--+--------+----+---- + * DDDD 111111DD + * + * The blocks marked "D" are freed; the blocks marked "1" are only + * referenced once and therefore the record is removed from the + * refcount btree. + */ + +#define RCNEXT(rc) ((rc).rc_startblock + (rc).rc_blockcount) +/* + * Split a refcount extent that crosses agbno. + */ +STATIC int +xfs_refcount_split_extent( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + bool *shape_changed) +{ + struct xfs_refcount_irec rcext, tmp; + int found_rec; + int error; + + *shape_changed = false; + error = xfs_refcountbt_lookup_le(cur, agbno, &found_rec); + if (error) + goto out_error; + if (!found_rec) + return 0; + + error = xfs_refcountbt_get_rec(cur, &rcext, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + if (rcext.rc_startblock == agbno || RCNEXT(rcext) <= agbno) + return 0; + + *shape_changed = true; + trace_xfs_refcount_split_extent(cur->bc_mp, cur->bc_private.a.agno, + &rcext, agbno); + + /* Establish the right extent. */ + tmp = rcext; + tmp.rc_startblock = agbno; + tmp.rc_blockcount -= (agbno - rcext.rc_startblock); + error = xfs_refcountbt_update(cur, &tmp); + if (error) + goto out_error; + + /* Insert the left extent. */ + tmp = rcext; + tmp.rc_blockcount = agbno - rcext.rc_startblock; + error = xfs_refcountbt_insert(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + return error; + +out_error: + trace_xfs_refcount_split_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Merge the left, center, and right extents. + */ +STATIC int +xfs_refcount_merge_center_extent( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *left, + struct xfs_refcount_irec *center, + unsigned long long extlen, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen) +{ + int error; + int found_rec; + + error = xfs_refcountbt_lookup_ge(cur, center->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + if (center->rc_refcount > 1) { + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + } + + error = xfs_refcountbt_lookup_le(cur, left->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + left->rc_blockcount = extlen; + error = xfs_refcountbt_update(cur, left); + if (error) + goto out_error; + + *aglen = 0; + return error; + +out_error: + trace_xfs_refcount_merge_center_extents_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Merge with the left extent. + */ +STATIC int +xfs_refcount_merge_left_extent( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *left, + struct xfs_refcount_irec *cleft, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen) +{ + int error; + int found_rec; + + if (cleft->rc_refcount > 1) { + error = xfs_refcountbt_lookup_le(cur, cleft->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + } + + error = xfs_refcountbt_lookup_le(cur, left->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + left->rc_blockcount += cleft->rc_blockcount; + error = xfs_refcountbt_update(cur, left); + if (error) + goto out_error; + + *agbno += cleft->rc_blockcount; + *aglen -= cleft->rc_blockcount; + return error; + +out_error: + trace_xfs_refcount_merge_left_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Merge with the right extent. + */ +STATIC int +xfs_refcount_merge_right_extent( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *right, + struct xfs_refcount_irec *cright, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen) +{ + int error; + int found_rec; + + if (cright->rc_refcount > 1) { + error = xfs_refcountbt_lookup_le(cur, cright->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + } + + error = xfs_refcountbt_lookup_le(cur, right->rc_startblock, + &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + right->rc_startblock -= cright->rc_blockcount; + right->rc_blockcount += cright->rc_blockcount; + error = xfs_refcountbt_update(cur, right); + if (error) + goto out_error; + + *aglen -= cright->rc_blockcount; + return error; + +out_error: + trace_xfs_refcount_merge_right_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Find the left extent and the one after it (cleft). This function assumes + * that we've already split any extent crossing agbno. + */ +STATIC int +xfs_refcount_find_left_extents( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *left, + struct xfs_refcount_irec *cleft, + xfs_agblock_t agbno, + xfs_extlen_t aglen) +{ + struct xfs_refcount_irec tmp; + int error; + int found_rec; + + left->rc_blockcount = cleft->rc_blockcount = 0; + error = xfs_refcountbt_lookup_le(cur, agbno - 1, &found_rec); + if (error) + goto out_error; + if (!found_rec) + return 0; + + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + if (RCNEXT(tmp) != agbno) + return 0; + /* We have a left extent; retrieve (or invent) the next right one */ + *left = tmp; + + error = xfs_btree_increment(cur, 0, &found_rec); + if (error) + goto out_error; + if (found_rec) { + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + /* if tmp starts at the end of our range, just use that */ + if (tmp.rc_startblock == agbno) + *cleft = tmp; + else { + /* + * There's a gap in the refcntbt at the start of the + * range we're interested in (refcount == 1) so + * create the implied extent and pass it back. + */ + cleft->rc_startblock = agbno; + cleft->rc_blockcount = min(aglen, + tmp.rc_startblock - agbno); + cleft->rc_refcount = 1; + } + } else { + /* + * No extents, so pretend that there's one covering the whole + * range. + */ + cleft->rc_startblock = agbno; + cleft->rc_blockcount = aglen; + cleft->rc_refcount = 1; + } + trace_xfs_refcount_find_left_extent(cur->bc_mp, cur->bc_private.a.agno, + left, cleft, agbno); + return error; + +out_error: + trace_xfs_refcount_find_left_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Find the right extent and the one before it (cright). This function + * assumes that we've already split any extents crossing agbno + aglen. + */ +STATIC int +xfs_refcount_find_right_extents( + struct xfs_btree_cur *cur, + struct xfs_refcount_irec *right, + struct xfs_refcount_irec *cright, + xfs_agblock_t agbno, + xfs_extlen_t aglen) +{ + struct xfs_refcount_irec tmp; + int error; + int found_rec; + + right->rc_blockcount = cright->rc_blockcount = 0; + error = xfs_refcountbt_lookup_ge(cur, agbno + aglen, &found_rec); + if (error) + goto out_error; + if (!found_rec) + return 0; + + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, out_error); + + if (tmp.rc_startblock != agbno + aglen) + return 0; + /* We have a right extent; retrieve (or invent) the next left one */ + *right = tmp; + + error = xfs_btree_decrement(cur, 0, &found_rec); + if (error) + goto out_error; + if (found_rec) { + error = xfs_refcountbt_get_rec(cur, &tmp, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, found_rec == 1, + out_error); + + /* if tmp ends at the end of our range, just use that */ + if (RCNEXT(tmp) == agbno + aglen) + *cright = tmp; + else { + /* + * There's a gap in the refcntbt at the end of the + * range we're interested in (refcount == 1) so + * create the implied extent and pass it back. + */ + cright->rc_startblock = max(agbno, RCNEXT(tmp)); + cright->rc_blockcount = right->rc_startblock - + cright->rc_startblock; + cright->rc_refcount = 1; + } + } else { + /* + * No extents, so pretend that there's one covering the whole + * range. + */ + cright->rc_startblock = agbno; + cright->rc_blockcount = aglen; + cright->rc_refcount = 1; + } + trace_xfs_refcount_find_right_extent(cur->bc_mp, cur->bc_private.a.agno, + cright, right, agbno + aglen); + return error; + +out_error: + trace_xfs_refcount_find_right_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} +#undef RCNEXT + +/* + * Try to merge with any extents on the boundaries of the adjustment range. + */ +STATIC int +xfs_refcount_merge_extents( + struct xfs_btree_cur *cur, + xfs_agblock_t *agbno, + xfs_extlen_t *aglen, + enum xfs_refc_adjust_op adjust, + bool *shape_changed) +{ + struct xfs_refcount_irec left = {0}, cleft = {0}; + struct xfs_refcount_irec cright = {0}, right = {0}; + int error; + unsigned long long ulen; + bool cequal; + + *shape_changed = false; + /* + * Find the extent just below agbno [left], just above agbno [cleft], + * just below (agbno + aglen) [cright], and just above (agbno + aglen) + * [right]. + */ + error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno, + *aglen); + if (error) + return error; + error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno, + *aglen); + if (error) + return error; + + /* No left or right extent to merge; exit. */ + if (left.rc_blockcount == 0 && right.rc_blockcount == 0) + return 0; + + *shape_changed = true; + cequal = (cleft.rc_startblock == cright.rc_startblock) && + (cleft.rc_blockcount == cright.rc_blockcount); + + /* Try to merge left, cleft, and right. cleft must == cright. */ + ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount + + right.rc_blockcount; + if (left.rc_blockcount != 0 && right.rc_blockcount != 0 && + cleft.rc_blockcount != 0 && cright.rc_blockcount != 0 && + cequal && + left.rc_refcount == cleft.rc_refcount + adjust && + right.rc_refcount == cleft.rc_refcount + adjust && + ulen < MAXREFCEXTLEN) { + trace_xfs_refcount_merge_center_extents(cur->bc_mp, + cur->bc_private.a.agno, &left, &cleft, &right); + return xfs_refcount_merge_center_extent(cur, &left, &cleft, + ulen, agbno, aglen); + } + + /* Try to merge left and cleft. */ + ulen = (unsigned long long)left.rc_blockcount + cleft.rc_blockcount; + if (left.rc_blockcount != 0 && cleft.rc_blockcount != 0 && + left.rc_refcount == cleft.rc_refcount + adjust && + ulen < MAXREFCEXTLEN) { + trace_xfs_refcount_merge_left_extent(cur->bc_mp, + cur->bc_private.a.agno, &left, &cleft); + error = xfs_refcount_merge_left_extent(cur, &left, &cleft, + agbno, aglen); + if (error) + return error; + + /* + * If we just merged left + cleft and cleft == cright, + * we no longer have a cright to merge with right. We're done. + */ + if (cequal) + return 0; + } + + /* Try to merge cright and right. */ + ulen = (unsigned long long)right.rc_blockcount + cright.rc_blockcount; + if (right.rc_blockcount != 0 && cright.rc_blockcount != 0 && + right.rc_refcount == cright.rc_refcount + adjust && + ulen < MAXREFCEXTLEN) { + trace_xfs_refcount_merge_right_extent(cur->bc_mp, + cur->bc_private.a.agno, &cright, &right); + return xfs_refcount_merge_right_extent(cur, &right, &cright, + agbno, aglen); + } + + return error; +} + +/* + * While we're adjusting the refcounts records of an extent, we have + * to keep an eye on the number of extents we're dirtying -- run too + * many in a single transaction and we'll exceed the transaction's + * reservation and crash the fs. Each record adds 12 bytes to the + * log (plus any key updates) so we'll conservatively assume 24 bytes + * per record. We must also leave space for btree splits on both ends + * of the range and space for the CUD and a new CUI. + * + * XXX: This is a pretty hand-wavy estimate. The penalty for guessing + * true incorrectly is a shutdown FS; the penalty for guessing false + * incorrectly is more transaction rolls than might be necessary. + * Be conservative here. + */ +static bool +xfs_refcount_still_have_space( + struct xfs_btree_cur *cur) +{ + unsigned long overhead; + + overhead = cur->bc_private.a.priv.refc.shape_changes * + xfs_allocfree_log_count(cur->bc_mp, 1); + overhead *= cur->bc_mp->m_sb.sb_blocksize; + + /* + * Only allow 2 refcount extent updates per transaction if the + * refcount continue update "error" has been injected. + */ + if (cur->bc_private.a.priv.refc.nr_ops > 2 && + XFS_TEST_ERROR(false, cur->bc_mp, + XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE, + XFS_RANDOM_REFCOUNT_CONTINUE_UPDATE)) + return false; + + if (cur->bc_private.a.priv.refc.nr_ops == 0) + return true; + else if (overhead > cur->bc_tp->t_log_res) + return false; + return cur->bc_tp->t_log_res - overhead > + cur->bc_private.a.priv.refc.nr_ops * 32; +} + +/* + * Adjust the refcounts of middle extents. At this point we should have + * split extents that crossed the adjustment range; merged with adjacent + * extents; and updated agbno/aglen to reflect the merges. Therefore, + * all we have to do is update the extents inside [agbno, agbno + aglen]. + */ +STATIC int +xfs_refcount_adjust_extents( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_extlen_t *adjusted, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops, + struct xfs_owner_info *oinfo) +{ + struct xfs_refcount_irec ext, tmp; + int error; + int found_rec, found_tmp; + xfs_fsblock_t fsbno; + + /* Merging did all the work already. */ + if (aglen == 0) + return 0; + + error = xfs_refcountbt_lookup_ge(cur, agbno, &found_rec); + if (error) + goto out_error; + + while (aglen > 0 && xfs_refcount_still_have_space(cur)) { + error = xfs_refcountbt_get_rec(cur, &ext, &found_rec); + if (error) + goto out_error; + if (!found_rec) { + ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks; + ext.rc_blockcount = 0; + ext.rc_refcount = 0; + } + + /* + * Deal with a hole in the refcount tree; if a file maps to + * these blocks and there's no refcountbt recourd, pretend that + * there is one with refcount == 1. + */ + if (ext.rc_startblock != agbno) { + tmp.rc_startblock = agbno; + tmp.rc_blockcount = min(aglen, + ext.rc_startblock - agbno); + tmp.rc_refcount = 1 + adj; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &tmp); + + /* + * Either cover the hole (increment) or + * delete the range (decrement). + */ + if (tmp.rc_refcount) { + error = xfs_refcountbt_insert(cur, &tmp, + &found_tmp); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_tmp == 1, out_error); + cur->bc_private.a.priv.refc.nr_ops++; + } else { + fsbno = XFS_AGB_TO_FSB(cur->bc_mp, + cur->bc_private.a.agno, + tmp.rc_startblock); + xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, + tmp.rc_blockcount, oinfo); + } + + (*adjusted) += tmp.rc_blockcount; + agbno += tmp.rc_blockcount; + aglen -= tmp.rc_blockcount; + + error = xfs_refcountbt_lookup_ge(cur, agbno, + &found_rec); + if (error) + goto out_error; + } + + /* Stop if there's nothing left to modify */ + if (aglen == 0 || !xfs_refcount_still_have_space(cur)) + break; + + /* + * Adjust the reference count and either update the tree + * (incr) or free the blocks (decr). + */ + if (ext.rc_refcount == MAXREFCOUNT) + goto skip; + ext.rc_refcount += adj; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &ext); + if (ext.rc_refcount > 1) { + error = xfs_refcountbt_update(cur, &ext); + if (error) + goto out_error; + cur->bc_private.a.priv.refc.nr_ops++; + } else if (ext.rc_refcount == 1) { + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_rec == 1, out_error); + cur->bc_private.a.priv.refc.nr_ops++; + goto advloop; + } else { + fsbno = XFS_AGB_TO_FSB(cur->bc_mp, + cur->bc_private.a.agno, + ext.rc_startblock); + xfs_bmap_add_free(cur->bc_mp, dfops, fsbno, + ext.rc_blockcount, oinfo); + } + +skip: + error = xfs_btree_increment(cur, 0, &found_rec); + if (error) + goto out_error; + +advloop: + (*adjusted) += ext.rc_blockcount; + agbno += ext.rc_blockcount; + aglen -= ext.rc_blockcount; + } + + return error; +out_error: + trace_xfs_refcount_modify_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* Adjust the reference count of a range of AG blocks. */ +STATIC int +xfs_refcount_adjust( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_extlen_t *adjusted, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops, + struct xfs_owner_info *oinfo) +{ + xfs_extlen_t orig_aglen; + bool shape_changed; + int shape_changes = 0; + int error; + + *adjusted = 0; + switch (adj) { + case XFS_REFCOUNT_ADJUST_INCREASE: + trace_xfs_refcount_increase(cur->bc_mp, cur->bc_private.a.agno, + agbno, aglen); + break; + case XFS_REFCOUNT_ADJUST_DECREASE: + trace_xfs_refcount_decrease(cur->bc_mp, cur->bc_private.a.agno, + agbno, aglen); + break; + default: + ASSERT(0); + } + + /* + * Ensure that no rcextents cross the boundary of the adjustment range. + */ + error = xfs_refcount_split_extent(cur, agbno, &shape_changed); + if (error) + goto out_error; + if (shape_changed) + shape_changes++; + + error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed); + if (error) + goto out_error; + if (shape_changed) + shape_changes++; + + /* + * Try to merge with the left or right extents of the range. + */ + orig_aglen = aglen; + error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj, + &shape_changed); + if (error) + goto out_error; + if (shape_changed) + shape_changes++; + (*adjusted) += orig_aglen - aglen; + if (shape_changes) + cur->bc_private.a.priv.refc.shape_changes++; + + /* Now that we've taken care of the ends, adjust the middle extents */ + error = xfs_refcount_adjust_extents(cur, agbno, aglen, adjusted, adj, + dfops, oinfo); + if (error) + goto out_error; + + return 0; + +out_error: + trace_xfs_refcount_adjust_error(cur->bc_mp, cur->bc_private.a.agno, + error, _RET_IP_); + return error; +} From darrick.wong@oracle.com Thu Jun 16 20:39:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6A81282BD for ; Thu, 16 Jun 2016 20:39:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 21823304048 for ; Thu, 16 Jun 2016 18:39:38 -0700 (PDT) X-ASG-Debug-ID: 1466127574-04cbb01fee6a420001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id OlbnEXJ91COIzQhw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:35 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1dUcw020280 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:30 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1dTwm030013 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:30 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1dSkW001682; Fri, 17 Jun 2016 01:39:28 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:27 -0700 Subject: [PATCH 082/145] xfs: connect refcount adjust functions to upper layers From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 082/145] xfs: connect refcount adjust functions to upper layers To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:26 -0700 Message-ID: <146612756653.16048.503698193001832949.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127575 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10376 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the upper level interface to schedule and finish deferred refcount operations via the deferred ops mechanism. Signed-off-by: Darrick J. Wong --- libxfs/defer_item.c | 123 +++++++++++++++++++++++++++++++++++ libxfs/xfs_defer.h | 1 libxfs/xfs_refcount.c | 171 +++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_refcount.h | 12 +++ 4 files changed, 307 insertions(+) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index d2e4ad0..a383813 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -31,6 +31,7 @@ #include "xfs_bmap.h" #include "xfs_alloc.h" #include "xfs_rmap_btree.h" +#include "xfs_refcount.h" /* Extent Freeing */ @@ -242,12 +243,134 @@ const struct xfs_defer_op_type xfs_rmap_update_defer_type = { .cancel_item = xfs_rmap_update_cancel_item, }; +/* Reference Counting */ + +/* Sort rmap intents by AG. */ +static int +xfs_refcount_update_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_mount *mp = priv; + struct xfs_refcount_intent *ra; + struct xfs_refcount_intent *rb; + + ra = container_of(a, struct xfs_refcount_intent, ri_list); + rb = container_of(b, struct xfs_refcount_intent, ri_list); + return XFS_FSB_TO_AGNO(mp, ra->ri_startblock) - + XFS_FSB_TO_AGNO(mp, rb->ri_startblock); +} + +/* Get an CUI. */ +STATIC void * +xfs_refcount_update_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return NULL; +} + +/* Log refcount updates in the intent item. */ +STATIC void +xfs_refcount_update_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ +} + +/* Get an CUD so we can process all the deferred refcount updates. */ +STATIC void * +xfs_refcount_update_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return NULL; +} + +/* Process a deferred refcount update. */ +STATIC int +xfs_refcount_update_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + struct xfs_refcount_intent *refc; + xfs_extlen_t adjusted; + int error; + + refc = container_of(item, struct xfs_refcount_intent, ri_list); + error = xfs_refcount_finish_one(tp, dop, + refc->ri_type, + refc->ri_startblock, + refc->ri_blockcount, + &adjusted, + (struct xfs_btree_cur **)state); + /* Did we run out of reservation? Requeue what we didn't finish. */ + if (!error && adjusted < refc->ri_blockcount) { + ASSERT(refc->ri_type == XFS_REFCOUNT_INCREASE || + refc->ri_type == XFS_REFCOUNT_DECREASE); + refc->ri_startblock += adjusted; + refc->ri_blockcount -= adjusted; + return -EAGAIN; + } + kmem_free(refc); + return error; +} + +/* Clean up after processing deferred refcounts. */ +STATIC void +xfs_refcount_update_finish_cleanup( + struct xfs_trans *tp, + void *state, + int error) +{ + struct xfs_btree_cur *rcur = state; + + xfs_refcount_finish_one_cleanup(tp, rcur, error); +} + +/* Abort all pending CUIs. */ +STATIC void +xfs_refcount_update_abort_intent( + void *intent) +{ +} + +/* Cancel a deferred refcount update. */ +STATIC void +xfs_refcount_update_cancel_item( + struct list_head *item) +{ + struct xfs_refcount_intent *refc; + + refc = container_of(item, struct xfs_refcount_intent, ri_list); + kmem_free(refc); +} + +const struct xfs_defer_op_type xfs_refcount_update_defer_type = { + .type = XFS_DEFER_OPS_TYPE_REFCOUNT, + .diff_items = xfs_refcount_update_diff_items, + .create_intent = xfs_refcount_update_create_intent, + .abort_intent = xfs_refcount_update_abort_intent, + .log_item = xfs_refcount_update_log_item, + .create_done = xfs_refcount_update_create_done, + .finish_item = xfs_refcount_update_finish_item, + .finish_cleanup = xfs_refcount_update_finish_cleanup, + .cancel_item = xfs_refcount_update_cancel_item, +}; + /* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_refcount_update_defer_type); xfs_defer_init_op_type(&xfs_rmap_update_defer_type); xfs_defer_init_op_type(&xfs_extent_free_defer_type); } diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h index 920642e..4081b00 100644 --- a/libxfs/xfs_defer.h +++ b/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_REFCOUNT, XFS_DEFER_OPS_TYPE_RMAP, XFS_DEFER_OPS_TYPE_FREE, XFS_DEFER_OPS_TYPE_MAX, diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index cd68c1e..55859cd 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -957,3 +957,174 @@ out_error: error, _RET_IP_); return error; } + +/* Clean up after calling xfs_refcount_finish_one. */ +void +xfs_refcount_finish_one_cleanup( + struct xfs_trans *tp, + struct xfs_btree_cur *rcur, + int error) +{ + struct xfs_buf *agbp; + + if (rcur == NULL) + return; + agbp = rcur->bc_private.a.agbp; + xfs_btree_del_cursor(rcur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(tp, agbp); +} + +/* + * Process one of the deferred refcount operations. We pass back the + * btree cursor to maintain our lock on the btree between calls. + * This saves time and eliminates a buffer deadlock between the + * superblock and the AGF because we'll always grab them in the same + * order. + */ +int +xfs_refcount_finish_one( + struct xfs_trans *tp, + struct xfs_defer_ops *dfops, + enum xfs_refcount_intent_type type, + xfs_fsblock_t startblock, + xfs_extlen_t blockcount, + xfs_extlen_t *adjusted, + struct xfs_btree_cur **pcur) +{ + struct xfs_mount *mp = tp->t_mountp; + struct xfs_btree_cur *rcur; + struct xfs_buf *agbp = NULL; + int error = 0; + xfs_agnumber_t agno; + xfs_agblock_t bno; + unsigned long nr_ops = 0; + int shape_changes = 0; + + agno = XFS_FSB_TO_AGNO(mp, startblock); + ASSERT(agno != NULLAGNUMBER); + bno = XFS_FSB_TO_AGBNO(mp, startblock); + + trace_xfs_refcount_deferred(mp, XFS_FSB_TO_AGNO(mp, startblock), + type, XFS_FSB_TO_AGBNO(mp, startblock), + blockcount); + + if (XFS_TEST_ERROR(false, mp, + XFS_ERRTAG_REFCOUNT_FINISH_ONE, + XFS_RANDOM_REFCOUNT_FINISH_ONE)) + return -EIO; + + /* + * If we haven't gotten a cursor or the cursor AG doesn't match + * the startblock, get one now. + */ + rcur = *pcur; + if (rcur != NULL && rcur->bc_private.a.agno != agno) { + nr_ops = rcur->bc_private.a.priv.refc.nr_ops; + shape_changes = rcur->bc_private.a.priv.refc.shape_changes; + xfs_refcount_finish_one_cleanup(tp, rcur, 0); + rcur = NULL; + *pcur = NULL; + } + if (rcur == NULL) { + error = xfs_alloc_read_agf(tp->t_mountp, tp, agno, + XFS_ALLOC_FLAG_FREEING, &agbp); + if (error) + return error; + if (!agbp) + return -EFSCORRUPTED; + + rcur = xfs_refcountbt_init_cursor(mp, tp, agbp, agno, dfops); + if (!rcur) { + error = -ENOMEM; + goto out_cur; + } + rcur->bc_private.a.priv.refc.nr_ops = nr_ops; + rcur->bc_private.a.priv.refc.shape_changes = shape_changes; + } + *pcur = rcur; + + switch (type) { + case XFS_REFCOUNT_INCREASE: + error = xfs_refcount_adjust(rcur, bno, blockcount, adjusted, + XFS_REFCOUNT_ADJUST_INCREASE, dfops, NULL); + break; + case XFS_REFCOUNT_DECREASE: + error = xfs_refcount_adjust(rcur, bno, blockcount, adjusted, + XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL); + break; + default: + ASSERT(0); + error = -EFSCORRUPTED; + } + if (!error && *adjusted != blockcount) + trace_xfs_refcount_finish_one_leftover(mp, agno, type, + bno, blockcount, *adjusted); + return error; + +out_cur: + xfs_trans_brelse(tp, agbp); + + return error; +} + +/* + * Record a refcount intent for later processing. + */ +static int +__xfs_refcount_add( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_refcount_intent *ri) +{ + struct xfs_refcount_intent *new; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 0; + + trace_xfs_refcount_defer(mp, XFS_FSB_TO_AGNO(mp, ri->ri_startblock), + ri->ri_type, XFS_FSB_TO_AGBNO(mp, ri->ri_startblock), + ri->ri_blockcount); + + new = kmem_zalloc(sizeof(struct xfs_refcount_intent), + KM_SLEEP | KM_NOFS); + *new = *ri; + + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_REFCOUNT, &new->ri_list); + return 0; +} + +/* + * Increase the reference count of the blocks backing a file's extent. + */ +int +xfs_refcount_increase_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_INCREASE; + ri.ri_startblock = PREV->br_startblock; + ri.ri_blockcount = PREV->br_blockcount; + + return __xfs_refcount_add(mp, dfops, &ri); +} + +/* + * Decrease the reference count of the blocks backing a file's extent. + */ +int +xfs_refcount_decrease_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_DECREASE; + ri.ri_startblock = PREV->br_startblock; + ri.ri_blockcount = PREV->br_blockcount; + + return __xfs_refcount_add(mp, dfops, &ri); +} diff --git a/libxfs/xfs_refcount.h b/libxfs/xfs_refcount.h index 0b36c1d..92c05ea 100644 --- a/libxfs/xfs_refcount.h +++ b/libxfs/xfs_refcount.h @@ -41,4 +41,16 @@ struct xfs_refcount_intent { xfs_extlen_t ri_blockcount; }; +extern int xfs_refcount_increase_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); +extern int xfs_refcount_decrease_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, struct xfs_bmbt_irec *irec); + +extern void xfs_refcount_finish_one_cleanup(struct xfs_trans *tp, + struct xfs_btree_cur *rcur, int error); +extern int xfs_refcount_finish_one(struct xfs_trans *tp, + struct xfs_defer_ops *dfops, enum xfs_refcount_intent_type type, + xfs_fsblock_t startblock, xfs_extlen_t blockcount, + xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur); + #endif /* __XFS_REFCOUNT_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:39:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 241A782BE for ; Thu, 16 Jun 2016 20:39:41 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id D62E1304039 for ; Thu, 16 Jun 2016 18:39:40 -0700 (PDT) X-ASG-Debug-ID: 1466127579-04bdf01e1796400001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id ExbVlqj6aAEn2kjz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1dZ9Q020326 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:36 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1dYmn010064 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:35 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1dYAp029469; Fri, 17 Jun 2016 01:39:34 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:34 -0700 Subject: [PATCH 083/145] xfs: adjust refcount when unmapping file blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 083/145] xfs: adjust refcount when unmapping file blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:32 -0700 Message-ID: <146612757275.16048.3246704899037088428.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127579 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1272 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we're unmapping blocks from a reflinked file, decrease the refcount of the affected blocks and free the extents that are no longer in use. v2: Use deferred ops system to avoid deadlocks and running out of transaction reservation. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 50faacd..7ef1d18 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -40,6 +40,7 @@ #include "xfs_quota_defs.h" #include "xfs_rmap_btree.h" #include "xfs_ag_resv.h" +#include "xfs_refcount.h" kmem_zone_t *xfs_bmap_free_item_zone; @@ -5053,9 +5054,16 @@ xfs_bmap_del_extent( /* * If we need to, add to list of extents to delete. */ - if (do_fx) - xfs_bmap_add_free(mp, dfops, del->br_startblock, - del->br_blockcount, NULL); + if (do_fx) { + if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) { + error = xfs_refcount_decrease_extent(mp, dfops, del); + if (error) + goto done; + } else + xfs_bmap_add_free(mp, dfops, del->br_startblock, + del->br_blockcount, NULL); + } + /* * Adjust inode # blocks in the file. */ From darrick.wong@oracle.com Thu Jun 16 20:39:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D297982C1 for ; Thu, 16 Jun 2016 20:39:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id A4475304048 for ; Thu, 16 Jun 2016 18:39:46 -0700 (PDT) X-ASG-Debug-ID: 1466127584-04cb6c5426581a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id EpqyzuC4g4UhMUCZ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:45 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1deu1020403 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:39:41 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1deM4003472 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:40 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1de7q029515; Fri, 17 Jun 2016 01:39:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:40 -0700 Subject: [PATCH 084/145] xfs: refcount btree requires more reserved space From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 084/145] xfs: refcount btree requires more reserved space To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:38 -0700 Message-ID: <146612757884.16048.3175525711587804664.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127585 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2800 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines The reference count btree is allocated from the free space, which means that we have to ensure that an AG can't run out of free space while performing a refcount operation. In the pathological case each AG block has its own refcntbt record, so we have to keep that much space available. v2: Calculate the maximum possible size of the rmap and refcount btrees based on minimally-full btree blocks. This increases the per-AG block reservations to handle the worst case btree size. Signed-off-by: Darrick J. Wong --- libxfs/xfs_alloc.c | 3 +++ libxfs/xfs_refcount_btree.c | 23 +++++++++++++++++++++++ libxfs/xfs_refcount_btree.h | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 6554ce7..ca3e7ce 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -34,6 +34,7 @@ #include "xfs_trace.h" #include "xfs_trans.h" #include "xfs_ag_resv.h" +#include "xfs_refcount_btree.h" struct workqueue_struct *xfs_alloc_wq; @@ -134,6 +135,8 @@ xfs_alloc_ag_max_usable(struct xfs_mount *mp) /* rmap root block + full tree split on full AG */ blocks += 1 + (2 * mp->m_ag_maxlevels) - 1; } + if (xfs_sb_version_hasreflink(&mp->m_sb)) + blocks += xfs_refcountbt_max_size(mp); return mp->m_sb.sb_agblocks - blocks; } diff --git a/libxfs/xfs_refcount_btree.c b/libxfs/xfs_refcount_btree.c index 8c53e71..8c1cba9 100644 --- a/libxfs/xfs_refcount_btree.c +++ b/libxfs/xfs_refcount_btree.c @@ -372,3 +372,26 @@ xfs_refcountbt_compute_maxlevels( mp->m_refc_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_refc_mnr, mp->m_sb.sb_agblocks); } + +/* Calculate the refcount btree size for some records. */ +xfs_extlen_t +xfs_refcountbt_calc_size( + struct xfs_mount *mp, + unsigned long long len) +{ + return xfs_btree_calc_size(mp, mp->m_refc_mnr, len); +} + +/* + * Calculate the maximum refcount btree size. + */ +xfs_extlen_t +xfs_refcountbt_max_size( + struct xfs_mount *mp) +{ + /* Bail out if we're uninitialized, which can happen in mkfs. */ + if (mp->m_refc_mxr[0] == 0) + return 0; + + return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); +} diff --git a/libxfs/xfs_refcount_btree.h b/libxfs/xfs_refcount_btree.h index 9e9ad7c..780b02f 100644 --- a/libxfs/xfs_refcount_btree.h +++ b/libxfs/xfs_refcount_btree.h @@ -64,4 +64,8 @@ extern int xfs_refcountbt_maxrecs(struct xfs_mount *mp, int blocklen, bool leaf); extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); +extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, + unsigned long long len); +extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); + #endif /* __XFS_REFCOUNT_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:39:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id F2AC382D1 for ; Thu, 16 Jun 2016 20:39:51 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id C37F4304048 for ; Thu, 16 Jun 2016 18:39:51 -0700 (PDT) X-ASG-Debug-ID: 1466127589-04cb6c5426581b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id CsbY3pEoOVHAZydQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:50 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1dm1c007826 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:39:48 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1dlVf003661 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:47 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1dk9A024279; Fri, 17 Jun 2016 01:39:47 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:46 -0700 Subject: [PATCH 085/145] xfs: introduce reflink utility functions From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 085/145] xfs: introduce reflink utility functions To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com, "Darrick J. Wong" Date: Thu, 16 Jun 2016 18:39:44 -0700 Message-ID: <146612758493.16048.18392330941529369752.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127589 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4927 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines These functions will be used by the other reflink functions to find the maximum length of a range of shared blocks. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 3 + libxfs/xfs_refcount.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_refcount.h | 4 ++ 3 files changed, 116 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 0b167e9..d3b2486 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -252,6 +252,9 @@ #define trace_xfs_refcount_deferred(...) ((void) 0) #define trace_xfs_refcount_defer(...) ((void) 0) #define trace_xfs_refcount_finish_one_leftover(...) ((void) 0) +#define trace_xfs_refcount_find_shared(...) ((void) 0) +#define trace_xfs_refcount_find_shared_result(...) ((void) 0) +#define trace_xfs_refcount_find_shared_error(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index 55859cd..d2b614b 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -1128,3 +1128,112 @@ xfs_refcount_decrease_extent( return __xfs_refcount_add(mp, dfops, &ri); } + +/* + * Given an AG extent, find the lowest-numbered run of shared blocks within + * that range and return the range in fbno/flen. If find_maximal is set, + * return the longest extent of shared blocks; if not, just return the first + * extent we find. If no shared blocks are found, flen will be set to zero. + */ +int +xfs_refcount_find_shared( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_agblock_t *fbno, + xfs_extlen_t *flen, + bool find_maximal) +{ + struct xfs_btree_cur *cur; + struct xfs_buf *agbp; + struct xfs_refcount_irec tmp; + int error; + int i, have; + int bt_error = XFS_BTREE_ERROR; + + trace_xfs_refcount_find_shared(mp, agno, agbno, aglen); + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + goto out; + cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); + + /* By default, skip the whole range */ + *fbno = agbno + aglen; + *flen = 0; + + /* Try to find a refcount extent that crosses the start */ + error = xfs_refcountbt_lookup_le(cur, agbno, &have); + if (error) + goto out_error; + if (!have) { + /* No left extent, look at the next one */ + error = xfs_btree_increment(cur, 0, &have); + if (error) + goto out_error; + if (!have) + goto done; + } + error = xfs_refcountbt_get_rec(cur, &tmp, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + /* If the extent ends before the start, look at the next one */ + if (tmp.rc_startblock + tmp.rc_blockcount <= agbno) { + error = xfs_btree_increment(cur, 0, &have); + if (error) + goto out_error; + if (!have) + goto done; + error = xfs_refcountbt_get_rec(cur, &tmp, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + } + + /* If the extent ends after the range we want, bail out */ + if (tmp.rc_startblock >= agbno + aglen) + goto done; + + /* We found the start of a shared extent! */ + if (tmp.rc_startblock < agbno) { + tmp.rc_blockcount -= (agbno - tmp.rc_startblock); + tmp.rc_startblock = agbno; + } + + *fbno = tmp.rc_startblock; + *flen = min(tmp.rc_blockcount, agbno + aglen - *fbno); + if (!find_maximal) + goto done; + + /* Otherwise, find the end of this shared extent */ + while (*fbno + *flen < agbno + aglen) { + error = xfs_btree_increment(cur, 0, &have); + if (error) + goto out_error; + if (!have) + break; + error = xfs_refcountbt_get_rec(cur, &tmp, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + if (tmp.rc_startblock >= agbno + aglen || + tmp.rc_startblock != *fbno + *flen) + break; + *flen = min(*flen + tmp.rc_blockcount, agbno + aglen - *fbno); + } + +done: + bt_error = XFS_BTREE_NOERROR; + trace_xfs_refcount_find_shared_result(mp, agno, *fbno, *flen); + +out_error: + xfs_btree_del_cursor(cur, bt_error); + xfs_buf_relse(agbp); +out: + if (error) + trace_xfs_refcount_find_shared_error(mp, agno, error, _RET_IP_); + return error; +} diff --git a/libxfs/xfs_refcount.h b/libxfs/xfs_refcount.h index 92c05ea..b7b83b8 100644 --- a/libxfs/xfs_refcount.h +++ b/libxfs/xfs_refcount.h @@ -53,4 +53,8 @@ extern int xfs_refcount_finish_one(struct xfs_trans *tp, xfs_fsblock_t startblock, xfs_extlen_t blockcount, xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur); +extern int xfs_refcount_find_shared(struct xfs_mount *mp, xfs_agnumber_t agno, + xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, + xfs_extlen_t *flen, bool find_maximal); + #endif /* __XFS_REFCOUNT_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:40:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EB462829E for ; Thu, 16 Jun 2016 20:40:00 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 60578AC001 for ; Thu, 16 Jun 2016 18:40:00 -0700 (PDT) X-ASG-Debug-ID: 1466127598-04cbb01fec6a460001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id m6wwHC9ALxdlz9d7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:39:58 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1duXt007896 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:39:57 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1duLY003889 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:39:56 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1drgB012214; Fri, 17 Jun 2016 01:39:54 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:39:53 -0700 Subject: [PATCH 086/145] xfs: create bmbt update intent log items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 086/145] xfs: create bmbt update intent log items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:51 -0700 Message-ID: <146612759115.16048.12033211481399359990.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127598 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3448 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create bmbt update intent/done log items to record redo information in the log. Because we need to roll transactions multiple times for reflink operations, between we also have to track the status of the metadata updates that will be recorded in the post-roll transactions, just in case we crash before committing the final transaction. This mechanism enables log recovery to finish what was already started. Signed-off-by: Darrick J. Wong --- libxfs/xfs_log_format.h | 52 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h index 923b08f..320a305 100644 --- a/libxfs/xfs_log_format.h +++ b/libxfs/xfs_log_format.h @@ -114,7 +114,9 @@ static inline uint xlog_get_cycle(char *ptr) #define XLOG_REG_TYPE_RUD_FORMAT 22 #define XLOG_REG_TYPE_CUI_FORMAT 23 #define XLOG_REG_TYPE_CUD_FORMAT 24 -#define XLOG_REG_TYPE_MAX 24 +#define XLOG_REG_TYPE_BUI_FORMAT 25 +#define XLOG_REG_TYPE_BUD_FORMAT 26 +#define XLOG_REG_TYPE_MAX 26 /* * Flags to log operation header @@ -235,6 +237,8 @@ typedef struct xfs_trans_header { #define XFS_LI_RUD 0x1241 #define XFS_LI_CUI 0x1242 /* refcount update intent */ #define XFS_LI_CUD 0x1243 +#define XFS_LI_BUI 0x1244 /* bmbt update intent */ +#define XFS_LI_BUD 0x1245 #define XFS_LI_TYPE_DESC \ { XFS_LI_EFI, "XFS_LI_EFI" }, \ @@ -248,7 +252,9 @@ typedef struct xfs_trans_header { { XFS_LI_RUI, "XFS_LI_RUI" }, \ { XFS_LI_RUD, "XFS_LI_RUD" }, \ { XFS_LI_CUI, "XFS_LI_CUI" }, \ - { XFS_LI_CUD, "XFS_LI_CUD" } + { XFS_LI_CUD, "XFS_LI_CUD" }, \ + { XFS_LI_BUI, "XFS_LI_BUI" }, \ + { XFS_LI_BUD, "XFS_LI_BUD" } /* * Inode Log Item Format definitions. @@ -717,6 +723,48 @@ struct xfs_cud_log_format { }; /* + * BUI/BUD (inode block mapping) log format definitions + */ + +/* bmbt me_flags: upper bits are flags, lower byte is type code */ +#define XFS_BMAP_EXTENT_MAP 1 +#define XFS_BMAP_EXTENT_UNMAP 2 +#define XFS_BMAP_EXTENT_TYPE_MASK 0xFF + +#define XFS_BMAP_EXTENT_ATTR_FORK (1U << 31) +#define XFS_BMAP_EXTENT_UNWRITTEN (1U << 30) + +#define XFS_BMAP_EXTENT_FLAGS (XFS_BMAP_EXTENT_TYPE_MASK | \ + XFS_BMAP_EXTENT_ATTR_FORK | \ + XFS_BMAP_EXTENT_UNWRITTEN) + +/* + * This is the structure used to lay out an bui log item in the + * log. The bui_extents field is a variable size array whose + * size is given by bui_nextents. + */ +struct xfs_bui_log_format { + __uint16_t bui_type; /* bui log item type */ + __uint16_t bui_size; /* size of this item */ + __uint32_t bui_nextents; /* # extents to free */ + __uint64_t bui_id; /* bui identifier */ + struct xfs_map_extent bui_extents[1]; /* array of extents to bmap */ +}; + +/* + * This is the structure used to lay out an bud log item in the + * log. The bud_extents array is a variable size array whose + * size is given by bud_nextents; + */ +struct xfs_bud_log_format { + __uint16_t bud_type; /* bud log item type */ + __uint16_t bud_size; /* size of this item */ + __uint32_t bud_nextents; /* # of extents freed */ + __uint64_t bud_bui_id; /* id of corresponding bui */ + struct xfs_map_extent bud_extents[1]; /* array of extents bmapped */ +}; + +/* * Dquot Log format definitions. * * The first two fields must be the type and size fitting into From darrick.wong@oracle.com Thu Jun 16 20:40:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EC0D682E0 for ; Thu, 16 Jun 2016 20:40:04 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id AA71B8F8050 for ; Thu, 16 Jun 2016 18:40:04 -0700 (PDT) X-ASG-Debug-ID: 1466127602-04bdf01e1596420001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id cdaQMNLYgVQsMGiJ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:02 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1e1gL007945 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:01 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1e1ic030834 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:01 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1e0nK001853; Fri, 17 Jun 2016 01:40:01 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:00 -0700 Subject: [PATCH 087/145] xfs: log bmap intent items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 087/145] xfs: log bmap intent items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:39:58 -0700 Message-ID: <146612759816.16048.13949394799554585448.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127602 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 909 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Provide a mechanism for higher levels to create BUI/BUD items, submit them to the log, and a stub function to deal with recovered BUI items. These parts will be connected to the rmapbt in a later patch. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index 41f7ef2..62a66d0 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -209,5 +209,17 @@ struct xfs_bmbt_rec_host * struct xfs_bmbt_irec *gotp, struct xfs_bmbt_irec *prevp); +enum xfs_bmap_intent_type { + XFS_BMAP_MAP, + XFS_BMAP_UNMAP, +}; + +struct xfs_bmap_intent { + struct list_head bi_list; + enum xfs_bmap_intent_type bi_type; + struct xfs_inode *bi_owner; + int bi_whichfork; + struct xfs_bmbt_irec bi_bmap; +}; #endif /* __XFS_BMAP_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:40:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id AE9E582AF for ; Thu, 16 Jun 2016 20:40:14 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 7E92D304039 for ; Thu, 16 Jun 2016 18:40:14 -0700 (PDT) X-ASG-Debug-ID: 1466127612-04cbb01fee6a490001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id dZpdM5NDGRLeT3iz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:12 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1e8eo020847 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:08 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1e7Bc031314 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:07 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1e6KF029617; Fri, 17 Jun 2016 01:40:07 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:06 -0700 Subject: [PATCH 088/145] xfs: map an inode's offset to an exact physical block From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 088/145] xfs: map an inode's offset to an exact physical block To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:05 -0700 Message-ID: <146612760515.16048.9407022403121181267.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127612 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5013 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach the bmap routine to know how to map a range of file blocks to a specific range of physical blocks, instead of simply allocating fresh blocks. This enables reflink to map a file to blocks that are already in use. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 3 ++ libxfs/xfs_bmap.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_bmap.h | 10 +++++++- 3 files changed, 75 insertions(+), 1 deletion(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index d3b2486..6277b53 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -256,6 +256,9 @@ #define trace_xfs_refcount_find_shared_result(...) ((void) 0) #define trace_xfs_refcount_find_shared_error(...) ((void) 0) +#define trace_xfs_bmap_remap_alloc(...) ((void) 0) +#define trace_xfs_bmap_remap_alloc_error(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 7ef1d18..58f730e 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -3864,6 +3864,55 @@ xfs_bmap_btalloc( } /* + * For a remap operation, just "allocate" an extent at the address that the + * caller passed in, and ensure that the AGFL is the right size. The caller + * will then map the "allocated" extent into the file somewhere. + */ +STATIC int +xfs_bmap_remap_alloc( + struct xfs_bmalloca *ap) +{ + struct xfs_trans *tp = ap->tp; + struct xfs_mount *mp = tp->t_mountp; + xfs_agblock_t bno; + struct xfs_alloc_arg args; + int error; + + /* + * validate that the block number is legal - the enables us to detect + * and handle a silent filesystem corruption rather than crashing. + */ + memset(&args, 0, sizeof(struct xfs_alloc_arg)); + args.tp = ap->tp; + args.mp = ap->tp->t_mountp; + bno = *ap->firstblock; + args.agno = XFS_FSB_TO_AGNO(mp, bno); + ASSERT(args.agno < mp->m_sb.sb_agcount); + args.agbno = XFS_FSB_TO_AGBNO(mp, bno); + ASSERT(args.agbno < mp->m_sb.sb_agblocks); + + /* "Allocate" the extent from the range we passed in. */ + trace_xfs_bmap_remap_alloc(ap->ip, *ap->firstblock, ap->length); + ap->blkno = bno; + ap->ip->i_d.di_nblocks += ap->length; + xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); + + /* Fix the freelist, like a real allocator does. */ + args.userdata = 1; + args.pag = xfs_perag_get(args.mp, args.agno); + ASSERT(args.pag); + + error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING); + if (error) + goto error0; +error0: + xfs_perag_put(args.pag); + if (error) + trace_xfs_bmap_remap_alloc_error(ap->ip, error, _RET_IP_); + return error; +} + +/* * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. * It figures out where to ask the underlying allocator to put the new extent. */ @@ -3871,6 +3920,8 @@ STATIC int xfs_bmap_alloc( struct xfs_bmalloca *ap) /* bmap alloc argument struct */ { + if (ap->flags & XFS_BMAPI_REMAP) + return xfs_bmap_remap_alloc(ap); if (XFS_IS_REALTIME_INODE(ap->ip) && ap->userdata) return xfs_bmap_rtalloc(ap); return xfs_bmap_btalloc(ap); @@ -4507,6 +4558,12 @@ xfs_bmapi_write( ASSERT(len > 0); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_LOCAL); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + if (whichfork == XFS_ATTR_FORK) + ASSERT(!(flags & XFS_BMAPI_REMAP)); + if (flags & XFS_BMAPI_REMAP) { + ASSERT(!(flags & XFS_BMAPI_PREALLOC)); + ASSERT(!(flags & XFS_BMAPI_CONVERT)); + } /* zeroing is for currently only for data extents, not metadata */ ASSERT((flags & (XFS_BMAPI_METADATA | XFS_BMAPI_ZERO)) != @@ -4568,6 +4625,12 @@ xfs_bmapi_write( wasdelay = !inhole && isnullstartblock(bma.got.br_startblock); /* + * Make sure we only reflink into a hole. + */ + if (flags & XFS_BMAPI_REMAP) + ASSERT(inhole); + + /* * First, deal with the hole before the allocated space * that we found, if any. */ diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index 62a66d0..fb2fd4c 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -97,6 +97,13 @@ struct xfs_bmap_free_item */ #define XFS_BMAPI_ZERO 0x080 +/* + * Map the inode offset to the block given in ap->firstblock. Primarily + * used for reflink. The range must be in a hole, and this flag cannot be + * turned on with PREALLOC or CONVERT, and cannot be used on the attr fork. + */ +#define XFS_BMAPI_REMAP 0x100 + #define XFS_BMAPI_FLAGS \ { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ { XFS_BMAPI_METADATA, "METADATA" }, \ @@ -105,7 +112,8 @@ struct xfs_bmap_free_item { XFS_BMAPI_IGSTATE, "IGSTATE" }, \ { XFS_BMAPI_CONTIG, "CONTIG" }, \ { XFS_BMAPI_CONVERT, "CONVERT" }, \ - { XFS_BMAPI_ZERO, "ZERO" } + { XFS_BMAPI_ZERO, "ZERO" }, \ + { XFS_BMAPI_REMAP, "REMAP" } static inline int xfs_bmapi_aflag(int w) From darrick.wong@oracle.com Thu Jun 16 20:40:17 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D185382EC for ; Thu, 16 Jun 2016 20:40:17 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 91080304039 for ; Thu, 16 Jun 2016 18:40:17 -0700 (PDT) X-ASG-Debug-ID: 1466127615-04cb6c5427581f0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id TLLwJUmDnk9l35Mh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1eDnG008262 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:40:14 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1eDUq004658 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:13 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1eDLH029735; Fri, 17 Jun 2016 01:40:13 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:12 -0700 Subject: [PATCH 089/145] xfs: implement deferred bmbt map/unmap operations From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 089/145] xfs: implement deferred bmbt map/unmap operations To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:11 -0700 Message-ID: <146612761130.16048.14802509002983794111.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127615 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8558 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Implement deferred versions of the inode block map/unmap functions. These will be used in subsequent patches to make reflink operations atomic. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 2 + libxfs/defer_item.c | 101 ++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_bmap.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_bmap.h | 11 +++++ libxfs/xfs_defer.h | 1 5 files changed, 239 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 6277b53..dfc92a6 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -258,6 +258,8 @@ #define trace_xfs_bmap_remap_alloc(...) ((void) 0) #define trace_xfs_bmap_remap_alloc_error(...) ((void) 0) +#define trace_xfs_bmap_deferred(...) ((void) 0) +#define trace_xfs_bmap_defer(...) ((void) 0) /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) diff --git a/libxfs/defer_item.c b/libxfs/defer_item.c index a383813..bd41808 100644 --- a/libxfs/defer_item.c +++ b/libxfs/defer_item.c @@ -32,6 +32,8 @@ #include "xfs_alloc.h" #include "xfs_rmap_btree.h" #include "xfs_refcount.h" +#include "xfs_bmap.h" +#include "xfs_inode.h" /* Extent Freeing */ @@ -364,12 +366,111 @@ const struct xfs_defer_op_type xfs_refcount_update_defer_type = { .cancel_item = xfs_refcount_update_cancel_item, }; +/* Inode Block Mapping */ + +/* Sort bmap intents by inode. */ +static int +xfs_bmap_update_diff_items( + void *priv, + struct list_head *a, + struct list_head *b) +{ + struct xfs_bmap_intent *ba; + struct xfs_bmap_intent *bb; + + ba = container_of(a, struct xfs_bmap_intent, bi_list); + bb = container_of(b, struct xfs_bmap_intent, bi_list); + return ba->bi_owner->i_ino - bb->bi_owner->i_ino; +} + +/* Get an BUI. */ +STATIC void * +xfs_bmap_update_create_intent( + struct xfs_trans *tp, + unsigned int count) +{ + return NULL; +} + +/* Log bmap updates in the intent item. */ +STATIC void +xfs_bmap_update_log_item( + struct xfs_trans *tp, + void *intent, + struct list_head *item) +{ +} + +/* Get an BUD so we can process all the deferred rmap updates. */ +STATIC void * +xfs_bmap_update_create_done( + struct xfs_trans *tp, + void *intent, + unsigned int count) +{ + return NULL; +} + +/* Process a deferred rmap update. */ +STATIC int +xfs_bmap_update_finish_item( + struct xfs_trans *tp, + struct xfs_defer_ops *dop, + struct list_head *item, + void *done_item, + void **state) +{ + struct xfs_bmap_intent *bmap; + int error; + + bmap = container_of(item, struct xfs_bmap_intent, bi_list); + error = xfs_bmap_finish_one(tp, dop, + bmap->bi_owner, + bmap->bi_type, bmap->bi_whichfork, + bmap->bi_bmap.br_startoff, + bmap->bi_bmap.br_startblock, + bmap->bi_bmap.br_blockcount, + bmap->bi_bmap.br_state); + kmem_free(bmap); + return error; +} + +/* Abort all pending BUIs. */ +STATIC void +xfs_bmap_update_abort_intent( + void *intent) +{ +} + +/* Cancel a deferred rmap update. */ +STATIC void +xfs_bmap_update_cancel_item( + struct list_head *item) +{ + struct xfs_bmap_intent *bmap; + + bmap = container_of(item, struct xfs_bmap_intent, bi_list); + kmem_free(bmap); +} + +const struct xfs_defer_op_type xfs_bmap_update_defer_type = { + .type = XFS_DEFER_OPS_TYPE_BMAP, + .diff_items = xfs_bmap_update_diff_items, + .create_intent = xfs_bmap_update_create_intent, + .abort_intent = xfs_bmap_update_abort_intent, + .log_item = xfs_bmap_update_log_item, + .create_done = xfs_bmap_update_create_done, + .finish_item = xfs_bmap_update_finish_item, + .cancel_item = xfs_bmap_update_cancel_item, +}; + /* Deferred Item Initialization */ /* Initialize the deferred operation types. */ void xfs_defer_init_types(void) { + xfs_defer_init_op_type(&xfs_bmap_update_defer_type); xfs_defer_init_op_type(&xfs_refcount_update_defer_type); xfs_defer_init_op_type(&xfs_rmap_update_defer_type); xfs_defer_init_op_type(&xfs_extent_free_defer_type); diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 58f730e..dff4b7b 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -6119,3 +6119,127 @@ out: xfs_trans_cancel(tp); return error; } + +/* Record a bmap intent. */ +static int +__xfs_bmap_add( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_bmap_intent *bi) +{ + int error; + struct xfs_bmap_intent *new; + + ASSERT(bi->bi_whichfork == XFS_DATA_FORK); + + trace_xfs_bmap_defer(mp, XFS_FSB_TO_AGNO(mp, bi->bi_bmap.br_startblock), + bi->bi_type, + XFS_FSB_TO_AGBNO(mp, bi->bi_bmap.br_startblock), + bi->bi_owner->i_ino, bi->bi_whichfork, + bi->bi_bmap.br_startoff, + bi->bi_bmap.br_blockcount, + bi->bi_bmap.br_state); + + new = kmem_zalloc(sizeof(struct xfs_bmap_intent), KM_SLEEP | KM_NOFS); + *new = *bi; + + error = xfs_defer_join(dfops, bi->bi_owner); + if (error) + return error; + + xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_BMAP, &new->bi_list); + return 0; +} + +/* Map an extent into a file. */ +int +xfs_bmap_map_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_bmap_intent bi; + + bi.bi_type = XFS_BMAP_MAP; + bi.bi_owner = ip; + bi.bi_whichfork = whichfork; + bi.bi_bmap = *PREV; + + return __xfs_bmap_add(mp, dfops, &bi); +} + +/* Unmap an extent out of a file. */ +int +xfs_bmap_unmap_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + int whichfork, + struct xfs_bmbt_irec *PREV) +{ + struct xfs_bmap_intent bi; + + bi.bi_type = XFS_BMAP_UNMAP; + bi.bi_owner = ip; + bi.bi_whichfork = whichfork; + bi.bi_bmap = *PREV; + + return __xfs_bmap_add(mp, dfops, &bi); +} + +/* + * Process one of the deferred bmap operations. We pass back the + * btree cursor to maintain our lock on the bmapbt between calls. + */ +int +xfs_bmap_finish_one( + struct xfs_trans *tp, + struct xfs_defer_ops *dfops, + struct xfs_inode *ip, + enum xfs_bmap_intent_type type, + int whichfork, + xfs_fileoff_t startoff, + xfs_fsblock_t startblock, + xfs_filblks_t blockcount, + xfs_exntst_t state) +{ + struct xfs_bmbt_irec bmap; + int nimaps = 1; + xfs_fsblock_t firstfsb; + int error = 0; + + bmap.br_startblock = startblock; + bmap.br_startoff = startoff; + bmap.br_blockcount = blockcount; + bmap.br_state = state; + + trace_xfs_bmap_deferred(tp->t_mountp, + XFS_FSB_TO_AGNO(tp->t_mountp, startblock), type, + XFS_FSB_TO_AGBNO(tp->t_mountp, startblock), + ip->i_ino, whichfork, startoff, blockcount, state); + + if (XFS_TEST_ERROR(false, tp->t_mountp, + XFS_ERRTAG_BMAP_FINISH_ONE, + XFS_RANDOM_BMAP_FINISH_ONE)) + return -EIO; + + switch (type) { + case XFS_BMAP_MAP: + firstfsb = bmap.br_startblock; + error = xfs_bmapi_write(tp, ip, bmap.br_startoff, + bmap.br_blockcount, + XFS_BMAPI_REMAP, &firstfsb, + bmap.br_blockcount, &bmap, &nimaps, + dfops); + break; + case XFS_BMAP_UNMAP: + /* not implemented for now */ + default: + ASSERT(0); + error = -EFSCORRUPTED; + } + + return error; +} diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index fb2fd4c..394a22c 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -230,4 +230,15 @@ struct xfs_bmap_intent { struct xfs_bmbt_irec bi_bmap; }; +int xfs_bmap_finish_one(struct xfs_trans *tp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, enum xfs_bmap_intent_type type, + int whichfork, xfs_fileoff_t startoff, xfs_fsblock_t startblock, + xfs_filblks_t blockcount, xfs_exntst_t state); +int xfs_bmap_map_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); +int xfs_bmap_unmap_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, + struct xfs_inode *ip, int whichfork, + struct xfs_bmbt_irec *imap); + #endif /* __XFS_BMAP_H__ */ diff --git a/libxfs/xfs_defer.h b/libxfs/xfs_defer.h index 4081b00..47aa048 100644 --- a/libxfs/xfs_defer.h +++ b/libxfs/xfs_defer.h @@ -51,6 +51,7 @@ struct xfs_defer_pending { * find all the space it needs. */ enum xfs_defer_ops_type { + XFS_DEFER_OPS_TYPE_BMAP, XFS_DEFER_OPS_TYPE_REFCOUNT, XFS_DEFER_OPS_TYPE_RMAP, XFS_DEFER_OPS_TYPE_FREE, From darrick.wong@oracle.com Thu Jun 16 20:40:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 69CF682F2 for ; Thu, 16 Jun 2016 20:40:23 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id E1DF1AC001 for ; Thu, 16 Jun 2016 18:40:22 -0700 (PDT) X-ASG-Debug-ID: 1466127620-04cbb01fed6a4b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 0AJk6vZEUu7LnhIQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:21 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1eKik008303 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:20 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1eJtY031552 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:19 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1eJtI029754; Fri, 17 Jun 2016 01:40:19 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:18 -0700 Subject: [PATCH 090/145] xfs: return work remaining at the end of a bunmapi operation From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 090/145] xfs: return work remaining at the end of a bunmapi operation To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:17 -0700 Message-ID: <146612761750.16048.7128549085400683099.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127621 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3531 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Return the range of file blocks that bunmapi didn't free. This hint is used by CoW and reflink to figure out what part of an extent actually got freed so that it can set up the appropriate atomic remapping of just the freed range. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.c | 36 ++++++++++++++++++++++++++++++------ libxfs/xfs_bmap.h | 4 ++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index dff4b7b..f0c0871 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -5157,17 +5157,16 @@ done: * *done is set. */ int /* error */ -xfs_bunmapi( +__xfs_bunmapi( xfs_trans_t *tp, /* transaction pointer */ struct xfs_inode *ip, /* incore inode */ xfs_fileoff_t bno, /* starting offset to unmap */ - xfs_filblks_t len, /* length to unmap in file */ + xfs_filblks_t *rlen, /* i/o: amount remaining */ int flags, /* misc flags */ xfs_extnum_t nexts, /* number of extents max */ xfs_fsblock_t *firstblock, /* first allocated block controls a.g. for allocs */ - struct xfs_defer_ops *dfops, /* i/o: list extents to free */ - int *done) /* set if not done yet */ + struct xfs_defer_ops *dfops) /* i/o: deferred updates */ { xfs_btree_cur_t *cur; /* bmap btree cursor */ xfs_bmbt_irec_t del; /* extent being deleted */ @@ -5189,6 +5188,7 @@ xfs_bunmapi( int wasdel; /* was a delayed alloc extent */ int whichfork; /* data or attribute fork */ xfs_fsblock_t sum; + xfs_filblks_t len = *rlen; /* length to unmap in file */ trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); @@ -5215,7 +5215,7 @@ xfs_bunmapi( return error; nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t); if (nextents == 0) { - *done = 1; + *rlen = 0; return 0; } XFS_STATS_INC(mp, xs_blk_unmap); @@ -5484,7 +5484,10 @@ nodelete: extno++; } } - *done = bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0; + if (bno == (xfs_fileoff_t)-1 || bno < start || lastx < 0) + *rlen = 0; + else + *rlen = bno - start + 1; /* * Convert to a btree if necessary. @@ -5540,6 +5543,27 @@ error0: return error; } +/* Unmap a range of a file. */ +int +xfs_bunmapi( + xfs_trans_t *tp, + struct xfs_inode *ip, + xfs_fileoff_t bno, + xfs_filblks_t len, + int flags, + xfs_extnum_t nexts, + xfs_fsblock_t *firstblock, + struct xfs_defer_ops *dfops, + int *done) +{ + int error; + + error = __xfs_bunmapi(tp, ip, bno, &len, flags, nexts, firstblock, + dfops); + *done = (len == 0); + return error; +} + /* * Determine whether an extent shift can be accomplished by a merge with the * extent that precedes the target hole of the shift. diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index 394a22c..97828c5 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -197,6 +197,10 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fsblock_t *firstblock, xfs_extlen_t total, struct xfs_bmbt_irec *mval, int *nmap, struct xfs_defer_ops *dfops); +int __xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, + xfs_fileoff_t bno, xfs_filblks_t *rlen, int flags, + xfs_extnum_t nexts, xfs_fsblock_t *firstblock, + struct xfs_defer_ops *dfops); int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, From darrick.wong@oracle.com Thu Jun 16 20:40:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AC78982F3 for ; Thu, 16 Jun 2016 20:40:31 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5EE938F804B for ; Thu, 16 Jun 2016 18:40:31 -0700 (PDT) X-ASG-Debug-ID: 1466127629-04bdf01e1396460001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id l5GcDwy3BCseBgDg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ePcf020991 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:40:26 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1ePC3004844 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:40:25 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1ePq4002055; Fri, 17 Jun 2016 01:40:25 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:24 -0700 Subject: [PATCH 091/145] xfs: add reflink feature flag to geometry From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 091/145] xfs: add reflink feature flag to geometry To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:23 -0700 Message-ID: <146612762359.16048.13694232631293022681.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127630 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 943 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Report the reflink feature in the XFS geometry so that xfs_info and friends know the filesystem has this feature. Signed-off-by: Darrick J. Wong --- libxfs/xfs_fs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index 085ea6f..f291a53 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -230,7 +230,8 @@ typedef struct xfs_fsop_resblks { #define XFS_FSOP_GEOM_FLAGS_FTYPE 0x10000 /* inode directory types */ #define XFS_FSOP_GEOM_FLAGS_FINOBT 0x20000 /* free inode btree */ #define XFS_FSOP_GEOM_FLAGS_SPINODES 0x40000 /* sparse inode chunks */ -#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* Reverse mapping btree */ +#define XFS_FSOP_GEOM_FLAGS_RMAPBT 0x80000 /* reverse mapping btree */ +#define XFS_FSOP_GEOM_FLAGS_REFLINK 0x100000 /* files can share blocks */ /* * Minimum and maximum sizes need for growth checks. From darrick.wong@oracle.com Thu Jun 16 20:40:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EFC898300 for ; Thu, 16 Jun 2016 20:40:37 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id B04DC8F804B for ; Thu, 16 Jun 2016 18:40:37 -0700 (PDT) X-ASG-Debug-ID: 1466127635-04cb6c542658230001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id WAMMHDhv9K9ALPei (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:36 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1eVpd021020 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:31 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1eVgH007426 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:31 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1eVNl002067; Fri, 17 Jun 2016 01:40:31 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:31 -0700 Subject: [PATCH 092/145] xfs: don't allow reflinked dir/dev/fifo/socket/pipe files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 092/145] xfs: don't allow reflinked dir/dev/fifo/socket/pipe files To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:29 -0700 Message-ID: <146612762967.16048.12520252071197307755.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127636 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1551 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Only non-rt files can be reflinked, so check that when we load an inode. Also, don't leak the attr fork if there's a failure. Signed-off-by: Darrick J. Wong --- libxfs/xfs_inode_fork.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 799873a..83fd4f3 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -117,6 +117,26 @@ xfs_iformat_fork( return -EFSCORRUPTED; } + if (unlikely(xfs_is_reflink_inode(ip) && + (VFS_I(ip)->i_mode & S_IFMT) != S_IFREG)) { + xfs_warn(ip->i_mount, + "corrupt dinode %llu, wrong file type for reflink.", + ip->i_ino); + XFS_CORRUPTION_ERROR("xfs_iformat(reflink)", + XFS_ERRLEVEL_LOW, ip->i_mount, dip); + return -EFSCORRUPTED; + } + + if (unlikely(xfs_is_reflink_inode(ip) && + (ip->i_d.di_flags & XFS_DIFLAG_REALTIME))) { + xfs_warn(ip->i_mount, + "corrupt dinode %llu, has reflink+realtime flag set.", + ip->i_ino); + XFS_CORRUPTION_ERROR("xfs_iformat(reflink)", + XFS_ERRLEVEL_LOW, ip->i_mount, dip); + return -EFSCORRUPTED; + } + switch (VFS_I(ip)->i_mode & S_IFMT) { case S_IFIFO: case S_IFCHR: @@ -204,7 +224,8 @@ xfs_iformat_fork( XFS_CORRUPTION_ERROR("xfs_iformat(8)", XFS_ERRLEVEL_LOW, ip->i_mount, dip); - return -EFSCORRUPTED; + error = -EFSCORRUPTED; + break; } error = xfs_iformat_local(ip, dip, XFS_ATTR_FORK, size); From darrick.wong@oracle.com Thu Jun 16 20:40:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 14C248306 for ; Thu, 16 Jun 2016 20:40:46 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id C81D6304039 for ; Thu, 16 Jun 2016 18:40:45 -0700 (PDT) X-ASG-Debug-ID: 1466127642-04bdf01e1796490001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id xMvYuUU6jEnYap3X (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:42 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1efgU008481 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:41 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ef2g011993 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:41 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ebn4012393; Fri, 17 Jun 2016 01:40:39 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:37 -0700 Subject: [PATCH 093/145] xfs: introduce the CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 093/145] xfs: introduce the CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:35 -0700 Message-ID: <146612763578.16048.16178899612338631224.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127642 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12341 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Introduce a new in-core fork for storing copy-on-write delalloc reservations and allocated extents that are in the process of being written out. v2: fix up bmapi_read so that we can query the CoW fork, and have it return a "hole" extent if there's no CoW fork. Signed-off-by: Darrick J. Wong --- include/xfs_inode.h | 3 +++ libxfs/rdwr.c | 2 ++ libxfs/xfs_bmap.c | 27 ++++++++++++++++++++------- libxfs/xfs_bmap.h | 22 +++++++++++++++++++--- libxfs/xfs_bmap_btree.c | 1 + libxfs/xfs_inode_fork.c | 47 ++++++++++++++++++++++++++++++++++++++++++++--- libxfs/xfs_inode_fork.h | 28 ++++++++++++++++++++++------ libxfs/xfs_rmap.c | 2 ++ libxfs/xfs_types.h | 1 + 9 files changed, 114 insertions(+), 19 deletions(-) diff --git a/include/xfs_inode.h b/include/xfs_inode.h index 3876fa6..b7623c0 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -50,6 +50,7 @@ typedef struct xfs_inode { struct xfs_imap i_imap; /* location for xfs_imap() */ struct xfs_buftarg i_dev; /* dev for this inode */ struct xfs_ifork *i_afp; /* attribute fork pointer */ + struct xfs_ifork *i_cowfp; /* copy on write extents */ struct xfs_ifork i_df; /* data fork */ struct xfs_trans *i_transp; /* ptr to owning transaction */ struct xfs_inode_log_item *i_itemp; /* logging information */ @@ -58,6 +59,8 @@ typedef struct xfs_inode { xfs_fsize_t i_size; /* in-memory size */ const struct xfs_dir_ops *d_ops; /* directory ops vector */ struct inode i_vnode; + xfs_extnum_t i_cnextents; /* # of extents in cow fork */ + unsigned int i_cformat; /* format of cow fork */ } xfs_inode_t; static inline struct inode *VFS_I(struct xfs_inode *ip) diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c index aa30522..533a064 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -1372,6 +1372,8 @@ libxfs_idestroy(xfs_inode_t *ip) } if (ip->i_afp) libxfs_idestroy_fork(ip, XFS_ATTR_FORK); + if (ip->i_cowfp) + xfs_idestroy_fork(ip, XFS_COW_FORK); } void diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index f0c0871..2ec3385 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -2916,6 +2916,7 @@ xfs_bmap_add_extent_hole_real( ASSERT(!isnullstartblock(new->br_startblock)); ASSERT(!bma->cur || !(bma->cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL)); + ASSERT(whichfork != XFS_COW_FORK); XFS_STATS_INC(mp, xs_add_exlist); @@ -4050,12 +4051,11 @@ xfs_bmapi_read( int error; int eof; int n = 0; - int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + int whichfork = xfs_bmapi_whichfork(flags); ASSERT(*nmap >= 1); ASSERT(!(flags & ~(XFS_BMAPI_ATTRFORK|XFS_BMAPI_ENTIRE| - XFS_BMAPI_IGSTATE))); + XFS_BMAPI_IGSTATE|XFS_BMAPI_COWFORK))); ASSERT(xfs_isilocked(ip, XFS_ILOCK_SHARED|XFS_ILOCK_EXCL)); if (unlikely(XFS_TEST_ERROR( @@ -4073,6 +4073,16 @@ xfs_bmapi_read( ifp = XFS_IFORK_PTR(ip, whichfork); + /* No CoW fork? Return a hole. */ + if (whichfork == XFS_COW_FORK && !ifp) { + mval->br_startoff = bno; + mval->br_startblock = HOLESTARTBLOCK; + mval->br_blockcount = len; + mval->br_state = XFS_EXT_NORM; + *nmap = 1; + return 0; + } + if (!(ifp->if_flags & XFS_IFEXTENTS)) { error = xfs_iread_extents(NULL, ip, whichfork); if (error) @@ -4425,8 +4435,7 @@ xfs_bmapi_convert_unwritten( xfs_filblks_t len, int flags) { - int whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + int whichfork = xfs_bmapi_whichfork(flags); struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); int tmp_logflags = 0; int error; @@ -4442,6 +4451,8 @@ xfs_bmapi_convert_unwritten( (XFS_BMAPI_PREALLOC | XFS_BMAPI_CONVERT)) return 0; + ASSERT(whichfork != XFS_COW_FORK); + /* * Modify (by adding) the state flag, if writing. */ @@ -4854,6 +4865,8 @@ xfs_bmap_del_extent( if (whichfork == XFS_ATTR_FORK) state |= BMAP_ATTRFORK; + else if (whichfork == XFS_COW_FORK) + state |= BMAP_COWFORK; ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT((*idx >= 0) && (*idx < ifp->if_bytes / @@ -5192,8 +5205,8 @@ __xfs_bunmapi( trace_xfs_bunmap(ip, bno, len, flags, _RET_IP_); - whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + whichfork = xfs_bmapi_whichfork(flags); + ASSERT(whichfork != XFS_COW_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); if (unlikely( XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index 97828c5..a8ef1c6 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -104,6 +104,9 @@ struct xfs_bmap_free_item */ #define XFS_BMAPI_REMAP 0x100 +/* Map something in the CoW fork. */ +#define XFS_BMAPI_COWFORK 0x200 + #define XFS_BMAPI_FLAGS \ { XFS_BMAPI_ENTIRE, "ENTIRE" }, \ { XFS_BMAPI_METADATA, "METADATA" }, \ @@ -113,12 +116,23 @@ struct xfs_bmap_free_item { XFS_BMAPI_CONTIG, "CONTIG" }, \ { XFS_BMAPI_CONVERT, "CONVERT" }, \ { XFS_BMAPI_ZERO, "ZERO" }, \ - { XFS_BMAPI_REMAP, "REMAP" } + { XFS_BMAPI_REMAP, "REMAP" }, \ + { XFS_BMAPI_COWFORK, "COWFORK" } static inline int xfs_bmapi_aflag(int w) { - return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : 0); + return (w == XFS_ATTR_FORK ? XFS_BMAPI_ATTRFORK : + (w == XFS_COW_FORK ? XFS_BMAPI_COWFORK : 0)); +} + +static inline int xfs_bmapi_whichfork(int bmapi_flags) +{ + if (bmapi_flags & XFS_BMAPI_COWFORK) + return XFS_COW_FORK; + else if (bmapi_flags & XFS_BMAPI_ATTRFORK) + return XFS_ATTR_FORK; + return XFS_DATA_FORK; } /* @@ -139,13 +153,15 @@ static inline int xfs_bmapi_aflag(int w) #define BMAP_LEFT_VALID (1 << 6) #define BMAP_RIGHT_VALID (1 << 7) #define BMAP_ATTRFORK (1 << 8) +#define BMAP_COWFORK (1 << 9) #define XFS_BMAP_EXT_FLAGS \ { BMAP_LEFT_CONTIG, "LC" }, \ { BMAP_RIGHT_CONTIG, "RC" }, \ { BMAP_LEFT_FILLING, "LF" }, \ { BMAP_RIGHT_FILLING, "RF" }, \ - { BMAP_ATTRFORK, "ATTR" } + { BMAP_ATTRFORK, "ATTR" }, \ + { BMAP_COWFORK, "COW" } /* diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 404e321..2145ac0 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -773,6 +773,7 @@ xfs_bmbt_init_cursor( { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_btree_cur *cur; + ASSERT(whichfork != XFS_COW_FORK); cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 83fd4f3..ab708dc 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -202,9 +202,14 @@ xfs_iformat_fork( XFS_ERROR_REPORT("xfs_iformat(7)", XFS_ERRLEVEL_LOW, ip->i_mount); return -EFSCORRUPTED; } - if (error) { + if (error) return error; + + if (xfs_is_reflink_inode(ip)) { + ASSERT(ip->i_cowfp == NULL); + xfs_ifork_init_cow(ip); } + if (!XFS_DFORK_Q(dip)) return 0; @@ -243,6 +248,9 @@ xfs_iformat_fork( if (error) { kmem_zone_free(xfs_ifork_zone, ip->i_afp); ip->i_afp = NULL; + if (ip->i_cowfp) + kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); + ip->i_cowfp = NULL; xfs_idestroy_fork(ip, XFS_DATA_FORK); } return error; @@ -757,6 +765,9 @@ xfs_idestroy_fork( if (whichfork == XFS_ATTR_FORK) { kmem_zone_free(xfs_ifork_zone, ip->i_afp); ip->i_afp = NULL; + } else if (whichfork == XFS_COW_FORK) { + kmem_zone_free(xfs_ifork_zone, ip->i_cowfp); + ip->i_cowfp = NULL; } } @@ -944,6 +955,19 @@ xfs_iext_get_ext( } } +/* XFS_IEXT_STATE_TO_FORK() -- Convert BMAP state flags to an inode fork. */ +xfs_ifork_t * +XFS_IEXT_STATE_TO_FORK( + struct xfs_inode *ip, + int state) +{ + if (state & BMAP_COWFORK) + return ip->i_cowfp; + else if (state & BMAP_ATTRFORK) + return ip->i_afp; + return &ip->i_df; +} + /* * Insert new item(s) into the extent records for incore inode * fork 'ifp'. 'count' new items are inserted at index 'idx'. @@ -956,7 +980,7 @@ xfs_iext_insert( xfs_bmbt_irec_t *new, /* items to insert */ int state) /* type of extent conversion */ { - xfs_ifork_t *ifp = (state & BMAP_ATTRFORK) ? ip->i_afp : &ip->i_df; + xfs_ifork_t *ifp = XFS_IEXT_STATE_TO_FORK(ip, state); xfs_extnum_t i; /* extent record index */ trace_xfs_iext_insert(ip, idx, new, state, _RET_IP_); @@ -1206,7 +1230,7 @@ xfs_iext_remove( int ext_diff, /* number of extents to remove */ int state) /* type of extent conversion */ { - xfs_ifork_t *ifp = (state & BMAP_ATTRFORK) ? ip->i_afp : &ip->i_df; + xfs_ifork_t *ifp = XFS_IEXT_STATE_TO_FORK(ip, state); xfs_extnum_t nextents; /* number of extents in file */ int new_size; /* size of extents after removal */ @@ -1951,3 +1975,20 @@ xfs_iext_irec_update_extoffs( ifp->if_u1.if_ext_irec[i].er_extoff += ext_diff; } } + +/* + * Initialize an inode's copy-on-write fork. + */ +void +xfs_ifork_init_cow( + struct xfs_inode *ip) +{ + if (ip->i_cowfp) + return; + + ip->i_cowfp = kmem_zone_zalloc(xfs_ifork_zone, + KM_SLEEP | KM_NOFS); + ip->i_cowfp->if_flags = XFS_IFEXTENTS; + ip->i_cformat = XFS_DINODE_FMT_EXTENTS; + ip->i_cnextents = 0; +} diff --git a/libxfs/xfs_inode_fork.h b/libxfs/xfs_inode_fork.h index f95e072..44d38eb 100644 --- a/libxfs/xfs_inode_fork.h +++ b/libxfs/xfs_inode_fork.h @@ -92,7 +92,9 @@ typedef struct xfs_ifork { #define XFS_IFORK_PTR(ip,w) \ ((w) == XFS_DATA_FORK ? \ &(ip)->i_df : \ - (ip)->i_afp) + ((w) == XFS_ATTR_FORK ? \ + (ip)->i_afp : \ + (ip)->i_cowfp)) #define XFS_IFORK_DSIZE(ip) \ (XFS_IFORK_Q(ip) ? \ XFS_IFORK_BOFF(ip) : \ @@ -105,26 +107,38 @@ typedef struct xfs_ifork { #define XFS_IFORK_SIZE(ip,w) \ ((w) == XFS_DATA_FORK ? \ XFS_IFORK_DSIZE(ip) : \ - XFS_IFORK_ASIZE(ip)) + ((w) == XFS_ATTR_FORK ? \ + XFS_IFORK_ASIZE(ip) : \ + 0)) #define XFS_IFORK_FORMAT(ip,w) \ ((w) == XFS_DATA_FORK ? \ (ip)->i_d.di_format : \ - (ip)->i_d.di_aformat) + ((w) == XFS_ATTR_FORK ? \ + (ip)->i_d.di_aformat : \ + (ip)->i_cformat)) #define XFS_IFORK_FMT_SET(ip,w,n) \ ((w) == XFS_DATA_FORK ? \ ((ip)->i_d.di_format = (n)) : \ - ((ip)->i_d.di_aformat = (n))) + ((w) == XFS_ATTR_FORK ? \ + ((ip)->i_d.di_aformat = (n)) : \ + ((ip)->i_cformat = (n)))) #define XFS_IFORK_NEXTENTS(ip,w) \ ((w) == XFS_DATA_FORK ? \ (ip)->i_d.di_nextents : \ - (ip)->i_d.di_anextents) + ((w) == XFS_ATTR_FORK ? \ + (ip)->i_d.di_anextents : \ + (ip)->i_cnextents)) #define XFS_IFORK_NEXT_SET(ip,w,n) \ ((w) == XFS_DATA_FORK ? \ ((ip)->i_d.di_nextents = (n)) : \ - ((ip)->i_d.di_anextents = (n))) + ((w) == XFS_ATTR_FORK ? \ + ((ip)->i_d.di_anextents = (n)) : \ + ((ip)->i_cnextents = (n)))) #define XFS_IFORK_MAXEXT(ip, w) \ (XFS_IFORK_SIZE(ip, w) / sizeof(xfs_bmbt_rec_t)) +xfs_ifork_t *XFS_IEXT_STATE_TO_FORK(struct xfs_inode *ip, int state); + int xfs_iformat_fork(struct xfs_inode *, struct xfs_dinode *); void xfs_iflush_fork(struct xfs_inode *, struct xfs_dinode *, struct xfs_inode_log_item *, int); @@ -169,4 +183,6 @@ void xfs_iext_irec_update_extoffs(struct xfs_ifork *, int, int); extern struct kmem_zone *xfs_ifork_zone; +extern void xfs_ifork_init_cow(struct xfs_inode *ip); + #endif /* __XFS_INODE_FORK_H__ */ diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 7637903..6e69208 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -1344,6 +1344,8 @@ __xfs_rmap_add( if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) return 0; + if (ri->ri_whichfork == XFS_COW_FORK) + return 0; trace_xfs_rmap_defer(mp, XFS_FSB_TO_AGNO(mp, ri->ri_bmap.br_startblock), ri->ri_type, diff --git a/libxfs/xfs_types.h b/libxfs/xfs_types.h index 690d616..cf044c0 100644 --- a/libxfs/xfs_types.h +++ b/libxfs/xfs_types.h @@ -93,6 +93,7 @@ typedef __int64_t xfs_sfiloff_t; /* signed block number in a file */ */ #define XFS_DATA_FORK 0 #define XFS_ATTR_FORK 1 +#define XFS_COW_FORK 2 /* * Min numbers of data/attr fork btree root pointers. From darrick.wong@oracle.com Thu Jun 16 20:40:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 81661830C for ; Thu, 16 Jun 2016 20:40:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 403638F804B for ; Thu, 16 Jun 2016 18:40:53 -0700 (PDT) X-ASG-Debug-ID: 1466127650-04cbb01fed6a500001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id vcTAgRql7uEUq41S (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:51 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ek31021149 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:46 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ekgo032091 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:46 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ehCK012432; Fri, 17 Jun 2016 01:40:44 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:43 -0700 Subject: [PATCH 094/145] xfs: support bmapping delalloc extents in the CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 094/145] xfs: support bmapping delalloc extents in the CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:42 -0700 Message-ID: <146612764201.16048.17050341682992352093.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127651 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5471 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Allow the creation of delayed allocation extents in the CoW fork. In a subsequent patch we'll wire up write_begin and page_mkwrite to actually do this. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.c | 29 ++++++++++++++++++----------- libxfs/xfs_bmap.h | 2 +- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 2ec3385..acb3011 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -2752,6 +2752,7 @@ done: STATIC void xfs_bmap_add_extent_hole_delay( xfs_inode_t *ip, /* incore inode pointer */ + int whichfork, xfs_extnum_t *idx, /* extent number to update/insert */ xfs_bmbt_irec_t *new) /* new data to add to file extents */ { @@ -2763,8 +2764,10 @@ xfs_bmap_add_extent_hole_delay( int state; /* state bits, accessed thru macros */ xfs_filblks_t temp=0; /* temp for indirect calculations */ - ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + ifp = XFS_IFORK_PTR(ip, whichfork); state = 0; + if (whichfork == XFS_COW_FORK) + state |= BMAP_COWFORK; ASSERT(isnullstartblock(new->br_startblock)); /* @@ -2782,7 +2785,7 @@ xfs_bmap_add_extent_hole_delay( * Check and set flags if the current (right) segment exists. * If it doesn't exist, we're converting the hole at end-of-file. */ - if (*idx < ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { + if (*idx < ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t)) { state |= BMAP_RIGHT_VALID; xfs_bmbt_get_all(xfs_iext_get_ext(ifp, *idx), &right); @@ -4132,6 +4135,7 @@ xfs_bmapi_read( STATIC int xfs_bmapi_reserve_delalloc( struct xfs_inode *ip, + int whichfork, xfs_fileoff_t aoff, xfs_filblks_t len, struct xfs_bmbt_irec *got, @@ -4140,7 +4144,7 @@ xfs_bmapi_reserve_delalloc( int eof) { struct xfs_mount *mp = ip->i_mount; - struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); xfs_extlen_t alen; xfs_extlen_t indlen; char rt = XFS_IS_REALTIME_INODE(ip); @@ -4199,7 +4203,7 @@ xfs_bmapi_reserve_delalloc( got->br_startblock = nullstartblock(indlen); got->br_blockcount = alen; got->br_state = XFS_EXT_NORM; - xfs_bmap_add_extent_hole_delay(ip, lastx, got); + xfs_bmap_add_extent_hole_delay(ip, whichfork, lastx, got); /* * Update our extent pointer, given that xfs_bmap_add_extent_hole_delay @@ -4231,6 +4235,7 @@ out_unreserve_quota: int xfs_bmapi_delay( struct xfs_inode *ip, /* incore inode */ + int whichfork, /* data or cow fork? */ xfs_fileoff_t bno, /* starting file offs. mapped */ xfs_filblks_t len, /* length to map in file */ struct xfs_bmbt_irec *mval, /* output: map values */ @@ -4238,7 +4243,7 @@ xfs_bmapi_delay( int flags) /* XFS_BMAPI_... */ { struct xfs_mount *mp = ip->i_mount; - struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK); + struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); struct xfs_bmbt_irec got; /* current file extent record */ struct xfs_bmbt_irec prev; /* previous file extent record */ xfs_fileoff_t obno; /* old block number (offset) */ @@ -4248,14 +4253,15 @@ xfs_bmapi_delay( int n = 0; /* current extent index */ int error = 0; + ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_COW_FORK); ASSERT(*nmap >= 1); ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); ASSERT(!(flags & ~XFS_BMAPI_ENTIRE)); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); if (unlikely(XFS_TEST_ERROR( - (XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_EXTENTS && - XFS_IFORK_FORMAT(ip, XFS_DATA_FORK) != XFS_DINODE_FMT_BTREE), + (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS && + XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE), mp, XFS_ERRTAG_BMAPIFORMAT, XFS_RANDOM_BMAPIFORMAT))) { XFS_ERROR_REPORT("xfs_bmapi_delay", XFS_ERRLEVEL_LOW, mp); return -EFSCORRUPTED; @@ -4266,19 +4272,20 @@ xfs_bmapi_delay( XFS_STATS_INC(mp, xs_blk_mapw); - if (!(ifp->if_flags & XFS_IFEXTENTS)) { - error = xfs_iread_extents(NULL, ip, XFS_DATA_FORK); + if (whichfork == XFS_DATA_FORK && !(ifp->if_flags & XFS_IFEXTENTS)) { + error = xfs_iread_extents(NULL, ip, whichfork); if (error) return error; } - xfs_bmap_search_extents(ip, bno, XFS_DATA_FORK, &eof, &lastx, &got, &prev); + xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, &prev); end = bno + len; obno = bno; while (bno < end && n < *nmap) { if (eof || got.br_startoff > bno) { - error = xfs_bmapi_reserve_delalloc(ip, bno, len, &got, + error = xfs_bmapi_reserve_delalloc(ip, whichfork, + bno, len, &got, &prev, &lastx, eof); if (error) { if (n == 0) { diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index a8ef1c6..d90f88e 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -205,7 +205,7 @@ int xfs_bmap_read_extents(struct xfs_trans *tp, struct xfs_inode *ip, int xfs_bmapi_read(struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, struct xfs_bmbt_irec *mval, int *nmap, int flags); -int xfs_bmapi_delay(struct xfs_inode *ip, xfs_fileoff_t bno, +int xfs_bmapi_delay(struct xfs_inode *ip, int whichfork, xfs_fileoff_t bno, xfs_filblks_t len, struct xfs_bmbt_irec *mval, int *nmap, int flags); int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, From darrick.wong@oracle.com Thu Jun 16 20:40:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8F5AD8314 for ; Thu, 16 Jun 2016 20:40:59 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2689CAC002 for ; Thu, 16 Jun 2016 18:40:59 -0700 (PDT) X-ASG-Debug-ID: 1466127656-04bdf01e15964b0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id oBCQ6Jnsbr0v54eE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:40:57 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1eqRk021184 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:53 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1eq1g032215 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:52 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1enGk012443; Fri, 17 Jun 2016 01:40:51 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:49 -0700 Subject: [PATCH 095/145] xfs: support allocating delayed extents in CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 095/145] xfs: support allocating delayed extents in CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:48 -0700 Message-ID: <146612764817.16048.15047976798476564439.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127657 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7320 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Modify xfs_bmap_add_extent_delay_real() so that we can convert delayed allocation extents in the CoW fork to real allocations, and wire this up all the way back to xfs_iomap_write_allocate(). In a subsequent patch, we'll modify the writepage handler to call this. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.c | 51 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index acb3011..18dcd5f 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -133,7 +133,8 @@ xfs_bmbt_lookup_ge( */ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork) { - return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && + return whichfork != XFS_COW_FORK && + XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS && XFS_IFORK_NEXTENTS(ip, whichfork) > XFS_IFORK_MAXEXT(ip, whichfork); } @@ -143,7 +144,8 @@ static inline bool xfs_bmap_needs_btree(struct xfs_inode *ip, int whichfork) */ static inline bool xfs_bmap_wants_extents(struct xfs_inode *ip, int whichfork) { - return XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && + return whichfork != XFS_COW_FORK && + XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE && XFS_IFORK_NEXTENTS(ip, whichfork) <= XFS_IFORK_MAXEXT(ip, whichfork); } @@ -633,6 +635,7 @@ xfs_bmap_btree_to_extents( mp = ip->i_mount; ifp = XFS_IFORK_PTR(ip, whichfork); + ASSERT(whichfork != XFS_COW_FORK); ASSERT(ifp->if_flags & XFS_IFEXTENTS); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE); rblock = ifp->if_broot; @@ -699,6 +702,7 @@ xfs_bmap_extents_to_btree( xfs_bmbt_ptr_t *pp; /* root block address pointer */ mp = ip->i_mount; + ASSERT(whichfork != XFS_COW_FORK); ifp = XFS_IFORK_PTR(ip, whichfork); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_EXTENTS); @@ -830,6 +834,7 @@ xfs_bmap_local_to_extents_empty( { struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork); + ASSERT(whichfork != XFS_COW_FORK); ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_LOCAL); ASSERT(ifp->if_bytes == 0); ASSERT(XFS_IFORK_NEXTENTS(ip, whichfork) == 0); @@ -1663,7 +1668,8 @@ xfs_bmap_one_block( */ STATIC int /* error */ xfs_bmap_add_extent_delay_real( - struct xfs_bmalloca *bma) + struct xfs_bmalloca *bma, + int whichfork) { struct xfs_bmbt_irec *new = &bma->got; int diff; /* temp value */ @@ -1682,10 +1688,13 @@ xfs_bmap_add_extent_delay_real( xfs_filblks_t temp2=0;/* value for da_new calculations */ int tmp_rval; /* partial logging flags */ struct xfs_mount *mp; - int whichfork = XFS_DATA_FORK; + xfs_extnum_t *nextents; mp = bma->ip->i_mount; ifp = XFS_IFORK_PTR(bma->ip, whichfork); + ASSERT(whichfork != XFS_ATTR_FORK); + nextents = (whichfork == XFS_COW_FORK ? &bma->ip->i_cnextents : + &bma->ip->i_d.di_nextents); ASSERT(bma->idx >= 0); ASSERT(bma->idx <= ifp->if_bytes / sizeof(struct xfs_bmbt_rec)); @@ -1699,6 +1708,9 @@ xfs_bmap_add_extent_delay_real( #define RIGHT r[1] #define PREV r[2] + if (whichfork == XFS_COW_FORK) + state |= BMAP_COWFORK; + /* * Set up a bunch of variables to make the tests simpler. */ @@ -1785,7 +1797,7 @@ xfs_bmap_add_extent_delay_real( trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_iext_remove(bma->ip, bma->idx + 1, 2, state); - bma->ip->i_d.di_nextents--; + (*nextents)--; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -1887,7 +1899,7 @@ xfs_bmap_add_extent_delay_real( xfs_bmbt_set_startblock(ep, new->br_startblock); trace_xfs_bmap_post_update(bma->ip, bma->idx, state, _THIS_IP_); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -1957,7 +1969,7 @@ xfs_bmap_add_extent_delay_real( temp = PREV.br_blockcount - new->br_blockcount; xfs_bmbt_set_blockcount(ep, temp); xfs_iext_insert(bma->ip, bma->idx, 1, new, state); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -2041,7 +2053,7 @@ xfs_bmap_add_extent_delay_real( trace_xfs_bmap_pre_update(bma->ip, bma->idx, state, _THIS_IP_); xfs_bmbt_set_blockcount(ep, temp); xfs_iext_insert(bma->ip, bma->idx + 1, 1, new, state); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -2110,7 +2122,7 @@ xfs_bmap_add_extent_delay_real( RIGHT.br_blockcount = temp2; /* insert LEFT (r[0]) and RIGHT (r[1]) at the same time */ xfs_iext_insert(bma->ip, bma->idx + 1, 2, &LEFT, state); - bma->ip->i_d.di_nextents++; + (*nextents)++; if (bma->cur == NULL) rval = XFS_ILOG_CORE | XFS_ILOG_DEXT; else { @@ -2208,7 +2220,8 @@ xfs_bmap_add_extent_delay_real( xfs_bmap_check_leaf_extents(bma->cur, bma->ip, whichfork); done: - bma->logflags |= rval; + if (whichfork != XFS_COW_FORK) + bma->logflags |= rval; return error; #undef LEFT #undef RIGHT @@ -3848,7 +3861,8 @@ xfs_bmap_btalloc( ASSERT(nullfb || fb_agno == args.agno || (ap->dfops->dop_low && fb_agno < args.agno)); ap->length = args.len; - ap->ip->i_d.di_nblocks += args.len; + if (!(ap->flags & XFS_BMAPI_COWFORK)) + ap->ip->i_d.di_nblocks += args.len; xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE); if (ap->wasdel) ap->ip->i_delayed_blks -= args.len; @@ -4322,8 +4336,7 @@ xfs_bmapi_allocate( struct xfs_bmalloca *bma) { struct xfs_mount *mp = bma->ip->i_mount; - int whichfork = (bma->flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + int whichfork = xfs_bmapi_whichfork(bma->flags); struct xfs_ifork *ifp = XFS_IFORK_PTR(bma->ip, whichfork); int tmp_logflags = 0; int error; @@ -4412,7 +4425,7 @@ xfs_bmapi_allocate( bma->got.br_state = XFS_EXT_UNWRITTEN; if (bma->wasdel) - error = xfs_bmap_add_extent_delay_real(bma); + error = xfs_bmap_add_extent_delay_real(bma, whichfork); else error = xfs_bmap_add_extent_hole_real(bma, whichfork); @@ -4566,8 +4579,7 @@ xfs_bmapi_write( orig_mval = mval; orig_nmap = *nmap; #endif - whichfork = (flags & XFS_BMAPI_ATTRFORK) ? - XFS_ATTR_FORK : XFS_DATA_FORK; + whichfork = xfs_bmapi_whichfork(flags); ASSERT(*nmap >= 1); ASSERT(*nmap <= XFS_BMAP_MAX_NMAP); @@ -4578,6 +4590,11 @@ xfs_bmapi_write( ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); if (whichfork == XFS_ATTR_FORK) ASSERT(!(flags & XFS_BMAPI_REMAP)); + if (whichfork == XFS_COW_FORK) { + ASSERT(!(flags & XFS_BMAPI_REMAP)); + ASSERT(!(flags & XFS_BMAPI_PREALLOC)); + ASSERT(!(flags & XFS_BMAPI_CONVERT)); + } if (flags & XFS_BMAPI_REMAP) { ASSERT(!(flags & XFS_BMAPI_PREALLOC)); ASSERT(!(flags & XFS_BMAPI_CONVERT)); @@ -4647,6 +4664,8 @@ xfs_bmapi_write( */ if (flags & XFS_BMAPI_REMAP) ASSERT(inhole); + if (flags & XFS_BMAPI_COWFORK) + ASSERT(!inhole); /* * First, deal with the hole before the allocated space From darrick.wong@oracle.com Thu Jun 16 20:41:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F33A382AF for ; Thu, 16 Jun 2016 20:41:03 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 67BC9AC002 for ; Thu, 16 Jun 2016 18:41:03 -0700 (PDT) X-ASG-Debug-ID: 1466127660-04cb6c542458270001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id p5Y892HVVrmDTF6b (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ewc6008638 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:59 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ewLi008098 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:40:58 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1etRG012457; Fri, 17 Jun 2016 01:40:57 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:40:55 -0700 Subject: [PATCH 096/145] xfs: support removing extents from CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 096/145] xfs: support removing extents from CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:40:54 -0700 Message-ID: <146612765433.16048.7762907945723924511.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127660 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7058 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a helper method to remove extents from the CoW fork without any of the side effects (rmapbt/bmbt updates) of the regular extent deletion routine. We'll eventually use this to clear out the CoW fork during ioend processing. v2: Use bmapi_read to iterate and trim the CoW extents instead of reading them raw via the iext code. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.c | 176 +++++++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_bmap.h | 1 2 files changed, 177 insertions(+) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 18dcd5f..3e4a3e7 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -4973,6 +4973,7 @@ xfs_bmap_del_extent( /* * Matches the whole extent. Delete the entry. */ + trace_xfs_bmap_pre_update(ip, *idx, state, _THIS_IP_); xfs_iext_remove(ip, *idx, 1, whichfork == XFS_ATTR_FORK ? BMAP_ATTRFORK : 0); --*idx; @@ -5190,6 +5191,181 @@ done: } /* + * xfs_bunmapi_cow() -- Remove the relevant parts of the CoW fork. + * See xfs_bmap_del_extent. + * @ip: XFS inode. + * @idx: Extent number to delete. + * @del: Extent to remove. + */ +int +xfs_bunmapi_cow( + xfs_inode_t *ip, + xfs_bmbt_irec_t *del) +{ + xfs_filblks_t da_new; /* new delay-alloc indirect blocks */ + xfs_filblks_t da_old; /* old delay-alloc indirect blocks */ + xfs_fsblock_t del_endblock = 0;/* first block past del */ + xfs_fileoff_t del_endoff; /* first offset past del */ + int delay; /* current block is delayed allocated */ + xfs_bmbt_rec_host_t *ep; /* current extent entry pointer */ + int error; /* error return value */ + xfs_bmbt_irec_t got; /* current extent entry */ + xfs_fileoff_t got_endoff; /* first offset past got */ + xfs_ifork_t *ifp; /* inode fork pointer */ + xfs_mount_t *mp; /* mount structure */ + xfs_filblks_t nblks; /* quota/sb block count */ + xfs_bmbt_irec_t new; /* new record to be inserted */ + /* REFERENCED */ + uint qfield; /* quota field to update */ + xfs_filblks_t temp; /* for indirect length calculations */ + xfs_filblks_t temp2; /* for indirect length calculations */ + int state = BMAP_COWFORK; + int eof; + xfs_extnum_t eidx; + + mp = ip->i_mount; + XFS_STATS_INC(mp, xs_del_exlist); + + ep = xfs_bmap_search_extents(ip, del->br_startoff, XFS_COW_FORK, &eof, + &eidx, &got, &new); + + ifp = XFS_IFORK_PTR(ip, XFS_COW_FORK); + ASSERT((eidx >= 0) && (eidx < ifp->if_bytes / + (uint)sizeof(xfs_bmbt_rec_t))); + ASSERT(del->br_blockcount > 0); + ASSERT(got.br_startoff <= del->br_startoff); + del_endoff = del->br_startoff + del->br_blockcount; + got_endoff = got.br_startoff + got.br_blockcount; + ASSERT(got_endoff >= del_endoff); + delay = isnullstartblock(got.br_startblock); + ASSERT(isnullstartblock(del->br_startblock) == delay); + qfield = 0; + error = 0; + /* + * If deleting a real allocation, must free up the disk space. + */ + if (!delay) { + nblks = del->br_blockcount; + qfield = XFS_TRANS_DQ_BCOUNT; + /* + * Set up del_endblock and cur for later. + */ + del_endblock = del->br_startblock + del->br_blockcount; + da_old = da_new = 0; + } else { + da_old = startblockval(got.br_startblock); + da_new = 0; + nblks = 0; + } + qfield = qfield; + nblks = nblks; + + /* + * Set flag value to use in switch statement. + * Left-contig is 2, right-contig is 1. + */ + switch (((got.br_startoff == del->br_startoff) << 1) | + (got_endoff == del_endoff)) { + case 3: + /* + * Matches the whole extent. Delete the entry. + */ + xfs_iext_remove(ip, eidx, 1, BMAP_COWFORK); + --eidx; + break; + + case 2: + /* + * Deleting the first part of the extent. + */ + trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_); + xfs_bmbt_set_startoff(ep, del_endoff); + temp = got.br_blockcount - del->br_blockcount; + xfs_bmbt_set_blockcount(ep, temp); + if (delay) { + temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), + da_old); + xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + da_new = temp; + break; + } + xfs_bmbt_set_startblock(ep, del_endblock); + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + break; + + case 1: + /* + * Deleting the last part of the extent. + */ + temp = got.br_blockcount - del->br_blockcount; + trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_); + xfs_bmbt_set_blockcount(ep, temp); + if (delay) { + temp = XFS_FILBLKS_MIN(xfs_bmap_worst_indlen(ip, temp), + da_old); + xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + da_new = temp; + break; + } + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + break; + + case 0: + /* + * Deleting the middle of the extent. + */ + temp = del->br_startoff - got.br_startoff; + trace_xfs_bmap_pre_update(ip, eidx, state, _THIS_IP_); + xfs_bmbt_set_blockcount(ep, temp); + new.br_startoff = del_endoff; + temp2 = got_endoff - del_endoff; + new.br_blockcount = temp2; + new.br_state = got.br_state; + if (!delay) { + new.br_startblock = del_endblock; + } else { + temp = xfs_bmap_worst_indlen(ip, temp); + xfs_bmbt_set_startblock(ep, nullstartblock((int)temp)); + temp2 = xfs_bmap_worst_indlen(ip, temp2); + new.br_startblock = nullstartblock((int)temp2); + da_new = temp + temp2; + while (da_new > da_old) { + if (temp) { + temp--; + da_new--; + xfs_bmbt_set_startblock(ep, + nullstartblock((int)temp)); + } + if (da_new == da_old) + break; + if (temp2) { + temp2--; + da_new--; + new.br_startblock = + nullstartblock((int)temp2); + } + } + } + trace_xfs_bmap_post_update(ip, eidx, state, _THIS_IP_); + xfs_iext_insert(ip, eidx + 1, 1, &new, state); + ++eidx; + break; + } + + /* + * Account for change in delayed indirect blocks. + * Nothing to do for disk quota accounting here. + */ + ASSERT(da_old >= da_new); + if (da_old > da_new) + xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false); + + return error; +} + +/* * Unmap (remove) blocks from a file. * If nexts is nonzero then the number of extents to remove is limited to * that value. If not all extents in the block range can be removed then diff --git a/libxfs/xfs_bmap.h b/libxfs/xfs_bmap.h index d90f88e..1c7ab70 100644 --- a/libxfs/xfs_bmap.h +++ b/libxfs/xfs_bmap.h @@ -221,6 +221,7 @@ int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, xfs_fileoff_t bno, xfs_filblks_t len, int flags, xfs_extnum_t nexts, xfs_fsblock_t *firstblock, struct xfs_defer_ops *dfops, int *done); +int xfs_bunmapi_cow(struct xfs_inode *ip, struct xfs_bmbt_irec *del); int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, xfs_extnum_t num); uint xfs_default_attroffset(struct xfs_inode *ip); From darrick.wong@oracle.com Thu Jun 16 20:41:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 143ED82F1 for ; Thu, 16 Jun 2016 20:41:11 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id D8EB18F804B for ; Thu, 16 Jun 2016 18:41:10 -0700 (PDT) X-ASG-Debug-ID: 1466127667-04cb6c542458280001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 6fWzhXoDCpVKv1hg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1f23G021493 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:41:03 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1f2Ko005722 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:41:02 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1f2ka002203; Fri, 17 Jun 2016 01:41:02 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:01 -0700 Subject: [PATCH 097/145] xfs: store in-progress CoW allocations in the refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 097/145] xfs: store in-progress CoW allocations in the refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:00 -0700 Message-ID: <146612766048.16048.7267003332348435121.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127667 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 16807 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Due to the way the CoW algorithm in XFS works, there's an interval during which blocks allocated to handle a CoW can be lost -- if the FS goes down after the blocks are allocated but before the block remapping takes place. This is exacerbated by the cowextsz hint -- allocated reservations can sit around for a while, waiting to get used. Since the refcount btree doesn't normally store records with refcount of 1, we can use it to record these in-progress extents. In-progress blocks cannot be shared because they're not user-visible, so there shouldn't be any conflicts with other programs. This is a better solution than holding EFIs during writeback because (a) EFIs can't be relogged currently, (b) even if they could, EFIs are bound by available log space, which puts an unnecessary upper bound on how much CoW we can have in flight, and (c) we already have a mechanism to track blocks. At mount time, read the refcount records and free anything we find with a refcount of 1 because those were in-progress when the FS went down. v2: Use the deferred operations system to avoid deadlocks and blowing out the transaction reservation. This allows us to unmap a CoW extent from the refcountbt and into a file atomically. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 4 + libxfs/xfs_bmap.c | 11 ++ libxfs/xfs_format.h | 3 libxfs/xfs_refcount.c | 321 ++++++++++++++++++++++++++++++++++++++++++++++++- libxfs/xfs_refcount.h | 7 + 5 files changed, 340 insertions(+), 6 deletions(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index dfc92a6..7022164 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -261,6 +261,10 @@ #define trace_xfs_bmap_deferred(...) ((void) 0) #define trace_xfs_bmap_defer(...) ((void) 0) +#define trace_xfs_refcount_adjust_cow_error(...) ((void) 0) +#define trace_xfs_refcount_cow_increase(...) ((void) 0) +#define trace_xfs_refcount_cow_decrease(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 3e4a3e7..4b77ed0 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -4697,6 +4697,17 @@ xfs_bmapi_write( goto error0; if (bma.blkno == NULLFSBLOCK) break; + + /* + * If this is a CoW allocation, record the data in + * the refcount btree for orphan recovery. + */ + if (whichfork == XFS_COW_FORK) { + error = xfs_refcount_alloc_cow_extent(mp, dfops, + bma.blkno, bma.length); + if (error) + goto error0; + } } /* Deal with the allocated space we found. */ diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index fdeaf53..820dfde 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -1401,7 +1401,8 @@ xfs_rmap_ino_owner( #define XFS_RMAP_OWN_INOBT (-6ULL) /* Inode btree blocks */ #define XFS_RMAP_OWN_INODES (-7ULL) /* Inode chunk */ #define XFS_RMAP_OWN_REFC (-8ULL) /* refcount tree */ -#define XFS_RMAP_OWN_MIN (-9ULL) /* guard */ +#define XFS_RMAP_OWN_COW (-9ULL) /* cow allocations */ +#define XFS_RMAP_OWN_MIN (-10ULL) /* guard */ #define XFS_RMAP_NON_INODE_OWNER(owner) (!!((owner) & (1ULL << 63))) diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index d2b614b..e03a9b7 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -35,13 +35,23 @@ #include "xfs_trans.h" #include "xfs_bit.h" #include "xfs_refcount.h" +#include "xfs_rmap_btree.h" /* Allowable refcount adjustment amounts. */ enum xfs_refc_adjust_op { XFS_REFCOUNT_ADJUST_INCREASE = 1, XFS_REFCOUNT_ADJUST_DECREASE = -1, + XFS_REFCOUNT_ADJUST_COW_ALLOC = 0, + XFS_REFCOUNT_ADJUST_COW_FREE = -1, }; +STATIC int __xfs_refcount_cow_alloc(struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, xfs_extlen_t aglen, + struct xfs_defer_ops *dfops); +STATIC int __xfs_refcount_cow_free(struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, xfs_extlen_t aglen, + struct xfs_defer_ops *dfops); + /* * Look up the first record less than or equal to [bno, len] in the btree * given by cur. @@ -467,6 +477,8 @@ out_error: return error; } +#define XFS_FIND_RCEXT_SHARED 1 +#define XFS_FIND_RCEXT_COW 2 /* * Find the left extent and the one after it (cleft). This function assumes * that we've already split any extent crossing agbno. @@ -477,7 +489,8 @@ xfs_refcount_find_left_extents( struct xfs_refcount_irec *left, struct xfs_refcount_irec *cleft, xfs_agblock_t agbno, - xfs_extlen_t aglen) + xfs_extlen_t aglen, + int flags) { struct xfs_refcount_irec tmp; int error; @@ -497,6 +510,10 @@ xfs_refcount_find_left_extents( if (RCNEXT(tmp) != agbno) return 0; + if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2) + return 0; + if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1) + return 0; /* We have a left extent; retrieve (or invent) the next right one */ *left = tmp; @@ -553,7 +570,8 @@ xfs_refcount_find_right_extents( struct xfs_refcount_irec *right, struct xfs_refcount_irec *cright, xfs_agblock_t agbno, - xfs_extlen_t aglen) + xfs_extlen_t aglen, + int flags) { struct xfs_refcount_irec tmp; int error; @@ -573,6 +591,10 @@ xfs_refcount_find_right_extents( if (tmp.rc_startblock != agbno + aglen) return 0; + if ((flags & XFS_FIND_RCEXT_SHARED) && tmp.rc_refcount < 2) + return 0; + if ((flags & XFS_FIND_RCEXT_COW) && tmp.rc_refcount > 1) + return 0; /* We have a right extent; retrieve (or invent) the next left one */ *right = tmp; @@ -629,6 +651,7 @@ xfs_refcount_merge_extents( xfs_agblock_t *agbno, xfs_extlen_t *aglen, enum xfs_refc_adjust_op adjust, + int flags, bool *shape_changed) { struct xfs_refcount_irec left = {0}, cleft = {0}; @@ -644,11 +667,11 @@ xfs_refcount_merge_extents( * [right]. */ error = xfs_refcount_find_left_extents(cur, &left, &cleft, *agbno, - *aglen); + *aglen, flags); if (error) return error; error = xfs_refcount_find_right_extents(cur, &right, &cright, *agbno, - *aglen); + *aglen, flags); if (error) return error; @@ -935,7 +958,7 @@ xfs_refcount_adjust( */ orig_aglen = aglen; error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj, - &shape_changed); + XFS_FIND_RCEXT_SHARED, &shape_changed); if (error) goto out_error; if (shape_changed) @@ -1052,6 +1075,18 @@ xfs_refcount_finish_one( error = xfs_refcount_adjust(rcur, bno, blockcount, adjusted, XFS_REFCOUNT_ADJUST_DECREASE, dfops, NULL); break; + case XFS_REFCOUNT_ALLOC_COW: + *adjusted = 0; + error = __xfs_refcount_cow_alloc(rcur, bno, blockcount, dfops); + if (!error) + *adjusted = blockcount; + break; + case XFS_REFCOUNT_FREE_COW: + *adjusted = 0; + error = __xfs_refcount_cow_free(rcur, bno, blockcount, dfops); + if (!error) + *adjusted = blockcount; + break; default: ASSERT(0); error = -EFSCORRUPTED; @@ -1237,3 +1272,279 @@ out: trace_xfs_refcount_find_shared_error(mp, agno, error, _RET_IP_); return error; } + +/* + * Recovering CoW Blocks After a Crash + * + * Due to the way that the copy on write mechanism works, there's a window of + * opportunity in which we can lose track of allocated blocks during a crash. + * Because CoW uses delayed allocation in the in-core CoW fork, writeback + * causes blocks to be allocated and stored in the CoW fork. The blocks are + * no longer in the free space btree but are not otherwise recorded anywhere + * until the write completes and the blocks are mapped into the file. A crash + * in between allocation and remapping results in the replacement blocks being + * lost. This situation is exacerbated by the CoW extent size hint because + * allocations can hang around for long time. + * + * However, there is a place where we can record these allocations before they + * become mappings -- the reference count btree. The btree does not record + * extents with refcount == 1, so we can record allocations with a refcount of + * 1. Blocks being used for CoW writeout cannot be shared, so there should be + * no conflict with shared block records. These mappings should be created + * when we allocate blocks to the CoW fork and deleted when they're removed + * from the CoW fork. + * + * Minor nit: records for in-progress CoW allocations and records for shared + * extents must never be merged, to preserve the property that (except for CoW + * allocations) there are no refcount btree entries with refcount == 1. The + * only time this could potentially happen is when unsharing a block that's + * adjacent to CoW allocations, so we must be careful to avoid this. + * + * At mount time we recover lost CoW allocations by searching the refcount + * btree for these refcount == 1 mappings. These represent CoW allocations + * that were in progress at the time the filesystem went down, so we can free + * them to get the space back. + * + * This mechanism is superior to creating EFIs for unmapped CoW extents for + * several reasons -- first, EFIs pin the tail of the log and would have to be + * periodically relogged to avoid filling up the log. Second, CoW completions + * will have to file an EFD and create new EFIs for whatever remains in the + * CoW fork; this partially takes care of (1) but extent-size reservations + * will have to periodically relog even if there's no writeout in progress. + * This can happen if the CoW extent size hint is set, which you really want. + * Third, EFIs cannot currently be automatically relogged into newer + * transactions to advance the log tail. Fourth, stuffing the log full of + * EFIs places an upper bound on the number of CoW allocations that can be + * held filesystem-wide at any given time. Recording them in the refcount + * btree doesn't require us to maintain any state in memory and doesn't pin + * the log. + */ +/* + * Adjust the refcounts of CoW allocations. These allocations are "magic" + * in that they're not referenced anywhere else in the filesystem, so we + * stash them in the refcount btree with a refcount of 1 until either file + * remapping (or CoW cancellation) happens. + */ +STATIC int +xfs_refcount_adjust_cow_extents( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops, + struct xfs_owner_info *oinfo) +{ + struct xfs_refcount_irec ext, tmp; + int error; + int found_rec, found_tmp; + + if (aglen == 0) + return 0; + + /* Find any overlapping refcount records */ + error = xfs_refcountbt_lookup_ge(cur, agbno, &found_rec); + if (error) + goto out_error; + error = xfs_refcountbt_get_rec(cur, &ext, &found_rec); + if (error) + goto out_error; + if (!found_rec) { + ext.rc_startblock = cur->bc_mp->m_sb.sb_agblocks; + ext.rc_blockcount = 0; + ext.rc_refcount = 0; + } + + switch (adj) { + case XFS_REFCOUNT_ADJUST_COW_ALLOC: + /* Adding a CoW reservation, there should be nothing here. */ + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_startblock >= agbno + aglen, out_error); + + tmp.rc_startblock = agbno; + tmp.rc_blockcount = aglen; + tmp.rc_refcount = 1; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &tmp); + + error = xfs_refcountbt_insert(cur, &tmp, + &found_tmp); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_tmp == 1, out_error); + break; + case XFS_REFCOUNT_ADJUST_COW_FREE: + /* Removing a CoW reservation, there should be one extent. */ + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_startblock == agbno, out_error); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_blockcount == aglen, out_error); + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + ext.rc_refcount == 1, out_error); + + ext.rc_refcount = 0; + trace_xfs_refcount_modify_extent(cur->bc_mp, + cur->bc_private.a.agno, &ext); + error = xfs_refcountbt_delete(cur, &found_rec); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(cur->bc_mp, + found_rec == 1, out_error); + break; + default: + ASSERT(0); + } + + return error; +out_error: + trace_xfs_refcount_modify_extent_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* + * Add or remove refcount btree entries for CoW reservations. + */ +STATIC int +xfs_refcount_adjust_cow( + struct xfs_btree_cur *cur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + enum xfs_refc_adjust_op adj, + struct xfs_defer_ops *dfops) +{ + bool shape_changed; + int error; + + /* + * Ensure that no rcextents cross the boundary of the adjustment range. + */ + error = xfs_refcount_split_extent(cur, agbno, &shape_changed); + if (error) + goto out_error; + + error = xfs_refcount_split_extent(cur, agbno + aglen, &shape_changed); + if (error) + goto out_error; + + /* + * Try to merge with the left or right extents of the range. + */ + error = xfs_refcount_merge_extents(cur, &agbno, &aglen, adj, + XFS_FIND_RCEXT_COW, &shape_changed); + if (error) + goto out_error; + + /* Now that we've taken care of the ends, adjust the middle extents */ + error = xfs_refcount_adjust_cow_extents(cur, agbno, aglen, adj, + dfops, NULL); + if (error) + goto out_error; + + return 0; + +out_error: + trace_xfs_refcount_adjust_cow_error(cur->bc_mp, cur->bc_private.a.agno, + error, _RET_IP_); + return error; +} + +/* + * Record a CoW allocation in the refcount btree. + */ +STATIC int +__xfs_refcount_cow_alloc( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + struct xfs_defer_ops *dfops) +{ + int error; + + trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_private.a.agno, + agbno, aglen); + + /* Add refcount btree reservation */ + error = xfs_refcount_adjust_cow(rcur, agbno, aglen, + XFS_REFCOUNT_ADJUST_COW_ALLOC, dfops); + if (error) + return error; + + /* Add rmap entry */ + if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { + error = xfs_rmap_alloc_defer(rcur->bc_mp, dfops, + rcur->bc_private.a.agno, + agbno, aglen, XFS_RMAP_OWN_COW); + if (error) + return error; + } + + return error; +} + +/* + * Remove a CoW allocation from the refcount btree. + */ +STATIC int +__xfs_refcount_cow_free( + struct xfs_btree_cur *rcur, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + struct xfs_defer_ops *dfops) +{ + int error; + + trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_private.a.agno, + agbno, aglen); + + /* Remove refcount btree reservation */ + error = xfs_refcount_adjust_cow(rcur, agbno, aglen, + XFS_REFCOUNT_ADJUST_COW_FREE, dfops); + if (error) + return error; + + /* Remove rmap entry */ + if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { + error = xfs_rmap_free_defer(rcur->bc_mp, dfops, + rcur->bc_private.a.agno, + agbno, aglen, XFS_RMAP_OWN_COW); + if (error) + return error; + } + + return error; +} + +/* Record a CoW staging extent in the refcount btree. */ +int +xfs_refcount_alloc_cow_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_fsblock_t fsb, + xfs_extlen_t len) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_ALLOC_COW; + ri.ri_startblock = fsb; + ri.ri_blockcount = len; + + return __xfs_refcount_add(mp, dfops, &ri); +} + +/* Forget a CoW staging event in the refcount btree. */ +int +xfs_refcount_free_cow_extent( + struct xfs_mount *mp, + struct xfs_defer_ops *dfops, + xfs_fsblock_t fsb, + xfs_extlen_t len) +{ + struct xfs_refcount_intent ri; + + ri.ri_type = XFS_REFCOUNT_FREE_COW; + ri.ri_startblock = fsb; + ri.ri_blockcount = len; + + return __xfs_refcount_add(mp, dfops, &ri); +} diff --git a/libxfs/xfs_refcount.h b/libxfs/xfs_refcount.h index b7b83b8..6665eeb 100644 --- a/libxfs/xfs_refcount.h +++ b/libxfs/xfs_refcount.h @@ -57,4 +57,11 @@ extern int xfs_refcount_find_shared(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_maximal); +extern int xfs_refcount_alloc_cow_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, + xfs_extlen_t len); +extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp, + struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, + xfs_extlen_t len); + #endif /* __XFS_REFCOUNT_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:41:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 50CF28328 for ; Thu, 16 Jun 2016 20:41:15 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 07CC88F804B for ; Thu, 16 Jun 2016 18:41:14 -0700 (PDT) X-ASG-Debug-ID: 1466127673-04cbb01fee6a560001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 9N8WSnQhJGIKAbPe (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:13 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fB1L009004 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:12 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fBSB032704 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:11 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1f8RZ029936; Fri, 17 Jun 2016 01:41:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:08 -0700 Subject: [PATCH 098/145] xfs: teach get_bmapx and fiemap about shared extents and the CoW fork From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 098/145] xfs: teach get_bmapx and fiemap about shared extents and the CoW fork To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:06 -0700 Message-ID: <146612766672.16048.349656239666586877.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127673 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1375 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach xfs_getbmapx how to report shared extents and CoW fork contents, then modify the FIEMAP formatters to set the appropriate flags. A previous version of this patch only modified the fiemap formatter, which is insufficient. Signed-off-by: Darrick J. Wong --- libxfs/xfs_fs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index f291a53..bb70066 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -105,14 +105,16 @@ struct getbmapx { #define BMV_IF_PREALLOC 0x4 /* rtn status BMV_OF_PREALLOC if req */ #define BMV_IF_DELALLOC 0x8 /* rtn status BMV_OF_DELALLOC if req */ #define BMV_IF_NO_HOLES 0x10 /* Do not return holes */ +#define BMV_IF_COWFORK 0x20 /* return CoW fork rather than data */ #define BMV_IF_VALID \ (BMV_IF_ATTRFORK|BMV_IF_NO_DMAPI_READ|BMV_IF_PREALLOC| \ - BMV_IF_DELALLOC|BMV_IF_NO_HOLES) + BMV_IF_DELALLOC|BMV_IF_NO_HOLES|BMV_IF_COWFORK) /* bmv_oflags values - returned for each non-header segment */ #define BMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ #define BMV_OF_DELALLOC 0x2 /* segment = delayed allocation */ #define BMV_OF_LAST 0x4 /* segment is the last in the file */ +#define BMV_OF_SHARED 0x8 /* segment shared with another file */ /* * Structure for XFS_IOC_FSSETDM. From darrick.wong@oracle.com Thu Jun 16 20:41:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 30A7C832E for ; Thu, 16 Jun 2016 20:41:21 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id D2FC7304048 for ; Thu, 16 Jun 2016 18:41:20 -0700 (PDT) X-ASG-Debug-ID: 1466127678-04bdf01e17964e0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id GBPUS7JF3wCG4CBV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:19 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fH3j009089 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:17 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fGns008449 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:17 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fE4f012630; Fri, 17 Jun 2016 01:41:15 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:14 -0700 Subject: [PATCH 099/145] xfs: support FS_XFLAG_REFLINK on reflink filesystems From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 099/145] xfs: support FS_XFLAG_REFLINK on reflink filesystems To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:12 -0700 Message-ID: <146612767278.16048.8454443224198853352.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127679 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3149 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add support for reporting the "reflink" inode flag in the XFS-specific getxflags ioctl, and allow the user to clear the flag if file size is zero. v2: Move the reflink flag out of the way of the DAX flag, and add the new cowextsize flag. v3: do not report (or allow changes to) FL_NOCOW_FL, since we don't support a flag to prevent CoWing and the reflink flag is a poor proxy. We'll try to design away the need for the NOCOW flag. Signed-off-by: Darrick J. Wong --- include/darwin.h | 2 ++ include/freebsd.h | 2 ++ include/irix.h | 2 ++ include/linux.h | 2 ++ 4 files changed, 8 insertions(+) diff --git a/include/darwin.h b/include/darwin.h index 2935b4c..abb2a22 100644 --- a/include/darwin.h +++ b/include/darwin.h @@ -314,6 +314,8 @@ struct fsxattr { #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ +#define FS_XFLAG_REFLINK 0x00010000 /* file is reflinked */ +#define FS_XFLAG_COWEXTSIZE 0x00020000 /* CoW extent size allocator hint */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) diff --git a/include/freebsd.h b/include/freebsd.h index 3feca07..fc58a74 100644 --- a/include/freebsd.h +++ b/include/freebsd.h @@ -204,6 +204,8 @@ struct fsxattr { #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ +#define FS_XFLAG_REFLINK 0x00010000 /* file is reflinked */ +#define FS_XFLAG_COWEXTSIZE 0x00020000 /* CoW extent size allocator hint */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) diff --git a/include/irix.h b/include/irix.h index 45c8594..c4d25b5 100644 --- a/include/irix.h +++ b/include/irix.h @@ -449,6 +449,8 @@ struct fsxattr { #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ +#define FS_XFLAG_REFLINK 0x00010000 /* file is reflinked */ +#define FS_XFLAG_COWEXTSIZE 0x00020000 /* CoW extent size allocator hint */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR F_FSGETXATTR diff --git a/include/linux.h b/include/linux.h index cd4b3eb..d47a29c 100644 --- a/include/linux.h +++ b/include/linux.h @@ -207,6 +207,8 @@ struct fsxattr { #define FS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ #define FS_XFLAG_FILESTREAM 0x00004000 /* use filestream allocator */ #define FS_XFLAG_DAX 0x00008000 /* use DAX for IO */ +#define FS_XFLAG_REFLINK 0x00010000 /* file is reflinked */ +#define FS_XFLAG_COWEXTSIZE 0x00020000 /* CoW extent size allocator hint */ #define FS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ #define FS_IOC_FSGETXATTR _IOR ('X', 31, struct fsxattr) From darrick.wong@oracle.com Thu Jun 16 20:41:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E1B2A82D0 for ; Thu, 16 Jun 2016 20:41:27 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id A3060304039 for ; Thu, 16 Jun 2016 18:41:27 -0700 (PDT) X-ASG-Debug-ID: 1466127685-04cbb01fef6a580001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id nhBXkpFaD4NJw9rn (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fKJd021735 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:21 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fKKE008550 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:20 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1fKLh002388; Fri, 17 Jun 2016 01:41:20 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:20 -0700 Subject: [PATCH 100/145] xfs: create a separate cow extent size hint for the allocator From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 100/145] xfs: create a separate cow extent size hint for the allocator To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:18 -0700 Message-ID: <146612767885.16048.6454121864397119567.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127685 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8218 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a per-inode extent size allocator hint for copy-on-write. This hint is separate from the existing extent size hint so that CoW can take advantage of the fragmentation-reducing properties of extent size hints without disabling delalloc for regular writes. The extent size hint that's fed to the allocator during a copy on write operation is the greater of the cowextsize and regular extsize hint. During reflink, if we're sharing the entire source file to the entire destination file and the destination file doesn't already have a cowextsize hint, propagate the source file's cowextsize hint to the destination file. Signed-off-by: Darrick J. Wong --- include/darwin.h | 3 ++- include/freebsd.h | 3 ++- include/irix.h | 3 ++- include/linux.h | 3 ++- libxfs/libxfs_priv.h | 1 + libxfs/xfs_bmap.c | 13 +++++++++++-- libxfs/xfs_format.h | 3 ++- libxfs/xfs_fs.h | 3 ++- libxfs/xfs_inode_buf.c | 4 +++- libxfs/xfs_inode_buf.h | 1 + libxfs/xfs_log_format.h | 3 ++- 11 files changed, 30 insertions(+), 10 deletions(-) diff --git a/include/darwin.h b/include/darwin.h index abb2a22..2cbd058 100644 --- a/include/darwin.h +++ b/include/darwin.h @@ -293,7 +293,8 @@ struct fsxattr { __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ - unsigned char fsx_pad[12]; + __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ + unsigned char fsx_pad[8]; }; /* diff --git a/include/freebsd.h b/include/freebsd.h index fc58a74..1d84b14 100644 --- a/include/freebsd.h +++ b/include/freebsd.h @@ -183,7 +183,8 @@ struct fsxattr { __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ - unsigned char fsx_pad[12]; + __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ + unsigned char fsx_pad[8]; }; /* diff --git a/include/irix.h b/include/irix.h index c4d25b5..0cf796a 100644 --- a/include/irix.h +++ b/include/irix.h @@ -428,7 +428,8 @@ struct fsxattr { __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ - unsigned char fsx_pad[12]; + __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ + unsigned char fsx_pad[8]; }; /* diff --git a/include/linux.h b/include/linux.h index d47a29c..2aeecd0 100644 --- a/include/linux.h +++ b/include/linux.h @@ -186,7 +186,8 @@ struct fsxattr { __u32 fsx_extsize; /* extsize field value (get/set)*/ __u32 fsx_nextents; /* nextents field value (get) */ __u32 fsx_projid; /* project identifier (get/set) */ - unsigned char fsx_pad[12]; + __u32 fsx_cowextsize; /* cow extsize field value (get/set) */ + unsigned char fsx_pad[8]; }; /* diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index ba16544..41f6b96 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -426,6 +426,7 @@ do { \ #define xfs_rotorstep 1 #define xfs_bmap_rtalloc(a) (-ENOSYS) #define xfs_get_extsz_hint(ip) (0) +#define xfs_get_cowextsz_hint(ip) (0) #define xfs_inode_is_filestream(ip) (0) #define xfs_filestream_lookup_ag(ip) (0) #define xfs_filestream_new_ag(ip,ag) (0) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index 4b77ed0..e81ade5 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -3657,7 +3657,13 @@ xfs_bmap_btalloc( else if (mp->m_dalign) stripe_align = mp->m_dalign; - align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0; + if (ap->userdata) { + if (ap->flags & XFS_BMAPI_COWFORK) + align = xfs_get_cowextsz_hint(ap->ip); + else + align = xfs_get_extsz_hint(ap->ip); + } else + align = 0; if (unlikely(align)) { error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev, align, 0, ap->eof, 0, ap->conv, @@ -4170,7 +4176,10 @@ xfs_bmapi_reserve_delalloc( alen = XFS_FILBLKS_MIN(alen, got->br_startoff - aoff); /* Figure out the extent size, adjust alen */ - extsz = xfs_get_extsz_hint(ip); + if (whichfork == XFS_COW_FORK) + extsz = xfs_get_cowextsz_hint(ip); + else + extsz = xfs_get_extsz_hint(ip); if (extsz) { error = xfs_bmap_extsize_align(mp, got, prev, extsz, rt, eof, 1, 0, &aoff, &alen); diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 820dfde..de29220 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -890,7 +890,8 @@ typedef struct xfs_dinode { __be64 di_changecount; /* number of attribute changes */ __be64 di_lsn; /* flush sequence */ __be64 di_flags2; /* more random flags */ - __u8 di_pad2[16]; /* more padding for future expansion */ + __be32 di_cowextsize; /* basic cow extent size for file */ + __u8 di_pad2[12]; /* more padding for future expansion */ /* fields only written to during inode creation */ xfs_timestamp_t di_crtime; /* time created */ diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index bb70066..df58c1c 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -302,7 +302,8 @@ typedef struct xfs_bstat { #define bs_projid bs_projid_lo /* (previously just bs_projid) */ __u16 bs_forkoff; /* inode fork offset in bytes */ __u16 bs_projid_hi; /* higher part of project id */ - unsigned char bs_pad[10]; /* pad space, unused */ + unsigned char bs_pad[6]; /* pad space, unused */ + __u32 bs_cowextsize; /* cow extent size */ __u32 bs_dmevmask; /* DMIG event mask */ __u16 bs_dmstate; /* DMIG state info */ __u16 bs_aextents; /* attribute number of extents */ diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index 572c101..8a804e2 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -265,6 +265,7 @@ xfs_inode_from_disk( to->di_crtime.t_sec = be32_to_cpu(from->di_crtime.t_sec); to->di_crtime.t_nsec = be32_to_cpu(from->di_crtime.t_nsec); to->di_flags2 = be64_to_cpu(from->di_flags2); + to->di_cowextsize = be32_to_cpu(from->di_cowextsize); } } @@ -314,7 +315,7 @@ xfs_inode_to_disk( to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); to->di_flags2 = cpu_to_be64(from->di_flags2); - + to->di_cowextsize = cpu_to_be32(from->di_cowextsize); to->di_ino = cpu_to_be64(ip->i_ino); to->di_lsn = cpu_to_be64(lsn); memset(to->di_pad2, 0, sizeof(to->di_pad2)); @@ -366,6 +367,7 @@ xfs_log_dinode_to_disk( to->di_crtime.t_sec = cpu_to_be32(from->di_crtime.t_sec); to->di_crtime.t_nsec = cpu_to_be32(from->di_crtime.t_nsec); to->di_flags2 = cpu_to_be64(from->di_flags2); + to->di_cowextsize = cpu_to_be32(from->di_cowextsize); to->di_ino = cpu_to_be64(from->di_ino); to->di_lsn = cpu_to_be64(from->di_lsn); memcpy(to->di_pad2, from->di_pad2, sizeof(to->di_pad2)); diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h index 958c543..6848a0a 100644 --- a/libxfs/xfs_inode_buf.h +++ b/libxfs/xfs_inode_buf.h @@ -47,6 +47,7 @@ struct xfs_icdinode { __uint16_t di_flags; /* random flags, XFS_DIFLAG_... */ __uint64_t di_flags2; /* more random flags */ + __uint32_t di_cowextsize; /* basic cow extent size for file */ xfs_ictimestamp_t di_crtime; /* time created */ }; diff --git a/libxfs/xfs_log_format.h b/libxfs/xfs_log_format.h index 320a305..9cab67f 100644 --- a/libxfs/xfs_log_format.h +++ b/libxfs/xfs_log_format.h @@ -423,7 +423,8 @@ struct xfs_log_dinode { __uint64_t di_changecount; /* number of attribute changes */ xfs_lsn_t di_lsn; /* flush sequence */ __uint64_t di_flags2; /* more random flags */ - __uint8_t di_pad2[16]; /* more padding for future expansion */ + __uint32_t di_cowextsize; /* basic cow extent size for file */ + __uint8_t di_pad2[12]; /* more padding for future expansion */ /* fields only written to during inode creation */ xfs_ictimestamp_t di_crtime; /* time created */ From darrick.wong@oracle.com Thu Jun 16 20:41:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B34E1833C for ; Thu, 16 Jun 2016 20:41:36 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 72D278F804C for ; Thu, 16 Jun 2016 18:41:36 -0700 (PDT) X-ASG-Debug-ID: 1466127693-04bdf01e1396500001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Bx1EJyflbXLEfFKr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:34 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fRAM021771 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:41:27 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1fRpg006222 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:41:27 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1fQYi002405; Fri, 17 Jun 2016 01:41:26 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:26 -0700 Subject: [PATCH 101/145] xfs: preallocate blocks for worst-case btree expansion From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 101/145] xfs: preallocate blocks for worst-case btree expansion To: david@fromorbit.com, darrick.wong@oracle.com Cc: Christoph Hellwig , xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:25 -0700 Message-ID: <146612768501.16048.10887544125329436696.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127694 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9986 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines To gracefully handle the situation where a CoW operation turns a single refcount extent into a lot of tiny ones and then run out of space when a tree split has to happen, use the per-AG reserved block pool to pre-allocate all the space we'll ever need for a maximal btree. For a 4K block size, this only costs an overhead of 0.3% of available disk space. When reflink is enabled, we have an unfortunate problem with rmap -- since we can share a block billions of times, this means that the reverse mapping btree can expand basically infinitely. When an AG is so full that there are no free blocks with which to expand the rmapbt, the filesystem will shut down hard. This is rather annoying to the user, so use the AG reservation code to reserve a "reasonable" amount of space for rmap. We'll prevent reflinks and CoW operations if we think we're getting close to exhausting an AG's free space rather than shutting down, but this permanent reservation should be enough for "most" users. Hopefully. v2: Simplify the return value from xfs_perag_pool_free_block to a bool so that we can easily call xfs_trans_binval for both the per-AG pool and the real freeing case. Without this we fail to invalidate the btree buffer and will trip over the write verifier on a shrinking refcount btree. v3: Convert to the new per-AG reservation code. v4: Combine this patch with the one that adds the rmapbt reservation, since the rmapbt reservation is only needed for reflink filesystems. Signed-off-by: Darrick J. Wong [hch@lst.de: ensure that we invalidate the freed btree buffer] Signed-off-by: Christoph Hellwig --- libxfs/xfs_ag_resv.c | 11 ++++++ libxfs/xfs_alloc.c | 2 - libxfs/xfs_refcount_btree.c | 61 ++++++++++++++++++++++++++++++--- libxfs/xfs_refcount_btree.h | 3 ++ libxfs/xfs_rmap_btree.c | 80 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.h | 7 ++++ 6 files changed, 157 insertions(+), 7 deletions(-) diff --git a/libxfs/xfs_ag_resv.c b/libxfs/xfs_ag_resv.c index 03413e4..dd899d4 100644 --- a/libxfs/xfs_ag_resv.c +++ b/libxfs/xfs_ag_resv.c @@ -37,6 +37,7 @@ #include "xfs_trans_space.h" #include "xfs_rmap_btree.h" #include "xfs_btree.h" +#include "xfs_refcount_btree.h" /* * Per-AG Block Reservations @@ -224,6 +225,11 @@ xfs_ag_resv_init( /* Create the metadata reservation. */ ask = used = 0; + err2 = xfs_refcountbt_calc_reserves(pag->pag_mount, pag->pag_agno, + &ask, &used); + if (err2 && !error) + error = err2; + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_METADATA, ask, used); if (err2 && !error) error = err2; @@ -235,6 +241,11 @@ init_agfl: /* Create the AGFL metadata reservation */ ask = used = 0; + err2 = xfs_rmapbt_calc_reserves(pag->pag_mount, pag->pag_agno, + &ask, &used); + if (err2 && !error) + error = err2; + err2 = __xfs_ag_resv_init(pag, XFS_AG_RESV_AGFL, ask, used); if (err2 && !error) error = err2; diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index ca3e7ce..33087e6 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -135,8 +135,6 @@ xfs_alloc_ag_max_usable(struct xfs_mount *mp) /* rmap root block + full tree split on full AG */ blocks += 1 + (2 * mp->m_ag_maxlevels) - 1; } - if (xfs_sb_version_hasreflink(&mp->m_sb)) - blocks += xfs_refcountbt_max_size(mp); return mp->m_sb.sb_agblocks - blocks; } diff --git a/libxfs/xfs_refcount_btree.c b/libxfs/xfs_refcount_btree.c index 8c1cba9..1b3ba07 100644 --- a/libxfs/xfs_refcount_btree.c +++ b/libxfs/xfs_refcount_btree.c @@ -75,6 +75,8 @@ xfs_refcountbt_alloc_block( struct xfs_alloc_arg args; /* block allocation args */ int error; /* error return value */ + XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); + memset(&args, 0, sizeof(args)); args.tp = cur->bc_tp; args.mp = cur->bc_mp; @@ -84,6 +86,7 @@ xfs_refcountbt_alloc_block( args.firstblock = args.fsbno; xfs_rmap_ag_owner(&args.oinfo, XFS_RMAP_OWN_REFC); args.minlen = args.maxlen = args.prod = 1; + args.resv = XFS_AG_RESV_METADATA; error = xfs_alloc_vextent(&args); if (error) @@ -115,17 +118,20 @@ xfs_refcountbt_free_block( struct xfs_buf *bp) { struct xfs_mount *mp = cur->bc_mp; - struct xfs_trans *tp = cur->bc_tp; xfs_fsblock_t fsbno = XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(bp)); struct xfs_owner_info oinfo; + int error; trace_xfs_refcountbt_free_block(cur->bc_mp, cur->bc_private.a.agno, XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), 1); xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_REFC); - xfs_bmap_add_free(mp, cur->bc_private.a.dfops, fsbno, 1, - &oinfo); - xfs_trans_binval(tp, bp); - return 0; + error = xfs_free_extent(cur->bc_tp, fsbno, 1, &oinfo, + XFS_AG_RESV_METADATA); + if (error) + return error; + + xfs_trans_binval(cur->bc_tp, bp); + return error; } STATIC int @@ -395,3 +401,48 @@ xfs_refcountbt_max_size( return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); } + +/* Count the blocks in the reference count tree. */ +static int +xfs_refcountbt_count_blocks( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *tree_blocks) +{ + struct xfs_buf *agbp; + struct xfs_btree_cur *cur; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + return error; + cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); + error = xfs_btree_count_blocks(cur, tree_blocks); + xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, agbp); + + return error; +} + +/* + * Figure out how many blocks to reserve and how many are used by this btree. + */ +int +xfs_refcountbt_calc_reserves( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *ask, + xfs_extlen_t *used) +{ + xfs_extlen_t tree_len = 0; + int error; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 0; + + *ask += xfs_refcountbt_max_size(mp); + error = xfs_refcountbt_count_blocks(mp, agno, &tree_len); + *used += tree_len; + + return error; +} diff --git a/libxfs/xfs_refcount_btree.h b/libxfs/xfs_refcount_btree.h index 780b02f..3be7768 100644 --- a/libxfs/xfs_refcount_btree.h +++ b/libxfs/xfs_refcount_btree.h @@ -68,4 +68,7 @@ extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, unsigned long long len); extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); +extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp, + xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); + #endif /* __XFS_REFCOUNT_BTREE_H__ */ diff --git a/libxfs/xfs_rmap_btree.c b/libxfs/xfs_rmap_btree.c index 3fedfd7..0b7da82 100644 --- a/libxfs/xfs_rmap_btree.c +++ b/libxfs/xfs_rmap_btree.c @@ -32,6 +32,7 @@ #include "xfs_rmap_btree.h" #include "xfs_trace.h" #include "xfs_cksum.h" +#include "xfs_ag_resv.h" /* * Reverse map btree. @@ -58,6 +59,14 @@ * try to recover tree and file data from corrupt primary metadata. */ +static bool +xfs_rmapbt_need_reserve( + struct xfs_mount *mp) +{ + return xfs_sb_version_hasrmapbt(&mp->m_sb) && + xfs_sb_version_hasreflink(&mp->m_sb); +} + static struct xfs_btree_cur * xfs_rmapbt_dup_cursor( struct xfs_btree_cur *cur) @@ -479,3 +488,74 @@ xfs_rmapbt_compute_maxlevels( mp->m_rmap_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_rmap_mnr, mp->m_sb.sb_agblocks); } + +/* Calculate the refcount btree size for some records. */ +xfs_extlen_t +xfs_rmapbt_calc_size( + struct xfs_mount *mp, + unsigned long long len) +{ + return xfs_btree_calc_size(mp, mp->m_rmap_mnr, len); +} + +/* + * Calculate the maximum refcount btree size. + */ +xfs_extlen_t +xfs_rmapbt_max_size( + struct xfs_mount *mp) +{ + /* Bail out if we're uninitialized, which can happen in mkfs. */ + if (mp->m_rmap_mxr[0] == 0) + return 0; + + return xfs_rmapbt_calc_size(mp, mp->m_sb.sb_agblocks); +} + +/* Count the blocks in the reference count tree. */ +static int +xfs_rmapbt_count_blocks( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *tree_blocks) +{ + struct xfs_buf *agbp; + struct xfs_btree_cur *cur; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + return error; + cur = xfs_rmapbt_init_cursor(mp, NULL, agbp, agno); + error = xfs_btree_count_blocks(cur, tree_blocks); + xfs_btree_del_cursor(cur, error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, agbp); + + return error; +} + +/* + * Figure out how many blocks to reserve and how many are used by this btree. + */ +int +xfs_rmapbt_calc_reserves( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_extlen_t *ask, + xfs_extlen_t *used) +{ + xfs_extlen_t pool_len; + xfs_extlen_t tree_len = 0; + int error; + + if (!xfs_rmapbt_need_reserve(mp)) + return 0; + + /* Reserve 1% of the AG or enough for 1 block per record. */ + pool_len = max(mp->m_sb.sb_agblocks / 100, xfs_rmapbt_max_size(mp)); + *ask += pool_len; + error = xfs_rmapbt_count_blocks(mp, agno, &tree_len); + *used += tree_len; + + return error; +} diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 5df406e..f398e8b 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -130,4 +130,11 @@ int xfs_rmap_finish_one(struct xfs_trans *tp, enum xfs_rmap_intent_type type, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state, struct xfs_btree_cur **pcur); +extern xfs_extlen_t xfs_rmapbt_calc_size(struct xfs_mount *mp, + unsigned long long len); +extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp); + +extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, + xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); + #endif /* __XFS_RMAP_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:41:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3203F8341 for ; Thu, 16 Jun 2016 20:41:40 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9D3F1AC002 for ; Thu, 16 Jun 2016 18:41:39 -0700 (PDT) X-ASG-Debug-ID: 1466127697-04cb6c5424582b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id AsnujC8aAaa1hBUT (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:37 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fZMj009219 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:41:36 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1fZcU006465 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:35 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fWiX012690; Fri, 17 Jun 2016 01:41:34 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:32 -0700 Subject: [PATCH 102/145] xfs: try other AGs to allocate a BMBT block From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 102/145] xfs: try other AGs to allocate a BMBT block To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:31 -0700 Message-ID: <146612769129.16048.14294337729712501169.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127697 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4595 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Prior to the introduction of reflink, allocating a block and mapping it into a file was performed in a single transaction with a single block reservation, and the allocator was supposed to find enough blocks to allocate the extent and any BMBT blocks that might be necessary (unless we're low on space). However, due to the way copy on write works, allocation and mapping have been split into two transactions, which means that we must be able to handle the case where we allocate an extent for CoW but that AG runs out of free space before the blocks can be mapped into a file, and the mapping requires a new BMBT block. When this happens, look in one of the other AGs for a BMBT block instead of taking the FS down. The same applies to the functions that convert a data fork to extents and later btree format. Signed-off-by: Darrick J. Wong --- libxfs/xfs_bmap.c | 30 ++++++++++++++++++++++++++++++ libxfs/xfs_bmap_btree.c | 17 +++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/libxfs/xfs_bmap.c b/libxfs/xfs_bmap.c index e81ade5..c48dd4a 100644 --- a/libxfs/xfs_bmap.c +++ b/libxfs/xfs_bmap.c @@ -745,6 +745,7 @@ xfs_bmap_extents_to_btree( args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); } else if (dfops->dop_low) { +try_another_ag: args.type = XFS_ALLOCTYPE_START_BNO; args.fsbno = *firstblock; } else { @@ -759,6 +760,21 @@ xfs_bmap_extents_to_btree( xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); return error; } + + /* + * During a CoW operation, the allocation and bmbt updates occur in + * different transactions. The mapping code tries to put new bmbt + * blocks near extents being mapped, but the only way to guarantee this + * is if the alloc and the mapping happen in a single transaction that + * has a block reservation. That isn't the case here, so if we run out + * of space we'll try again with another AG. + */ + if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && + args.fsbno == NULLFSBLOCK && + args.type == XFS_ALLOCTYPE_NEAR_BNO) { + dfops->dop_low = true; + goto try_another_ag; + } /* * Allocation can't fail, the space was reserved. */ @@ -894,6 +910,7 @@ xfs_bmap_local_to_extents( * file currently fits in an inode. */ if (*firstblock == NULLFSBLOCK) { +try_another_ag: args.fsbno = XFS_INO_TO_FSB(args.mp, ip->i_ino); args.type = XFS_ALLOCTYPE_START_BNO; } else { @@ -906,6 +923,19 @@ xfs_bmap_local_to_extents( if (error) goto done; + /* + * During a CoW operation, the allocation and bmbt updates occur in + * different transactions. The mapping code tries to put new bmbt + * blocks near extents being mapped, but the only way to guarantee this + * is if the alloc and the mapping happen in a single transaction that + * has a block reservation. That isn't the case here, so if we run out + * of space we'll try again with another AG. + */ + if (xfs_sb_version_hasreflink(&ip->i_mount->m_sb) && + args.fsbno == NULLFSBLOCK && + args.type == XFS_ALLOCTYPE_NEAR_BNO) { + goto try_another_ag; + } /* Can't fail, the space was reserved. */ ASSERT(args.fsbno != NULLFSBLOCK); ASSERT(args.len == 1); diff --git a/libxfs/xfs_bmap_btree.c b/libxfs/xfs_bmap_btree.c index 2145ac0..ecfcd5a 100644 --- a/libxfs/xfs_bmap_btree.c +++ b/libxfs/xfs_bmap_btree.c @@ -449,6 +449,7 @@ xfs_bmbt_alloc_block( if (args.fsbno == NULLFSBLOCK) { args.fsbno = be64_to_cpu(start->l); +try_another_ag: args.type = XFS_ALLOCTYPE_START_BNO; /* * Make sure there is sufficient room left in the AG to @@ -478,6 +479,22 @@ xfs_bmbt_alloc_block( if (error) goto error0; + /* + * During a CoW operation, the allocation and bmbt updates occur in + * different transactions. The mapping code tries to put new bmbt + * blocks near extents being mapped, but the only way to guarantee this + * is if the alloc and the mapping happen in a single transaction that + * has a block reservation. That isn't the case here, so if we run out + * of space we'll try again with another AG. + */ + if (xfs_sb_version_hasreflink(&cur->bc_mp->m_sb) && + args.fsbno == NULLFSBLOCK && + args.type == XFS_ALLOCTYPE_NEAR_BNO) { + cur->bc_private.b.dfops->dop_low = true; + args.fsbno = cur->bc_private.b.firstblock; + goto try_another_ag; + } + if (args.fsbno == NULLFSBLOCK && args.minleft) { /* * Could not find an AG with enough free space to satisfy From darrick.wong@oracle.com Thu Jun 16 20:41:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 27540834D for ; Thu, 16 Jun 2016 20:41:47 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id A0A1FAC005 for ; Thu, 16 Jun 2016 18:41:46 -0700 (PDT) X-ASG-Debug-ID: 1466127704-04cb6c542458300001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id dskvRzVpYoeXs6Bp (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:44 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ferN021896 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:40 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fdou013271 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:40 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fdGJ030130; Fri, 17 Jun 2016 01:41:39 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:38 -0700 Subject: [PATCH 103/145] xfs: provide switch to force filesystem to copy-on-write all the time From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 103/145] xfs: provide switch to force filesystem to copy-on-write all the time To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:37 -0700 Message-ID: <146612769744.16048.10282280464454097330.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127704 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1089 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Make it possible to force XFS to use copy on write all the time, at least if reflink is turned on. Signed-off-by: Darrick J. Wong --- libxfs/libxfs_priv.h | 2 ++ libxfs/xfs_refcount.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index 41f6b96..527bd49 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -517,4 +517,6 @@ int libxfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb, bool xfs_log_check_lsn(struct xfs_mount *, xfs_lsn_t); +#define xfs_always_cow (false) + #endif /* __LIBXFS_INTERNAL_XFS_H__ */ diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index e03a9b7..855ab54 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -1189,6 +1189,12 @@ xfs_refcount_find_shared( trace_xfs_refcount_find_shared(mp, agno, agbno, aglen); + if (xfs_always_cow) { + *fbno = agbno; + *flen = aglen; + return 0; + } + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); if (error) goto out; From darrick.wong@oracle.com Thu Jun 16 20:41:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D54A7834B for ; Thu, 16 Jun 2016 20:41:52 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id A203930404E for ; Thu, 16 Jun 2016 18:41:52 -0700 (PDT) X-ASG-Debug-ID: 1466127710-04cbb01fed6a5f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id M8fj8OU9KfxHHBas (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:51 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fkAE021943 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:46 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fjgg013392 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:45 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1fjMf002493; Fri, 17 Jun 2016 01:41:45 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:44 -0700 Subject: [PATCH 104/145] xfs: increase log reservations for reflink From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 104/145] xfs: increase log reservations for reflink To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:43 -0700 Message-ID: <146612770352.16048.10431104509314627818.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127711 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2621 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Increase the log reservations to handle the increased rolling that happens at the end of copy-on-write operations. Signed-off-by: Darrick J. Wong --- libxfs/xfs_trans_resv.c | 16 +++++++++++++--- libxfs/xfs_trans_resv.h | 2 ++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/libxfs/xfs_trans_resv.c b/libxfs/xfs_trans_resv.c index 5b6bbcd..5152a5b 100644 --- a/libxfs/xfs_trans_resv.c +++ b/libxfs/xfs_trans_resv.c @@ -811,11 +811,18 @@ xfs_trans_resv_calc( * require a permanent reservation on space. */ resp->tr_write.tr_logres = xfs_calc_write_reservation(mp); - resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; + else + resp->tr_write.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_write.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_itruncate.tr_logres = xfs_calc_itruncate_reservation(mp); - resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + resp->tr_itruncate.tr_logcount = + XFS_ITRUNCATE_LOG_COUNT_REFLINK; + else + resp->tr_itruncate.tr_logcount = XFS_ITRUNCATE_LOG_COUNT; resp->tr_itruncate.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_rename.tr_logres = xfs_calc_rename_reservation(mp); @@ -872,7 +879,10 @@ xfs_trans_resv_calc( resp->tr_growrtalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; resp->tr_qm_dqalloc.tr_logres = xfs_calc_qm_dqalloc_reservation(mp); - resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT_REFLINK; + else + resp->tr_qm_dqalloc.tr_logcount = XFS_WRITE_LOG_COUNT; resp->tr_qm_dqalloc.tr_logflags |= XFS_TRANS_PERM_LOG_RES; /* diff --git a/libxfs/xfs_trans_resv.h b/libxfs/xfs_trans_resv.h index 36a1511..b7e5357 100644 --- a/libxfs/xfs_trans_resv.h +++ b/libxfs/xfs_trans_resv.h @@ -87,6 +87,7 @@ struct xfs_trans_resv { #define XFS_DEFAULT_LOG_COUNT 1 #define XFS_DEFAULT_PERM_LOG_COUNT 2 #define XFS_ITRUNCATE_LOG_COUNT 2 +#define XFS_ITRUNCATE_LOG_COUNT_REFLINK 8 #define XFS_INACTIVE_LOG_COUNT 2 #define XFS_CREATE_LOG_COUNT 2 #define XFS_CREATE_TMPFILE_LOG_COUNT 2 @@ -96,6 +97,7 @@ struct xfs_trans_resv { #define XFS_LINK_LOG_COUNT 2 #define XFS_RENAME_LOG_COUNT 2 #define XFS_WRITE_LOG_COUNT 2 +#define XFS_WRITE_LOG_COUNT_REFLINK 8 #define XFS_ADDAFORK_LOG_COUNT 2 #define XFS_ATTRINVAL_LOG_COUNT 1 #define XFS_ATTRSET_LOG_COUNT 3 From darrick.wong@oracle.com Thu Jun 16 20:41:58 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3E4768356 for ; Thu, 16 Jun 2016 20:41:58 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id A535AAC002 for ; Thu, 16 Jun 2016 18:41:57 -0700 (PDT) X-ASG-Debug-ID: 1466127713-04cbb01fee6a600001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id zKGlc1FH4WqO3v8H (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:41:54 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fqPI009513 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:52 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fpjl001011 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:52 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1fpTN002505; Fri, 17 Jun 2016 01:41:51 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:50 -0700 Subject: [PATCH 105/145] xfs: use interval query for rmap map and unmap operations on shared files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 105/145] xfs: use interval query for rmap map and unmap operations on shared files To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:49 -0700 Message-ID: <146612770959.16048.6513699127969735731.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127713 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19623 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When it's possible for reverse mappings to overlap (data fork extents of files on reflink filesystems), use the interval query function to find the left neighbor of an extent we're trying to add; and be careful to use the lookup functions to update the neighbors and/or add new extents. v2: xfs_rmap_find_left_neighbor() needs to calculate the high key of a query range correctly. We can also add a few shortcuts -- there are no left neighbors of a query at offset zero. Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 13 + libxfs/xfs_rmap.c | 483 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.h | 7 + 3 files changed, 500 insertions(+), 3 deletions(-) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index 7022164..ce973ba 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -210,7 +210,6 @@ #define trace_xfs_rmap_convert_state(...) ((void) 0) #define trace_xfs_rmap_convert_done(...) ((void) 0) #define trace_xfs_rmap_convert_error(...) ((void) 0) -#define trace_xfs_rmap_find_left_neighbor_result(...) ((void) 0) #define trace_xfs_ag_resv_critical(...) ((void) 0) #define trace_xfs_ag_resv_needed(...) ((void) 0) @@ -265,6 +264,18 @@ #define trace_xfs_refcount_cow_increase(...) ((void) 0) #define trace_xfs_refcount_cow_decrease(...) ((void) 0) +#define trace_xfs_rmap_find_left_neighbor_candidate(...) ((void) 0) +#define trace_xfs_rmap_find_left_neighbor_query(...) ((void) 0) +#define trace_xfs_rmap_find_left_neighbor_result(...) ((void) 0) +#define trace_xfs_rmap_lookup_le_range_candidate(...) ((void) 0) +#define trace_xfs_rmap_lookup_le_range(...) ((void) 0) +#define trace_xfs_rmap_unmap(...) ((void) 0) +#define trace_xfs_rmap_unmap_done(...) ((void) 0) +#define trace_xfs_rmap_unmap_error(...) ((void) 0) +#define trace_xfs_rmap_map(...) ((void) 0) +#define trace_xfs_rmap_map_done(...) ((void) 0) +#define trace_xfs_rmap_map_error(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 6e69208..c1cb218 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -209,6 +209,160 @@ xfs_rmap_get_rec( return xfs_rmapbt_btrec_to_irec(rec, irec); } +struct xfs_find_left_neighbor_info { + struct xfs_rmap_irec high; + struct xfs_rmap_irec *irec; + int *stat; +}; + +/* For each rmap given, figure out if it matches the key we want. */ +STATIC int +xfs_rmap_find_left_neighbor_helper( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct xfs_find_left_neighbor_info *info = priv; + + trace_xfs_rmap_find_left_neighbor_candidate(cur->bc_mp, + cur->bc_private.a.agno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + rec->rm_flags); + + if (rec->rm_owner != info->high.rm_owner) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && + !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && + rec->rm_offset + rec->rm_blockcount - 1 != info->high.rm_offset) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + + *info->irec = *rec; + *info->stat = 1; + return XFS_BTREE_QUERY_RANGE_ABORT; +} + +/* + * Find the record to the left of the given extent, being careful only to + * return a match with the same owner and adjacent physical and logical + * block ranges. + */ +int +xfs_rmap_find_left_neighbor( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + uint64_t owner, + uint64_t offset, + unsigned int flags, + struct xfs_rmap_irec *irec, + int *stat) +{ + struct xfs_find_left_neighbor_info info; + int error; + + *stat = 0; + if (bno == 0) + return 0; + info.high.rm_startblock = bno - 1; + info.high.rm_owner = owner; + if (!XFS_RMAP_NON_INODE_OWNER(owner) && + !(flags & XFS_RMAP_BMBT_BLOCK)) { + if (offset == 0) + return 0; + info.high.rm_offset = offset - 1; + } else + info.high.rm_offset = 0; + info.high.rm_flags = flags; + info.high.rm_blockcount = 0; + info.irec = irec; + info.stat = stat; + + trace_xfs_rmap_find_left_neighbor_query(cur->bc_mp, + cur->bc_private.a.agno, bno, 0, owner, offset, flags); + + error = xfs_rmapbt_query_range(cur, &info.high, &info.high, + xfs_rmap_find_left_neighbor_helper, &info); + if (error == XFS_BTREE_QUERY_RANGE_ABORT) + error = 0; + if (*stat) + trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, + cur->bc_private.a.agno, irec->rm_startblock, + irec->rm_blockcount, irec->rm_owner, + irec->rm_offset, irec->rm_flags); + return error; +} + +/* For each rmap given, figure out if it matches the key we want. */ +STATIC int +xfs_rmap_lookup_le_range_helper( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct xfs_find_left_neighbor_info *info = priv; + + trace_xfs_rmap_lookup_le_range_candidate(cur->bc_mp, + cur->bc_private.a.agno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + rec->rm_flags); + + if (rec->rm_owner != info->high.rm_owner) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + if (!XFS_RMAP_NON_INODE_OWNER(rec->rm_owner) && + !(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) && + (rec->rm_offset > info->high.rm_offset || + rec->rm_offset + rec->rm_blockcount <= info->high.rm_offset)) + return XFS_BTREE_QUERY_RANGE_CONTINUE; + + *info->irec = *rec; + *info->stat = 1; + return XFS_BTREE_QUERY_RANGE_ABORT; +} + +/* + * Find the record to the left of the given extent, being careful only to + * return a match with the same owner and overlapping physical and logical + * block ranges. This is the overlapping-interval version of + * xfs_rmap_lookup_le. + */ +int +xfs_rmap_lookup_le_range( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + uint64_t owner, + uint64_t offset, + unsigned int flags, + struct xfs_rmap_irec *irec, + int *stat) +{ + struct xfs_find_left_neighbor_info info; + int error; + + info.high.rm_startblock = bno; + info.high.rm_owner = owner; + if (!XFS_RMAP_NON_INODE_OWNER(owner) && !(flags & XFS_RMAP_BMBT_BLOCK)) + info.high.rm_offset = offset; + else + info.high.rm_offset = 0; + info.high.rm_flags = flags; + info.high.rm_blockcount = 0; + *stat = 0; + info.irec = irec; + info.stat = stat; + + trace_xfs_rmap_lookup_le_range(cur->bc_mp, + cur->bc_private.a.agno, bno, 0, owner, offset, flags); + error = xfs_rmapbt_query_range(cur, &info.high, &info.high, + xfs_rmap_lookup_le_range_helper, &info); + if (error == XFS_BTREE_QUERY_RANGE_ABORT) + error = 0; + if (*stat) + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, + cur->bc_private.a.agno, irec->rm_startblock, + irec->rm_blockcount, irec->rm_owner, + irec->rm_offset, irec->rm_flags); + return error; +} + /* * Find the extent in the rmap btree and remove it. * @@ -1157,6 +1311,168 @@ xfs_rmap_unmap( } /* + * Find an extent in the rmap btree and unmap it. For rmap extent types that + * can overlap (data fork rmaps on reflink filesystems) we must be careful + * that the prev/next records in the btree might belong to another owner. + * Therefore we must use delete+insert to alter any of the key fields. + * + * For every other situation there can only be one owner for a given extent, + * so we can call the regular _free function. + */ +STATIC int +xfs_rmap_unmap_shared( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + uint64_t ltoff; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_unmap(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * We should always have a left record because there's a static record + * for the AG headers at rm_startblock == 0 created by mkfs/growfs that + * will not ever be removed from the tree. + */ + error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, + <rec, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + ltoff = ltrec.rm_offset; + + /* Make sure the extent we found covers the entire freeing range. */ + XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && + ltrec.rm_startblock + ltrec.rm_blockcount >= + bno + len, out_error); + + /* Make sure the owner matches what we expect to find in the tree. */ + XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner, out_error); + + /* Make sure the unwritten flag matches. */ + XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == + (ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); + + /* Check the offset. */ + XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_offset <= offset, out_error); + XFS_WANT_CORRUPTED_GOTO(mp, offset <= ltoff + ltrec.rm_blockcount, + out_error); + + if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) { + /* Exact match, simply remove the record from rmap tree. */ + error = xfs_rmapbt_delete(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + if (error) + goto out_error; + } else if (ltrec.rm_startblock == bno) { + /* + * Overlap left hand side of extent: move the start, trim the + * length and update the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + + /* Delete prev rmap. */ + error = xfs_rmapbt_delete(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + if (error) + goto out_error; + + /* Add an rmap at the new offset. */ + ltrec.rm_startblock += len; + ltrec.rm_blockcount -= len; + ltrec.rm_offset += len; + error = xfs_rmapbt_insert(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags); + if (error) + goto out_error; + } else if (ltrec.rm_startblock + ltrec.rm_blockcount == bno + len) { + /* + * Overlap right hand side of extent: trim the length and + * update the current record. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrrrrrrr| + * bno len + */ + error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + ltrec.rm_blockcount -= len; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else { + /* + * Overlap middle of extent: trim the length of the existing + * record to the length of the new left-extent size, increment + * the insertion position so we can insert a new record + * containing the remaining right-extent space. + * + * ltbno ltlen + * Orig: |oooooooooooooooooooo| + * Freeing: |fffffffff| + * Result: |rrrrr| |rrrr| + * bno len + */ + xfs_extlen_t orig_len = ltrec.rm_blockcount; + + /* Shrink the left side of the rmap */ + error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + ltrec.rm_blockcount = bno - ltrec.rm_startblock; + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + + /* Add an rmap at the new offset */ + error = xfs_rmapbt_insert(cur, bno + len, + orig_len - len - ltrec.rm_blockcount, + ltrec.rm_owner, offset + len, + ltrec.rm_flags); + if (error) + goto out_error; + } + + trace_xfs_rmap_unmap_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_unmap_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + +/* * Find an extent in the rmap btree and map it. */ STATIC int @@ -1170,6 +1486,159 @@ xfs_rmap_map( return __xfs_rmap_alloc(cur, bno, len, unwritten, oinfo); } +/* + * Find an extent in the rmap btree and map it. For rmap extent types that + * can overlap (data fork rmaps on reflink filesystems) we must be careful + * that the prev/next records in the btree might belong to another owner. + * Therefore we must use delete+insert to alter any of the key fields. + * + * For every other situation there can only be one owner for a given extent, + * so we can call the regular _alloc function. + */ +STATIC int +xfs_rmap_map_shared( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec ltrec; + struct xfs_rmap_irec gtrec; + int have_gt; + int have_lt; + int error = 0; + int i; + uint64_t owner; + uint64_t offset; + unsigned int flags = 0; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + if (unwritten) + flags |= XFS_RMAP_UNWRITTEN; + trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* Is there a left record that abuts our range? */ + error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, flags, + <rec, &have_lt); + if (error) + goto out_error; + if (have_lt && + !xfs_rmap_is_mergeable(<rec, owner, offset, len, flags)) + have_lt = 0; + + /* Is there a right record that abuts our range? */ + error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, + flags, &have_gt); + if (error) + goto out_error; + if (have_gt) { + error = xfs_rmap_get_rec(cur, >rec, &have_gt); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, have_gt == 1, out_error); + trace_xfs_rmap_map_gtrec(cur->bc_mp, + cur->bc_private.a.agno, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + + if (!xfs_rmap_is_mergeable(>rec, owner, offset, len, flags)) + have_gt = 0; + } + + if (have_lt && + ltrec.rm_startblock + ltrec.rm_blockcount == bno && + ltrec.rm_offset + ltrec.rm_blockcount == offset) { + /* + * Left edge contiguous, merge into left record. + * + * ltbno ltlen + * orig: |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + ltrec.rm_blockcount += len; + if (have_gt && + bno + len == gtrec.rm_startblock && + offset + len == gtrec.rm_offset) { + /* + * Right edge also contiguous, delete right record + * and merge into left record. + * + * ltbno ltlen gtbno gtlen + * orig: |ooooooooo| |ooooooooo| + * adding: |aaaaaaaaa| + * result: |rrrrrrrrrrrrrrrrrrrrrrrrrrrrr| + */ + ltrec.rm_blockcount += gtrec.rm_blockcount; + error = xfs_rmapbt_delete(cur, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (error) + goto out_error; + } + + /* Point the cursor back to the left record and update. */ + error = xfs_rmap_lookup_eq(cur, ltrec.rm_startblock, + ltrec.rm_blockcount, ltrec.rm_owner, + ltrec.rm_offset, ltrec.rm_flags, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + error = xfs_rmap_update(cur, <rec); + if (error) + goto out_error; + } else if (have_gt && + bno + len == gtrec.rm_startblock && + offset + len == gtrec.rm_offset) { + /* + * Right edge contiguous, merge into right record. + * + * gtbno gtlen + * Orig: |ooooooooo| + * adding: |aaaaaaaaa| + * Result: |rrrrrrrrrrrrrrrrrrr| + * bno len + */ + /* Delete the old record. */ + error = xfs_rmapbt_delete(cur, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (error) + goto out_error; + + /* Move the start and re-add it. */ + gtrec.rm_startblock = bno; + gtrec.rm_blockcount += len; + gtrec.rm_offset = offset; + error = xfs_rmapbt_insert(cur, gtrec.rm_startblock, + gtrec.rm_blockcount, gtrec.rm_owner, + gtrec.rm_offset, gtrec.rm_flags); + if (error) + goto out_error; + } else { + /* + * No contiguous edge with identical owner, insert + * new record at current cursor position. + */ + error = xfs_rmapbt_insert(cur, bno, len, owner, offset, flags); + if (error) + goto out_error; + } + + trace_xfs_rmap_map_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +out_error: + if (error) + trace_xfs_rmap_map_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + struct xfs_rmapbt_query_range_info { xfs_rmapbt_query_range_fn fn; void *priv; @@ -1302,10 +1771,18 @@ xfs_rmap_finish_one( case XFS_RMAP_MAP: error = xfs_rmap_map(rcur, bno, blockcount, unwritten, &oinfo); break; + case XFS_RMAP_MAP_SHARED: + error = xfs_rmap_map_shared(rcur, bno, blockcount, unwritten, + &oinfo); + break; case XFS_RMAP_UNMAP: error = xfs_rmap_unmap(rcur, bno, blockcount, unwritten, &oinfo); break; + case XFS_RMAP_UNMAP_SHARED: + error = xfs_rmap_unmap_shared(rcur, bno, blockcount, unwritten, + &oinfo); + break; case XFS_RMAP_CONVERT: error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, &oinfo); @@ -1373,7 +1850,8 @@ xfs_rmap_map_extent( { struct xfs_rmap_intent ri; - ri.ri_type = XFS_RMAP_MAP; + ri.ri_type = xfs_is_reflink_inode(ip) ? XFS_RMAP_MAP_SHARED : + XFS_RMAP_MAP; ri.ri_owner = ip->i_ino; ri.ri_whichfork = whichfork; ri.ri_bmap = *PREV; @@ -1392,7 +1870,8 @@ xfs_rmap_unmap_extent( { struct xfs_rmap_intent ri; - ri.ri_type = XFS_RMAP_UNMAP; + ri.ri_type = xfs_is_reflink_inode(ip) ? XFS_RMAP_UNMAP_SHARED : + XFS_RMAP_UNMAP; ri.ri_owner = ip->i_ino; ri.ri_whichfork = whichfork; ri.ri_bmap = *PREV; diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index f398e8b..5baa81f 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -70,6 +70,13 @@ int xfs_rmapbt_insert(struct xfs_btree_cur *rcur, xfs_agblock_t agbno, int xfs_rmap_get_rec(struct xfs_btree_cur *cur, struct xfs_rmap_irec *irec, int *stat); +int xfs_rmap_find_left_neighbor(struct xfs_btree_cur *cur, xfs_agblock_t bno, + uint64_t owner, uint64_t offset, unsigned int flags, + struct xfs_rmap_irec *irec, int *stat); +int xfs_rmap_lookup_le_range(struct xfs_btree_cur *cur, xfs_agblock_t bno, + uint64_t owner, uint64_t offset, unsigned int flags, + struct xfs_rmap_irec *irec, int *stat); + /* functions for updating the rmapbt for bmbt blocks and AG btree blocks */ int xfs_rmap_alloc(struct xfs_trans *tp, struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t bno, xfs_extlen_t len, From darrick.wong@oracle.com Thu Jun 16 20:42:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7B680835A for ; Thu, 16 Jun 2016 20:42:07 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 361298F8052 for ; Thu, 16 Jun 2016 18:42:07 -0700 (PDT) X-ASG-Debug-ID: 1466127724-04bdf01e1396540001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 9U2Iq4bKvrkvTkJA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1fxvJ022062 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:59 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fwj2001109 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:41:58 GMT Received: from abhmp0016.oracle.com (abhmp0016.oracle.com [141.146.116.22]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1fvGA030178; Fri, 17 Jun 2016 01:41:57 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:41:57 -0700 Subject: [PATCH 106/145] xfs: convert unwritten status of shared-extent reverse mappings on shared files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 106/145] xfs: convert unwritten status of shared-extent reverse mappings on shared files To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:41:55 -0700 Message-ID: <146612771588.16048.3966278488905711053.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127724 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13064 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Upgrade the rmap extent conversion function to handle shared extents. v2: Move unwritten bit to rm_offset. Signed-off-by: Darrick J. Wong --- libxfs/xfs_rmap.c | 385 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 384 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index c1cb218..23bffdc 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -1291,6 +1291,384 @@ xfs_rmap_convert( return __xfs_rmap_convert(cur, bno, len, unwritten, oinfo); } +/* + * Convert an unwritten extent to a real extent or vice versa. If there is no + * possibility of overlapping extents, delegate to the simpler convert + * function. + */ +STATIC int +xfs_rmap_convert_shared( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool unwritten, + struct xfs_owner_info *oinfo) +{ + struct xfs_mount *mp = cur->bc_mp; + struct xfs_rmap_irec r[4]; /* neighbor extent entries */ + /* left is 0, right is 1, prev is 2 */ + /* new is 3 */ + uint64_t owner; + uint64_t offset; + uint64_t new_endoff; + unsigned int oldext; + unsigned int newext; + unsigned int flags = 0; + int i; + int state = 0; + int error; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || + (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); + oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; + new_endoff = offset + len; + trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); + + /* + * For the initial lookup, look for and exact match or the left-adjacent + * record for our insertion point. This will also give us the record for + * start block contiguity tests. + */ + error = xfs_rmap_lookup_le_range(cur, bno, owner, offset, flags, + &PREV, &i); + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + + ASSERT(PREV.rm_offset <= offset); + ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); + ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); + newext = ~oldext & XFS_RMAP_UNWRITTEN; + + /* + * Set flags determining what part of the previous oldext allocation + * extent is being replaced by a newext allocation. + */ + if (PREV.rm_offset == offset) + state |= RMAP_LEFT_FILLING; + if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) + state |= RMAP_RIGHT_FILLING; + + /* Is there a left record that abuts our range? */ + error = xfs_rmap_find_left_neighbor(cur, bno, owner, offset, newext, + &LEFT, &i); + if (error) + goto done; + if (i) { + state |= RMAP_LEFT_VALID; + XFS_WANT_CORRUPTED_GOTO(mp, + LEFT.rm_startblock + LEFT.rm_blockcount <= bno, + done); + if (xfs_rmap_is_mergeable(&LEFT, owner, offset, len, newext)) + state |= RMAP_LEFT_CONTIG; + } + + /* Is there a right record that abuts our range? */ + error = xfs_rmap_lookup_eq(cur, bno + len, len, owner, offset + len, + newext, &i); + if (error) + goto done; + if (i) { + state |= RMAP_RIGHT_VALID; + error = xfs_rmap_get_rec(cur, &RIGHT, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, + done); + trace_xfs_rmap_convert_gtrec(cur->bc_mp, + cur->bc_private.a.agno, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (xfs_rmap_is_mergeable(&RIGHT, owner, offset, len, newext)) + state |= RMAP_RIGHT_CONTIG; + } + + /* check that left + prev + right is not too long */ + if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == + (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && + (unsigned long)LEFT.rm_blockcount + len + + RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) + state &= ~RMAP_RIGHT_CONTIG; + + trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, + _RET_IP_); + /* + * Switch out based on the FILLING and CONTIG state bits. + */ + switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left and right neighbors are both contiguous with new. + */ + error = xfs_rmapbt_delete(cur, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (error) + goto done; + error = xfs_rmapbt_delete(cur, PREV.rm_startblock, + PREV.rm_blockcount, PREV.rm_owner, + PREV.rm_offset, PREV.rm_flags); + if (error) + goto done; + NEW = LEFT; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The left neighbor is contiguous, the right is not. + */ + error = xfs_rmapbt_delete(cur, PREV.rm_startblock, + PREV.rm_blockcount, PREV.rm_owner, + PREV.rm_offset, PREV.rm_flags); + if (error) + goto done; + NEW = LEFT; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += PREV.rm_blockcount; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting all of a previous oldext extent to newext. + * The right neighbor is contiguous, the left is not. + */ + error = xfs_rmapbt_delete(cur, RIGHT.rm_startblock, + RIGHT.rm_blockcount, RIGHT.rm_owner, + RIGHT.rm_offset, RIGHT.rm_flags); + if (error) + goto done; + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += RIGHT.rm_blockcount; + NEW.rm_flags = RIGHT.rm_flags; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: + /* + * Setting all of a previous oldext extent to newext. + * Neither the left nor right neighbors are contiguous with + * the new one. + */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_flags = newext; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is contiguous. + */ + NEW = PREV; + error = xfs_rmapbt_delete(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW.rm_offset += len; + NEW.rm_startblock += len; + NEW.rm_blockcount -= len; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW = LEFT; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount += len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING: + /* + * Setting the first part of a previous oldext extent to newext. + * The left neighbor is not contiguous. + */ + NEW = PREV; + error = xfs_rmapbt_delete(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW.rm_offset += len; + NEW.rm_startblock += len; + NEW.rm_blockcount -= len; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + error = xfs_rmapbt_insert(cur, bno, len, owner, offset, newext); + if (error) + goto done; + break; + + case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is contiguous with the new allocation. + */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount = offset - NEW.rm_offset; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + NEW = RIGHT; + error = xfs_rmapbt_delete(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + NEW.rm_offset = offset; + NEW.rm_startblock = bno; + NEW.rm_blockcount += len; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags); + if (error) + goto done; + break; + + case RMAP_RIGHT_FILLING: + /* + * Setting the last part of a previous oldext extent to newext. + * The right neighbor is not contiguous. + */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount -= len; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + error = xfs_rmapbt_insert(cur, bno, len, owner, offset, newext); + if (error) + goto done; + break; + + case 0: + /* + * Setting the middle part of a previous oldext extent to + * newext. Contiguity is impossible here. + * One extent becomes three extents. + */ + /* new right extent - oldext */ + NEW.rm_startblock = bno + len; + NEW.rm_owner = owner; + NEW.rm_offset = new_endoff; + NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - + new_endoff; + NEW.rm_flags = PREV.rm_flags; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, + NEW.rm_flags); + if (error) + goto done; + /* new left extent - oldext */ + NEW = PREV; + error = xfs_rmap_lookup_eq(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, + NEW.rm_offset, NEW.rm_flags, &i); + if (error) + goto done; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); + NEW.rm_blockcount = offset - NEW.rm_offset; + error = xfs_rmap_update(cur, &NEW); + if (error) + goto done; + /* new middle extent - newext */ + NEW.rm_startblock = bno; + NEW.rm_blockcount = len; + NEW.rm_owner = owner; + NEW.rm_offset = offset; + NEW.rm_flags = newext; + error = xfs_rmapbt_insert(cur, NEW.rm_startblock, + NEW.rm_blockcount, NEW.rm_owner, NEW.rm_offset, + NEW.rm_flags); + if (error) + goto done; + break; + + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: + case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: + case RMAP_LEFT_CONTIG: + case RMAP_RIGHT_CONTIG: + /* + * These cases are all impossible. + */ + ASSERT(0); + } + + trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, + unwritten, oinfo); +done: + if (error) + trace_xfs_rmap_convert_error(cur->bc_mp, + cur->bc_private.a.agno, error, _RET_IP_); + return error; +} + #undef NEW #undef LEFT #undef RIGHT @@ -1787,6 +2165,10 @@ xfs_rmap_finish_one( error = xfs_rmap_convert(rcur, bno, blockcount, !unwritten, &oinfo); break; + case XFS_RMAP_CONVERT_SHARED: + error = xfs_rmap_convert_shared(rcur, bno, blockcount, + !unwritten, &oinfo); + break; case XFS_RMAP_ALLOC: error = __xfs_rmap_alloc(rcur, bno, blockcount, unwritten, &oinfo); @@ -1890,7 +2272,8 @@ xfs_rmap_convert_extent( { struct xfs_rmap_intent ri; - ri.ri_type = XFS_RMAP_CONVERT; + ri.ri_type = xfs_is_reflink_inode(ip) ? XFS_RMAP_CONVERT_SHARED : + XFS_RMAP_CONVERT; ri.ri_owner = ip->i_ino; ri.ri_whichfork = whichfork; ri.ri_bmap = *PREV; From darrick.wong@oracle.com Thu Jun 16 20:42:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C56B58363 for ; Thu, 16 Jun 2016 20:42:10 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 973DA304039 for ; Thu, 16 Jun 2016 18:42:10 -0700 (PDT) X-ASG-Debug-ID: 1466127729-04cb6c5426583b0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id wKk5TcF75enQTZK6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:09 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1g4RO022407 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:42:05 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1g40s007318 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:04 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1g382025064; Fri, 17 Jun 2016 01:42:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:03 -0700 Subject: [PATCH 107/145] xfs: don't allow realtime and reflinked files to mix From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 107/145] xfs: don't allow realtime and reflinked files to mix To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:02 -0700 Message-ID: <146612772210.16048.9804805935166635640.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127729 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 948 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines We don't support sharing blocks on the realtime device. Signed-off-by: Darrick J. Wong --- libxfs/xfs_inode_buf.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index 8a804e2..3e46bc5 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -384,6 +384,9 @@ xfs_dinode_verify( xfs_ino_t ino, struct xfs_dinode *dip) { + uint16_t flags; + uint64_t flags2; + if (dip->di_magic != cpu_to_be16(XFS_DINODE_MAGIC)) return false; @@ -400,6 +403,13 @@ xfs_dinode_verify( return false; if (!uuid_equal(&dip->di_uuid, &mp->m_sb.sb_meta_uuid)) return false; + + /* don't let reflink and realtime mix */ + flags = be16_to_cpu(dip->di_flags); + flags2 = be64_to_cpu(dip->di_flags2); + if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & XFS_DIFLAG_REALTIME)) + return false; + return true; } From darrick.wong@oracle.com Thu Jun 16 20:42:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8C397836A for ; Thu, 16 Jun 2016 20:42:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3E6B88F8054 for ; Thu, 16 Jun 2016 18:42:13 -0700 (PDT) X-ASG-Debug-ID: 1466127731-04bdf01e1096570001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Z9rqjxkAtPVy1Tiu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:11 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1gAjm009971 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:10 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gALX001752 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:10 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1g9om002669; Fri, 17 Jun 2016 01:42:10 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:09 -0700 Subject: [PATCH 108/145] xfs: don't mix reflink and DAX mode for now From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 108/145] xfs: don't mix reflink and DAX mode for now To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:08 -0700 Message-ID: <146612772816.16048.8102485898993534089.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127731 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 710 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since we don't have a strategy for handling both DAX and reflink, for now we'll just prohibit both being set at the same time. Signed-off-by: Darrick J. Wong --- libxfs/xfs_inode_buf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index 3e46bc5..cf48c8c 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -410,6 +410,10 @@ xfs_dinode_verify( if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags & XFS_DIFLAG_REALTIME)) return false; + /* don't let reflink and dax mix */ + if ((flags2 & XFS_DIFLAG2_REFLINK) && (flags2 & XFS_DIFLAG2_DAX)) + return false; + return true; } From darrick.wong@oracle.com Thu Jun 16 20:42:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BB3FF833B for ; Thu, 16 Jun 2016 20:42:19 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8B0E28F804C for ; Thu, 16 Jun 2016 18:42:19 -0700 (PDT) X-ASG-Debug-ID: 1466127737-04cb6c5426583d0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id XJRxj9BlBI48bGOV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:18 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1gGPw010039 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:17 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gGvR014174 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:16 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gFxe025093; Fri, 17 Jun 2016 01:42:16 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:15 -0700 Subject: [PATCH 109/145] xfs: recognize the reflink feature bit From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 109/145] xfs: recognize the reflink feature bit To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:14 -0700 Message-ID: <146612773421.16048.9778759502152238980.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127738 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 843 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add the reflink feature flag to the set of recognized feature flags. This enables users to write to reflink filesystems. Signed-off-by: Darrick J. Wong --- libxfs/xfs_format.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index de29220..bfbf6e8 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -459,7 +459,8 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_REFLINK (1 << 2) /* reflinked files */ #define XFS_SB_FEAT_RO_COMPAT_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ - XFS_SB_FEAT_RO_COMPAT_RMAPBT) + XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ + XFS_SB_FEAT_RO_COMPAT_REFLINK) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool xfs_sb_has_ro_compat_feature( From darrick.wong@oracle.com Thu Jun 16 20:42:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 50D7D8341 for ; Thu, 16 Jun 2016 20:42:31 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 224738F804C for ; Thu, 16 Jun 2016 18:42:31 -0700 (PDT) X-ASG-Debug-ID: 1466127748-04cbb01fec6a670001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 4r4Xn7VKgK4sKuVD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:28 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1gNop022626 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:23 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gMUh001999 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:23 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gM4a030357; Fri, 17 Jun 2016 01:42:22 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:21 -0700 Subject: [PATCH 110/145] xfs_db: dump refcount btree data From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 110/145] xfs_db: dump refcount btree data To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:20 -0700 Message-ID: <146612774028.16048.6356654455150232768.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127748 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11203 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add the ability to walk and dump the refcount btree in xfs_db. Signed-off-by: Darrick J. Wong --- db/agf.c | 10 ++++++++-- db/btblock.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ db/btblock.h | 5 +++++ db/field.c | 9 +++++++++ db/field.h | 4 ++++ db/inode.c | 3 +++ db/sb.c | 2 ++ db/type.c | 5 +++++ db/type.h | 2 +- man/man8/xfs_db.8 | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 10 files changed, 132 insertions(+), 5 deletions(-) diff --git a/db/agf.c b/db/agf.c index f4c4269..86d8929 100644 --- a/db/agf.c +++ b/db/agf.c @@ -47,7 +47,7 @@ const field_t agf_flds[] = { { "versionnum", FLDT_UINT32D, OI(OFF(versionnum)), C1, 0, TYP_NONE }, { "seqno", FLDT_AGNUMBER, OI(OFF(seqno)), C1, 0, TYP_NONE }, { "length", FLDT_AGBLOCK, OI(OFF(length)), C1, 0, TYP_NONE }, - { "roots", FLDT_AGBLOCK, OI(OFF(roots)), CI(XFS_BTNUM_AGF), + { "roots", FLDT_AGBLOCK, OI(OFF(roots)), CI(XFS_BTNUM_AGF) + 1, FLD_ARRAY|FLD_SKIPALL, TYP_NONE }, { "bnoroot", FLDT_AGBLOCK, OI(OFF(roots) + XFS_BTNUM_BNO * SZ(roots[XFS_BTNUM_BNO])), C1, 0, @@ -58,7 +58,10 @@ const field_t agf_flds[] = { { "rmaproot", FLDT_AGBLOCKNZ, OI(OFF(roots) + XFS_BTNUM_RMAP * SZ(roots[XFS_BTNUM_RMAP])), C1, 0, TYP_RMAPBT }, - { "levels", FLDT_UINT32D, OI(OFF(levels)), CI(XFS_BTNUM_AGF), + { "refcntroot", FLDT_AGBLOCKNZ, + OI(OFF(refcount_root)), C1, 0, + TYP_REFCBT }, + { "levels", FLDT_UINT32D, OI(OFF(levels)), CI(XFS_BTNUM_AGF) + 1, FLD_ARRAY|FLD_SKIPALL, TYP_NONE }, { "bnolevel", FLDT_UINT32D, OI(OFF(levels) + XFS_BTNUM_BNO * SZ(levels[XFS_BTNUM_BNO])), C1, 0, @@ -69,6 +72,9 @@ const field_t agf_flds[] = { { "rmaplevel", FLDT_UINT32D, OI(OFF(levels) + XFS_BTNUM_RMAP * SZ(levels[XFS_BTNUM_RMAP])), C1, 0, TYP_NONE }, + { "refcntlevel", FLDT_UINT32D, + OI(OFF(refcount_level)), C1, 0, + TYP_NONE }, { "flfirst", FLDT_UINT32D, OI(OFF(flfirst)), C1, 0, TYP_NONE }, { "fllast", FLDT_UINT32D, OI(OFF(fllast)), C1, 0, TYP_NONE }, { "flcount", FLDT_UINT32D, OI(OFF(flcount)), C1, 0, TYP_NONE }, diff --git a/db/btblock.c b/db/btblock.c index ce59d18..e0c896b 100644 --- a/db/btblock.c +++ b/db/btblock.c @@ -102,6 +102,12 @@ struct xfs_db_btree { sizeof(struct xfs_rmap_rec), sizeof(__be32), }, + { XFS_REFC_CRC_MAGIC, + XFS_BTREE_SBLOCK_CRC_LEN, + sizeof(struct xfs_refcount_key), + sizeof(struct xfs_refcount_rec), + sizeof(__be32), + }, { 0, }, }; @@ -707,3 +713,47 @@ const field_t rmapbt_rec_flds[] = { { NULL } }; #undef ROFF + +/* refcount btree blocks */ +const field_t refcbt_crc_hfld[] = { + { "", FLDT_REFCBT_CRC, OI(0), C1, 0, TYP_NONE }, + { NULL } +}; + +#define OFF(f) bitize(offsetof(struct xfs_btree_block, bb_ ## f)) +const field_t refcbt_crc_flds[] = { + { "magic", FLDT_UINT32X, OI(OFF(magic)), C1, 0, TYP_NONE }, + { "level", FLDT_UINT16D, OI(OFF(level)), C1, 0, TYP_NONE }, + { "numrecs", FLDT_UINT16D, OI(OFF(numrecs)), C1, 0, TYP_NONE }, + { "leftsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_leftsib)), C1, 0, TYP_REFCBT }, + { "rightsib", FLDT_AGBLOCK, OI(OFF(u.s.bb_rightsib)), C1, 0, TYP_REFCBT }, + { "bno", FLDT_DFSBNO, OI(OFF(u.s.bb_blkno)), C1, 0, TYP_REFCBT }, + { "lsn", FLDT_UINT64X, OI(OFF(u.s.bb_lsn)), C1, 0, TYP_NONE }, + { "uuid", FLDT_UUID, OI(OFF(u.s.bb_uuid)), C1, 0, TYP_NONE }, + { "owner", FLDT_AGNUMBER, OI(OFF(u.s.bb_owner)), C1, 0, TYP_NONE }, + { "crc", FLDT_CRC, OI(OFF(u.s.bb_crc)), C1, 0, TYP_NONE }, + { "recs", FLDT_REFCBTREC, btblock_rec_offset, btblock_rec_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "keys", FLDT_REFCBTKEY, btblock_key_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_NONE }, + { "ptrs", FLDT_REFCBTPTR, btblock_ptr_offset, btblock_key_count, + FLD_ARRAY|FLD_ABASE1|FLD_COUNT|FLD_OFFSET, TYP_REFCBT }, + { NULL } +}; +#undef OFF + +#define KOFF(f) bitize(offsetof(struct xfs_refcount_key, rc_ ## f)) +const field_t refcbt_key_flds[] = { + { "startblock", FLDT_AGBLOCK, OI(KOFF(startblock)), C1, 0, TYP_DATA }, + { NULL } +}; +#undef KOFF + +#define ROFF(f) bitize(offsetof(struct xfs_refcount_rec, rc_ ## f)) +const field_t refcbt_rec_flds[] = { + { "startblock", FLDT_AGBLOCK, OI(ROFF(startblock)), C1, 0, TYP_DATA }, + { "blockcount", FLDT_EXTLEN, OI(ROFF(blockcount)), C1, 0, TYP_NONE }, + { "refcount", FLDT_UINT32D, OI(ROFF(refcount)), C1, 0, TYP_DATA }, + { NULL } +}; +#undef ROFF diff --git a/db/btblock.h b/db/btblock.h index 35299b4..fead2f1 100644 --- a/db/btblock.h +++ b/db/btblock.h @@ -59,4 +59,9 @@ extern const struct field rmapbt_crc_hfld[]; extern const struct field rmapbt_key_flds[]; extern const struct field rmapbt_rec_flds[]; +extern const struct field refcbt_crc_flds[]; +extern const struct field refcbt_crc_hfld[]; +extern const struct field refcbt_key_flds[]; +extern const struct field refcbt_rec_flds[]; + extern int btblock_size(void *obj, int startoff, int idx); diff --git a/db/field.c b/db/field.c index 58728a9..f81b64d 100644 --- a/db/field.c +++ b/db/field.c @@ -183,6 +183,15 @@ const ftattr_t ftattrtab[] = { { FLDT_RMAPBTREC, "rmapbtrec", fp_sarray, (char *)rmapbt_rec_flds, SI(bitsz(struct xfs_rmap_rec)), 0, NULL, rmapbt_rec_flds }, + { FLDT_REFCBT_CRC, "refcntbt", NULL, (char *)refcbt_crc_flds, btblock_size, + FTARG_SIZE, NULL, refcbt_crc_flds }, + { FLDT_REFCBTKEY, "refcntbtkey", fp_sarray, (char *)refcbt_key_flds, + SI(bitsz(struct xfs_refcount_key)), 0, NULL, refcbt_key_flds }, + { FLDT_REFCBTPTR, "refcntbtptr", fp_num, "%u", SI(bitsz(xfs_refcount_ptr_t)), + 0, fa_agblock, NULL }, + { FLDT_REFCBTREC, "refcntbtrec", fp_sarray, (char *)refcbt_rec_flds, + SI(bitsz(struct xfs_refcount_rec)), 0, NULL, refcbt_rec_flds }, + /* CRC field */ { FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(__uint32_t)), 0, NULL, NULL }, diff --git a/db/field.h b/db/field.h index 47f562a..ae5f490 100644 --- a/db/field.h +++ b/db/field.h @@ -89,6 +89,10 @@ typedef enum fldt { FLDT_RMAPBTKEY, FLDT_RMAPBTPTR, FLDT_RMAPBTREC, + FLDT_REFCBT_CRC, + FLDT_REFCBTKEY, + FLDT_REFCBTPTR, + FLDT_REFCBTREC, /* CRC field type */ FLDT_CRC, diff --git a/db/inode.c b/db/inode.c index 442e6ea..702cdf8 100644 --- a/db/inode.c +++ b/db/inode.c @@ -175,6 +175,9 @@ const field_t inode_v3_flds[] = { { "crtime", FLDT_TIMESTAMP, OI(COFF(crtime)), C1, 0, TYP_NONE }, { "inumber", FLDT_INO, OI(COFF(ino)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(COFF(uuid)), C1, 0, TYP_NONE }, + { "reflink", FLDT_UINT1, + OI(COFF(flags2) + bitsz(__uint64_t) - XFS_DIFLAG2_REFLINK_BIT-1), C1, + 0, TYP_NONE }, { NULL } }; diff --git a/db/sb.c b/db/sb.c index 79a3c1d..8e7722c 100644 --- a/db/sb.c +++ b/db/sb.c @@ -694,6 +694,8 @@ version_string( strcat(s, ",SPARSE_INODES"); if (xfs_sb_version_hasmetauuid(sbp)) strcat(s, ",META_UUID"); + if (xfs_sb_version_hasreflink(sbp)) + strcat(s, ",REFLINK"); return s; } diff --git a/db/type.c b/db/type.c index dd192a1..2a501ca 100644 --- a/db/type.c +++ b/db/type.c @@ -59,6 +59,7 @@ static const typ_t __typtab[] = { { TYP_BNOBT, "bnobt", handle_struct, bnobt_hfld, NULL }, { TYP_CNTBT, "cntbt", handle_struct, cntbt_hfld, NULL }, { TYP_RMAPBT, NULL }, + { TYP_REFCBT, NULL }, { TYP_DATA, "data", handle_block, NULL, NULL }, { TYP_DIR2, "dir2", handle_struct, dir2_hfld, NULL }, { TYP_DQBLK, "dqblk", handle_struct, dqblk_hfld, NULL }, @@ -91,6 +92,8 @@ static const typ_t __typtab_crc[] = { &xfs_allocbt_buf_ops }, { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, &xfs_rmapbt_buf_ops }, + { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld, + &xfs_refcountbt_buf_ops }, { TYP_DATA, "data", handle_block, NULL, NULL }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops }, @@ -129,6 +132,8 @@ static const typ_t __typtab_spcrc[] = { &xfs_allocbt_buf_ops }, { TYP_RMAPBT, "rmapbt", handle_struct, rmapbt_crc_hfld, &xfs_rmapbt_buf_ops }, + { TYP_REFCBT, "refcntbt", handle_struct, refcbt_crc_hfld, + &xfs_refcountbt_buf_ops }, { TYP_DATA, "data", handle_block, NULL, NULL }, { TYP_DIR2, "dir3", handle_struct, dir3_hfld, &xfs_dir3_db_buf_ops }, diff --git a/db/type.h b/db/type.h index 1bef8e6..998f755 100644 --- a/db/type.h +++ b/db/type.h @@ -24,7 +24,7 @@ struct field; typedef enum typnm { TYP_AGF, TYP_AGFL, TYP_AGI, TYP_ATTR, TYP_BMAPBTA, - TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_RMAPBT, TYP_DATA, + TYP_BMAPBTD, TYP_BNOBT, TYP_CNTBT, TYP_RMAPBT, TYP_REFCBT, TYP_DATA, TYP_DIR2, TYP_DQBLK, TYP_INOBT, TYP_INODATA, TYP_INODE, TYP_LOG, TYP_RTBITMAP, TYP_RTSUMMARY, TYP_SB, TYP_SYMLINK, TYP_TEXT, TYP_FINOBT, TYP_NONE diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index a380f78..b6d2f64 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -673,8 +673,8 @@ If no argument is given, show the current data type. The possible data types are: .BR agf ", " agfl ", " agi ", " attr ", " bmapbta ", " bmapbtd , .BR bnobt ", " cntbt ", " data ", " dir ", " dir2 ", " dqblk , -.BR inobt ", " inode ", " log ", " rmapbt ", " rtbitmap ", " rtsummary , -.BR sb ", " symlink " and " text . +.BR inobt ", " inode ", " log ", " refcntbt ", " rmapbt ", " rtbitmap , +.BR rtsummary ", " sb ", " symlink " and " text . See the TYPES section below for more information on these data types. .TP .BI "uuid [" uuid " | " generate " | " rewrite " | " restore ] @@ -1658,6 +1658,49 @@ use .BR xfs_logprint (8) instead. .TP +.B refcntbt +There is one set of filesystem blocks forming the reference count Btree for +each allocation group. The root block of this Btree is designated by the +.B refcntroot +field in the corresponding AGF block. The blocks are linked to sibling left +and right blocks at each level, as well as by pointers from parent to child +blocks. Each block has the following fields: +.RS 1.4i +.PD 0 +.TP 1.2i +.B magic +REFC block magic number, 0x52334643 ('R3FC'). +.TP +.B level +level number of this block, 0 is a leaf. +.TP +.B numrecs +number of data entries in the block. +.TP +.B leftsib +left (logically lower) sibling block, 0 if none. +.TP +.B rightsib +right (logically higher) sibling block, 0 if none. +.TP +.B recs +[leaf blocks only] array of reference count records. Each record contains +.BR startblock , +.BR blockcount , +and +.BR refcount . +.TP +.B keys +[non-leaf blocks only] array of key records. These are the first value +of each block in the level below this one. Each record contains +.BR startblock . +.TP +.B ptrs +[non-leaf blocks only] array of child block pointers. Each pointer is a +block number within the allocation group to the next level in the Btree. +.PD +.RE +.TP .B rmapbt There is one set of filesystem blocks forming the reverse mapping Btree for each allocation group. The root block of this Btree is designated by the From darrick.wong@oracle.com Thu Jun 16 20:42:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6490B82AF for ; Thu, 16 Jun 2016 20:42:35 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 183498F804C for ; Thu, 16 Jun 2016 18:42:35 -0700 (PDT) X-ASG-Debug-ID: 1466127752-04bdf01e10965b0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id cEWDF4Nr8s4ULLxa (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:32 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1gSFf022690 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:42:28 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1gSuZ007881 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:42:28 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1gSTa002754; Fri, 17 Jun 2016 01:42:28 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:27 -0700 Subject: [PATCH 111/145] xfs_db: add support for checking the refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 111/145] xfs_db: add support for checking the refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:26 -0700 Message-ID: <146612774650.16048.1340535669886062716.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127752 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8007 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Do some basic checks of the refcount btree. xfs_repair will have to check that the reference counts match the various bmbt mappings. Signed-off-by: Darrick J. Wong --- db/check.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 128 insertions(+), 8 deletions(-) diff --git a/db/check.c b/db/check.c index 2964b5f..3b17585 100644 --- a/db/check.c +++ b/db/check.c @@ -44,7 +44,8 @@ typedef enum { DBM_FREE1, DBM_FREE2, DBM_FREELIST, DBM_INODE, DBM_LOG, DBM_MISSING, DBM_QUOTA, DBM_RTBITMAP, DBM_RTDATA, DBM_RTFREE, DBM_RTSUM, DBM_SB, - DBM_SYMLINK, DBM_BTFINO, DBM_BTRMAP, + DBM_SYMLINK, DBM_BTFINO, DBM_BTRMAP, DBM_BTREFC, + DBM_RLDATA, DBM_NDBM } dbm_t; @@ -52,7 +53,8 @@ typedef struct inodata { struct inodata *next; nlink_t link_set; nlink_t link_add; - char isdir; + char isdir:1; + char isreflink:1; char security; char ilist; xfs_ino_t ino; @@ -172,6 +174,8 @@ static const char *typename[] = { "symlink", "btfino", "btrmap", + "btrefcnt", + "rldata", NULL }; static int verbose; @@ -229,7 +233,8 @@ static int blocktrash_f(int argc, char **argv); static int blockuse_f(int argc, char **argv); static int check_blist(xfs_fsblock_t bno); static void check_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, - xfs_extlen_t len, dbm_t type); + xfs_extlen_t len, dbm_t type, + int ignore_reflink); static int check_inomap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, xfs_ino_t c_ino); static void check_linkcounts(xfs_agnumber_t agno); @@ -353,6 +358,9 @@ static void scanfunc_fino(struct xfs_btree_block *block, int level, static void scanfunc_rmap(struct xfs_btree_block *block, int level, struct xfs_agf *agf, xfs_agblock_t bno, int isroot); +static void scanfunc_refcnt(struct xfs_btree_block *block, int level, + struct xfs_agf *agf, xfs_agblock_t bno, + int isroot); static void set_dbmap(xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, dbm_t type, xfs_agnumber_t c_agno, xfs_agblock_t c_agbno); @@ -1055,6 +1063,7 @@ blocktrash_f( (1 << DBM_SYMLINK) | (1 << DBM_BTFINO) | (1 << DBM_BTRMAP) | + (1 << DBM_BTREFC) | (1 << DBM_SB); while ((c = getopt(argc, argv, "0123n:o:s:t:x:y:z")) != EOF) { switch (c) { @@ -1291,18 +1300,25 @@ check_dbmap( xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t len, - dbm_t type) + dbm_t type, + int ignore_reflink) { xfs_extlen_t i; char *p; + dbm_t d; for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { + d = (dbm_t)*p; + if (ignore_reflink && (d == DBM_UNKNOWN || d == DBM_DATA || + d == DBM_RLDATA)) + continue; if ((dbm_t)*p != type) { - if (!sflag || CHECK_BLISTA(agno, agbno + i)) + if (!sflag || CHECK_BLISTA(agno, agbno + i)) { dbprintf(_("block %u/%u expected type %s got " "%s\n"), agno, agbno + i, typename[type], typename[(dbm_t)*p]); + } error++; } } @@ -1336,7 +1352,7 @@ check_inomap( return 0; } for (i = 0, rval = 1, idp = &inomap[agno][agbno]; i < len; i++, idp++) { - if (*idp) { + if (*idp && !(*idp)->isreflink) { if (!sflag || (*idp)->ilist || CHECK_BLISTA(agno, agbno + i)) dbprintf(_("block %u/%u claimed by inode %lld, " @@ -1542,6 +1558,26 @@ check_rrange( return 1; } +/* + * We don't check the accuracy of reference counts -- all we do is ensure + * that a data block never crosses with non-data blocks. repair can check + * those kinds of things. + * + * So with that in mind, if we're setting a block to be data or rldata, + * don't complain so long as the block is currently unknown, data, or rldata. + * Don't let blocks downgrade from rldata -> data. + */ +static bool +is_reflink( + dbm_t type2) +{ + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return false; + if (type2 == DBM_DATA || type2 == DBM_RLDATA) + return true; + return false; +} + static void check_set_dbmap( xfs_agnumber_t agno, @@ -1561,10 +1597,15 @@ check_set_dbmap( agbno, agbno + len - 1, c_agno, c_agbno); return; } - check_dbmap(agno, agbno, len, type1); + check_dbmap(agno, agbno, len, type1, is_reflink(type2)); mayprint = verbose | blist_size; for (i = 0, p = &dbmap[agno][agbno]; i < len; i++, p++) { - *p = (char)type2; + if (*p == DBM_RLDATA && type2 == DBM_DATA) + ; /* do nothing */ + if (*p == DBM_DATA && type2 == DBM_DATA) + *p = (char)DBM_RLDATA; + else + *p = (char)type2; if (mayprint && (verbose || CHECK_BLISTA(agno, agbno + i))) dbprintf(_("setting block %u/%u to %s\n"), agno, agbno + i, typename[type2]); @@ -2804,6 +2845,7 @@ process_inode( break; } + id->isreflink = !!(xino.i_d.di_flags2 & XFS_DIFLAG2_REFLINK); setlink_inode(id, VFS_I(&xino)->i_nlink, type == DBM_DIR, security); switch (xino.i_d.di_format) { @@ -3910,6 +3952,12 @@ scan_ag( be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]), 1, scanfunc_rmap, TYP_RMAPBT); } + if (agf->agf_refcount_root) { + scan_sbtree(agf, + be32_to_cpu(agf->agf_refcount_root), + be32_to_cpu(agf->agf_refcount_level), + 1, scanfunc_refcnt, TYP_REFCBT); + } scan_sbtree(agf, be32_to_cpu(agi->agi_root), be32_to_cpu(agi->agi_level), @@ -4733,6 +4781,78 @@ scanfunc_rmap( } static void +scanfunc_refcnt( + struct xfs_btree_block *block, + int level, + struct xfs_agf *agf, + xfs_agblock_t bno, + int isroot) +{ + xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); + int i; + xfs_refcount_ptr_t *pp; + struct xfs_refcount_rec *rp; + xfs_agblock_t lastblock; + + if (be32_to_cpu(block->bb_magic) != XFS_REFC_CRC_MAGIC) { + dbprintf(_("bad magic # %#x in refcntbt block %u/%u\n"), + be32_to_cpu(block->bb_magic), seqno, bno); + serious_error++; + return; + } + if (be16_to_cpu(block->bb_level) != level) { + if (!sflag) + dbprintf(_("expected level %d got %d in refcntbt block " + "%u/%u\n"), + level, be16_to_cpu(block->bb_level), seqno, bno); + error++; + } + set_dbmap(seqno, bno, 1, DBM_BTREFC, seqno, bno); + if (level == 0) { + if (be16_to_cpu(block->bb_numrecs) > mp->m_refc_mxr[0] || + (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_refc_mnr[0])) { + dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in " + "refcntbt block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), mp->m_refc_mnr[0], + mp->m_refc_mxr[0], seqno, bno); + serious_error++; + return; + } + rp = XFS_REFCOUNT_REC_ADDR(block, 1); + lastblock = 0; + for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { + set_dbmap(seqno, be32_to_cpu(rp[i].rc_startblock), + be32_to_cpu(rp[i].rc_blockcount), DBM_RLDATA, + seqno, bno); + if (be32_to_cpu(rp[i].rc_startblock) < lastblock) { + dbprintf(_( + "out-of-order refcnt btree record %d (%u %u) block %u/%u\n"), + i, be32_to_cpu(rp[i].rc_startblock), + be32_to_cpu(rp[i].rc_startblock), + be32_to_cpu(agf->agf_seqno), bno); + } else { + lastblock = be32_to_cpu(rp[i].rc_startblock) + + be32_to_cpu(rp[i].rc_blockcount); + } + } + return; + } + if (be16_to_cpu(block->bb_numrecs) > mp->m_refc_mxr[1] || + (isroot == 0 && be16_to_cpu(block->bb_numrecs) < mp->m_refc_mnr[1])) { + dbprintf(_("bad btree nrecs (%u, min=%u, max=%u) in refcntbt " + "block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), mp->m_refc_mnr[1], + mp->m_refc_mxr[1], seqno, bno); + serious_error++; + return; + } + pp = XFS_REFCOUNT_PTR_ADDR(block, 1, mp->m_refc_mxr[1]); + for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) + scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_refcnt, + TYP_REFCBT); +} + +static void set_dbmap( xfs_agnumber_t agno, xfs_agblock_t agbno, From darrick.wong@oracle.com Thu Jun 16 20:42:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5A2D28384 for ; Thu, 16 Jun 2016 20:42:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2A4468F804B for ; Thu, 16 Jun 2016 18:42:42 -0700 (PDT) X-ASG-Debug-ID: 1466127759-04cb6c5427583f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 3jQRGFg7X0Ys8qUi (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:40 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1gZCi022740 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:35 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gYEX002279 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:35 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gYak030475; Fri, 17 Jun 2016 01:42:34 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:34 -0700 Subject: [PATCH 112/145] xfs_db: metadump should copy the refcount btree too From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 112/145] xfs_db: metadump should copy the refcount btree too To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:32 -0700 Message-ID: <146612775267.16048.14038936933078418653.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127760 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2590 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach metadump to copy the refcount btree. Signed-off-by: Darrick J. Wong --- db/metadump.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/db/metadump.c b/db/metadump.c index 609a5d7..a98e951 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -615,6 +615,78 @@ copy_rmap_btree( return scan_btree(agno, root, levels, TYP_RMAPBT, agf, scanfunc_rmapbt); } +static int +scanfunc_refcntbt( + struct xfs_btree_block *block, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + int level, + typnm_t btype, + void *arg) +{ + xfs_refcount_ptr_t *pp; + int i; + int numrecs; + + if (level == 0) + return 1; + + numrecs = be16_to_cpu(block->bb_numrecs); + if (numrecs > mp->m_refc_mxr[1]) { + if (show_warnings) + print_warning("invalid numrecs (%u) in %s block %u/%u", + numrecs, typtab[btype].name, agno, agbno); + return 1; + } + + pp = XFS_REFCOUNT_PTR_ADDR(block, 1, mp->m_refc_mxr[1]); + for (i = 0; i < numrecs; i++) { + if (!valid_bno(agno, be32_to_cpu(pp[i]))) { + if (show_warnings) + print_warning("invalid block number (%u/%u) " + "in %s block %u/%u", + agno, be32_to_cpu(pp[i]), + typtab[btype].name, agno, agbno); + continue; + } + if (!scan_btree(agno, be32_to_cpu(pp[i]), level, btype, arg, + scanfunc_refcntbt)) + return 0; + } + return 1; +} + +static int +copy_refcount_btree( + xfs_agnumber_t agno, + struct xfs_agf *agf) +{ + xfs_agblock_t root; + int levels; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 1; + + root = be32_to_cpu(agf->agf_refcount_root); + levels = be32_to_cpu(agf->agf_refcount_level); + + /* validate root and levels before processing the tree */ + if (root == 0 || root > mp->m_sb.sb_agblocks) { + if (show_warnings) + print_warning("invalid block number (%u) in refcntbt " + "root in agf %u", root, agno); + return 1; + } + if (levels >= XFS_BTREE_MAXLEVELS) { + if (show_warnings) + print_warning("invalid level (%u) in refcntbt root " + "in agf %u", levels, agno); + return 1; + } + + return scan_btree(agno, root, levels, TYP_REFCBT, agf, scanfunc_refcntbt); +} + /* filename and extended attribute obfuscation routines */ struct name_ent { @@ -2525,6 +2597,8 @@ scan_ag( goto pop_out; if (!copy_rmap_btree(agno, agf)) goto pop_out; + if (!copy_refcount_btree(agno, agf)) + goto pop_out; } /* copy inode btrees and the inodes and their associated metadata */ From darrick.wong@oracle.com Thu Jun 16 20:42:44 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0DE268354 for ; Thu, 16 Jun 2016 20:42:44 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id D1F8E8F804B for ; Thu, 16 Jun 2016 18:42:43 -0700 (PDT) X-ASG-Debug-ID: 1466127762-04cbb01fec6a6b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 0EZvhIrb2GLZEABL (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:42 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1getu010235 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:42:41 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1geO1008095 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:40 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1geIG030558; Fri, 17 Jun 2016 01:42:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:40 -0700 Subject: [PATCH 113/145] xfs_db: deal with the CoW extent size hint From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 113/145] xfs_db: deal with the CoW extent size hint To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:38 -0700 Message-ID: <146612775876.16048.7337361121630211530.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127762 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1080 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Display the CoW extent hint size when dumping inodes. Signed-off-by: Darrick J. Wong --- db/inode.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/db/inode.c b/db/inode.c index 702cdf8..cac19fc 100644 --- a/db/inode.c +++ b/db/inode.c @@ -172,12 +172,16 @@ const field_t inode_v3_flds[] = { { "change_count", FLDT_UINT64D, OI(COFF(changecount)), C1, 0, TYP_NONE }, { "lsn", FLDT_UINT64X, OI(COFF(lsn)), C1, 0, TYP_NONE }, { "flags2", FLDT_UINT64X, OI(COFF(flags2)), C1, 0, TYP_NONE }, + { "cowextsize", FLDT_EXTLEN, OI(COFF(cowextsize)), C1, 0, TYP_NONE }, { "crtime", FLDT_TIMESTAMP, OI(COFF(crtime)), C1, 0, TYP_NONE }, { "inumber", FLDT_INO, OI(COFF(ino)), C1, 0, TYP_NONE }, { "uuid", FLDT_UUID, OI(COFF(uuid)), C1, 0, TYP_NONE }, { "reflink", FLDT_UINT1, OI(COFF(flags2) + bitsz(__uint64_t) - XFS_DIFLAG2_REFLINK_BIT-1), C1, 0, TYP_NONE }, + { "cowextsz", FLDT_UINT1, + OI(COFF(flags2) + bitsz(__uint64_t) - XFS_DIFLAG2_COWEXTSIZE_BIT-1), C1, + 0, TYP_NONE }, { NULL } }; From darrick.wong@oracle.com Thu Jun 16 20:42:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8DD2C8360 for ; Thu, 16 Jun 2016 20:42:54 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 05E77AC004 for ; Thu, 16 Jun 2016 18:42:53 -0700 (PDT) X-ASG-Debug-ID: 1466127771-04cbb01fed6a6e0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id rlMx7DIAU9iLeKvg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1gl3x022855 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:42:48 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1gl1c008182 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:47 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gki1025209; Fri, 17 Jun 2016 01:42:46 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:46 -0700 Subject: [PATCH 114/145] xfs_growfs: report the presence of the reflink feature From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 114/145] xfs_growfs: report the presence of the reflink feature To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:44 -0700 Message-ID: <146612776485.16048.12300889530409014364.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127772 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2529 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Report the presence of the reflink feature in xfs_info. Signed-off-by: Darrick J. Wong --- growfs/xfs_growfs.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/growfs/xfs_growfs.c b/growfs/xfs_growfs.c index 2b46480..a294e14 100644 --- a/growfs/xfs_growfs.c +++ b/growfs/xfs_growfs.c @@ -59,12 +59,14 @@ report_info( int ftype_enabled, int finobt_enabled, int spinodes, - int rmapbt_enabled) + int rmapbt_enabled, + int reflink_enabled) { printf(_( "meta-data=%-22s isize=%-6u agcount=%u, agsize=%u blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" " =%-22s crc=%-8u finobt=%u spinodes=%u rmapbt=%u\n" + " =%-22s reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" @@ -75,6 +77,7 @@ report_info( mntpoint, geo.inodesize, geo.agcount, geo.agblocks, "", geo.sectsize, attrversion, projid32bit, "", crcs_enabled, finobt_enabled, spinodes, rmapbt_enabled, + "", reflink_enabled, "", geo.blocksize, (unsigned long long)geo.datablocks, geo.imaxpct, "", geo.sunit, geo.swidth, @@ -129,6 +132,7 @@ main(int argc, char **argv) int finobt_enabled; /* free inode btree */ int spinodes; int rmapbt_enabled; + int reflink_enabled; progname = basename(argv[0]); setlocale(LC_ALL, ""); @@ -253,12 +257,13 @@ main(int argc, char **argv) finobt_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_FINOBT ? 1 : 0; spinodes = geo.flags & XFS_FSOP_GEOM_FLAGS_SPINODES ? 1 : 0; rmapbt_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_RMAPBT ? 1 : 0; + reflink_enabled = geo.flags & XFS_FSOP_GEOM_FLAGS_REFLINK ? 1 : 0; if (nflag) { report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, attrversion, projid32bit, crcs_enabled, ci, ftype_enabled, finobt_enabled, spinodes, - rmapbt_enabled); + rmapbt_enabled, reflink_enabled); exit(0); } @@ -296,7 +301,8 @@ main(int argc, char **argv) report_info(geo, datadev, isint, logdev, rtdev, lazycount, dirversion, logversion, attrversion, projid32bit, crcs_enabled, ci, ftype_enabled, - finobt_enabled, spinodes, rmapbt_enabled); + finobt_enabled, spinodes, rmapbt_enabled, + reflink_enabled); ddsize = xi.dsize; dlsize = ( xi.logBBsize? xi.logBBsize : From darrick.wong@oracle.com Thu Jun 16 20:42:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6BDC28397 for ; Thu, 16 Jun 2016 20:42:57 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2B939304039 for ; Thu, 16 Jun 2016 18:42:57 -0700 (PDT) X-ASG-Debug-ID: 1466127774-04bdf01e15965f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id trq7ruS5xDWqU5t8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:42:54 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1gruY022879 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:42:53 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1grC9008272 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:42:53 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1gqth002873; Fri, 17 Jun 2016 01:42:52 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:52 -0700 Subject: [PATCH 115/145] xfs_io: bmap should support querying CoW fork, shared blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 115/145] xfs_io: bmap should support querying CoW fork, shared blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:50 -0700 Message-ID: <146612777093.16048.15058864646971176390.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127774 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5701 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach the bmap command to report shared and delayed allocation extents, and to be able to query the CoW fork. Signed-off-by: Darrick J. Wong --- io/bmap.c | 43 ++++++++++++++++++++++++++++++++++--------- man/man8/xfs_bmap.8 | 14 ++++++++++++++ man/man8/xfs_io.8 | 2 +- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/io/bmap.c b/io/bmap.c index 04d04c7..0834cdd 100644 --- a/io/bmap.c +++ b/io/bmap.c @@ -41,7 +41,9 @@ bmap_help(void) " Holes are marked by replacing the startblock..endblock with 'hole'.\n" " All the file offsets and disk blocks are in units of 512-byte blocks.\n" " -a -- prints the attribute fork map instead of the data fork.\n" +" -c -- prints the copy-on-write fork map instead of the data fork.\n" " -d -- suppresses a DMAPI read event, offline portions shown as holes.\n" +" -e -- print delayed allocation extents.\n" " -l -- also displays the length of each extent in 512-byte blocks.\n" " -n -- query n extents.\n" " -p -- obtain all unwritten extents as well (w/ -v show which are unwritten.)\n" @@ -75,6 +77,7 @@ bmap_f( int loop = 0; int flg = 0; int aflag = 0; + int cflag = 0; int lflag = 0; int nflag = 0; int pflag = 0; @@ -85,12 +88,19 @@ bmap_f( int c; int egcnt; - while ((c = getopt(argc, argv, "adln:pv")) != EOF) { + while ((c = getopt(argc, argv, "acdeln:pv")) != EOF) { switch (c) { case 'a': /* Attribute fork. */ bmv_iflags |= BMV_IF_ATTRFORK; aflag = 1; break; + case 'c': /* CoW fork. */ + bmv_iflags |= BMV_IF_COWFORK | BMV_IF_DELALLOC; + cflag = 1; + break; + case 'e': + bmv_iflags |= BMV_IF_DELALLOC; + break; case 'l': /* list number of blocks with each extent */ lflag = 1; break; @@ -113,7 +123,7 @@ bmap_f( return command_usage(&bmap_cmd); } } - if (aflag) + if (aflag || cflag) bmv_iflags &= ~(BMV_IF_PREALLOC|BMV_IF_NO_DMAPI_READ); if (vflag) { @@ -271,13 +281,14 @@ bmap_f( #define MINRANGE_WIDTH 16 #define MINAG_WIDTH 2 #define MINTOT_WIDTH 5 -#define NFLG 5 /* count of flags */ -#define FLG_NULL 000000 /* Null flag */ -#define FLG_PRE 010000 /* Unwritten extent */ -#define FLG_BSU 001000 /* Not on begin of stripe unit */ -#define FLG_ESU 000100 /* Not on end of stripe unit */ -#define FLG_BSW 000010 /* Not on begin of stripe width */ -#define FLG_ESW 000001 /* Not on end of stripe width */ +#define NFLG 6 /* count of flags */ +#define FLG_NULL 0000000 /* Null flag */ +#define FLG_SHARED 0100000 /* shared extent */ +#define FLG_PRE 0010000 /* Unwritten extent */ +#define FLG_BSU 0001000 /* Not on begin of stripe unit */ +#define FLG_ESU 0000100 /* Not on end of stripe unit */ +#define FLG_BSW 0000010 /* Not on begin of stripe width */ +#define FLG_ESW 0000001 /* Not on end of stripe width */ int agno; off64_t agoff, bbperag; int foff_w, boff_w, aoff_w, tot_w, agno_w; @@ -348,6 +359,10 @@ bmap_f( if (map[i + 1].bmv_oflags & BMV_OF_PREALLOC) { flg |= FLG_PRE; } + if (map[i + 1].bmv_oflags & BMV_OF_SHARED) + flg |= FLG_SHARED; + if (map[i + 1].bmv_oflags & BMV_OF_DELALLOC) + map[i + 1].bmv_block = -2; /* * If striping enabled, determine if extent starts/ends * on a stripe unit boundary. @@ -380,6 +395,14 @@ bmap_f( agno_w, "", aoff_w, "", tot_w, (long long)map[i+1].bmv_length); + } else if (map[i + 1].bmv_block == -2) { + printf("%4d: %-*s %-*s %*s %-*s %*lld\n", + i, + foff_w, rbuf, + boff_w, _("delalloc"), + agno_w, "", + aoff_w, "", + tot_w, (long long)map[i+1].bmv_length); } else { snprintf(bbuf, sizeof(bbuf), "%lld..%lld", (long long) map[i + 1].bmv_block, @@ -411,6 +434,8 @@ bmap_f( } if ((flg || pflag) && vflag > 1) { printf(_(" FLAG Values:\n")); + printf(_(" %*.*o Shared extent\n"), + NFLG+1, NFLG+1, FLG_SHARED); printf(_(" %*.*o Unwritten preallocated extent\n"), NFLG+1, NFLG+1, FLG_PRE); printf(_(" %*.*o Doesn't begin on stripe unit\n"), diff --git a/man/man8/xfs_bmap.8 b/man/man8/xfs_bmap.8 index e196559..098cfae 100644 --- a/man/man8/xfs_bmap.8 +++ b/man/man8/xfs_bmap.8 @@ -36,6 +36,10 @@ no matter what the filesystem's block size is. If this option is specified, information about the file's attribute fork is printed instead of the default data fork. .TP +.B \-c +If this option is specified, information about the file's +copy on write fork is printed instead of the default data fork. +.TP .B \-d If portions of the file have been migrated offline by a DMAPI application, a DMAPI read event will be generated to @@ -45,6 +49,16 @@ printed. However if the option is used, no DMAPI read event will be generated for a DMAPI file and offline portions will be reported as holes. .TP +.B \-e +If this option is used, +.B xfs_bmap +obtains all delayed allocation extents, and does not flush dirty pages +to disk before querying extent data. With the +.B \-v +option, the +.I flags +column will show which extents have not yet been allocated. +.TP .B \-l If this option is used, then .IP diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index b0300bb..6c45c37 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -256,7 +256,7 @@ See the .B pwrite command. .TP -.BI "bmap [ \-adlpv ] [ \-n " nx " ]" +.BI "bmap [ \-acdelpv ] [ \-n " nx " ]" Prints the block mapping for the current open file. Refer to the .BR xfs_bmap (8) manual page for complete documentation. From darrick.wong@oracle.com Thu Jun 16 20:43:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2FFF2836F for ; Thu, 16 Jun 2016 20:43:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id E3F24304039 for ; Thu, 16 Jun 2016 18:43:04 -0700 (PDT) X-ASG-Debug-ID: 1466127781-04bdf01e1096600001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id UaD3IAjnC4HBR9vA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1h0X1010427 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:00 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gxsJ002690 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:42:59 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1gwE2030602; Fri, 17 Jun 2016 01:42:59 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:42:58 -0700 Subject: [PATCH 116/145] xfs_io: get and set the CoW extent size hint From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 116/145] xfs_io: get and set the CoW extent size hint To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:42:57 -0700 Message-ID: <146612777707.16048.16381607370131674150.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127781 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7903 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.50 X-Barracuda-Spam-Status: No, SCORE=0.50 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_MV0713, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.50 BSF_SC0_MV0713 Custom rule MV0713 Enable administrators to get or set the CoW extent size hint. Signed-off-by: Darrick J. Wong --- io/attr.c | 8 ++- io/open.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++ man/man8/xfs_io.8 | 16 +++++ 3 files changed, 189 insertions(+), 1 deletion(-) diff --git a/io/attr.c b/io/attr.c index 0186b1d..13bec73 100644 --- a/io/attr.c +++ b/io/attr.c @@ -48,9 +48,11 @@ static struct xflags { { FS_XFLAG_NODEFRAG, "f", "no-defrag" }, { FS_XFLAG_FILESTREAM, "S", "filestream" }, { FS_XFLAG_DAX, "x", "dax" }, + { FS_XFLAG_REFLINK, "R", "reflink" }, + { FS_XFLAG_COWEXTSIZE, "C", "cowextsize" }, { 0, NULL, NULL } }; -#define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSx" +#define CHATTR_XFLAG_LIST "r"/*p*/"iasAdtPneEfSxRC" static void lsattr_help(void) @@ -75,6 +77,8 @@ lsattr_help(void) " f -- do not include this file when defragmenting the filesystem\n" " S -- enable filestreams allocator for this directory\n" " x -- Use direct access (DAX) for data in this file\n" +" R -- file data blocks may be shared with another file\n" +" C -- for files with shared blocks, observe the inode CoW extent size value\n" "\n" " Options:\n" " -R -- recursively descend (useful when current file is a directory)\n" @@ -111,6 +115,8 @@ chattr_help(void) " +/-f -- set/clear the no-defrag flag\n" " +/-S -- set/clear the filestreams allocator flag\n" " +/-x -- set/clear the direct access (DAX) flag\n" +" +/-R -- set/clear the reflink flag\n" +" +/-C -- set/clear the CoW extent-size flag\n" " Note1: user must have certain capabilities to modify immutable/append-only.\n" " Note2: immutable/append-only files cannot be deleted; removing these files\n" " requires the immutable/append-only flag to be cleared first.\n" diff --git a/io/open.c b/io/open.c index 2303527..1e682a4 100644 --- a/io/open.c +++ b/io/open.c @@ -46,8 +46,10 @@ static cmdinfo_t chproj_cmd; static cmdinfo_t lsproj_cmd; static cmdinfo_t extsize_cmd; static cmdinfo_t inode_cmd; +static cmdinfo_t cowextsize_cmd; static prid_t prid; static long extsize; +static long cowextsize; off64_t filesize(void) @@ -125,6 +127,7 @@ stat_f( printxattr(fsx.fsx_xflags, verbose, 0, file->name, 1, 1); printf(_("fsxattr.projid = %u\n"), fsx.fsx_projid); printf(_("fsxattr.extsize = %u\n"), fsx.fsx_extsize); + printf(_("fsxattr.cowextsize = %u\n"), fsx.fsx_cowextsize); printf(_("fsxattr.nextents = %u\n"), fsx.fsx_nextents); printf(_("fsxattr.naextents = %u\n"), fsxa.fsx_nextents); } @@ -696,6 +699,158 @@ extsize_f( return 0; } +static void +cowextsize_help(void) +{ + printf(_( +"\n" +" report or modify preferred CoW extent size (in bytes) for the current path\n" +"\n" +" -R -- recursively descend (useful when current path is a directory)\n" +" -D -- recursively descend, only modifying cowextsize on directories\n" +"\n")); +} + +static int +get_cowextsize(const char *path, int fd) +{ + struct fsxattr fsx; + + if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) { + printf("%s: XFS_IOC_FSGETXATTR %s: %s\n", + progname, path, strerror(errno)); + return 0; + } + printf("[%u] %s\n", fsx.fsx_cowextsize, path); + return 0; +} + +static int +set_cowextsize(const char *path, int fd, long extsz) +{ + struct fsxattr fsx; + struct stat64 stat; + + if (fstat64(fd, &stat) < 0) { + perror("fstat64"); + return 0; + } + if ((xfsctl(path, fd, XFS_IOC_FSGETXATTR, &fsx)) < 0) { + printf("%s: XFS_IOC_FSGETXATTR %s: %s\n", + progname, path, strerror(errno)); + return 0; + } + + if (S_ISREG(stat.st_mode) || S_ISDIR(stat.st_mode)) { + fsx.fsx_xflags |= FS_XFLAG_COWEXTSIZE; + } else { + printf(_("invalid target file type - file %s\n"), path); + return 0; + } + fsx.fsx_cowextsize = extsz; + + if ((xfsctl(path, fd, XFS_IOC_FSSETXATTR, &fsx)) < 0) { + printf("%s: XFS_IOC_FSSETXATTR %s: %s\n", + progname, path, strerror(errno)); + return 0; + } + + return 0; +} + +static int +get_cowextsize_callback( + const char *path, + const struct stat *stat, + int status, + struct FTW *data) +{ + int fd; + + if (recurse_dir && !S_ISDIR(stat->st_mode)) + return 0; + + fd = open(path, O_RDONLY); + if (fd < 0) { + fprintf(stderr, _("%s: cannot open %s: %s\n"), + progname, path, strerror(errno)); + } else { + get_cowextsize(path, fd); + close(fd); + } + return 0; +} + +static int +set_cowextsize_callback( + const char *path, + const struct stat *stat, + int status, + struct FTW *data) +{ + int fd; + + if (recurse_dir && !S_ISDIR(stat->st_mode)) + return 0; + + fd = open(path, O_RDONLY); + if (fd < 0) { + fprintf(stderr, _("%s: cannot open %s: %s\n"), + progname, path, strerror(errno)); + } else { + set_cowextsize(path, fd, cowextsize); + close(fd); + } + return 0; +} + +static int +cowextsize_f( + int argc, + char **argv) +{ + size_t blocksize, sectsize; + int c; + + recurse_all = recurse_dir = 0; + init_cvtnum(&blocksize, §size); + while ((c = getopt(argc, argv, "DR")) != EOF) { + switch (c) { + case 'D': + recurse_all = 0; + recurse_dir = 1; + break; + case 'R': + recurse_all = 1; + recurse_dir = 0; + break; + default: + return command_usage(&cowextsize_cmd); + } + } + + if (optind < argc) { + cowextsize = (long)cvtnum(blocksize, sectsize, argv[optind]); + if (cowextsize < 0) { + printf(_("non-numeric cowextsize argument -- %s\n"), + argv[optind]); + return 0; + } + } else { + cowextsize = -1; + } + + if (recurse_all || recurse_dir) + nftw(file->name, (extsize >= 0) ? + set_cowextsize_callback : get_cowextsize_callback, + 100, FTW_PHYS | FTW_MOUNT | FTW_DEPTH); + else if (cowextsize >= 0) + set_cowextsize(file->name, file->fd, cowextsize); + else + get_cowextsize(file->name, file->fd); + return 0; +} + static int statfs_f( int argc, @@ -964,6 +1119,16 @@ open_init(void) _("Query inode number usage in the filesystem"); inode_cmd.help = inode_help; + cowextsize_cmd.name = "cowextsize"; + cowextsize_cmd.cfunc = cowextsize_f; + cowextsize_cmd.args = _("[-D | -R] [cowextsize]"); + cowextsize_cmd.argmin = 0; + cowextsize_cmd.argmax = -1; + cowextsize_cmd.flags = CMD_NOMAP_OK; + cowextsize_cmd.oneline = + _("get/set preferred CoW extent size (in bytes) for the open file"); + cowextsize_cmd.help = cowextsize_help; + add_command(&open_cmd); add_command(&stat_cmd); add_command(&close_cmd); @@ -972,4 +1137,5 @@ open_init(void) add_command(&lsproj_cmd); add_command(&extsize_cmd); add_command(&inode_cmd); + add_command(&cowextsize_cmd); } diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index 6c45c37..cc70b7c 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -283,6 +283,22 @@ The should be specified in bytes, or using one of the usual units suffixes (k, m, g, b, etc). The extent size is always reported in units of bytes. .TP +.BI "cowextsize [ \-R | \-D ] [ " value " ]" +Display and/or modify the preferred copy-on-write extent size used +when allocating space for the currently open file. If the +.B \-R +option is specified, a recursive descent is performed +for all directory entries below the currently open file +.RB ( \-D +can be used to restrict the output to directories only). +If the target file is a directory, then the inherited CoW extent size +is set for that directory (new files created in that directory +inherit that CoW extent size). +The +.I value +should be specified in bytes, or using one of the usual units suffixes +(k, m, g, b, etc). The extent size is always reported in units of bytes. +.TP .BI "allocsp " size " 0" Sets the size of the file to .I size From darrick.wong@oracle.com Thu Jun 16 20:43:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 396A383A9 for ; Thu, 16 Jun 2016 20:43:09 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id F05658F804B for ; Thu, 16 Jun 2016 18:43:08 -0700 (PDT) X-ASG-Debug-ID: 1466127787-04cb6c542758410001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id K3A4OZHZPTJIwWYU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1h5B7010656 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:06 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1h5wC015509 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:05 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1h4dD025366; Fri, 17 Jun 2016 01:43:05 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:04 -0700 Subject: [PATCH 117/145] xfs_io: add refcount+bmap error injection types From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 117/145] xfs_io: add refcount+bmap error injection types To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:03 -0700 Message-ID: <146612778322.16048.5833598458395784088.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127787 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1028 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Add refcount and bmap deferred finish to the types of errors we can inject. Signed-off-by: Darrick J. Wong --- io/inject.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/io/inject.c b/io/inject.c index 16ac925..56642b8 100644 --- a/io/inject.c +++ b/io/inject.c @@ -78,7 +78,13 @@ error_tag(char *name) { XFS_ERRTAG_FREE_EXTENT, "free_extent" }, #define XFS_ERRTAG_RMAP_FINISH_ONE 23 { XFS_ERRTAG_RMAP_FINISH_ONE, "rmap_finish_one" }, -#define XFS_ERRTAG_MAX 24 +#define XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE 24 + { XFS_ERRTAG_REFCOUNT_CONTINUE_UPDATE, "refcount_continue_update" }, +#define XFS_ERRTAG_REFCOUNT_FINISH_ONE 25 + { XFS_ERRTAG_REFCOUNT_FINISH_ONE, "refcount_finish_one" }, +#define XFS_ERRTAG_BMAP_FINISH_ONE 26 + { XFS_ERRTAG_BMAP_FINISH_ONE, "bmap_finish_one" }, +#define XFS_ERRTAG_MAX 27 { XFS_ERRTAG_MAX, NULL } }; int count; From darrick.wong@oracle.com Thu Jun 16 20:43:14 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8D4468375 for ; Thu, 16 Jun 2016 20:43:14 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5E3938F804C for ; Thu, 16 Jun 2016 18:43:14 -0700 (PDT) X-ASG-Debug-ID: 1466127793-04cbb01fed6a720001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id qjbfodgUUvyfRtMn (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:13 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1hBdm010813 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:43:12 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1hBJL009004 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:11 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hA9g030795; Fri, 17 Jun 2016 01:43:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:10 -0700 Subject: [PATCH 118/145] xfs_logprint: support cowextsize reporting in log contents From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 118/145] xfs_logprint: support cowextsize reporting in log contents To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:09 -0700 Message-ID: <146612778940.16048.13738003970479416066.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127793 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1161 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- logprint/log_misc.c | 4 ++++ logprint/log_print_all.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/logprint/log_misc.c b/logprint/log_misc.c index 479fc14..f6488d9 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -513,6 +513,10 @@ xlog_print_trans_inode_core( ip->di_dmstate); printf(_("flags 0x%x gen 0x%x\n"), ip->di_flags, ip->di_gen); + if (ip->di_version == 3) { + printf(_("flags2 0x%llx cowextsize 0x%x\n"), + (unsigned long long)ip->di_flags2, ip->di_cowextsize); + } } void diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index 0fe354b..46952c4 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -272,6 +272,10 @@ xlog_recover_print_inode_core( "gen:%d\n"), (int)di->di_forkoff, di->di_dmevmask, (int)di->di_dmstate, (int)di->di_flags, di->di_gen); + if (di->di_version == 3) { + printf(_("flags2 0x%llx cowextsize 0x%x\n"), + (unsigned long long)di->di_flags2, di->di_cowextsize); + } } STATIC void From darrick.wong@oracle.com Thu Jun 16 20:43:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 1CCD28341 for ; Thu, 16 Jun 2016 20:43:22 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id E13138F804B for ; Thu, 16 Jun 2016 18:43:21 -0700 (PDT) X-ASG-Debug-ID: 1466127799-04cb6c542658440001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 1wUcHGp2vl0vBU3X (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:20 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1hIVJ023614 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:18 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hHf6003493 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:18 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hHZx030905; Fri, 17 Jun 2016 01:43:17 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:16 -0700 Subject: [PATCH 119/145] xfs_logprint: support refcount redo items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 119/145] xfs_logprint: support refcount redo items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:15 -0700 Message-ID: <146612779547.16048.11591159287269642096.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127800 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6205 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Print reference count update redo items. Signed-off-by: Darrick J. Wong --- logprint/log_misc.c | 11 +++ logprint/log_print_all.c | 12 ++++ logprint/log_redo.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++ logprint/logprint.h | 5 ++ 4 files changed, 179 insertions(+) diff --git a/logprint/log_misc.c b/logprint/log_misc.c index f6488d9..5389b72 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -1008,6 +1008,17 @@ xlog_print_record( be32_to_cpu(op_head->oh_len)); break; } + case XFS_LI_CUI: { + skip = xlog_print_trans_cui(&ptr, + be32_to_cpu(op_head->oh_len), + continued); + break; + } + case XFS_LI_CUD: { + skip = xlog_print_trans_cud(&ptr, + be32_to_cpu(op_head->oh_len)); + break; + } case XFS_LI_QUOTAOFF: { skip = xlog_print_trans_qoff(&ptr, be32_to_cpu(op_head->oh_len)); diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index 46952c4..eb3e326 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -418,6 +418,12 @@ xlog_recover_print_logitem( case XFS_LI_RUI: xlog_recover_print_rui(item); break; + case XFS_LI_CUD: + xlog_recover_print_cud(item); + break; + case XFS_LI_CUI: + xlog_recover_print_cui(item); + break; case XFS_LI_DQUOT: xlog_recover_print_dquot(item); break; @@ -458,6 +464,12 @@ xlog_recover_print_item( case XFS_LI_RUI: printf("RUI"); break; + case XFS_LI_CUD: + printf("CUD"); + break; + case XFS_LI_CUI: + printf("CUI"); + break; case XFS_LI_DQUOT: printf("DQ "); break; diff --git a/logprint/log_redo.c b/logprint/log_redo.c index 717dccd..1539be1 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -381,3 +381,154 @@ xlog_recover_print_rud( f = item->ri_buf[0].i_addr; xlog_print_trans_rud(&f, sizeof(struct xfs_rud_log_format)); } + +/* Reference Count Update Items */ + +static int +xfs_cui_copy_format( + char *buf, + uint len, + struct xfs_cui_log_format *dst_fmt, + int continued) +{ + uint nextents = ((struct xfs_cui_log_format *)buf)->cui_nextents; + uint dst_len = sizeof(struct xfs_cui_log_format) + + (nextents - 1) * sizeof(struct xfs_phys_extent); + + if (len == dst_len || continued) { + memcpy((char *)dst_fmt, buf, len); + return 0; + } + fprintf(stderr, _("%s: bad size of CUI format: %u; expected %u; nextents = %u\n"), + progname, len, dst_len, nextents); + return 1; +} + +int +xlog_print_trans_cui( + char **ptr, + uint src_len, + int continued) +{ + struct xfs_cui_log_format *src_f, *f = NULL; + uint dst_len; + uint nextents; + struct xfs_phys_extent *ex; + int i; + int error = 0; + int core_size; + + core_size = offsetof(struct xfs_cui_log_format, cui_extents); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * struct xfs_cui_log_format structure + */ + src_f = malloc(src_len); + if (src_f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + memmove((char*)src_f, *ptr, src_len); + *ptr += src_len; + + /* convert to native format */ + nextents = src_f->cui_nextents; + dst_len = sizeof(struct xfs_cui_log_format) + + (nextents - 1) * sizeof(struct xfs_phys_extent); + + if (continued && src_len < core_size) { + printf(_("CUI: Not enough data to decode further\n")); + error = 1; + goto error; + } + + f = malloc(dst_len); + if (f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + if (xfs_cui_copy_format((char *)src_f, src_len, f, continued)) { + error = 1; + goto error; + } + + printf(_("CUI: #regs: %d num_extents: %d id: 0x%llx\n"), + f->cui_size, f->cui_nextents, (unsigned long long)f->cui_id); + + if (continued) { + printf(_("CUI extent data skipped (CONTINUE set, no space)\n")); + goto error; + } + + ex = f->cui_extents; + for (i=0; i < f->cui_nextents; i++) { + printf("(s: 0x%llx, l: %d, f: 0x%x) ", + (unsigned long long)ex->pe_startblock, ex->pe_len, + ex->pe_flags); + printf("\n"); + ex++; + } +error: + free(src_f); + free(f); + return error; +} + +void +xlog_recover_print_cui( + struct xlog_recover_item *item) +{ + char *src_f; + uint src_len; + + src_f = item->ri_buf[0].i_addr; + src_len = item->ri_buf[0].i_len; + + xlog_print_trans_cui(&src_f, src_len, 0); +} + +int +xlog_print_trans_cud( + char **ptr, + uint len) +{ + struct xfs_cud_log_format *f; + struct xfs_cud_log_format lbuf; + + /* size without extents at end */ + uint core_size = sizeof(struct xfs_cud_log_format) - + sizeof(struct xfs_phys_extent); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * xfs_efd_log_format_t structure + */ + memmove(&lbuf, *ptr, MIN(core_size, len)); + f = &lbuf; + *ptr += len; + if (len >= core_size) { + printf(_("CUD: #regs: %d num_extents: %d id: 0x%llx\n"), + f->cud_size, f->cud_nextents, + (unsigned long long)f->cud_cui_id); + + /* don't print extents as they are not used */ + + return 0; + } else { + printf(_("CUD: Not enough data to decode further\n")); + return 1; + } +} + +void +xlog_recover_print_cud( + struct xlog_recover_item *item) +{ + char *f; + + f = item->ri_buf[0].i_addr; + xlog_print_trans_cud(&f, sizeof(struct xfs_cud_log_format)); +} diff --git a/logprint/logprint.h b/logprint/logprint.h index 0c03c08..a1115e2 100644 --- a/logprint/logprint.h +++ b/logprint/logprint.h @@ -56,4 +56,9 @@ extern void xlog_recover_print_rui(struct xlog_recover_item *item); extern int xlog_print_trans_rud(char **ptr, uint len); extern void xlog_recover_print_rud(struct xlog_recover_item *item); +extern int xlog_print_trans_cui(char **ptr, uint src_len, int continued); +extern void xlog_recover_print_cui(struct xlog_recover_item *item); +extern int xlog_print_trans_cud(char **ptr, uint len); +extern void xlog_recover_print_cud(struct xlog_recover_item *item); + #endif /* LOGPRINT_H */ From darrick.wong@oracle.com Thu Jun 16 20:43:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id ED50D83B7 for ; Thu, 16 Jun 2016 20:43:29 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id ABFF2304048 for ; Thu, 16 Jun 2016 18:43:29 -0700 (PDT) X-ASG-Debug-ID: 1466127806-04bdf01e1396650001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id JeT2Al8fKYwHKUlu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:27 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1hPTH011247 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:26 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hPDc003610 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:25 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hNrc013288; Fri, 17 Jun 2016 01:43:24 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:22 -0700 Subject: [PATCH 120/145] xfs_logprint: support bmap redo items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 120/145] xfs_logprint: support bmap redo items To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:21 -0700 Message-ID: <146612780162.16048.16369479141761925697.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127807 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6286 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Print block mapping update redo items. Signed-off-by: Darrick J. Wong --- logprint/log_misc.c | 11 +++ logprint/log_print_all.c | 12 ++++ logprint/log_redo.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++ logprint/logprint.h | 5 ++ 4 files changed, 180 insertions(+) diff --git a/logprint/log_misc.c b/logprint/log_misc.c index 5389b72..c10a1d1 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -1019,6 +1019,17 @@ xlog_print_record( be32_to_cpu(op_head->oh_len)); break; } + case XFS_LI_BUI: { + skip = xlog_print_trans_bui(&ptr, + be32_to_cpu(op_head->oh_len), + continued); + break; + } + case XFS_LI_BUD: { + skip = xlog_print_trans_bud(&ptr, + be32_to_cpu(op_head->oh_len)); + break; + } case XFS_LI_QUOTAOFF: { skip = xlog_print_trans_qoff(&ptr, be32_to_cpu(op_head->oh_len)); diff --git a/logprint/log_print_all.c b/logprint/log_print_all.c index eb3e326..f49316e 100644 --- a/logprint/log_print_all.c +++ b/logprint/log_print_all.c @@ -424,6 +424,12 @@ xlog_recover_print_logitem( case XFS_LI_CUI: xlog_recover_print_cui(item); break; + case XFS_LI_BUD: + xlog_recover_print_bud(item); + break; + case XFS_LI_BUI: + xlog_recover_print_bui(item); + break; case XFS_LI_DQUOT: xlog_recover_print_dquot(item); break; @@ -470,6 +476,12 @@ xlog_recover_print_item( case XFS_LI_CUI: printf("CUI"); break; + case XFS_LI_BUD: + printf("BUD"); + break; + case XFS_LI_BUI: + printf("BUI"); + break; case XFS_LI_DQUOT: printf("DQ "); break; diff --git a/logprint/log_redo.c b/logprint/log_redo.c index 1539be1..7a1bbef 100644 --- a/logprint/log_redo.c +++ b/logprint/log_redo.c @@ -532,3 +532,155 @@ xlog_recover_print_cud( f = item->ri_buf[0].i_addr; xlog_print_trans_cud(&f, sizeof(struct xfs_cud_log_format)); } + +/* Block Mapping Update Items */ + +static int +xfs_bui_copy_format( + char *buf, + uint len, + struct xfs_bui_log_format *dst_fmt, + int continued) +{ + uint nextents = ((struct xfs_bui_log_format *)buf)->bui_nextents; + uint dst_len = sizeof(struct xfs_bui_log_format) + + (nextents - 1) * sizeof(struct xfs_map_extent); + + if (len == dst_len || continued) { + memcpy((char *)dst_fmt, buf, len); + return 0; + } + fprintf(stderr, _("%s: bad size of BUI format: %u; expected %u; nextents = %u\n"), + progname, len, dst_len, nextents); + return 1; +} + +int +xlog_print_trans_bui( + char **ptr, + uint src_len, + int continued) +{ + struct xfs_bui_log_format *src_f, *f = NULL; + uint dst_len; + uint nextents; + struct xfs_map_extent *ex; + int i; + int error = 0; + int core_size; + + core_size = offsetof(struct xfs_bui_log_format, bui_extents); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * struct xfs_bui_log_format structure + */ + src_f = malloc(src_len); + if (src_f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + memmove((char*)src_f, *ptr, src_len); + *ptr += src_len; + + /* convert to native format */ + nextents = src_f->bui_nextents; + dst_len = sizeof(struct xfs_bui_log_format) + + (nextents - 1) * sizeof(struct xfs_map_extent); + + if (continued && src_len < core_size) { + printf(_("BUI: Not enough data to decode further\n")); + error = 1; + goto error; + } + + f = malloc(dst_len); + if (f == NULL) { + fprintf(stderr, _("%s: %s: malloc failed\n"), + progname, __func__); + exit(1); + } + if (xfs_bui_copy_format((char *)src_f, src_len, f, continued)) { + error = 1; + goto error; + } + + printf(_("BUI: #regs: %d num_extents: %d id: 0x%llx\n"), + f->bui_size, f->bui_nextents, (unsigned long long)f->bui_id); + + if (continued) { + printf(_("BUI extent data skipped (CONTINUE set, no space)\n")); + goto error; + } + + ex = f->bui_extents; + for (i=0; i < f->bui_nextents; i++) { + printf("(s: 0x%llx, l: %d, own: %lld, off: %llu, f: 0x%x) ", + (unsigned long long)ex->me_startblock, ex->me_len, + (long long)ex->me_owner, + (unsigned long long)ex->me_startoff, ex->me_flags); + printf("\n"); + ex++; + } +error: + free(src_f); + free(f); + return error; +} + +void +xlog_recover_print_bui( + struct xlog_recover_item *item) +{ + char *src_f; + uint src_len; + + src_f = item->ri_buf[0].i_addr; + src_len = item->ri_buf[0].i_len; + + xlog_print_trans_bui(&src_f, src_len, 0); +} + +int +xlog_print_trans_bud( + char **ptr, + uint len) +{ + struct xfs_bud_log_format *f; + struct xfs_bud_log_format lbuf; + + /* size without extents at end */ + uint core_size = sizeof(struct xfs_bud_log_format) - + sizeof(struct xfs_map_extent); + + /* + * memmove to ensure 8-byte alignment for the long longs in + * xfs_efd_log_format_t structure + */ + memmove(&lbuf, *ptr, MIN(core_size, len)); + f = &lbuf; + *ptr += len; + if (len >= core_size) { + printf(_("BUD: #regs: %d num_extents: %d id: 0x%llx\n"), + f->bud_size, f->bud_nextents, + (unsigned long long)f->bud_bui_id); + + /* don't print extents as they are not used */ + + return 0; + } else { + printf(_("BUD: Not enough data to decode further\n")); + return 1; + } +} + +void +xlog_recover_print_bud( + struct xlog_recover_item *item) +{ + char *f; + + f = item->ri_buf[0].i_addr; + xlog_print_trans_bud(&f, sizeof(struct xfs_bud_log_format)); +} diff --git a/logprint/logprint.h b/logprint/logprint.h index a1115e2..81feff3 100644 --- a/logprint/logprint.h +++ b/logprint/logprint.h @@ -61,4 +61,9 @@ extern void xlog_recover_print_cui(struct xlog_recover_item *item); extern int xlog_print_trans_cud(char **ptr, uint len); extern void xlog_recover_print_cud(struct xlog_recover_item *item); +extern int xlog_print_trans_bui(char **ptr, uint src_len, int continued); +extern void xlog_recover_print_bui(struct xlog_recover_item *item); +extern int xlog_print_trans_bud(char **ptr, uint len); +extern void xlog_recover_print_bud(struct xlog_recover_item *item); + #endif /* LOGPRINT_H */ From darrick.wong@oracle.com Thu Jun 16 20:43:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E0BF88363 for ; Thu, 16 Jun 2016 20:43:35 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id A47B58F8050 for ; Thu, 16 Jun 2016 18:43:35 -0700 (PDT) X-ASG-Debug-ID: 1466127813-04cbb01fec6a770001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id zxMMka6hadXNKXbw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:33 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1hWSF023677 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:32 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hVKd011480 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:32 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hTIU013302; Fri, 17 Jun 2016 01:43:30 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:29 -0700 Subject: [PATCH 121/145] man: document the reflink inode flag in fsxattr From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 121/145] man: document the reflink inode flag in fsxattr To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:27 -0700 Message-ID: <146612780777.16048.2394921482033235268.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127813 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1056 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Document the new inode flag in struct fsxattr for reflink. Signed-off-by: Darrick J. Wong --- man/man3/xfsctl.3 | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/man/man3/xfsctl.3 b/man/man3/xfsctl.3 index 9e7f138..ef6c992 100644 --- a/man/man3/xfsctl.3 +++ b/man/man3/xfsctl.3 @@ -230,6 +230,16 @@ If the filesystem lives on directly accessible persistent memory, reads and writes to this file will go straight to the persistent memory, bypassing the page cache. .TP +.SM "Bit 16 (0x10000) \- XFS_XFLAG_REFLINK" +This file is sharing or has shared blocks with another file. +This flag can be set by reflinking or deduping blocks with another file +and cleared by fallocating the entire file to pre-copy all shared extents. +A file cannot have +.BR XFS_XFLAG_REFLINK +and +.BR XFS_XFLAG_DAX +set at the same time, that is to say that DAX files cannot share blocks. +.TP .SM "Bit 31 (0x80000000) \- XFS_XFLAG_HASATTR" The file has extended attributes associated with it. .RE From darrick.wong@oracle.com Thu Jun 16 20:43:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A53B480DB for ; Thu, 16 Jun 2016 20:43:41 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6CC5F304048 for ; Thu, 16 Jun 2016 18:43:41 -0700 (PDT) X-ASG-Debug-ID: 1466127819-04cb6c542458450001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id uqgS4PcUj0h7spkS (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:39 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1hbUd011333 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:38 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hbKD016282 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:37 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hZJ1013358; Fri, 17 Jun 2016 01:43:36 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:35 -0700 Subject: [PATCH 122/145] man: document the inode cowextsize flags & fields From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 122/145] man: document the inode cowextsize flags & fields To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:33 -0700 Message-ID: <146612781384.16048.1828413487089680067.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127819 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2300 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Document the new copy-on-write extent size fields and inode flags available in struct fsxattr. Signed-off-by: Darrick J. Wong --- man/man3/xfsctl.3 | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/man/man3/xfsctl.3 b/man/man3/xfsctl.3 index ef6c992..77506aa 100644 --- a/man/man3/xfsctl.3 +++ b/man/man3/xfsctl.3 @@ -150,6 +150,15 @@ value returned indicates that a preferred extent size was previously set on the file, a .B fsx_extsize of zero indicates that the defaults for that filesystem will be used. +A +.B fsx_cowextsize +value returned indicates that a preferred copy on write extent size was +previously set on the file, whereas a +.B fsx_cowextsize +of zero indicates that the defaults for that filesystem will be used. +The current default for +.B fsx_cowextsize +is 128 blocks. Currently the meaningful bits for the .B fsx_xflags field are: @@ -240,6 +249,15 @@ and .BR XFS_XFLAG_DAX set at the same time, that is to say that DAX files cannot share blocks. .TP +.SM "Bit 17 (0x20000) \- XFS_XFLAG_COWEXTSIZE" +Copy on Write Extent size bit - if a CoW extent size value is set on the file, +the allocator will allocate extents for staging a copy on write operation +in multiples of the set size for this file (see +.B XFS_IOC_FSSETXATTR +below). +If the CoW extent size is set on a directory, then new file and directories +created in the directory will inherit the parent's CoW extent size value. +.TP .SM "Bit 31 (0x80000000) \- XFS_XFLAG_HASATTR" The file has extended attributes associated with it. .RE @@ -261,7 +279,8 @@ The final argument points to a variable of type .BR "struct fsxattr" , but only the following fields are used in this call: .BR fsx_xflags , -.B fsx_extsize +.BR fsx_extsize , +.BR fsx_cowextsize , and .BR fsx_projid . The @@ -271,6 +290,9 @@ when the file is empty, except in the case of a directory where the extent size can be set at any time (this value is only used for regular file allocations, so should only be set on a directory in conjunction with the XFS_XFLAG_EXTSZINHERIT flag). +The copy on write extent size, +.BR fsx_cowextsize , +can be set at any time. .TP .B XFS_IOC_GETBMAP From darrick.wong@oracle.com Thu Jun 16 20:43:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A2D4980E9 for ; Thu, 16 Jun 2016 20:43:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 728AC8F804B for ; Thu, 16 Jun 2016 18:43:48 -0700 (PDT) X-ASG-Debug-ID: 1466127825-04cbb01fef6a7c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id s9nv6xBxyZBxUTzN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:45 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1hi4e011416 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:44 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hi3m003823 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:44 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hfT6013467; Fri, 17 Jun 2016 01:43:42 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:41 -0700 Subject: [PATCH 123/145] xfs_repair: fix get_agino_buf to avoid corrupting inodes From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 123/145] xfs_repair: fix get_agino_buf to avoid corrupting inodes To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:39 -0700 Message-ID: <146612781992.16048.3010681907202444358.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127825 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5547 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines The inode buffering code tries to read inodes in units of chunks, which are the larger of 8K or 1 FSB. Each chunk gets its own xfs_buf, which means that get_agino_buf must calculate the disk address of the chunk and feed that to libxfs_readbuf in order to find the inode data correctly. The current code simply grabs the chunk for the start inode and indexes from that, which corrupts memory because the start inode and the target inode could be in different inode chunks. That causes the assert in rmap.c to blow when we clear the reflink flag. (Also fix some minor errors in the debugging printfs.) Signed-off-by: Darrick J. Wong --- libxfs/rdwr.c | 8 +++--- repair/dinode.c | 73 +++++++++++++++++++++++++++++++++---------------------- repair/dinode.h | 12 +++++---- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/libxfs/rdwr.c b/libxfs/rdwr.c index 533a064..9fcc319 100644 --- a/libxfs/rdwr.c +++ b/libxfs/rdwr.c @@ -1038,9 +1038,9 @@ libxfs_readbufr_map(struct xfs_buftarg *btp, struct xfs_buf *bp, int flags) if (!error) bp->b_flags |= LIBXFS_B_UPTODATE; #ifdef IO_DEBUG - printf("%lx: %s: read %u bytes, error %d, blkno=0x%llx(0x%llx), %p\n", - pthread_self(), __FUNCTION__, , error, - (long long)LIBXFS_BBTOOFF64(blkno), (long long)blkno, bp); + printf("%lx: %s: read %lu bytes, error %d, blkno=%llu(%llu), %p\n", + pthread_self(), __FUNCTION__, buf - (char *)bp->b_addr, error, + (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn, bp); #endif return error; } @@ -1070,7 +1070,7 @@ libxfs_readbuf_map(struct xfs_buftarg *btp, struct xfs_buf_map *map, int nmaps, if (!error) libxfs_readbuf_verify(bp, ops); -#ifdef IO_DEBUG +#ifdef IO_DEBUGX printf("%lx: %s: read %lu bytes, error %d, blkno=%llu(%llu), %p\n", pthread_self(), __FUNCTION__, buf - (char *)bp->b_addr, error, (long long)LIBXFS_BBTOOFF64(bp->b_bn), (long long)bp->b_bn, bp); diff --git a/repair/dinode.c b/repair/dinode.c index 89163b1..e9b4f8f 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -847,43 +847,58 @@ scan_bmbt_reclist( } /* - * these two are meant for routines that read and work with inodes - * one at a time where the inodes may be in any order (like walking - * the unlinked lists to look for inodes). the caller is responsible - * for writing/releasing the buffer. + * Grab the buffer backing an inode. This is meant for routines that + * work with inodes one at a time in any order (like walking the + * unlinked lists to look for inodes). The caller is responsible for + * writing/releasing the buffer. */ -xfs_buf_t * -get_agino_buf(xfs_mount_t *mp, - xfs_agnumber_t agno, - xfs_agino_t agino, - xfs_dinode_t **dipp) +struct xfs_buf * +get_agino_buf( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agino_t agino, + struct xfs_dinode **dipp) { - ino_tree_node_t *irec; - xfs_buf_t *bp; - int size; - - if ((irec = find_inode_rec(mp, agno, agino)) == NULL) - return(NULL); + struct xfs_buf *bp; + int cluster_size; + int ino_per_cluster; + xfs_agino_t cluster_agino; + xfs_daddr_t cluster_daddr; + xfs_daddr_t cluster_blks; - size = MAX(1, XFS_FSB_TO_BB(mp, + /* + * Inode buffers have been read into memory in inode_cluster_size + * chunks (or one FSB). To find the correct buffer for an inode, + * we must find the buffer for its cluster, add the appropriate + * offset, and return that. + */ + cluster_size = MAX(mp->m_inode_cluster_size, mp->m_sb.sb_blocksize); + ino_per_cluster = cluster_size / mp->m_sb.sb_inodesize; + cluster_agino = agino & ~(ino_per_cluster - 1); + cluster_blks = XFS_FSB_TO_DADDR(mp, MAX(1, mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog)); - bp = libxfs_readbuf(mp->m_dev, XFS_AGB_TO_DADDR(mp, agno, - XFS_AGINO_TO_AGBNO(mp, irec->ino_startnum)), size, 0, - &xfs_inode_buf_ops); + cluster_daddr = XFS_AGB_TO_DADDR(mp, agno, + XFS_AGINO_TO_AGBNO(mp, cluster_agino)); + +#ifdef XR_INODE_TRACE + printf("cluster_size %d ipc %d clusagino %d daddr %lld sectors %lld\n", + cluster_size, ino_per_cluster, cluster_agino, cluster_daddr, + cluster_blks); +#endif + + bp = libxfs_readbuf(mp->m_dev, cluster_daddr, cluster_blks, + 0, &xfs_inode_buf_ops); if (!bp) { do_warn(_("cannot read inode (%u/%u), disk block %" PRIu64 "\n"), - agno, irec->ino_startnum, - XFS_AGB_TO_DADDR(mp, agno, - XFS_AGINO_TO_AGBNO(mp, irec->ino_startnum))); - return(NULL); + agno, cluster_agino, cluster_daddr); + return NULL; } - *dipp = xfs_make_iptr(mp, bp, agino - - XFS_OFFBNO_TO_AGINO(mp, XFS_AGINO_TO_AGBNO(mp, - irec->ino_startnum), - 0)); - - return(bp); + *dipp = xfs_make_iptr(mp, bp, agino - cluster_agino); + ASSERT(!xfs_sb_version_hascrc(&mp->m_sb) || + XFS_AGINO_TO_INO(mp, agno, agino) == + be64_to_cpu((*dipp)->di_ino)); + return bp; } /* diff --git a/repair/dinode.h b/repair/dinode.h index 5aebf5b..61d0736 100644 --- a/repair/dinode.h +++ b/repair/dinode.h @@ -113,12 +113,12 @@ void check_uncertain_aginodes(xfs_mount_t *mp, xfs_agnumber_t agno); -xfs_buf_t * -get_agino_buf(xfs_mount_t *mp, - xfs_agnumber_t agno, - xfs_agino_t agino, - xfs_dinode_t **dipp); - +struct xfs_buf * +get_agino_buf( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agino_t agino, + struct xfs_dinode **dipp); void dinode_bmbt_translation_init(void); char * get_forkname(int whichfork); From darrick.wong@oracle.com Thu Jun 16 20:43:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 87F24842D for ; Thu, 16 Jun 2016 20:43:55 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3A5B0304039 for ; Thu, 16 Jun 2016 18:43:55 -0700 (PDT) X-ASG-Debug-ID: 1466127831-04bdf01e1796680001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 2KFmejkd2Yojqt4z (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:43:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1ho8L023827 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:50 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hoh7011830 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:50 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hlcA013478; Fri, 17 Jun 2016 01:43:48 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:47 -0700 Subject: [PATCH 124/145] xfs_repair: check the existing refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 124/145] xfs_repair: check the existing refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:46 -0700 Message-ID: <146612782607.16048.11743925855006104394.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127832 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7168 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Spot-check the refcount btree for obvious errors, and mark the refcount btree blocks as such. Signed-off-by: Darrick J. Wong --- repair/incore.h | 3 + repair/scan.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++ repair/xfs_repair.c | 2 + 3 files changed, 189 insertions(+), 1 deletion(-) diff --git a/repair/incore.h b/repair/incore.h index bc0810b..b6c4b4f 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -106,7 +106,8 @@ typedef struct rt_extent_tree_node { #define XR_E_INUSE_FS1 9 /* used by fs ag header or log (rmap btree) */ #define XR_E_INO1 10 /* used by inodes (marked by rmap btree) */ #define XR_E_FS_MAP1 11 /* used by fs space/inode maps (rmap btree) */ -#define XR_E_BAD_STATE 12 +#define XR_E_REFC 12 /* used by fs ag reference count btree */ +#define XR_E_BAD_STATE 13 /* separate state bit, OR'ed into high (4th) bit of ex_state field */ diff --git a/repair/scan.c b/repair/scan.c index ec41ba6..6300204 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -995,6 +995,9 @@ advance: case XFS_RMAP_OWN_INODES: set_bmap(agno, b, XR_E_INO1); break; + case XFS_RMAP_OWN_REFC: + set_bmap(agno, b, XR_E_REFC); + break; case XFS_RMAP_OWN_NULL: /* still unknown */ break; @@ -1030,6 +1033,14 @@ _("inode block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), agno, b, b + blen - 1, name, state, owner); break; + case XR_E_REFC: + if (owner == XFS_RMAP_OWN_REFC) + break; + do_warn( +_("AG refcount block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), + agno, b, b + blen - 1, + name, state, owner); + break; case XR_E_INUSE: if (owner >= 0 && owner < mp->m_sb.sb_dblocks) @@ -1148,6 +1159,167 @@ out: rmap_avoid_check(); } +static void +scan_refcbt( + struct xfs_btree_block *block, + int level, + xfs_agblock_t bno, + xfs_agnumber_t agno, + int suspect, + int isroot, + __uint32_t magic, + void *priv) +{ + const char *name = "refcount"; + int i; + xfs_refcount_ptr_t *pp; + struct xfs_refcount_rec *rp; + int hdr_errors = 0; + int numrecs; + int state; + xfs_agblock_t lastblock = 0; + + if (magic != XFS_REFC_CRC_MAGIC) { + name = "(unknown)"; + hdr_errors++; + suspect++; + goto out; + } + + if (be32_to_cpu(block->bb_magic) != magic) { + do_warn(_("bad magic # %#x in %s btree block %d/%d\n"), + be32_to_cpu(block->bb_magic), name, agno, bno); + hdr_errors++; + if (suspect) + goto out; + } + + if (be16_to_cpu(block->bb_level) != level) { + do_warn(_("expected level %d got %d in %s btree block %d/%d\n"), + level, be16_to_cpu(block->bb_level), name, agno, bno); + hdr_errors++; + if (suspect) + goto out; + } + + /* check for btree blocks multiply claimed */ + state = get_bmap(agno, bno); + if (!(state == XR_E_UNKNOWN || state == XR_E_REFC)) { + set_bmap(agno, bno, XR_E_MULT); + do_warn( +_("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), + name, state, agno, bno, suspect); + goto out; + } + set_bmap(agno, bno, XR_E_FS_MAP); + + numrecs = be16_to_cpu(block->bb_numrecs); + if (level == 0) { + if (numrecs > mp->m_refc_mxr[0]) { + numrecs = mp->m_refc_mxr[0]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_refc_mnr[0]) { + numrecs = mp->m_refc_mnr[0]; + hdr_errors++; + } + + if (hdr_errors) { + do_warn( + _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_refc_mnr[0], mp->m_refc_mxr[0], + name, agno, bno); + suspect++; + } + + rp = XFS_REFCOUNT_REC_ADDR(block, 1); + for (i = 0; i < numrecs; i++) { + xfs_agblock_t b, end; + xfs_extlen_t len; + xfs_nlink_t nr; + + b = be32_to_cpu(rp[i].rc_startblock); + len = be32_to_cpu(rp[i].rc_blockcount); + nr = be32_to_cpu(rp[i].rc_refcount); + end = b + len; + + if (!verify_agbno(mp, agno, b)) { + do_warn( + _("invalid start block %u in record %u of %s btree block %u/%u\n"), + b, i, name, agno, bno); + continue; + } + if (len == 0 || !verify_agbno(mp, agno, end - 1)) { + do_warn( + _("invalid length %u in record %u of %s btree block %u/%u\n"), + len, i, name, agno, bno); + continue; + } + + if (nr < 2 || nr > MAXREFCOUNT) { + do_warn( + _("invalid reference count %u in record %u of %s btree block %u/%u\n"), + nr, i, name, agno, bno); + continue; + } + + if (b && b <= lastblock) { + do_warn(_( + "out-of-order %s btree record %d (%u %u) block %u/%u\n"), + name, i, b, len, agno, bno); + } else { + lastblock = b; + } + + /* XXX: probably want to mark the reflinked areas? */ + } + goto out; + } + + /* + * interior record + */ + pp = XFS_REFCOUNT_PTR_ADDR(block, 1, mp->m_refc_mxr[1]); + + if (numrecs > mp->m_refc_mxr[1]) { + numrecs = mp->m_refc_mxr[1]; + hdr_errors++; + } + if (isroot == 0 && numrecs < mp->m_refc_mnr[1]) { + numrecs = mp->m_refc_mnr[1]; + hdr_errors++; + } + + /* + * don't pass bogus tree flag down further if this block + * looked ok. bail out if two levels in a row look bad. + */ + if (hdr_errors) { + do_warn( + _("bad btree nrecs (%u, min=%u, max=%u) in %s btree block %u/%u\n"), + be16_to_cpu(block->bb_numrecs), + mp->m_refc_mnr[1], mp->m_refc_mxr[1], + name, agno, bno); + if (suspect) + goto out; + suspect++; + } else if (suspect) { + suspect = 0; + } + + for (i = 0; i < numrecs; i++) { + xfs_agblock_t bno = be32_to_cpu(pp[i]); + + if (bno != 0 && verify_agbno(mp, agno, bno)) { + scan_sbtree(bno, level, agno, suspect, scan_refcbt, 0, + magic, priv, &xfs_refcountbt_buf_ops); + } + } +out: + return; +} + /* * The following helpers are to help process and validate individual on-disk * inode btree records. We have two possible inode btrees with slightly @@ -1933,6 +2105,19 @@ validate_agf( } } + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + bno = be32_to_cpu(agf->agf_refcount_root); + if (bno != 0 && verify_agbno(mp, agno, bno)) { + scan_sbtree(bno, + be32_to_cpu(agf->agf_refcount_level), + agno, 0, scan_refcbt, 1, XFS_REFC_CRC_MAGIC, + agcnts, &xfs_refcountbt_buf_ops); + } else { + do_warn(_("bad agbno %u for refcntbt root, agno %d\n"), + bno, agno); + } + } + if (be32_to_cpu(agf->agf_freeblks) != agcnts->agffreeblks) { do_warn(_("agf_freeblks %u, counted %u in ag %u\n"), be32_to_cpu(agf->agf_freeblks), agcnts->agffreeblks, agno); diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 2ecd81d..cc557f7 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -423,6 +423,8 @@ calc_mkfs(xfs_mount_t *mp) fino_bno += min(2, mp->m_rmap_maxlevels); fino_bno++; } + if (xfs_sb_version_hasreflink(&mp->m_sb)) + fino_bno++; /* * If the log is allocated in the first allocation group we need to From darrick.wong@oracle.com Thu Jun 16 20:44:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 02DB383B1 for ; Thu, 16 Jun 2016 20:44:08 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id B6BC6304039 for ; Thu, 16 Jun 2016 18:44:07 -0700 (PDT) X-ASG-Debug-ID: 1466127839-04bdf01e1796690001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 38qxg1B4l4Vmyr1n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1hwKZ011492 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:58 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1hwKg016677 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:43:58 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1htJG013485; Fri, 17 Jun 2016 01:43:56 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:43:55 -0700 Subject: [PATCH 125/145] xfs_repair: handle multiple owners of data blocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 125/145] xfs_repair: handle multiple owners of data blocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:43:52 -0700 Message-ID: <146612783221.16048.14013741850074078546.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127839 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4703 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines If reflink is enabled, don't freak out if there are multiple owners of a given block; that's just a sign that each of those owners are reflink files. Signed-off-by: Darrick J. Wong --- repair/dinode.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/scan.c | 38 +++++++++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 1 deletion(-) diff --git a/repair/dinode.c b/repair/dinode.c index e9b4f8f..ecba3be 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -722,6 +722,9 @@ _("Fatal error: inode %" PRIu64 " - blkmap_set_ext(): %s\n" * checking each entry without setting the * block bitmap */ + if (type == XR_INO_DATA && + xfs_sb_version_hasreflink(&mp->m_sb)) + goto skip_dup; if (search_dup_extent(agno, agbno, ebno)) { do_warn( _("%s fork in ino %" PRIu64 " claims dup extent, " @@ -731,6 +734,7 @@ _("%s fork in ino %" PRIu64 " claims dup extent, " irec.br_blockcount); goto done; } +skip_dup: *tot += irec.br_blockcount; continue; } @@ -770,6 +774,9 @@ _("%s fork in inode %" PRIu64 " claims metadata block %" PRIu64 "\n"), case XR_E_INUSE: case XR_E_MULT: set_bmap_ext(agno, agbno, blen, XR_E_MULT); + if (type == XR_INO_DATA && + xfs_sb_version_hasreflink(&mp->m_sb)) + break; do_warn( _("%s fork in %s inode %" PRIu64 " claims used block %" PRIu64 "\n"), forkname, ftype, ino, b); @@ -2475,6 +2482,65 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), } } + /* + * check that we only have valid flags2 set, and those that are set make + * sense. + */ + if (dino->di_version >= 3) { + uint16_t flags = be16_to_cpu(dino->di_flags); + uint64_t flags2 = be64_to_cpu(dino->di_flags2); + + if (flags2 & ~XFS_DIFLAG2_ANY) { + if (!uncertain) { + do_warn( + _("Bad flags2 set in inode %" PRIu64 "\n"), + lino); + } + flags2 &= XFS_DIFLAG2_ANY; + } + + if ((flags2 & XFS_DIFLAG2_REFLINK) && + !xfs_sb_version_hasreflink(&mp->m_sb)) { + if (!uncertain) { + do_warn( + _("inode %" PRIu64 " is marked reflinked but file system does not support reflink\n"), + lino); + } + goto clear_bad_out; + } + + if (flags2 & XFS_DIFLAG2_REFLINK) { + /* must be a file */ + if (di_mode && !S_ISREG(di_mode)) { + if (!uncertain) { + do_warn( + _("reflink flag set on non-file inode %" PRIu64 "\n"), + lino); + } + goto clear_bad_out; + } + } + + if ((flags2 & XFS_DIFLAG2_REFLINK) && + (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) { + if (!uncertain) { + do_warn( + _("Cannot have a reflinked realtime inode %" PRIu64 "\n"), + lino); + } + goto clear_bad_out; + } + + if (!verify_mode && flags2 != be64_to_cpu(dino->di_flags2)) { + if (!no_modify) { + do_warn(_("fixing bad flags2.\n")); + dino->di_flags2 = cpu_to_be64(flags2); + *dirty = 1; + } else + do_warn(_("would fix bad flags2.\n")); + } + } + if (verify_mode) return retval; diff --git a/repair/scan.c b/repair/scan.c index 6300204..8938341 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -790,6 +790,28 @@ struct rmap_priv { struct xfs_rmap_irec last_rec; }; +static bool +rmap_in_order( + xfs_agblock_t b, + xfs_agblock_t lastblock, + int64_t owner, + int64_t lastowner, + int64_t offset, + int64_t lastoffset) +{ + if (b > lastblock) + return true; + else if (b < lastblock) + return false; + + if (owner > lastowner) + return true; + else if (owner < lastowner) + return false; + + return offset > lastoffset; +} + static void scan_rmapbt( struct xfs_btree_block *block, @@ -947,7 +969,12 @@ advance: } else { bool bad; - bad = b <= lastblock; + if (xfs_sb_version_hasreflink(&mp->m_sb)) + bad = !rmap_in_order(b, lastblock, + owner, lastowner, + offset, lastoffset); + else + bad = b <= lastblock; if (bad) do_warn( _("out-of-order rmap btree record %d (%u %"PRId64" %"PRIx64" %u) block %u/%u\n"), @@ -1057,6 +1084,15 @@ _("in use block (%d,%d-%d) mismatch in %s tree, state - %d,%" PRIx64 "\n"), * be caught later. */ break; + case XR_E_INUSE1: + /* + * multiple inode owners are ok with + * reflink enabled + */ + if (xfs_sb_version_hasreflink(&mp->m_sb) && + !XFS_RMAP_NON_INODE_OWNER(owner)) + break; + /* fall through */ default: do_warn( _("unknown block (%d,%d-%d) mismatch on %s tree, state - %d,%" PRIx64 "\n"), From darrick.wong@oracle.com Thu Jun 16 20:44:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 852F283B1 for ; Thu, 16 Jun 2016 20:44:09 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 549758F804B for ; Thu, 16 Jun 2016 18:44:09 -0700 (PDT) X-ASG-Debug-ID: 1466127846-04cb6c5424584b0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id tVjhFvK0mDIm9qzo (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:06 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1i4SP024116 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:05 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1i4pu012317 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:04 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1i1hX013506; Fri, 17 Jun 2016 01:44:03 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:01 -0700 Subject: [PATCH 126/145] xfs_repair: process reverse-mapping data into refcount data From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 126/145] xfs_repair: process reverse-mapping data into refcount data To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:00 -0700 Message-ID: <146612784023.16048.7721919145713117950.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127846 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11607 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Take all the reverse-mapping data we've acquired and use it to generate reference count data. This data is used in phase 5 to rebuild the refcount btree. v2: Update to reflect separation of rmap_irec flags. Signed-off-by: Darrick J. Wong --- repair/phase4.c | 27 ++++++ repair/rmap.c | 232 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 2 3 files changed, 259 insertions(+), 2 deletions(-) diff --git a/repair/phase4.c b/repair/phase4.c index 3be3786..021d51d 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -193,6 +193,21 @@ _("%s while checking reverse-mappings"), } static void +compute_ag_refcounts( + work_queue_t *wq, + xfs_agnumber_t agno, + void *arg) +{ + int error; + + error = compute_refcounts(wq->mp, agno); + if (error) + do_error( +_("%s while computing reference count records.\n"), + strerror(-error)); +} + +static void process_rmap_data( struct xfs_mount *mp) { @@ -206,6 +221,14 @@ process_rmap_data( for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, check_rmap_btrees, i, NULL); destroy_work_queue(&wq); + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return; + + create_work_queue(&wq, mp, libxfs_nproc()); + for (i = 0; i < mp->m_sb.sb_agcount; i++) + queue_work(&wq, compute_ag_refcounts, i, NULL); + destroy_work_queue(&wq); } void @@ -359,7 +382,9 @@ phase4(xfs_mount_t *mp) /* * Process all the reverse-mapping data that we collected. This - * involves checking the rmap data against the btree. + * involves checking the rmap data against the btree, computing + * reference counts based on the rmap data, and checking the counts + * against the refcount btree. */ process_rmap_data(mp); diff --git a/repair/rmap.c b/repair/rmap.c index e39df5a..4da8003 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -42,6 +42,7 @@ struct xfs_ag_rmap { int ar_flcount; /* agfl entries from leftover */ /* agbt allocations */ struct xfs_rmap_irec ar_last_rmap; /* last rmap seen */ + struct xfs_slab *ar_refcount_items; /* refcount items, p4-5 */ }; static struct xfs_ag_rmap *ag_rmaps; @@ -88,7 +89,8 @@ bool needs_rmap_work( struct xfs_mount *mp) { - return xfs_sb_version_hasrmapbt(&mp->m_sb); + return xfs_sb_version_hasreflink(&mp->m_sb) || + xfs_sb_version_hasrmapbt(&mp->m_sb); } /* @@ -120,6 +122,11 @@ _("Insufficient memory while allocating reverse mapping slabs.")); do_error( _("Insufficient memory while allocating raw metadata reverse mapping slabs.")); ag_rmaps[i].ar_last_rmap.rm_owner = XFS_RMAP_OWN_UNKNOWN; + error = init_slab(&ag_rmaps[i].ar_refcount_items, + sizeof(struct xfs_refcount_irec)); + if (error) + do_error( +_("Insufficient memory while allocating refcount item slabs.")); } } @@ -138,6 +145,7 @@ free_rmaps( for (i = 0; i < mp->m_sb.sb_agcount; i++) { free_slab(&ag_rmaps[i].ar_rmaps); free_slab(&ag_rmaps[i].ar_raw_rmaps); + free_slab(&ag_rmaps[i].ar_refcount_items); } free(ag_rmaps); ag_rmaps = NULL; @@ -591,6 +599,228 @@ dump_rmap( #endif /* + * Rebuilding the Reference Count & Reverse Mapping Btrees + * + * The reference count (refcnt) and reverse mapping (rmap) btrees are rebuilt + * during phase 5, like all other AG btrees. Therefore, reverse mappings must + * be processed into reference counts at the end of phase 4, and the rmaps must + * be recorded during phase 4. There is a need to access the rmaps in physical + * block order, but no particular need for random access, so the slab.c code + * provides a big logical array (consisting of smaller slabs) and some inorder + * iterator functions. + * + * Once we've recorded all the reverse mappings, we're ready to translate the + * rmaps into refcount entries. Imagine the rmap entries as rectangles + * representing extents of physical blocks, and that the rectangles can be laid + * down to allow them to overlap each other; then we know that we must emit + * a refcnt btree entry wherever the amount of overlap changes, i.e. the + * emission stimulus is level-triggered: + * + * - --- + * -- ----- ---- --- ------ + * -- ---- ----------- ---- --------- + * -------------------------------- ----------- + * ^ ^ ^^ ^^ ^ ^^ ^^^ ^^^^ ^ ^^ ^ ^ ^ + * 2 1 23 21 3 43 234 2123 1 01 2 3 0 + * + * For our purposes, a rmap is a tuple (startblock, len, fileoff, owner). + * + * Note that in the actual refcnt btree we don't store the refcount < 2 cases + * because the bnobt tells us which blocks are free; single-use blocks aren't + * recorded in the bnobt or the refcntbt. If the rmapbt supports storing + * multiple entries covering a given block we could theoretically dispense with + * the refcntbt and simply count rmaps, but that's inefficient in the (hot) + * write path, so we'll take the cost of the extra tree to save time. Also + * there's no guarantee that rmap will be enabled. + * + * Given an array of rmaps sorted by physical block number, a starting physical + * block (sp), a bag to hold rmaps that cover sp, and the next physical + * block where the level changes (np), we can reconstruct the refcount + * btree as follows: + * + * While there are still unprocessed rmaps in the array, + * - Set sp to the physical block (pblk) of the next unprocessed rmap. + * - Add to the bag all rmaps in the array where startblock == sp. + * - Set np to the physical block where the bag size will change. + * This is the minimum of (the pblk of the next unprocessed rmap) and + * (startblock + len of each rmap in the bag). + * - Record the bag size as old_bag_size. + * + * - While the bag isn't empty, + * - Remove from the bag all rmaps where startblock + len == np. + * - Add to the bag all rmaps in the array where startblock == np. + * - If the bag size isn't old_bag_size, store the refcount entry + * (sp, np - sp, bag_size) in the refcnt btree. + * - If the bag is empty, break out of the inner loop. + * - Set old_bag_size to the bag size + * - Set sp = np. + * - Set np to the physical block where the bag size will change. + * This is the minimum of (the pblk of the next unprocessed rmap) and + * (startblock + len of each rmap in the bag). + * + * An implementation detail is that because this processing happens during + * phase 4, the refcount entries are stored in an array so that phase 5 can + * load them into the refcount btree. The rmaps can be loaded directly into + * the rmap btree during phase 5 as well. + */ + +/* + * Emit a refcount object for refcntbt reconstruction during phase 5. + */ +#define REFCOUNT_CLAMP(nr) ((nr) > MAXREFCOUNT ? MAXREFCOUNT : (nr)) +static void +refcount_emit( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + xfs_extlen_t len, + size_t nr_rmaps) +{ + struct xfs_refcount_irec rlrec; + int error; + struct xfs_slab *rlslab; + + rlslab = ag_rmaps[agno].ar_refcount_items; + ASSERT(nr_rmaps > 0); + + dbg_printf("REFL: agno=%u pblk=%u, len=%u -> refcount=%zu\n", + agno, agbno, len, nr_rmaps); + rlrec.rc_startblock = agbno; + rlrec.rc_blockcount = len; + rlrec.rc_refcount = REFCOUNT_CLAMP(nr_rmaps); + error = slab_add(rlslab, &rlrec); + if (error) + do_error( +_("Insufficient memory while recreating refcount tree.")); +} +#undef REFCOUNT_CLAMP + +/* + * Transform a pile of physical block mapping observations into refcount data + * for eventual rebuilding of the btrees. + */ +#define RMAP_END(r) ((r)->rm_startblock + (r)->rm_blockcount) +int +compute_refcounts( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_bag *stack_top = NULL; + struct xfs_slab *rmaps; + struct xfs_slab_cursor *rmaps_cur; + struct xfs_rmap_irec *array_cur; + struct xfs_rmap_irec *rmap; + xfs_agblock_t sbno; /* first bno of this rmap set */ + xfs_agblock_t cbno; /* first bno of this refcount set */ + xfs_agblock_t nbno; /* next bno where rmap set changes */ + size_t n, idx; + size_t old_stack_nr; + int error; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 0; + + rmaps = ag_rmaps[agno].ar_rmaps; + + error = init_slab_cursor(rmaps, rmap_compare, &rmaps_cur); + if (error) + return error; + + error = init_bag(&stack_top); + if (error) + goto err; + + /* While there are rmaps to be processed... */ + n = 0; + while (n < slab_count(rmaps)) { + array_cur = peek_slab_cursor(rmaps_cur); + sbno = cbno = array_cur->rm_startblock; + /* Push all rmaps with pblk == sbno onto the stack */ + for (; + array_cur && array_cur->rm_startblock == sbno; + array_cur = peek_slab_cursor(rmaps_cur)) { + advance_slab_cursor(rmaps_cur); n++; + dump_rmap("push0", agno, array_cur); + error = bag_add(stack_top, array_cur); + if (error) + goto err; + } + + /* Set nbno to the bno of the next refcount change */ + if (n < slab_count(rmaps)) + nbno = array_cur->rm_startblock; + else + nbno = NULLAGBLOCK; + foreach_bag_ptr(stack_top, idx, rmap) { + nbno = min(nbno, RMAP_END(rmap)); + } + + /* Emit reverse mappings, if needed */ + ASSERT(nbno > sbno); + old_stack_nr = bag_count(stack_top); + + /* While stack isn't empty... */ + while (bag_count(stack_top)) { + /* Pop all rmaps that end at nbno */ + foreach_bag_ptr_reverse(stack_top, idx, rmap) { + if (RMAP_END(rmap) != nbno) + continue; + dump_rmap("pop", agno, rmap); + error = bag_remove(stack_top, idx); + if (error) + goto err; + } + + /* Push array items that start at nbno */ + for (; + array_cur && array_cur->rm_startblock == nbno; + array_cur = peek_slab_cursor(rmaps_cur)) { + advance_slab_cursor(rmaps_cur); n++; + dump_rmap("push1", agno, array_cur); + error = bag_add(stack_top, array_cur); + if (error) + goto err; + } + + /* Emit refcount if necessary */ + ASSERT(nbno > cbno); + if (bag_count(stack_top) != old_stack_nr) { + if (old_stack_nr > 1) { + refcount_emit(mp, agno, cbno, + nbno - cbno, + old_stack_nr); + } + cbno = nbno; + } + + /* Stack empty, go find the next rmap */ + if (bag_count(stack_top) == 0) + break; + old_stack_nr = bag_count(stack_top); + sbno = nbno; + + /* Set nbno to the bno of the next refcount change */ + if (n < slab_count(rmaps)) + nbno = array_cur->rm_startblock; + else + nbno = NULLAGBLOCK; + foreach_bag_ptr(stack_top, idx, rmap) { + nbno = min(nbno, RMAP_END(rmap)); + } + + /* Emit reverse mappings, if needed */ + ASSERT(nbno > sbno); + } + } +err: + free_bag(&stack_top); + free_slab_cursor(&rmaps_cur); + + return error; +} +#undef RMAP_END + +/* * Return the number of rmap objects for an AG. */ size_t diff --git a/repair/rmap.h b/repair/rmap.h index 69215e8..65f33e0 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -49,6 +49,8 @@ extern __int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1, extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key); +extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); + extern void fix_freelist(struct xfs_mount *, xfs_agnumber_t, bool); extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int); From darrick.wong@oracle.com Thu Jun 16 20:44:17 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8C7F183B1 for ; Thu, 16 Jun 2016 20:44:17 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5D2D38F804B for ; Thu, 16 Jun 2016 18:44:17 -0700 (PDT) X-ASG-Debug-ID: 1466127854-04cb6c5427584e0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id aH8JA7jvFFT3noXR (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1iA7o011828 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:10 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iAFP004623 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:10 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1i8at013527; Fri, 17 Jun 2016 01:44:09 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:07 -0700 Subject: [PATCH 127/145] xfs_repair: record reflink inode state From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 127/145] xfs_repair: record reflink inode state To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:06 -0700 Message-ID: <146612784645.16048.2327933728611184796.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127855 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5359 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Record the state of the per-inode reflink flag, so that we can compare against the rmap data and update the flags accordingly. Clear the (reflink) state if we clear the inode. Signed-off-by: Darrick J. Wong --- repair/dino_chunks.c | 1 + repair/dinode.c | 6 ++++++ repair/incore.h | 38 ++++++++++++++++++++++++++++++++++++++ repair/incore_ino.c | 2 ++ repair/rmap.c | 26 ++++++++++++++++++++++++++ repair/rmap.h | 2 ++ 6 files changed, 75 insertions(+) diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index 7dbaca6..4db9512 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -931,6 +931,7 @@ next_readbuf: do_warn(_("would have cleared inode %" PRIu64 "\n"), ino); } + clear_inode_was_rl(ino_rec, irec_offset); } process_next: diff --git a/repair/dinode.c b/repair/dinode.c index ecba3be..d48e415 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2636,6 +2636,12 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "), goto clear_bad_out; /* + * record the state of the reflink flag + */ + if (collect_rmaps) + record_inode_reflink_flag(mp, dino, agno, ino, lino); + + /* * check data fork -- if it's bad, clear the inode */ if (process_inode_data_fork(mp, agno, ino, dino, type, dirty, diff --git a/repair/incore.h b/repair/incore.h index b6c4b4f..bcd2f4b 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -283,6 +283,8 @@ typedef struct ino_tree_node { __uint64_t ir_sparse; /* sparse inode bitmask */ __uint64_t ino_confirmed; /* confirmed bitmask */ __uint64_t ino_isa_dir; /* bit == 1 if a directory */ + __uint64_t ino_was_rl; /* bit == 1 if reflink flag set */ + __uint64_t ino_is_rl; /* bit == 1 if reflink flag should be set */ __uint8_t nlink_size; union ino_nlink disk_nlinks; /* on-disk nlinks, set in P3 */ union { @@ -494,6 +496,42 @@ static inline bool is_inode_sparse(struct ino_tree_node *irec, int offset) } /* + * set/clear/test was inode marked as reflinked + */ +static inline void set_inode_was_rl(struct ino_tree_node *irec, int offset) +{ + irec->ino_was_rl |= IREC_MASK(offset); +} + +static inline void clear_inode_was_rl(struct ino_tree_node *irec, int offset) +{ + irec->ino_was_rl &= ~IREC_MASK(offset); +} + +static inline int inode_was_rl(struct ino_tree_node *irec, int offset) +{ + return (irec->ino_was_rl & IREC_MASK(offset)) != 0; +} + +/* + * set/clear/test should inode be marked as reflinked + */ +static inline void set_inode_is_rl(struct ino_tree_node *irec, int offset) +{ + irec->ino_is_rl |= IREC_MASK(offset); +} + +static inline void clear_inode_is_rl(struct ino_tree_node *irec, int offset) +{ + irec->ino_is_rl &= ~IREC_MASK(offset); +} + +static inline int inode_is_rl(struct ino_tree_node *irec, int offset) +{ + return (irec->ino_is_rl & IREC_MASK(offset)) != 0; +} + +/* * add_inode_reached() is set on inode I only if I has been reached * by an inode P claiming to be the parent and if I is a directory, * the .. link in the I says that P is I's parent. diff --git a/repair/incore_ino.c b/repair/incore_ino.c index 1898257..2ec1765 100644 --- a/repair/incore_ino.c +++ b/repair/incore_ino.c @@ -257,6 +257,8 @@ alloc_ino_node( irec->ino_startnum = starting_ino; irec->ino_confirmed = 0; irec->ino_isa_dir = 0; + irec->ino_was_rl = 0; + irec->ino_is_rl = 0; irec->ir_free = (xfs_inofree_t) - 1; irec->ir_sparse = 0; irec->ino_un.ex_data = NULL; diff --git a/repair/rmap.c b/repair/rmap.c index 4da8003..6a62665 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -1073,6 +1073,32 @@ rmap_high_key_from_rec( } /* + * Record that an inode had the reflink flag set when repair started. The + * inode reflink flag will be adjusted as necessary. + */ +void +record_inode_reflink_flag( + struct xfs_mount *mp, + struct xfs_dinode *dino, + xfs_agnumber_t agno, + xfs_agino_t ino, + xfs_ino_t lino) +{ + struct ino_tree_node *irec; + int off; + + ASSERT(XFS_AGINO_TO_INO(mp, agno, ino) == be64_to_cpu(dino->di_ino)); + if (!(be64_to_cpu(dino->di_flags2) & XFS_DIFLAG2_REFLINK)) + return; + irec = find_inode_rec(mp, agno, ino); + off = get_inode_offset(mp, lino, irec); + ASSERT(!inode_was_rl(irec, off)); + set_inode_was_rl(irec, off); + dbg_printf("set was_rl lino=%llu was=0x%llx\n", + (unsigned long long)lino, (unsigned long long)irec->ino_was_rl); +} + +/* * Regenerate the AGFL so that we don't run out of it while rebuilding the * rmap btree. If skip_rmapbt is true, don't update the rmapbt (most probably * because we're updating the rmapbt). diff --git a/repair/rmap.h b/repair/rmap.h index 65f33e0..47b2f3b 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -50,6 +50,8 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key); extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); +extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *, + xfs_agnumber_t, xfs_agino_t, xfs_ino_t); extern void fix_freelist(struct xfs_mount *, xfs_agnumber_t, bool); extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int); From darrick.wong@oracle.com Thu Jun 16 20:44:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id AB9B88383 for ; Thu, 16 Jun 2016 20:44:22 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 25F5CAC004 for ; Thu, 16 Jun 2016 18:44:22 -0700 (PDT) X-ASG-Debug-ID: 1466127859-04cbb01fef6a870001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id FJHoRAgGcPl91GzU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:19 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1iFlU011930 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:15 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iE4L004713 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:15 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iEhU031229; Fri, 17 Jun 2016 01:44:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:13 -0700 Subject: [PATCH 128/145] xfs_repair: fix inode reflink flags From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 128/145] xfs_repair: fix inode reflink flags To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:12 -0700 Message-ID: <146612785261.16048.12190820987789813213.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127859 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6323 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines While we're computing reference counts, record which inodes actually share blocks with other files and fix the flags as necessary. Signed-off-by: Darrick J. Wong --- repair/phase4.c | 20 ++++++++ repair/rmap.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 1 3 files changed, 154 insertions(+) diff --git a/repair/phase4.c b/repair/phase4.c index 021d51d..59bb9fb 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -208,6 +208,21 @@ _("%s while computing reference count records.\n"), } static void +process_inode_reflink_flags( + struct work_queue *wq, + xfs_agnumber_t agno, + void *arg) +{ + int error; + + error = fix_inode_reflink_flags(wq->mp, agno); + if (error) + do_error( +_("%s while fixing inode reflink flags.\n"), + strerror(-error)); +} + +static void process_rmap_data( struct xfs_mount *mp) { @@ -229,6 +244,11 @@ process_rmap_data( for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, compute_ag_refcounts, i, NULL); destroy_work_queue(&wq); + + create_work_queue(&wq, mp, libxfs_nproc()); + for (i = 0; i < mp->m_sb.sb_agcount; i++) + queue_work(&wq, process_inode_reflink_flags, i, NULL); + destroy_work_queue(&wq); } void diff --git a/repair/rmap.c b/repair/rmap.c index 6a62665..124173d 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -665,6 +665,39 @@ dump_rmap( */ /* + * Mark all inodes in the reverse-mapping observation stack as requiring the + * reflink inode flag, if the stack depth is greater than 1. + */ +static void +mark_inode_rl( + struct xfs_mount *mp, + struct xfs_bag *rmaps) +{ + xfs_agnumber_t iagno; + struct xfs_rmap_irec *rmap; + struct ino_tree_node *irec; + int off; + size_t idx; + xfs_agino_t ino; + + if (bag_count(rmaps) < 2) + return; + + /* Reflink flag accounting */ + foreach_bag_ptr(rmaps, idx, rmap) { + ASSERT(!XFS_RMAP_NON_INODE_OWNER(rmap->rm_owner)); + iagno = XFS_INO_TO_AGNO(mp, rmap->rm_owner); + ino = XFS_INO_TO_AGINO(mp, rmap->rm_owner); + pthread_mutex_lock(&ag_locks[iagno].lock); + irec = find_inode_rec(mp, iagno, ino); + off = get_inode_offset(mp, rmap->rm_owner, irec); + /* lock here because we might go outside this ag */ + set_inode_is_rl(irec, off); + pthread_mutex_unlock(&ag_locks[iagno].lock); + } +} + +/* * Emit a refcount object for refcntbt reconstruction during phase 5. */ #define REFCOUNT_CLAMP(nr) ((nr) > MAXREFCOUNT ? MAXREFCOUNT : (nr)) @@ -745,6 +778,7 @@ compute_refcounts( if (error) goto err; } + mark_inode_rl(mp, stack_top); /* Set nbno to the bno of the next refcount change */ if (n < slab_count(rmaps)) @@ -781,6 +815,7 @@ compute_refcounts( if (error) goto err; } + mark_inode_rl(mp, stack_top); /* Emit refcount if necessary */ ASSERT(nbno > cbno); @@ -1099,6 +1134,104 @@ record_inode_reflink_flag( } /* + * Fix an inode's reflink flag. + */ +static int +fix_inode_reflink_flag( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agino_t agino, + bool set) +{ + struct xfs_dinode *dino; + struct xfs_buf *buf; + + if (set) + do_warn( +_("setting reflink flag on inode %"PRIu64"\n"), + XFS_AGINO_TO_INO(mp, agno, agino)); + else if (!no_modify) /* && !set */ + do_warn( +_("clearing reflink flag on inode %"PRIu64"\n"), + XFS_AGINO_TO_INO(mp, agno, agino)); + if (no_modify) + return 0; + + buf = get_agino_buf(mp, agno, agino, &dino); + if (!buf) + return 1; + ASSERT(XFS_AGINO_TO_INO(mp, agno, agino) == be64_to_cpu(dino->di_ino)); + if (set) + dino->di_flags2 |= cpu_to_be64(XFS_DIFLAG2_REFLINK); + else + dino->di_flags2 &= cpu_to_be64(~XFS_DIFLAG2_REFLINK); + libxfs_dinode_calc_crc(mp, dino); + libxfs_writebuf(buf, 0); + + return 0; +} + +/* + * Fix discrepancies between the state of the inode reflink flag and our + * observations as to whether or not the inode really needs it. + */ +int +fix_inode_reflink_flags( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct ino_tree_node *irec; + int bit; + __uint64_t was; + __uint64_t is; + __uint64_t diff; + __uint64_t mask; + int error = 0; + xfs_agino_t agino; + + /* + * Update the reflink flag for any inode where there's a discrepancy + * between the inode flag and whether or not we found any reflinked + * extents. + */ + for (irec = findfirst_inode_rec(agno); + irec != NULL; + irec = next_ino_rec(irec)) { + ASSERT((irec->ino_was_rl & irec->ir_free) == 0); + ASSERT((irec->ino_is_rl & irec->ir_free) == 0); + was = irec->ino_was_rl; + is = irec->ino_is_rl; + if (was == is) + continue; + diff = was ^ is; + dbg_printf("mismatch ino=%llu was=0x%lx is=0x%lx dif=0x%lx\n", + (unsigned long long)XFS_AGINO_TO_INO(mp, agno, + irec->ino_startnum), + was, is, diff); + + for (bit = 0, mask = 1; bit < 64; bit++, mask <<= 1) { + agino = bit + irec->ino_startnum; + if (!(diff & mask)) + continue; + else if (was & mask) + error = fix_inode_reflink_flag(mp, agno, agino, + false); + else if (is & mask) + error = fix_inode_reflink_flag(mp, agno, agino, + true); + else + ASSERT(0); + if (error) + do_error( +_("Unable to fix reflink flag on inode %"PRIu64".\n"), + XFS_AGINO_TO_INO(mp, agno, agino)); + } + } + + return error; +} + +/* * Regenerate the AGFL so that we don't run out of it while rebuilding the * rmap btree. If skip_rmapbt is true, don't update the rmapbt (most probably * because we're updating the rmapbt). diff --git a/repair/rmap.h b/repair/rmap.h index 47b2f3b..d6d360f 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -52,6 +52,7 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *, xfs_agnumber_t, xfs_agino_t, xfs_ino_t); +extern int fix_inode_reflink_flags(struct xfs_mount *, xfs_agnumber_t); extern void fix_freelist(struct xfs_mount *, xfs_agnumber_t, bool); extern void rmap_store_agflcount(struct xfs_mount *, xfs_agnumber_t, int); From darrick.wong@oracle.com Thu Jun 16 20:44:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8849A8458 for ; Thu, 16 Jun 2016 20:44:33 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 4C335304039 for ; Thu, 16 Jun 2016 18:44:33 -0700 (PDT) X-ASG-Debug-ID: 1466127870-04cbb01fef6a8a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 6n2IlHRwMq7H7h3n (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1iSQG024394 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:29 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iSh0012877 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:28 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1iRhk003624; Fri, 17 Jun 2016 01:44:28 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:27 -0700 Subject: [PATCH 130/145] xfs_repair: rebuild the refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 130/145] xfs_repair: rebuild the refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:26 -0700 Message-ID: <146612786622.16048.8969386185247411464.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127870 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11463 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Rebuild the refcount btree with the reference count data we assembled during phase 4. Signed-off-by: Darrick J. Wong --- repair/phase5.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+), 2 deletions(-) diff --git a/repair/phase5.c b/repair/phase5.c index db84440..5018191 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -1691,6 +1691,297 @@ _("Insufficient memory to construct reverse-map cursor.")); free_slab_cursor(&rmap_cur); } +/* rebuild the refcount tree */ + +/* + * we don't have to worry here about how chewing up free extents + * may perturb things because reflink tree building happens before + * freespace tree building. + */ +static void +init_refc_cursor( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *btree_curs) +{ + size_t num_recs; + int level; + struct bt_stat_level *lptr; + struct bt_stat_level *p_lptr; + xfs_extlen_t blocks_allocated; + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) { + memset(btree_curs, 0, sizeof(struct bt_status)); + return; + } + + lptr = &btree_curs->level[0]; + btree_curs->init = 1; + btree_curs->owner = XFS_RMAP_OWN_REFC; + + /* + * build up statistics + */ + num_recs = refcount_record_count(mp, agno); + if (num_recs == 0) { + /* + * easy corner-case -- no refcount records + */ + lptr->num_blocks = 1; + lptr->modulo = 0; + lptr->num_recs_pb = 0; + lptr->num_recs_tot = 0; + + btree_curs->num_levels = 1; + btree_curs->num_tot_blocks = btree_curs->num_free_blocks = 1; + + setup_cursor(mp, agno, btree_curs); + + return; + } + + blocks_allocated = lptr->num_blocks = howmany(num_recs, + mp->m_refc_mxr[0]); + + lptr->modulo = num_recs % lptr->num_blocks; + lptr->num_recs_pb = num_recs / lptr->num_blocks; + lptr->num_recs_tot = num_recs; + level = 1; + + if (lptr->num_blocks > 1) { + for (; btree_curs->level[level-1].num_blocks > 1 + && level < XFS_BTREE_MAXLEVELS; + level++) { + lptr = &btree_curs->level[level]; + p_lptr = &btree_curs->level[level - 1]; + lptr->num_blocks = howmany(p_lptr->num_blocks, + mp->m_refc_mxr[1]); + lptr->modulo = p_lptr->num_blocks % lptr->num_blocks; + lptr->num_recs_pb = p_lptr->num_blocks + / lptr->num_blocks; + lptr->num_recs_tot = p_lptr->num_blocks; + + blocks_allocated += lptr->num_blocks; + } + } + ASSERT(lptr->num_blocks == 1); + btree_curs->num_levels = level; + + btree_curs->num_tot_blocks = btree_curs->num_free_blocks + = blocks_allocated; + + setup_cursor(mp, agno, btree_curs); +} + +static void +prop_refc_cursor( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *btree_curs, + xfs_agblock_t startbno, + int level) +{ + struct xfs_btree_block *bt_hdr; + struct xfs_refcount_key *bt_key; + xfs_refcount_ptr_t *bt_ptr; + xfs_agblock_t agbno; + struct bt_stat_level *lptr; + + level++; + + if (level >= btree_curs->num_levels) + return; + + lptr = &btree_curs->level[level]; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + + if (be16_to_cpu(bt_hdr->bb_numrecs) == 0) { + /* + * this only happens once to initialize the + * first path up the left side of the tree + * where the agbno's are already set up + */ + prop_refc_cursor(mp, agno, btree_curs, startbno, level); + } + + if (be16_to_cpu(bt_hdr->bb_numrecs) == + lptr->num_recs_pb + (lptr->modulo > 0)) { + /* + * write out current prev block, grab us a new block, + * and set the rightsib pointer of current block + */ +#ifdef XR_BLD_INO_TRACE + fprintf(stderr, " ino prop agbno %d ", lptr->prev_agbno); +#endif + if (lptr->prev_agbno != NULLAGBLOCK) { + ASSERT(lptr->prev_buf_p != NULL); + libxfs_writebuf(lptr->prev_buf_p, 0); + } + lptr->prev_agbno = lptr->agbno; + lptr->prev_buf_p = lptr->buf_p; + agbno = get_next_blockaddr(agno, level, btree_curs); + + bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(agbno); + + lptr->buf_p = libxfs_getbuf(mp->m_dev, + XFS_AGB_TO_DADDR(mp, agno, agbno), + XFS_FSB_TO_BB(mp, 1)); + lptr->agbno = agbno; + + if (lptr->modulo) + lptr->modulo--; + + /* + * initialize block header + */ + lptr->buf_p->b_ops = &xfs_refcountbt_buf_ops; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + memset(bt_hdr, 0, mp->m_sb.sb_blocksize); + xfs_btree_init_block(mp, lptr->buf_p, XFS_REFC_CRC_MAGIC, + level, 0, agno, + XFS_BTREE_CRC_BLOCKS); + + bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); + + /* + * propagate extent record for first extent in new block up + */ + prop_refc_cursor(mp, agno, btree_curs, startbno, level); + } + /* + * add inode info to current block + */ + be16_add_cpu(&bt_hdr->bb_numrecs, 1); + + bt_key = XFS_REFCOUNT_KEY_ADDR(bt_hdr, + be16_to_cpu(bt_hdr->bb_numrecs)); + bt_ptr = XFS_REFCOUNT_PTR_ADDR(bt_hdr, + be16_to_cpu(bt_hdr->bb_numrecs), + mp->m_refc_mxr[1]); + + bt_key->rc_startblock = cpu_to_be32(startbno); + *bt_ptr = cpu_to_be32(btree_curs->level[level-1].agbno); +} + +/* + * rebuilds a refcount btree given a cursor. + */ +static void +build_refcount_tree( + struct xfs_mount *mp, + xfs_agnumber_t agno, + struct bt_status *btree_curs) +{ + xfs_agnumber_t i; + xfs_agblock_t j; + xfs_agblock_t agbno; + struct xfs_btree_block *bt_hdr; + struct xfs_refcount_irec *refc_rec; + struct xfs_slab_cursor *refc_cur; + struct xfs_refcount_rec *bt_rec; + struct bt_stat_level *lptr; + int level = btree_curs->num_levels; + int error; + + for (i = 0; i < level; i++) { + lptr = &btree_curs->level[i]; + + agbno = get_next_blockaddr(agno, i, btree_curs); + lptr->buf_p = libxfs_getbuf(mp->m_dev, + XFS_AGB_TO_DADDR(mp, agno, agbno), + XFS_FSB_TO_BB(mp, 1)); + + if (i == btree_curs->num_levels - 1) + btree_curs->root = agbno; + + lptr->agbno = agbno; + lptr->prev_agbno = NULLAGBLOCK; + lptr->prev_buf_p = NULL; + /* + * initialize block header + */ + + lptr->buf_p->b_ops = &xfs_refcountbt_buf_ops; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + memset(bt_hdr, 0, mp->m_sb.sb_blocksize); + xfs_btree_init_block(mp, lptr->buf_p, XFS_REFC_CRC_MAGIC, + i, 0, agno, + XFS_BTREE_CRC_BLOCKS); + } + + /* + * run along leaf, setting up records. as we have to switch + * blocks, call the prop_refc_cursor routine to set up the new + * pointers for the parent. that can recurse up to the root + * if required. set the sibling pointers for leaf level here. + */ + error = init_refcount_cursor(agno, &refc_cur); + if (error) + do_error( +_("Insufficient memory to construct refcount cursor.")); + refc_rec = pop_slab_cursor(refc_cur); + lptr = &btree_curs->level[0]; + + for (i = 0; i < lptr->num_blocks; i++) { + /* + * block initialization, lay in block header + */ + lptr->buf_p->b_ops = &xfs_refcountbt_buf_ops; + bt_hdr = XFS_BUF_TO_BLOCK(lptr->buf_p); + memset(bt_hdr, 0, mp->m_sb.sb_blocksize); + xfs_btree_init_block(mp, lptr->buf_p, XFS_REFC_CRC_MAGIC, + 0, 0, agno, + XFS_BTREE_CRC_BLOCKS); + + bt_hdr->bb_u.s.bb_leftsib = cpu_to_be32(lptr->prev_agbno); + bt_hdr->bb_numrecs = cpu_to_be16(lptr->num_recs_pb + + (lptr->modulo > 0)); + + if (lptr->modulo > 0) + lptr->modulo--; + + if (lptr->num_recs_pb > 0) + prop_refc_cursor(mp, agno, btree_curs, + refc_rec->rc_startblock, 0); + + bt_rec = (struct xfs_refcount_rec *) + ((char *)bt_hdr + XFS_REFCOUNT_BLOCK_LEN); + for (j = 0; j < be16_to_cpu(bt_hdr->bb_numrecs); j++) { + ASSERT(refc_rec != NULL); + bt_rec[j].rc_startblock = + cpu_to_be32(refc_rec->rc_startblock); + bt_rec[j].rc_blockcount = + cpu_to_be32(refc_rec->rc_blockcount); + bt_rec[j].rc_refcount = cpu_to_be32(refc_rec->rc_refcount); + + refc_rec = pop_slab_cursor(refc_cur); + } + + if (refc_rec != NULL) { + /* + * get next leaf level block + */ + if (lptr->prev_buf_p != NULL) { +#ifdef XR_BLD_RL_TRACE + fprintf(stderr, "writing refcntbt agbno %u\n", + lptr->prev_agbno); +#endif + ASSERT(lptr->prev_agbno != NULLAGBLOCK); + libxfs_writebuf(lptr->prev_buf_p, 0); + } + lptr->prev_buf_p = lptr->buf_p; + lptr->prev_agbno = lptr->agbno; + lptr->agbno = get_next_blockaddr(agno, 0, btree_curs); + bt_hdr->bb_u.s.bb_rightsib = cpu_to_be32(lptr->agbno); + + lptr->buf_p = libxfs_getbuf(mp->m_dev, + XFS_AGB_TO_DADDR(mp, agno, lptr->agbno), + XFS_FSB_TO_BB(mp, 1)); + } + } + free_slab_cursor(&refc_cur); +} + /* * build both the agf and the agfl for an agno given both * btree cursors. @@ -1705,7 +1996,8 @@ build_agf_agfl( struct bt_status *bcnt_bt, xfs_extlen_t freeblks, /* # free blocks in tree */ int lostblocks, /* # blocks that will be lost */ - struct bt_status *rmap_bt) + struct bt_status *rmap_bt, + struct bt_status *refcnt_bt) { struct extent_tree_node *ext_ptr; struct xfs_buf *agf_buf, *agfl_buf; @@ -1747,6 +2039,8 @@ build_agf_agfl( agf->agf_roots[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->root); agf->agf_levels[XFS_BTNUM_RMAP] = cpu_to_be32(rmap_bt->num_levels); agf->agf_freeblks = cpu_to_be32(freeblks); + agf->agf_refcount_root = cpu_to_be32(refcnt_bt->root); + agf->agf_refcount_level = cpu_to_be32(refcnt_bt->num_levels); /* * Count and record the number of btree blocks consumed if required. @@ -1864,6 +2158,10 @@ build_agf_agfl( ASSERT(be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi]) != be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi])); + ASSERT(be32_to_cpu(agf->agf_refcount_root) != + be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNOi])); + ASSERT(be32_to_cpu(agf->agf_refcount_root) != + be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNTi])); libxfs_writebuf(agf_buf, 0); @@ -1933,6 +2231,7 @@ phase5_func( bt_status_t ino_btree_curs; bt_status_t fino_btree_curs; bt_status_t rmap_btree_curs; + bt_status_t refcnt_btree_curs; int extra_blocks = 0; uint num_freeblocks; xfs_extlen_t freeblks1; @@ -1995,6 +2294,12 @@ phase5_func( */ init_rmapbt_cursor(mp, agno, &rmap_btree_curs); + /* + * Set up the btree cursors for the on-disk refcount btrees, + * which includes pre-allocating all required blocks. + */ + init_refc_cursor(mp, agno, &refcnt_btree_curs); + num_extents = count_bno_extents_blocks(agno, &num_freeblocks); /* * lose two blocks per AG -- the space tree roots @@ -2088,12 +2393,17 @@ phase5_func( rmap_btree_curs.num_free_blocks) - 1; } + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + build_refcount_tree(mp, agno, &refcnt_btree_curs); + write_cursor(&refcnt_btree_curs); + } + /* * set up agf and agfl */ build_agf_agfl(mp, agno, &bno_btree_curs, &bcnt_btree_curs, freeblks1, extra_blocks, - &rmap_btree_curs); + &rmap_btree_curs, &refcnt_btree_curs); /* * build inode allocation tree. */ @@ -2124,6 +2434,8 @@ phase5_func( finish_cursor(&ino_btree_curs); if (xfs_sb_version_hasrmapbt(&mp->m_sb)) finish_cursor(&rmap_btree_curs); + if (xfs_sb_version_hasreflink(&mp->m_sb)) + finish_cursor(&refcnt_btree_curs); if (xfs_sb_version_hasfinobt(&mp->m_sb)) finish_cursor(&fino_btree_curs); finish_cursor(&bcnt_btree_curs); From darrick.wong@oracle.com Thu Jun 16 20:44:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B349C845C for ; Thu, 16 Jun 2016 20:44:43 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 49DF7AC001 for ; Thu, 16 Jun 2016 18:44:43 -0700 (PDT) X-ASG-Debug-ID: 1466127876-04bdf01e1596710001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 0NMoCqkCFCSdmC0I (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:38 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1iNKM012062 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:23 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iMYI012778 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:23 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iLKS025846; Fri, 17 Jun 2016 01:44:22 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:21 -0700 Subject: [PATCH 129/145] xfs_repair: check the refcount btree against our observed reference counts when -n From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 129/145] xfs_repair: check the refcount btree against our observed reference counts when -n To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:18 -0700 Message-ID: <146612785877.16048.4642751275301910078.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127878 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6291 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Check the observed reference counts against whatever's in the refcount btree for discrepancies. Signed-off-by: Darrick J. Wong --- repair/phase4.c | 20 +++++++++ repair/rmap.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ repair/rmap.h | 5 ++ repair/scan.c | 3 + 4 files changed, 154 insertions(+) diff --git a/repair/phase4.c b/repair/phase4.c index 59bb9fb..9f4e0d0 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -223,6 +223,21 @@ _("%s while fixing inode reflink flags.\n"), } static void +check_refcount_btrees( + work_queue_t *wq, + xfs_agnumber_t agno, + void *arg) +{ + int error; + + error = check_refcounts(wq->mp, agno); + if (error) + do_error( +_("%s while checking reference counts"), + strerror(-error)); +} + +static void process_rmap_data( struct xfs_mount *mp) { @@ -249,6 +264,11 @@ process_rmap_data( for (i = 0; i < mp->m_sb.sb_agcount; i++) queue_work(&wq, process_inode_reflink_flags, i, NULL); destroy_work_queue(&wq); + + create_work_queue(&wq, mp, libxfs_nproc()); + for (i = 0; i < mp->m_sb.sb_agcount; i++) + queue_work(&wq, check_refcount_btrees, i, NULL); + destroy_work_queue(&wq); } void diff --git a/repair/rmap.c b/repair/rmap.c index 124173d..5c0e015 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -47,6 +47,7 @@ struct xfs_ag_rmap { static struct xfs_ag_rmap *ag_rmaps; static bool rmapbt_suspect; +static bool refcbt_suspect; /* * Compare rmap observations for array sorting. @@ -1232,6 +1233,131 @@ _("Unable to fix reflink flag on inode %"PRIu64".\n"), } /* + * Return the number of refcount objects for an AG. + */ +size_t +refcount_record_count( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return slab_count(ag_rmaps[agno].ar_refcount_items); +} + +/* + * Return a slab cursor that will return refcount objects in order. + */ +int +init_refcount_cursor( + xfs_agnumber_t agno, + struct xfs_slab_cursor **cur) +{ + return init_slab_cursor(ag_rmaps[agno].ar_refcount_items, NULL, cur); +} + +/* + * Disable the refcount btree check. + */ +void +refcount_avoid_check(void) +{ + refcbt_suspect = true; +} + +/* + * Compare the observed reference counts against what's in the ag btree. + */ +int +check_refcounts( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_slab_cursor *rl_cur; + struct xfs_btree_cur *bt_cur = NULL; + int error; + int have; + int i; + struct xfs_buf *agbp = NULL; + struct xfs_refcount_irec *rl_rec; + struct xfs_refcount_irec tmp; + struct xfs_perag *pag; /* per allocation group data */ + + if (!xfs_sb_version_hasreflink(&mp->m_sb)) + return 0; + if (refcbt_suspect) { + if (no_modify && agno == 0) + do_warn(_("would rebuild corrupt refcount btrees.\n")); + return 0; + } + + /* Create cursors to refcount structures */ + error = init_refcount_cursor(agno, &rl_cur); + if (error) + return error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + goto err; + + /* Leave the per-ag data "uninitialized" since we rewrite it later */ + pag = xfs_perag_get(mp, agno); + pag->pagf_init = 0; + xfs_perag_put(pag); + + bt_cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); + if (!bt_cur) { + error = -ENOMEM; + goto err; + } + + rl_rec = pop_slab_cursor(rl_cur); + while (rl_rec) { + /* Look for a refcount record in the btree */ + error = xfs_refcountbt_lookup_le(bt_cur, + rl_rec->rc_startblock, &have); + if (error) + goto err; + if (!have) { + do_warn( +_("Missing reference count record for (%u/%u) len %u count %u\n"), + agno, rl_rec->rc_startblock, + rl_rec->rc_blockcount, rl_rec->rc_refcount); + goto next_loop; + } + + error = xfs_refcountbt_get_rec(bt_cur, &tmp, &i); + if (error) + goto err; + if (!i) { + do_warn( +_("Missing reference count record for (%u/%u) len %u count %u\n"), + agno, rl_rec->rc_startblock, + rl_rec->rc_blockcount, rl_rec->rc_refcount); + goto next_loop; + } + + /* Compare each refcount observation against the btree's */ + if (tmp.rc_startblock != rl_rec->rc_startblock || + tmp.rc_blockcount < rl_rec->rc_blockcount || + tmp.rc_refcount < rl_rec->rc_refcount) + do_warn( +_("Incorrect reference count: saw (%u/%u) len %u nlinks %u; should be (%u/%u) len %u nlinks %u\n"), + agno, tmp.rc_startblock, tmp.rc_blockcount, + tmp.rc_refcount, agno, rl_rec->rc_startblock, + rl_rec->rc_blockcount, rl_rec->rc_refcount); +next_loop: + rl_rec = pop_slab_cursor(rl_cur); + } + +err: + if (bt_cur) + xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); + if (agbp) + libxfs_putbuf(agbp); + free_slab_cursor(&rl_cur); + return 0; +} + +/* * Regenerate the AGFL so that we don't run out of it while rebuilding the * rmap btree. If skip_rmapbt is true, don't update the rmapbt (most probably * because we're updating the rmapbt). diff --git a/repair/rmap.h b/repair/rmap.h index d6d360f..d26c259 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -50,6 +50,11 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, struct xfs_rmap_irec *key); extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); +extern size_t refcount_record_count(struct xfs_mount *, xfs_agnumber_t); +extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); +extern void refcount_avoid_check(void); +extern int check_refcounts(struct xfs_mount *, xfs_agnumber_t); + extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *, xfs_agnumber_t, xfs_agino_t, xfs_ino_t); extern int fix_inode_reflink_flags(struct xfs_mount *, xfs_agnumber_t); diff --git a/repair/scan.c b/repair/scan.c index 8938341..4e78335 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1353,6 +1353,8 @@ _("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), } } out: + if (suspect) + refcount_avoid_check(); return; } @@ -2151,6 +2153,7 @@ validate_agf( } else { do_warn(_("bad agbno %u for refcntbt root, agno %d\n"), bno, agno); + refcount_avoid_check(); } } From darrick.wong@oracle.com Thu Jun 16 20:44:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AAA65846A for ; Thu, 16 Jun 2016 20:44:47 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 72E738F8050 for ; Thu, 16 Jun 2016 18:44:47 -0700 (PDT) X-ASG-Debug-ID: 1466127885-04cb6c542458540001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id m6plnk4s8txckiGS (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:46 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1if2X012259 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:41 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ifTg017848 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:41 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iecO025891; Fri, 17 Jun 2016 01:44:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:39 -0700 Subject: [PATCH 132/145] xfs_repair: check the CoW extent size hint From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 132/145] xfs_repair: check the CoW extent size hint To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:38 -0700 Message-ID: <146612787853.16048.11239305835199080494.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127885 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2405 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- repair/dinode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/repair/dinode.c b/repair/dinode.c index d48e415..9973f3e 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -2531,6 +2531,38 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), goto clear_bad_out; } + if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) && + !xfs_sb_version_hasreflink(&mp->m_sb)) { + if (!uncertain) { + do_warn( + _("inode %" PRIu64 " has CoW extent size hint but file system does not support reflink\n"), + lino); + } + flags2 &= ~XFS_DIFLAG2_COWEXTSIZE; + } + + if (flags2 & XFS_DIFLAG2_COWEXTSIZE) { + /* must be a directory or file */ + if (di_mode && !S_ISDIR(di_mode) && !S_ISREG(di_mode)) { + if (!uncertain) { + do_warn( + _("CoW extent size flag set on non-file, non-directory inode %" PRIu64 "\n" ), + lino); + } + flags2 &= ~XFS_DIFLAG2_COWEXTSIZE; + } + } + + if ((flags2 & XFS_DIFLAG2_COWEXTSIZE) && + (flags & (XFS_DIFLAG_REALTIME | XFS_DIFLAG_RTINHERIT))) { + if (!uncertain) { + do_warn( + _("Cannot have CoW extent size hint on a realtime inode %" PRIu64 "\n"), + lino); + } + flags2 &= ~XFS_DIFLAG2_COWEXTSIZE; + } + if (!verify_mode && flags2 != be64_to_cpu(dino->di_flags2)) { if (!no_modify) { do_warn(_("fixing bad flags2.\n")); @@ -2624,6 +2656,29 @@ _("bad non-zero extent size %u for non-realtime/extsize inode %" PRIu64 ", "), } /* + * Only (regular files and directories) with COWEXTSIZE flags + * set can have extsize set. + */ + if (dino->di_version >= 3 && + be32_to_cpu(dino->di_cowextsize) != 0) { + if ((type == XR_INO_DIR || type == XR_INO_DATA) && + (be64_to_cpu(dino->di_flags2) & + XFS_DIFLAG2_COWEXTSIZE)) { + /* s'okay */ ; + } else { + do_warn( +_("Cannot have non-zero CoW extent size %u on non-cowextsize inode %" PRIu64 ", "), + be32_to_cpu(dino->di_cowextsize), lino); + if (!no_modify) { + do_warn(_("resetting to zero\n")); + dino->di_cowextsize = 0; + *dirty = 1; + } else + do_warn(_("would reset to zero\n")); + } + } + + /* * general size/consistency checks: */ if (process_check_inode_sizes(mp, dino, lino, type) != 0) From darrick.wong@oracle.com Thu Jun 16 20:44:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C44748436 for ; Thu, 16 Jun 2016 20:44:52 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 738EE8F8050 for ; Thu, 16 Jun 2016 18:44:52 -0700 (PDT) X-ASG-Debug-ID: 1466127888-04bdf01e1596730001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id nc8bBBEcObl3w2eO (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:49 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1iZmg024450 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:35 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iYXe017722 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:34 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iYVv031364; Fri, 17 Jun 2016 01:44:34 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:33 -0700 Subject: [PATCH 131/145] xfs_repair: complain about copy-on-write leftovers From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 131/145] xfs_repair: complain about copy-on-write leftovers To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:32 -0700 Message-ID: <146612787245.16048.8651678769147816626.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127889 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3440 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Complain about leftover CoW allocations that are hanging off the refcount btree. These are cleaned out at mount time, but we could be louder about flagging down evidence of trouble. Since these extents aren't "owned" by anything, we'll free them up by reconstructing the free space btrees. Signed-off-by: Darrick J. Wong --- db/check.c | 21 +++++++++++++++++---- repair/incore.h | 3 ++- repair/scan.c | 25 ++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/db/check.c b/db/check.c index 3b17585..841a605 100644 --- a/db/check.c +++ b/db/check.c @@ -45,7 +45,7 @@ typedef enum { DBM_LOG, DBM_MISSING, DBM_QUOTA, DBM_RTBITMAP, DBM_RTDATA, DBM_RTFREE, DBM_RTSUM, DBM_SB, DBM_SYMLINK, DBM_BTFINO, DBM_BTRMAP, DBM_BTREFC, - DBM_RLDATA, + DBM_RLDATA, DBM_COWDATA, DBM_NDBM } dbm_t; @@ -4821,9 +4821,22 @@ scanfunc_refcnt( rp = XFS_REFCOUNT_REC_ADDR(block, 1); lastblock = 0; for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { - set_dbmap(seqno, be32_to_cpu(rp[i].rc_startblock), - be32_to_cpu(rp[i].rc_blockcount), DBM_RLDATA, - seqno, bno); + if (be32_to_cpu(rp[i].rc_refcount) == 1) { + dbprintf(_( + "leftover CoW extent (%u/%u) len %u\n"), + seqno, + be32_to_cpu(rp[i].rc_startblock), + be32_to_cpu(rp[i].rc_blockcount)); + set_dbmap(seqno, + be32_to_cpu(rp[i].rc_startblock), + be32_to_cpu(rp[i].rc_blockcount), + DBM_COWDATA, seqno, bno); + } else { + set_dbmap(seqno, + be32_to_cpu(rp[i].rc_startblock), + be32_to_cpu(rp[i].rc_blockcount), + DBM_RLDATA, seqno, bno); + } if (be32_to_cpu(rp[i].rc_startblock) < lastblock) { dbprintf(_( "out-of-order refcnt btree record %d (%u %u) block %u/%u\n"), diff --git a/repair/incore.h b/repair/incore.h index bcd2f4b..c23a3a3 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -107,7 +107,8 @@ typedef struct rt_extent_tree_node { #define XR_E_INO1 10 /* used by inodes (marked by rmap btree) */ #define XR_E_FS_MAP1 11 /* used by fs space/inode maps (rmap btree) */ #define XR_E_REFC 12 /* used by fs ag reference count btree */ -#define XR_E_BAD_STATE 13 +#define XR_E_COW 13 /* leftover cow extent */ +#define XR_E_BAD_STATE 14 /* separate state bit, OR'ed into high (4th) bit of ex_state field */ diff --git a/repair/scan.c b/repair/scan.c index 4e78335..1c2afb6 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1293,7 +1293,30 @@ _("%s btree block claimed (state %d), agno %d, bno %d, suspect %d\n"), continue; } - if (nr < 2 || nr > MAXREFCOUNT) { + if (nr == 1) { + xfs_agblock_t c; + xfs_extlen_t cnr; + + for (c = b; c < end; c += cnr) { + state = get_bmap_ext(agno, c, end, &cnr); + switch (state) { + case XR_E_COW: + break; + case XR_E_UNKNOWN: + do_warn( +_("leftover CoW extent (%u/%u) len %u\n"), + agno, c, cnr); + set_bmap_ext(agno, c, cnr, XR_E_FREE); + break; + default: + do_warn( +_("extent (%u/%u) len %u claimed, state is %d\n"), + agno, c, cnr, state); + set_bmap_ext(agno, c, cnr, XR_E_FREE); + break; + } + } + } else if (nr < 2 || nr > MAXREFCOUNT) { do_warn( _("invalid reference count %u in record %u of %s btree block %u/%u\n"), nr, i, name, agno, bno); From darrick.wong@oracle.com Thu Jun 16 20:44:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B68178474 for ; Thu, 16 Jun 2016 20:44:56 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2A8A0AC001 for ; Thu, 16 Jun 2016 18:44:56 -0700 (PDT) X-ASG-Debug-ID: 1466127893-04cbb01fef6a910001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ees1io5VaHKZ0r7u (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:54 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1in99012310 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:49 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1im6k013242 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:49 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ikmK013727; Fri, 17 Jun 2016 01:44:47 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:45 -0700 Subject: [PATCH 133/145] xfs_repair: use range query when while checking rmaps From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 133/145] xfs_repair: use range query when while checking rmaps To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:44 -0700 Message-ID: <146612788463.16048.1497238555000280268.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127894 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2180 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines For shared extents, we ought to use a range query on the rmapbt to find the corresponding rmap. However, most of the time the observed rmap will be an exact match for the rmapbt rmap, in which case we could have used the (much faster) regular lookup. Therefore, try the regular lookup first and resort to the range lookup if that doesn't get us what we want. This can cut the run time of the rmap check of xfs_repair in half. Theoretically, the only reason why an observed rmap wouldn't be an exact match for an rmapbt rmap is because we modified some file on account of a metadata error. Signed-off-by: Darrick J. Wong --- repair/rmap.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/repair/rmap.c b/repair/rmap.c index 5c0e015..1b89d4c 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -909,6 +909,20 @@ lookup_rmap( return xfs_rmap_get_rec(bt_cur, tmp, have); } +/* Look for an rmap in the rmapbt that matches a given rmap. */ +static int +lookup_rmap_overlapped( + struct xfs_btree_cur *bt_cur, + struct xfs_rmap_irec *rm_rec, + struct xfs_rmap_irec *tmp, + int *have) +{ + /* Have to use our fancy version for overlapped */ + return xfs_rmap_lookup_le_range(bt_cur, rm_rec->rm_startblock, + rm_rec->rm_owner, rm_rec->rm_offset, + rm_rec->rm_flags, tmp, have); +} + /* Does the btree rmap cover the observed rmap? */ #define NEXTP(x) ((x)->rm_startblock + (x)->rm_blockcount) #define NEXTL(x) ((x)->rm_offset + (x)->rm_blockcount) @@ -997,6 +1011,18 @@ check_rmaps( error = lookup_rmap(bt_cur, rm_rec, &tmp, &have); if (error) goto err; + /* + * Using the range query is expensive, so only do it if + * the regular lookup doesn't find anything or if it doesn't + * match the observed rmap. + */ + if (xfs_sb_version_hasreflink(&bt_cur->bc_mp->m_sb) && + (!have || !is_good_rmap(rm_rec, &tmp))) { + error = lookup_rmap_overlapped(bt_cur, rm_rec, + &tmp, &have); + if (error) + goto err; + } if (!have) { do_warn( _("Missing reverse-mapping record for (%u/%u) %slen %u owner %"PRId64" \ From darrick.wong@oracle.com Thu Jun 16 20:44:58 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C66B48481 for ; Thu, 16 Jun 2016 20:44:58 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8D68830404E for ; Thu, 16 Jun 2016 18:44:58 -0700 (PDT) X-ASG-Debug-ID: 1466127896-04cb6c5427585a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 6fhJiAnhLrhwOoFN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:44:56 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1isgt024582 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:55 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1isOO005271 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:44:54 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iq5D013742; Fri, 17 Jun 2016 01:44:53 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:52 -0700 Subject: [PATCH 134/145] xfs_repair: check for mergeable refcount records From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 134/145] xfs_repair: check for mergeable refcount records To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:50 -0700 Message-ID: <146612789069.16048.5418520558159694317.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127896 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2117 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Make sure there aren't adjacent refcount records that could be merged; this is a sign that the refcount tree algorithms aren't working correctly. Signed-off-by: Darrick J. Wong --- repair/scan.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/repair/scan.c b/repair/scan.c index 1c2afb6..d2e588a 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1195,6 +1195,11 @@ out: rmap_avoid_check(); } +struct refc_priv { + struct xfs_refcount_irec last_rec; +}; + + static void scan_refcbt( struct xfs_btree_block *block, @@ -1214,6 +1219,7 @@ scan_refcbt( int numrecs; int state; xfs_agblock_t lastblock = 0; + struct refc_priv *refc_priv = priv; if (magic != XFS_REFC_CRC_MAGIC) { name = "(unknown)"; @@ -1331,6 +1337,20 @@ _("extent (%u/%u) len %u claimed, state is %d\n"), lastblock = b; } + /* Is this record mergeable with the last one? */ + if (refc_priv->last_rec.rc_startblock + + refc_priv->last_rec.rc_blockcount == b && + refc_priv->last_rec.rc_refcount == nr) { + do_warn( + _("record %d in block (%u/%u) of %s tree should be merged with previous record\n"), + i, agno, bno, name); + refc_priv->last_rec.rc_blockcount += len; + } else { + refc_priv->last_rec.rc_startblock = b; + refc_priv->last_rec.rc_blockcount = len; + refc_priv->last_rec.rc_refcount = nr; + } + /* XXX: probably want to mark the reflinked areas? */ } goto out; @@ -2169,10 +2189,13 @@ validate_agf( if (xfs_sb_version_hasreflink(&mp->m_sb)) { bno = be32_to_cpu(agf->agf_refcount_root); if (bno != 0 && verify_agbno(mp, agno, bno)) { + struct refc_priv priv; + + memset(&priv, 0, sizeof(priv)); scan_sbtree(bno, be32_to_cpu(agf->agf_refcount_level), agno, 0, scan_refcbt, 1, XFS_REFC_CRC_MAGIC, - agcnts, &xfs_refcountbt_buf_ops); + &priv, &xfs_refcountbt_buf_ops); } else { do_warn(_("bad agbno %u for refcntbt root, agno %d\n"), bno, agno); From darrick.wong@oracle.com Thu Jun 16 20:45:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C41A38457 for ; Thu, 16 Jun 2016 20:45:09 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8CB688F804B for ; Thu, 16 Jun 2016 18:45:09 -0700 (PDT) X-ASG-Debug-ID: 1466127907-04cbb01fec6a940001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id sWJjWambzLTy4JaK (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:07 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1j5es024972 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:06 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1j5vH018519 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:05 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1j4T6003809; Fri, 17 Jun 2016 01:45:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:04 -0700 Subject: [PATCH 136/145] xfs: introduce the XFS_IOC_GETFSMAPX ioctl From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 136/145] xfs: introduce the XFS_IOC_GETFSMAPX ioctl To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:03 -0700 Message-ID: <146612790296.16048.8214179908320601737.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127907 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6775 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Introduce a new ioctl that uses the reverse mapping btree to return information about the physical layout of the filesystem. Signed-off-by: Darrick J. Wong --- libxfs/xfs_fs.h | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_refcount.c | 51 +++++++++++++++++++++++++++++----------- libxfs/xfs_refcount.h | 4 +++ 3 files changed, 103 insertions(+), 14 deletions(-) diff --git a/libxfs/xfs_fs.h b/libxfs/xfs_fs.h index df58c1c..236a5a7 100644 --- a/libxfs/xfs_fs.h +++ b/libxfs/xfs_fs.h @@ -117,6 +117,67 @@ struct getbmapx { #define BMV_OF_SHARED 0x8 /* segment shared with another file */ /* + * Structure for XFS_IOC_GETFSMAPX. + * + * Similar to XFS_IOC_GETBMAPX, the first two elements in the array are + * used to constrain the output. The first element in the array should + * represent the lowest disk address that the user wants to learn about. + * The second element in the array should represent the highest disk + * address to query. Subsequent array elements will be filled out by the + * command. + * + * The fmv_iflags field is only used in the first structure. The + * fmv_oflags field is filled in for each returned structure after the + * second structure. The fmv_unused1 fields in the first two array + * elements must be zero. + * + * The fmv_count, fmv_entries, and fmv_iflags fields in the second array + * element must be zero. + * + * fmv_block, fmv_offset, and fmv_length are expressed in units of 512 + * byte sectors. + */ +#ifndef HAVE_GETFSMAPX +struct getfsmapx { + __u32 fmv_device; /* device id */ + __u32 fmv_unused1; /* future use, must be zero */ + __u64 fmv_block; /* starting block */ + __u64 fmv_owner; /* owner id */ + __u64 fmv_offset; /* file offset of segment */ + __u64 fmv_length; /* length of segment, blocks */ + __u32 fmv_oflags; /* mapping flags */ + __u32 fmv_iflags; /* control flags (1st structure) */ + __u32 fmv_count; /* # of entries in array incl. input */ + __u32 fmv_entries; /* # of entries filled in (output). */ + __u64 fmv_unused2; /* future use, must be zero */ +}; +#endif + +/* fmv_flags values - set by XFS_IOC_GETFSMAPX caller. */ +/* no flags defined yet */ +#define FMV_IF_VALID 0 + +/* fmv_flags values - returned for each non-header segment */ +#define FMV_OF_PREALLOC 0x1 /* segment = unwritten pre-allocation */ +#define FMV_OF_ATTR_FORK 0x2 /* segment = attribute fork */ +#define FMV_OF_EXTENT_MAP 0x4 /* segment = extent map */ +#define FMV_OF_SHARED 0x8 /* segment = shared with another file */ +#define FMV_OF_SPECIAL_OWNER 0x10 /* owner is a special value */ +#define FMV_OF_LAST 0x20 /* segment is the last in the FS */ + +/* fmv_owner special values */ +#define FMV_OWN_FREE (-1ULL) /* free space */ +#define FMV_OWN_UNKNOWN (-2ULL) /* unknown owner */ +#define FMV_OWN_FS (-3ULL) /* static fs metadata */ +#define FMV_OWN_LOG (-4ULL) /* journalling log */ +#define FMV_OWN_AG (-5ULL) /* per-AG metadata */ +#define FMV_OWN_INOBT (-6ULL) /* inode btree blocks */ +#define FMV_OWN_INODES (-7ULL) /* inodes */ +#define FMV_OWN_REFC (-8ULL) /* refcount tree */ +#define FMV_OWN_COW (-9ULL) /* cow allocations */ +#define FMV_OWN_DEFECTIVE (-10ULL) /* bad blocks */ + +/* * Structure for XFS_IOC_FSSETDM. * For use by backup and restore programs to set the XFS on-disk inode * fields di_dmevmask and di_dmstate. These must be set to exactly and @@ -523,6 +584,7 @@ typedef struct xfs_swapext #define XFS_IOC_GETBMAPX _IOWR('X', 56, struct getbmap) #define XFS_IOC_ZERO_RANGE _IOW ('X', 57, struct xfs_flock64) #define XFS_IOC_FREE_EOFBLOCKS _IOR ('X', 58, struct xfs_fs_eofblocks) +#define XFS_IOC_GETFSMAPX _IOWR('X', 59, struct getfsmapx) /* * ioctl commands that replace IRIX syssgi()'s diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index 855ab54..a19cb45 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -1171,8 +1171,9 @@ xfs_refcount_decrease_extent( * extent we find. If no shared blocks are found, flen will be set to zero. */ int -xfs_refcount_find_shared( +__xfs_refcount_find_shared( struct xfs_mount *mp, + struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen, @@ -1181,23 +1182,13 @@ xfs_refcount_find_shared( bool find_maximal) { struct xfs_btree_cur *cur; - struct xfs_buf *agbp; struct xfs_refcount_irec tmp; - int error; int i, have; int bt_error = XFS_BTREE_ERROR; + int error; trace_xfs_refcount_find_shared(mp, agno, agbno, aglen); - if (xfs_always_cow) { - *fbno = agbno; - *flen = aglen; - return 0; - } - - error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); - if (error) - goto out; cur = xfs_refcountbt_init_cursor(mp, NULL, agbp, agno, NULL); /* By default, skip the whole range */ @@ -1272,14 +1263,46 @@ done: out_error: xfs_btree_del_cursor(cur, bt_error); - xfs_buf_relse(agbp); -out: if (error) trace_xfs_refcount_find_shared_error(mp, agno, error, _RET_IP_); return error; } /* + * Given an AG extent, find the lowest-numbered run of shared blocks within + * that range and return the range in fbno/flen. + */ +int +xfs_refcount_find_shared( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_agblock_t agbno, + xfs_extlen_t aglen, + xfs_agblock_t *fbno, + xfs_extlen_t *flen, + bool find_maximal) +{ + struct xfs_buf *agbp; + int error; + + if (xfs_always_cow) { + *fbno = agbno; + *flen = aglen; + return 0; + } + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) + return error; + + error = __xfs_refcount_find_shared(mp, agbp, agno, agbno, aglen, + fbno, flen, find_maximal); + + xfs_buf_relse(agbp); + return error; +} + +/* * Recovering CoW Blocks After a Crash * * Due to the way that the copy on write mechanism works, there's a window of diff --git a/libxfs/xfs_refcount.h b/libxfs/xfs_refcount.h index 6665eeb..44b0346 100644 --- a/libxfs/xfs_refcount.h +++ b/libxfs/xfs_refcount.h @@ -53,6 +53,10 @@ extern int xfs_refcount_finish_one(struct xfs_trans *tp, xfs_fsblock_t startblock, xfs_extlen_t blockcount, xfs_extlen_t *adjusted, struct xfs_btree_cur **pcur); +extern int __xfs_refcount_find_shared(struct xfs_mount *mp, + struct xfs_buf *agbp, xfs_agnumber_t agno, xfs_agblock_t agbno, + xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, + bool find_maximal); extern int xfs_refcount_find_shared(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agblock_t agbno, xfs_extlen_t aglen, xfs_agblock_t *fbno, xfs_extlen_t *flen, bool find_maximal); From darrick.wong@oracle.com Thu Jun 16 20:45:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 873DE8494 for ; Thu, 16 Jun 2016 20:45:23 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4987F8F804B for ; Thu, 16 Jun 2016 18:45:23 -0700 (PDT) X-ASG-Debug-ID: 1466127918-04cb6c5425585c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id BuV9BSCH9ZGQLWFr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:19 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jHMV025535 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:45:17 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1jHsf012177 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:45:17 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1jHUU004138; Fri, 17 Jun 2016 01:45:17 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:16 -0700 Subject: [PATCH 138/145] xfs_io: support the new getfsmap ioctl From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 138/145] xfs_io: support the new getfsmap ioctl To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:15 -0700 Message-ID: <146612791523.16048.4631582604422386010.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127919 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17741 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- io/Makefile | 2 io/fsmap.c | 488 +++++++++++++++++++++++++++++++++++++++++++++++++++++ io/init.c | 1 io/io.h | 1 man/man8/xfs_io.8 | 47 +++++ 5 files changed, 538 insertions(+), 1 deletion(-) create mode 100644 io/fsmap.c diff --git a/io/Makefile b/io/Makefile index 0b53f41..6439e1d 100644 --- a/io/Makefile +++ b/io/Makefile @@ -11,7 +11,7 @@ HFILES = init.h io.h CFILES = init.c \ attr.c bmap.c file.c freeze.c fsync.c getrusage.c imap.c link.c \ mmap.c open.c parent.c pread.c prealloc.c pwrite.c seek.c shutdown.c \ - sync.c truncate.c reflink.c + sync.c truncate.c reflink.c fsmap.c LLDLIBS = $(LIBXCMD) $(LIBHANDLE) LTDEPENDENCIES = $(LIBXCMD) $(LIBHANDLE) diff --git a/io/fsmap.c b/io/fsmap.c new file mode 100644 index 0000000..7cf3776 --- /dev/null +++ b/io/fsmap.c @@ -0,0 +1,488 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "platform_defs.h" +#include "command.h" +#include "init.h" +#include "io.h" +#include "input.h" + +static cmdinfo_t fsmap_cmd; + +static void +fsmap_help(void) +{ + printf(_( +"\n" +" prints the block mapping for an XFS filesystem" +"\n" +" Example:\n" +" 'fsmap -vp' - tabular format verbose map, including unwritten extents\n" +"\n" +" fsmap prints the map of disk blocks used by the whole filesystem.\n" +" The map lists each extent used by the file, as well as regions in the\n" +" filesystem that do not have any corresponding blocks (free space).\n" +" By default, each line of the listing takes the following form:\n" +" extent: [startoffset..endoffset] owner startblock..endblock\n" +" All the file offsets and disk blocks are in units of 512-byte blocks.\n" +" -n -- query n extents.\n" +" -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" +"\n")); +} + +static int +numlen( + off64_t val) +{ + off64_t tmp; + int len; + + for (len = 0, tmp = val; tmp > 0; tmp = tmp/10) + len++; + return (len == 0 ? 1 : len); +} + +static const char * +special_owner( + __int64_t owner) +{ + switch (owner) { + case FMV_OWN_FREE: + return _("free space"); + case FMV_OWN_UNKNOWN: + return _("unknown"); + case FMV_OWN_FS: + return _("static fs metadata"); + case FMV_OWN_LOG: + return _("journalling log"); + case FMV_OWN_AG: + return _("per-AG metadata"); + case FMV_OWN_INOBT: + return _("inode btree"); + case FMV_OWN_INODES: + return _("inodes"); + case FMV_OWN_REFC: + return _("refcount btree"); + case FMV_OWN_COW: + return _("cow reservation"); + case FMV_OWN_DEFECTIVE: + return _("defective"); + default: + return _("unknown"); + } +} + +static void +dump_map( + unsigned long long nr, + struct getfsmapx *map) +{ + unsigned long long i; + struct getfsmapx *p; + + for (i = 0, p = map + 2; i < map->fmv_entries; i++, p++) { + printf("\t%llu: %u:%u [%lld..%lld]: ", i + nr, + major(p->fmv_device), minor(p->fmv_device), + (long long) p->fmv_block, + (long long)(p->fmv_block + p->fmv_length - 1)); + if (p->fmv_oflags & FMV_OF_SPECIAL_OWNER) + printf("%s", special_owner(p->fmv_owner)); + else if (p->fmv_oflags & FMV_OF_EXTENT_MAP) + printf(_("inode %lld extent map"), + (long long) p->fmv_owner); + else + printf(_("inode %lld %lld..%lld"), + (long long) p->fmv_owner, + (long long) p->fmv_offset, + (long long)(p->fmv_offset + p->fmv_length - 1)); + printf(_(" %lld blocks\n"), + (long long)p->fmv_length); + } +} + +/* + * Verbose mode displays: + * extent: major:minor [startblock..endblock]: startoffset..endoffset \ + * ag# (agoffset..agendoffset) totalbbs flags + */ +#define MINRANGE_WIDTH 16 +#define MINAG_WIDTH 2 +#define MINTOT_WIDTH 5 +#define NFLG 7 /* count of flags */ +#define FLG_NULL 00000000 /* Null flag */ +#define FLG_SHARED 01000000 /* shared extent */ +#define FLG_ATTR_FORK 00100000 /* attribute fork */ +#define FLG_PRE 00010000 /* Unwritten extent */ +#define FLG_BSU 00001000 /* Not on begin of stripe unit */ +#define FLG_ESU 00000100 /* Not on end of stripe unit */ +#define FLG_BSW 00000010 /* Not on begin of stripe width */ +#define FLG_ESW 00000001 /* Not on end of stripe width */ +static void +dump_map_verbose( + unsigned long long nr, + struct getfsmapx *map, + bool *dumped_flags, + struct xfs_fsop_geom *fsgeo) +{ + unsigned long long i; + struct getfsmapx *p; + int agno; + off64_t agoff, bbperag; + int foff_w, boff_w, aoff_w, tot_w, agno_w, own_w, nr_w, dev_w; + char rbuf[32], bbuf[32], abuf[32], obuf[32], nbuf[32], dbuf[32]; + int sunit, swidth; + int flg = 0; + + foff_w = boff_w = aoff_w = own_w = MINRANGE_WIDTH; + dev_w = 3; + nr_w = 4; + tot_w = MINTOT_WIDTH; + bbperag = (off64_t)fsgeo->agblocks * + (off64_t)fsgeo->blocksize / BBSIZE; + sunit = (fsgeo->sunit * fsgeo->blocksize) / BBSIZE; + swidth = (fsgeo->swidth * fsgeo->blocksize) / BBSIZE; + + /* + * Go through the extents and figure out the width + * needed for all columns. + */ + for (i = 0, p = map + 2; i < map->fmv_entries; i++, p++) { + if (p->fmv_oflags & FMV_OF_PREALLOC || + p->fmv_oflags & FMV_OF_ATTR_FORK || + p->fmv_oflags & FMV_OF_SHARED) + flg = 1; + if (sunit && + (p->fmv_block % sunit != 0 || + ((p->fmv_block + p->fmv_length) % sunit) != 0 || + p->fmv_block % swidth != 0 || + ((p->fmv_block + p->fmv_length) % swidth) != 0)) + flg = 1; + if (flg) + *dumped_flags = true; + snprintf(nbuf, sizeof(nbuf), "%llu", nr + i); + nr_w = max(nr_w, strlen(nbuf)); + snprintf(dbuf, sizeof(dbuf), "%u:%u", major(p->fmv_device), + minor(p->fmv_device)); + dev_w = max(dev_w, strlen(dbuf)); + snprintf(bbuf, sizeof(bbuf), "[%lld..%lld]:", + (long long) p->fmv_block, + (long long)(p->fmv_block + p->fmv_length - 1)); + boff_w = max(boff_w, strlen(bbuf)); + if (p->fmv_oflags & FMV_OF_SPECIAL_OWNER) + own_w = max(own_w, strlen(special_owner(p->fmv_owner))); + else { + snprintf(obuf, sizeof(obuf), "%lld", + (long long)p->fmv_owner); + own_w = max(own_w, strlen(obuf)); + } + if (p->fmv_oflags & FMV_OF_EXTENT_MAP) + foff_w = max(foff_w, strlen(_("extent_map"))); + else if (p->fmv_oflags & FMV_OF_SPECIAL_OWNER) + ; + else { + snprintf(rbuf, sizeof(rbuf), "%lld..%lld", + (long long) p->fmv_offset, + (long long)(p->fmv_offset + p->fmv_length - 1)); + foff_w = max(foff_w, strlen(rbuf)); + } + agno = p->fmv_block / bbperag; + agoff = p->fmv_block - (agno * bbperag); + snprintf(abuf, sizeof(abuf), + "(%lld..%lld)", + (long long)agoff, + (long long)(agoff + p->fmv_length - 1)); + aoff_w = max(aoff_w, strlen(abuf)); + tot_w = max(tot_w, + numlen(p->fmv_length)); + } + agno_w = max(MINAG_WIDTH, numlen(fsgeo->agcount)); + if (nr == 0) + printf("%*s: %-*s %-*s %-*s %-*s %*s %-*s %*s%s\n", + nr_w, _("EXT"), + dev_w, _("DEV"), + boff_w, _("BLOCK-RANGE"), + own_w, _("OWNER"), + foff_w, _("FILE-OFFSET"), + agno_w, _("AG"), + aoff_w, _("AG-OFFSET"), + tot_w, _("TOTAL"), + flg ? _(" FLAGS") : ""); + for (i = 0, p = map + 2; i < map->fmv_entries; i++, p++) { + flg = FLG_NULL; + if (p->fmv_oflags & FMV_OF_PREALLOC) + flg |= FLG_PRE; + if (p->fmv_oflags & FMV_OF_ATTR_FORK) + flg |= FLG_ATTR_FORK; + if (p->fmv_oflags & FMV_OF_SHARED) + flg |= FLG_SHARED; + /* + * If striping enabled, determine if extent starts/ends + * on a stripe unit boundary. + */ + if (sunit) { + if (p->fmv_block % sunit != 0) + flg |= FLG_BSU; + if (((p->fmv_block + + p->fmv_length ) % sunit ) != 0) + flg |= FLG_ESU; + if (p->fmv_block % swidth != 0) + flg |= FLG_BSW; + if (((p->fmv_block + + p->fmv_length ) % swidth ) != 0) + flg |= FLG_ESW; + } + snprintf(dbuf, sizeof(dbuf), "%u:%u", major(p->fmv_device), + minor(p->fmv_device)); + snprintf(bbuf, sizeof(bbuf), "[%lld..%lld]:", + (long long) p->fmv_block, + (long long)(p->fmv_block + p->fmv_length - 1)); + if (p->fmv_oflags & FMV_OF_SPECIAL_OWNER) { + snprintf(obuf, sizeof(obuf), "%s", + special_owner(p->fmv_owner)); + snprintf(rbuf, sizeof(rbuf), " "); + } else { + snprintf(obuf, sizeof(obuf), "%lld", + (long long)p->fmv_owner); + snprintf(rbuf, sizeof(rbuf), "%lld..%lld", + (long long) p->fmv_offset, + (long long)(p->fmv_offset + p->fmv_length - 1)); + } + agno = p->fmv_block / bbperag; + agoff = p->fmv_block - (agno * bbperag); + snprintf(abuf, sizeof(abuf), + "(%lld..%lld)", + (long long)agoff, + (long long)(agoff + p->fmv_length - 1)); + if (p->fmv_oflags & FMV_OF_EXTENT_MAP) + printf("%*llu: %-*s %-*s %-*s %-*s %*d %-*s %*lld\n", + nr_w, nr + i, + dev_w, dbuf, + boff_w, bbuf, + own_w, obuf, + foff_w, _("extent map"), + agno_w, agno, + aoff_w, abuf, + tot_w, (long long)p->fmv_length); + else { + printf("%*llu: %-*s %-*s %-*s %-*s", nr_w, nr + i, + dev_w, dbuf, boff_w, bbuf, own_w, obuf, + foff_w, rbuf); + printf(" %*d %-*s", agno_w, agno, + aoff_w, abuf); + printf(" %*lld", tot_w, + (long long)p->fmv_length); + if (flg == FLG_NULL) + printf("\n"); + else + printf(" %-*.*o\n", NFLG, NFLG, flg); + } + } +} + +static void +dump_verbose_key(void) +{ + printf(_(" FLAG Values:\n")); + printf(_(" %*.*o Shared extent\n"), + NFLG+1, NFLG+1, FLG_SHARED); + printf(_(" %*.*o Attribute fork\n"), + NFLG+1, NFLG+1, FLG_ATTR_FORK); + printf(_(" %*.*o Unwritten preallocated extent\n"), + NFLG+1, NFLG+1, FLG_PRE); + printf(_(" %*.*o Doesn't begin on stripe unit\n"), + NFLG+1, NFLG+1, FLG_BSU); + printf(_(" %*.*o Doesn't end on stripe unit\n"), + NFLG+1, NFLG+1, FLG_ESU); + printf(_(" %*.*o Doesn't begin on stripe width\n"), + NFLG+1, NFLG+1, FLG_BSW); + printf(_(" %*.*o Doesn't end on stripe width\n"), + NFLG+1, NFLG+1, FLG_ESW); +} + +int +fsmap_f( + int argc, + char **argv) +{ + struct getfsmapx *p; + struct getfsmapx *nmap; + struct getfsmapx *map; + struct xfs_fsop_geom fsgeo; + long long start = 0; + long long end = -1; + int nmap_size; + int map_size; + int nflag = 0; + int vflag = 0; + int fmv_iflags = 0; /* flags for GETFSMAPX */ + int i = 0; + int c; + unsigned long long nr = 0; + size_t fsblocksize, fssectsize; + bool dumped_flags = false; + + init_cvtnum(&fsblocksize, &fssectsize); + + while ((c = getopt(argc, argv, "n:v")) != EOF) { + switch (c) { + case 'n': /* number of extents specified */ + nflag = atoi(optarg); + break; + case 'v': /* Verbose output */ + vflag++; + break; + default: + return command_usage(&fsmap_cmd); + } + } + + if (argc > optind) { + start = cvtnum(fsblocksize, fssectsize, argv[optind]); + if (start < 0) { + fprintf(stderr, + _("Bad rmap start_fsb %s.\n"), + argv[optind]); + return 0; + } + } + + if (argc > optind + 1) { + end = cvtnum(fsblocksize, fssectsize, argv[optind + 1]); + if (end < 0) { + fprintf(stderr, + _("Bad rmap end_fsb %s.\n"), + argv[optind + 1]); + return 0; + } + } + + if (vflag) { + c = xfsctl(file->name, file->fd, XFS_IOC_FSGEOMETRY_V1, &fsgeo); + if (c < 0) { + fprintf(stderr, + _("%s: can't get geometry [\"%s\"]: %s\n"), + progname, file->name, strerror(errno)); + exitcode = 1; + return 0; + } + } + + map_size = nflag ? nflag + 2 : 32; /* initial guess - 32 */ + map = malloc(map_size * sizeof(*map)); + if (map == NULL) { + fprintf(stderr, _("%s: malloc of %zu bytes failed.\n"), + progname, map_size * sizeof(*map)); + exitcode = 1; + return 0; + } + + memset(map, 0, sizeof(*map) * 2); + map->fmv_iflags = fmv_iflags; + map->fmv_block = start / 512; + (map + 1)->fmv_device = UINT_MAX; + (map + 1)->fmv_block = (unsigned long long)end / 512; + (map + 1)->fmv_owner = ULLONG_MAX; + (map + 1)->fmv_offset = ULLONG_MAX; + + /* Count mappings */ + if (!nflag) { + map->fmv_count = 2; + i = xfsctl(file->name, file->fd, XFS_IOC_GETFSMAPX, map); + if (i < 0) { + fprintf(stderr, _("%s: xfsctl(XFS_IOC_GETFSMAPX)" + " iflags=0x%x [\"%s\"]: %s\n"), + progname, map->fmv_iflags, file->name, + strerror(errno)); + free(map); + exitcode = 1; + return 0; + } + if (map->fmv_entries > map_size * 2) { + unsigned long long nr; + + nr = 5ULL * map->fmv_entries / 4 + 2; + nmap_size = nr > INT_MAX ? INT_MAX : nr; + nmap = realloc(map, nmap_size * sizeof(*map)); + if (nmap == NULL) { + fprintf(stderr, + _("%s: cannot realloc %zu bytes\n"), + progname, map_size*sizeof(*map)); + } else { + map = nmap; + map_size = nmap_size; + } + } + } + + map->fmv_count = map_size; + do { + /* Get some extents */ + i = xfsctl(file->name, file->fd, XFS_IOC_GETFSMAPX, map); + if (i < 0) { + fprintf(stderr, _("%s: xfsctl(XFS_IOC_GETFSMAPX)" + " iflags=0x%x [\"%s\"]: %s\n"), + progname, map->fmv_iflags, file->name, + strerror(errno)); + free(map); + exitcode = 1; + return 0; + } + + if (map->fmv_entries == 0) + break; + + if (!vflag) + dump_map(nr, map); + else + dump_map_verbose(nr, map, &dumped_flags, &fsgeo); + + p = map + 1 + map->fmv_entries; + if (p->fmv_oflags & FMV_OF_LAST) + break; + + nr += map->fmv_entries; + map->fmv_device = p->fmv_device; + map->fmv_block = p->fmv_block; + map->fmv_owner = p->fmv_owner; + map->fmv_offset = p->fmv_offset; + map->fmv_oflags = p->fmv_oflags; + map->fmv_length = p->fmv_length; + } while (true); + + if (dumped_flags) + dump_verbose_key(); + + free(map); + return 0; +} + +void +fsmap_init(void) +{ + fsmap_cmd.name = "fsmap"; + fsmap_cmd.cfunc = fsmap_f; + fsmap_cmd.argmin = 0; + fsmap_cmd.argmax = -1; + fsmap_cmd.flags = CMD_NOMAP_OK; + fsmap_cmd.args = _("[-v] [-n nx] [start] [end]"); + fsmap_cmd.oneline = _("print filesystem mapping for a range of blocks"); + fsmap_cmd.help = fsmap_help; + + add_command(&fsmap_cmd); +} diff --git a/io/init.c b/io/init.c index 51f1f5c..4ae8274 100644 --- a/io/init.c +++ b/io/init.c @@ -60,6 +60,7 @@ init_commands(void) file_init(); flink_init(); freeze_init(); + fsmap_init(); fsync_init(); getrusage_init(); help_init(); diff --git a/io/io.h b/io/io.h index 172b1f8..cef1763 100644 --- a/io/io.h +++ b/io/io.h @@ -97,6 +97,7 @@ extern void bmap_init(void); extern void file_init(void); extern void flink_init(void); extern void freeze_init(void); +extern void fsmap_init(void); extern void fsync_init(void); extern void getrusage_init(void); extern void help_init(void); diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 index cc70b7c..2872f13 100644 --- a/man/man8/xfs_io.8 +++ b/man/man8/xfs_io.8 @@ -267,6 +267,53 @@ ioctl. Options behave as described in the .BR xfs_bmap (8) manual page. .TP +.BI "fsmap [ \-v ] [ \-n " nx " ] [ " start " ] [ " end " ] +Prints the mapping of disk blocks used by an XFS filesystem. The map +lists each extent used by files, allocation group metadata, +journalling logs, and static filesystem metadata, as well as any +regions that are unused. Each line of the listings takes the +following form: +.PP +.RS +.IR extent ": " major ":" minor " [" startblock .. endblock "]: " owner " " startoffset .. endoffset " " length +.PP +Static filesystem metadata, allocation group metadata, btrees, +journalling logs, and free space are marked by replacing the +.IR startoffset .. endoffset +with the appropriate marker. All blocks, offsets, and lengths are specified +in units of 512-byte blocks, no matter what the filesystem's block size is. +.BI "The optional " start " and " end " arguments can be used to constrain +the output to a particular range of disk blocks. +.RE +.RS 1.0i +.PD 0 +.TP +.BI \-n " num_extents" +If this option is given, +.B xfs_fsmap +obtains the extent list of the file in groups of +.I num_extents +extents. In the absence of +.BR \-n ", " xfs_fsmap +queries the system for the number of extents in the filesystem and uses that +value to compute the group size. +.TP +.B \-v +Shows verbose information. When this flag is specified, additional AG +specific information is appended to each line in the following form: +.IP +.RS 1.2i +.IR agno " (" startagblock .. endagblock ") " nblocks " " flags +.RE +.IP +A second +.B \-v +option will print out the +.I flags +legend. +.RE +.PD +.TP .BI "extsize [ \-R | \-D ] [ " value " ]" Display and/or modify the preferred extent size used when allocating space for the currently open file. If the From darrick.wong@oracle.com Thu Jun 16 20:45:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 3397283F3 for ; Thu, 16 Jun 2016 20:45:30 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 02DB78F804B for ; Thu, 16 Jun 2016 18:45:29 -0700 (PDT) X-ASG-Debug-ID: 1466127925-04cbb01fef6a9a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id hagkMOwN8muQXSp4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jNBI025574 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:24 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jNga014474 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:23 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1jNuf004173; Fri, 17 Jun 2016 01:45:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:22 -0700 Subject: [PATCH 139/145] xfs: scrub btree records and pointers while querying From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 139/145] xfs: scrub btree records and pointers while querying To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:21 -0700 Message-ID: <146612792154.16048.3444883625309291288.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127925 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 22226 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Create a function that walks a btree, checking the integrity of each btree block (headers, keys, records) and calling back to the caller to perform further checks on the records. v2: Prefix function names with xfs_ Signed-off-by: Darrick J. Wong --- libxfs/Makefile | 2 libxfs/xfs_alloc.c | 33 ++++ libxfs/xfs_alloc.h | 3 libxfs/xfs_btree.c | 12 + libxfs/xfs_btree.h | 15 ++ libxfs/xfs_format.h | 2 libxfs/xfs_rmap.c | 39 +++++ libxfs/xfs_rmap_btree.h | 3 libxfs/xfs_scrub.c | 396 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_scrub.h | 76 +++++++++ 10 files changed, 572 insertions(+), 9 deletions(-) create mode 100644 libxfs/xfs_scrub.c create mode 100644 libxfs/xfs_scrub.h diff --git a/libxfs/Makefile b/libxfs/Makefile index 4b1ada0..a2188ec 100644 --- a/libxfs/Makefile +++ b/libxfs/Makefile @@ -41,6 +41,7 @@ HFILES = \ xfs_refcount_btree.h \ xfs_rmap_btree.h \ xfs_sb.h \ + xfs_scrub.h \ xfs_shared.h \ xfs_trans_resv.h \ xfs_trans_space.h \ @@ -93,6 +94,7 @@ CFILES = cache.c \ xfs_rmap_btree.c \ xfs_rtbitmap.c \ xfs_sb.c \ + xfs_scrub.c \ xfs_symlink_remote.c \ xfs_trans_resv.c diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 33087e6..7ab05e3 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -2920,3 +2920,36 @@ err: xfs_trans_brelse(tp, agbp); return error; } + +/* Is there a record covering a given extent? */ +int +xfs_alloc_record_exists( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + bool *is_freesp) +{ + int stat; + xfs_agblock_t fbno; + xfs_extlen_t flen; + int error; + + error = xfs_alloc_lookup_le(cur, bno, len, &stat); + if (error) + return error; + if (!stat) { + *is_freesp = false; + return 0; + } + + error = xfs_alloc_get_rec(cur, &fbno, &flen, &stat); + if (error) + return error; + if (!stat) { + *is_freesp = false; + return 0; + } + + *is_freesp = (fbno <= bno && fbno + flen >= bno + len); + return 0; +} diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 9f6373a..4f2ce38 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -210,4 +210,7 @@ int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); +int xfs_alloc_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, bool *is_freesp); + #endif /* __XFS_ALLOC_H__ */ diff --git a/libxfs/xfs_btree.c b/libxfs/xfs_btree.c index 89fb2fe..89d4bec 100644 --- a/libxfs/xfs_btree.c +++ b/libxfs/xfs_btree.c @@ -545,7 +545,7 @@ xfs_btree_ptr_offset( /* * Return a pointer to the n-th record in the btree block. */ -STATIC union xfs_btree_rec * +union xfs_btree_rec * xfs_btree_rec_addr( struct xfs_btree_cur *cur, int n, @@ -558,7 +558,7 @@ xfs_btree_rec_addr( /* * Return a pointer to the n-th key in the btree block. */ -STATIC union xfs_btree_key * +union xfs_btree_key * xfs_btree_key_addr( struct xfs_btree_cur *cur, int n, @@ -571,7 +571,7 @@ xfs_btree_key_addr( /* * Return a pointer to the n-th high key in the btree block. */ -STATIC union xfs_btree_key * +union xfs_btree_key * xfs_btree_high_key_addr( struct xfs_btree_cur *cur, int n, @@ -584,7 +584,7 @@ xfs_btree_high_key_addr( /* * Return a pointer to the n-th block pointer in the btree block. */ -STATIC union xfs_btree_ptr * +union xfs_btree_ptr * xfs_btree_ptr_addr( struct xfs_btree_cur *cur, int n, @@ -618,7 +618,7 @@ xfs_btree_get_iroot( * Retrieve the block pointer from the cursor at the given level. * This may be an inode btree root or from a buffer. */ -STATIC struct xfs_btree_block * /* generic btree block pointer */ +struct xfs_btree_block * /* generic btree block pointer */ xfs_btree_get_block( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level in btree */ @@ -1729,7 +1729,7 @@ error0: return error; } -STATIC int +int xfs_btree_lookup_get_block( struct xfs_btree_cur *cur, /* btree cursor */ int level, /* level in the btree */ diff --git a/libxfs/xfs_btree.h b/libxfs/xfs_btree.h index dbf299f..6f22cb0 100644 --- a/libxfs/xfs_btree.h +++ b/libxfs/xfs_btree.h @@ -194,7 +194,6 @@ struct xfs_btree_ops { const struct xfs_buf_ops *buf_ops; -#if defined(DEBUG) || defined(XFS_WARN) /* check that k1 is lower than k2 */ int (*keys_inorder)(struct xfs_btree_cur *cur, union xfs_btree_key *k1, @@ -204,7 +203,6 @@ struct xfs_btree_ops { int (*recs_inorder)(struct xfs_btree_cur *cur, union xfs_btree_rec *r1, union xfs_btree_rec *r2); -#endif }; /* btree ops flags */ @@ -537,4 +535,17 @@ int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks); +union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +union xfs_btree_key *xfs_btree_key_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +union xfs_btree_key *xfs_btree_high_key_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +union xfs_btree_ptr *xfs_btree_ptr_addr(struct xfs_btree_cur *cur, int n, + struct xfs_btree_block *block); +int xfs_btree_lookup_get_block(struct xfs_btree_cur *cur, int level, + union xfs_btree_ptr *pp, struct xfs_btree_block **blkp); +struct xfs_btree_block *xfs_btree_get_block(struct xfs_btree_cur *cur, + int level, struct xfs_buf **bpp); + #endif /* __XFS_BTREE_H__ */ diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index bfbf6e8..de69327 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -518,7 +518,7 @@ static inline int xfs_sb_version_hasftype(struct xfs_sb *sbp) (sbp->sb_features2 & XFS_SB_VERSION2_FTYPE)); } -static inline int xfs_sb_version_hasfinobt(xfs_sb_t *sbp) +static inline bool xfs_sb_version_hasfinobt(xfs_sb_t *sbp) { return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FINOBT); diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 23bffdc..3ec9a35 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -2326,3 +2326,42 @@ xfs_rmap_free_defer( return __xfs_rmap_add(mp, dfops, &ri); } + +/* Is there a record covering a given extent? */ +int +xfs_rmap_record_exists( + struct xfs_btree_cur *cur, + xfs_agblock_t bno, + xfs_extlen_t len, + struct xfs_owner_info *oinfo, + bool *has_rmap) +{ + uint64_t owner; + uint64_t offset; + unsigned int flags; + int stat; + struct xfs_rmap_irec irec; + int error; + + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); + + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, flags, &stat); + if (error) + return error; + if (!stat) { + *has_rmap = false; + return 0; + } + + error = xfs_rmap_get_rec(cur, &irec, &stat); + if (error) + return error; + if (!stat) { + *has_rmap = false; + return 0; + } + + *has_rmap = (irec.rm_startblock <= bno && + irec.rm_startblock + irec.rm_blockcount >= bno + len); + return 0; +} diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 5baa81f..2f072c8 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -144,4 +144,7 @@ extern xfs_extlen_t xfs_rmapbt_max_size(struct xfs_mount *mp); extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_extlen_t *ask, xfs_extlen_t *used); +extern int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, + xfs_extlen_t len, struct xfs_owner_info *oinfo, bool *has_rmap); + #endif /* __XFS_RMAP_BTREE_H__ */ diff --git a/libxfs/xfs_scrub.c b/libxfs/xfs_scrub.c new file mode 100644 index 0000000..750c482 --- /dev/null +++ b/libxfs/xfs_scrub.c @@ -0,0 +1,396 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs_priv.h" +#include "xfs_fs.h" +#include "xfs_shared.h" +#include "xfs_format.h" +#include "xfs_trans_resv.h" +#include "xfs_mount.h" +#include "xfs_defer.h" +#include "xfs_btree.h" +#include "xfs_bit.h" +#include "xfs_alloc.h" +#include "xfs_bmap.h" +#include "xfs_ialloc.h" +#include "xfs_refcount.h" +#include "xfs_alloc_btree.h" +#include "xfs_rmap_btree.h" +#include "xfs_log_format.h" +#include "xfs_trans.h" +#include "xfs_scrub.h" + +static const char * const btree_types[] = { + [XFS_BTNUM_BNO] = "bnobt", + [XFS_BTNUM_CNT] = "cntbt", + [XFS_BTNUM_RMAP] = "rmapbt", + [XFS_BTNUM_BMAP] = "bmapbt", + [XFS_BTNUM_INO] = "inobt", + [XFS_BTNUM_FINO] = "finobt", + [XFS_BTNUM_REFC] = "refcountbt", +}; + +/* Report a scrub corruption in dmesg. */ +void +xfs_btree_scrub_error( + struct xfs_btree_cur *cur, + int level, + const char *file, + int line, + const char *check) +{ + char buf[16]; + xfs_fsblock_t fsbno; + + if (cur->bc_ptrs[level] >= 1) + snprintf(buf, 16, " ptr %d", cur->bc_ptrs[level]); + else + buf[0] = 0; + + fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, cur->bc_bufs[level]->b_bn); + xfs_alert(cur->bc_mp, "scrub: %s btree corruption in block %u/%u%s: %s, file: %s, line: %d", + btree_types[cur->bc_btnum], + XFS_FSB_TO_AGNO(cur->bc_mp, fsbno), + XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno), + buf, check, file, line); +} + +/* AG metadata scrubbing */ + +/* + * Make sure this record is in order and doesn't stray outside of the parent + * keys. + */ +static int +xfs_btree_scrub_rec( + struct xfs_btree_scrub *bs) +{ + struct xfs_btree_cur *cur = bs->cur; + union xfs_btree_rec *rec; + union xfs_btree_key key; + union xfs_btree_key *keyp; + struct xfs_btree_block *block; + struct xfs_btree_block *keyblock; + + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[0]); + rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); + + /* If this isn't the first record, are they in order? */ + XFS_BTREC_SCRUB_CHECK(bs, bs->firstrec || + cur->bc_ops->recs_inorder(cur, &bs->lastrec, rec)); + bs->firstrec = false; + bs->lastrec = *rec; + + if (cur->bc_nlevels == 1) + return 0; + + /* Is this at least as large as the parent low key? */ + cur->bc_ops->init_key_from_rec(&key, rec); + keyblock = XFS_BUF_TO_BLOCK(cur->bc_bufs[1]); + keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, 0, + cur->bc_ops->diff_two_keys(cur, keyp, &key) >= 0); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return 0; + + /* Is this no larger than the parent high key? */ + keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, 0, + cur->bc_ops->diff_two_keys(cur, &key, keyp) >= 0); + + return 0; +} + +/* + * Make sure this key is in order and doesn't stray outside of the parent + * keys. + */ +static int +xfs_btree_scrub_key( + struct xfs_btree_scrub *bs, + int level) +{ + struct xfs_btree_cur *cur = bs->cur; + union xfs_btree_key *key; + union xfs_btree_key *keyp; + struct xfs_btree_block *block; + struct xfs_btree_block *keyblock; + + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); + key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); + + /* If this isn't the first key, are they in order? */ + XFS_BTKEY_SCRUB_CHECK(bs, level, bs->firstkey[level] || + cur->bc_ops->keys_inorder(cur, &bs->lastkey[level], + key)); + bs->firstkey[level] = false; + bs->lastkey[level] = *key; + + if (level + 1 >= cur->bc_nlevels) + return 0; + + /* Is this at least as large as the parent low key? */ + keyblock = XFS_BUF_TO_BLOCK(cur->bc_bufs[level + 1]); + keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, level, + cur->bc_ops->diff_two_keys(cur, keyp, key) >= 0); + + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) + return 0; + + /* Is this no larger than the parent high key? */ + key = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); + keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1], keyblock); + + XFS_BTKEY_SCRUB_CHECK(bs, level, + cur->bc_ops->diff_two_keys(cur, key, keyp) >= 0); + + return 0; +} + +struct check_owner { + struct list_head list; + xfs_agblock_t bno; +}; + +/* + * Make sure this btree block isn't in the free list and that there's + * an rmap record for it. + */ +static int +xfs_btree_block_check_owner( + struct xfs_btree_scrub *bs, + xfs_agblock_t bno) +{ + bool has_rmap; + bool is_freesp; + int error; + + /* Check that this block isn't free */ + error = xfs_alloc_record_exists(bs->bno_cur, bno, 1, &is_freesp); + if (error) + goto err; + XFS_BTREC_SCRUB_CHECK(bs, !is_freesp); + + if (!bs->rmap_cur) + return 0; + + /* Check that there's an rmap record for this */ + error = xfs_rmap_record_exists(bs->rmap_cur, bno, 1, &bs->oinfo, + &has_rmap); + if (error) + goto err; + XFS_BTREC_SCRUB_CHECK(bs, has_rmap); +err: + return error; +} + +/* Check the owner of a btree block. */ +static int +xfs_btree_scrub_check_owner( + struct xfs_btree_scrub *bs, + struct xfs_buf *bp) +{ + struct xfs_btree_cur *cur = bs->cur; + xfs_agblock_t bno; + xfs_fsblock_t fsbno; + struct check_owner *co; + + fsbno = XFS_DADDR_TO_FSB(cur->bc_mp, bp->b_bn); + bno = XFS_FSB_TO_AGBNO(cur->bc_mp, fsbno); + + /* Do we need to defer this one? */ + if ((!bs->rmap_cur && xfs_sb_version_hasrmapbt(&cur->bc_mp->m_sb)) || + !bs->bno_cur) { + co = kmem_alloc(sizeof(struct check_owner), KM_SLEEP | KM_NOFS); + co->bno = bno; + list_add_tail(&co->list, &bs->to_check); + return 0; + } + + return xfs_btree_block_check_owner(bs, bno); +} + +/* + * Visit all nodes and leaves of a btree. Check that all pointers and + * records are in order, that the keys reflect the records, and use a callback + * so that the caller can verify individual records. The callback is the same + * as the one for xfs_btree_query_range, so therefore this function also + * returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a negative error code. + */ +int +xfs_btree_scrub( + struct xfs_btree_scrub *bs) +{ + struct xfs_btree_cur *cur = bs->cur; + union xfs_btree_ptr ptr; + union xfs_btree_ptr *pp; + union xfs_btree_rec *recp; + struct xfs_btree_block *block; + int level; + struct xfs_buf *bp; + int i; + struct check_owner *co, *n; + int error; + + /* Finish filling out the scrub state */ + bs->error = 0; + bs->firstrec = true; + for (i = 0; i < XFS_BTREE_MAXLEVELS; i++) + bs->firstkey[i] = true; + bs->bno_cur = bs->rmap_cur = NULL; + INIT_LIST_HEAD(&bs->to_check); + if (bs->cur->bc_btnum != XFS_BTNUM_BNO) + bs->bno_cur = xfs_allocbt_init_cursor(cur->bc_mp, NULL, + bs->agf_bp, bs->cur->bc_private.a.agno, + XFS_BTNUM_BNO); + if (bs->cur->bc_btnum != XFS_BTNUM_RMAP && + xfs_sb_version_hasrmapbt(&cur->bc_mp->m_sb)) + bs->rmap_cur = xfs_rmapbt_init_cursor(cur->bc_mp, NULL, + bs->agf_bp, bs->cur->bc_private.a.agno); + + /* Load the root of the btree. */ + level = cur->bc_nlevels - 1; + cur->bc_ops->init_ptr_from_cur(cur, &ptr); + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); + if (error) + goto out; + + xfs_btree_get_block(cur, level, &bp); + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; + error = xfs_btree_scrub_check_owner(bs, bp); + if (error) + goto out; + + cur->bc_ptrs[level] = 1; + + while (level < cur->bc_nlevels) { + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); + + if (level == 0) { + /* End of leaf, pop back towards the root. */ + if (cur->bc_ptrs[level] > + be16_to_cpu(block->bb_numrecs)) { + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + /* Records in order for scrub? */ + error = xfs_btree_scrub_rec(bs); + if (error) + goto out; + + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); + error = bs->scrub_rec(bs, recp); + if (error < 0 || + error == XFS_BTREE_QUERY_RANGE_ABORT) + break; + + cur->bc_ptrs[level]++; + continue; + } + + /* End of node, pop back towards the root. */ + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { + if (level < cur->bc_nlevels - 1) + cur->bc_ptrs[level + 1]++; + level++; + continue; + } + + /* Keys in order for scrub? */ + error = xfs_btree_scrub_key(bs, level); + if (error) + goto out; + + /* Drill another level deeper. */ + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); + level--; + error = xfs_btree_lookup_get_block(cur, level, pp, + &block); + if (error) + goto out; + + xfs_btree_get_block(cur, level, &bp); + error = xfs_btree_check_block(cur, block, level, bp); + if (error) + goto out; + + error = xfs_btree_scrub_check_owner(bs, bp); + if (error) + goto out; + + cur->bc_ptrs[level] = 1; + } + +out: + /* + * If we don't end this function with the cursor pointing at a record + * block, a subsequent non-error cursor deletion will not release + * node-level buffers, causing a buffer leak. This is quite possible + * with a zero-results range query, so release the buffers if we + * failed to return any results. + */ + if (cur->bc_bufs[0] == NULL) { + for (i = 0; i < cur->bc_nlevels; i++) { + if (cur->bc_bufs[i]) { + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); + cur->bc_bufs[i] = NULL; + cur->bc_ptrs[i] = 0; + cur->bc_ra[i] = 0; + } + } + } + + /* Check the deferred stuff */ + if (!error) { + if (bs->cur->bc_btnum == XFS_BTNUM_BNO) + bs->bno_cur = bs->cur; + else if (bs->cur->bc_btnum == XFS_BTNUM_RMAP) + bs->rmap_cur = bs->cur; + list_for_each_entry(co, &bs->to_check, list) { + error = xfs_btree_block_check_owner(bs, co->bno); + if (error) + break; + } + } + list_for_each_entry_safe(co, n, &bs->to_check, list) { + list_del(&co->list); + kmem_free(co); + } + + if (bs->bno_cur && bs->bno_cur != bs->cur) + xfs_btree_del_cursor(bs->bno_cur, XFS_BTREE_ERROR); + if (bs->rmap_cur && bs->rmap_cur != bs->cur) + xfs_btree_del_cursor(bs->rmap_cur, XFS_BTREE_ERROR); + + if (error || bs->error) + xfs_alert(cur->bc_mp, + "Corruption detected. Unmount and run xfs_repair."); + + return error; +} diff --git a/libxfs/xfs_scrub.h b/libxfs/xfs_scrub.h new file mode 100644 index 0000000..af80a9d --- /dev/null +++ b/libxfs/xfs_scrub.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef __XFS_SCRUB_H__ +#define __XFS_SCRUB_H__ + +/* btree scrub */ +struct xfs_btree_scrub; + +typedef int (*xfs_btree_scrub_rec_fn)( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec); + +struct xfs_btree_scrub { + /* caller-provided scrub state */ + struct xfs_btree_cur *cur; + xfs_btree_scrub_rec_fn scrub_rec; + struct xfs_buf *agi_bp; + struct xfs_buf *agf_bp; + struct xfs_buf *agfl_bp; + struct xfs_owner_info oinfo; + + /* internal scrub state */ + union xfs_btree_rec lastrec; + bool firstrec; + union xfs_btree_key lastkey[XFS_BTREE_MAXLEVELS]; + bool firstkey[XFS_BTREE_MAXLEVELS]; + struct xfs_btree_cur *rmap_cur; + struct xfs_btree_cur *bno_cur; + struct list_head to_check; + int error; +}; + +int xfs_btree_scrub(struct xfs_btree_scrub *bs); +void xfs_btree_scrub_error(struct xfs_btree_cur *cur, int level, + const char *file, int line, const char *check); +#define XFS_BTREC_SCRUB_CHECK(bs, fs_ok) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + } +#define XFS_BTREC_SCRUB_GOTO(bs, fs_ok, label) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + goto label; \ + } +#define XFS_BTKEY_SCRUB_CHECK(bs, level, fs_ok) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, (level), __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + } +#define XFS_BTKEY_SCRUB_GOTO(bs, level, fs_ok, label) \ + if (!(fs_ok)) { \ + xfs_btree_scrub_error((bs)->cur, 0, __FILE__, __LINE__, #fs_ok); \ + (bs)->error = -EFSCORRUPTED; \ + goto label; \ + } + +#endif /* __XFS_SCRUB_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:45:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id DE01584A6 for ; Thu, 16 Jun 2016 20:45:48 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id AF61A8F804C for ; Thu, 16 Jun 2016 18:45:48 -0700 (PDT) X-ASG-Debug-ID: 1466127943-04cb6c5427585f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id fEvs1qfCyetXIV7a (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:43 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jB0C025126 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:12 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jBkb018701 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:11 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jAXx026145; Fri, 17 Jun 2016 01:45:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:10 -0700 Subject: [PATCH 137/145] xfs_db: introduce the 'fsmap' command to find what owns a set of fsblocks From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 137/145] xfs_db: introduce the 'fsmap' command to find what owns a set of fsblocks To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:09 -0700 Message-ID: <146612790910.16048.446600163243739830.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127943 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8013 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Introduce a new 'fsmap' command to the fs debugger that will query the rmap btree to report the file/metadata extents mapped to a range of physical blocks. Signed-off-by: Darrick J. Wong --- db/Makefile | 2 - db/command.c | 2 + db/fsmap.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++ db/fsmap.h | 20 +++++++ man/man8/xfs_db.8 | 9 +++ 5 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 db/fsmap.c create mode 100644 db/fsmap.h diff --git a/db/Makefile b/db/Makefile index 8260da3..5adea48 100644 --- a/db/Makefile +++ b/db/Makefile @@ -12,7 +12,7 @@ HFILES = addr.h agf.h agfl.h agi.h attr.h attrshort.h bit.h block.h bmap.h \ dir2.h dir2sf.h dquot.h echo.h faddr.h field.h \ flist.h fprint.h frag.h freesp.h hash.h help.h init.h inode.h input.h \ io.h logformat.h malloc.h metadump.h output.h print.h quit.h sb.h \ - sig.h strvec.h text.h type.h write.h attrset.h symlink.h + sig.h strvec.h text.h type.h write.h attrset.h symlink.h fsmap.h CFILES = $(HFILES:.h=.c) LSRCFILES = xfs_admin.sh xfs_ncheck.sh xfs_metadump.sh diff --git a/db/command.c b/db/command.c index 3c17a1e..278c357 100644 --- a/db/command.c +++ b/db/command.c @@ -49,6 +49,7 @@ #include "write.h" #include "malloc.h" #include "dquot.h" +#include "fsmap.h" cmdinfo_t *cmdtab; int ncmds; @@ -128,6 +129,7 @@ init_commands(void) echo_init(); frag_init(); freesp_init(); + fsmap_init(); help_init(); hash_init(); inode_init(); diff --git a/db/fsmap.c b/db/fsmap.c new file mode 100644 index 0000000..a9de401 --- /dev/null +++ b/db/fsmap.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs.h" +#include "command.h" +#include "fsmap.h" +#include "output.h" +#include "init.h" + +struct fsmap_info { + unsigned long long nr; + xfs_agnumber_t agno; +}; + +static int +fsmap_fn( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct fsmap_info *info = priv; + + dbprintf(_("%llu: %u/%u len %u owner %lld offset %llu bmbt %d attrfork %d extflag %d\n"), + info->nr, info->agno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + !!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK), + !!(rec->rm_flags & XFS_RMAP_ATTR_FORK), + !!(rec->rm_flags & XFS_RMAP_UNWRITTEN)); + info->nr++; + + return 0; +} + +int +fsmap_f( + int argc, + char **argv) +{ + char *p; + struct fsmap_info info; + xfs_agnumber_t start_ag; + xfs_agnumber_t end_ag; + xfs_agnumber_t agno; + xfs_fsblock_t start_fsb = 0; + xfs_fsblock_t end_fsb = NULLFSBLOCK; + struct xfs_rmap_irec low; + struct xfs_rmap_irec high; + struct xfs_btree_cur *bt_cur; + struct xfs_buf *agbp; + int c; + xfs_daddr_t eofs; + int error; + + if (!xfs_sb_version_hasrmapbt(&mp->m_sb)) { + dbprintf(_("Filesystem does not support reverse mapping btree.\n")); + return 0; + } + + while ((c = getopt(argc, argv, "")) != EOF) { + switch (c) { + default: + dbprintf(_("Bad option for fsmap command.\n")); + return 0; + } + } + + if (argc > optind) { + start_fsb = strtoull(argv[optind], &p, 0); + if (*p != '\0' || start_fsb >= mp->m_sb.sb_dblocks) { + dbprintf(_("Bad fsmap start_fsb %s.\n"), argv[optind]); + return 0; + } + } + + if (argc > optind + 1) { + end_fsb = strtoull(argv[optind + 1], &p, 0); + if (*p != '\0') { + dbprintf(_("Bad fsmap end_fsb %s.\n"), argv[optind + 1]); + return 0; + } + } + + eofs = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks); + if (XFS_FSB_TO_DADDR(mp, end_fsb) >= eofs) + end_fsb = XFS_DADDR_TO_FSB(mp, eofs - 1); + + low.rm_startblock = XFS_FSB_TO_AGBNO(mp, start_fsb); + low.rm_owner = 0; + low.rm_offset = 0; + low.rm_flags = 0; + high.rm_startblock = -1U; + high.rm_owner = ULLONG_MAX; + high.rm_offset = ULLONG_MAX; + high.rm_flags = XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK | XFS_RMAP_UNWRITTEN; + + start_ag = XFS_FSB_TO_AGNO(mp, start_fsb); + end_ag = XFS_FSB_TO_AGNO(mp, end_fsb); + + info.nr = 0; + for (agno = start_ag; agno <= end_ag; agno++) { + if (agno == end_ag) + high.rm_startblock = XFS_FSB_TO_AGBNO(mp, end_fsb); + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &agbp); + if (error) { + dbprintf(_("Error %d while reading AGF.\n"), error); + return 0; + } + + bt_cur = xfs_rmapbt_init_cursor(mp, NULL, agbp, agno); + if (!bt_cur) { + libxfs_putbuf(agbp); + dbprintf(_("Not enough memory.\n")); + return 0; + } + + info.agno = agno; + error = xfs_rmapbt_query_range(bt_cur, &low, &high, + fsmap_fn, &info); + if (error) { + xfs_btree_del_cursor(bt_cur, XFS_BTREE_ERROR); + libxfs_putbuf(agbp); + dbprintf(_("Error %d while querying fsmap btree.\n"), + error); + return 0; + } + + xfs_btree_del_cursor(bt_cur, XFS_BTREE_NOERROR); + libxfs_putbuf(agbp); + + if (agno == start_ag) + low.rm_startblock = 0; + } + + return 0; +} + +static const cmdinfo_t fsmap_cmd = + { "fsmap", NULL, fsmap_f, 0, 2, 0, + N_("start_fsb [end_fsb]"), + N_("display reverse mapping(s)"), NULL }; + +void +fsmap_init(void) +{ + add_command(&fsmap_cmd); +} diff --git a/db/fsmap.h b/db/fsmap.h new file mode 100644 index 0000000..f8aacd3 --- /dev/null +++ b/db/fsmap.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +extern void fsmap_init(void); diff --git a/man/man8/xfs_db.8 b/man/man8/xfs_db.8 index b6d2f64..514e3aa 100644 --- a/man/man8/xfs_db.8 +++ b/man/man8/xfs_db.8 @@ -568,6 +568,15 @@ command to convert to and from this form. Block numbers given for file blocks .B bmap command) are in this form. .TP +.BI "fsmap [ " start " ] [ " end " ] +Prints the mapping of disk blocks used by an XFS filesystem. The map +lists each extent used by files, allocation group metadata, +journalling logs, and static filesystem metadata, as well as any +regions that are unused. All blocks, offsets, and lengths are specified +in units of 512-byte blocks, no matter what the filesystem's block size is. +.BI "The optional " start " and " end " arguments can be used to constrain +the output to a particular range of disk blocks. +.TP .BI hash " string Prints the hash value of .I string From darrick.wong@oracle.com Thu Jun 16 20:45:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6BAE384A7 for ; Thu, 16 Jun 2016 20:45:49 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3D02E8F804C for ; Thu, 16 Jun 2016 18:45:49 -0700 (PDT) X-ASG-Debug-ID: 1466127947-04cbb01fee6aa00001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id EDPfJKMdlO4MRFYQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:47 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jgie013469 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:43 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jgFQ014984 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:42 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jgtb031977; Fri, 17 Jun 2016 01:45:42 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:41 -0700 Subject: [PATCH 142/145] xfs: support scrubbing rmap btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 142/145] xfs: support scrubbing rmap btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:40 -0700 Message-ID: <146612794031.16048.1037164649883976756.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127947 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4390 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the rmap btree. Signed-off-by: Darrick J. Wong --- libxfs/xfs_rmap.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_rmap_btree.c | 4 -- libxfs/xfs_rmap_btree.h | 2 + 3 files changed, 79 insertions(+), 4 deletions(-) diff --git a/libxfs/xfs_rmap.c b/libxfs/xfs_rmap.c index 3ec9a35..4e0e472 100644 --- a/libxfs/xfs_rmap.c +++ b/libxfs/xfs_rmap.c @@ -36,6 +36,7 @@ #include "xfs_trace.h" #include "xfs_bmap.h" #include "xfs_inode.h" +#include "xfs_scrub.h" /* * Lookup the first record less than or equal to [bno, len, owner, offset] @@ -2365,3 +2366,79 @@ xfs_rmap_record_exists( irec.rm_startblock + irec.rm_blockcount >= bno + len); return 0; } + +STATIC int +xfs_rmapbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + struct xfs_rmap_irec irec; + bool is_freesp; + bool non_inode; + bool is_unwritten; + bool is_bmbt; + bool is_attr; + int error; + + error = xfs_rmapbt_btrec_to_irec(rec, &irec); + if (error) + return error; + + XFS_BTREC_SCRUB_CHECK(bs, irec.rm_startblock < mp->m_sb.sb_agblocks) + XFS_BTREC_SCRUB_CHECK(bs, irec.rm_startblock < irec.rm_startblock + + irec.rm_blockcount); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)irec.rm_startblock + + irec.rm_blockcount <= mp->m_sb.sb_agblocks) + + non_inode = XFS_RMAP_NON_INODE_OWNER(irec.rm_owner); + is_bmbt = irec.rm_flags & XFS_RMAP_ATTR_FORK; + is_attr = irec.rm_flags & XFS_RMAP_BMBT_BLOCK; + is_unwritten = irec.rm_flags & XFS_RMAP_UNWRITTEN; + + XFS_BTREC_SCRUB_CHECK(bs, !is_bmbt || irec.rm_offset == 0); + XFS_BTREC_SCRUB_CHECK(bs, !non_inode || irec.rm_offset == 0); + XFS_BTREC_SCRUB_CHECK(bs, !is_unwritten || !(is_bmbt || non_inode || + is_attr)); + XFS_BTREC_SCRUB_CHECK(bs, !non_inode || !(is_bmbt || is_unwritten || + is_attr)); + + /* check there's no record in freesp btrees */ + error = xfs_alloc_record_exists(bs->bno_cur, irec.rm_startblock, + irec.rm_blockcount, &is_freesp); + if (error) + goto err; + XFS_BTREC_SCRUB_CHECK(bs, !is_freesp); + + /* XXX: check with the owner */ + +err: + return error; +} + +/* Scrub the rmap btree for some AG. */ +int +xfs_rmapbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) + return error; + + bs.cur = xfs_rmapbt_init_cursor(mp, NULL, bs.agf_bp, agno); + bs.scrub_rec = xfs_rmapbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_AG); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} diff --git a/libxfs/xfs_rmap_btree.c b/libxfs/xfs_rmap_btree.c index 0b7da82..e592833 100644 --- a/libxfs/xfs_rmap_btree.c +++ b/libxfs/xfs_rmap_btree.c @@ -370,7 +370,6 @@ const struct xfs_buf_ops xfs_rmapbt_buf_ops = { .verify_write = xfs_rmapbt_write_verify, }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_rmapbt_keys_inorder( struct xfs_btree_cur *cur, @@ -406,7 +405,6 @@ xfs_rmapbt_recs_inorder( return 1; return 0; } -#endif /* DEBUG */ static const struct xfs_btree_ops xfs_rmapbt_ops = { .rec_len = sizeof(struct xfs_rmap_rec), @@ -426,10 +424,8 @@ static const struct xfs_btree_ops xfs_rmapbt_ops = { .key_diff = xfs_rmapbt_key_diff, .buf_ops = &xfs_rmapbt_buf_ops, .diff_two_keys = xfs_rmapbt_diff_two_keys, -#if defined(DEBUG) || defined(XFS_WARN) .keys_inorder = xfs_rmapbt_keys_inorder, .recs_inorder = xfs_rmapbt_recs_inorder, -#endif }; /* diff --git a/libxfs/xfs_rmap_btree.h b/libxfs/xfs_rmap_btree.h index 2f072c8..3f8742d 100644 --- a/libxfs/xfs_rmap_btree.h +++ b/libxfs/xfs_rmap_btree.h @@ -147,4 +147,6 @@ extern int xfs_rmapbt_calc_reserves(struct xfs_mount *mp, extern int xfs_rmap_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, struct xfs_owner_info *oinfo, bool *has_rmap); +int xfs_rmapbt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); + #endif /* __XFS_RMAP_BTREE_H__ */ From darrick.wong@oracle.com Thu Jun 16 20:45:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C09FA84BC for ; Thu, 16 Jun 2016 20:45:52 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 49110AC001 for ; Thu, 16 Jun 2016 18:45:52 -0700 (PDT) X-ASG-Debug-ID: 1466127949-04bdf01e15967a0001-NocioJ Received: from aserp1050.oracle.com (aserp1050.oracle.com [141.146.126.70]) by cuda.sgi.com with ESMTP id 6e8ENQB75qBUkusg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:49 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1050.oracle.com[141.146.126.70] X-Barracuda-Apparent-Source-IP: 141.146.126.70 Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by aserp1050.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jdl5031639 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Fri, 17 Jun 2016 01:45:40 GMT Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1j148012445 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:01 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ixX0005445 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:01 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1iw8O031473; Fri, 17 Jun 2016 01:44:58 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:44:58 -0700 Subject: [PATCH 135/145] mkfs.xfs: format reflink enabled filesystems From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 135/145] mkfs.xfs: format reflink enabled filesystems To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:44:56 -0700 Message-ID: <146612789675.16048.3320445583494719487.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserp1040.oracle.com [141.146.126.69] X-Barracuda-Connect: aserp1050.oracle.com[141.146.126.70] X-Barracuda-Start-Time: 1466127949 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9221 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.75 X-Barracuda-Spam-Status: No, SCORE=0.75 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_RULE_7580D, BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.75 BSF_RULE_7580D Custom Rule 7580D Create the refcount btree at mkfs time and set the feature flag. v2: Turn on the reflink feature when calculating the minimum log size. Signed-off-by: Darrick J. Wong --- include/xfs_multidisk.h | 3 +- man/man8/mkfs.xfs.8 | 28 ++++++++++++++++++++ mkfs/maxtrres.c | 5 +++- mkfs/xfs_mkfs.c | 67 +++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 95 insertions(+), 8 deletions(-) diff --git a/include/xfs_multidisk.h b/include/xfs_multidisk.h index 8dc3027..ce9bbce 100644 --- a/include/xfs_multidisk.h +++ b/include/xfs_multidisk.h @@ -68,6 +68,7 @@ extern void res_failed (int err); /* maxtrres.c */ extern int max_trans_res(unsigned long agsize, int crcs_enabled, int dirversion, int sectorlog, int blocklog, int inodelog, int dirblocklog, - int logversion, int log_sunit, int finobt, int rmapbt); + int logversion, int log_sunit, int finobt, int rmapbt, + int reflink); #endif /* __XFS_MULTIDISK_H__ */ diff --git a/man/man8/mkfs.xfs.8 b/man/man8/mkfs.xfs.8 index d88d314..6131e24 100644 --- a/man/man8/mkfs.xfs.8 +++ b/man/man8/mkfs.xfs.8 @@ -213,6 +213,34 @@ for filesystems created with the (default) option set. When the option .B \-m crc=0 is used, the reverse mapping btree feature is not supported and is disabled. +.TP +.BI reflink= value +This option enables the use of a separate reference count btree index in each +allocation group. The value is either 0 to disable the feature, or 1 to create +a reference count btree in each allocation group. +.IP +The reference count btree enables the sharing of physical extents between +the data forks of different files, which is commonly known as "reflink". +Unlike traditional Unix filesystems which assume that every inode and +logical block pair map to a unique physical block, a reflink-capable +XFS filesystem removes the uniqueness requirement, allowing up to four +billion arbitrary inode/logical block pairs to map to a physical block. +If a program tries to write to a multiply-referenced block in a file, the write +will be redirected to a new block, and that file's logical-to-physical +mapping will be changed to the new block ("copy on write"). This feature +enables the creation of per-file snapshots and deduplication. It is only +available for the data forks of regular files. +.IP +By default, +.B mkfs.xfs +will not create reference count btrees and therefore will not enable the +reflink feature. This feature is only available for filesystems created with +the (default) +.B \-m crc=1 +option set. When the option +.B \-m crc=0 +is used, the reference count btree feature is not supported and reflink is +disabled. .RE .TP .BI \-d " data_section_options" diff --git a/mkfs/maxtrres.c b/mkfs/maxtrres.c index fc24eac..a9c0985 100644 --- a/mkfs/maxtrres.c +++ b/mkfs/maxtrres.c @@ -39,7 +39,8 @@ max_trans_res( int logversion, int log_sunit, int finobt, - int rmapbt) + int rmapbt, + int reflink) { xfs_sb_t *sbp; xfs_mount_t mount; @@ -75,6 +76,8 @@ max_trans_res( sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_FINOBT; if (rmapbt) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT; + if (reflink) + sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK; libxfs_mount(&mount, sbp, 0,0,0,0); maxfsb = xfs_log_calc_minimum_size(&mount); diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 634dcfd..3753731 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -682,6 +682,8 @@ struct opt_params mopts = { "uuid", #define M_RMAPBT 3 "rmapbt", +#define M_REFLINK 4 + "reflink", NULL }, .subopt_params = { @@ -707,6 +709,12 @@ struct opt_params mopts = { .maxval = 1, .defaultval = 0, }, + { .index = M_REFLINK, + .conflicts = { LAST_CONFLICT }, + .minval = 0, + .maxval = 1, + .defaultval = 0, + }, }, }; @@ -1463,6 +1471,7 @@ struct sb_feat_args { bool dirftype; bool parent_pointers; bool rmapbt; + bool reflink; }; static void @@ -1535,6 +1544,8 @@ sb_set_features( sbp->sb_features_ro_compat = XFS_SB_FEAT_RO_COMPAT_FINOBT; if (fp->rmapbt) sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_RMAPBT; + if (fp->reflink) + sbp->sb_features_ro_compat |= XFS_SB_FEAT_RO_COMPAT_REFLINK; /* * Sparse inode chunk support has two main inode alignment requirements. @@ -1796,6 +1807,7 @@ main( .dirftype = true, .parent_pointers = false, .rmapbt = false, + .reflink = false, }; platform_uuid_generate(&uuid); @@ -2089,6 +2101,10 @@ main( sb_feat.rmapbt = getnum( value, &mopts, M_RMAPBT); break; + case M_REFLINK: + sb_feat.reflink = getnum( + value, &mopts, M_REFLINK); + break; default: unknown('m', value); } @@ -2431,6 +2447,13 @@ _("rmapbt not supported without CRC support\n")); usage(); } sb_feat.rmapbt = false; + + if (sb_feat.reflink) { + fprintf(stderr, +_("reflink not supported without CRC support\n")); + usage(); + } + sb_feat.reflink = false; } @@ -2921,7 +2944,7 @@ an AG size that is one stripe unit smaller, for example %llu.\n"), sb_feat.crcs_enabled, sb_feat.dir_version, sectorlog, blocklog, inodelog, dirblocklog, sb_feat.log_version, lsunit, sb_feat.finobt, - sb_feat.rmapbt); + sb_feat.rmapbt, sb_feat.reflink); ASSERT(min_logblocks); min_logblocks = MAX(XFS_MIN_LOG_BLOCKS, min_logblocks); if (!logsize && dblocks >= (1024*1024*1024) >> blocklog) @@ -3056,7 +3079,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), printf(_( "meta-data=%-22s isize=%-6d agcount=%lld, agsize=%lld blks\n" " =%-22s sectsz=%-5u attr=%u, projid32bit=%u\n" - " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u\n" + " =%-22s crc=%-8u finobt=%u, sparse=%u, rmapbt=%u, reflink=%u\n" "data =%-22s bsize=%-6u blocks=%llu, imaxpct=%u\n" " =%-22s sunit=%-6u swidth=%u blks\n" "naming =version %-14u bsize=%-6u ascii-ci=%d ftype=%d\n" @@ -3067,7 +3090,7 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), "", sectorsize, sb_feat.attr_version, !sb_feat.projid16bit, "", sb_feat.crcs_enabled, sb_feat.finobt, sb_feat.spinodes, - sb_feat.rmapbt, + sb_feat.rmapbt, sb_feat.reflink, "", blocksize, (long long)dblocks, imaxpct, "", dsunit, dswidth, sb_feat.dir_version, dirblocksize, sb_feat.nci, @@ -3254,7 +3277,10 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), cpu_to_be32(XFS_RMAP_BLOCK(mp)); agf->agf_levels[XFS_BTNUM_RMAPi] = cpu_to_be32(1); } - + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + agf->agf_refcount_root = cpu_to_be32(xfs_refc_block(mp)); + agf->agf_refcount_level = cpu_to_be32(1); + } agf->agf_flfirst = 0; agf->agf_fllast = cpu_to_be32(XFS_AGFL_SIZE(mp) - 1); agf->agf_flcount = 0; @@ -3423,6 +3449,23 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); /* + * refcount btree root block + */ + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + buf = libxfs_getbuf(mp->m_ddev_targp, + XFS_AGB_TO_DADDR(mp, agno, xfs_refc_block(mp)), + bsize); + buf->b_ops = &xfs_refcountbt_buf_ops; + + block = XFS_BUF_TO_BLOCK(buf); + memset(block, 0, blocksize); + xfs_btree_init_block(mp, buf, XFS_REFC_CRC_MAGIC, 0, 0, + agno, XFS_BTREE_CRC_BLOCKS); + + libxfs_writebuf(buf, LIBXFS_EXIT_ON_FAILURE); + } + + /* * INO btree root block */ buf = libxfs_getbuf(mp->m_ddev_targp, @@ -3510,9 +3553,21 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), rrec->rm_offset = 0; be16_add_cpu(&block->bb_numrecs, 1); + /* account for refcount btree root */ + if (xfs_sb_version_hasreflink(&mp->m_sb)) { + rrec = XFS_RMAP_REC_ADDR(block, 5); + rrec->rm_startblock = cpu_to_be32( + xfs_refc_block(mp)); + rrec->rm_blockcount = cpu_to_be32(1); + rrec->rm_owner = cpu_to_be64(XFS_RMAP_OWN_REFC); + rrec->rm_offset = 0; + be16_add_cpu(&block->bb_numrecs, 1); + } + /* account for the log space */ if (loginternal && agno == logagno) { - rrec = XFS_RMAP_REC_ADDR(block, 5); + rrec = XFS_RMAP_REC_ADDR(block, + be16_to_cpu(block->bb_numrecs) + 1); rrec->rm_startblock = cpu_to_be32( XFS_FSB_TO_AGBNO(mp, logstart)); rrec->rm_blockcount = cpu_to_be32(logblocks); @@ -3748,7 +3803,7 @@ usage( void ) { fprintf(stderr, _("Usage: %s\n\ /* blocksize */ [-b log=n|size=num]\n\ -/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1]\n\ +/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx,rmapbt=0|1,reflink=0|1]\n\ /* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,\n\ (sunit=value,swidth=value|su=num,sw=num|noalign),\n\ sectlog=n|sectsize=num\n\ From darrick.wong@oracle.com Thu Jun 16 20:45:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 22DEF84C2 for ; Thu, 16 Jun 2016 20:45:55 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id A10FAAC002 for ; Thu, 16 Jun 2016 18:45:54 -0700 (PDT) X-ASG-Debug-ID: 1466127951-04bdf01e13967b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ytsqlsCbAZvEdsUk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1je42013438 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:45:41 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1jebC012645 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:40 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jZRT014164; Fri, 17 Jun 2016 01:45:39 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:35 -0700 Subject: [PATCH 141/145] xfs: support scrubbing inode btrees From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 141/145] xfs: support scrubbing inode btrees To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:34 -0700 Message-ID: <146612793409.16048.2627788174769006287.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127952 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8438 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the inode btrees. Signed-off-by: Darrick J. Wong --- libxfs/xfs_ialloc.c | 178 +++++++++++++++++++++++++++++++++++++++++---- libxfs/xfs_ialloc.h | 2 + libxfs/xfs_ialloc_btree.c | 18 +++-- 3 files changed, 176 insertions(+), 22 deletions(-) diff --git a/libxfs/xfs_ialloc.c b/libxfs/xfs_ialloc.c index 8c2344c..d0fb2db 100644 --- a/libxfs/xfs_ialloc.c +++ b/libxfs/xfs_ialloc.c @@ -34,6 +34,8 @@ #include "xfs_cksum.h" #include "xfs_trans.h" #include "xfs_trace.h" +#include "xfs_rmap_btree.h" +#include "xfs_scrub.h" /* @@ -92,24 +94,14 @@ xfs_inobt_update( return xfs_btree_update(cur, &rec); } -/* - * Get the data from the pointed-to record. - */ -int /* error */ -xfs_inobt_get_rec( - struct xfs_btree_cur *cur, /* btree cursor */ - xfs_inobt_rec_incore_t *irec, /* btree record */ - int *stat) /* output: success/failure */ +STATIC void +xfs_inobt_btrec_to_irec( + struct xfs_mount *mp, + union xfs_btree_rec *rec, + struct xfs_inobt_rec_incore *irec) { - union xfs_btree_rec *rec; - int error; - - error = xfs_btree_get_rec(cur, &rec, stat); - if (error || *stat == 0) - return error; - irec->ir_startino = be32_to_cpu(rec->inobt.ir_startino); - if (xfs_sb_version_hassparseinodes(&cur->bc_mp->m_sb)) { + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) { irec->ir_holemask = be16_to_cpu(rec->inobt.ir_u.sp.ir_holemask); irec->ir_count = rec->inobt.ir_u.sp.ir_count; irec->ir_freecount = rec->inobt.ir_u.sp.ir_freecount; @@ -124,6 +116,25 @@ xfs_inobt_get_rec( be32_to_cpu(rec->inobt.ir_u.f.ir_freecount); } irec->ir_free = be64_to_cpu(rec->inobt.ir_free); +} + +/* + * Get the data from the pointed-to record. + */ +int /* error */ +xfs_inobt_get_rec( + struct xfs_btree_cur *cur, /* btree cursor */ + xfs_inobt_rec_incore_t *irec, /* btree record */ + int *stat) /* output: success/failure */ +{ + union xfs_btree_rec *rec; + int error; + + error = xfs_btree_get_rec(cur, &rec, stat); + if (error || *stat == 0) + return error; + + xfs_inobt_btrec_to_irec(cur->bc_mp, rec, irec); return 0; } @@ -2644,3 +2655,138 @@ xfs_ialloc_pagi_init( xfs_trans_brelse(tp, bp); return 0; } + +STATIC int +xfs_iallocbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + struct xfs_inobt_rec_incore irec; + __uint16_t holemask; + xfs_agino_t agino; + xfs_agblock_t bno; + xfs_extlen_t len; + int holecount; + int i; + bool has_rmap = false; + struct xfs_owner_info oinfo; + int error = 0; + uint64_t holes; + + xfs_inobt_btrec_to_irec(mp, rec, &irec); + + XFS_BTREC_SCRUB_CHECK(bs, irec.ir_count <= XFS_INODES_PER_CHUNK); + XFS_BTREC_SCRUB_CHECK(bs, irec.ir_freecount <= XFS_INODES_PER_CHUNK); + agino = irec.ir_startino; + xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_INODES); + + /* Handle non-sparse inodes */ + if (!xfs_inobt_issparse(irec.ir_holemask)) { + len = XFS_B_TO_FSB(mp, + XFS_INODES_PER_CHUNK * mp->m_sb.sb_inodesize); + bno = XFS_AGINO_TO_AGBNO(mp, agino); + + XFS_BTREC_SCRUB_CHECK(bs, bno < mp->m_sb.sb_agblocks) + XFS_BTREC_SCRUB_CHECK(bs, bno < bno + len); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <= + mp->m_sb.sb_agblocks); + + if (!bs->rmap_cur) + return error; + error = xfs_rmap_record_exists(bs->rmap_cur, bno, len, &oinfo, + &has_rmap); + if (error) + return error; + XFS_BTREC_SCRUB_CHECK(bs, has_rmap); + return 0; + } + + /* Check each chunk of a sparse inode cluster. */ + holemask = irec.ir_holemask; + holecount = 0; + len = XFS_B_TO_FSB(mp, + XFS_INODES_PER_HOLEMASK_BIT * mp->m_sb.sb_inodesize); + holes = ~xfs_inobt_irec_to_allocmask(&irec); + XFS_BTREC_SCRUB_CHECK(bs, (holes & irec.ir_free) == holes); + XFS_BTREC_SCRUB_CHECK(bs, irec.ir_freecount <= irec.ir_count); + + for (i = 0; i < XFS_INOBT_HOLEMASK_BITS; holemask >>= 1, + i++, agino += XFS_INODES_PER_HOLEMASK_BIT) { + if (holemask & 1) { + holecount += XFS_INODES_PER_HOLEMASK_BIT; + continue; + } + bno = XFS_AGINO_TO_AGBNO(mp, agino); + + XFS_BTREC_SCRUB_CHECK(bs, bno < mp->m_sb.sb_agblocks) + XFS_BTREC_SCRUB_CHECK(bs, bno < bno + len); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <= + mp->m_sb.sb_agblocks); + + if (!bs->rmap_cur) + continue; + error = xfs_rmap_record_exists(bs->rmap_cur, bno, len, &oinfo, + &has_rmap); + if (error) + break; + XFS_BTREC_SCRUB_CHECK(bs, has_rmap); + } + + XFS_BTREC_SCRUB_CHECK(bs, holecount <= XFS_INODES_PER_CHUNK); + XFS_BTREC_SCRUB_CHECK(bs, holecount + irec.ir_count == + XFS_INODES_PER_CHUNK); + + return error; +} + +/* Scrub the inode btrees for some AG. */ +STATIC int +xfs_iallocbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno, + xfs_btnum_t which) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_ialloc_read_agi(mp, NULL, agno, &bs.agi_bp); + if (error) + return error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) { + xfs_trans_brelse(NULL, bs.agi_bp); + return error; + } + + bs.cur = xfs_inobt_init_cursor(mp, NULL, bs.agi_bp, agno, which); + bs.scrub_rec = xfs_iallocbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_INOBT); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + xfs_trans_brelse(NULL, bs.agi_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} + +int +xfs_inobt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_iallocbt_scrub(mp, agno, XFS_BTNUM_INO); +} + +int +xfs_finobt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_iallocbt_scrub(mp, agno, XFS_BTNUM_FINO); +} diff --git a/libxfs/xfs_ialloc.h b/libxfs/xfs_ialloc.h index 0bb8966..7ea6ff3 100644 --- a/libxfs/xfs_ialloc.h +++ b/libxfs/xfs_ialloc.h @@ -168,5 +168,7 @@ int xfs_ialloc_inode_init(struct xfs_mount *mp, struct xfs_trans *tp, int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp, xfs_agnumber_t agno, struct xfs_buf **bpp); +extern int xfs_inobt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); +extern int xfs_finobt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); #endif /* __XFS_IALLOC_H__ */ diff --git a/libxfs/xfs_ialloc_btree.c b/libxfs/xfs_ialloc_btree.c index 36d09eb..81a7b97 100644 --- a/libxfs/xfs_ialloc_btree.c +++ b/libxfs/xfs_ialloc_btree.c @@ -203,6 +203,16 @@ xfs_inobt_key_diff( cur->bc_rec.i.ir_startino; } +STATIC __int64_t +xfs_inobt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->inobt.ir_startino) - + be32_to_cpu(k1->inobt.ir_startino); +} + static int xfs_inobt_verify( struct xfs_buf *bp) @@ -277,7 +287,6 @@ const struct xfs_buf_ops xfs_inobt_buf_ops = { .verify_write = xfs_inobt_write_verify, }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_inobt_keys_inorder( struct xfs_btree_cur *cur, @@ -297,7 +306,6 @@ xfs_inobt_recs_inorder( return be32_to_cpu(r1->inobt.ir_startino) + XFS_INODES_PER_CHUNK <= be32_to_cpu(r2->inobt.ir_startino); } -#endif /* DEBUG */ static const struct xfs_btree_ops xfs_inobt_ops = { .rec_len = sizeof(xfs_inobt_rec_t), @@ -314,10 +322,9 @@ static const struct xfs_btree_ops xfs_inobt_ops = { .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, .buf_ops = &xfs_inobt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_inobt_diff_two_keys, .keys_inorder = xfs_inobt_keys_inorder, .recs_inorder = xfs_inobt_recs_inorder, -#endif }; static const struct xfs_btree_ops xfs_finobt_ops = { @@ -335,10 +342,9 @@ static const struct xfs_btree_ops xfs_finobt_ops = { .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, .key_diff = xfs_inobt_key_diff, .buf_ops = &xfs_inobt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_inobt_diff_two_keys, .keys_inorder = xfs_inobt_keys_inorder, .recs_inorder = xfs_inobt_recs_inorder, -#endif }; /* From darrick.wong@oracle.com Thu Jun 16 20:45:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 217AD84C2 for ; Thu, 16 Jun 2016 20:45:56 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id C909D8F804C for ; Thu, 16 Jun 2016 18:45:55 -0700 (PDT) X-ASG-Debug-ID: 1466127953-04bdf01e17967c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id DmJmEUstHDKjymr6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:53 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jU3p025613 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:31 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jUWK006497 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:30 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jTDm031895; Fri, 17 Jun 2016 01:45:29 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:29 -0700 Subject: [PATCH 140/145] xfs: support scrubbing free space btrees From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 140/145] xfs: support scrubbing free space btrees To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:27 -0700 Message-ID: <146612792793.16048.10429034360993638272.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127953 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7261 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the free space btrees. Signed-off-by: Darrick J. Wong --- libxfs/libxfs_priv.h | 1 libxfs/xfs_alloc.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_alloc.h | 3 + libxfs/xfs_alloc_btree.c | 51 +++++++++++++++++++++--- 4 files changed, 147 insertions(+), 6 deletions(-) diff --git a/libxfs/libxfs_priv.h b/libxfs/libxfs_priv.h index 527bd49..dabdafc 100644 --- a/libxfs/libxfs_priv.h +++ b/libxfs/libxfs_priv.h @@ -518,5 +518,6 @@ int libxfs_zero_extent(struct xfs_inode *ip, xfs_fsblock_t start_fsb, bool xfs_log_check_lsn(struct xfs_mount *, xfs_lsn_t); #define xfs_always_cow (false) +#define xfs_err(...) ((void)0) #endif /* __LIBXFS_INTERNAL_XFS_H__ */ diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c index 7ab05e3..7219057 100644 --- a/libxfs/xfs_alloc.c +++ b/libxfs/xfs_alloc.c @@ -35,6 +35,7 @@ #include "xfs_trans.h" #include "xfs_ag_resv.h" #include "xfs_refcount_btree.h" +#include "xfs_scrub.h" struct workqueue_struct *xfs_alloc_wq; @@ -2953,3 +2954,100 @@ xfs_alloc_record_exists( *is_freesp = (fbno <= bno && fbno + flen >= bno + len); return 0; } + +STATIC int +xfs_allocbt_scrub_rmap_check( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + xfs_err(cur->bc_mp, "%s: freespace in rmapbt! %u/%u %u %lld %lld %x", + __func__, cur->bc_private.a.agno, rec->rm_startblock, + rec->rm_blockcount, rec->rm_owner, rec->rm_offset, + rec->rm_flags); + return XFS_BTREE_QUERY_RANGE_ABORT; +} + +STATIC int +xfs_allocbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + xfs_agblock_t bno; + xfs_extlen_t len; + struct xfs_rmap_irec low; + struct xfs_rmap_irec high; + bool no_rmap; + int error; + + bno = be32_to_cpu(rec->alloc.ar_startblock); + len = be32_to_cpu(rec->alloc.ar_blockcount); + + XFS_BTREC_SCRUB_CHECK(bs, bno <= mp->m_sb.sb_agblocks); + XFS_BTREC_SCRUB_CHECK(bs, bno < bno + len); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)bno + len <= + mp->m_sb.sb_agblocks); + + /* if rmapbt, make sure there's no record */ + if (!bs->rmap_cur) + return 0; + + memset(&low, 0, sizeof(low)); + low.rm_startblock = bno; + memset(&high, 0xFF, sizeof(high)); + high.rm_startblock = bno + len - 1; + + error = xfs_rmapbt_query_range(bs->rmap_cur, &low, &high, + &xfs_allocbt_scrub_rmap_check, NULL); + if (error && error != XFS_BTREE_QUERY_RANGE_ABORT) + goto err; + no_rmap = error == 0; + XFS_BTREC_SCRUB_CHECK(bs, no_rmap); +err: + return error; +} + +/* Scrub the freespace btrees for some AG. */ +STATIC int +xfs_allocbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno, + int which) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) + return error; + + bs.cur = xfs_allocbt_init_cursor(mp, NULL, bs.agf_bp, agno, which); + bs.scrub_rec = xfs_allocbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_AG); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} + +int +xfs_bnobt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_allocbt_scrub(mp, agno, XFS_BTNUM_BNO); +} + +int +xfs_cntbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + return xfs_allocbt_scrub(mp, agno, XFS_BTNUM_CNT); +} diff --git a/libxfs/xfs_alloc.h b/libxfs/xfs_alloc.h index 4f2ce38..f1fcc7e 100644 --- a/libxfs/xfs_alloc.h +++ b/libxfs/xfs_alloc.h @@ -213,4 +213,7 @@ xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); int xfs_alloc_record_exists(struct xfs_btree_cur *cur, xfs_agblock_t bno, xfs_extlen_t len, bool *is_freesp); +int xfs_bnobt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); +int xfs_cntbt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); + #endif /* __XFS_ALLOC_H__ */ diff --git a/libxfs/xfs_alloc_btree.c b/libxfs/xfs_alloc_btree.c index ff4bae4..1794791 100644 --- a/libxfs/xfs_alloc_btree.c +++ b/libxfs/xfs_alloc_btree.c @@ -254,6 +254,26 @@ xfs_allocbt_key_diff( return (__int64_t)be32_to_cpu(kp->ar_startblock) - rec->ar_startblock; } +STATIC __int64_t +xfs_bnobt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->alloc.ar_startblock) - + be32_to_cpu(k1->alloc.ar_startblock); +} + +STATIC __int64_t +xfs_cntbt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->alloc.ar_blockcount) - + be32_to_cpu(k1->alloc.ar_blockcount); +} + static bool xfs_allocbt_verify( struct xfs_buf *bp) @@ -342,7 +362,6 @@ const struct xfs_buf_ops xfs_allocbt_buf_ops = { }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_allocbt_keys_inorder( struct xfs_btree_cur *cur, @@ -379,9 +398,29 @@ xfs_allocbt_recs_inorder( be32_to_cpu(r2->alloc.ar_startblock)); } } -#endif /* DEBUG */ -static const struct xfs_btree_ops xfs_allocbt_ops = { +static const struct xfs_btree_ops xfs_bnobt_ops = { + .rec_len = sizeof(xfs_alloc_rec_t), + .key_len = sizeof(xfs_alloc_key_t), + + .dup_cursor = xfs_allocbt_dup_cursor, + .set_root = xfs_allocbt_set_root, + .alloc_block = xfs_allocbt_alloc_block, + .free_block = xfs_allocbt_free_block, + .update_lastrec = xfs_allocbt_update_lastrec, + .get_minrecs = xfs_allocbt_get_minrecs, + .get_maxrecs = xfs_allocbt_get_maxrecs, + .init_key_from_rec = xfs_allocbt_init_key_from_rec, + .init_rec_from_cur = xfs_allocbt_init_rec_from_cur, + .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, + .key_diff = xfs_allocbt_key_diff, + .buf_ops = &xfs_allocbt_buf_ops, + .diff_two_keys = xfs_bnobt_diff_two_keys, + .keys_inorder = xfs_allocbt_keys_inorder, + .recs_inorder = xfs_allocbt_recs_inorder, +}; + +static const struct xfs_btree_ops xfs_cntbt_ops = { .rec_len = sizeof(xfs_alloc_rec_t), .key_len = sizeof(xfs_alloc_key_t), @@ -397,10 +436,9 @@ static const struct xfs_btree_ops xfs_allocbt_ops = { .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, .key_diff = xfs_allocbt_key_diff, .buf_ops = &xfs_allocbt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_cntbt_diff_two_keys, .keys_inorder = xfs_allocbt_keys_inorder, .recs_inorder = xfs_allocbt_recs_inorder, -#endif }; /* @@ -425,12 +463,13 @@ xfs_allocbt_init_cursor( cur->bc_mp = mp; cur->bc_btnum = btnum; cur->bc_blocklog = mp->m_sb.sb_blocklog; - cur->bc_ops = &xfs_allocbt_ops; if (btnum == XFS_BTNUM_CNT) { + cur->bc_ops = &xfs_cntbt_ops; cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]); cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; } else { + cur->bc_ops = &xfs_bnobt_ops; cur->bc_nlevels = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]); } From darrick.wong@oracle.com Thu Jun 16 20:45:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C79B784C2 for ; Thu, 16 Jun 2016 20:45:56 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8A21E304039 for ; Thu, 16 Jun 2016 18:45:56 -0700 (PDT) X-ASG-Debug-ID: 1466127953-04cb6c542758600001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id CiSlWO6UPD9XHSRw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:45:54 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jqk4025824 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:52 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jqxX015167 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:52 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jnZr014264; Fri, 17 Jun 2016 01:45:50 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:49 -0700 Subject: [PATCH 143/145] xfs: support scrubbing refcount btree From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 143/145] xfs: support scrubbing refcount btree To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:46 -0700 Message-ID: <146612794647.16048.14999761589341788073.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127954 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9530 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Plumb in the pieces necessary to check the refcount btree. If rmap is available, check the reference count by performing an interval query against the rmapbt. v2: Handle the case where the rmap records are not all at least the length of the refcount extent. Signed-off-by: Darrick J. Wong --- libxfs/xfs_refcount.c | 224 +++++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_refcount.h | 2 libxfs/xfs_refcount_btree.c | 16 ++- 3 files changed, 238 insertions(+), 4 deletions(-) diff --git a/libxfs/xfs_refcount.c b/libxfs/xfs_refcount.c index a19cb45..760ad7e 100644 --- a/libxfs/xfs_refcount.c +++ b/libxfs/xfs_refcount.c @@ -36,6 +36,7 @@ #include "xfs_bit.h" #include "xfs_refcount.h" #include "xfs_rmap_btree.h" +#include "xfs_scrub.h" /* Allowable refcount adjustment amounts. */ enum xfs_refc_adjust_op { @@ -1577,3 +1578,226 @@ xfs_refcount_free_cow_extent( return __xfs_refcount_add(mp, dfops, &ri); } + +struct xfs_refcountbt_scrub_fragment { + struct xfs_rmap_irec rm; + struct list_head list; +}; + +struct xfs_refcountbt_scrub_rmap_check_info { + xfs_nlink_t nr; + struct xfs_refcount_irec rc; + struct list_head fragments; +}; + +static int +xfs_refcountbt_scrub_rmap_check( + struct xfs_btree_cur *cur, + struct xfs_rmap_irec *rec, + void *priv) +{ + struct xfs_refcountbt_scrub_rmap_check_info *rsrci = priv; + struct xfs_refcountbt_scrub_fragment *frag; + xfs_agblock_t rm_last; + xfs_agblock_t rc_last; + + rm_last = rec->rm_startblock + rec->rm_blockcount; + rc_last = rsrci->rc.rc_startblock + rsrci->rc.rc_blockcount; + if (rec->rm_startblock <= rsrci->rc.rc_startblock && rm_last >= rc_last) + rsrci->nr++; + else { + frag = kmem_zalloc(sizeof(struct xfs_refcountbt_scrub_fragment), + KM_SLEEP); + frag->rm = *rec; + list_add_tail(&frag->list, &rsrci->fragments); + } + + return 0; +} + +STATIC void +xfs_refcountbt_process_rmap_fragments( + struct xfs_mount *mp, + struct xfs_refcountbt_scrub_rmap_check_info *rsrci) +{ + struct list_head worklist; + struct xfs_refcountbt_scrub_fragment *cur; + struct xfs_refcountbt_scrub_fragment *n; + xfs_agblock_t bno; + xfs_agblock_t rbno; + xfs_agblock_t next_rbno; + xfs_nlink_t nr; + xfs_nlink_t target_nr; + + target_nr = rsrci->rc.rc_refcount - rsrci->nr; + if (target_nr == 0) + return; + + /* + * There are (rsrci->rc.rc_refcount - rsrci->nr refcount) + * references we haven't found yet. Pull that many off the + * fragment list and figure out where the smallest rmap ends + * (and therefore the next rmap should start). All the rmaps + * we pull off should start at or before the beginning of the + * refcount record's range. + */ + INIT_LIST_HEAD(&worklist); + rbno = NULLAGBLOCK; + nr = 1; + list_for_each_entry_safe(cur, n, &rsrci->fragments, list) { + if (cur->rm.rm_startblock > rsrci->rc.rc_startblock) + goto fail; + bno = cur->rm.rm_startblock + cur->rm.rm_blockcount; + if (rbno > bno) + rbno = bno; + list_del(&cur->list); + list_add_tail(&cur->list, &worklist); + if (nr == target_nr) + break; + nr++; + } + + if (nr != target_nr) + goto fail; + + while (!list_empty(&rsrci->fragments)) { + /* Discard any fragments ending at rbno. */ + nr = 0; + next_rbno = NULLAGBLOCK; + list_for_each_entry_safe(cur, n, &worklist, list) { + bno = cur->rm.rm_startblock + cur->rm.rm_blockcount; + if (bno != rbno) { + if (next_rbno > bno) + next_rbno = bno; + continue; + } + list_del(&cur->list); + kmem_free(cur); + nr++; + } + + /* Empty list? We're done. */ + if (list_empty(&rsrci->fragments)) + break; + + /* Try to add nr rmaps starting at rbno to the worklist. */ + list_for_each_entry_safe(cur, n, &rsrci->fragments, list) { + bno = cur->rm.rm_startblock + cur->rm.rm_blockcount; + if (cur->rm.rm_startblock != rbno) + goto fail; + list_del(&cur->list); + list_add_tail(&cur->list, &worklist); + if (next_rbno > bno) + next_rbno = bno; + nr--; + if (nr == 0) + break; + } + + rbno = next_rbno; + } + + /* + * Make sure the last extent we processed ends at or beyond + * the end of the refcount extent. + */ + if (rbno < rsrci->rc.rc_startblock + rsrci->rc.rc_blockcount) + goto fail; + + rsrci->nr = rsrci->rc.rc_refcount; +fail: + /* Delete fragments and work list. */ + while (!list_empty(&worklist)) { + cur = list_first_entry(&worklist, + struct xfs_refcountbt_scrub_fragment, list); + list_del(&cur->list); + kmem_free(cur); + } + while (!list_empty(&rsrci->fragments)) { + cur = list_first_entry(&rsrci->fragments, + struct xfs_refcountbt_scrub_fragment, list); + list_del(&cur->list); + kmem_free(cur); + } +} + +STATIC int +xfs_refcountbt_scrub_helper( + struct xfs_btree_scrub *bs, + union xfs_btree_rec *rec) +{ + struct xfs_mount *mp = bs->cur->bc_mp; + struct xfs_rmap_irec low; + struct xfs_rmap_irec high; + struct xfs_refcount_irec irec; + struct xfs_refcountbt_scrub_rmap_check_info rsrci; + struct xfs_refcountbt_scrub_fragment *cur; + int error; + + irec.rc_startblock = be32_to_cpu(rec->refc.rc_startblock); + irec.rc_blockcount = be32_to_cpu(rec->refc.rc_blockcount); + irec.rc_refcount = be32_to_cpu(rec->refc.rc_refcount); + + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_startblock < mp->m_sb.sb_agblocks); + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_startblock < irec.rc_startblock + + irec.rc_blockcount); + XFS_BTREC_SCRUB_CHECK(bs, (unsigned long long)irec.rc_startblock + + irec.rc_blockcount <= mp->m_sb.sb_agblocks); + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_refcount >= 1); + + /* confirm the refcount */ + if (!bs->rmap_cur) + return 0; + + memset(&low, 0, sizeof(low)); + low.rm_startblock = irec.rc_startblock; + memset(&high, 0xFF, sizeof(high)); + high.rm_startblock = irec.rc_startblock + irec.rc_blockcount - 1; + + rsrci.nr = 0; + rsrci.rc = irec; + INIT_LIST_HEAD(&rsrci.fragments); + error = xfs_rmapbt_query_range(bs->rmap_cur, &low, &high, + &xfs_refcountbt_scrub_rmap_check, &rsrci); + if (error && error != XFS_BTREE_QUERY_RANGE_ABORT) + goto err; + error = 0; + xfs_refcountbt_process_rmap_fragments(mp, &rsrci); + XFS_BTREC_SCRUB_CHECK(bs, irec.rc_refcount == rsrci.nr); + +err: + while (!list_empty(&rsrci.fragments)) { + cur = list_first_entry(&rsrci.fragments, + struct xfs_refcountbt_scrub_fragment, list); + list_del(&cur->list); + kmem_free(cur); + } + return error; +} + +/* Scrub the refcount btree for some AG. */ +int +xfs_refcountbt_scrub( + struct xfs_mount *mp, + xfs_agnumber_t agno) +{ + struct xfs_btree_scrub bs; + int error; + + error = xfs_alloc_read_agf(mp, NULL, agno, 0, &bs.agf_bp); + if (error) + return error; + + bs.cur = xfs_refcountbt_init_cursor(mp, NULL, bs.agf_bp, agno, NULL); + bs.scrub_rec = xfs_refcountbt_scrub_helper; + xfs_rmap_ag_owner(&bs.oinfo, XFS_RMAP_OWN_REFC); + error = xfs_btree_scrub(&bs); + xfs_btree_del_cursor(bs.cur, + error ? XFS_BTREE_ERROR : XFS_BTREE_NOERROR); + xfs_trans_brelse(NULL, bs.agf_bp); + + if (!error && bs.error) + error = bs.error; + + return error; +} diff --git a/libxfs/xfs_refcount.h b/libxfs/xfs_refcount.h index 44b0346..d2317f1 100644 --- a/libxfs/xfs_refcount.h +++ b/libxfs/xfs_refcount.h @@ -68,4 +68,6 @@ extern int xfs_refcount_free_cow_extent(struct xfs_mount *mp, struct xfs_defer_ops *dfops, xfs_fsblock_t fsb, xfs_extlen_t len); +extern int xfs_refcountbt_scrub(struct xfs_mount *mp, xfs_agnumber_t agno); + #endif /* __XFS_REFCOUNT_H__ */ diff --git a/libxfs/xfs_refcount_btree.c b/libxfs/xfs_refcount_btree.c index 1b3ba07..3cd30d0 100644 --- a/libxfs/xfs_refcount_btree.c +++ b/libxfs/xfs_refcount_btree.c @@ -196,6 +196,16 @@ xfs_refcountbt_key_diff( return (__int64_t)be32_to_cpu(kp->rc_startblock) - rec->rc_startblock; } +STATIC __int64_t +xfs_refcountbt_diff_two_keys( + struct xfs_btree_cur *cur, + union xfs_btree_key *k1, + union xfs_btree_key *k2) +{ + return (__int64_t)be32_to_cpu(k2->refc.rc_startblock) - + be32_to_cpu(k1->refc.rc_startblock); +} + STATIC bool xfs_refcountbt_verify( struct xfs_buf *bp) @@ -258,7 +268,6 @@ const struct xfs_buf_ops xfs_refcountbt_buf_ops = { .verify_write = xfs_refcountbt_write_verify, }; -#if defined(DEBUG) || defined(XFS_WARN) STATIC int xfs_refcountbt_keys_inorder( struct xfs_btree_cur *cur, @@ -287,13 +296,13 @@ xfs_refcountbt_recs_inorder( b.rc_startblock = be32_to_cpu(r2->refc.rc_startblock); b.rc_blockcount = be32_to_cpu(r2->refc.rc_blockcount); b.rc_refcount = be32_to_cpu(r2->refc.rc_refcount); + a = a; b = b; trace_xfs_refcount_rec_order_error(cur->bc_mp, cur->bc_private.a.agno, &a, &b); } return ret; } -#endif /* DEBUG */ static const struct xfs_btree_ops xfs_refcountbt_ops = { .rec_len = sizeof(struct xfs_refcount_rec), @@ -310,10 +319,9 @@ static const struct xfs_btree_ops xfs_refcountbt_ops = { .init_ptr_from_cur = xfs_refcountbt_init_ptr_from_cur, .key_diff = xfs_refcountbt_key_diff, .buf_ops = &xfs_refcountbt_buf_ops, -#if defined(DEBUG) || defined(XFS_WARN) + .diff_two_keys = xfs_refcountbt_diff_two_keys, .keys_inorder = xfs_refcountbt_keys_inorder, .recs_inorder = xfs_refcountbt_recs_inorder, -#endif }; /* From darrick.wong@oracle.com Thu Jun 16 20:46:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B8ED08442 for ; Thu, 16 Jun 2016 20:46:03 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 34812AC002 for ; Thu, 16 Jun 2016 18:46:03 -0700 (PDT) X-ASG-Debug-ID: 1466127961-04bdf01e15967d0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id gas3F75qtwui3ZmZ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:01 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1jvEI013598 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:57 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1juT1006901 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:45:56 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1jtEA032019; Fri, 17 Jun 2016 01:45:56 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:45:55 -0700 Subject: [PATCH 144/145] xfs: add btree scrub tracepoints From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 144/145] xfs: add btree scrub tracepoints To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:45:54 -0700 Message-ID: <146612795427.16048.13096589914276724799.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127961 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1977 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- include/xfs_trace.h | 3 +++ libxfs/xfs_scrub.c | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/include/xfs_trace.h b/include/xfs_trace.h index ce973ba..206e550 100644 --- a/include/xfs_trace.h +++ b/include/xfs_trace.h @@ -276,6 +276,9 @@ #define trace_xfs_rmap_map_done(...) ((void) 0) #define trace_xfs_rmap_map_error(...) ((void) 0) +#define trace_xfs_btree_scrub_key(...) ((void) 0) +#define trace_xfs_btree_scrub_rec(...) ((void) 0) + /* set c = c to avoid unused var warnings */ #define trace_xfs_perag_get(a,b,c,d) ((c) = (c)) #define trace_xfs_perag_get_tag(a,b,c,d) ((c) = (c)) diff --git a/libxfs/xfs_scrub.c b/libxfs/xfs_scrub.c index 750c482..bd9669d 100644 --- a/libxfs/xfs_scrub.c +++ b/libxfs/xfs_scrub.c @@ -34,6 +34,7 @@ #include "xfs_rmap_btree.h" #include "xfs_log_format.h" #include "xfs_trans.h" +#include "xfs_trace.h" #include "xfs_scrub.h" static const char * const btree_types[] = { @@ -88,6 +89,12 @@ xfs_btree_scrub_rec( struct xfs_btree_block *block; struct xfs_btree_block *keyblock; + trace_xfs_btree_scrub_rec(cur->bc_mp, cur->bc_private.a.agno, + XFS_FSB_TO_AGBNO(cur->bc_mp, + XFS_DADDR_TO_FSB(cur->bc_mp, + cur->bc_bufs[0]->b_bn)), + cur->bc_btnum, 0, cur->bc_nlevels, cur->bc_ptrs[0]); + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[0]); rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); @@ -135,6 +142,13 @@ xfs_btree_scrub_key( struct xfs_btree_block *block; struct xfs_btree_block *keyblock; + trace_xfs_btree_scrub_key(cur->bc_mp, cur->bc_private.a.agno, + XFS_FSB_TO_AGBNO(cur->bc_mp, + XFS_DADDR_TO_FSB(cur->bc_mp, + cur->bc_bufs[level]->b_bn)), + cur->bc_btnum, level, cur->bc_nlevels, + cur->bc_ptrs[level]); + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); From darrick.wong@oracle.com Thu Jun 16 20:46:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id ED74C84E1 for ; Thu, 16 Jun 2016 20:46:12 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 66FD4AC002 for ; Thu, 16 Jun 2016 18:46:12 -0700 (PDT) X-ASG-Debug-ID: 1466127970-04cb6c542558610001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id HD1ScyCub7cx30n2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:10 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1k5F0013846 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:46:06 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1k4mn013492 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:05 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1k3fX026565; Fri, 17 Jun 2016 01:46:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:03 -0700 Subject: [PATCH v6 00/20] xfstests: minor fixes for the reflink/dedupe tests From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH v6 00/20] xfstests: minor fixes for the reflink/dedupe tests To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:02 -0700 Message-ID: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127970 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1440 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Hi all, This is the sixth revision of a patchset that adds to xfstests support for testing reverse-mappings of physical blocks to file and metadata (rmap); support for testing multiple file logical blocks to the same physical block (reflink); and implements the beginnings of online metadata scrubbing. The first eight patches are in Eryu Guan's pull request on 2016-06-15. Those patches haven't changed, but they're not yet in the upstream repo. If you're going to start using this mess, you probably ought to just pull from my github trees for kernel[1], xfsprogs[2], and xfstests[3]. There are also updates for xfs-docs[4]. The kernel patches should apply to dchinner's for-next; xfsprogs patches to for-next; and xfstest to master. The kernel git tree already has for-next included. The patches have been xfstested with x64, i386, and armv7l--arm64, ppc64, and ppc64le no longer boot in qemu. All three architectures pass all 'clone' group tests except xfs/128 (which is the swapext test), and AFAICT don't cause any new failures for the 'auto' group. This is an extraordinary way to eat your data. Enjoy! Comments and questions are, as always, welcome. --D [1] https://github.com/djwong/linux/tree/djwong-devel [2] https://github.com/djwong/xfsprogs/tree/djwong-devel [3] https://github.com/djwong/xfstests/tree/djwong-devel [4] https://github.com/djwong/xfs-documentation/tree/djwong-devel From darrick.wong@oracle.com Thu Jun 16 20:46:12 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E1E2184E0 for ; Thu, 16 Jun 2016 20:46:12 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id A44DE8F8050 for ; Thu, 16 Jun 2016 18:46:12 -0700 (PDT) X-ASG-Debug-ID: 1466127965-04cbb01fec6aa40001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id CVI3eW9dV6NvuKhX (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:05 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1k32H026109 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:03 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1k2VP020050 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:03 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1k2Ld032035; Fri, 17 Jun 2016 01:46:02 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:01 -0700 Subject: [PATCH 145/145] xfs_scrub: create online filesystem scrub program From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 145/145] xfs_scrub: create online filesystem scrub program To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:00 -0700 Message-ID: <146612796035.16048.11351652928279022077.stgit@birch.djwong.org> In-Reply-To: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127965 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 43469 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.50 X-Barracuda-Spam-Status: No, SCORE=0.50 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_MV0713, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.50 BSF_SC0_MV0713 Custom rule MV0713 Create a toy filesystem scrubbing tool that walks the directory tree, queries every file's extents, extended attributes, and stat data. For generic (non-XFS) filesystems this depends on the kernel to do nearly all the validation. Optionally, we can (try to) read all the file data. Future XFS extensions to this program will perform much stronger metadata checking and cross-referencing. In the future we might be able to do such things like lock a directory, check the entries and back pointers, and unlock it; or lock an inode to check the extent map and cross-reference the entries therein with a reverse-mapping index. However, this tool /should/ work for most non-XFS filesystems. Signed-off-by: Darrick J. Wong --- Makefile | 2 man/man8/xfs_scrub.8 | 82 +++++ scrub/Makefile | 26 ++ scrub/generic.c | 372 +++++++++++++++++++++++ scrub/scrub.c | 822 ++++++++++++++++++++++++++++++++++++++++++++++++++ scrub/scrub.h | 100 ++++++ scrub/xfs.c | 241 +++++++++++++++ 7 files changed, 1644 insertions(+), 1 deletion(-) create mode 100644 man/man8/xfs_scrub.8 create mode 100644 scrub/Makefile create mode 100644 scrub/generic.c create mode 100644 scrub/scrub.c create mode 100644 scrub/scrub.h create mode 100644 scrub/xfs.c diff --git a/Makefile b/Makefile index fca0a42..72334d9 100644 --- a/Makefile +++ b/Makefile @@ -46,7 +46,7 @@ HDR_SUBDIRS = include libxfs DLIB_SUBDIRS = libxlog libxcmd libhandle LIB_SUBDIRS = libxfs $(DLIB_SUBDIRS) TOOL_SUBDIRS = copy db estimate fsck fsr growfs io logprint mkfs quota \ - mdrestore repair rtcp m4 man doc debian + mdrestore repair rtcp m4 man doc debian scrub ifneq ("$(XGETTEXT)","") TOOL_SUBDIRS += po diff --git a/man/man8/xfs_scrub.8 b/man/man8/xfs_scrub.8 new file mode 100644 index 0000000..95d7169 --- /dev/null +++ b/man/man8/xfs_scrub.8 @@ -0,0 +1,82 @@ +.TH xfs_scrub 8 +.SH NAME +xfs_scrub \- scrub the contents of an XFS filesystem +.SH SYNOPSIS +.B xfs_scrub +[ +.B \-dvx +] [ +.B \-t +.I fstype +] +.I mountpoint +.br +.B xfs_scrub \-V +.SH DESCRIPTION +.B xfs_scrub +attempts to read and check all the metadata in a Linux filesystem. +.PP +If +.B xfs_scrub +does not detect an XFS filesystem, it will use a generic backend to +scrub the filesystem. This involves walking the directory tree, +querying the data and extended attribute extent maps, performing +limited checks of directory and inode data, reading all of an +inode's extended attributes, and optionally reading all data in +a file. +.PP +If an XFS filesystem is detected, then +.B xfs_scrub +will use private XFS ioctls and sysfs interfaces to perform more +rigorous scrubbing of the internal metadata. Currently this is +limited to asking the kernel to check the per-AG btrees, which +also performs limited cross-referencing. +.SH OPTIONS +.TP +.B \-d +Enable debugging mode, which augments error reports with the exact file +and line where the scrub failure occurred. This also enables verbose +mode. +.TP +.B \-v +Enable verbose mode, which prints periodic status updates. +.TP +.BI \-t " fstype" +Force the use of a particular type of filesystem scrubber. Currently +supported backends are +.I xfs +and +.I generic +scrubbers. +.TP +.B \-V +Prints the version number and exits. +.TP +.B \-x +Scrub file data. This reads every block of every file on disk. +.SH EXIT CODE +The exit code returned by +.B xfs_scrub +is the sum of the following conditions: +.br +\ 0\ \-\ No errors +.br +\ 4\ \-\ File system errors left uncorrected +.br +\ 8\ \-\ Operational error +.br +\ 16\ \-\ Usage or syntax error +.br +.SH CAVEATS +.B xfs_scrub +is a very immature utility! The generic scrub backend walks the directory +tree, reads file extents and data, and queries every extended attribute it +can find. The generic scrub does not grab exclusive locks on the objects +it is examining, nor does it have any way to cross-reference what it sees +against the internal filesystem metadata. +.PP +The XFS backend will some day learn how to do all those things, but for +now its only advantage over the generic backend is that it knows how to +ask the kernel to perform a basic scrub of the XFS AG metadata. +.SH SEE ALSO +.BR xfs_repair (8). diff --git a/scrub/Makefile b/scrub/Makefile new file mode 100644 index 0000000..52b2838 --- /dev/null +++ b/scrub/Makefile @@ -0,0 +1,26 @@ +# +# Copyright (c) 2016 Oracle. All Rights Reserved. +# + +TOPDIR = .. +include $(TOPDIR)/include/builddefs + +LTCOMMAND = xfs_scrub + +HFILES = scrub.h +CFILES = scrub.c generic.c xfs.c + +LLDLIBS += $(LIBBLKID) $(LIBXFS) $(LIBUUID) $(LIBRT) $(LIBPTHREAD) +LTDEPENDENCIES += $(LIBXFS) +LLDFLAGS = -static-libtool-libs + +default: depend $(LTCOMMAND) + +include $(BUILDRULES) + +install: default + $(INSTALL) -m 755 -d $(PKG_ROOT_SBIN_DIR) + $(LTINSTALL) -m 755 $(LTCOMMAND) $(PKG_ROOT_SBIN_DIR) +install-dev: + +-include .dep diff --git a/scrub/generic.c b/scrub/generic.c new file mode 100644 index 0000000..6c397fd --- /dev/null +++ b/scrub/generic.c @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include +#include "libxfs.h" +#include "scrub.h" + +/* Routines to scrub a generic filesystem with nothing but the VFS. */ + +bool +generic_scan_fs( + struct scrub_ctx *ctx) +{ + /* Nothing to do here. */ + return true; +} + +bool +generic_scan_inodes( + struct scrub_ctx *ctx) +{ + /* Nothing to do here. */ + return true; +} + +bool +generic_cleanup( + struct scrub_ctx *ctx) +{ + /* Nothing to do here. */ + return true; +} + +bool +generic_scan_metadata( + struct scrub_ctx *ctx) +{ + /* Nothing to do here. */ + return true; +} + +/* Check all entries in a directory. */ +bool +generic_check_dir( + struct scrub_ctx *ctx, + int dir_fd) +{ + /* Nothing to do here. */ + return true; +} + +/* Check an inode's extents... the hard way. */ +static bool +generic_scan_extents_fibmap( + struct scrub_ctx *ctx, + int fd, + struct stat64 *sb) +{ + unsigned int blk; + unsigned int b; + off_t numblocks; + int error; + + if (!(ctx->quirks & SCRUB_QUIRK_FIBMAP_WORKS)) + return true; + + numblocks = (sb->st_size + sb->st_blksize - 1) / sb->st_blksize; + if (numblocks > UINT_MAX) + numblocks = UINT_MAX; + for (blk = 0; blk < numblocks; blk++) { + b = blk; + error = ioctl(fd, FIBMAP, &b); + if (error) { + if (errno == EOPNOTSUPP) { + path_warn(ctx, +_("data block FIEMAP/FIBMAP not supported, will not check extent map.")); + ctx->quirks &= ~SCRUB_QUIRK_FIBMAP_WORKS; + return true; + } + path_errno(ctx); + } + } + + return true; +} + +/* Check an inode's extents. */ +#define NR_EXTENTS 512 +bool +generic_scan_extents( + struct scrub_ctx *ctx, + int fd, + struct stat64 *sb, + bool attr_fork) +{ + struct fiemap *fiemap; + size_t sz; + struct fiemap_extent *extent; + __u64 next_logical; + bool last = false; + int error; + unsigned int i; + + /* FIEMAP only works for files. */ + if (!S_ISREG(sb->st_mode)) + return true; + + if (!attr_fork && !(ctx->quirks & SCRUB_QUIRK_FIEMAP_WORKS)) + return generic_scan_extents_fibmap(ctx, fd, sb); + else if (attr_fork && !(ctx->quirks & SCRUB_QUIRK_FIEMAP_ATTR_WORKS)) + return true; + + sz = sizeof(struct fiemap) + sizeof(struct fiemap_extent) * NR_EXTENTS; + fiemap = calloc(sz, 1); + if (!fiemap) { + path_errno(ctx); + return false; + } + + fiemap->fm_length = ~0ULL; + fiemap->fm_flags = FIEMAP_FLAG_SYNC; + if (attr_fork) + fiemap->fm_flags |= FIEMAP_FLAG_XATTR; + fiemap->fm_extent_count = NR_EXTENTS; + fiemap->fm_reserved = 0; + next_logical = 0; + + while (!last) { + fiemap->fm_start = next_logical; + error = ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fiemap); + if (error < 0 && errno == EOPNOTSUPP) { + if (attr_fork) { + path_warn(ctx, +_("extended attribute FIEMAP not supported, will not check extent map.")); + ctx->quirks &= ~SCRUB_QUIRK_FIEMAP_WORKS; + } else + ctx->quirks &= ~SCRUB_QUIRK_FIEMAP_ATTR_WORKS; + break; + } + if (error < 0) { + path_errno(ctx); + break; + } + + /* No more extents to map, exit */ + if (!fiemap->fm_mapped_extents) + break; + + for (i = 0; i < fiemap->fm_mapped_extents; i++) { + extent = &fiemap->fm_extents[i]; + + if (extent->fe_length == 0) + path_error(ctx, +_("zero-length extent at offset %llu\n"), + extent->fe_logical); + + next_logical = extent->fe_logical + extent->fe_length; + if (extent->fe_flags & FIEMAP_EXTENT_LAST) + last = true; + } + } + + free(fiemap); + return true; +} + +/* Check the fields of an inode. */ +bool +generic_check_inode( + struct scrub_ctx *ctx, + int fd, + struct stat64 *sb) +{ + if (sb->st_nlink == 0) + path_error(ctx, +_("nlinks should not be 0.")); + + return true; +} + +/* Try to read all the extended attributes. */ +bool +generic_scan_xattrs( + struct scrub_ctx *ctx, + int fd) +{ + char *buf = NULL; + char *p; + ssize_t buf_sz; + ssize_t sz; + char *valbuf = NULL; + ssize_t valbuf_sz = 0; + ssize_t val_sz; + ssize_t sz2; + bool moveon = true; + char *x; + + buf_sz = flistxattr(fd, NULL, 0); + if (buf_sz == -EOPNOTSUPP) + return true; + else if (buf_sz == 0) + return true; + else if (buf_sz < 0) { + path_errno(ctx); + return true; + } + + buf = malloc(buf_sz); + if (!buf) { + path_errno(ctx); + return false; + } + + sz = flistxattr(fd, buf, buf_sz); + if (sz < 0) { + path_errno(ctx); + goto out; + } else if (sz != buf_sz) { + path_error(ctx, +_("read %zu bytes of xattr names, expected %zu bytes."), + sz, buf_sz); + } + + /* Read all the attrs and values. */ + for (p = buf; p < buf + sz; p += strlen(p) + 1) { + val_sz = fgetxattr(fd, p, NULL, 0); + if (val_sz < 0) { + if (errno != ENODATA) + path_errno(ctx); + continue; + } + if (val_sz > valbuf_sz) { + x = realloc(valbuf, val_sz); + if (!x) { + path_errno(ctx); + moveon = false; + break; + } + valbuf = x; + valbuf_sz = val_sz; + } + sz2 = fgetxattr(fd, p, valbuf, val_sz); + if (sz2 < 0) { + path_errno(ctx); + continue; + } else if (sz2 != val_sz) + path_error(ctx, +_("read %zu bytes from xattr %s value, expected %zu bytes."), + sz2, p, val_sz); + } +out: + free(valbuf); + free(buf); + return moveon; +} + +/* Try to read all the extended attributes of things that have no fd. */ +bool +generic_scan_special_xattrs( + struct scrub_ctx *ctx) +{ + char *buf = NULL; + char *p; + ssize_t buf_sz; + ssize_t sz; + char *valbuf = NULL; + ssize_t valbuf_sz = 0; + ssize_t val_sz; + ssize_t sz2; + bool moveon = true; + char *x; + char path[PATH_MAX]; + int error; + + /* Construct the full path to this file. */ + error = construct_path(ctx, path, PATH_MAX); + if (error) { + path_errno(ctx); + return false; + } + + buf_sz = llistxattr(path, NULL, 0); + if (buf_sz == -EOPNOTSUPP) + return true; + else if (buf_sz == 0) + return true; + else if (buf_sz < 0) { + path_errno(ctx); + return true; + } + + buf = malloc(buf_sz); + if (!buf) { + path_errno(ctx); + return false; + } + + sz = llistxattr(path, buf, buf_sz); + if (sz < 0) { + path_errno(ctx); + goto out; + } else if (sz != buf_sz) { + path_error(ctx, +_("read %zu bytes of xattr names, expected %zu bytes."), + sz, buf_sz); + } + + /* Read all the attrs and values. */ + for (p = buf; p < buf + sz; p += strlen(p) + 1) { + val_sz = lgetxattr(path, p, NULL, 0); + if (val_sz < 0) { + path_errno(ctx); + continue; + } + if (val_sz > valbuf_sz) { + x = realloc(valbuf, val_sz); + if (!x) { + path_errno(ctx); + moveon = false; + break; + } + valbuf = x; + valbuf_sz = val_sz; + } + sz2 = lgetxattr(path, p, valbuf, val_sz); + if (sz2 < 0) { + path_errno(ctx); + continue; + } else if (sz2 != val_sz) + path_error(ctx, +_("read %zu bytes from xattr %s value, expected %zu bytes."), + sz2, p, val_sz); + } +out: + free(valbuf); + free(buf); + return moveon; +} + +struct scrub_ops generic_scrub_ops = { + .name = "generic", + .cleanup = generic_cleanup, + .scan_fs = generic_scan_fs, + .scan_inodes = generic_scan_inodes, + .check_dir = generic_check_dir, + .check_inode = generic_check_inode, + .scan_extents = generic_scan_extents, + .scan_xattrs = generic_scan_xattrs, + .scan_special_xattrs = generic_scan_special_xattrs, + .scan_metadata = generic_scan_metadata, +}; diff --git a/scrub/scrub.c b/scrub/scrub.c new file mode 100644 index 0000000..2d68b07 --- /dev/null +++ b/scrub/scrub.c @@ -0,0 +1,822 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "scrub.h" + +#define _PATH_PROC_MOUNTS "/proc/mounts" + +bool verbose; +bool debug; +bool scrub_data; + +static void __attribute__((noreturn)) +usage(void) +{ + fprintf(stderr, _("Usage: %s [OPTIONS] mountpoint\n"), progname); + fprintf(stderr, _("-d:\tRun program in debug mode.\n")); + fprintf(stderr, _("-t:\tUse this filesystem backend for scrubbing.\n")); + fprintf(stderr, _("-v:\tVerbose output.\n")); + fprintf(stderr, _("-x:\tScrub file data too.\n")); + + exit(16); +} + +/* + * Check if the argument is either the device name or mountpoint of a mounted + * filesystem. + */ +static bool +find_mountpoint_check(struct stat64 *sb, struct mntent *t) +{ + struct stat64 ms; + + if (S_ISDIR(sb->st_mode)) { /* mount point */ + if (stat64(t->mnt_dir, &ms) < 0) + return false; + if (sb->st_ino != ms.st_ino) + return false; + if (sb->st_dev != ms.st_dev) + return false; + /* + * Make sure the device given by mtab is accessible + * before using it. + */ + if (stat64(t->mnt_fsname, &ms) < 0) + return false; + } else { /* device */ + if (stat64(t->mnt_fsname, &ms) < 0) + return false; + if (sb->st_rdev != ms.st_rdev) + return false; + /* + * Make sure the mountpoint given by mtab is accessible + * before using it. + */ + if (stat64(t->mnt_dir, &ms) < 0) + return false; + } + + return true; +} + +/* Check that our alleged mountpoint is in mtab */ +static bool +find_mountpoint(char *mtab, struct stat64 *sb, struct mntent *mnt) +{ + struct mntent_cursor cursor; + struct mntent *t = NULL; + bool found = false; + + if (platform_mntent_open(&cursor, mtab) != 0) { + fprintf(stderr, "Error: can't get mntent entries.\n"); + exit(1); + } + + while ((t = platform_mntent_next(&cursor)) != NULL) { + if (find_mountpoint_check(sb, t)) { + *mnt = *t; + found = true; + break; + } + } + platform_mntent_close(&cursor); + return found; +} + +/* Print a string and whatever error is stored in errno. */ +void +__str_errno( + struct scrub_ctx *ctx, + const char *str, + const char *file, + int line) +{ + char buf[256]; + + fprintf(stderr, "%s: %s.", str, strerror_r(errno, buf, 256)); + if (debug) + fprintf(stderr, " (%s line %d)", file, line); + fprintf(stderr, "\n"); + ctx->errors_found++; +} + +/* Print a string and some error text. */ +void +__str_error( + struct scrub_ctx *ctx, + const char *str, + const char *file, + int line, + const char *format, + ...) +{ + va_list args; + + fprintf(stderr, "%s: ", str); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + if (debug) + fprintf(stderr, " (%s line %d)", file, line); + fprintf(stderr, "\n"); + ctx->errors_found++; +} + +/* Print a string and some warning text. */ +void +__str_warn( + struct scrub_ctx *ctx, + const char *str, + const char *file, + int line, + const char *format, + ...) +{ + va_list args; + + fprintf(stderr, "%s: ", str); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + if (debug) + fprintf(stderr, " (%s line %d)", file, line); + fprintf(stderr, "\n"); + ctx->warnings_found++; +} + +/* Print the current path and whatever error is stored in errno. */ +void +__path_errno( + struct scrub_ctx *ctx, + const char *file, + int line) +{ + char buf[256]; + struct list_head *l; + struct path_piece *pp; + int err; + + err = errno; + fprintf(stderr, "%s", ctx->mntpoint); + list_for_each(l, &ctx->path_stack) { + pp = container_of(l, struct path_piece, list); + fprintf(stderr, "/%s", pp->name); + } + fprintf(stderr, ": %s.", strerror_r(err, buf, 256)); + if (debug) + fprintf(stderr, " (%s line %d)", file, line); + fprintf(stderr, "\n"); + ctx->errors_found++; +} + +/* Print the current path and some error text. */ +void +__path_error( + struct scrub_ctx *ctx, + const char *file, + int line, + const char *format, + ...) +{ + va_list args; + struct list_head *l; + struct path_piece *pp; + + fprintf(stderr, "%s", ctx->mntpoint); + list_for_each(l, &ctx->path_stack) { + pp = container_of(l, struct path_piece, list); + fprintf(stderr, "/%s", pp->name); + } + fprintf(stderr, ": "); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + if (debug) + fprintf(stderr, " (%s line %d)", file, line); + fprintf(stderr, "\n"); + ctx->errors_found++; +} + +/* Print the current path and some warning text. */ +void +__path_warn( + struct scrub_ctx *ctx, + const char *file, + int line, + const char *format, + ...) +{ + va_list args; + struct list_head *l; + struct path_piece *pp; + + fprintf(stderr, "%s", ctx->mntpoint); + list_for_each(l, &ctx->path_stack) { + pp = container_of(l, struct path_piece, list); + fprintf(stderr, "/%s", pp->name); + } + fprintf(stderr, ": "); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + if (debug) + fprintf(stderr, " (%s line %d)", file, line); + fprintf(stderr, "\n"); + ctx->warnings_found++; +} + +/* Construct the current path. */ +int +construct_path( + struct scrub_ctx *ctx, + char *buf, + size_t buflen) +{ + size_t nr = 0; + struct list_head *l; + struct path_piece *pp; + int sz; + + /* Mountpoint */ + sz = snprintf(buf + nr, buflen - nr, "%s", ctx->mntpoint); + if (sz < 0) + return -1; + else if (sz > buflen - nr) { + errno = ENOMEM; + return -1; + } + nr += sz; + + /* Intermediate path components. */ + list_for_each(l, &ctx->path_stack) { + pp = container_of(l, struct path_piece, list); + + sz = snprintf(buf + nr, buflen - nr, "/%s", pp->name); + if (sz < 0) + return -1; + else if (sz > buflen - nr) { + errno = ENOMEM; + return -1; + } + nr += sz; + } + + return 0; +} + +#define CHECK_TYPE(type) \ + case DT_##type: \ + if (!S_IS##type(sb->st_mode)) { \ + path_error(ctx, \ +_("dtype of block does not match mode 0x%x\n"), \ + sb->st_mode & S_IFMT); \ + } \ + break; + +/* Ensure that the directory entry matches the stat info. */ +static bool +verify_dirent( + struct scrub_ctx *ctx, + struct dirent *dirent, + struct stat64 *sb) +{ + if (dirent->d_ino != sb->st_ino) + path_error(ctx, +_("inode numbers (%llu != %llu) do not match!"), + (unsigned long long)dirent->d_ino, + (unsigned long long)sb->st_ino); + + switch (dirent->d_type) { + case DT_UNKNOWN: + break; + CHECK_TYPE(BLK) + CHECK_TYPE(CHR) + CHECK_TYPE(DIR) + CHECK_TYPE(FIFO) + CHECK_TYPE(LNK) + CHECK_TYPE(REG) + CHECK_TYPE(SOCK) + } + + return true; +} +#undef CHECK_TYPE + +/* Read all the data in a file. */ +#define READ_BUF_SIZE 262144 +static bool +read_file( + struct scrub_ctx *ctx, + int fd, + struct stat64 *sb) +{ + off_t data_end = 0; + off_t data_start; + off_t start; + ssize_t sz; + size_t count; + static char *readbuf; + bool reports_holes = true; + bool direct_io = false; + int flags; + int error; + static long page_size; + + /* Find the page size. */ + if (!page_size) { + page_size = sysconf(_SC_PAGESIZE); + if (page_size < 0) { + path_errno(ctx); + return false; + } + } + + /* Try to allocate a read buffer if we don't have one. */ + if (!readbuf) { + error = posix_memalign((void **)&readbuf, page_size, + READ_BUF_SIZE); + if (error || !readbuf) { + path_errno(ctx); + return false; + } + } + + /* Can we set O_DIRECT? */ + flags = fcntl(fd, F_GETFL); + error = fcntl(fd, F_SETFL, flags | O_DIRECT); + if (!error) + direct_io = true; + + /* See if SEEK_DATA/SEEK_HOLE work... */ + data_start = lseek(fd, data_end, SEEK_DATA); + if (data_start < 0) { + /* ENXIO for SEEK_DATA means no file data anywhere. */ + if (errno == ENXIO) + return true; + reports_holes = false; + } + + if (reports_holes) { + data_end = lseek(fd, data_start, SEEK_HOLE); + if (data_end < 0) + reports_holes = false; + } + + /* ...or just read everything if they don't. */ + if (!reports_holes) { + data_start = 0; + data_end = sb->st_size; + } + + if (!direct_io) { + posix_fadvise(fd, 0, sb->st_size, POSIX_FADV_SEQUENTIAL); + posix_fadvise(fd, 0, sb->st_size, POSIX_FADV_WILLNEED); + } + /* Read the non-hole areas. */ + while (data_start < data_end) { + start = data_start; + + if (direct_io && (start & (page_size - 1))) + start &= ~(page_size - 1); + count = min(READ_BUF_SIZE, data_end - start); + if (direct_io && (count & (page_size - 1))) + count = (count + page_size) & ~(page_size - 1); + sz = pread(fd, readbuf, count, start); + if (sz < 0) + path_errno(ctx); + else if (sz == 0) { + path_error(ctx, +_("Read zero bytes, expected %zu."), + count); + break; + } else if (sz != count && start + sz != data_end) { + path_warn(ctx, +_("Short read of %zu bytes, expected %zu."), + sz, count); + } + data_start = start + sz; + + if (data_start >= data_end && reports_holes) { + data_start = lseek(fd, data_end, SEEK_DATA); + if (data_start < 0) { + if (errno != ENXIO) + path_errno(ctx); + break; + } + data_end = lseek(fd, data_start, SEEK_HOLE); + if (data_end < 0) { + if (errno != ENXIO) + path_errno(ctx); + break; + } + } + } + + /* Turn off O_DIRECT. */ + if (direct_io) { + flags = fcntl(fd, F_GETFL); + error = fcntl(fd, F_SETFL, flags & ~O_DIRECT); + if (error) + path_errno(ctx); + } + + return true; +} + +/* Scrub a directory. */ +static bool +check_dir( + struct scrub_ctx *ctx, + int dir_fd) +{ + DIR *dir; + struct dirent *dirent; + struct path_piece pp; + int fd = -1; + struct stat64 sb; + struct stat64 fd_sb; + bool moveon; + static char linkbuf[PATH_MAX]; + ssize_t len; + int error; + + /* FS-specific directory checks. */ + moveon = ctx->ops->check_dir(ctx, dir_fd); + if (!moveon) + return moveon; + + /* Iterate the directory entries. */ + dir = fdopendir(dir_fd); + if (!dir) { + path_errno(ctx); + return true; + } + + /* Iterate every directory entry. */ + INIT_LIST_HEAD(&pp.list); + list_add_tail(&pp.list, &ctx->path_stack); + dirent = readdir(dir); + while (dirent) { + if (!strcmp(".", dirent->d_name) || + !strcmp("..", dirent->d_name)) + goto next; + + pp.name = dirent->d_name; + error = fstatat64(dir_fd, dirent->d_name, &sb, + AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW); + if (error) { + path_errno(ctx); + break; + } + + /* Ignore files on other filesystems. */ + if (sb.st_dev != ctx->mnt_sb.st_dev) + goto next; + + /* Check the directory entry itself. */ + moveon = verify_dirent(ctx, dirent, &sb); + if (!moveon) + break; + + /* If symlink, read the target value. */ + if (S_ISLNK(sb.st_mode)) { + len = readlinkat(dir_fd, dirent->d_name, linkbuf, + PATH_MAX); + if (len < 0) + path_errno(ctx); + else if (len != sb.st_size) + path_error(ctx, +_("read %zu bytes from a %zu byte symlink?"), + len, sb.st_size); + } + + /* Read the xattrs without a file descriptor. */ + if (S_ISSOCK(sb.st_mode) || S_ISFIFO(sb.st_mode) || + S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode) || + S_ISLNK(sb.st_mode)) { + moveon = ctx->ops->scan_special_xattrs(ctx); + if (!moveon) + break; + } + + /* If not dir or file, move on to the next dirent. */ + if (!S_ISDIR(sb.st_mode) && !S_ISREG(sb.st_mode)) + goto next; + + /* Open the file */ + fd = openat(dir_fd, dirent->d_name, + O_RDONLY | O_NOATIME | O_NOFOLLOW | O_NOCTTY); + if (fd < 0) { + path_errno(ctx); + goto next; + } + + /* Did the fstatat and the open race? */ + if (fstat64(fd, &fd_sb) < 0) { + path_errno(ctx); + goto close; + } + if (fd_sb.st_ino != sb.st_ino || fd_sb.st_dev != sb.st_dev) + path_warn(ctx, +_("inode changed out from under us!")); + + /* Check the inode. */ + moveon = ctx->ops->check_inode(ctx, fd, &fd_sb); + if (!moveon) + break; + + /* Scan the extent maps. */ + moveon = ctx->ops->scan_extents(ctx, fd, &fd_sb, false); + if (!moveon) + break; + moveon = ctx->ops->scan_extents(ctx, fd, &fd_sb, true); + if (!moveon) + break; + + /* Read all the file data. */ + if (scrub_data && S_ISREG(fd_sb.st_mode)) { + moveon = read_file(ctx, fd, &fd_sb); + if (!moveon) + break; + } + + /* Read all the extended attributes. */ + moveon = ctx->ops->scan_xattrs(ctx, fd); + if (!moveon) + break; + + /* If directory, call ourselves recursively. */ + if (S_ISDIR(fd_sb.st_mode)) { + moveon = check_dir(ctx, fd); + if (!moveon) + break; + /* closedir already closed fd for us */ + fd = -1; + goto next; + } + + /* Close file. */ +close: + error = close(fd); + if (error) + path_errno(ctx); + fd = -1; + +next: + dirent = readdir(dir); + } + + if (fd >= 0) { + error = close(fd); + if (error) + path_errno(ctx); + } + list_del(&pp.list); + + /* Close dir, go away. */ + error = closedir(dir); + if (error) + path_errno(ctx); + + return moveon; +} + + + +/* Traverse the directory tree. */ +static bool +traverse_fs( + struct scrub_ctx *ctx) +{ + bool moveon; + + /* Check the inode. */ + moveon = ctx->ops->check_inode(ctx, ctx->mnt_fd, &ctx->mnt_sb); + if (!moveon) + return moveon; + + /* Scan the extent maps. */ + moveon = ctx->ops->scan_extents(ctx, ctx->mnt_fd, &ctx->mnt_sb, false); + if (!moveon) + return moveon; + moveon = ctx->ops->scan_extents(ctx, ctx->mnt_fd, &ctx->mnt_sb, true); + if (!moveon) + return moveon; + + /* Check the mountpoint directory. */ + moveon = check_dir(ctx, ctx->mnt_fd); + if (!moveon) + return moveon; + + return true; +} + +static struct scrub_ops *scrub_impl[] = { + &xfs_scrub_ops, + &generic_scrub_ops, + NULL +}; + +int +main( + int argc, + char **argv) +{ + int c; + char *mtab = NULL; + struct scrub_ctx ctx; + bool ismnt; + bool moveon; + int ret; + struct scrub_ops **ops; + + progname = basename(argv[0]); + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + ctx.ops = NULL; + while ((c = getopt(argc, argv, "dt:vxV")) != EOF) { + switch (c) { + case 'd': + debug = true; + break; + case 't': + for (ops = scrub_impl; *ops; ops++) { + if (!strcmp(optarg, (*ops)->name)) { + ctx.ops = *ops; + break; + } + } + if (!ctx.ops) { + fprintf(stderr, +_("Unknown filesystem driver '%s'.\n"), + optarg); + return 1; + } + break; + case 'v': + verbose = true; + break; + case 'x': + scrub_data = true; + break; + case 'V': + printf(_("%s version %s\n"), progname, VERSION); + exit(0); + case '?': + default: + usage(); + } + } + + if (optind != argc - 1) + usage(); + + ctx.errors_found = 0; + ctx.warnings_found = 0; + ctx.mntpoint = argv[optind]; + ctx.quirks = SCRUB_QUIRK_FIEMAP_WORKS | SCRUB_QUIRK_FIEMAP_ATTR_WORKS | + SCRUB_QUIRK_FIBMAP_WORKS; + + /* Find the mount record for the passed-in argument. */ + + if (stat64(argv[optind], &ctx.mnt_sb) < 0) { + fprintf(stderr, + _("%s: could not stat: %s: %s\n"), + progname, argv[optind], strerror(errno)); + return 16; + } + + /* + * If the user did not specify an explicit mount table, try to use + * /proc/mounts if it is available, else /etc/mtab. We prefer + * /proc/mounts because it is kernel controlled, while /etc/mtab + * may contain garbage that userspace tools like pam_mounts wrote + * into it. + */ + if (!mtab) { + if (access(_PATH_PROC_MOUNTS, R_OK) == 0) + mtab = _PATH_PROC_MOUNTS; + else + mtab = _PATH_MOUNTED; + } + + ismnt = find_mountpoint(mtab, &ctx.mnt_sb, &ctx.mnt_ent); + if (!ismnt) { + fprintf(stderr, _("%s: Not a mount point or block device.\n"), + ctx.mntpoint); + return 16; + } + ctx.mntpoint = ctx.mnt_ent.mnt_dir; + + /* Find an appropriate scrub backend. */ + for (ops = scrub_impl; !ctx.ops && *ops; ops++) { + if (!strcmp(ctx.mnt_ent.mnt_type, (*ops)->name)) + ctx.ops = *ops; + } + if (!ctx.ops) + ctx.ops = &generic_scrub_ops; + INIT_LIST_HEAD(&ctx.path_stack); + if (verbose) + printf(_("%s: scrubbing %s filesystem with %s driver.\n"), + ctx.mntpoint, ctx.mnt_ent.mnt_type, ctx.ops->name); + + /* Phase 1: Find and verify filesystem */ + if (verbose) + printf(_("Phase 1: Find filesystem.\n")); + ctx.mnt_fd = open(ctx.mntpoint, O_RDONLY | O_NOATIME); + if (ctx.mnt_fd < 0) { + perror(ctx.mntpoint); + return 8; + } + ret = fstat64(ctx.mnt_fd, &ctx.mnt_sb); + if (ret) { + path_errno(&ctx); + moveon = false; + goto out; + } + moveon = ctx.ops->scan_fs(&ctx); + if (!moveon) + goto out; + + /* Phase 2: Check inodes, blocks, and sizes */ + if (verbose) + printf(_("Phase 2: Scanning inodes.\n")); + moveon = ctx.ops->scan_inodes(&ctx); + if (!moveon) + goto out; + + /* Phase 3: Check the directory structure. */ + if (verbose) + printf(_("Phase 3: Check the directory structure.\n")); + moveon = traverse_fs(&ctx); + if (!moveon) + goto out; + + /* Phase X: Check for duplicate blocks(??) */ + + /* Phase Y: Verify link counts(??) */ + + /* Phase 4: Check internal group metadata. */ + if (verbose) + printf(_("Phase 4: Check internal metadata.\n")); + moveon = ctx.ops->scan_metadata(&ctx); + if (!moveon) + goto out; + + /* Clean up scan data. */ + moveon = ctx.ops->cleanup(&ctx); + if (!moveon) + goto out; + +out: + ret = 0; + if (!moveon) + ret |= 8; + + if (ctx.errors_found && ctx.warnings_found) + fprintf(stderr, +_("%s: %lu errors and %lu warnings found. Unmount and run fsck.\n"), + ctx.mntpoint, ctx.errors_found, ctx.warnings_found); + else if (ctx.errors_found && ctx.warnings_found == 0) + fprintf(stderr, +_("%s: %lu errors found. Unmount and run fsck.\n"), + ctx.mntpoint, ctx.errors_found); + else if (ctx.errors_found == 0 && ctx.warnings_found) + fprintf(stderr, +_("%s: %lu warnings found.\n"), + ctx.mntpoint, ctx.warnings_found); + if (ctx.errors_found) + ret |= 4; + + return ret; +} diff --git a/scrub/scrub.h b/scrub/scrub.h new file mode 100644 index 0000000..b7436c1 --- /dev/null +++ b/scrub/scrub.h @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef SCRUB_H_ +#define SCRUB_H_ + +struct scrub_ctx; + +struct scrub_ops { + const char *name; + bool (*cleanup)(struct scrub_ctx *ctx); + bool (*scan_fs)(struct scrub_ctx *ctx); + bool (*scan_inodes)(struct scrub_ctx *ctx); + bool (*check_dir)(struct scrub_ctx *ctx, int dir_fd); + bool (*check_inode)(struct scrub_ctx *ctx, int fd, struct stat64 *sb); + bool (*scan_extents)(struct scrub_ctx *ctx, int fd, struct stat64 *sb, + bool attr_fork); + bool (*scan_xattrs)(struct scrub_ctx *ctx, int fd); + bool (*scan_special_xattrs)(struct scrub_ctx *ctx); + bool (*scan_metadata)(struct scrub_ctx *ctx); +}; + +#define SCRUB_QUIRK_FIEMAP_WORKS (1 << 0) +#define SCRUB_QUIRK_FIEMAP_ATTR_WORKS (1 << 1) +#define SCRUB_QUIRK_FIBMAP_WORKS (1 << 2) +struct scrub_ctx { + struct scrub_ops *ops; + char *mntpoint; + int mnt_fd; + struct mntent mnt_ent; + struct stat64 mnt_sb; + struct statvfs mnt_sv; + struct statfs mnt_sf; + unsigned long errors_found; + unsigned long warnings_found; + unsigned long quirks; + + struct list_head path_stack; + void *priv; +}; + +struct path_piece { + struct list_head list; + const char *name; +}; + +extern bool verbose; +extern bool debug; +extern bool scrub_data; + +void __path_errno(struct scrub_ctx *, const char *, int); +void __path_error(struct scrub_ctx *, const char *, int, const char *, ...); +void __path_warn(struct scrub_ctx *, const char *, int, const char *, ...); +void __str_errno(struct scrub_ctx *, const char *, const char *, int); +void __str_error(struct scrub_ctx *, const char *, const char *, int, const char *, ...); +void __str_warn(struct scrub_ctx *, const char *, const char *, int, const char *, ...); + +#define path_errno(ctx) __path_errno(ctx, __FILE__, __LINE__) +#define path_error(ctx, ...) __path_error(ctx, __FILE__, __LINE__, __VA_ARGS__) +#define path_warn(ctx, ...) __path_warn(ctx, __FILE__, __LINE__, __VA_ARGS__) +#define str_errno(ctx, str) __str_errno(ctx, str, __FILE__, __LINE__) +#define str_error(ctx, str, ...) __str_error(ctx, str, __FILE__, __LINE__, __VA_ARGS__) +#define str_warn(ctx, str, ...) __str_warn(ctx, str, __FILE__, __LINE__, __VA_ARGS__) + +int construct_path(struct scrub_ctx *ctx, char *buf, size_t buflen); + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +extern struct scrub_ops generic_scrub_ops; +extern struct scrub_ops xfs_scrub_ops; + +bool generic_cleanup(struct scrub_ctx *ctx); +bool generic_scan_fs(struct scrub_ctx *ctx); +bool generic_scan_inodes(struct scrub_ctx *ctx); +bool generic_check_dir(struct scrub_ctx *ctx, int dir_fd); +bool generic_check_inode(struct scrub_ctx *ctx, int fd, struct stat64 *sb); +bool generic_scan_extents(struct scrub_ctx *ctx, int fd, struct stat64 *sb, + bool attr_fork); +bool generic_scan_xattrs(struct scrub_ctx *ctx, int fd); +bool generic_scan_special_xattrs(struct scrub_ctx *ctx); + +#endif /* SCRUB_H_ */ diff --git a/scrub/xfs.c b/scrub/xfs.c new file mode 100644 index 0000000..0300066 --- /dev/null +++ b/scrub/xfs.c @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2016 Oracle. All Rights Reserved. + * + * Author: Darrick J. Wong + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "libxfs.h" +#include +#include +#include +#include "scrub.h" + +/* Routines to scrub an XFS filesystem. */ + +struct xfs_scrub_ctx { + xfs_fsop_geom_t geo; + int check_fd; +}; + +static bool +xfs_cleanup( + struct scrub_ctx *ctx) +{ + free(ctx->priv); + ctx->priv = NULL; + + return generic_cleanup(ctx); +} + +/* Find the /sys/fs/xfs/$dev/check path that corresponds to this fs. */ +static bool +xfs_find_sysfs_check( + struct scrub_ctx *ctx) +{ + struct xfs_scrub_ctx *xctx = ctx->priv; + char path[PATH_MAX]; + char buf[PATH_MAX]; + int sz; + ssize_t ssz; + char *p; + + /* /dev/block/$major:$minor usually points "../$kernel_name" */ + sz = snprintf(path, PATH_MAX, "/dev/block/%d:%d", + major(ctx->mnt_sb.st_dev), minor(ctx->mnt_sb.st_dev)); + if (sz < 0) { + path_errno(ctx); + return false; + } + + ssz = readlink(path, buf, PATH_MAX); + if (ssz < 0) { + perror(path); + return false; + } + buf[PATH_MAX - 1] = 0; + + p = strchr(buf, '/'); + p = NULL ? buf : p + 1; + + /* See if we can find a pointer to /sys/fs/xfs/$p/check */ + sz = snprintf(path, PATH_MAX, "/sys/fs/xfs/%s/check", p); + if (sz < 0) { + path_errno(ctx); + return false; + } + + xctx->check_fd = open(path, O_RDONLY | O_DIRECTORY); + if (xctx->check_fd < 0) { + if (errno != ENOENT) + perror(path); + return false; + } + + return true; +} + +/* Read the XFS geometry. */ +static bool +xfs_scan_fs( + struct scrub_ctx *ctx) +{ + struct xfs_scrub_ctx *xctx; + int error; + + if (!platform_test_xfs_fd(ctx->mnt_fd)) { + path_error(ctx, +_("Does not appear to be an XFS filesystem!")); + return false; + } + + xctx = malloc(sizeof(struct xfs_scrub_ctx)); + if (!ctx) { + path_errno(ctx); + return false; + } + xctx->check_fd = -1; + + /* Retrieve XFS geometry. */ + error = xfsctl(ctx->mntpoint, ctx->mnt_fd, XFS_IOC_FSGEOMETRY, + &xctx->geo); + if (error) { + path_errno(ctx); + xfs_cleanup(ctx); + return false; + } + ctx->priv = xctx; + + printf("xfs_scrub is incomplete on XFS.\n"); + + /* XXX: should we whine if we can't find the sysfs check dir? */ + xfs_find_sysfs_check(ctx); + + return generic_scan_fs(ctx); +} + +/* Scrub a piece of metadata in a particular AG. */ +static bool +xfs_scan_ag_metadata( + struct scrub_ctx *ctx, + const char *name, + xfs_agnumber_t ag) +{ + struct xfs_scrub_ctx *xctx = ctx->priv; + char descr[256]; + char cmd[256]; + int fd; + int sz; + ssize_t ssz; + + sz = snprintf(descr, 256, "AG %d %s", ag, name); + if (sz < 0) { + str_errno(ctx, name); + return false; + } + + fd = openat(xctx->check_fd, name, O_WRONLY); + if (fd < 0) { + str_errno(ctx, descr); + return true; + } + + sz = snprintf(cmd, 256, "%d", ag); + if (sz < 0) { + str_errno(ctx, descr); + goto out; + } + + ssz = write(fd, cmd, strlen(cmd)); + if (ssz < 0) { + str_errno(ctx, descr); + goto out; + } else if (ssz != strlen(cmd)) { + str_error(ctx, descr, +_("Strange output length %zu (expected %zu)\n"), + ssz, strlen(cmd)); + ctx->errors_found++; + goto out; + } + +out: + sz = close(fd); + if (sz) + str_errno(ctx, descr); + + return true; +} + +/* Try to scan metadata via sysfs. */ +static bool +xfs_scan_metadata( + struct scrub_ctx *ctx) +{ + struct xfs_scrub_ctx *xctx = ctx->priv; + xfs_agnumber_t ag; + DIR *checkdir; + bool moveon = true; + struct dirent *dirent; + int error; + + if (xctx->check_fd < 0) + return true; + + /* Open the check controls. */ + checkdir = fdopendir(xctx->check_fd); + if (!checkdir) { + path_error(ctx, +_("Failed to open the check control.")); + return false; + } + + /* Scan everything we can in here. */ + while ((dirent = readdir(checkdir)) != NULL) { + if (!strcmp(".", dirent->d_name) || + !strcmp("..", dirent->d_name)) + continue; + + for (ag = 0; ag < xctx->geo.agcount; ag++) { + moveon = xfs_scan_ag_metadata(ctx, dirent->d_name, ag); + if (!moveon) + break; + } + } + + /* Done with metadata scrub. */ + error = closedir(checkdir); + if (error) + path_errno(ctx); + xctx->check_fd = -1; + + return moveon; +} + +/* + * XXX: eventually we'll want to do better checking here, but the generic + * tree walk + metadata scrub is good enough for now. + */ +struct scrub_ops xfs_scrub_ops = { + .name = "xfs", + .cleanup = xfs_cleanup, + .scan_fs = xfs_scan_fs, + .scan_inodes = generic_scan_inodes, + .check_dir = generic_check_dir, + .check_inode = generic_check_inode, + .scan_extents = generic_scan_extents, + .scan_xattrs = generic_scan_xattrs, + .scan_special_xattrs = generic_scan_special_xattrs, + .scan_metadata = xfs_scan_metadata, +}; From darrick.wong@oracle.com Thu Jun 16 20:46:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8E21E84E0 for ; Thu, 16 Jun 2016 20:46:19 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 149D5AC001 for ; Thu, 16 Jun 2016 18:46:19 -0700 (PDT) X-ASG-Debug-ID: 1466127977-04cbb01fec6aa70001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id kOct3ZBgW4relyXz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:17 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kCkv013931 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:12 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kCbQ020216 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:12 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kA0i014344; Fri, 17 Jun 2016 01:46:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:09 -0700 Subject: [PATCH 01/20] xfs/104: don't enospc when ag metadata overhead grows From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 01/20] xfs/104: don't enospc when ag metadata overhead grows To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:08 -0700 Message-ID: <146612796843.25024.7729638172520969379.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127977 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1002 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Adapt to different metadata overhead sizes by trying to reserve decreasing amounts of disk space until we actually succeed at it. Signed-off-by: Darrick J. Wong --- tests/xfs/104 | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/xfs/104 b/tests/xfs/104 index 17f9b62..785027e 100755 --- a/tests/xfs/104 +++ b/tests/xfs/104 @@ -88,9 +88,14 @@ sizeb=`expr $size / $dbsize` # in data blocks echo "*** creating scratch filesystem" _create_scratch -lsize=10m -dsize=${size} -dagcount=${nags} -fillsize=`expr 110 \* 1048576` # 110 megabytes of filling echo "*** using some initial space on scratch filesystem" -_fill_scratch $fillsize +for i in `seq 125 -1 90`; do + fillsize=`expr $i \* 1048576` + out="$(_fill_scratch $fillsize 2>&1)" + echo "$out" | grep -q 'No space left on device' && continue + test -n "${out}" && echo "$out" + break +done # # Grow the filesystem while actively stressing it... From darrick.wong@oracle.com Thu Jun 16 20:46:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5A9F984EA for ; Thu, 16 Jun 2016 20:46:27 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id D9EBFAC002 for ; Thu, 16 Jun 2016 18:46:26 -0700 (PDT) X-ASG-Debug-ID: 1466127983-04bdf01e15967f0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 1PdihesRLb5K07y5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:24 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kJ2T013974 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:19 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kIFl020359 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:19 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kGhn014347; Fri, 17 Jun 2016 01:46:17 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:16 -0700 Subject: [PATCH 02/20] tests: don't put loop control files on the scratch mount From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 02/20] tests: don't put loop control files on the scratch mount To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:14 -0700 Message-ID: <146612797466.25024.4591042273728464399.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127983 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12042 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines If we're doing write/overwrite/snapshot/resource exhaustion tests on the scratch device, use the test directory to hold the loop termination signal files. This way we don't run infinitely because we can't create the flag due to ENOSPC. v2: put the control files in /tmp, not $TEST_DIR Signed-off-by: Darrick J. Wong --- tests/generic/162 | 8 +++++--- tests/generic/163 | 8 +++++--- tests/generic/164 | 8 +++++--- tests/generic/165 | 8 +++++--- tests/generic/166 | 8 +++++--- tests/generic/167 | 8 +++++--- tests/generic/168 | 8 +++++--- tests/generic/170 | 8 +++++--- tests/generic/333 | 20 ++++++++++++-------- tests/generic/334 | 20 ++++++++++++-------- 10 files changed, 64 insertions(+), 40 deletions(-) diff --git a/tests/generic/162 b/tests/generic/162 index 5ff2ee2..61cf463 100755 --- a/tests/generic/162 +++ b/tests/generic/162 @@ -33,7 +33,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -51,6 +51,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=512 @@ -64,7 +66,7 @@ _pwrite_byte 0x61 0 $((loops * blksz)) $testdir/file2 >> $seqres.full _scratch_cycle_mount overwrite() { - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do seq $nr_loops -1 0 | while read i; do _pwrite_byte 0x61 $((i * blksz)) $blksz $testdir/file2 >> $seqres.full done @@ -81,7 +83,7 @@ for i in `seq 1 2`; do done done echo "Finished dedupeing" -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/163 b/tests/generic/163 index fcba677..e2c6042 100755 --- a/tests/generic/163 +++ b/tests/generic/163 @@ -33,7 +33,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -51,6 +51,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=512 @@ -64,7 +66,7 @@ _pwrite_byte 0x61 0 $((loops * blksz)) $testdir/file2 >> $seqres.full _scratch_cycle_mount overwrite() { - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do seq $nr_loops -1 0 | while read i; do _pwrite_byte 0x61 $((i * blksz)) $blksz $testdir/file1 >> $seqres.full done @@ -81,7 +83,7 @@ for i in `seq 1 2`; do done done echo "Finished dedupeing" -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/164 b/tests/generic/164 index acacb7f..78ea787 100755 --- a/tests/generic/164 +++ b/tests/generic/164 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -53,6 +53,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=512 @@ -71,7 +73,7 @@ fbytes() { } reader() { - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do _read_range $testdir/file3 0 $((loops * blksz)) | fbytes done } @@ -91,7 +93,7 @@ for i in `seq 1 2`; do done done echo "Finished reflinking" -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/165 b/tests/generic/165 index b742d19..ca11e1e 100755 --- a/tests/generic/165 +++ b/tests/generic/165 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -54,6 +54,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=512 @@ -72,7 +74,7 @@ fbytes() { } reader() { - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do _read_range $testdir/file3 0 $((loops * blksz)) -d | fbytes done } @@ -92,7 +94,7 @@ for i in `seq 1 2`; do done done echo "Finished reflinking" -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/166 b/tests/generic/166 index 0e31f2e..8600a13 100755 --- a/tests/generic/166 +++ b/tests/generic/166 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -54,6 +54,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=1024 @@ -68,7 +70,7 @@ _scratch_cycle_mount # Snapshot creator... snappy() { n=0 - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do out="$(_cp_reflink $testdir/file1 $testdir/snap_$n 2>&1)" res=$? echo "$out" | grep -q "No space left" && break @@ -83,7 +85,7 @@ snappy & seq $nr_loops -1 0 | while read i; do _pwrite_byte 0x63 $((i * blksz)) $blksz -d $testdir/file1 >> $seqres.full done -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/167 b/tests/generic/167 index b2d6c87..261506b 100755 --- a/tests/generic/167 +++ b/tests/generic/167 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -53,6 +53,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=1024 @@ -67,7 +69,7 @@ _scratch_cycle_mount # Snapshot creator... snappy() { n=0 - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do out="$(_cp_reflink $testdir/file1 $testdir/snap_$n 2>&1)" res=$? echo "$out" | grep -q "No space left" && break @@ -82,7 +84,7 @@ snappy & seq $nr_loops -1 0 | while read i; do _pwrite_byte 0x63 $((i * blksz)) $blksz $testdir/file1 >> $seqres.full done -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/168 b/tests/generic/168 index 7047d10..ceee264 100755 --- a/tests/generic/168 +++ b/tests/generic/168 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -52,6 +52,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=1024 @@ -66,7 +68,7 @@ _scratch_cycle_mount # Direct I/O overwriter... overwrite() { - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do seq $nr_loops -1 0 | while read i; do _pwrite_byte 0x63 $((i * blksz)) $blksz $testdir/file2 >> $seqres.full done @@ -82,7 +84,7 @@ seq 1 10 | while read j; do [ $? -ne 0 ] && exit done done -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/170 b/tests/generic/170 index 4861052..6559243 100755 --- a/tests/generic/170 +++ b/tests/generic/170 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file wait } @@ -53,6 +53,8 @@ _scratch_mkfs > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file mkdir $testdir loops=1024 @@ -67,7 +69,7 @@ _scratch_cycle_mount # Direct I/O overwriter... overwrite() { - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do seq $nr_loops -1 0 | while read i; do _pwrite_byte 0x63 $((i * blksz)) $blksz -d $testdir/file2 >> $seqres.full done @@ -83,7 +85,7 @@ seq 1 10 | while read j; do [ $? -ne 0 ] && exit done done -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/333 b/tests/generic/333 index 8db86e3..3d874d7 100755 --- a/tests/generic/333 +++ b/tests/generic/333 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file $abort_file wait } @@ -54,6 +54,10 @@ _scratch_mkfs_sized $((400 * 1048576)) > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file +abort_file=/tmp/abort +rm -rf $abort_file mkdir $testdir loops=1024 @@ -68,7 +72,7 @@ _scratch_cycle_mount # Snapshot creator... snappy() { n=0 - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do out="$(_cp_reflink $testdir/file1 $testdir/snap_$n 2>&1)" res=$? echo $out | grep -q "No space left" && break @@ -76,7 +80,7 @@ snappy() { test $res -ne 0 && break n=$((n + 1)) done - touch $testdir/abort + touch $abort_file } echo "Snapshot a file undergoing directio rewrite" @@ -85,13 +89,13 @@ seq 1 1000 | while read j; do seq $nr_loops -1 0 | while read i; do out="$(_pwrite_byte 0x63 $((i * blksz)) $blksz -d $testdir/file1 2>&1)" echo $out >> $seqres.full - echo $out | grep -q "No space left" && touch $testdir/abort - echo $out | grep -qi "error" && touch $testdir/abort - test -e $testdir/abort && break + echo $out | grep -q "No space left" && touch $abort_file + echo $out | grep -qi "error" && touch $abort_file + test -e $abort_file && break done - test -e $testdir/abort && break + test -e $abort_file && break done -touch $testdir/finished +touch $finished_file wait # success, all done diff --git a/tests/generic/334 b/tests/generic/334 index 5714125..fb21d4f 100755 --- a/tests/generic/334 +++ b/tests/generic/334 @@ -34,7 +34,7 @@ trap "_cleanup; exit \$status" 0 1 2 3 7 15 _cleanup() { cd / - rm -rf $tmp.* + rm -rf $tmp.* $finished_file $abort_file wait } @@ -53,6 +53,10 @@ _scratch_mkfs_sized $((400 * 1048576)) > $seqres.full 2>&1 _scratch_mount >> $seqres.full 2>&1 testdir=$SCRATCH_MNT/test-$seq +finished_file=/tmp/finished +rm -rf $finished_file +abort_file=/tmp/abort +rm -rf $abort_file mkdir $testdir loops=1024 @@ -67,7 +71,7 @@ _scratch_cycle_mount # Snapshot creator... snappy() { n=0 - while [ ! -e $testdir/finished ]; do + while [ ! -e $finished_file ]; do out="$(_cp_reflink $testdir/file1 $testdir/snap_$n 2>&1)" res=$? echo $out | grep -q "No space left" && break @@ -75,7 +79,7 @@ snappy() { test $res -ne 0 && break n=$((n + 1)) done - touch $testdir/abort + touch $abort_file } echo "Snapshot a file undergoing buffered rewrite" @@ -84,13 +88,13 @@ seq 1 1000 | while read j; do seq $nr_loops -1 0 | while read i; do out="$(_pwrite_byte 0x63 $((i * blksz)) $blksz $testdir/file1 2>&1)" echo $out >> $seqres.full - echo $out | grep -q "No space left" && touch $testdir/abort - echo $out | grep -qi "error" && touch $testdir/abort - test -e $testdir/abort && break + echo $out | grep -q "No space left" && touch $abort_file + echo $out | grep -qi "error" && touch $abort_file + test -e $abort_file && break done - test -e $testdir/abort && break + test -e $abort_file && break done -touch $testdir/finished +touch $finished_file wait # success, all done From darrick.wong@oracle.com Thu Jun 16 20:46:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id CE7E584EA for ; Thu, 16 Jun 2016 20:46:28 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5C5E7AC001 for ; Thu, 16 Jun 2016 18:46:28 -0700 (PDT) X-ASG-Debug-ID: 1466127985-04bdf01e13967f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id DGBdBwkhEOjSDYXU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kNig026241 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:24 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kNRG015828 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:23 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kMZX032165; Fri, 17 Jun 2016 01:46:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:22 -0700 Subject: [PATCH 03/20] xfs: test copy-on-write leftover recovery From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 03/20] xfs: test copy-on-write leftover recovery To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:21 -0700 Message-ID: <146612798101.25024.17766898485265622934.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466127985 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 13850 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Test recovery of CoW leftovers in xfs_repair. Signed-off-by: Darrick J. Wong --- tests/xfs/853 | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/853.out | 13 ++++ tests/xfs/854 | 180 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/854.out | 13 ++++ tests/xfs/group | 2 + 5 files changed, 387 insertions(+) create mode 100755 tests/xfs/853 create mode 100644 tests/xfs/853.out create mode 100755 tests/xfs/854 create mode 100644 tests/xfs/854.out diff --git a/tests/xfs/853 b/tests/xfs/853 new file mode 100755 index 0000000..14a6940 --- /dev/null +++ b/tests/xfs/853 @@ -0,0 +1,179 @@ +#! /bin/bash +# FS QA Test No. 853 +# +# Test recovery of "lost" CoW blocks: +# - Use the debugger to fake a leftover CoW extent +# - See if xfs_repair fixes it +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch_reflink + +rm -f $seqres.full + +echo "Format" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +umount $SCRATCH_MNT + +_get_agf_data() { + field="$1" + shift + + xfs_db -c 'agf 1' "$@" -c "p $field" $SCRATCH_DEV | awk '{print $3}' +} + +_set_agf_data() { + field="$1" + value="$2" + shift; shift + + xfs_db -x -c 'agf 1' "$@" -c "write $field -- $value" $SCRATCH_DEV >> $seqres.full +} + +_get_sb_data() { + field="$1" + shift + + xfs_db -c 'sb 0' "$@" -c "p $field" $SCRATCH_DEV | awk '{print $3}' +} + +_set_sb_data() { + field="$1" + value="$2" + shift; shift + + xfs_db -x -c 'sb 0' "$@" -c "write $field -- $value" $SCRATCH_DEV >> $seqres.full +} + +_filter_leftover() { + grep "^leftover" | sed -e "s/[0-9]\+/NR/g" +} + +_dump_status() { + echo "** " "$@" + xfs_db -c 'sb 0' -c p $SCRATCH_DEV + echo "** agf header" + xfs_db -c 'agf 1' -c p $SCRATCH_DEV + echo "** refcntbt" + xfs_db -c 'agf 1' -c 'addr refcntroot' -c p $SCRATCH_DEV + echo "** rmapbt" + test $is_rmap -gt 0 && xfs_db -c 'agf 1' -c 'addr rmaproot' -c p $SCRATCH_DEV + echo "** bnobt" + xfs_db -c 'agf 1' -c 'addr bnoroot' -c p $SCRATCH_DEV + echo "** cntbt" + xfs_db -c 'agf 1' -c 'addr cntroot' -c p $SCRATCH_DEV +} + +echo "We need AG1 to have a single free extent" +bno_lvl=$(_get_agf_data level -c 'addr bnoroot') +bno_nr=$(_get_agf_data numrecs -c 'addr bnoroot') +refc_lvl=$(_get_agf_data level -c 'addr refcntroot') +refc_nr=$(_get_agf_data numrecs -c 'addr refcntroot') + +test $bno_lvl -eq 0 || echo " AG 1 bnobt must only have one level" +test $bno_nr -eq 1 || echo " AG 1 bnobt must only have one record" +test $refc_lvl -eq 0 || echo " AG 1 refcountbt must only have one level" +test $refc_nr -eq 0 || echo " AG 1 refcountbt must only have one record" + +if [ $is_rmap -gt 0 ]; then + rmap_lvl=$(_get_agf_data level -c 'addr rmaproot') + rmap_nr=$(_get_agf_data numrecs -c 'addr rmaproot') + test $rmap_lvl -eq 0 || echo " AG 1 rmapbt must only have one level" +fi + +echo "Find our extent and old counter values" +bno=$(_get_agf_data "recs[1].startblock" -c 'addr bnoroot') +len=$(_get_agf_data "recs[1].blockcount" -c 'addr bnoroot') +agf_freeblks=$(_get_agf_data freeblks) +sb_fdblocks=$(_get_sb_data fdblocks) + +test $len -ge 200 || echo " AG 1 doesn't have enough free blocks" + +# Take the last 100 blocks of the free extent +debris_len=100 +debris_bno=$((bno + len - debris_len)) + +echo "Remove the extent from the freesp btrees" +_set_agf_data "recs[1].blockcount" $((len - debris_len)) -c 'addr bnoroot' +_set_agf_data "recs[1].blockcount" $((len - debris_len)) -c 'addr cntroot' +_set_agf_data freeblks $((agf_freeblks - debris_len)) +_set_agf_data longest $((len - debris_len)) +_set_sb_data fdblocks $((sb_fdblocks - debris_len)) + +echo "Add the extent to the refcount btree" +_set_agf_data numrecs 1 -c 'addr refcntroot' +_set_agf_data "recs[1].startblock" $debris_bno -c 'addr refcntroot' +_set_agf_data "recs[1].blockcount" $debris_len -c 'addr refcntroot' +_set_agf_data "recs[1].refcount" 1 -c 'addr refcntroot' + +if [ $is_rmap -gt 0 ]; then + rmap_nr=$((rmap_nr + 1)) + _set_agf_data numrecs $rmap_nr -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].startblock" $debris_bno -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].blockcount" $debris_len -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].owner" -9 -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].offset" 0 -c 'addr rmaproot' +fi + +_dump_status "broken fs config" >> $seqres.full + +echo "Look for leftover warning in xfs_check" +_scratch_xfs_check | _filter_leftover + +echo "Look for leftover warning in xfs_repair" +_scratch_xfs_repair -n 2>&1 | _filter_leftover + +echo "Fix filesystem" +_scratch_xfs_repair >> $seqres.full 2>&1 || echo "xfs_repair failed?" + +_dump_status "supposedly fixed fs config" >> $seqres.full + +echo "Look for no more leftover warning in xfs_check" +_scratch_xfs_check | _filter_leftover + +echo "Look for no more leftover warning in xfs_repair" +_scratch_xfs_repair -n 2>&1 | _filter_leftover + +# success, all done +status=0 +exit diff --git a/tests/xfs/853.out b/tests/xfs/853.out new file mode 100644 index 0000000..3224e8d --- /dev/null +++ b/tests/xfs/853.out @@ -0,0 +1,13 @@ +QA output created by 853 +Format +We need AG1 to have a single free extent +Find our extent and old counter values +Remove the extent from the freesp btrees +Add the extent to the refcount btree +Look for leftover warning in xfs_check +leftover CoW extent (NR/NR) len NR +Look for leftover warning in xfs_repair +leftover CoW extent (NR/NR) len NR +Fix filesystem +Look for no more leftover warning in xfs_check +Look for no more leftover warning in xfs_repair diff --git a/tests/xfs/854 b/tests/xfs/854 new file mode 100755 index 0000000..5c6bec9 --- /dev/null +++ b/tests/xfs/854 @@ -0,0 +1,180 @@ +#! /bin/bash +# FS QA Test No. 854 +# +# Test recovery of "lost" CoW blocks: +# - Use the debugger to fake a leftover CoW extent +# - See if mount/umount fixes it +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch_reflink + +rm -f $seqres.full + +echo "Format" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +umount $SCRATCH_MNT + +_get_agf_data() { + field="$1" + shift + + xfs_db -c 'agf 1' "$@" -c "p $field" $SCRATCH_DEV | awk '{print $3}' +} + +_set_agf_data() { + field="$1" + value="$2" + shift; shift + + xfs_db -x -c 'agf 1' "$@" -c "write $field -- $value" $SCRATCH_DEV >> $seqres.full +} + +_get_sb_data() { + field="$1" + shift + + xfs_db -c 'sb 0' "$@" -c "p $field" $SCRATCH_DEV | awk '{print $3}' +} + +_set_sb_data() { + field="$1" + value="$2" + shift; shift + + xfs_db -x -c 'sb 0' "$@" -c "write $field -- $value" $SCRATCH_DEV >> $seqres.full +} + +_filter_leftover() { + grep "^leftover" | sed -e "s/[0-9]\+/NR/g" +} + +_dump_status() { + echo "** " "$@" + xfs_db -c 'sb 0' -c p $SCRATCH_DEV + echo "** agf header" + xfs_db -c 'agf 1' -c p $SCRATCH_DEV + echo "** refcntbt" + xfs_db -c 'agf 1' -c 'addr refcntroot' -c p $SCRATCH_DEV + echo "** rmapbt" + test $is_rmap -gt 0 && xfs_db -c 'agf 1' -c 'addr rmaproot' -c p $SCRATCH_DEV + echo "** bnobt" + xfs_db -c 'agf 1' -c 'addr bnoroot' -c p $SCRATCH_DEV + echo "** cntbt" + xfs_db -c 'agf 1' -c 'addr cntroot' -c p $SCRATCH_DEV +} + +echo "We need AG1 to have a single free extent" +bno_lvl=$(_get_agf_data level -c 'addr bnoroot') +bno_nr=$(_get_agf_data numrecs -c 'addr bnoroot') +refc_lvl=$(_get_agf_data level -c 'addr refcntroot') +refc_nr=$(_get_agf_data numrecs -c 'addr refcntroot') + +test $bno_lvl -eq 0 || echo " AG 1 bnobt must only have one level" +test $bno_nr -eq 1 || echo " AG 1 bnobt must only have one record" +test $refc_lvl -eq 0 || echo " AG 1 refcountbt must only have one level" +test $refc_nr -eq 0 || echo " AG 1 refcountbt must only have one record" + +if [ $is_rmap -gt 0 ]; then + rmap_lvl=$(_get_agf_data level -c 'addr rmaproot') + rmap_nr=$(_get_agf_data numrecs -c 'addr rmaproot') + test $rmap_lvl -eq 0 || echo " AG 1 rmapbt must only have one level" +fi + +echo "Find our extent and old counter values" +bno=$(_get_agf_data "recs[1].startblock" -c 'addr bnoroot') +len=$(_get_agf_data "recs[1].blockcount" -c 'addr bnoroot') +agf_freeblks=$(_get_agf_data freeblks) +sb_fdblocks=$(_get_sb_data fdblocks) + +test $len -ge 200 || echo " AG 1 doesn't have enough free blocks" + +# Take the last 100 blocks of the free extent +debris_len=100 +debris_bno=$((bno + len - debris_len)) + +echo "Remove the extent from the freesp btrees" +_set_agf_data "recs[1].blockcount" $((len - debris_len)) -c 'addr bnoroot' +_set_agf_data "recs[1].blockcount" $((len - debris_len)) -c 'addr cntroot' +_set_agf_data freeblks $((agf_freeblks - debris_len)) +_set_agf_data longest $((len - debris_len)) +_set_sb_data fdblocks $((sb_fdblocks - debris_len)) + +echo "Add the extent to the refcount btree" +_set_agf_data numrecs 1 -c 'addr refcntroot' +_set_agf_data "recs[1].startblock" $debris_bno -c 'addr refcntroot' +_set_agf_data "recs[1].blockcount" $debris_len -c 'addr refcntroot' +_set_agf_data "recs[1].refcount" 1 -c 'addr refcntroot' + +if [ $is_rmap -gt 0 ]; then + rmap_nr=$((rmap_nr + 1)) + _set_agf_data numrecs $rmap_nr -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].startblock" $debris_bno -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].blockcount" $debris_len -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].owner" -9 -c 'addr rmaproot' + _set_agf_data "recs[$rmap_nr].offset" 0 -c 'addr rmaproot' +fi + +_dump_status "broken fs config" >> $seqres.full + +echo "Look for leftover warning in xfs_check" +_scratch_xfs_check | _filter_leftover + +echo "Look for leftover warning in xfs_repair" +_scratch_xfs_repair -n 2>&1 | _filter_leftover + +echo "Mount filesystem" +_scratch_mount +umount $SCRATCH_MNT + +_dump_status "supposedly fixed fs config" >> $seqres.full + +echo "Look for no more leftover warning in xfs_check" +_scratch_xfs_check | _filter_leftover + +echo "Look for no more leftover warning in xfs_repair" +_scratch_xfs_repair -n 2>&1 | _filter_leftover + +# success, all done +status=0 +exit diff --git a/tests/xfs/854.out b/tests/xfs/854.out new file mode 100644 index 0000000..aae2fd7 --- /dev/null +++ b/tests/xfs/854.out @@ -0,0 +1,13 @@ +QA output created by 854 +Format +We need AG1 to have a single free extent +Find our extent and old counter values +Remove the extent from the freesp btrees +Add the extent to the refcount btree +Look for leftover warning in xfs_check +leftover CoW extent (NR/NR) len NR +Look for leftover warning in xfs_repair +leftover CoW extent (NR/NR) len NR +Mount filesystem +Look for no more leftover warning in xfs_check +Look for no more leftover warning in xfs_repair diff --git a/tests/xfs/group b/tests/xfs/group index f4c6816..4ac62c1 100644 --- a/tests/xfs/group +++ b/tests/xfs/group @@ -285,3 +285,5 @@ 303 auto quick quota 304 auto quick quota 305 auto quota +853 auto quick clone +854 auto quick clone From darrick.wong@oracle.com Thu Jun 16 20:46:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D750B84B6 for ; Thu, 16 Jun 2016 20:46:39 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id A8AA18F804C for ; Thu, 16 Jun 2016 18:46:39 -0700 (PDT) X-ASG-Debug-ID: 1466127997-04cb6c542658660001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ZGD4KCA5zFBriRzs (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:37 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kUMh014059 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:31 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kUXv015940 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:30 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kTYl026607; Fri, 17 Jun 2016 01:46:29 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:28 -0700 Subject: [PATCH 04/20] xfs: test per-ag allocation accounting during truncate-caused refcountbt expansion From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 04/20] xfs: test per-ag allocation accounting during truncate-caused refcountbt expansion To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, Christoph Hellwig , fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:27 -0700 Message-ID: <146612798735.25024.15150901661628191347.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466127997 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3990 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Ensure that refcountbt allocations during truncate operations come from the per-AG reservation and are not charged to the transaction. Reported-by: Christoph Hellwig Signed-off-by: Darrick J. Wong --- tests/xfs/855 | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/855.out | 10 ++++++ tests/xfs/group | 1 + 3 files changed, 106 insertions(+) create mode 100755 tests/xfs/855 create mode 100644 tests/xfs/855.out diff --git a/tests/xfs/855 b/tests/xfs/855 new file mode 100755 index 0000000..93bd286 --- /dev/null +++ b/tests/xfs/855 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 855 +# +# Ensure that we can create enough distinct reflink entries to force creation +# of a multi-level refcount btree by reflinking a file a number of times and +# truncating the copies at successively lower sizes. Delete and recreate a few +# times to exercise the refcount btree grow/shrink functions. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch_reflink +_require_cp_reflink + +rm -f $seqres.full + +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount + +testdir=$SCRATCH_MNT/test-$seq +mkdir $testdir + +echo "Create the original file blocks" +blksz="$(stat -f $testdir -c '%S')" +nr_blks=$((2 * blksz / 12)) + +for i in 1 2 x; do + _pwrite_byte 0x61 0 $((blksz * nr_blks)) $testdir/file1 >> $seqres.full + + echo "$i: Reflink a bunch of times" + seq 1 $nr_blks | while read nr; do + _cp_reflink $testdir/file1 $testdir/file1.$nr >> $seqres.full + done + sync + + echo "$i: Truncate files" + seq 1 $nr_blks | while read nr; do + truncate -s $((blksz * (nr_blks - nr))) $testdir/file1.$nr >> $seqres.full + done + + umount $SCRATCH_MNT + _check_scratch_fs + _scratch_mount + + test $i = "x" && break + + echo "$i: Delete both files" + rm -rf $testdir + mkdir -p $testdir + umount $SCRATCH_MNT + _check_scratch_fs + _scratch_mount +done + +# success, all done +status=0 +exit diff --git a/tests/xfs/855.out b/tests/xfs/855.out new file mode 100644 index 0000000..d196352 --- /dev/null +++ b/tests/xfs/855.out @@ -0,0 +1,10 @@ +QA output created by 855 +Create the original file blocks +1: Reflink a bunch of times +1: Truncate files +1: Delete both files +2: Reflink a bunch of times +2: Truncate files +2: Delete both files +x: Reflink a bunch of times +x: Truncate files diff --git a/tests/xfs/group b/tests/xfs/group index 4ac62c1..f0ca410 100644 --- a/tests/xfs/group +++ b/tests/xfs/group @@ -287,3 +287,4 @@ 305 auto quota 853 auto quick clone 854 auto quick clone +855 auto clone From darrick.wong@oracle.com Thu Jun 16 20:46:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 96831850C for ; Thu, 16 Jun 2016 20:46:45 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0D857AC001 for ; Thu, 16 Jun 2016 18:46:44 -0700 (PDT) X-ASG-Debug-ID: 1466128002-04cbb01fef6aae0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id mr8l44wq9D8FelEg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:42 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kaRh014082 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:46:36 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1ka7j013940 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:46:36 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1kZb2004484; Fri, 17 Jun 2016 01:46:35 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:35 -0700 Subject: [PATCH 05/20] reflink: test interaction with swap files From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 05/20] reflink: test interaction with swap files To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, Christoph Hellwig , fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:33 -0700 Message-ID: <146612799371.25024.16214922782653970895.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128002 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6087 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since none of the current filesystems support reflinked swap files, make sure that we prohibit reflinking of swapfiles and swapon of reflinked files. Signed-off-by: Darrick J. Wong Cc: Christoph Hellwig --- tests/generic/923 | 74 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/923.out | 6 ++++ tests/generic/924 | 73 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/924.out | 5 +++ tests/generic/group | 2 + 5 files changed, 160 insertions(+) create mode 100755 tests/generic/923 create mode 100644 tests/generic/923.out create mode 100755 tests/generic/924 create mode 100644 tests/generic/924.out diff --git a/tests/generic/923 b/tests/generic/923 new file mode 100755 index 0000000..73c1621 --- /dev/null +++ b/tests/generic/923 @@ -0,0 +1,74 @@ +#! /bin/bash +# FS QA Test No. 923 +# +# Check that we can't reflink a swapfile. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 7 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* + wait +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_require_scratch_reflink +_require_cp_reflink + +echo "Format and mount" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full 2>&1 + +testdir=$SCRATCH_MNT/test-$seq +mkdir $testdir + +blocks=160 +blksz=65536 + +echo "Initialize file" +echo > $seqres.full +_pwrite_byte 0x61 0 $((blocks * blksz)) $testdir/file1 >> $seqres.full +mkswap -U 27376b42-ff65-42ca-919f-6c9b62292a5c $testdir/file1 >> $seqres.full +swapon $testdir/file1 + +echo "Try to reflink" +_cp_reflink $testdir/file1 $testdir/file2 2>&1 | _filter_scratch + +echo "Tear it down" +swapoff $testdir/file1 + +# success, all done +status=0 +exit diff --git a/tests/generic/923.out b/tests/generic/923.out new file mode 100644 index 0000000..97c18cf --- /dev/null +++ b/tests/generic/923.out @@ -0,0 +1,6 @@ +QA output created by 923 +Format and mount +Initialize file +Try to reflink +cp: failed to clone 'SCRATCH_MNT/test-923/file2' from 'SCRATCH_MNT/test-923/file1': Text file busy +Tear it down diff --git a/tests/generic/924 b/tests/generic/924 new file mode 100755 index 0000000..86c2a39 --- /dev/null +++ b/tests/generic/924 @@ -0,0 +1,73 @@ +#! /bin/bash +# FS QA Test No. 924 +# +# Check that we can't swapon a reflinked file. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 7 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* + wait +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_require_scratch_reflink +_require_cp_reflink + +echo "Format and mount" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full 2>&1 + +testdir=$SCRATCH_MNT/test-$seq +mkdir $testdir + +blocks=160 +blksz=65536 + +echo "Initialize file" +echo > $seqres.full +_pwrite_byte 0x61 0 $((blocks * blksz)) $testdir/file1 >> $seqres.full +mkswap -U 27376b42-ff65-42ca-919f-6c9b62292a5c $testdir/file1 >> $seqres.full +_cp_reflink $testdir/file1 $testdir/file2 2>&1 | _filter_scratch + +echo "Try to swapon" +swapon $testdir/file1 2>&1 | _filter_scratch + +swapoff $testdir/file1 >> $seqres.full 2>&1 + +# success, all done +status=0 +exit diff --git a/tests/generic/924.out b/tests/generic/924.out new file mode 100644 index 0000000..b67e6fa --- /dev/null +++ b/tests/generic/924.out @@ -0,0 +1,5 @@ +QA output created by 924 +Format and mount +Initialize file +Try to swapon +swapon: SCRATCH_MNT/test-924/file1: swapon failed: Invalid argument diff --git a/tests/generic/group b/tests/generic/group index 36fb759..6fdf109 100644 --- a/tests/generic/group +++ b/tests/generic/group @@ -354,3 +354,5 @@ 349 blockdev quick rw 350 blockdev quick rw 351 blockdev quick rw +923 auto quick clone +924 auto quick clone From darrick.wong@oracle.com Thu Jun 16 20:46:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AFDD5850C for ; Thu, 16 Jun 2016 20:46:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 750958F804C for ; Thu, 16 Jun 2016 18:46:46 -0700 (PDT) X-ASG-Debug-ID: 1466128003-04cb6c542658670001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 7BnXWNg8loYVxR4c (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:44 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kgD0026391 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:46:42 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1kgQU013983 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:42 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kfDo032270; Fri, 17 Jun 2016 01:46:41 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:41 -0700 Subject: [PATCH 06/20] xfs: test rmap behavior when multiple bmbt records map to a single rmapbt record From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 06/20] xfs: test rmap behavior when multiple bmbt records map to a single rmapbt record To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:40 -0700 Message-ID: <146612800006.25024.13315461947793130372.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128004 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8614 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Make sure that we can handle multiple bmbt records mapping to a single rmapbt record. This can happen if you fallocate more than 2^21 contiguous blocks to a file. (Also add some helpers that can create huge devices with some dm-zero and dm-snapshot fakery.) v2: remove irrelevant t_immutable changes, put test in correct group v3: calculate the hugedisk size correctly so that there are 2^22 blocks/AG Signed-off-by: Darrick J. Wong --- common/dmhugedisk | 61 +++++++++++++++++++++++++++ tests/xfs/856 | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/856.out | 13 ++++++ tests/xfs/group | 1 4 files changed, 196 insertions(+) create mode 100644 common/dmhugedisk create mode 100755 tests/xfs/856 create mode 100644 tests/xfs/856.out diff --git a/common/dmhugedisk b/common/dmhugedisk new file mode 100644 index 0000000..9c3c7d5 --- /dev/null +++ b/common/dmhugedisk @@ -0,0 +1,61 @@ +##/bin/bash +# Routines for creating huge (fake) disks +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle. All Rights Reserved. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# Contact information: Oracle Corporation, 500 Oracle Parkway, +# Redwood Shores, CA 94065, USA, or: http://www.oracle.com/ +#----------------------------------------------------------------------- + +_require_dmhugedisk() +{ + _require_dm_target zero + _require_dm_target snapshot +} + +_dmhugedisk_init() +{ + test -z "$1" && _fatal "must specify sector count to _dmhugedisk_init" + local dm_backing_dev=$SCRATCH_DEV + + $DMSETUP_PROG remove huge-test > /dev/null 2>&1 + $DMSETUP_PROG remove huge-test-zero > /dev/null 2>&1 + + local blk_dev_size=$1 + + DMHUGEDISK_ZERO='/dev/mapper/huge-test-zero' + DMHUGEDISK_DEV='/dev/mapper/huge-test' + + DMHUGEDISK_ZERO_TABLE="0 $blk_dev_size zero" + DMHUGEDISK_DEV_TABLE="0 $blk_dev_size snapshot $DMHUGEDISK_ZERO $SCRATCH_DEV N 512" + + $DMSETUP_PROG create huge-test-zero --table "$DMHUGEDISK_ZERO_TABLE" || \ + _fatal "failed to create dm huge zero device" + $DMSETUP_PROG create huge-test --table "$DMHUGEDISK_DEV_TABLE" || \ + _fatal "failed to create dm huge device" +} + +_dmhugedisk_cleanup() +{ + $UMOUNT_PROG $SCRATCH_MNT > /dev/null 2>&1 + # wait for device to be fully settled so that 'dmsetup remove' doesn't + # fail due to EBUSY + $UDEV_SETTLE_PROG >/dev/null 2>&1 + $DMSETUP_PROG remove huge-test > /dev/null 2>&1 + $DMSETUP_PROG remove huge-test-zero > /dev/null 2>&1 +} + diff --git a/tests/xfs/856 b/tests/xfs/856 new file mode 100755 index 0000000..1bfb581 --- /dev/null +++ b/tests/xfs/856 @@ -0,0 +1,121 @@ +#! /bin/bash +# FS QA Test No. 856 +# +# Create a file with more than 2^21 extents (the max length of a bmbt record). +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + _dmhugedisk_cleanup + rm -rf $tmp.* + _scratch_mkfs >/dev/null 2>&1 +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/dmhugedisk + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch +_require_xfs_io_command "falloc" + +rm -f $seqres.full + +# Figure out block size +echo "Figure out block size" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +test $is_rmap -gt 0 || _notrun "rmap not supported on scratch fs" + +testdir=$SCRATCH_MNT/test-$seq +blksz="$(stat -f $SCRATCH_MNT -c '%S')" + +umount $SCRATCH_MNT + +echo "Format huge device" +_dmhugedisk_init $((blksz * 4 * 4400)) # more than 2^22 blocks per AG, 2 AGs +_mkfs_dev -d agcount=2 $DMHUGEDISK_DEV +_mount $DMHUGEDISK_DEV $SCRATCH_MNT +xfs_info $SCRATCH_MNT >> $seqres.full + +echo "Create the original file blocks" +mkdir $testdir +blksz="$(stat -f $testdir -c '%S')" +nr_blks=2100000 # 2^21 plus a little more +echo $XFS_IO_PROG -f -c "falloc 0 $((nr_blks * blksz))" $testdir/file1 >> $seqres.full +$XFS_IO_PROG -f -c "falloc 0 $((nr_blks * blksz))" $testdir/file1 >> $seqres.full + +echo "Check extent count" +xfs_bmap -l -p -v $testdir/file1 >> $seqres.full +xfs_bmap -l -p -v $testdir/file1 | grep '^[[:space:]]*1:' -q && xfs_bmap -l -p -v $testdir/file1 +inum=$(stat -c '%i' $testdir/file1) +umount $SCRATCH_MNT + +echo "Check bmap count" +nr_bmaps=$(xfs_db -c "inode $inum" -c "bmap" $DMHUGEDISK_DEV | grep 'data offset' | wc -l) +test $nr_bmaps -gt 1 || xfs_db -c "inode $inum" -c "bmap" $DMHUGEDISK_DEV +#xfs_db -c "agf 0" -c p -c "inode $inum" -c "bmap" $DMHUGEDISK_DEV + +echo "Check rmap count" +nr_rmaps=$(xfs_db -c 'agf 0' -c 'addr rmaproot' -c 'p' $DMHUGEDISK_DEV | grep ",$inum,[0-9]*,1,0,0" | wc -l) +test $nr_rmaps -eq 1 || xfs_db -c 'agf 0' -c 'addr rmaproot' -c 'p' $DMHUGEDISK_DEV | grep ",$inum,[0-9]*,1,0,0" + +echo "Check and fake-repair huge filesystem" | tee -a $seqres.full +$XFS_DB_PROG -c 'check' $DMHUGEDISK_DEV +$XFS_REPAIR_PROG -n $DMHUGEDISK_DEV >> $seqres.full 2>&1 +test $? -eq 0 || echo "xfs_repair -n failed, see $seqres.full" + +echo "Real repair huge filesystem" | tee -a $seqres.full +$XFS_REPAIR_PROG $DMHUGEDISK_DEV >> $seqres.full 2>&1 +test $? -eq 0 || echo "xfs_repair failed, see $seqres.full" + +echo "Check bmap count again" +nr_bmaps=$(xfs_db -c "inode $inum" -c "bmap" $DMHUGEDISK_DEV | grep 'data offset' | wc -l) +test $nr_bmaps -gt 1 || xfs_db -c "inode $inum" -c "bmap" $DMHUGEDISK_DEV + +echo "Check rmap count again" +nr_rmaps=$(xfs_db -c 'agf 0' -c 'addr rmaproot' -c 'p' $DMHUGEDISK_DEV | grep ",$inum,[0-9]*,1,0,0" | wc -l) +test $nr_rmaps -eq 1 || xfs_db -c 'agf 0' -c 'addr rmaproot' -c 'p' $DMHUGEDISK_DEV | grep ",$inum,[0-9]*,1,0,0" + +echo "Check and fake-repair huge filesystem again" | tee -a $seqres.full +$XFS_DB_PROG -c 'check' $DMHUGEDISK_DEV +$XFS_REPAIR_PROG -n $DMHUGEDISK_DEV >> $seqres.full 2>&1 +_dmhugedisk_cleanup + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/856.out b/tests/xfs/856.out new file mode 100644 index 0000000..b24ebf2 --- /dev/null +++ b/tests/xfs/856.out @@ -0,0 +1,13 @@ +QA output created by 856 +Figure out block size +Format huge device +Create the original file blocks +Check extent count +Check bmap count +Check rmap count +Check and fake-repair huge filesystem +Real repair huge filesystem +Check bmap count again +Check rmap count again +Check and fake-repair huge filesystem again +Done diff --git a/tests/xfs/group b/tests/xfs/group index f0ca410..1ad37ff 100644 --- a/tests/xfs/group +++ b/tests/xfs/group @@ -288,3 +288,4 @@ 853 auto quick clone 854 auto quick clone 855 auto clone +856 auto quick clone rmap From darrick.wong@oracle.com Thu Jun 16 20:46:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id BDF6284DF for ; Thu, 16 Jun 2016 20:46:59 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 7CB39304048 for ; Thu, 16 Jun 2016 18:46:59 -0700 (PDT) X-ASG-Debug-ID: 1466128016-04bdf01e1096820001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ibUlTBFGUBEmIQGh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:56 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kpWu014290 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:46:51 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1koGt014097 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:51 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kmdx014508; Fri, 17 Jun 2016 01:46:49 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:47 -0700 Subject: [PATCH 07/20] reflink: test changing sharers of a block while keeping refcount the same From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 07/20] reflink: test changing sharers of a block while keeping refcount the same To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:46 -0700 Message-ID: <146612800634.25024.14778502538091640792.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128016 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12326 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Ensure that we can handle the case where the refcount stays the same even though the actual sharers changes. Signed-off-by: Darrick J. Wong --- tests/generic/925 | 80 ++++++++++++++++++++++++++++++++++++++++++ tests/generic/925.out | 69 ++++++++++++++++++++++++++++++++++++ tests/generic/926 | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/926.out | 20 ++++++++++ tests/generic/group | 2 + 5 files changed, 265 insertions(+) create mode 100755 tests/generic/925 create mode 100644 tests/generic/925.out create mode 100755 tests/generic/926 create mode 100644 tests/generic/926.out diff --git a/tests/generic/925 b/tests/generic/925 new file mode 100755 index 0000000..9fa4ba9 --- /dev/null +++ b/tests/generic/925 @@ -0,0 +1,80 @@ +#! /bin/bash +# FS QA Test No. 925 +# +# Share an extent amongst a bunch of files such that the refcount +# stays the same while the rate of change of the set of owners is +# steadily increasing. For example, an extent of 32 blocks is owned +# by 32 files. At block 1, change one of the owners. At block 2, +# change 2 of the owners, and so on. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 7 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* + wait +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_require_scratch_reflink + +echo "Format and mount" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full 2>&1 + +testdir=$SCRATCH_MNT/test-$seq +mkdir $testdir + +blocks=64 +blksz=65536 + +echo "Initialize file" +_pwrite_byte 0x61 0 $((blocks * blksz)) $testdir/file >> $seqres.full + +echo "Share the file n-ways" +seq 1 $((blocks - 1)) | while read nr; do + _reflink_range $testdir/file 0 $testdir/file$nr.0 0 $((nr * blksz)) >> $seqres.full + seq $nr $((blocks - 1)) | while read nnr; do + _reflink_range $testdir/file $((nnr * blksz)) $testdir/file$nr.$nnr $((nnr * blksz)) $blksz >> $seqres.full + done +done +_scratch_cycle_mount + +echo "Check output" +md5sum $testdir/file $testdir/file*.0 | _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/generic/925.out b/tests/generic/925.out new file mode 100644 index 0000000..099d6d3 --- /dev/null +++ b/tests/generic/925.out @@ -0,0 +1,69 @@ +QA output created by 925 +Format and mount +Initialize file +Share the file n-ways +Check output +bdbcf02ee0aa977795a79d25fcfdccb1 SCRATCH_MNT/test-925/file +2d61aa54b58c2e94403fb092c3dbc027 SCRATCH_MNT/test-925/file1.0 +399c239a8d72b5b2beb15565cf14f6d6 SCRATCH_MNT/test-925/file10.0 +7f783291615a5db41ba33d6c50318095 SCRATCH_MNT/test-925/file11.0 +4feff1bdae53d042e572a5e240b1183f SCRATCH_MNT/test-925/file12.0 +ac2b0a907cd84c091c1cc36384246e42 SCRATCH_MNT/test-925/file13.0 +ff420a8abc25ff0a012638ddd9b81e6c SCRATCH_MNT/test-925/file14.0 +3eb1751bcb7cff809df2ec376e45fe6f SCRATCH_MNT/test-925/file15.0 +7202826a7791073fe2787f0c94603278 SCRATCH_MNT/test-925/file16.0 +7b0fea2a208aa4738d8b9433c7b8421d SCRATCH_MNT/test-925/file17.0 +c6b6ec99b28741ffb3be2d7ff361ad89 SCRATCH_MNT/test-925/file18.0 +d609dcbdc972b8cff16acd74414a8dc9 SCRATCH_MNT/test-925/file19.0 +81615449a98aaaad8dc179b3bec87f38 SCRATCH_MNT/test-925/file2.0 +d97ae5fdb25c4622d5a2f313460a2b96 SCRATCH_MNT/test-925/file20.0 +afae74f7a13edf57f43bab5da6e411d6 SCRATCH_MNT/test-925/file21.0 +0ed53c341d0154d68c336eaa9d05990d SCRATCH_MNT/test-925/file22.0 +ab20d0025b58cbf9fc49e436b7d7acef SCRATCH_MNT/test-925/file23.0 +5279106ed91359051fbdb61e87d5077d SCRATCH_MNT/test-925/file24.0 +9a8719c84c1a42d030fc6d700046eaf5 SCRATCH_MNT/test-925/file25.0 +d9b21a065727fd8118d493f7c62e7fb2 SCRATCH_MNT/test-925/file26.0 +d74ee01c55b2474f91a3723a01c83591 SCRATCH_MNT/test-925/file27.0 +ba7202bfc4b9cda564156562d8672a3f SCRATCH_MNT/test-925/file28.0 +1b3d697355ca662451eb12419cab8eef SCRATCH_MNT/test-925/file29.0 +998b4ba52f2940dc515001e75926b19f SCRATCH_MNT/test-925/file3.0 +6b2648f84c57f58786cf75ac06e37217 SCRATCH_MNT/test-925/file30.0 +c400b872b0fb3fb58920c4e570937a32 SCRATCH_MNT/test-925/file31.0 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-925/file32.0 +cac15c2eeaf1b63614469f675ec71c5f SCRATCH_MNT/test-925/file33.0 +ebd2d819d56725bd1a2a35ababd06cad SCRATCH_MNT/test-925/file34.0 +a26ebf37da9976dfd7c86b4271c59501 SCRATCH_MNT/test-925/file35.0 +11f61aaa1f5f726929c91c6d434edf72 SCRATCH_MNT/test-925/file36.0 +1f73d21c457843ea20048726d461648e SCRATCH_MNT/test-925/file37.0 +9ed53cefd1548008ed1948286e471233 SCRATCH_MNT/test-925/file38.0 +af5195351947da43e7a57f69086aa7d7 SCRATCH_MNT/test-925/file39.0 +c946b71bb69c07daf25470742c967e7c SCRATCH_MNT/test-925/file4.0 +f31ecd4106278b5fb1aeabdedd43036a SCRATCH_MNT/test-925/file40.0 +e8a8d1a0873e25697171ebb87125d794 SCRATCH_MNT/test-925/file41.0 +5920fd86bc7be6a0ef5d7ea283e16307 SCRATCH_MNT/test-925/file42.0 +8360c3c368143821045f9b7994ab8344 SCRATCH_MNT/test-925/file43.0 +6c76a6c9e2b039c82e62d985479f73ee SCRATCH_MNT/test-925/file44.0 +8b5c6cab2f0da5ba2d3b2d3ca205ca75 SCRATCH_MNT/test-925/file45.0 +b4ef05d705b8e99d8824d85e993bf8fa SCRATCH_MNT/test-925/file46.0 +0db1f2d5ad692ccd8941a8bc308cdba2 SCRATCH_MNT/test-925/file47.0 +6a11a8872b36343799a15617bea78cef SCRATCH_MNT/test-925/file48.0 +015ab57c35525eeb776308e14fe2e731 SCRATCH_MNT/test-925/file49.0 +17af09af790a9b4c79cddf72f6b642cb SCRATCH_MNT/test-925/file5.0 +fbc6203955f9c6e9010f831971a073b2 SCRATCH_MNT/test-925/file50.0 +aae01cd767e508bdf2d01f647d10c4b8 SCRATCH_MNT/test-925/file51.0 +4d942a936328991bcd9821072ac0fd9e SCRATCH_MNT/test-925/file52.0 +b77f243bb207746743aeaafbdef4203a SCRATCH_MNT/test-925/file53.0 +9fc7f158bd2ded9df3965ef4fe2fa932 SCRATCH_MNT/test-925/file54.0 +36dff6091853c946411bc40fdae79e84 SCRATCH_MNT/test-925/file55.0 +82a2f6d28f1bff4ce7edc1a7a31b02cb SCRATCH_MNT/test-925/file56.0 +b0d123bf023332bba783abb5b68e4c98 SCRATCH_MNT/test-925/file57.0 +26b49b145b128c0abef0f92b3ccaf1d6 SCRATCH_MNT/test-925/file58.0 +b5ef5d86d6ef15a535ee95b8069d29c9 SCRATCH_MNT/test-925/file59.0 +cd3eccbf2f0126c4141740007ba70c3f SCRATCH_MNT/test-925/file6.0 +205cb48615014f6f2377345b62442609 SCRATCH_MNT/test-925/file60.0 +89691c001b3a3d5473081687ae519a18 SCRATCH_MNT/test-925/file61.0 +a040ce9774652bd00c3cbf493a006e00 SCRATCH_MNT/test-925/file62.0 +970b42855c15ee8caa824cd5e177759a SCRATCH_MNT/test-925/file63.0 +eb74da58c6e4f93b4bf82a62fef4ab93 SCRATCH_MNT/test-925/file7.0 +30c2557e8302a5beb290c71520d87f42 SCRATCH_MNT/test-925/file8.0 +6dc42f5ed1007a3e20d08af71e198cdc SCRATCH_MNT/test-925/file9.0 diff --git a/tests/generic/926 b/tests/generic/926 new file mode 100755 index 0000000..7dedc3f --- /dev/null +++ b/tests/generic/926 @@ -0,0 +1,94 @@ +#! /bin/bash +# FS QA Test No. 926 +# +# Make sure that the reference counting mechanism can handle the case +# where we share the first 1/4 of an extent with a file, share the +# last 1/4 of the extent with a second file, share the first half of +# the extent with N files, and share the second half of the extent +# with a different set of N files. The key point here is to test that +# we handle the case where a refcount extent record doesn't coincide +# exactly with the block mapping records. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 7 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* + wait +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_require_scratch_reflink + +echo "Format and mount" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full 2>&1 + +testdir=$SCRATCH_MNT/test-$seq +mkdir $testdir + +blocks=64 +blksz=65536 +nr=4 +halfway=$((blocks / 2 * blksz)) +quarter=$((blocks / 4 * blksz)) + +echo "Initialize file" +_pwrite_byte 0x61 0 $((blocks * blksz)) $testdir/file >> $seqres.full + +echo "Share the first half of the extent" +seq 1 $nr | while read nr; do + _reflink_range $testdir/file 0 $testdir/file$nr.0 0 $halfway >> $seqres.full +done + +echo "Share the last half of the extent" +seq 1 $nr | while read nr; do + _reflink_range $testdir/file $halfway $testdir/file$nr.1 0 $halfway >> $seqres.full +done + +echo "Share the first quarter of the extent" +_reflink_range $testdir/file 0 $testdir/file.2 0 $quarter >> $seqres.full + +echo "Share the last quarter of the extent" +_reflink_range $testdir/file $((quarter * 3)) $testdir/file.3 0 $quarter >> $seqres.full + +_scratch_cycle_mount + +echo "Check output" +md5sum $testdir/file $testdir/file* | _filter_scratch + +# success, all done +status=0 +exit diff --git a/tests/generic/926.out b/tests/generic/926.out new file mode 100644 index 0000000..d3e6b59 --- /dev/null +++ b/tests/generic/926.out @@ -0,0 +1,20 @@ +QA output created by 926 +Format and mount +Initialize file +Share the first half of the extent +Share the last half of the extent +Share the first quarter of the extent +Share the last quarter of the extent +Check output +bdbcf02ee0aa977795a79d25fcfdccb1 SCRATCH_MNT/test-926/file +bdbcf02ee0aa977795a79d25fcfdccb1 SCRATCH_MNT/test-926/file +7202826a7791073fe2787f0c94603278 SCRATCH_MNT/test-926/file.2 +7202826a7791073fe2787f0c94603278 SCRATCH_MNT/test-926/file.3 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file1.0 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file1.1 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file2.0 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file2.1 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file3.0 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file3.1 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file4.0 +de89461b64701958984c95d1bfb0065a SCRATCH_MNT/test-926/file4.1 diff --git a/tests/generic/group b/tests/generic/group index 6fdf109..2bd40a1 100644 --- a/tests/generic/group +++ b/tests/generic/group @@ -356,3 +356,5 @@ 351 blockdev quick rw 923 auto quick clone 924 auto quick clone +925 auto quick clone +926 auto quick clone From darrick.wong@oracle.com Thu Jun 16 20:47:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E3371851B for ; Thu, 16 Jun 2016 20:47:00 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id A5189304048 for ; Thu, 16 Jun 2016 18:47:00 -0700 (PDT) X-ASG-Debug-ID: 1466128018-04cbb01fee6ab20001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 5vzvBjJbIF6jlHk2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:46:59 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1kvKO026477 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:57 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1kuIQ008154 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:46:56 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1ksDQ014524; Fri, 17 Jun 2016 01:46:55 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:46:54 -0700 Subject: [PATCH 08/20] xfs/122: don't break on old xfsprogs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 08/20] xfs/122: don't break on old xfsprogs To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:52 -0700 Message-ID: <146612801269.25024.6120665241562735488.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128018 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2136 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines If we're running against a old version of xfsprogs that lacks some of the structures that the golden output knows about, copy the structure size definition from the golden output to the program output. This way we can check for structure size mutations on old xfsprogs without generating false error reports for structs that don't exist in the old release. v2: Remove the xfsprogs 2.9.8 compatibility cruft. Signed-off-by: Darrick J. Wong --- tests/xfs/122 | 17 ++++++----------- tests/xfs/122.out | 1 + 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/tests/xfs/122 b/tests/xfs/122 index 845cdd2..330d3ac 100755 --- a/tests/xfs/122 +++ b/tests/xfs/122 @@ -73,6 +73,7 @@ _attribute_filter() cprog=$tmp.get_structs.c oprog=$tmp.get_structs progout=$tmp.output +keyfile=$tmp.keys cat >$cprog <> $seqres.full 2>&1 || \ _notrun "Could not compile test program (see end of $seqres.full)" $oprog | _type_size_filter | _type_name_filter > $progout -# -# add addition sizes and xfs_sb_t fields that don't exist in the version -# being tested. -# +# Find all the items that only exist in the golden output +comm -23 <(grep '=' $0.out | sed -e 's/ =.*$//g' | LC_COLLATE=POSIX sort) \ + <(sed -e 's/ =.*$//g' < $progout | LC_COLLATE=POSIX sort) > $keyfile -# xfsprogs 2.9.8: sb_bad_features2 in pv 978822 -if [ $XFSPROGS_VERSION -lt 20908 ]; then - echo 'offsetof(xfs_sb_t, sb_bad_features2 ) = 204' >>$progout -fi -if [ $XFSPROGS_VERSION -lt 30000 ]; then - echo 'sizeof( xfs_dsb_t ) = 208' >>$progout; -fi +# Copy those items to the program output +grep -F -f $keyfile $0.out >> $progout LC_COLLATE=POSIX sort $progout diff --git a/tests/xfs/122.out b/tests/xfs/122.out index 451871e..46d1dd4 100644 --- a/tests/xfs/122.out +++ b/tests/xfs/122.out @@ -147,3 +147,4 @@ sizeof(xfs_lookup_t) = 4 sizeof(xfs_qoff_logformat_t) = 20 sizeof(xfs_timestamp_t) = 8 sizeof(xfs_trans_header_t) = 16 +sizeof(xfs_zzzz_test_the_test_program) = -47 From darrick.wong@oracle.com Thu Jun 16 20:47:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 03F1984A5 for ; Thu, 16 Jun 2016 20:47:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id BAEB1304048 for ; Thu, 16 Jun 2016 18:47:07 -0700 (PDT) X-ASG-Debug-ID: 1466128026-04cb6c542758690001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id F46jqfEv8DLZ75wh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:06 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1l1IV014428 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:47:02 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1l11b014547 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:01 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1l0m1032299; Fri, 17 Jun 2016 01:47:01 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:00 -0700 Subject: [PATCH 09/20] xfs/122: fix test output to reflect latest xfsprogs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 09/20] xfs/122: fix test output to reflect latest xfsprogs To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:46:58 -0700 Message-ID: <146612801892.25024.8323572138026562066.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128026 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 892 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Since we're getting rid of the rmapxbt, don't test for it. Add back the log inode structure. Signed-off-by: Darrick J. Wong --- tests/xfs/122.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/xfs/122.out b/tests/xfs/122.out index 46d1dd4..ebc4421 100644 --- a/tests/xfs/122.out +++ b/tests/xfs/122.out @@ -75,11 +75,11 @@ sizeof(struct xfs_extent_data) = 24 sizeof(struct xfs_extent_data_info) = 32 sizeof(struct xfs_fs_eofblocks) = 128 sizeof(struct xfs_icreate_log) = 28 +sizeof(struct xfs_log_dinode) = 176 sizeof(struct xfs_refcount_key) = 4 sizeof(struct xfs_refcount_rec) = 12 -sizeof(struct xfs_rmap_key) = 4 +sizeof(struct xfs_rmap_key) = 20 sizeof(struct xfs_rmap_rec) = 24 -sizeof(struct xfs_rmapx_key) = 20 sizeof(xfs_agf_t) = 224 sizeof(xfs_agfl_t) = 36 sizeof(xfs_agi_t) = 336 From darrick.wong@oracle.com Thu Jun 16 20:47:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 211308532 for ; Thu, 16 Jun 2016 20:47:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id D41FA8F804C for ; Thu, 16 Jun 2016 18:47:12 -0700 (PDT) X-ASG-Debug-ID: 1466128030-04bdf01e1096840001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id gqt1huCL5IymRHJ2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:11 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1l9BH026906 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:09 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1l9v9008503 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:09 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1l6Dm014549; Fri, 17 Jun 2016 01:47:08 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:06 -0700 Subject: [PATCH 10/20] xfs/122: list the new log redo items From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 10/20] xfs/122: list the new log redo items To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:05 -0700 Message-ID: <146612802514.25024.7488322050997745494.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128031 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1392 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines List the new log redo items. These should have stable sizes. Signed-off-by: Darrick J. Wong --- tests/xfs/122.out | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/xfs/122.out b/tests/xfs/122.out index ebc4421..c4ed725 100644 --- a/tests/xfs/122.out +++ b/tests/xfs/122.out @@ -60,7 +60,11 @@ sizeof(struct xfs_attr3_leaf_hdr) = 80 sizeof(struct xfs_attr3_leafblock) = 88 sizeof(struct xfs_attr3_rmt_hdr) = 56 sizeof(struct xfs_btree_block) = 72 +sizeof(struct xfs_bud_log_format) = 48 +sizeof(struct xfs_bui_log_format) = 48 sizeof(struct xfs_clone_args) = 32 +sizeof(struct xfs_cud_log_format) = 32 +sizeof(struct xfs_cui_log_format) = 32 sizeof(struct xfs_da3_blkinfo) = 56 sizeof(struct xfs_da3_intnode) = 64 sizeof(struct xfs_da3_node_hdr) = 64 @@ -76,10 +80,14 @@ sizeof(struct xfs_extent_data_info) = 32 sizeof(struct xfs_fs_eofblocks) = 128 sizeof(struct xfs_icreate_log) = 28 sizeof(struct xfs_log_dinode) = 176 +sizeof(struct xfs_map_extent) = 32 +sizeof(struct xfs_phys_extent) = 16 sizeof(struct xfs_refcount_key) = 4 sizeof(struct xfs_refcount_rec) = 12 sizeof(struct xfs_rmap_key) = 20 sizeof(struct xfs_rmap_rec) = 24 +sizeof(struct xfs_rud_log_format) = 48 +sizeof(struct xfs_rui_log_format) = 48 sizeof(xfs_agf_t) = 224 sizeof(xfs_agfl_t) = 36 sizeof(xfs_agi_t) = 336 From darrick.wong@oracle.com Thu Jun 16 20:47:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id DD5F0852D for ; Thu, 16 Jun 2016 20:47:26 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9C37E8F804C for ; Thu, 16 Jun 2016 18:47:26 -0700 (PDT) X-ASG-Debug-ID: 1466128044-04bdf01e1396860001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id etqvKGfOuuKa9Mnr (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1lK8q014766 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:20 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lKeG016917 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:20 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1lJV6004703; Fri, 17 Jun 2016 01:47:19 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:19 -0700 Subject: [PATCH 12/20] xfs/235: fix logic errors when checking rmap usage after failures From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 12/20] xfs/235: fix logic errors when checking rmap usage after failures To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:17 -0700 Message-ID: <146612803789.25024.1998523832682276472.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128045 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1132 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- tests/xfs/235 | 4 ++-- tests/xfs/235.out | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/xfs/235 b/tests/xfs/235 index c388af1..c2e0340 100755 --- a/tests/xfs/235 +++ b/tests/xfs/235 @@ -80,8 +80,8 @@ echo "+ mount image" _scratch_mount echo "+ copy more" -$XFS_IO_PROG -f -c "pwrite -S 0x63 0 $((blksz * 64))" -c "fsync" ${SCRATCH_MNT}/file4 >> $seqres.full -test -s ${SCRATCH_MNT}/file4 || _fail "should not be able to copy with busted rmap btree" +$XFS_IO_PROG -f -c "pwrite -S 0x63 0 $((blksz * 64))" -c "fsync" ${SCRATCH_MNT}/file4 >> $seqres.full 2>&1 +test -s ${SCRATCH_MNT}/file4 && _fail "should not be able to copy with busted rmap btree" umount ${SCRATCH_MNT} echo "+ repair fs" diff --git a/tests/xfs/235.out b/tests/xfs/235.out index 89a11d6..7640224 100644 --- a/tests/xfs/235.out +++ b/tests/xfs/235.out @@ -6,7 +6,6 @@ QA output created by 235 + corrupt image + mount image + copy more -fsync: Structure needs cleaning + repair fs + mount image (2) + chattr -R -i From darrick.wong@oracle.com Thu Jun 16 20:47:30 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id CE1FC853F for ; Thu, 16 Jun 2016 20:47:30 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 914B0304048 for ; Thu, 16 Jun 2016 18:47:30 -0700 (PDT) X-ASG-Debug-ID: 1466128041-04cb6c5424586c0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id z4PMeJFmP1xG08M1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:22 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1lGbL014743 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:16 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lFDt016847 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:16 GMT Received: from abhmp0002.oracle.com (abhmp0002.oracle.com [141.146.116.8]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lDmG014556; Fri, 17 Jun 2016 01:47:14 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:12 -0700 Subject: [PATCH 11/20] xfs: inject errors at various parts of the deferred op completion From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 11/20] xfs: inject errors at various parts of the deferred op completion To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:11 -0700 Message-ID: <146612803133.25024.1931929844195025512.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128042 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 63770 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- common/inject | 93 +++++++++++++++++++++++++++++++++++++++++++++ common/log | 28 ++++++++++++++ common/rc | 8 ++++ tests/xfs/857 | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/857.out | 18 +++++++++ tests/xfs/858 | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/858.out | 18 +++++++++ tests/xfs/859 | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/859.out | 18 +++++++++ tests/xfs/860 | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/860.out | 16 ++++++++ tests/xfs/861 | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/861.out | 16 ++++++++ tests/xfs/862 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/862.out | 16 ++++++++ tests/xfs/863 | 93 +++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/863.out | 15 +++++++ tests/xfs/864 | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/864.out | 19 +++++++++ tests/xfs/865 | 96 +++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/865.out | 18 +++++++++ tests/xfs/866 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/866.out | 17 ++++++++ tests/xfs/867 | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/867.out | 17 ++++++++ tests/xfs/868 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/868.out | 17 ++++++++ tests/xfs/869 | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/869.out | 17 ++++++++ tests/xfs/870 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/870.out | 15 +++++++ tests/xfs/871 | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/871.out | 18 +++++++++ tests/xfs/group | 15 +++++++ 34 files changed, 1883 insertions(+) create mode 100644 common/inject create mode 100755 tests/xfs/857 create mode 100644 tests/xfs/857.out create mode 100755 tests/xfs/858 create mode 100644 tests/xfs/858.out create mode 100755 tests/xfs/859 create mode 100644 tests/xfs/859.out create mode 100755 tests/xfs/860 create mode 100644 tests/xfs/860.out create mode 100755 tests/xfs/861 create mode 100644 tests/xfs/861.out create mode 100755 tests/xfs/862 create mode 100644 tests/xfs/862.out create mode 100755 tests/xfs/863 create mode 100644 tests/xfs/863.out create mode 100755 tests/xfs/864 create mode 100644 tests/xfs/864.out create mode 100755 tests/xfs/865 create mode 100644 tests/xfs/865.out create mode 100755 tests/xfs/866 create mode 100644 tests/xfs/866.out create mode 100755 tests/xfs/867 create mode 100644 tests/xfs/867.out create mode 100755 tests/xfs/868 create mode 100644 tests/xfs/868.out create mode 100755 tests/xfs/869 create mode 100644 tests/xfs/869.out create mode 100755 tests/xfs/870 create mode 100644 tests/xfs/870.out create mode 100755 tests/xfs/871 create mode 100644 tests/xfs/871.out diff --git a/common/inject b/common/inject new file mode 100644 index 0000000..e666d6d --- /dev/null +++ b/common/inject @@ -0,0 +1,93 @@ +##/bin/bash +# Routines for injecting errors into filesystems +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle. All Rights Reserved. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# Contact information: Oracle Corporation, 500 Oracle Parkway, +# Redwood Shores, CA 94065, USA, or: http://www.oracle.com/ +#----------------------------------------------------------------------- +. ./common/log + +# Tests whether $FSTYP is one of the filesystems that supports error injection +_require_error_injection() +{ + case "$FSTYP" in + "xfs") + grep -q 'debug 1' /proc/fs/xfs/stat || \ + _notrun "XFS error injection requires CONFIG_XFS_DEBUG" + ;; + *) + _notrun "Error injection not supported on filesystem type: $FSTYP" + esac +} + +# Requires that xfs_io inject command knows about this error type +_require_xfs_io_error_injection() +{ + type="$1" + _require_error_injection + + # NOTE: We can't actually test error injection here because xfs + # hasn't always range checked the argument to xfs_errortag_add. + # We also don't want to trip an error before we're ready to deal + # with it. + + $XFS_IO_PROG -x -c 'inject' $TEST_DIR | grep -q "$type" || \ + _notrun "XFS error injection $type unknown." +} + +# Inject an error into the test fs +_test_inject_error() +{ + type="$1" + + $XFS_IO_PROG -x -c "inject $type" $TEST_DIR +} + +# Inject an error into the scratch fs +_scratch_inject_error() +{ + type="$1" + + $XFS_IO_PROG -x -c "inject $type" $SCRATCH_MNT +} + +# Unmount and remount the scratch device, dumping the log +_scratch_inject_logprint() +{ + local opts="$1" + + if test -n "$opts"; then + opts="-o $opts" + fi + _scratch_unmount + _scratch_dump_log + _scratch_mount "$opts" +} + +# Unmount and remount the test device, dumping the log +_test_inject_logprint() +{ + local opts="$1" + + if test -n "$opts"; then + opts="-o $opts" + fi + _test_unmount + _test_dump_log + _test_mount "$opts" +} diff --git a/common/log b/common/log index cb687d2..44b9625 100644 --- a/common/log +++ b/common/log @@ -228,6 +228,34 @@ _scratch_f2fs_logstate() echo $? } +_scratch_dump_log() +{ + case "$FSTYP" in + xfs) + _scratch_xfs_logprint + ;; + f2fs) + $DUMP_F2FS_PROG $SCRATCH_DEV + ;; + *) + ;; + esac +} + +_test_dump_log() +{ + case "$FSTYP" in + xfs) + _test_xfs_logprint + ;; + f2fs) + $DUMP_F2FS_PROG $TEST_DEV + ;; + *) + ;; + esac +} + _print_logstate() { case "$FSTYP" in diff --git a/common/rc b/common/rc index 1648a8a..1225047 100644 --- a/common/rc +++ b/common/rc @@ -982,6 +982,14 @@ _scratch_xfs_logprint() $XFS_LOGPRINT_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV } +_test_xfs_logprint() +{ + TEST_OPTIONS="" + [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \ + TEST_OPTIONS="-l$TEST_LOGDEV" + $XFS_LOGPRINT_PROG $TEST_OPTIONS $* $TEST_DEV +} + _scratch_xfs_check() { SCRATCH_OPTIONS="" diff --git a/tests/xfs/857 b/tests/xfs/857 new file mode 100755 index 0000000..7798362 --- /dev/null +++ b/tests/xfs/857 @@ -0,0 +1,102 @@ +#! /bin/bash +# FS QA Test No. 857 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during block remap to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_xfs_io_error_injection "bmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "bmap_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/857.out b/tests/xfs/857.out new file mode 100644 index 0000000..ecc8e04 --- /dev/null +++ b/tests/xfs/857.out @@ -0,0 +1,18 @@ +QA output created by 857 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +1e108771fba35e2f2961d1ad23efbff7 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/858 b/tests/xfs/858 new file mode 100755 index 0000000..fe3ac07 --- /dev/null +++ b/tests/xfs/858 @@ -0,0 +1,102 @@ +#! /bin/bash +# FS QA Test No. 858 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during refcount updates to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_xfs_io_error_injection "refcount_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/858.out b/tests/xfs/858.out new file mode 100644 index 0000000..f5302de --- /dev/null +++ b/tests/xfs/858.out @@ -0,0 +1,18 @@ +QA output created by 858 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/859 b/tests/xfs/859 new file mode 100755 index 0000000..c36cc5b --- /dev/null +++ b/tests/xfs/859 @@ -0,0 +1,106 @@ +#! /bin/bash +# FS QA Test No. 859 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during rmap updates to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +test $is_rmap -gt 0 || _notrun "rmap not supported on scratch fs" + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "rmap_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/859.out b/tests/xfs/859.out new file mode 100644 index 0000000..b83e963 --- /dev/null +++ b/tests/xfs/859.out @@ -0,0 +1,18 @@ +QA output created by 859 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/860 b/tests/xfs/860 new file mode 100755 index 0000000..15716c1 --- /dev/null +++ b/tests/xfs/860 @@ -0,0 +1,99 @@ +#! /bin/bash +# FS QA Test No. 860 +# +# Reflink a file with a few dozen extents and CoW a few blocks. +# Inject an error during extent freeing to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "free_extent" + +rm -f $seqres.full + +blksz=65536 +blks=4 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +$XFS_IO_PROG -c "cowextsize $sz" $SCRATCH_MNT + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_pwrite_byte 0x66 $((sz / 2)) $((sz / 2)) $SCRATCH_MNT/file2 >> $seqres.full +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file2 0 $((sz / 2)) >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz 0 $sz" $SCRATCH_MNT/file1 >> $seqres.full +sync + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/860.out b/tests/xfs/860.out new file mode 100644 index 0000000..0a6d763 --- /dev/null +++ b/tests/xfs/860.out @@ -0,0 +1,16 @@ +QA output created by 860 +Format filesystem +Create files +Check files +cf41e243bf211225660f3fabe6db9eb6 SCRATCH_MNT/file1 +cf41e243bf211225660f3fabe6db9eb6 SCRATCH_MNT/file2 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +fe9070b9c9deb97ed53811efda5c4ad5 SCRATCH_MNT/file1 +cf41e243bf211225660f3fabe6db9eb6 SCRATCH_MNT/file2 +Done diff --git a/tests/xfs/861 b/tests/xfs/861 new file mode 100755 index 0000000..6f716a4 --- /dev/null +++ b/tests/xfs/861 @@ -0,0 +1,100 @@ +#! /bin/bash +# FS QA Test No. 861 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Force XFS into "two refcount updates per transaction" mode. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "refcount_continue_update" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_continue_update" + +echo "CoW all the blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz 0 $((blks * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/861.out b/tests/xfs/861.out new file mode 100644 index 0000000..d353526 --- /dev/null +++ b/tests/xfs/861.out @@ -0,0 +1,16 @@ +QA output created by 861 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW all the blocks +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/862 b/tests/xfs/862 new file mode 100755 index 0000000..167386c --- /dev/null +++ b/tests/xfs/862 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 862 +# +# Simulate rmap update errors with a file write and a file remove. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +test $is_rmap -gt 0 || _notrun "rmap not supported on scratch fs" + +echo "Create files" +touch $SCRATCH_MNT/file1 +_pwrite_byte 0x67 0 $sz $SCRATCH_MNT/file0 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file0 | _filter_scratch +md5sum $SCRATCH_MNT/file1 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "rmap_finish_one" + +echo "Write files" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz 0 $sz" $SCRATCH_MNT/file1 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file0 | _filter_scratch +md5sum $SCRATCH_MNT/file1 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/862.out b/tests/xfs/862.out new file mode 100644 index 0000000..1f6b47b --- /dev/null +++ b/tests/xfs/862.out @@ -0,0 +1,16 @@ +QA output created by 862 +Format filesystem +Create files +Check files +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file0 +d41d8cd98f00b204e9800998ecf8427e SCRATCH_MNT/file1 +Inject error +Write files +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file0 +d41d8cd98f00b204e9800998ecf8427e SCRATCH_MNT/file1 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/863 b/tests/xfs/863 new file mode 100755 index 0000000..5069245 --- /dev/null +++ b/tests/xfs/863 @@ -0,0 +1,93 @@ +#! /bin/bash +# FS QA Test No. 863 +# +# Simulate free extent errors with a file write and a file remove. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +touch $SCRATCH_MNT/file1 + +echo "Write files" +$XFS_IO_PROG -c "pwrite -S 0x67 0 $sz" $SCRATCH_MNT/file1 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 2>&1 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "Remove files" +rm -rf $SCRATCH_MNT/file1 +sync + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 2>&1 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/863.out b/tests/xfs/863.out new file mode 100644 index 0000000..718691f --- /dev/null +++ b/tests/xfs/863.out @@ -0,0 +1,15 @@ +QA output created by 863 +Format filesystem +Create files +Write files +Check files +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file1 +Inject error +Remove files +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +md5sum: SCRATCH_MNT/file1: No such file or directory +FS should be online, touch should succeed +Done diff --git a/tests/xfs/864 b/tests/xfs/864 new file mode 100755 index 0000000..6483639 --- /dev/null +++ b/tests/xfs/864 @@ -0,0 +1,98 @@ +#! /bin/bash +# FS QA Test No. 864 +# +# Reflink a file. +# Inject an error during block remap to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_scratch_reflink +_require_xfs_io_error_injection "bmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_pwrite_byte 0x67 0 $sz $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "bmap_finish_one" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/864.out b/tests/xfs/864.out new file mode 100644 index 0000000..cd16235 --- /dev/null +++ b/tests/xfs/864.out @@ -0,0 +1,19 @@ +QA output created by 864 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/865 b/tests/xfs/865 new file mode 100755 index 0000000..9e2bf05 --- /dev/null +++ b/tests/xfs/865 @@ -0,0 +1,96 @@ +#! /bin/bash +# FS QA Test No. 865 +# +# Reflink a file. +# Inject an error during block remap to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_cp_reflink +_require_xfs_io_error_injection "bmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks - 17)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "bmap_finish_one" + +echo "Try to reflink" +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 2>&1 | _filter_scratch + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/865.out b/tests/xfs/865.out new file mode 100644 index 0000000..9a2b04d --- /dev/null +++ b/tests/xfs/865.out @@ -0,0 +1,18 @@ +QA output created by 865 +Format filesystem +Create files +Check files +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file1 +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file2 +Inject error +Try to reflink +cp: failed to clone 'SCRATCH_MNT/file3' from 'SCRATCH_MNT/file1': Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file1 +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file2 +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/866 b/tests/xfs/866 new file mode 100755 index 0000000..9405325 --- /dev/null +++ b/tests/xfs/866 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 866 +# +# Reflink a file. +# Inject an error during refcount update to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_scratch_reflink +_require_xfs_io_error_injection "refcount_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +$XFS_IO_PROG -f -c "truncate $sz" $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_finish_one" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/866.out b/tests/xfs/866.out new file mode 100644 index 0000000..f2ca58c --- /dev/null +++ b/tests/xfs/866.out @@ -0,0 +1,17 @@ +QA output created by 866 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +b5cfa9d6c8febd618f91ac2843d50a1c SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/867 b/tests/xfs/867 new file mode 100755 index 0000000..5037a88 --- /dev/null +++ b/tests/xfs/867 @@ -0,0 +1,98 @@ +#! /bin/bash +# FS QA Test No. 867 +# +# Reflink a file. +# Inject an error during rmap update to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_scratch_reflink +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +test $is_rmap -gt 0 || _notrun "rmap not supported on scratch fs" + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +$XFS_IO_PROG -f -c "truncate $sz" $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "rmap_finish_one" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/867.out b/tests/xfs/867.out new file mode 100644 index 0000000..78a4e5a --- /dev/null +++ b/tests/xfs/867.out @@ -0,0 +1,17 @@ +QA output created by 867 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +b5cfa9d6c8febd618f91ac2843d50a1c SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/868 b/tests/xfs/868 new file mode 100755 index 0000000..71cf7ee --- /dev/null +++ b/tests/xfs/868 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 868 +# +# Reflink a file. +# Inject an error during extent free to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_scratch_reflink +_require_xfs_io_error_injection "free_extent" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_pwrite_byte 0x67 0 $sz $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/868.out b/tests/xfs/868.out new file mode 100644 index 0000000..583b1f9 --- /dev/null +++ b/tests/xfs/868.out @@ -0,0 +1,17 @@ +QA output created by 868 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/869 b/tests/xfs/869 new file mode 100755 index 0000000..97c803b --- /dev/null +++ b/tests/xfs/869 @@ -0,0 +1,101 @@ +#! /bin/bash +# FS QA Test No. 869 +# +# Reflink a file with a few dozen extents. +# Force XFS into "two refcount updates per transaction" mode. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "refcount_continue_update" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_continue_update" + +echo "Reflink all the blocks" +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file4 + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch +md5sum $SCRATCH_MNT/file4 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/869.out b/tests/xfs/869.out new file mode 100644 index 0000000..1e7822e --- /dev/null +++ b/tests/xfs/869.out @@ -0,0 +1,17 @@ +QA output created by 869 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +Reflink all the blocks +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file4 +Done diff --git a/tests/xfs/870 b/tests/xfs/870 new file mode 100755 index 0000000..fc13f53 --- /dev/null +++ b/tests/xfs/870 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 870 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during extent freeing to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "free_extent" + +rm -f $seqres.full + +blksz=65536 +blks=30 +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $((blksz * blks)) $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full +rm $SCRATCH_MNT/file1 +sync + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/870.out b/tests/xfs/870.out new file mode 100644 index 0000000..49c4e4b --- /dev/null +++ b/tests/xfs/870.out @@ -0,0 +1,15 @@ +QA output created by 870 +Format filesystem +Create files +Check files +d5a0ed0305c8df4180cb2bf975ecffe8 SCRATCH_MNT/file1 +d5a0ed0305c8df4180cb2bf975ecffe8 SCRATCH_MNT/file2 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +7629bd70d19d7291b448221ac44b26d9 SCRATCH_MNT/file2 +Done diff --git a/tests/xfs/871 b/tests/xfs/871 new file mode 100755 index 0000000..69bb637 --- /dev/null +++ b/tests/xfs/871 @@ -0,0 +1,109 @@ +#! /bin/bash +# FS QA Test No. 871 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during refcount updates to test log recovery. Use +# cowextsize so that the refcount failure is somewhere in the CoW remap +# instead of when we're stashing the CoW orphan record. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch +_require_xfs_io_error_injection "refcount_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +$XFS_IO_PROG -c "cowextsize $sz" $SCRATCH_MNT + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +$XFS_IO_PROG -c "pwrite -W -S 0x67 $((10 * blksz)) 1" $SCRATCH_MNT/file2 >> $seqres.full +sync + +echo "Inject error" +_scratch_inject_error "refcount_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/871.out b/tests/xfs/871.out new file mode 100644 index 0000000..c0aba73 --- /dev/null +++ b/tests/xfs/871.out @@ -0,0 +1,18 @@ +QA output created by 871 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +1e108771fba35e2f2961d1ad23efbff7 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/group b/tests/xfs/group index 1ad37ff..0f94794 100644 --- a/tests/xfs/group +++ b/tests/xfs/group @@ -289,3 +289,18 @@ 854 auto quick clone 855 auto clone 856 auto quick clone rmap +857 auto quick clone +858 auto quick clone +859 auto quick clone +860 auto quick clone +861 auto quick clone +862 auto quick rmap +863 auto quick rw +864 auto quick clone +865 auto quick clone +866 auto quick clone +867 auto quick clone +868 auto quick clone +869 auto quick clone +870 auto quick clone +871 auto quick clone From darrick.wong@oracle.com Thu Jun 16 20:47:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B7265853F for ; Thu, 16 Jun 2016 20:47:33 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3F56BAC002 for ; Thu, 16 Jun 2016 18:47:33 -0700 (PDT) X-ASG-Debug-ID: 1466128051-04cb6c5424586d0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id jR75nuuKJ6MZ1lJ0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:31 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1lQEm014819 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:47:26 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1lQNB014932 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:47:26 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1lP2G004723; Fri, 17 Jun 2016 01:47:25 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:25 -0700 Subject: [PATCH 13/20] xfs/229: require 3GB of space From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 13/20] xfs/229: require 3GB of space To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:24 -0700 Message-ID: <146612804411.25024.3885802903047011536.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128051 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 503 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines This test requires 3GB of space, so check for that. Signed-off-by: Darrick J. Wong --- tests/xfs/229 | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/xfs/229 b/tests/xfs/229 index c057677..b8fd914 100755 --- a/tests/xfs/229 +++ b/tests/xfs/229 @@ -50,6 +50,7 @@ trap "_cleanup ; exit \$status" 0 1 2 3 15 _supported_fs xfs _supported_os Linux _require_test +_require_fs_space $TEST_DIR 3200000 TDIR="${TEST_DIR}/t_holes" NFILES="10" From darrick.wong@oracle.com Thu Jun 16 20:47:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BC67B853F for ; Thu, 16 Jun 2016 20:47:40 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 34240AC002 for ; Thu, 16 Jun 2016 18:47:40 -0700 (PDT) X-ASG-Debug-ID: 1466128057-04cbb01fec6abd0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id KRQkCxIiEVY87w7I (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:38 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1lXXT014882 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:33 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lWRF017208 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:32 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lW3R032535; Fri, 17 Jun 2016 01:47:32 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:31 -0700 Subject: [PATCH 14/20] xfs: test clearing reflink inode flag From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 14/20] xfs: test clearing reflink inode flag To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:30 -0700 Message-ID: <146612805032.25024.3244105391915486280.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128058 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4277 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Check that xfs_repair can clear the reflink inode flag. Signed-off-by: Darrick J. Wong --- tests/xfs/872 | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/872.out | 20 +++++++++++ tests/xfs/group | 1 + 3 files changed, 114 insertions(+) create mode 100755 tests/xfs/872 create mode 100644 tests/xfs/872.out diff --git a/tests/xfs/872 b/tests/xfs/872 new file mode 100755 index 0000000..1a13f50 --- /dev/null +++ b/tests/xfs/872 @@ -0,0 +1,93 @@ +#! /bin/bash +# FS QA Test No. 872 +# +# Create 100 reflinked files, CoW them all, and see if xfs_repair will +# clear the reflink flag. There was a buffer handling bug in xfs_repair +# that (fortunately) triggered asserts in the rmap code when clearing +# the reflink flag. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch + +rm -f $seqres.full + +nr=128 # spanning at least one inode chunk tickles a bug in xfs_repair +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 1 $SCRATCH_MNT/file.0 >> $seqres.full +seq 1 $nr | while read i; do + _cp_reflink $SCRATCH_MNT/file.0 $SCRATCH_MNT/file.$i +done +sync + +echo "Check files" +for i in 0 $((nr / 2)) $nr; do + md5sum $SCRATCH_MNT/file.$i | _filter_scratch + $XFS_IO_PROG -c 'lsattr -v' $SCRATCH_MNT/file.$i | _filter_scratch +done + +echo "CoW all files" +seq 1 $nr | while read i; do + echo m >> $SCRATCH_MNT/file.$i +done + +echo "Repair filesystem" +_scratch_unmount +_repair_scratch_fs >> $seqres.full +_scratch_mount + +echo "Check files again" +for i in 0 $((nr / 2)) $nr; do + md5sum $SCRATCH_MNT/file.$i | _filter_scratch + $XFS_IO_PROG -c 'lsattr -v' $SCRATCH_MNT/file.$i | _filter_scratch +done + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/872.out b/tests/xfs/872.out new file mode 100644 index 0000000..316cb0a --- /dev/null +++ b/tests/xfs/872.out @@ -0,0 +1,20 @@ +QA output created by 872 +Format filesystem +Create files +Check files +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.0 +[reflink] SCRATCH_MNT/file.0 +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.64 +[reflink] SCRATCH_MNT/file.64 +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.128 +[reflink] SCRATCH_MNT/file.128 +CoW all files +Repair filesystem +Check files again +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.0 +[] SCRATCH_MNT/file.0 +0f17fd72b7bbf5bda0ff433e6d1fc118 SCRATCH_MNT/file.64 +[] SCRATCH_MNT/file.64 +0f17fd72b7bbf5bda0ff433e6d1fc118 SCRATCH_MNT/file.128 +[] SCRATCH_MNT/file.128 +Done diff --git a/tests/xfs/group b/tests/xfs/group index 0f94794..ca36ad6 100644 --- a/tests/xfs/group +++ b/tests/xfs/group @@ -304,3 +304,4 @@ 869 auto quick clone 870 auto quick clone 871 auto quick clone +872 auto quick clone From darrick.wong@oracle.com Thu Jun 16 20:47:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 7FB328529 for ; Thu, 16 Jun 2016 20:47:51 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 34147304053 for ; Thu, 16 Jun 2016 18:47:51 -0700 (PDT) X-ASG-Debug-ID: 1466128067-04bdf01e1596890001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id aBxBVLDDAYYVgDOp (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:48 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1lfDk014958 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:41 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lfPo009078 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:41 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lc8k014677; Fri, 17 Jun 2016 01:47:40 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:38 -0700 Subject: [PATCH 15/20] xfstests: fix unreferenced variables in generic/186 and generic/187 From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 15/20] xfstests: fix unreferenced variables in generic/186 and generic/187 To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, Christoph Hellwig , fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:36 -0700 Message-ID: <146612805661.25024.577635269102170354.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128068 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1170 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines From: Christoph Hellwig There is not i variable in scope, and the comments suggest the operation is to be done on ${file}. Signed-off-by: Christoph Hellwig --- tests/generic/186 | 2 +- tests/generic/187 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/generic/186 b/tests/generic/186 index 70a0280..5de120a 100755 --- a/tests/generic/186 +++ b/tests/generic/186 @@ -87,7 +87,7 @@ _fragment_freesp() # Try again anyway avail=`_get_available_space $SCRATCH_MNT` - $XFS_IO_PROG -fc "pwrite -S 0x65 0 $avail" ${file}.${i} + $XFS_IO_PROG -fc "pwrite -S 0x65 0 $avail" ${file} # Punch out whatever we need seq 1 $((nr * 4)) | while read f; do diff --git a/tests/generic/187 b/tests/generic/187 index 25cbcd9..3f534c8 100755 --- a/tests/generic/187 +++ b/tests/generic/187 @@ -88,7 +88,7 @@ _fragment_freesp() # Try again anyway avail=`_get_available_space $SCRATCH_MNT` - $XFS_IO_PROG -fc "pwrite -S 0x65 0 $avail" ${file}.${i} + $XFS_IO_PROG -fc "pwrite -S 0x65 0 $avail" ${file} # Punch out whatever we need seq 1 $((nr * 4)) | while read f; do From darrick.wong@oracle.com Thu Jun 16 20:47:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9EF58855B for ; Thu, 16 Jun 2016 20:47:54 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 709B630404E for ; Thu, 16 Jun 2016 18:47:54 -0700 (PDT) X-ASG-Debug-ID: 1466128072-04cb6c542658720001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id nUqfVHDfCQlLWhye (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1lphf027167 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:51 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lphT017550 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:51 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1lomb004839; Fri, 17 Jun 2016 01:47:50 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:50 -0700 Subject: [PATCH 17/20] generic/204: increase log size for rmap/reflink From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 17/20] generic/204: increase log size for rmap/reflink To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:49 -0700 Message-ID: <146612806917.25024.2970222019985115835.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128072 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1017 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines We're going to need a bigger log for rmap & reflink on XFS, so increase the size of the log and the fs appropriately. Signed-off-by: Darrick J. Wong --- tests/generic/204 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/generic/204 b/tests/generic/204 index 42985ab..7b0dc2a 100755 --- a/tests/generic/204 +++ b/tests/generic/204 @@ -55,9 +55,9 @@ _scratch_mkfs 2> /dev/null | _filter_mkfs 2> $tmp.mkfs > /dev/null # versions of mkfs create. All should be valid with a 7MB log, so use that. # And v4/512 v5/1k xfs don't have enough free inodes, set imaxpct=50 at mkfs # time solves this problem. -[ $FSTYP = "xfs" ] && MKFS_OPTIONS="$MKFS_OPTIONS -l size=7m -i maxpct=50" +[ $FSTYP = "xfs" ] && MKFS_OPTIONS="$MKFS_OPTIONS -l size=16m -i maxpct=50" -SIZE=`expr 106 \* 1024 \* 1024` +SIZE=`expr 115 \* 1024 \* 1024` _scratch_mkfs_sized $SIZE $dbsize 2> /dev/null \ | _filter_mkfs 2> $tmp.mkfs > /dev/null _scratch_mount From darrick.wong@oracle.com Thu Jun 16 20:47:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6FE23855C for ; Thu, 16 Jun 2016 20:47:55 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id DE79FAC003 for ; Thu, 16 Jun 2016 18:47:54 -0700 (PDT) X-ASG-Debug-ID: 1466128072-04cb6c542758720001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id ZKRXmB9MxsleB8HG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1llnd015024 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:47:48 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1llqO015255 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:47 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1liuE014733; Fri, 17 Jun 2016 01:47:45 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:44 -0700 Subject: [PATCH 16/20] reflink: test cross-mountpoint reflink and dedupe From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 16/20] reflink: test cross-mountpoint reflink and dedupe To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:42 -0700 Message-ID: <146612806287.25024.6626531953151914169.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128072 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7689 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Test sharing blocks via reflink and dedupe between two different mountpoints of the same filesystem. This shouldn't work, since we don't allow cross-mountpoint functions. Signed-off-by: Darrick J. Wong --- common/reflink | 2 + tests/generic/927 | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/927.out | 9 +++++ tests/generic/928 | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/generic/928.out | 10 ++++++ tests/generic/group | 2 + 6 files changed, 196 insertions(+), 1 deletion(-) create mode 100755 tests/generic/927 create mode 100644 tests/generic/927.out create mode 100755 tests/generic/928 create mode 100644 tests/generic/928.out diff --git a/common/reflink b/common/reflink index 4ec390d..1363971 100644 --- a/common/reflink +++ b/common/reflink @@ -107,7 +107,7 @@ _require_scratch_dedupe() _scratch_mount "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file1" > /dev/null "$XFS_IO_PROG" -f -c "pwrite -S 0x61 0 65536" "$SCRATCH_MNT/file2" > /dev/null - testio="$("$XFS_IO_PROG" -f -c "dedupe $TEST_DIR/file1 0 0 65536" "$TEST_DIR/file2" 2>&1)" + testio="$("$XFS_IO_PROG" -f -c "dedupe $SCRATCH_MNT/file1 0 0 65536" "$SCRATCH_MNT/file2" 2>&1)" echo $testio | grep -q "Operation not supported" && \ _notrun "Dedupe not supported by test filesystem type: $FSTYP" echo $testio | grep -q "Inappropriate ioctl for device" && \ diff --git a/tests/generic/927 b/tests/generic/927 new file mode 100755 index 0000000..e1c30bd --- /dev/null +++ b/tests/generic/927 @@ -0,0 +1,88 @@ +#! /bin/bash +# FS QA Test No. 927 +# +# Check that cross-mountpoint reflink doesn't work. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 7 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* + wait +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_require_scratch_reflink +_require_cp_reflink + +echo "Format and mount" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full 2>&1 + +testdir=$SCRATCH_MNT/test-$seq +mkdir $testdir +otherdir=/tmp/m.$seq +othertestdir=$otherdir/test-$seq +rm -rf $otherdir +mkdir $otherdir + +blocks=1 +blksz=65536 +sz=$((blksz * blocks)) + +echo "Mount otherdir" +SCRATCH_MNT=$otherdir _scratch_mount + +echo "Create file" +_pwrite_byte 0x61 0 $sz $testdir/file >> $seqres.full + +filter_md5() { + _filter_scratch | sed -e "s,$otherdir,OTHER_DIR,g" +} + +echo "Reflink one file to another" +_cp_reflink $testdir/file $othertestdir/otherfiles 2>&1 | filter_md5 + +echo "Check output" +md5sum $testdir/file | _filter_scratch +test -e $othertestdir/otherfile && echo "otherfile should not exist" + +echo "Unmount otherdir" +umount $otherdir +rm -rf $otherdir + +# success, all done +status=0 +exit diff --git a/tests/generic/927.out b/tests/generic/927.out new file mode 100644 index 0000000..3ef3057 --- /dev/null +++ b/tests/generic/927.out @@ -0,0 +1,9 @@ +QA output created by 927 +Format and mount +Mount otherdir +Create file +Reflink one file to another +cp: failed to clone 'OTHER_DIR/test-927/otherfiles' from 'SCRATCH_MNT/test-927/file': Invalid cross-device link +Check output +2d61aa54b58c2e94403fb092c3dbc027 SCRATCH_MNT/test-927/file +Unmount otherdir diff --git a/tests/generic/928 b/tests/generic/928 new file mode 100755 index 0000000..050f34b --- /dev/null +++ b/tests/generic/928 @@ -0,0 +1,86 @@ +#! /bin/bash +# FS QA Test No. 928 +# +# Check that cross-mountpoint dedupe doesn't work. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle, Inc. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- +# + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 7 15 + +_cleanup() +{ + cd / + rm -rf $tmp.* + wait +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_require_scratch_dedupe + +echo "Format and mount" +_scratch_mkfs > $seqres.full 2>&1 +_scratch_mount >> $seqres.full 2>&1 + +testdir=$SCRATCH_MNT/test-$seq +mkdir $testdir +otherdir=/tmp/m.$seq +othertestdir=$otherdir/test-$seq +rm -rf $otherdir +mkdir $otherdir + +blocks=1 +blksz=65536 +sz=$((blocks * blksz)) + +echo "Mount otherdir" +SCRATCH_MNT=$otherdir _scratch_mount + +echo "Create file" +_pwrite_byte 0x61 0 $sz $testdir/file >> $seqres.full +_pwrite_byte 0x61 0 $sz $testdir/otherfile >> $seqres.full + +echo "Dedupe one file to another" +_dedupe_range $testdir/file 0 $othertestdir/otherfile 0 $sz >> $seqres.full + +filter_md5() { + _filter_scratch | sed -e "s,$otherdir,OTHER_DIR,g" +} +echo "Check output" +md5sum $testdir/file $othertestdir/otherfile | filter_md5 + +echo "Unmount otherdir" +umount $otherdir +rm -rf $otherdir + +# success, all done +status=0 +exit diff --git a/tests/generic/928.out b/tests/generic/928.out new file mode 100644 index 0000000..ef35c5b --- /dev/null +++ b/tests/generic/928.out @@ -0,0 +1,10 @@ +QA output created by 928 +Format and mount +Mount otherdir +Create file +Dedupe one file to another +dedupe: Invalid cross-device link +Check output +2d61aa54b58c2e94403fb092c3dbc027 SCRATCH_MNT/test-928/file +2d61aa54b58c2e94403fb092c3dbc027 OTHER_DIR/test-928/otherfile +Unmount otherdir diff --git a/tests/generic/group b/tests/generic/group index 2bd40a1..3286b0f 100644 --- a/tests/generic/group +++ b/tests/generic/group @@ -358,3 +358,5 @@ 924 auto quick clone 925 auto quick clone 926 auto quick clone +927 auto quick clone +928 auto quick clone dedupe From darrick.wong@oracle.com Thu Jun 16 20:48:00 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id BB0A5856D for ; Thu, 16 Jun 2016 20:48:00 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8B65F8F804B for ; Thu, 16 Jun 2016 18:48:00 -0700 (PDT) X-ASG-Debug-ID: 1466128079-04cbb01fee6ac40001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Hxp0kScDTFYnPjmc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:47:59 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1lv5q027189 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:58 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lvXO017626 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:47:57 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1lv2c032573; Fri, 17 Jun 2016 01:47:57 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:47:56 -0700 Subject: [PATCH 18/20] xfs/128: use $XFS_FSR_PROG instead of xfs_fsr directly From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 18/20] xfs/128: use $XFS_FSR_PROG instead of xfs_fsr directly To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:47:55 -0700 Message-ID: <146612807538.25024.6579124315123898764.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128079 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1061 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- tests/xfs/128 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/xfs/128 b/tests/xfs/128 index 68f6f94..8758d7e 100755 --- a/tests/xfs/128 +++ b/tests/xfs/128 @@ -97,10 +97,10 @@ c14=$(_md5_checksum $testdir/file4) echo "Defragment" lsattr -l $testdir/ | _filter_scratch | _filter_spaces -xfs_fsr -v -d $testdir/file1 >> $seqres.full -xfs_fsr -v -d $testdir/file2 >> $seqres.full # fsr probably breaks the link -xfs_fsr -v -d $testdir/file3 >> $seqres.full # fsr probably breaks the link -xfs_fsr -v -d $testdir/file4 >> $seqres.full # fsr probably ignores this file +$XFS_FSR_PROG -v -d $testdir/file1 >> $seqres.full +$XFS_FSR_PROG -v -d $testdir/file2 >> $seqres.full # fsr probably breaks the link +$XFS_FSR_PROG -v -d $testdir/file3 >> $seqres.full # fsr probably breaks the link +$XFS_FSR_PROG -v -d $testdir/file4 >> $seqres.full # fsr probably ignores this file _test_cycle_mount free_blocks3=$(stat -f $testdir -c '%f') From darrick.wong@oracle.com Thu Jun 16 20:48:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 2B630856B for ; Thu, 16 Jun 2016 20:48:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 98306AC002 for ; Thu, 16 Jun 2016 18:48:10 -0700 (PDT) X-ASG-Debug-ID: 1466128088-04cbb01fec6ac60001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 5HHODkqca3lU35vh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:09 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1m4pb015628 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:04 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1m45m009795 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:04 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1m3hx027053; Fri, 17 Jun 2016 01:48:03 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:03 -0700 Subject: [PATCH 19/20] xfs: run xfs_repair at the end of each test From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 19/20] xfs: run xfs_repair at the end of each test To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:01 -0700 Message-ID: <146612808160.25024.5986137574652014794.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128089 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 726 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Run xfs_repair twice at the end of each test -- once to rebuild the btree indices, and again with -n to check the rebuild work. Signed-off-by: Darrick J. Wong --- common/rc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/common/rc b/common/rc index 1225047..847191e 100644 --- a/common/rc +++ b/common/rc @@ -2225,6 +2225,9 @@ _check_xfs_filesystem() ok=0 fi + $XFS_REPAIR_PROG $extra_options $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1 + cat $tmp.repair | _fix_malloc >>$seqres.full + $XFS_REPAIR_PROG -n $extra_options $extra_log_options $extra_rt_options $device >$tmp.repair 2>&1 if [ $? -ne 0 ] then From darrick.wong@oracle.com Thu Jun 16 20:48:15 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 73AA7850B for ; Thu, 16 Jun 2016 20:48:15 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 43F6E8F804B for ; Thu, 16 Jun 2016 18:48:15 -0700 (PDT) X-ASG-Debug-ID: 1466128093-04cb6c542758760001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Y9xjoJnFKEDYn9EL (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:13 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1mBI2027527 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:12 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mBO7022935 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:11 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mAbV032675; Fri, 17 Jun 2016 01:48:11 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:10 -0700 Subject: [PATCH v6 0/6] xfs-docs: reorganize chapters, rmapbt and refcountbt chapter updates From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH v6 0/6] xfs-docs: reorganize chapters, rmapbt and refcountbt chapter updates To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:09 -0700 Message-ID: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128093 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2052 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Hi all, This is the sixth revision of a patchset that updates the xfs documentation for tracking reverse-mappings of physical blocks to file and metadata (rmap); support for mapping multiple file logical blocks to the same physical block (reflink); and implements the beginnings of online metadata scrubbing. Given the significant amount of design assumptions that change with block sharing, rmap and reflink are provided together. There shouldn't be any incompatible on-disk format changes, pending a thorough review of the patches within. This patch set does the following: * Adds a chapter discussing the importance of thoroughly testing new disk format changes with xfstests, and how to find the source code. * Adds in all the disk format changes for Linux 4.5. * Separates the btree sections into a separate chapter about the generic btree structure, and adds a section about the new support for overlapped interval records. * Adds chapters discussing reflink, the reference count btree, and * the reserve-mapping btree. If you're going to start using this mess, you probably ought to just pull from my github trees for kernel[1], xfsprogs[2], and xfstests[3]. There are also updates for xfs-docs[4]. The kernel patches should apply to dchinner's for-next; xfsprogs patches to for-next; and xfstest to master. The kernel git tree already has for-next included. The patches have been xfstested with x64, i386, and armv7l--arm64, ppc64, and ppc64le no longer boot in qemu. All three architectures pass all 'clone' group tests except xfs/128 (which is the swapext test), and AFAICT don't cause any new failures for the 'auto' group. This is an extraordinary way to eat your data. Enjoy! Comments and questions are, as always, welcome. --D [1] https://github.com/djwong/linux/tree/djwong-devel [2] https://github.com/djwong/xfsprogs/tree/djwong-devel [3] https://github.com/djwong/xfstests/tree/djwong-devel [4] https://github.com/djwong/xfs-documentation/tree/djwong-devel From darrick.wong@oracle.com Thu Jun 16 20:48:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 89A88857B for ; Thu, 16 Jun 2016 20:48:19 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4A2DC8F804C for ; Thu, 16 Jun 2016 18:48:19 -0700 (PDT) X-ASG-Debug-ID: 1466128092-04bdf01e10968a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id aRQdEU3uAD5JSzgW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:12 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1mAL2027516 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:11 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mARP022889 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:10 GMT Received: from abhmp0008.oracle.com (abhmp0008.oracle.com [141.146.116.14]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1m9v1005396; Fri, 17 Jun 2016 01:48:09 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:09 -0700 Subject: [PATCH 20/20] xfs: scrub fs (if still mounted) at the end of the test From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 20/20] xfs: scrub fs (if still mounted) at the end of the test To: david@fromorbit.com, darrick.wong@oracle.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:07 -0700 Message-ID: <146612808781.25024.9354886387434772563.stgit@birch.djwong.org> In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128092 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1365 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Teach _check_xfs_filesystem to scrub mounted filesystems before unmounting and fscking them. This is mostly to test the online scrub tool... Signed-off-by: Darrick J. Wong --- common/config | 1 + common/rc | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/common/config b/common/config index cacd815..41edb0c 100644 --- a/common/config +++ b/common/config @@ -163,6 +163,7 @@ export XFS_REPAIR_PROG="`set_prog_path xfs_repair`" export XFS_DB_PROG="`set_prog_path xfs_db`" export XFS_GROWFS_PROG=`set_prog_path xfs_growfs` export XFS_IO_PROG="`set_prog_path xfs_io`" +export XFS_SCRUB_PROG="`set_prog_path xfs_scrub`" export XFS_PARALLEL_REPAIR_PROG="`set_prog_path xfs_prepair`" export XFS_PARALLEL_REPAIR64_PROG="`set_prog_path xfs_prepair64`" export __XFSDUMP_PROG="`set_prog_path xfsdump`" diff --git a/common/rc b/common/rc index 847191e..ea5baea 100644 --- a/common/rc +++ b/common/rc @@ -2188,6 +2188,13 @@ _check_xfs_filesystem() if [ "$type" = "xfs" ] then + if [ -x "$XFS_SCRUB_PROG" ]; then + "$XFS_SCRUB_PROG" $scrubflag -vd $device >>$seqres.full + if [ $? -ne 0 ]; then + echo "filesystem on $device failed scrub (see $seqres.full)" + ok=0 + fi + fi # mounted ... mountpoint=`_umount_or_remount_ro $device` fi From darrick.wong@oracle.com Thu Jun 16 20:48:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A60E48552 for ; Thu, 16 Jun 2016 20:48:27 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3DB67AC004 for ; Thu, 16 Jun 2016 18:48:27 -0700 (PDT) X-ASG-Debug-ID: 1466128101-04bdf01e10968b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id dz2i5jigBwbuyk84 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:22 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1mHhG015706 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:17 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mHng010095 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:17 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1mGof005496; Fri, 17 Jun 2016 01:48:17 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:16 -0700 Subject: [PATCH 1/6] journaling_log: fix some typos in the section about EFDs From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 1/6] journaling_log: fix some typos in the section about EFDs To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:15 -0700 Message-ID: <146612809529.25586.12927884450458378559.stgit@birch.djwong.org> In-Reply-To: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> References: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128102 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1326 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- .../journaling_log.asciidoc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/design/XFS_Filesystem_Structure/journaling_log.asciidoc b/design/XFS_Filesystem_Structure/journaling_log.asciidoc index a67fcc2..67d209f 100644 --- a/design/XFS_Filesystem_Structure/journaling_log.asciidoc +++ b/design/XFS_Filesystem_Structure/journaling_log.asciidoc @@ -368,7 +368,7 @@ typedef struct xfs_efd_log_format { ---- *efd_type*:: -The signature of an EFI operation, 0x1236. This value is in host-endian order, +The signature of an EFD operation, 0x1237. This value is in host-endian order, not big-endian like the rest of XFS. *efd_size*:: @@ -382,9 +382,9 @@ A 64-bit number that binds the corresponding EFI log item to this EFD log item. *efd_extents*:: Variable-length array of extents to be freed. The array length is given by -+efi_nextents+. The record type will be either +xfs_extent_64_t+ or ++efd_nextents+. The record type will be either +xfs_extent_64_t+ or +xfs_extent_32_t+; this can be determined from the log item size (+oh_len+) and -the number of extents (+efi_nextents+). +the number of extents (+efd_nextents+). [[Inode_Log_Item]] === Inode Updates From darrick.wong@oracle.com Thu Jun 16 20:48:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A72468582 for ; Thu, 16 Jun 2016 20:48:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2C644AC003 for ; Thu, 16 Jun 2016 18:48:27 -0700 (PDT) X-ASG-Debug-ID: 1466128104-04cb6c542458770001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Fgpz8Qq0KIvEEH3o (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:25 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1mNeJ015753 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:48:23 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1mN8P016344 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:48:23 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1mMIK005516; Fri, 17 Jun 2016 01:48:23 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:22 -0700 Subject: [PATCH 2/6] xfsdocs: document known testing procedures From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 2/6] xfsdocs: document known testing procedures To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:21 -0700 Message-ID: <146612810138.25586.1436538015885713552.stgit@birch.djwong.org> In-Reply-To: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> References: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128105 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3206 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- design/XFS_Filesystem_Structure/docinfo.xml | 14 ++++++++++++ design/XFS_Filesystem_Structure/testing.asciidoc | 23 ++++++++++++++++++++ .../xfs_filesystem_structure.asciidoc | 2 ++ 3 files changed, 39 insertions(+) create mode 100644 design/XFS_Filesystem_Structure/testing.asciidoc diff --git a/design/XFS_Filesystem_Structure/docinfo.xml b/design/XFS_Filesystem_Structure/docinfo.xml index ba97809..cc5596d 100644 --- a/design/XFS_Filesystem_Structure/docinfo.xml +++ b/design/XFS_Filesystem_Structure/docinfo.xml @@ -108,4 +108,18 @@ + + 3.14 + January 2016 + + Darrick + Wong + + + + + Document disk format change testing. + + + diff --git a/design/XFS_Filesystem_Structure/testing.asciidoc b/design/XFS_Filesystem_Structure/testing.asciidoc new file mode 100644 index 0000000..f1c90bc --- /dev/null +++ b/design/XFS_Filesystem_Structure/testing.asciidoc @@ -0,0 +1,23 @@ +[[Testing]] += Testing Filesystem Changes + +People put a lot of trust in filesystems to preserve their data in a reliable +fashion. To that end, it is very important that users and developers have +access to a suite of regression tests that can be used to prove correct +operation of any given filesystem code, or to analyze failures to fix problems +found in the code. The XFS regression test suite, +xfstests+, is hosted at ++git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git+. Most tests apply to +filesystems in general, but the suite also contains tests for features specific +to each filesystem. + +When fixing bugs, it is important to provide a testcase exposing the bug so +that the developers can avoid a future re-occurrence of the regression. +Furthermore, if you're developing a new user-visible feature for XFS, please +help the rest of the development community to sustain and maintain the whole +codebase by providing generous test coverage to check its behavior. + +When altering, adding, or removing an on-disk data structure, please remember +to update both the in-kernel structure size checks in +xfs_ondisk.h+ and to +ensure that your changes are reflected in xfstest xfs/122. These regression +tests enable us to detect compiler bugs, alignment problems, and anything +else that might result in the creation of incompatible filesystem images. diff --git a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc index 53262bf..f580aab 100644 --- a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc +++ b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc @@ -52,6 +52,8 @@ include::common_types.asciidoc[] include::magic.asciidoc[] +include::testing.asciidoc[] + // return titles to normal :leveloffset: 0 From darrick.wong@oracle.com Thu Jun 16 20:48:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8BA29858E for ; Thu, 16 Jun 2016 20:48:33 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 46289304048 for ; Thu, 16 Jun 2016 18:48:33 -0700 (PDT) X-ASG-Debug-ID: 1466128111-04cbb01fec6acc0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id gVZsOTndCsCFVtrB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:32 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1mUHk027614 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:30 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mTdC023454 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:30 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mTDd027153; Fri, 17 Jun 2016 01:48:29 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:28 -0700 Subject: [PATCH 3/6] xfsdocs: update the on-disk format with changes for Linux 4.5 From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 3/6] xfsdocs: update the on-disk format with changes for Linux 4.5 To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:27 -0700 Message-ID: <146612810746.25586.15997328091238540438.stgit@birch.djwong.org> In-Reply-To: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> References: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128112 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1773 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Signed-off-by: Darrick J. Wong --- .../XFS_Filesystem_Structure/ondisk_inode.asciidoc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc b/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc index 4aabc55..dc1fad2 100644 --- a/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc +++ b/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc @@ -66,9 +66,10 @@ of the literal area and +di_forkoff+. The attribute fork is located between [[Inode_Core]] == Inode Core -The inode's core is 96 bytes in size and contains information about the file -itself including most stat data information about data and attribute forks after -the core within the inode. It uses the following structure: +The inode's core is 96 bytes on a V4 filesystem and 176 bytes on a V5 +filesystem. It contains information about the file itself including most stat +data information about data and attribute forks after the core within the +inode. It uses the following structure: [source, c] ---- @@ -313,8 +314,16 @@ Counts the number of changes made to the attributes in this inode. Log sequence number of the last inode write. *di_flags2*:: -Specifies extended flags associated with a v3 inode. There are no flags defined -currently. +Specifies extended flags associated with a v3 inode. + +.Version 3 Inode flags +[options="header"] +|===== +| Flag | Description +| +XFS_DIFLAG2_DAX+ | +For a file, enable DAX to increase performance on persistent-memory storage. +If set on a directory, files created in the directory will inherit this flag. +|===== *di_pad2*:: Padding for future expansion of the inode. From darrick.wong@oracle.com Thu Jun 16 20:48:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 4DC638507 for ; Thu, 16 Jun 2016 20:48:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 10F998F804B for ; Thu, 16 Jun 2016 18:48:50 -0700 (PDT) X-ASG-Debug-ID: 1466128125-04cb6c5425587a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id dqFaHdVKwSmLVF3a (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:46 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1minm027765 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:44 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mhGC023753 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:44 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mfOi014983; Fri, 17 Jun 2016 01:48:42 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:41 -0700 Subject: [PATCH 5/6] xfsdocs: reverse-mapping btree documentation From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 5/6] xfsdocs: reverse-mapping btree documentation To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:39 -0700 Message-ID: <146612811976.25586.4109341284933778121.stgit@birch.djwong.org> In-Reply-To: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> References: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 8bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128126 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 27064 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC5_SA210e, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.00 BSF_SC5_SA210e Custom Rule SA210e Add chapters on the operation of the reverse mapping btree and future things we could do with rmap data. v2: Add magic number to the table. Signed-off-by: Darrick J. Wong --- .../allocation_groups.asciidoc | 24 +- design/XFS_Filesystem_Structure/docinfo.xml | 17 + .../journaling_log.asciidoc | 130 +++++++++ design/XFS_Filesystem_Structure/magic.asciidoc | 3 .../reconstruction.asciidoc | 53 +++ design/XFS_Filesystem_Structure/rmapbt.asciidoc | 305 ++++++++++++++++++++ .../xfs_filesystem_structure.asciidoc | 4 7 files changed, 528 insertions(+), 8 deletions(-) create mode 100644 design/XFS_Filesystem_Structure/reconstruction.asciidoc create mode 100644 design/XFS_Filesystem_Structure/rmapbt.asciidoc diff --git a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc index 55bbc50..8ced83a 100644 --- a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc +++ b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc @@ -12,6 +12,7 @@ Each AG has the following characteristics: * A super block describing overall filesystem info * Free space management * Inode allocation and tracking + * Reverse block-mapping index (optional) Having multiple AGs allows XFS to handle most operations in parallel without degrading performance as the number of concurrent accesses increases. @@ -379,6 +380,12 @@ it doesn't understand the flag. Free inode B+tree. Each allocation group contains a B+tree to track inode chunks containing free inodes. This is a performance optimization to reduce the time required to allocate inodes. + +| +XFS_SB_FEAT_RO_COMPAT_RMAPBT+ | +Reverse mapping B+tree. Each allocation group contains a B+tree containing +records mapping AG blocks to their owners. See the section about +xref:Reconstruction[reconstruction] for more details. + |===== *sb_features_incompat*:: @@ -529,9 +536,7 @@ struct xfs_agf { __be32 agf_seqno; __be32 agf_length; __be32 agf_roots[XFS_BTNUM_AGF]; - __be32 agf_spare0; __be32 agf_levels[XFS_BTNUM_AGF]; - __be32 agf_spare1; __be32 agf_flfirst; __be32 agf_fllast; __be32 agf_flcount; @@ -550,9 +555,10 @@ struct xfs_agf { }; ---- -The rest of the bytes in the sector are zeroed. +XFS_BTNUM_AGF+ is set to 2: -index 0 for the free space B+tree indexed by block number; and index 1 for the -free space B+tree indexed by extent size. +The rest of the bytes in the sector are zeroed. +XFS_BTNUM_AGF+ is set to 3: +index 0 for the free space B+tree indexed by block number; index 1 for the free +space B+tree indexed by extent size; and index 2 for the reverse-mapping +B+tree. *agf_magicnum*:: Specifies the magic number for the AGF sector: ``XAGF'' (0x58414746). @@ -570,11 +576,13 @@ this could be less than the +sb_agblocks+ value. It is this value that should be used to determine the size of the AG. *agf_roots*:: -Specifies the block number for the root of the two free space B+trees. +Specifies the block number for the root of the two free space B+trees and the +reverse-mapping B+tree, if enabled. *agf_levels*:: -Specifies the level or depth of the two free space B+trees. For a fresh AG, this -will be one, and the ``roots'' will point to a single leaf of level 0. +Specifies the level or depth of the two free space B+trees and the +reverse-mapping B+tree, if enabled. For a fresh AG, this value will be one, +and the ``roots'' will point to a single leaf of level 0. *agf_flfirst*:: Specifies the index of the first ``free list'' block. Free lists are covered in diff --git a/design/XFS_Filesystem_Structure/docinfo.xml b/design/XFS_Filesystem_Structure/docinfo.xml index cc5596d..44f944a 100644 --- a/design/XFS_Filesystem_Structure/docinfo.xml +++ b/design/XFS_Filesystem_Structure/docinfo.xml @@ -122,4 +122,21 @@ + + 3.141 + June 2016 + + Darrick + Wong + + + + + Document the reverse-mapping btree. + Move the b+tree info to a separate chapter. + Discuss overlapping interval b+trees. + Discuss new log items for atomic updates. + + + diff --git a/design/XFS_Filesystem_Structure/journaling_log.asciidoc b/design/XFS_Filesystem_Structure/journaling_log.asciidoc index 67d209f..0fbbcee 100644 --- a/design/XFS_Filesystem_Structure/journaling_log.asciidoc +++ b/design/XFS_Filesystem_Structure/journaling_log.asciidoc @@ -209,6 +209,8 @@ magic number to distinguish themselves. Buffer data items only appear after | +XFS_LI_DQUOT+ | 0x123d | xref:Quota_Update_Log_Item[Update Quota] | +XFS_LI_QUOTAOFF+ | 0x123e | xref:Quota_Off_Log_Item[Quota Off] | +XFS_LI_ICREATE+ | 0x123f | xref:Inode_Create_Log_Item[Inode Creation] +| +XFS_LI_RUI+ | 0x1240 | xref:RUI_Log_Item[Reverse Mapping Update Intent] +| +XFS_LI_RUD+ | 0x1241 | xref:RUD_Log_Item[Reverse Mapping Update Done] |===== [[Log_Transaction_Headers]] @@ -386,6 +388,134 @@ Variable-length array of extents to be freed. The array length is given by +xfs_extent_32_t+; this can be determined from the log item size (+oh_len+) and the number of extents (+efd_nextents+). +[[RUI_Log_Item]] +=== Reverse Mapping Updates Intent + +The next two operation types work together to handle deferred reverse mapping +updates. Naturally, the mappings to be updated can be expressed in terms of +mapping extents: + +[source, c] +---- +struct xfs_map_extent { + __uint64_t me_owner; + __uint64_t me_startblock; + __uint64_t me_startoff; + __uint32_t me_len; + __uint32_t me_flags; +}; +---- + +*me_owner*:: +Owner of this reverse mapping. See the values in the section about +xref:Reverse_Mapping_Btree[reverse mapping] for more information. + +*me_startblock*:: +Filesystem block of this mapping. + +*me_startoff*:: +Logical block offset of this mapping. + +*me_len*:: +The length of this mapping. + +*me_flags*:: +The lower byte of this field is a type code indicating what sort of +reverse mapping operation we want. The upper three bytes are flag bits. + +.Reverse mapping update log intent types +[options="header"] +|===== +| Value | Description +| +XFS_RMAP_EXTENT_MAP+ | Add a reverse mapping for file data. +| +XFS_RMAP_EXTENT_MAP_SHARED+ | Add a reverse mapping for file data for a file with shared blocks. +| +XFS_RMAP_EXTENT_UNMAP+ | Remove a reverse mapping for file data. +| +XFS_RMAP_EXTENT_UNMAP_SHARED+ | Remove a reverse mapping for file data for a file with shared blocks. +| +XFS_RMAP_EXTENT_CONVERT+ | Convert a reverse mapping for file data between unwritten and normal. +| +XFS_RMAP_EXTENT_CONVERT_SHARED+ | Convert a reverse mapping for file data between unwritten and normal for a file with shared blocks. +| +XFS_RMAP_EXTENT_ALLOC+ | Add a reverse mapping for non-file data. +| +XFS_RMAP_EXTENT_FREE+ | Remove a reverse mapping for non-file data. +|===== + +.Reverse mapping update log intent flags +[options="header"] +|===== +| Value | Description +| +XFS_RMAP_EXTENT_ATTR_FORK+ | Extent is for the attribute fork. +| +XFS_RMAP_EXTENT_BMBT_BLOCK+ | Extent is for a block mapping btree block. +| +XFS_RMAP_EXTENT_UNWRITTEN+ | Extent is unwritten. +|===== + +The ``rmap update intent'' operation comes first; it tells the log that XFS +wants to update some reverse mappings. This record is crucial for correct log +recovery because it enables us to spread a complex metadata update across +multiple transactions while ensuring that a crash midway through the complex +update will be replayed fully during log recovery. + +[source, c] +---- +struct xfs_rui_log_format { + __uint16_t rui_type; + __uint16_t rui_size; + __uint32_t rui_nextents; + __uint64_t rui_id; + struct xfs_map_extent rui_extents[1]; +}; +---- + +*rui_type*:: +The signature of an RUI operation, 0x1240. This value is in host-endian order, +not big-endian like the rest of XFS. + +*rui_size*:: +Size of this log item. Should be 1. + +*rui_nextents*:: +Number of reverse mappings. + +*rui_id*:: +A 64-bit number that binds the corresponding RUD log item to this RUI log item. + +*rui_extents*:: +Variable-length array of reverse mappings to update. + +[[RUD_Log_Item]] +=== Completion of Reverse Mapping Updates + +The ``reverse mapping update done'' operation complements the ``reverse mapping +update intent'' operation. This second operation indicates that the update +actually happened, so that log recovery needn't replay the update. The RUD and +the actual updates are typically found in a new transaction following the +transaction in which the RUI was logged. + +[source, c] +---- +struct xfs_rud_log_format { + __uint16_t rud_type; + __uint16_t rud_size; + __uint32_t rud_nextents; + __uint64_t rud_rui_id; + struct xfs_map_extent rud_extents[1]; +}; +---- + +*rud_type*:: +The signature of an RUD operation, 0x1241. This value is in host-endian order, +not big-endian like the rest of XFS. + +*rud_size*:: +Size of this log item. Should be 1. + +*rud_nextents*:: +Number of reverse mappings. + +*rud_id*:: +A 64-bit number that binds the corresponding RUI log item to this RUD log item. + +*rud_extents*:: +Variable-length array of reverse mappings. The array length is given by ++rud_nextents+. + [[Inode_Log_Item]] === Inode Updates diff --git a/design/XFS_Filesystem_Structure/magic.asciidoc b/design/XFS_Filesystem_Structure/magic.asciidoc index 301cfa0..10fd15f 100644 --- a/design/XFS_Filesystem_Structure/magic.asciidoc +++ b/design/XFS_Filesystem_Structure/magic.asciidoc @@ -44,6 +44,7 @@ relevant chapters. Magic numbers tend to have consistent locations: | +XFS_ATTR_LEAF_MAGIC+ | 0xfbee | | xref:Leaf_Attributes[Leaf Attribute] | +XFS_ATTR3_LEAF_MAGIC+ | 0x3bee | | xref:Leaf_Attributes[Leaf Attribute], v5 only | +XFS_ATTR3_RMT_MAGIC+ | 0x5841524d | XARM | xref:Remote_Values[Remote Attribute Value], v5 only +| +XFS_RMAP_CRC_MAGIC+ | 0x524d4233 | RMB3 | xref:Reverse_Mapping_Btree[Reverse Mapping B+tree], v5 only |===== The magic numbers for log items are at offset zero in each log item, but items @@ -61,6 +62,8 @@ are not aligned to blocks. | +XFS_LI_DQUOT+ | 0x123d | | xref:Quota_Update_Log_Item[Update Quota Log Item] | +XFS_LI_QUOTAOFF+ | 0x123e | | xref:Quota_Off_Log_Item[Quota Off Log Item] | +XFS_LI_ICREATE+ | 0x123f | | xref:Inode_Create_Log_Item[Inode Creation Log Item] +| +XFS_LI_RUI+ | 0x1240 | | xref:RUI_Log_Item[Reverse Mapping Update Intent] +| +XFS_LI_RUD+ | 0x1241 | | xref:RUD_Log_Item[Reverse Mapping Update Done] |===== = Theoretical Limits diff --git a/design/XFS_Filesystem_Structure/reconstruction.asciidoc b/design/XFS_Filesystem_Structure/reconstruction.asciidoc new file mode 100644 index 0000000..f172e0f --- /dev/null +++ b/design/XFS_Filesystem_Structure/reconstruction.asciidoc @@ -0,0 +1,53 @@ +[[Reconstruction]] += Metadata Reconstruction + +[NOTE] +This is a theoretical discussion of how reconstruction could work; none of this +is implemented as of 2015. + +A simple UNIX filesystem can be thought of in terms of a directed acyclic graph. +To a first approximation, there exists a root directory node, which points to +other nodes. Those other nodes can themselves be directories or they can be +files. Each file, in turn, points to data blocks. + +XFS adds a few more details to this picture: + +* The real root(s) of an XFS filesystem are the allocation group headers +(superblock, AGF, AGI, AGFL). +* Each allocation group’s headers point to various per-AG B+trees (free space, +inode, free inodes, free list, etc.) +* The free space B+trees point to unused extents; +* The inode B+trees point to blocks containing inode chunks; +* All superblocks point to the root directory and the log; +* Hardlinks mean that multiple directories can point to a single file node; +* File data block pointers are indexed by file offset; +* Files and directories can have a second collection of pointers to data blocks +which contain extended attributes; +* Large directories require multiple data blocks to store all the subpointers; +* Still larger directories use high-offset data blocks to store a B+tree of +hashes to directory entries; +* Large extended attribute forks similarly use high-offset data blocks to store +a B+tree of hashes to attribute keys; and +* Symbolic links can point to data blocks. + +The beauty of this massive graph structure is that under normal circumstances, +everything known to the filesystem is discoverable (access controls +notwithstanding) from the root. The major weakness of this structure of course +is that breaking a edge in the graph can render entire subtrees inaccessible. ++xfs_repair+ “recovers” from broken directories by scanning for unlinked inodes +and connecting them to +/lost+found+, but this isn’t sufficiently general to +recover from breaks in other parts of the graph structure. Wouldn’t it be +useful to have back pointers as a secondary data structure? The current repair +strategy is to reconstruct whatever can be rebuilt, but to scrap anything that +doesn't check out. + +The xref:Reverse_Mapping_Btree[reverse-mapping B+tree] fills in part of the +puzzle. Since it contains copies of every entry in each inode’s data and +attribute forks, we can fix a corrupted block map with these records. +Furthermore, if the inode B+trees become corrupt, it is possible to visit all +inode chunks using the reverse-mapping data. Should XFS ever gain the ability +to store parent directory information in each inode, it also becomes possible +to resurrect damaged directory trees, which should reduce the complaints about +inodes ending up in +/lost+found+. Everything else in the per-AG primary +metadata can already be reconstructed via +xfs_repair+. Hopefully, +reconstruction will not turn out to be a fool's errand. diff --git a/design/XFS_Filesystem_Structure/rmapbt.asciidoc b/design/XFS_Filesystem_Structure/rmapbt.asciidoc new file mode 100644 index 0000000..a8a210b --- /dev/null +++ b/design/XFS_Filesystem_Structure/rmapbt.asciidoc @@ -0,0 +1,305 @@ +[[Reverse_Mapping_Btree]] +== Reverse-Mapping B+tree + +[NOTE] +This data structure is under construction! Details may change. + +If the feature is enabled, each allocation group has its own reverse +block-mapping B+tree, which grows in the free space like the free space +B+trees. As mentioned in the chapter about +xref:Reconstruction[reconstruction], this data structure is another piece of +the puzzle necessary to reconstruct the data or attribute fork of a file from +reverse-mapping records; we can also use it to double-check allocations to +ensure that we are not accidentally cross-linking blocks, which can cause +severe damage to the filesystem. + +This B+tree is only present if the +XFS_SB_FEAT_RO_COMPAT_RMAPBT+ +feature is enabled. The feature requires a version 5 filesystem. + +Each record in the reverse-mapping B+tree has the following structure: + +[source, c] +---- +struct xfs_rmap_rec { + __be32 rm_startblock; + __be32 rm_blockcount; + __be64 rm_owner; + __be64 rm_fork:1; + __be64 rm_bmbt:1; + __be64 rm_unwritten:1; + __be64 rm_unused:7; + __be64 rm_offset:54; +}; +---- + +*rm_startblock*:: +AG block number of this record. + +*rm_blockcount*:: +The length of this extent. + +*rm_owner*:: +A 64-bit number describing the owner of this extent. This is typically the +absolute inode number, but can also correspond to one of the following: + +.Special owner values +[options="header"] +|===== +| Value | Description +| +XFS_RMAP_OWN_NULL+ | No owner. This should never appear on disk. +| +XFS_RMAP_OWN_UNKNOWN+ | Unknown owner; for EFI recovery. This should never appear on disk. +| +XFS_RMAP_OWN_FS+ | Allocation group headers +| +XFS_RMAP_OWN_LOG+ | XFS log blocks +| +XFS_RMAP_OWN_AG+ | Per-allocation group B+tree blocks. This means free space B+tree blocks, blocks on the freelist, and reverse-mapping B+tree blocks. +| +XFS_RMAP_OWN_INOBT+ | Per-allocation group inode B+tree blocks. This includes free inode B+tree blocks. +| +XFS_RMAP_OWN_INODES+ | Inode chunks +|===== + +*rm_fork*:: +If +rm_owner+ describes an inode, this can be 1 if this record is for an +attribute fork. + +*rm_bmbt*:: +If +rm_owner+ describes an inode, this can be 1 to signify that this record is +for a block map B+tree block. In this case, +rm_offset+ has no meaning. + +*rm_unwritten*:: +A flag indicating that the extent is unwritten. This corresponds to the flag in +the xref:Data_Extents[extent record] format which means +XFS_EXT_UNWRITTEN+. + +*rm_offset*:: +The 54-bit logical file block offset, if +rm_owner+ describes an inode. +Meaningless otherwise. + +[NOTE] +The single-bit flag values +rm_unwritten+, +rm_fork+, and +rm_bmbt+ are packed +into the larger fields in the C structure definition. + +The key has the following structure: + +[source, c] +---- +struct xfs_rmap_key { + __be32 rm_startblock; + __be64 rm_owner; + __be64 rm_fork:1; + __be64 rm_bmbt:1; + __be64 rm_reserved:1; + __be64 rm_unused:7; + __be64 rm_offset:54; +}; +---- + +For the reverse-mapping B+tree on a filesystem that supports sharing of file +data blocks, the key definition is larger than the usual AG block number. On a +classic XFS filesystem, each block has only one owner, which means that ++rm_startblock+ is sufficient to uniquely identify each record. However, +shared block support (reflink) on XFS breaks that assumption; now filesystem +blocks can be linked to any logical block offset of any file inode. Therefore, +the key must include the owner and offset information to preserve the 1 to 1 +relation between key and record. + +* As the reference counting is AG relative, all the block numbers are only +32-bits. +* The +bb_magic+ value is "RMB3" (0x524d4233). +* The +xfs_btree_sblock_t+ header is used for intermediate B+tree node as well +as the leaves. +* Each pointer is associated with two keys. The first of these is the "low +key", which is the key of the smallest record accessible through the pointer. +This low key has the same meaning as the key in all other btrees. The second +key is the high key, which is the maximum of the largest key that can be used +to access a given record underneath the pointer. Recall that each record +in the reverse mapping b+tree describes an interval of physical blocks mapped +to an interval of logical file block offsets; therefore, it makes sense that +a range of keys can be used to find to a record. + +=== xfs_db rmapbt Example + +This example shows a reverse-mapping B+tree from a freshly populated root +filesystem: + +---- +xfs_db> agf 0 +xfs_db> addr rmaproot +xfs_db> p +magic = 0x524d4233 +level = 1 +numrecs = 43 +leftsib = null +rightsib = null +bno = 56 +lsn = 0x3000004c8 +uuid = 1977221d-8345-464e-b1f4-aa2ea36895f4 +owner = 0 +crc = 0x7cf8be6f (correct) +keys[1-43] = [startblock,owner,offset] +keys[1-43] = [startblock,owner,offset,attrfork,bmbtblock,startblock_hi,owner_hi, + offset_hi,attrfork_hi,bmbtblock_hi] + 1:[0,-3,0,0,0,351,4418,66,0,0] + 2:[417,285,0,0,0,827,4419,2,0,0] + 3:[829,499,0,0,0,2352,573,55,0,0] + 4:[1292,710,0,0,0,32168,262923,47,0,0] + 5:[32215,-5,0,0,0,34655,2365,3411,0,0] + 6:[34083,1161,0,0,0,34895,265220,1,0,1] + 7:[34896,256191,0,0,0,36522,-9,0,0,0] + ... + 41:[50998,326734,0,0,0,51430,-5,0,0,0] + 42:[51431,327010,0,0,0,51600,325722,11,0,0] + 43:[51611,327112,0,0,0,94063,23522,28375272,0,0] +ptrs[1-43] = 1:5 2:6 3:8 4:9 5:10 6:11 7:418 ... 41:46377 42:48784 43:49522 +---- + +We arbitrarily pick pointer 17 to traverse downwards: + +---- +xfs_db> addr ptrs[17] +xfs_db> p +magic = 0x524d4233 +level = 0 +numrecs = 168 +leftsib = 36284 +rightsib = 37617 +bno = 294760 +lsn = 0x200002761 +uuid = 1977221d-8345-464e-b1f4-aa2ea36895f4 +owner = 0 +crc = 0x2dad3fbe (correct) +recs[1-168] = [startblock,blockcount,owner,offset,extentflag,attrfork,bmbtblock] + 1:[40326,1,259615,0,0,0,0] 2:[40327,1,-5,0,0,0,0] + 3:[40328,2,259618,0,0,0,0] 4:[40330,1,259619,0,0,0,0] + ... + 127:[40540,1,324266,0,0,0,0] 128:[40541,1,324266,8388608,0,0,0] + 129:[40542,2,324266,1,0,0,0] 130:[40544,32,-7,0,0,0,0] +---- + +Several interesting things pop out here. The first record shows that inode +259,615 has mapped AG block 40,326 at offset 0. We confirm this by looking at +the block map for that inode: + +---- +xfs_db> inode 259615 +xfs_db> bmap +data offset 0 startblock 40326 (0/40326) count 1 flag 0 +---- + +Next, notice records 127 and 128, which describe neighboring AG blocks that are +mapped to non-contiguous logical blocks in inode 324,266. Given the logical +offset of 8,388,608 we surmise that this is a leaf directory, but let us +confirm: + +---- +xfs_db> inode 324266 +xfs_db> p core.mode +core.mode = 040755 +xfs_db> bmap +data offset 0 startblock 40540 (0/40540) count 1 flag 0 +data offset 1 startblock 40542 (0/40542) count 2 flag 0 +data offset 3 startblock 40576 (0/40576) count 1 flag 0 +data offset 8388608 startblock 40541 (0/40541) count 1 flag 0 +xfs_db> p core.mode +core.mode = 0100644 +xfs_db> dblock 0 +xfs_db> p dhdr.hdr.magic +dhdr.hdr.magic = 0x58444433 +xfs_db> dblock 8388608 +xfs_db> p lhdr.info.hdr.magic +lhdr.info.hdr.magic = 0x3df1 +---- + +Indeed, this inode 324,266 appears to be a leaf directory, as it has regular +directory data blocks at low offsets, and a single leaf block. + +Notice further the two reverse-mapping records with negative owners. An owner +of -7 corresponds to +XFS_RMAP_OWN_INODES+, which is an inode chunk, and an +owner code of -5 corresponds to +XFS_RMAP_OWN_AG+, which covers free space +B+trees and free space. Let's see if block 40,544 is part of an inode chunk: + +---- +xfs_db> blockget +xfs_db> fsblock 40544 +xfs_db> blockuse +block 40544 (0/40544) type inode +xfs_db> stack +1: + byte offset 166068224, length 4096 + buffer block 324352 (fsbno 40544), 8 bbs + inode 324266, dir inode 324266, type data +xfs_db> type inode +xfs_db> p +core.magic = 0x494e +---- + +Our suspicions are confirmed. Let's also see if 40,327 is part of a free space +tree: + +---- +xfs_db> fsblock 40327 +xfs_db> blockuse +block 40327 (0/40327) type btrmap +xfs_db> type rmapbt +xfs_db> p +magic = 0x524d4233 +---- + +As you can see, the reverse block-mapping B+tree is an important secondary +metadata structure, which can be used to reconstruct damaged primary metadata. +Now let's look at an extend rmap btree: + +---- +xfs_db> agf 0 +xfs_db> addr rmaproot +xfs_db> p +magic = 0x34524d42 +level = 1 +numrecs = 5 +leftsib = null +rightsib = null +bno = 6368 +lsn = 0x100000d1b +uuid = 400f0928-6b88-4c37-af1e-cef1f8911f3f +owner = 0 +crc = 0x8d4ace05 (correct) +keys[1-5] = [startblock,owner,offset,attrfork,bmbtblock,startblock_hi,owner_hi,offset_hi,attrfork_hi,bmbtblock_hi] +1:[0,-3,0,0,0,705,132,681,0,0] +2:[24,5761,0,0,0,548,5761,524,0,0] +3:[24,5929,0,0,0,380,5929,356,0,0] +4:[24,6097,0,0,0,212,6097,188,0,0] +5:[24,6277,0,0,0,807,-7,0,0,0] +ptrs[1-5] = 1:5 2:771 3:9 4:10 5:11 +---- + +The second pointer stores both the low key [24,5761,0,0,0] and the high key +[548,5761,524,0,0], which means that we can expect block 771 to contain records +starting at physical block 24, inode 5761, offset zero; and that one of the +records can be used to find a reverse mapping for physical block 548, inode +5761, and offset 524: + +---- +xfs_db> addr ptrs[2] +xfs_db> p +magic = 0x34524d42 +level = 0 +numrecs = 168 +leftsib = 5 +rightsib = 9 +bno = 6168 +lsn = 0x100000d1b +uuid = 400f0928-6b88-4c37-af1e-cef1f8911f3f +owner = 0 +crc = 0xd58eff0e (correct) +recs[1-168] = [startblock,blockcount,owner,offset,extentflag,attrfork,bmbtblock] +1:[24,525,5761,0,0,0,0] +2:[24,524,5762,0,0,0,0] +3:[24,523,5763,0,0,0,0] +... +166:[24,360,5926,0,0,0,0] +167:[24,359,5927,0,0,0,0] +168:[24,358,5928,0,0,0,0] +---- + +Observe that the first record in the block starts at physical block 24, inode +5761, offset zero, just as we expected. Note that this first record is also +indexed by the highest key as provided in the node block; physical block 548, +inode 5761, offset 524 is the very last block mapped by this record. Furthermore, +note that record 168, despite being the last record in this block, has a lower +maximum key (physical block 382, inode 5928, offset 23) than the first record. diff --git a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc index 62502b3..1b8658d 100644 --- a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc +++ b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc @@ -48,6 +48,8 @@ include::overview.asciidoc[] include::metadata_integrity.asciidoc[] +include::reconstruction.asciidoc[] + include::common_types.asciidoc[] include::magic.asciidoc[] @@ -66,6 +68,8 @@ include::btrees.asciidoc[] include::allocation_groups.asciidoc[] +include::rmapbt.asciidoc[] + include::journaling_log.asciidoc[] include::internal_inodes.asciidoc[] From darrick.wong@oracle.com Thu Jun 16 20:48:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 29A2F859E for ; Thu, 16 Jun 2016 20:48:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id DDF7D304059 for ; Thu, 16 Jun 2016 18:48:54 -0700 (PDT) X-ASG-Debug-ID: 1466128131-04cbb01fef6ad10001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id eWxw3WMJjYFPIgbb (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:51 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1mmF1015879 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 01:48:49 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5H1mm0s016846 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:48 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mlb2000395; Fri, 17 Jun 2016 01:48:48 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:47 -0700 Subject: [PATCH 6/6] xfsdocs: document refcount btree and reflink From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 6/6] xfsdocs: document refcount btree and reflink To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:46 -0700 Message-ID: <146612812605.25586.14230585950316760238.stgit@birch.djwong.org> In-Reply-To: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> References: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466128131 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 26803 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Document the reference count btree and talk a little bit about how the reflink feature uses it. Signed-off-by: Darrick J. Wong --- .../allocation_groups.asciidoc | 20 ++ .../XFS_Filesystem_Structure/directories.asciidoc | 1 design/XFS_Filesystem_Structure/docinfo.xml | 2 .../journaling_log.asciidoc | 207 ++++++++++++++++++++ design/XFS_Filesystem_Structure/magic.asciidoc | 5 .../XFS_Filesystem_Structure/ondisk_inode.asciidoc | 25 ++ .../XFS_Filesystem_Structure/refcountbt.asciidoc | 145 ++++++++++++++ design/XFS_Filesystem_Structure/reflink.asciidoc | 40 ++++ design/XFS_Filesystem_Structure/rmapbt.asciidoc | 2 .../xfs_filesystem_structure.asciidoc | 4 10 files changed, 446 insertions(+), 5 deletions(-) create mode 100644 design/XFS_Filesystem_Structure/refcountbt.asciidoc create mode 100644 design/XFS_Filesystem_Structure/reflink.asciidoc diff --git a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc index 8ced83a..ece7f8b 100644 --- a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc +++ b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc @@ -13,6 +13,7 @@ Each AG has the following characteristics: * Free space management * Inode allocation and tracking * Reverse block-mapping index (optional) + * Data block reference count index (optional) Having multiple AGs allows XFS to handle most operations in parallel without degrading performance as the number of concurrent accesses increases. @@ -386,6 +387,12 @@ Reverse mapping B+tree. Each allocation group contains a B+tree containing records mapping AG blocks to their owners. See the section about xref:Reconstruction[reconstruction] for more details. +| +XFS_SB_FEAT_RO_COMPAT_REFLINK+ | +Reference count B+tree. Each allocation group contains a B+tree to track the +reference counts of AG blocks. This enables files to share data blocks safely. +See the section about xref:Reflink_Deduplication[reflink and deduplication] for +more details. + |===== *sb_features_incompat*:: @@ -546,7 +553,9 @@ struct xfs_agf { /* version 5 filesystem fields start here */ uuid_t agf_uuid; - __be64 agf_spare64[16]; + __be32 agf_refcount_root; + __be32 agf_refcount_level; + __be64 agf_spare64[15]; /* unlogged fields, written during buffer writeback. */ __be64 agf_lsn; @@ -608,6 +617,12 @@ used if the +XFS_SB_VERSION2_LAZYSBCOUNTBIT+ bit is set in +sb_features2+. The UUID of this block, which must match either +sb_uuid+ or +sb_meta_uuid+ depending on which features are set. +*agf_refcount_root*:: +Block number for the root of the reference count B+tree, if enabled. + +*agf_refcount_root*:: +Depth of the reference count B+tree, if enabled. + *agf_spare64*:: Empty space in the logged part of the AGF sector, for use for future features. @@ -1238,4 +1253,5 @@ By placing the real time device (and the journal) on separate high-performance storage devices, it is possible to reduce most of the unpredictability in I/O response times that come from metadata operations. -None of the XFS per-AG B+trees are involved with real time files. +None of the XFS per-AG B+trees are involved with real time files. It is not +possible for real time files to share data blocks. diff --git a/design/XFS_Filesystem_Structure/directories.asciidoc b/design/XFS_Filesystem_Structure/directories.asciidoc index bccf912..1758c4e 100644 --- a/design/XFS_Filesystem_Structure/directories.asciidoc +++ b/design/XFS_Filesystem_Structure/directories.asciidoc @@ -1419,6 +1419,7 @@ The hash value of a particular record. The directory/attribute logical block containing all entries up to the corresponding hash value. +// * The freeindex's +bests+ array starts from the end of the block and grows to the start of the block. diff --git a/design/XFS_Filesystem_Structure/docinfo.xml b/design/XFS_Filesystem_Structure/docinfo.xml index 44f944a..f5e62bc 100644 --- a/design/XFS_Filesystem_Structure/docinfo.xml +++ b/design/XFS_Filesystem_Structure/docinfo.xml @@ -136,6 +136,8 @@ Move the b+tree info to a separate chapter. Discuss overlapping interval b+trees. Discuss new log items for atomic updates. + Document the reference-count btree. + Discuss block sharing, reflink, & deduplication. diff --git a/design/XFS_Filesystem_Structure/journaling_log.asciidoc b/design/XFS_Filesystem_Structure/journaling_log.asciidoc index 0fbbcee..e772a84 100644 --- a/design/XFS_Filesystem_Structure/journaling_log.asciidoc +++ b/design/XFS_Filesystem_Structure/journaling_log.asciidoc @@ -211,6 +211,10 @@ magic number to distinguish themselves. Buffer data items only appear after | +XFS_LI_ICREATE+ | 0x123f | xref:Inode_Create_Log_Item[Inode Creation] | +XFS_LI_RUI+ | 0x1240 | xref:RUI_Log_Item[Reverse Mapping Update Intent] | +XFS_LI_RUD+ | 0x1241 | xref:RUD_Log_Item[Reverse Mapping Update Done] +| +XFS_LI_CUI+ | 0x1242 | xref:CUI_Log_Item[Reference Count Update Intent] +| +XFS_LI_CUD+ | 0x1243 | xref:CUD_Log_Item[Reference Count Update Done] +| +XFS_LI_BUI+ | 0x1244 | xref:BUI_Log_Item[File Block Mapping Update Intent] +| +XFS_LI_BUD+ | 0x1245 | xref:BUD_Log_Item[File Block Mapping Update Done] |===== [[Log_Transaction_Headers]] @@ -516,6 +520,209 @@ A 64-bit number that binds the corresponding RUI log item to this RUD log item. Variable-length array of reverse mappings. The array length is given by +rud_nextents+. +[[CUI_Log_Item]] +=== Reference Count Updates Intent + +The next two operation types work together to handle reference count updates. +Naturally, the ranges of extents having reference count updates can be +expressed in terms of physical extents: + +[source, c] +---- +struct xfs_phys_extent { + __uint64_t pe_startblock; + __uint32_t pe_len; + __uint32_t pe_flags; +}; +---- + +*pe_startblock*:: +Filesystem block of this extent. + +*pe_len*:: +The length of this extent. + +*pe_flags*:: +The lower byte of this field is a type code indicating what sort of +reverse mapping operation we want. The upper three bytes are flag bits. + +.Reference count update log intent types +[options="header"] +|===== +| Value | Description +| +XFS_REFCOUNT_EXTENT_INCREASE+ | Increase the reference count for this extent. +| +XFS_REFCOUNT_EXTENT_DECREASE+ | Decrease the reference count for this extent. +| +XFS_REFCOUNT_EXTENT_ALLOC_COW+ | Reserve an extent for staging copy on write. +| +XFS_REFCOUNT_EXTENT_FREE_COW+ | Unreserve an extent for staging copy on write. +|===== + +The ``reference count update intent'' operation comes first; it tells the log +that XFS wants to update some reference counts. This record is crucial for +correct log recovery because it enables us to spread a complex metadata update +across multiple transactions while ensuring that a crash midway through the +complex update will be replayed fully during log recovery. + +[source, c] +---- +struct xfs_cui_log_format { + __uint16_t cui_type; + __uint16_t cui_size; + __uint32_t cui_nextents; + __uint64_t cui_id; + struct xfs_map_extent cui_extents[1]; +}; +---- + +*cui_type*:: +The signature of an CUI operation, 0x1242. This value is in host-endian order, +not big-endian like the rest of XFS. + +*cui_size*:: +Size of this log item. Should be 1. + +*cui_nextents*:: +Number of reference count updates. + +*cui_id*:: +A 64-bit number that binds the corresponding RUD log item to this RUI log item. + +*cui_extents*:: +Variable-length array of reference count update information. + +[[CUD_Log_Item]] +=== Completion of Reference Count Updates + +The ``reference count update done'' operation complements the ``reference count +update intent'' operation. This second operation indicates that the update +actually happened, so that log recovery needn't replay the update. The CUD and +the actual updates are typically found in a new transaction following the +transaction in which the CUI was logged. + +[source, c] +---- +struct xfs_cud_log_format { + __uint16_t cud_type; + __uint16_t cud_size; + __uint32_t cud_nextents; + __uint64_t cud_rui_id; + struct xfs_map_extent cud_extents[1]; +}; +---- + +*cud_type*:: +The signature of an RUD operation, 0x1243. This value is in host-endian order, +not big-endian like the rest of XFS. + +*cud_size*:: +Size of this log item. Should be 1. + +*cud_nextents*:: +Number of reverse mappings. + +*cud_id*:: +A 64-bit number that binds the corresponding CUI log item to this CUD log item. + +*cud_extents*:: +Variable-length array of reverse mappings. The array length is given by ++cud_nextents+. + +[[BUI_Log_Item]] +=== File Block Mapping Intent + +The next two operation types work together to handle deferred file block +mapping updates. The extents to be mapped are expressed via the ++xfs_map_extent+ structure discussed in the section about +xref:RUI_Log_Item[reverse mapping intents]. + +The lower byte of the +me_flags+ field is a type code indicating what sort of +file block mapping operation we want. The upper three bytes are flag bits. + +.File block mapping update log intent types +[options="header"] +|===== +| Value | Description +| +XFS_BMAP_EXTENT_MAP+ | Add a mapping for file data. +| +XFS_BMAP_EXTENT_UNMAP+ | Remove a mapping for file data. +|===== + +.File block mapping update log intent flags +[options="header"] +|===== +| Value | Description +| +XFS_BMAP_EXTENT_ATTR_FORK+ | Extent is for the attribute fork. +| +XFS_BMAP_EXTENT_UNWRITTEN+ | Extent is unwritten. +|===== + +The ``file block mapping update intent'' operation comes first; it tells the +log that XFS wants to map or unmap some extents in a file. This record is +crucial for correct log recovery because it enables us to spread a complex +metadata update across multiple transactions while ensuring that a crash midway +through the complex update will be replayed fully during log recovery. + +[source, c] +---- +struct xfs_bui_log_format { + __uint16_t bui_type; + __uint16_t bui_size; + __uint32_t bui_nextents; + __uint64_t bui_id; + struct xfs_map_extent bui_extents[1]; +}; +---- + +*bui_type*:: +The signature of an BUI operation, 0x1244. This value is in host-endian order, +not big-endian like the rest of XFS. + +*bui_size*:: +Size of this log item. Should be 1. + +*bui_nextents*:: +Number of file mappings. + +*bui_id*:: +A 64-bit number that binds the corresponding BUD log item to this BUI log item. + +*bui_extents*:: +Variable-length array of file block mappings to update. + +[[BUD_Log_Item]] +=== Completion of File Block Mapping Updates + +The ``file block mapping update done'' operation complements the ``file block +mapping update intent'' operation. This second operation indicates that the +update actually happened, so that log recovery needn't replay the update. The +BUD and the actual updates are typically found in a new transaction following +the transaction in which the BUI was logged. + +[source, c] +---- +struct xfs_bud_log_format { + __uint16_t bud_type; + __uint16_t bud_size; + __uint32_t bud_nextents; + __uint64_t bud_rui_id; + struct xfs_map_extent bud_extents[1]; +}; +---- + +*bud_type*:: +The signature of an BUD operation, 0x1245. This value is in host-endian order, +not big-endian like the rest of XFS. + +*bud_size*:: +Size of this log item. Should be 1. + +*bud_nextents*:: +Number of file block mappings. + +*bud_id*:: +A 64-bit number that binds the corresponding BUI log item to this BUD log item. + +*bud_extents*:: +Variable-length array of file block mappings. The array length is given by ++bud_nextents+. + [[Inode_Log_Item]] === Inode Updates diff --git a/design/XFS_Filesystem_Structure/magic.asciidoc b/design/XFS_Filesystem_Structure/magic.asciidoc index 10fd15f..bc172f3 100644 --- a/design/XFS_Filesystem_Structure/magic.asciidoc +++ b/design/XFS_Filesystem_Structure/magic.asciidoc @@ -45,6 +45,7 @@ relevant chapters. Magic numbers tend to have consistent locations: | +XFS_ATTR3_LEAF_MAGIC+ | 0x3bee | | xref:Leaf_Attributes[Leaf Attribute], v5 only | +XFS_ATTR3_RMT_MAGIC+ | 0x5841524d | XARM | xref:Remote_Values[Remote Attribute Value], v5 only | +XFS_RMAP_CRC_MAGIC+ | 0x524d4233 | RMB3 | xref:Reverse_Mapping_Btree[Reverse Mapping B+tree], v5 only +| +XFS_REFC_CRC_MAGIC+ | 0x52334643 | R3FC | xref:Reference_Count_Btree[Reference Count B+tree], v5 only |===== The magic numbers for log items are at offset zero in each log item, but items @@ -64,6 +65,10 @@ are not aligned to blocks. | +XFS_LI_ICREATE+ | 0x123f | | xref:Inode_Create_Log_Item[Inode Creation Log Item] | +XFS_LI_RUI+ | 0x1240 | | xref:RUI_Log_Item[Reverse Mapping Update Intent] | +XFS_LI_RUD+ | 0x1241 | | xref:RUD_Log_Item[Reverse Mapping Update Done] +| +XFS_LI_CUI+ | 0x1242 | | xref:CUI_Log_Item[Reference Count Update Intent] +| +XFS_LI_CUD+ | 0x1243 | | xref:CUD_Log_Item[Reference Count Update Done] +| +XFS_LI_BUI+ | 0x1244 | | xref:BUI_Log_Item[File Block Mapping Update Intent] +| +XFS_LI_BUD+ | 0x1245 | | xref:BUD_Log_Item[File Block Mapping Update Done] |===== = Theoretical Limits diff --git a/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc b/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc index dc1fad2..4415c38 100644 --- a/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc +++ b/design/XFS_Filesystem_Structure/ondisk_inode.asciidoc @@ -109,7 +109,8 @@ struct xfs_dinode_core { __be64 di_changecount; __be64 di_lsn; __be64 di_flags2; - __u8 di_pad2[16]; + __be32 di_cowextsize; + __u8 di_pad2[12]; xfs_timestamp_t di_crtime; __be64 di_ino; uuid_t di_uuid; @@ -215,7 +216,7 @@ including relevant metadata like B+trees. This does not include blocks used for extended attributes. *di_extsize*:: -Specifies the extent size for filesystems with real-time devices and an extent +Specifies the extent size for filesystems with real-time devices or an extent size hint for standard filesystems. For normal filesystems, and with directories, the +XFS_DIFLAG_EXTSZINHERIT+ flag must be set in +di_flags+ if this field is used. Inodes created in these directories will inherit the @@ -279,7 +280,7 @@ For directory inodes, new inodes inherit the +di_projid+ value. For directory inodes, symlinks cannot be created. | +XFS_DIFLAG_EXTSIZE+ | -Specifies the extent size for real-time files or a and extent size hint for regular files. +Specifies the extent size for real-time files or an extent size hint for regular files. | +XFS_DIFLAG_EXTSZINHERIT+ | For directory inodes, new inodes inherit the +di_extsize+ value. @@ -323,8 +324,26 @@ Specifies extended flags associated with a v3 inode. | +XFS_DIFLAG2_DAX+ | For a file, enable DAX to increase performance on persistent-memory storage. If set on a directory, files created in the directory will inherit this flag. +| +XFS_DIFLAG2_REFLINK+ | +This inode shares (or has shared) data blocks with another inode. +| +XFS_DIFLAG2_COWEXTSIZE+ | +For files, this is the extent size hint for copy on write operations; see ++di_cowextsize+ for details. For directories, the value in +di_cowextsize+ +will be copied to all newly created files and directories. |===== +*di_cowextsize*:: +Specifies the extent size hint for copy on write operations. When allocating +extents for a copy on write operation, the allocator will be asked to align +its allocations to either +di_cowextsize+ blocks or +di_extsize+ blocks, +whichever is greater. The +XFS_DIFLAG2_COWEXTSIZE+ flag must be set if this +field is used. If this field and its flag are set on a directory file, the +value will be copied into any files or directories created within this +directory. During a block sharing operation, this value will be copied from +the source file to the destination file if the sharing operation completely +overwrites the destination file's contents and the destination file does not +already have +di_cowextsize+ set. + *di_pad2*:: Padding for future expansion of the inode. diff --git a/design/XFS_Filesystem_Structure/refcountbt.asciidoc b/design/XFS_Filesystem_Structure/refcountbt.asciidoc new file mode 100644 index 0000000..dbbb98e --- /dev/null +++ b/design/XFS_Filesystem_Structure/refcountbt.asciidoc @@ -0,0 +1,145 @@ +[[Reference_Count_Btree]] +== Reference Count B+tree + +[NOTE] +This data structure is under construction! Details may change. + +To support the sharing of file data blocks (reflink), each allocation group has +its own reference count B+tree, which grows in the allocated space like the +inode B+trees. This data could be gleaned by performing an interval query of +the reverse-mapping B+tree, but doing so would come at a huge performance +penalty. Therefore, this data structure is a cache of computable information. + +This B+tree is only present if the +XFS_SB_FEAT_RO_COMPAT_REFLINK+ +feature is enabled. The feature requires a version 5 filesystem. + +Each record in the reference count B+tree has the following structure: + +[source, c] +---- +struct xfs_refcount_rec { + __be32 rc_startblock; + __be32 rc_blockcount; + __be32 rc_refcount; +}; +---- + +*rc_startblock*:: +AG block number of this record. + +*rc_blockcount*:: +The length of this extent. + +*rc_refcount*:: +Number of mappings of this filesystem extent. + +Node pointers are an AG relative block pointer: + +[source, c] +---- +struct xfs_refcount_key { + __be32 rc_startblock; +}; +---- + +* As the reference counting is AG relative, all the block numbers are only +32-bits. +* The +bb_magic+ value is "R3FC" (0x52334643). +* The +xfs_btree_sblock_t+ header is used for intermediate B+tree node as well +as the leaves. + +=== xfs_db refcntbt Example + +For this example, an XFS filesystem was populated with a root filesystem and +a deduplication program was run to create shared blocks: + +---- +xfs_db> agf 0 +xfs_db> addr refcntroot +xfs_db> p +magic = 0x52334643 +level = 1 +numrecs = 6 +leftsib = null +rightsib = null +bno = 36892 +lsn = 0x200004ec2 +uuid = f1f89746-e00b-49c9-96b3-ecef0f2f14ae +owner = 0 +crc = 0x75f35128 (correct) +keys[1-6] = [startblock] 1:[14] 2:[65633] 3:[65780] 4:[94571] 5:[117201] 6:[152442] +ptrs[1-6] = 1:7 2:25836 3:25835 4:18447 5:18445 6:18449 +xfs_db> addr ptrs[3] +xfs_db> p +magic = 0x52334643 +level = 0 +numrecs = 80 +leftsib = 25836 +rightsib = 18447 +bno = 51670 +lsn = 0x200004ec2 +uuid = f1f89746-e00b-49c9-96b3-ecef0f2f14ae +owner = 0 +crc = 0xc3962813 (correct) +recs[1-80] = [startblock,blockcount,refcount] + 1:[65780,1,2] 2:[65781,1,3] 3:[65785,2,2] 4:[66640,1,2] + 5:[69602,4,2] 6:[72256,16,2] 7:[72871,4,2] 8:[72879,20,2] + 9:[73395,4,2] 10:[75063,4,2] 11:[79093,4,2] 12:[86344,16,2] +---- + +Record 6 in the reference count B+tree for AG 0 indicates that the AG extent +starting at block 72,256 and running for 16 blocks has a reference count of 2. +This means that there are two files sharing the block: + +---- +xfs_db> blockget -n +xfs_db> fsblock 72256 +xfs_db> blockuse +block 72256 (0/72256) type rldata inode 25169197 +---- + +The blockuse type changes to ``rldata'' to indicate that the block is shared +data. Unfortunately, blockuse only tells us about one block owner. If we +happen to have enabled the reverse-mapping B+tree, we can use it to find all +inodes that own this block: + +---- +xfs_db> agf 0 +xfs_db> addr rmaproot +... +xfs_db> addr ptrs[3] +... +xfs_db> addr ptrs[7] +xfs_db> p +magic = 0x524d4233 +level = 0 +numrecs = 22 +leftsib = 65057 +rightsib = 65058 +bno = 291478 +lsn = 0x200004ec2 +uuid = f1f89746-e00b-49c9-96b3-ecef0f2f14ae +owner = 0 +crc = 0xed7da3f7 (correct) +recs[1-22] = [startblock,blockcount,owner,offset,extentflag,attrfork,bmbtblock] + 1:[68957,8,3201,0,0,0,0] 2:[68965,4,25260953,0,0,0,0] + ... + 18:[72232,58,3227,0,0,0,0] 19:[72256,16,25169197,24,0,0,0] + 20:[72290,75,3228,0,0,0,0] 21:[72365,46,3229,0,0,0,0] +---- + +Records 18 and 19 intersect the block 72,256; they tell us that inodes 3,227 +and 25,169,197 both claim ownership. Let us confirm this: + +---- +xfs_db> inode 25169197 +xfs_db> bmap +data offset 0 startblock 12632259 (3/49347) count 24 flag 0 +data offset 24 startblock 72256 (0/72256) count 16 flag 0 +data offset 40 startblock 12632299 (3/49387) count 18 flag 0 +xfs_db> inode 3227 +xfs_db> bmap +data offset 0 startblock 72232 (0/72232) count 58 flag 0 +---- + +Inodes 25,169,197 and 3,227 both contain mappings to block 0/72,256. diff --git a/design/XFS_Filesystem_Structure/reflink.asciidoc b/design/XFS_Filesystem_Structure/reflink.asciidoc new file mode 100644 index 0000000..8f52b90 --- /dev/null +++ b/design/XFS_Filesystem_Structure/reflink.asciidoc @@ -0,0 +1,40 @@ +[[Reflink_Deduplication]] += Sharing Data Blocks + +On a traditional filesystem, there is a 1:1 mapping between a logical block +offset in a file and a physical block on disk, which is to say that physical +blocks are not shared. However, there exist various use cases for being able +to share blocks between files -- deduplicating files saves space on archival +systems; creating space-efficient clones of disk images for virtual machines +and containers facilitates efficient datacenters; and deferring the payment of +the allocation cost of a file system tree copy as long as possible makes +regular work faster. In all of these cases, a write to one of the shared +copies *must* not affect the other shared copies, which means that writes to +shared blocks must employ a copy-on-write strategy. Sharing blocks in this +manner is commonly referred to as ``reflinking''. + +XFS implements block sharing in a fairly straightforward manner. All existing +data fork structures remain unchanged, save for the addition of a +per-allocation group xref:Reference_Count_Btree[reference count B+tree]. This +data structure tracks reference counts for all shared physical blocks, with a +few rules to maintain compatibility with existing code: If a block is free, it +will be tracked in the free space B+trees. If a block is owned by a single +file, it appears in neither the free space nor the reference count B+trees. If +a block is shared, it will appear in the reference count B+tree with a +reference count >= 2. The first two cases are established precedent in XFS, so +the third case is the only behavioral change. + +When a filesystem block is shared, the block mapping in the destination file is +updated to point to that filesystem block and the reference count B+tree records +are updated to reflect the increased refcount. If a shared block is written, a +new block will be allocated, the dirty data written to this new block, and the +file's block mapping updated to point to the new block. If a shared block is +unmapped, the reference count records are updated to reflect the decreased +refcount and the block is also freed if its reference count becomes zero. This +enables users to create space efficient clones of disk images and to copy +filesystem subtrees quickly, using the standard Linux coreutils packages. + +Deduplication employs the same mechanism to share blocks and copy them at write +time. However, the kernel confirms that the contents of both files are +identical before updating the destination file's mapping. This enables XFS to +be used by userspace deduplication programs such as +duperemove+. diff --git a/design/XFS_Filesystem_Structure/rmapbt.asciidoc b/design/XFS_Filesystem_Structure/rmapbt.asciidoc index a8a210b..0ec72c1 100644 --- a/design/XFS_Filesystem_Structure/rmapbt.asciidoc +++ b/design/XFS_Filesystem_Structure/rmapbt.asciidoc @@ -53,6 +53,8 @@ absolute inode number, but can also correspond to one of the following: | +XFS_RMAP_OWN_AG+ | Per-allocation group B+tree blocks. This means free space B+tree blocks, blocks on the freelist, and reverse-mapping B+tree blocks. | +XFS_RMAP_OWN_INOBT+ | Per-allocation group inode B+tree blocks. This includes free inode B+tree blocks. | +XFS_RMAP_OWN_INODES+ | Inode chunks +| +XFS_RMAP_OWN_REFC+ | Per-allocation group refcount B+tree blocks. This will be used for reflink support. +| +XFS_RMAP_OWN_COW+ | Blocks that have been reserved for a copy-on-write operation that has not completed. |===== *rm_fork*:: diff --git a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc index 1b8658d..7916fbe 100644 --- a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc +++ b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc @@ -48,6 +48,8 @@ include::overview.asciidoc[] include::metadata_integrity.asciidoc[] +include::reflink.asciidoc[] + include::reconstruction.asciidoc[] include::common_types.asciidoc[] @@ -70,6 +72,8 @@ include::allocation_groups.asciidoc[] include::rmapbt.asciidoc[] +include::refcountbt.asciidoc[] + include::journaling_log.asciidoc[] include::internal_inodes.asciidoc[] From darrick.wong@oracle.com Thu Jun 16 20:48:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 92DCF85A0 for ; Thu, 16 Jun 2016 20:48:55 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4E7448F8054 for ; Thu, 16 Jun 2016 18:48:55 -0700 (PDT) X-ASG-Debug-ID: 1466128117-04bdf01e10968d0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id bK5t8WKJCkIKCMej (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 18:48:37 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H1maHa027648 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:36 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H1mZwF023599 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 01:48:35 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H1mZfZ005590; Fri, 17 Jun 2016 01:48:35 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 18:48:34 -0700 Subject: [PATCH 4/6] xfsdocs: move the discussions of short and long format btrees to a separate chapter From: "Darrick J. Wong" X-ASG-Orig-Subj: [PATCH 4/6] xfsdocs: move the discussions of short and long format btrees to a separate chapter To: david@fromorbit.com, darrick.wong@oracle.com Cc: xfs@oss.sgi.com Date: Thu, 16 Jun 2016 18:48:33 -0700 Message-ID: <146612811355.25586.2303327639177399141.stgit@birch.djwong.org> In-Reply-To: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> References: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466128117 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 14274 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Move the discussion of short and long format btrees into a separate chapter. Signed-off-by: Darrick J. Wong --- .../allocation_groups.asciidoc | 59 ------ design/XFS_Filesystem_Structure/btrees.asciidoc | 200 ++++++++++++++++++++ .../XFS_Filesystem_Structure/data_extents.asciidoc | 71 ------- .../xfs_filesystem_structure.asciidoc | 2 4 files changed, 206 insertions(+), 126 deletions(-) create mode 100644 design/XFS_Filesystem_Structure/btrees.asciidoc diff --git a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc index 0633175..55bbc50 100644 --- a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc +++ b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc @@ -612,65 +612,6 @@ Checksum of the AGF sector. *agf_spare2*:: Empty space in the unlogged part of the AGF sector. -[[Short_Format_Btrees]] -=== Short Format B+trees - -Each allocation group uses a ``short format'' B+tree to index various -information about the allocation group. The structure is called short format -because all block pointers are AG block numbers. The trees use the following -header: - -[source, c] ----- -struct xfs_btree_sblock { - __be32 bb_magic; - __be16 bb_level; - __be16 bb_numrecs; - __be32 bb_leftsib; - __be32 bb_rightsib; - - /* version 5 filesystem fields start here */ - __be64 bb_blkno; - __be64 bb_lsn; - uuid_t bb_uuid; - __be32 bb_owner; - __le32 bb_crc; -}; ----- - -*bb_magic*:: -Specifies the magic number for the per-AG B+tree block. - -*bb_level*:: -The level of the tree in which this block is found. If this value is 0, this -is a leaf block and contains records; otherwise, it is a node block and -contains keys and pointers. - -*bb_numrecs*:: -Number of records in this block. - -*bb_leftsib*:: -AG block number of the left sibling of this B+tree node. - -*bb_rightsib*:: -AG block number of the right sibling of this B+tree node. - -*bb_blkno*:: -FS block number of this B+tree block. - -*bb_lsn*:: -Log sequence number of the last write to this block. - -*bb_uuid*:: -The UUID of this block, which must match either +sb_uuid+ or +sb_meta_uuid+ -depending on which features are set. - -*bb_owner*:: -The AG number that this B+tree block ought to be in. - -*bb_crc*:: -Checksum of the B+tree block. - [[AG_Free_Space_Btrees]] === AG Free Space B+trees diff --git a/design/XFS_Filesystem_Structure/btrees.asciidoc b/design/XFS_Filesystem_Structure/btrees.asciidoc new file mode 100644 index 0000000..c67669c --- /dev/null +++ b/design/XFS_Filesystem_Structure/btrees.asciidoc @@ -0,0 +1,200 @@ += B+trees + +XFS uses b+trees to index all metadata records. This well known data structure +is used to provide efficient random and sequential access to metadata records +while minimizing seek times. There are two btree formats: a short format +for records pertaining to a single allocation group, since all block pointers +in an AG are 32-bits in size; and a long format for records pertaining to a +file, since file data can have 64-bit block offsets. Each b+tree block is +either a leaf node containing records, or an internal node containing keys and +pointers to other b+tree blocks. The tree consists of a root block which may +point to some number of other blocks; blocks in the bottom level of the b+tree +contains only records. + +Leaf blocks of both types of b+trees have the same general format: a header +describing the data in the block, and an array of records. The specific header +formats are given in the next two sections, and the record format is provided +by the b+tree client itself. The generic b+tree code does not have any +specific knowledge of the record format. + +---- ++--------+------------+------------+ +| header | record | records... | ++--------+------------+------------+ +---- + +Internal node blocks of both types of b+trees also have the same general +format: a header describing the data in the block, an array of keys, and an +array of pointers. Each pointer may be associated with one or two keys. The +first key uniquely identifies the first record accessible via the leftmost path +down the branch of the tree. + +If the records in a b+tree are indexed by an interval, then a range of keys can +uniquely identify a single record. For example, if a record covers blocks +12-16, then any one of the keys 12, 13, 14, 15, or 16 return the same record. +In this case, the key for the record describing "12-16" is 12. If none of the +records overlap, we only need to store one key. + +This is the format of a standard b+tree node: + +---- ++--------+---------+---------+---------+---------+ +| header | key | keys... | ptr | ptrs... | ++--------+---------+---------+---------+---------+ +---- + +If the b+tree records do not overlap, performing a b+tree lookup is simple. +Start with the root. If it is a leaf block, perform a binary search of the +records until we find the record with a lower key than our search key. If the +block is a node block, perform a binary search of the keys until we find a +key lower than our search key, then follow the pointer to the next block. +Repeat until we find a record. + +However, if b+tree records contain intervals and are allowed to overlap, the +internal nodes of the b+tree become larger: + +---- ++--------+---------+----------+---------+-------------+---------+---------+ +| header | low key | high key | low key | high key... | ptr | ptrs... | ++--------+---------+----------+---------+-------------+---------+---------+ +---- + +The low keys are exactly the same as the keys in the non-overlapping b+tree. +High keys, however, are a little different. Recall that a record with a key +consisting of an interval can be referenced by a number of keys. Since the low +key of a record indexes the low end of that key range, the high key indexes the +high end of the key range. Returning to the example above, the high key for +the record describing "12-16" is 16. The high key recorded in a b+tree node +is the largest of the high keys of all records accessible under the subtree +rooted by the pointer. For a level 1 node, this is the largest high key in +the pointed-to leaf node; for any other node, this is the largest of the high +keys in the pointed-to node. + +Nodes and leaves use the same magic numbers. + +[[Short_Format_Btrees]] +== Short Format B+trees + +Each allocation group uses a ``short format'' B+tree to index various +information about the allocation group. The structure is called short format +because all block pointers are AG block numbers. The trees use the following +header: + +[source, c] +---- +struct xfs_btree_sblock { + __be32 bb_magic; + __be16 bb_level; + __be16 bb_numrecs; + __be32 bb_leftsib; + __be32 bb_rightsib; + + /* version 5 filesystem fields start here */ + __be64 bb_blkno; + __be64 bb_lsn; + uuid_t bb_uuid; + __be32 bb_owner; + __le32 bb_crc; +}; +---- + +*bb_magic*:: +Specifies the magic number for the per-AG B+tree block. + +*bb_level*:: +The level of the tree in which this block is found. If this value is 0, this +is a leaf block and contains records; otherwise, it is a node block and +contains keys and pointers. + +*bb_numrecs*:: +Number of records in this block. + +*bb_leftsib*:: +AG block number of the left sibling of this B+tree node. + +*bb_rightsib*:: +AG block number of the right sibling of this B+tree node. + +*bb_blkno*:: +FS block number of this B+tree block. + +*bb_lsn*:: +Log sequence number of the last write to this block. + +*bb_uuid*:: +The UUID of this block, which must match either +sb_uuid+ or +sb_meta_uuid+ +depending on which features are set. + +*bb_owner*:: +The AG number that this B+tree block ought to be in. + +*bb_crc*:: +Checksum of the B+tree block. + +[[Long_Format_Btrees]] +== Long Format B+trees + +If an inode's block map requires more records than fit into the inode's fork +area, it will use a b+tree to index the records. The nodes and leaves of this +B+tree use the +xfs_btree_lblock+ declaration: + +[source, c] +---- +struct xfs_btree_lblock { + __be32 bb_magic; + __be16 bb_level; + __be16 bb_numrecs; + __be64 bb_leftsib; + __be64 bb_rightsib; + + /* version 5 filesystem fields start here */ + __be64 bb_blkno; + __be64 bb_lsn; + uuid_t bb_uuid; + __be64 bb_owner; + __le32 bb_crc; + __be32 bb_pad; +}; +---- + +*bb_magic*:: +Specifies the magic number for the BMBT block: ``BMAP'' (0x424d4150). +On a v5 filesystem, this is ``BMA3'' (0x424d4133). + +*bb_level*:: +The level of the tree in which this block is found. If this value is 0, this +is a leaf block and contains records; otherwise, it is a node block and +contains keys and pointers. + +*bb_numrecs*:: +Number of records in this block. + +*bb_leftsib*:: +FS block number of the left sibling of this B+tree node. + +*bb_rightsib*:: +FS block number of the right sibling of this B+tree node. + +*bb_blkno*:: +FS block number of this B+tree block. + +*bb_lsn*:: +Log sequence number of the last write to this block. + +*bb_uuid*:: +The UUID of this block, which must match either +sb_uuid+ or +sb_meta_uuid+ +depending on which features are set. + +*bb_owner*:: +The AG number that this B+tree block ought to be in. + +*bb_crc*:: +Checksum of the B+tree block. + +*bb_pad*:: +Pads the structure to 64 bytes. + +// force-split the lists + +* Long format b+trees are rooted in an inode, not a separate block. + diff --git a/design/XFS_Filesystem_Structure/data_extents.asciidoc b/design/XFS_Filesystem_Structure/data_extents.asciidoc index a39045d..530406d 100644 --- a/design/XFS_Filesystem_Structure/data_extents.asciidoc +++ b/design/XFS_Filesystem_Structure/data_extents.asciidoc @@ -203,9 +203,10 @@ u.bmx[0-1] = [startoff,startblock,blockcount,extentflag] [[Btree_Extent_List]] == B+tree Extent List -To manage extent maps that cannot fit in the inode fork area, XFS uses long -format B+trees. The root node of the B+tree is stored in the inode's data -fork. All block pointers for extent B+trees are 64-bit absolute block numbers. +To manage extent maps that cannot fit in the inode fork area, XFS uses +xref:Long_Format_Btrees[long format B+trees]. The root node of the B+tree is +stored in the inode's data fork. All block pointers for extent B+trees are +64-bit absolute block numbers. For a single level B+tree, the root node points to the B+tree's leaves. Each leaf occupies one filesystem block and contains a header and an array of extents @@ -242,70 +243,6 @@ standard 256 byte inode before a new level of nodes is added between the root and the leaves. This will be less if +di_forkoff+ is not zero (i.e. attributes are in use on the inode). -[[Long_Format_Btrees]] -=== Long Format B+trees - -The subsequent nodes and leaves of the B+tree use the +xfs_btree_lblock+ -declaration: - -[source, c] ----- -struct xfs_btree_lblock { - __be32 bb_magic; - __be16 bb_level; - __be16 bb_numrecs; - __be64 bb_leftsib; - __be64 bb_rightsib; - - /* version 5 filesystem fields start here */ - __be64 bb_blkno; - __be64 bb_lsn; - uuid_t bb_uuid; - __be64 bb_owner; - __le32 bb_crc; - __be32 bb_pad; -}; ----- - -*bb_magic*:: -Specifies the magic number for the BMBT block: ``BMAP'' (0x424d4150). -On a v5 filesystem, this is ``BMA3'' (0x424d4133). - -*bb_level*:: -The level of the tree in which this block is found. If this value is 0, this -is a leaf block and contains records; otherwise, it is a node block and -contains keys and pointers. - -*bb_numrecs*:: -Number of records in this block. - -*bb_leftsib*:: -FS block number of the left sibling of this B+tree node. - -*bb_rightsib*:: -FS block number of the right sibling of this B+tree node. - -*bb_blkno*:: -FS block number of this B+tree block. - -*bb_lsn*:: -Log sequence number of the last write to this block. - -*bb_uuid*:: -The UUID of this block, which must match either +sb_uuid+ or +sb_meta_uuid+ -depending on which features are set. - -*bb_owner*:: -The AG number that this B+tree block ought to be in. - -*bb_crc*:: -Checksum of the B+tree block. - -*bb_pad*:: -Pads the structure to 64 bytes. - -// force-split the lists - * For intermediate nodes, the data following +xfs_btree_lblock+ is the same as the root node: array of +xfs_bmbt_key+ value followed by an array of +xfs_bmbt_ptr_t+ values that starts halfway through the block (offset 0x808 for diff --git a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc index f580aab..62502b3 100644 --- a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc +++ b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc @@ -62,6 +62,8 @@ Global Structures :leveloffset: 1 +include::btrees.asciidoc[] + include::allocation_groups.asciidoc[] include::journaling_log.asciidoc[] From darrick.wong@oracle.com Thu Jun 16 21:09:54 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5B87884B8 for ; Thu, 16 Jun 2016 21:09:54 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2BCA48F804B for ; Thu, 16 Jun 2016 19:09:51 -0700 (PDT) X-ASG-Debug-ID: 1466129388-04cb6c542658ea0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 18abdPaxsujvRKSM (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 19:09:48 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H29i0P032346 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 02:09:45 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H29iUX025498 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 02:09:44 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5H29hTB012822; Fri, 17 Jun 2016 02:09:44 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 19:09:43 -0700 Date: Thu, 16 Jun 2016 19:09:42 -0700 From: "Darrick J. Wong" To: Vishal Verma Cc: linux-nvdimm@ml01.01.org, xfs@oss.sgi.com, Jan Kara Subject: Re: [RFC PATCH 0/2] Initial support for badblock checking in xfs Message-ID: <20160617020942.GB11810@birch.djwong.org> X-ASG-Orig-Subj: Re: [RFC PATCH 0/2] Initial support for badblock checking in xfs References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466129388 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2726 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30506 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Thu, Jun 16, 2016 at 07:03:37PM -0600, Vishal Verma wrote: > These are early/RFC patches to add badblock support in xfs. > > Patch 1 should be relatively straightforward - it adds a notifier chain > to badblocks that filesystems can register with. > > Patch 2 is the beginnings of xfs support. So far, I have the notifier > registration and building the initial badblock list happening in > xfs_mountfs. The next steps (and I may need some help with this as I'm > no (x)fs developer :)) are to add this badblocks info to the reverse > mapping tree, and then to check for it before accessing the media. > > Right now, this just prints the sector numbers/counts/{added, removed} > to the kernel log, for both the initial list, and subsequent notifier > hits. > > While I've tested this with a fake pmem device using libnvdimm's > nfit_test framework, it should also work using badblock injection with > any block device: > > # mkfs.xfs -f /dev/ > # echo 122 1 > /sys/block//badblocks > # echo 124 1 > /sys/block//badblocks > # mount -t xfs /dev/ /mnt > ... in log: > [ +8.803776] XFS (pmem7): Mounting V4 Filesystem > [ +0.009633] XFS (pmem7): Ending clean mount > [ +0.001655] XFS (pmem7): got badblocks: sector 122, count 1 > [ +0.002018] XFS (pmem7): got badblocks: sector 124, count 1 > > # echo 132 5 | > /sys/block//badblocks > [Jun16 18:56] XFS (pmem7): xfs badblock added sector 132 (count 5) > > This is all based on Darrik's rmap work at: > https://github.com/djwong/linux/tree/rmap-reflink-devel > > Since this is based on a v4.5-rc kernel, it lacks pmem support for > clearing badblocks on zeroing/writing, so those parts can't easily > be tested yet. The clearing work is in 4.7-rs kernels, and once we > rebase to that, that should also be available. I'm assuming you got at least a few of the 300 patches I just sent. IOW: The whole kit and kaboodle have been rebased to for-next, which means the kernel patches are based on 4.7-rc3. Will have a look at the other patches. :) --D > > > Vishal Verma (2): > block, badblocks: add a notifier for badblocks > xfs: initial/partial support for badblocks > > block/badblocks.c | 79 +++++++++++++++++++++++++++++++++-- > fs/xfs/xfs_linux.h | 1 + > fs/xfs/xfs_mount.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/xfs_mount.h | 1 + > include/linux/badblocks.h | 19 +++++++++ > 5 files changed, 201 insertions(+), 3 deletions(-) > > -- > 2.5.5 > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Thu Jun 16 21:26:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_FOLLOW1,T_FRT_FOLLOW2, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 261FC7EA2 for ; Thu, 16 Jun 2016 21:26:21 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id DC6A4304039 for ; Thu, 16 Jun 2016 19:26:17 -0700 (PDT) X-ASG-Debug-ID: 1466130374-04cbb01fec6be70001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Is5xAGbMZQNsfqQG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Thu, 16 Jun 2016 19:26:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5H2QBCG023462 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 02:26:11 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5H2QAlA015570 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 02:26:11 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5H2Q8Wa026397; Fri, 17 Jun 2016 02:26:09 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 16 Jun 2016 19:26:08 -0700 Date: Thu, 16 Jun 2016 19:26:06 -0700 From: "Darrick J. Wong" To: Vishal Verma Cc: linux-nvdimm@ml01.01.org, xfs@oss.sgi.com, Jan Kara Subject: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks Message-ID: <20160617022606.GC11810@birch.djwong.org> X-ASG-Orig-Subj: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> <1466125419-17736-3-git-send-email-vishal.l.verma@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466125419-17736-3-git-send-email-vishal.l.verma@intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466130375 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7234 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30507 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Thu, Jun 16, 2016 at 07:03:39PM -0600, Vishal Verma wrote: > RFC/WIP commit. > > This adds the foollowing: > 1. In xfs_mountfs(), get an initial badblocks list from gendisk's > badblocks infrastructure. > 2. Register with the badblocks notifier to get updates for this disk's > badblocks > > TODO: > 1. Add badblocks info to the reverse mapping tree (and remove if a > badblock was cleared). Well... there are a number of things we /could/ do... theoretically one could use the rmap info to find all the affected inodes and simply convert that part of their extent trees to 'unwritten'. Reads will just get zeroes, and writes will remove the unwritten flag (for that file, anyway). Will a successful write trigger the BB_CLEAR notifier? I guess you could punch out the bad blocks too... not clear if you'd want all the owner files staying mapped to data they'll never get back. We could also create another rmap "special owner" (XFS_RMAP_OWN_BAD?) for bad blocks, so we'd know which parts are just plain bad. It might be useful to know that kind of thing. I think earlier Dave was talking about adding a new 'badblocks' bit to both the file extent records and the rmap records to signify that something's wrong with the extent. I'll let him write about that. > 2. Before doing file IO, refer the rmap/badblocks to error out early if > the IO will attempt wo read a bad sector > 3. Figure out interactions with mmap/DAX. Woot. > Cc: Darrick J. Wong > Cc: Dave Chinner > Signed-off-by: Vishal Verma > --- > fs/xfs/xfs_linux.h | 1 + > fs/xfs/xfs_mount.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/xfs_mount.h | 1 + > 3 files changed, 106 insertions(+) > > diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h > index 7e749be..f66d181 100644 > --- a/fs/xfs/xfs_linux.h > +++ b/fs/xfs/xfs_linux.h > @@ -78,6 +78,7 @@ typedef __u32 xfs_nlink_t; > #include > #include > #include > +#include > > #include > #include > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c > index 5e68b2c..1a47737 100644 > --- a/fs/xfs/xfs_mount.c > +++ b/fs/xfs/xfs_mount.c > @@ -618,6 +618,96 @@ xfs_default_resblks(xfs_mount_t *mp) > return resblks; > } > > +STATIC int > +xfs_notifier_call( > + struct notifier_block *nb, > + unsigned long action, > + void *data) > +{ > + struct bb_notifier_data *bb_data = data; > + struct xfs_mount *mp; > + > + mp = container_of(nb, struct xfs_mount, m_badblocks_nb); > + /* TODO xfs_add_bb_to_rmap(mp, bb_data->sector, bb_data->count); */ > + xfs_warn(mp, "xfs badblock %s sector %lu (count %d)\n", > + (action == BB_ADD)?"added":"cleared", > + bb_data->sector, bb_data->count); > + return 0; Probably a xfs_rmapbt_query_range here? > +} > + > +STATIC int > +xfs_init_badblocks(struct xfs_mount *mp) > +{ > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > + int done = 0, error = 0; > + ssize_t len, off = 0; > + char *p; > + > + /* > + * TODO: get a list of known badblocks so far and process it. > + * Can we just parse the sysfs format that badblocks_show() > + * returns? That should be the fastest way to get this. > + * Something like: (Is this too hacky? Should we just do > + * badblocks_check() in a (rather large) loop?) > + */ > + p = kzalloc(PAGE_SIZE, GFP_KERNEL); > + len = badblocks_show(bb, p, 0); > + while (len) { > + int count, n; > + sector_t s; > + > + /* > + * The sysfs badblocks format is multiple lines of: > + * " " > + */ > + n = sscanf(p + off, "%lu %d\n%n", &s, &count, &done); Ick, there's got to be a better way to iterate the badblocks list than this. It would be very nice to have a single function that deals with a change in badness status, which would be called by both the notifier and the badblocks iterator. > + if (n < 2 || done < 3) { > + error = -1; > + break; > + } > + off += done; > + len -= done; > + xfs_warn(mp, "got badblocks: sector %ld, count %d", s, count); > + /* TODO xfs_add_bb_to_rmap(mp, s, count); */ > + } > + kfree(p); > + if (error) > + return error; > + > + mp->m_badblocks_nb.notifier_call = xfs_notifier_call; > + error = bb_notifier_register(bb, &mp->m_badblocks_nb); > + if (error) > + return error; > + > + /* > + * TODO: There is probably a TOCTOU race hiding here - what if the > + * badblocks list gets updated before we register for notifications.. > + * Can likely be solved by registering for notifications _first_ (the > + * above xfs_add_bb_to_rmap function has to be ready to accept new > + * blocks), then querying for the initial list (there could be overlap > + * here, shich the above function could handle), and then setting the > + * mount flag below. > + */ (Yeah, pretty much. :)) > + > + /* > + * TODO: set some flag (mount flag?) in xfs so that xfs knows > + * it will be doing error checking, and can possibly, later, > + * tell the block layer (possibly using a REQ_ flag in its IO > + * requests) not to do further badblock checking for those IOs. > + */ > + > + /* mp->m_flags |= XFS_MOUNT_FS_BADBLOCKS; */ > + return 0; > +} > + > +STATIC void > +xfs_badblocks_unmount(struct xfs_mount *mp) > +{ > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > + > + bb_notifier_unregister(bb, &mp->m_badblocks_nb); > +} > + > /* > * This function does the following on an initial mount of a file system: > * - reads the superblock from disk and init the mount struct > @@ -955,6 +1045,19 @@ xfs_mountfs( > } > > /* > + * Register with the badblocks notifier chain > + */ > + error = xfs_init_badblocks(mp); > + if (error) { > + xfs_warn(mp, "Unable to register to badblocks notifications\n"); > + /* > + * TODO is this a hard error or can we simply > + * warn and continue? > + */ > + goto out_rtunmount; > + } > + > + /* > * Now we are mounted, reserve a small amount of unused space for > * privileged transactions. This is needed so that transaction > * space required for critical operations can dip into this pool > @@ -1085,6 +1188,7 @@ xfs_unmountfs( > xfs_log_unmount(mp); > xfs_da_unmount(mp); > xfs_uuid_unmount(mp); > + xfs_badblocks_unmount(mp); > > #if defined(DEBUG) > xfs_errortag_clearall(mp, 0); > diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h > index 0ca9244..f0d1111 100644 > --- a/fs/xfs/xfs_mount.h > +++ b/fs/xfs/xfs_mount.h > @@ -139,6 +139,7 @@ typedef struct xfs_mount { > /* low free space thresholds */ > struct xfs_kobj m_kobj; > struct xstats m_stats; /* per-fs stats */ > + struct notifier_block m_badblocks_nb; /* disk badblocks notifier */ > > struct workqueue_struct *m_buf_workqueue; > struct workqueue_struct *m_data_workqueue; > -- > 2.5.5 > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:32:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 346B67CAF for ; Fri, 17 Jun 2016 06:32:28 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 03B72304039 for ; Fri, 17 Jun 2016 04:32:27 -0700 (PDT) X-ASG-Debug-ID: 1466163145-04cb6c542563180001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id 4xkZvMFRWCAGMvva (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:32:26 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDs0d-0005Cz-QV; Fri, 17 Jun 2016 11:32:23 +0000 Date: Fri, 17 Jun 2016 04:32:23 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 001/119] vfs: fix return type of ioctl_file_dedupe_range Message-ID: <20160617113223.GA19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 001/119] vfs: fix return type of ioctl_file_dedupe_range References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612627940.12839.15145788608361492501.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612627940.12839.15145788608361492501.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466163146 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 329 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Thu, Jun 16, 2016 at 06:17:59PM -0700, Darrick J. Wong wrote: > All the VFS functions in the dedupe ioctl path return int status, so > the ioctl handler ought to as well. > > Found by Coverity, CID 1350952. > > Signed-off-by: Darrick J. Wong This should go out to Al as a separate patch. From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:33:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BB7767CB7 for ; Fri, 17 Jun 2016 06:33:20 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 45FEBAC004 for ; Fri, 17 Jun 2016 04:33:17 -0700 (PDT) X-ASG-Debug-ID: 1466163195-04bdf01e10a9f30001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id muzc3kkTupQslAxM (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:33:16 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDs1S-0005J7-4V; Fri, 17 Jun 2016 11:33:14 +0000 Date: Fri, 17 Jun 2016 04:33:14 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 003/119] xfs: check offsets of variable length structures Message-ID: <20160617113314.GB19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 003/119] xfs: check offsets of variable length structures References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612629195.12839.14090954204243398929.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612629195.12839.14090954204243398929.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466163195 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 494 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Thu, Jun 16, 2016 at 06:18:12PM -0700, Darrick J. Wong wrote: > Some of the directory/attr structures contain variable-length objects, > so the enclosing structure doesn't have a meaningful fixed size at > compile time. We can check the offsets of the members before the > variable-length member, so do those. > > Signed-off-by: Darrick J. Wong Looks fine, and should go in independently of the rmap work: Reviewed-by: Christoph Hellwig From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:34:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4EF147CAF for ; Fri, 17 Jun 2016 06:34:28 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id B9901AC002 for ; Fri, 17 Jun 2016 04:34:27 -0700 (PDT) X-ASG-Debug-ID: 1466163265-04cbb01fee7cac0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id teZg9C4Cok9J3ZEW (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:34:25 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDs2Z-0005Ow-ET; Fri, 17 Jun 2016 11:34:23 +0000 Date: Fri, 17 Jun 2016 04:34:23 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 004/119] xfs: enable buffer deadlock postmortem diagnosis via ftrace Message-ID: <20160617113423.GC19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 004/119] xfs: enable buffer deadlock postmortem diagnosis via ftrace References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612629822.12839.7938642541078923297.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612629822.12839.7938642541078923297.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466163265 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 642 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS > diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c > index efa2a73..2333db7 100644 > --- a/fs/xfs/xfs_buf.c > +++ b/fs/xfs/xfs_buf.c > @@ -947,7 +947,8 @@ xfs_buf_trylock( > if (locked) > XB_SET_OWNER(bp); > > - trace_xfs_buf_trylock(bp, _RET_IP_); > + locked ? trace_xfs_buf_trylock(bp, _RET_IP_) : > + trace_xfs_buf_trylock_fail(bp, _RET_IP_); > return locked; I think this should be something like: if (locked) { XB_SET_OWNER(bp); trace_xfs_buf_trylock(bp, _RET_IP_); } else { trace_xfs_buf_trylock_fail(bp, _RET_IP_); } otherwise this looks good and can go in without the rest of the series. From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:34:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C26EE7CAF for ; Fri, 17 Jun 2016 06:34:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 962BE8F8035 for ; Fri, 17 Jun 2016 04:34:45 -0700 (PDT) X-ASG-Debug-ID: 1466163283-04cbb01fec7cb20001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id ywWiZx66wEvTBrGe (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:34:44 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDs2s-0005QI-Ey; Fri, 17 Jun 2016 11:34:42 +0000 Date: Fri, 17 Jun 2016 04:34:42 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 005/119] xfs: check for a valid error_tag in errortag_add Message-ID: <20160617113442.GD19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 005/119] xfs: check for a valid error_tag in errortag_add References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612630452.12839.3528211000490660021.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612630452.12839.3528211000490660021.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466163284 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 474 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Thu, Jun 16, 2016 at 06:18:24PM -0700, Darrick J. Wong wrote: > Currently we don't check the error_tag when someone's trying to set up > error injection testing. If userspace passes in a value we don't know > about, send back an error. This will help xfstests to _notrun a test > that uses error injection to test things like log replay. > > Signed-off-by: Darrick J. Wong Looks fine, Reviewed-by: Christoph Hellwig From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:39:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 8C79C7CD3 for ; Fri, 17 Jun 2016 06:39:38 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5F8A18F8035 for ; Fri, 17 Jun 2016 04:39:38 -0700 (PDT) X-ASG-Debug-ID: 1466163576-04cbb01fec7cd20001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id XFmqbs3OlO77NmSJ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:39:36 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDs7Z-0007JG-9L; Fri, 17 Jun 2016 11:39:33 +0000 Date: Fri, 17 Jun 2016 04:39:33 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, Christoph Hellwig , Dave Chinner Subject: Re: [PATCH 007/119] xfs: rearrange xfs_bmap_add_free parameters Message-ID: <20160617113933.GE19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 007/119] xfs: rearrange xfs_bmap_add_free parameters References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612631720.12839.5804944531874278200.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612631720.12839.5804944531874278200.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466163576 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 220 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Thu, Jun 16, 2016 at 06:18:37PM -0700, Darrick J. Wong wrote: > This is already in xfsprogs' libxfs, so port it to the kernel. Oh well, this is something that should have gone into the kernel at the same time.. From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:41:21 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 33B587CD3 for ; Fri, 17 Jun 2016 06:41:21 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C0B74AC001 for ; Fri, 17 Jun 2016 04:41:20 -0700 (PDT) X-ASG-Debug-ID: 1466163679-04bdf01e10aa210001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id Gg5RVHS8Sx9lxwQ5 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:41:19 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDs9G-0000MJ-0X; Fri, 17 Jun 2016 11:41:18 +0000 Date: Fri, 17 Jun 2016 04:41:17 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE Message-ID: <20160617114117.GF19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612628567.12839.3246258786290141903.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612628567.12839.3246258786290141903.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466163679 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 502 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Thu, Jun 16, 2016 at 06:18:05PM -0700, Darrick J. Wong wrote: > Introduce XFLAGs for the new XFS reflink inode flag and the CoW extent > size hint, and actually plumb the CoW extent size hint into the fsxattr > structure. > > Signed-off-by: Darrick J. Wong Should go behind all the updates that are useful without any new rmap or reflink functionality. In fact it would be great if you could send out a series with just those little fixes and cleanups first. From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:52:09 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E0EE87CEE for ; Fri, 17 Jun 2016 06:52:09 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id A36D230404E for ; Fri, 17 Jun 2016 04:52:09 -0700 (PDT) X-ASG-Debug-ID: 1466164327-04cbb01fee7d060001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id 9Y0LXDzysA1v9YGG (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:52:07 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDsJg-0005Z1-8V; Fri, 17 Jun 2016 11:52:04 +0000 Date: Fri, 17 Jun 2016 04:52:04 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 008/119] xfs: separate freelist fixing into a separate helper Message-ID: <20160617115204.GG19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 008/119] xfs: separate freelist fixing into a separate helper References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612632363.12839.15504324533944246285.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612632363.12839.15504324533944246285.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466164327 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 822 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS > +/* Ensure that the freelist is at full capacity. */ > +int > +xfs_free_extent_fix_freelist( > + struct xfs_trans *tp, > + xfs_agnumber_t agno, > + struct xfs_buf **agbp) > { > - xfs_alloc_arg_t args; > - int error; > + xfs_alloc_arg_t args; Use struct xfs_alloc_arg if you change this anyway. > + int error; > > - ASSERT(len != 0); > memset(&args, 0, sizeof(xfs_alloc_arg_t)); Same here. > - if (args.agbno + len > > - be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) { > - error = -EFSCORRUPTED; > - goto error0; > - } > + XFS_WANT_CORRUPTED_GOTO(mp, > + agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), > + err); This introduces an overly long line. But except for these nitpicks this looks fine: Reviewed-by: Christoph Hellwig From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 06:59:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1D8A87CEE for ; Fri, 17 Jun 2016 06:59:34 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id A6400AC004 for ; Fri, 17 Jun 2016 04:59:33 -0700 (PDT) X-ASG-Debug-ID: 1466164772-04bdf01e17aa650001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id Wj0ixaizj5BbezjP (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 04:59:32 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDsQs-0008Va-Dj; Fri, 17 Jun 2016 11:59:30 +0000 Date: Fri, 17 Jun 2016 04:59:30 -0700 From: Christoph Hellwig To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 009/119] xfs: convert list of extents to free into a regular list Message-ID: <20160617115930.GH19042@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 009/119] xfs: convert list of extents to free into a regular list References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612632997.12839.18026491074892368053.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612632997.12839.18026491074892368053.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466164772 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1517 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.70 X-Barracuda-Spam-Status: No, SCORE=0.70 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS > { > + struct xfs_bmap_free_item *new; /* new element */ > #ifdef DEBUG > xfs_agnumber_t agno; > xfs_agblock_t agbno; > @@ -597,17 +595,7 @@ xfs_bmap_add_free( > new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); > new->xbfi_startblock = bno; > new->xbfi_blockcount = (xfs_extlen_t)len; > + list_add(&new->xbfi_list, &flist->xbf_flist); > flist->xbf_count++; Please kill xbf_count while you're at it, it's entirely superflous. > @@ -617,14 +605,10 @@ xfs_bmap_add_free( > */ > void > xfs_bmap_del_free( > - xfs_bmap_free_t *flist, /* free item list header */ > - xfs_bmap_free_item_t *prev, /* previous item on list, if any */ > - xfs_bmap_free_item_t *free) /* list item to be freed */ > + struct xfs_bmap_free *flist, /* free item list header */ > + struct xfs_bmap_free_item *free) /* list item to be freed */ Which then also gets rid of the flist argument here. > @@ -634,17 +618,16 @@ xfs_bmap_del_free( > */ > void > xfs_bmap_cancel( > + struct xfs_bmap_free *flist) /* list of bmap_free_items */ > { > + struct xfs_bmap_free_item *free; /* free list item */ > > if (flist->xbf_count == 0) > return; > + while (!list_empty(&flist->xbf_flist)) { > + free = list_first_entry(&flist->xbf_flist, > + struct xfs_bmap_free_item, xbfi_list); while ((free = list_first_entry_or_null(...)) > + list_sort((*tp)->t_mountp, &flist->xbf_flist, xfs_bmap_free_list_cmp); Can you add a comment on why we are sorting the list? From hch@lst.de Fri Jun 17 07:01:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A6A1A7CEE for ; Fri, 17 Jun 2016 07:01:52 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 306FBAC002 for ; Fri, 17 Jun 2016 05:01:48 -0700 (PDT) X-ASG-Debug-ID: 1466164905-04bdf01e10aa720001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id otNConbVD6cQeX22 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 05:01:46 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 9183D68C4F; Fri, 17 Jun 2016 14:01:44 +0200 (CEST) Date: Fri, 17 Jun 2016 14:01:44 +0200 From: Christoph Hellwig To: Jan Kara Cc: Christoph Hellwig , xfs@oss.sgi.com, rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: [PATCH 02/14] fs: introduce iomap infrastructure Message-ID: <20160617120144.GA333@lst.de> X-ASG-Orig-Subj: Re: [PATCH 02/14] fs: introduce iomap infrastructure References: <1464792297-13185-1-git-send-email-hch@lst.de> <1464792297-13185-3-git-send-email-hch@lst.de> <20160616161242.GB2106@quack2.suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160616161242.GB2106@quack2.suse.cz> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1466164906 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 187 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30515 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 16, 2016 at 06:12:42PM +0200, Jan Kara wrote: > This is actually in 512-byte units, not in fs blocks as the comment > suggests, right? Indeed, thanks for spotting this! From bfoster@redhat.com Fri Jun 17 07:16:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 3CD357CA6 for ; Fri, 17 Jun 2016 07:16:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0DEE18F8035 for ; Fri, 17 Jun 2016 05:16:08 -0700 (PDT) X-ASG-Debug-ID: 1466165766-04cbb01fed7d970001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id SONsLSlX2AOB8Q9Y (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 05:16:07 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6899B8E3E5; Fri, 17 Jun 2016 12:16:06 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5HCG6Rr004923; Fri, 17 Jun 2016 08:16:06 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 19C88123469; Fri, 17 Jun 2016 08:16:05 -0400 (EDT) Date: Fri, 17 Jun 2016 08:16:05 -0400 From: Brian Foster To: Christoph Hellwig Cc: "Darrick J. Wong" , linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE Message-ID: <20160617121604.GB23661@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612628567.12839.3246258786290141903.stgit@birch.djwong.org> <20160617114117.GF19042@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617114117.GF19042@infradead.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Fri, 17 Jun 2016 12:16:06 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466165767 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1549 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jun 17, 2016 at 04:41:17AM -0700, Christoph Hellwig wrote: > On Thu, Jun 16, 2016 at 06:18:05PM -0700, Darrick J. Wong wrote: > > Introduce XFLAGs for the new XFS reflink inode flag and the CoW extent > > size hint, and actually plumb the CoW extent size hint into the fsxattr > > structure. > > > > Signed-off-by: Darrick J. Wong > > Should go behind all the updates that are useful without any new > rmap or reflink functionality. In fact it would be great if you > could send out a series with just those little fixes and cleanups > first. > I'd take that a step further and suggest the entire series be split into independent feature series, as appropriate. Unless I'm missing something, I don't think there's any reason these all need to be bundled together. Further, my expectation is that they probably end up being merged as independent units, so I think it's easier for everybody for Darrick to carve that up on the logical boundaries rather than assume all reviewers and maintainer are going to do so consistently. Note that I'm not saying this has to be reposted.. I think I can pull off the rmap bits for the time being. I'm just suggesting that if a repost is required from this point forward for any of the logical subunits (deps, rmap, reflink, scrub), I'd suggest to post, version and changelog those units independently. Brian > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 17 10:07:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6C88D7CD2 for ; Fri, 17 Jun 2016 10:07:01 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3CF80304048 for ; Fri, 17 Jun 2016 08:06:58 -0700 (PDT) X-ASG-Debug-ID: 1466176016-04cb6c542767830001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id nNAxiZnZr16SVwAT (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 08:06:56 -0700 (PDT) X-Barracuda-Envelope-From: BATV+70a9152458e4a578216d+4681+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bDvMF-0006sH-1K; Fri, 17 Jun 2016 15:06:55 +0000 Date: Fri, 17 Jun 2016 08:06:55 -0700 From: Christoph Hellwig To: Brian Foster Cc: Christoph Hellwig , linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com, "Darrick J. Wong" Subject: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE Message-ID: <20160617150654.GA21627@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612628567.12839.3246258786290141903.stgit@birch.djwong.org> <20160617114117.GF19042@infradead.org> <20160617121604.GB23661@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617121604.GB23661@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466176016 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 529 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30518 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Fri, Jun 17, 2016 at 08:16:05AM -0400, Brian Foster wrote: > I'd take that a step further and suggest the entire series be split into > independent feature series, as appropriate. Yes, that's what I meant. I just didn't manage to get to the rest yet. > off the rmap bits for the time being. I'm just suggesting that if a > repost is required from this point forward for any of the logical > subunits (deps, rmap, reflink, scrub), I'd suggest to post, version and > changelog those units independently. Agreed. From grace9@offer.com Fri Jun 17 10:52:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_MESSAGE,MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 745557CCA for ; Fri, 17 Jun 2016 10:52:28 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0BA6AAC002 for ; Fri, 17 Jun 2016 08:52:27 -0700 (PDT) X-ASG-Debug-ID: 1466178740-04bdf01e17b0f90001-NocioJ Received: from offer.com ([61.144.196.136]) by cuda.sgi.com with SMTP id OwnWgsQVYczDty2N for ; Fri, 17 Jun 2016 08:52:21 -0700 (PDT) X-Barracuda-Envelope-From: grace9@offer.com X-Barracuda-Effective-Source-IP: UNKNOWN[61.144.196.136] X-Barracuda-Apparent-Source-IP: 61.144.196.136 Received: from DESKTOP-9S5QUR1[127.0.0.1] by DESKTOP-9S5QUR1[127.0.0.1] (SMTPD32); Fri, 17 Jun 2016 23:48:12 +0800 From: "liguoyan2@163.com" Subject: re:pigeon ring,bird ring manufactory directly from china To: xfs@oss.sgi.com X-ASG-Orig-Subj: re:pigeon ring,bird ring manufactory directly from china MIME-Version: 1.0 Sender: grace9@offer.com Reply-To: liguoyan2@163.com Date: Fri, 17 Jun 2016 23:48:12 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline X-Barracuda-Connect: UNKNOWN[61.144.196.136] X-Barracuda-Start-Time: 1466178740 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 727 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.74 X-Barracuda-Spam-Status: No, SCORE=0.74 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, HTML_MESSAGE, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30519 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160617155227.CFFA9A420A0@cuda.sgi.com> PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVU Ri04IiBodHRwLWVxdWl2PWNvbnRlbnQtdHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCAxMS4wMC4xMDU4Ni4wIj48L0hFQUQ+DQo8Qk9EWT4NCjxQPmhpIGRlYXI8L1A+ DQo8UD50aGlzIGlzIGdyYWNlIGxpIGZyb20gR2VzaGlmZW5nIGZhY3RvcnkgaW4gY2hpbmEsIG91 ciBmYWN0b3J5IG1haW5seSBwcm9kdWNlIA0KPC9QPg0KPFA+PFNUUk9ORz5waWdlb24gcmluZyxi aXJkIHJpbmcsIHBpZ2VvbiBjYWdlcywgZHJpbmtlciBhbmQgZmVlZGVyLCB0aGUgcXVhbGl0eSAN CmlzIHRoZSBiZXN0IGFuZCBwcmljZSB2ZXJ5IGNoZWFwZXI8L1NUUk9ORz48L1A+DQo8UD48U1RS T05HPjwvU1RST05HPiZuYnNwOzwvUD4NCjxQPndlY2xvbWUgdG8gcGxhY2UmbmJzcDsgb3JkZXJz PC9QPg0KPFA+VGhhbmtzIGFuZCBiZXN0IHJlZ2FyZHM8L1A+DQo8UD5ncmFjZSBsaSA8L1A+DQo8 UD53ZWNoYXQvbW9iaWxlL3doYXRzYXBwOiAwMDg2LTEzNTEwNzI2NzE2PC9QPg0KPFA+c2t5cGU6 Z3JhY2VfYmVzdG9uZXI8L1A+DQo8UD48U1RST05HPjwvU1RST05HPiZuYnNwOzwvUD4NCjxQPjxT VFJPTkc+PC9TVFJPTkc+Jm5ic3A7PC9QPjwvQk9EWT48L0hUTUw+DQoNCg== From darrick.wong@oracle.com Fri Jun 17 11:40:17 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0D6C17CBA for ; Fri, 17 Jun 2016 11:40:17 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6C5E3AC005 for ; Fri, 17 Jun 2016 09:40:13 -0700 (PDT) X-ASG-Debug-ID: 1466181603-04cbb01fef87210001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id Cit5GIBNw9BPwFZ1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 09:40:03 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5HGdvw0017835 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 16:39:57 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5HGdtfB017238 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 16:39:56 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5HGdsOw028470; Fri, 17 Jun 2016 16:39:54 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 17 Jun 2016 09:39:53 -0700 Date: Fri, 17 Jun 2016 09:39:52 -0700 From: "Darrick J. Wong" To: david@fromorbit.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Subject: [PATCH v2 11/20] xfs: inject errors at various parts of the deferred op completion Message-ID: <20160617163952.GE5740@birch.djwong.org> X-ASG-Orig-Subj: [PATCH v2 11/20] xfs: inject errors at various parts of the deferred op completion References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> <146612803133.25024.1931929844195025512.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612803133.25024.1931929844195025512.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466181603 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 63939 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30520 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Use the error injection mechanism to test log recovery of deferred work. v2: fix the tests to _require_scratch_reflink, since most of the deferred work is done on behalf of reflinky operations. Signed-off-by: Darrick J. Wong --- common/inject | 93 +++++++++++++++++++++++++++++++++++++++++++++ common/log | 28 ++++++++++++++ common/rc | 8 ++++ tests/xfs/857 | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/857.out | 18 +++++++++ tests/xfs/858 | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/858.out | 18 +++++++++ tests/xfs/859 | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/859.out | 18 +++++++++ tests/xfs/860 | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/860.out | 16 ++++++++ tests/xfs/861 | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/861.out | 16 ++++++++ tests/xfs/862 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/862.out | 16 ++++++++ tests/xfs/863 | 93 +++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/863.out | 15 +++++++ tests/xfs/864 | 97 +++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/864.out | 19 +++++++++ tests/xfs/865 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/865.out | 18 +++++++++ tests/xfs/866 | 94 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/866.out | 17 ++++++++ tests/xfs/867 | 97 +++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/867.out | 17 ++++++++ tests/xfs/868 | 94 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/868.out | 17 ++++++++ tests/xfs/869 | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/869.out | 17 ++++++++ tests/xfs/870 | 95 ++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/870.out | 15 +++++++ tests/xfs/871 | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/871.out | 18 +++++++++ tests/xfs/group | 15 +++++++ 34 files changed, 1878 insertions(+) create mode 100644 common/inject create mode 100755 tests/xfs/857 create mode 100644 tests/xfs/857.out create mode 100755 tests/xfs/858 create mode 100644 tests/xfs/858.out create mode 100755 tests/xfs/859 create mode 100644 tests/xfs/859.out create mode 100755 tests/xfs/860 create mode 100644 tests/xfs/860.out create mode 100755 tests/xfs/861 create mode 100644 tests/xfs/861.out create mode 100755 tests/xfs/862 create mode 100644 tests/xfs/862.out create mode 100755 tests/xfs/863 create mode 100644 tests/xfs/863.out create mode 100755 tests/xfs/864 create mode 100644 tests/xfs/864.out create mode 100755 tests/xfs/865 create mode 100644 tests/xfs/865.out create mode 100755 tests/xfs/866 create mode 100644 tests/xfs/866.out create mode 100755 tests/xfs/867 create mode 100644 tests/xfs/867.out create mode 100755 tests/xfs/868 create mode 100644 tests/xfs/868.out create mode 100755 tests/xfs/869 create mode 100644 tests/xfs/869.out create mode 100755 tests/xfs/870 create mode 100644 tests/xfs/870.out create mode 100755 tests/xfs/871 create mode 100644 tests/xfs/871.out diff --git a/common/inject b/common/inject new file mode 100644 index 0000000..e666d6d --- /dev/null +++ b/common/inject @@ -0,0 +1,93 @@ +##/bin/bash +# Routines for injecting errors into filesystems +#----------------------------------------------------------------------- +# Copyright (c) 2016 Oracle. All Rights Reserved. +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +# USA +# +# Contact information: Oracle Corporation, 500 Oracle Parkway, +# Redwood Shores, CA 94065, USA, or: http://www.oracle.com/ +#----------------------------------------------------------------------- +. ./common/log + +# Tests whether $FSTYP is one of the filesystems that supports error injection +_require_error_injection() +{ + case "$FSTYP" in + "xfs") + grep -q 'debug 1' /proc/fs/xfs/stat || \ + _notrun "XFS error injection requires CONFIG_XFS_DEBUG" + ;; + *) + _notrun "Error injection not supported on filesystem type: $FSTYP" + esac +} + +# Requires that xfs_io inject command knows about this error type +_require_xfs_io_error_injection() +{ + type="$1" + _require_error_injection + + # NOTE: We can't actually test error injection here because xfs + # hasn't always range checked the argument to xfs_errortag_add. + # We also don't want to trip an error before we're ready to deal + # with it. + + $XFS_IO_PROG -x -c 'inject' $TEST_DIR | grep -q "$type" || \ + _notrun "XFS error injection $type unknown." +} + +# Inject an error into the test fs +_test_inject_error() +{ + type="$1" + + $XFS_IO_PROG -x -c "inject $type" $TEST_DIR +} + +# Inject an error into the scratch fs +_scratch_inject_error() +{ + type="$1" + + $XFS_IO_PROG -x -c "inject $type" $SCRATCH_MNT +} + +# Unmount and remount the scratch device, dumping the log +_scratch_inject_logprint() +{ + local opts="$1" + + if test -n "$opts"; then + opts="-o $opts" + fi + _scratch_unmount + _scratch_dump_log + _scratch_mount "$opts" +} + +# Unmount and remount the test device, dumping the log +_test_inject_logprint() +{ + local opts="$1" + + if test -n "$opts"; then + opts="-o $opts" + fi + _test_unmount + _test_dump_log + _test_mount "$opts" +} diff --git a/common/log b/common/log index cb687d2..44b9625 100644 --- a/common/log +++ b/common/log @@ -228,6 +228,34 @@ _scratch_f2fs_logstate() echo $? } +_scratch_dump_log() +{ + case "$FSTYP" in + xfs) + _scratch_xfs_logprint + ;; + f2fs) + $DUMP_F2FS_PROG $SCRATCH_DEV + ;; + *) + ;; + esac +} + +_test_dump_log() +{ + case "$FSTYP" in + xfs) + _test_xfs_logprint + ;; + f2fs) + $DUMP_F2FS_PROG $TEST_DEV + ;; + *) + ;; + esac +} + _print_logstate() { case "$FSTYP" in diff --git a/common/rc b/common/rc index 1648a8a..1225047 100644 --- a/common/rc +++ b/common/rc @@ -982,6 +982,14 @@ _scratch_xfs_logprint() $XFS_LOGPRINT_PROG $SCRATCH_OPTIONS $* $SCRATCH_DEV } +_test_xfs_logprint() +{ + TEST_OPTIONS="" + [ "$USE_EXTERNAL" = yes -a ! -z "$TEST_LOGDEV" ] && \ + TEST_OPTIONS="-l$TEST_LOGDEV" + $XFS_LOGPRINT_PROG $TEST_OPTIONS $* $TEST_DEV +} + _scratch_xfs_check() { SCRATCH_OPTIONS="" diff --git a/tests/xfs/857 b/tests/xfs/857 new file mode 100755 index 0000000..eff6e4d --- /dev/null +++ b/tests/xfs/857 @@ -0,0 +1,102 @@ +#! /bin/bash +# FS QA Test No. 857 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during block remap to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "bmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "bmap_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/857.out b/tests/xfs/857.out new file mode 100644 index 0000000..ecc8e04 --- /dev/null +++ b/tests/xfs/857.out @@ -0,0 +1,18 @@ +QA output created by 857 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +1e108771fba35e2f2961d1ad23efbff7 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/858 b/tests/xfs/858 new file mode 100755 index 0000000..c13733a --- /dev/null +++ b/tests/xfs/858 @@ -0,0 +1,102 @@ +#! /bin/bash +# FS QA Test No. 858 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during refcount updates to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "refcount_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/858.out b/tests/xfs/858.out new file mode 100644 index 0000000..f5302de --- /dev/null +++ b/tests/xfs/858.out @@ -0,0 +1,18 @@ +QA output created by 858 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/859 b/tests/xfs/859 new file mode 100755 index 0000000..96c3390 --- /dev/null +++ b/tests/xfs/859 @@ -0,0 +1,106 @@ +#! /bin/bash +# FS QA Test No. 859 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during rmap updates to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_error_injection +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +test $is_rmap -gt 0 || _notrun "rmap not supported on scratch fs" + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "rmap_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/859.out b/tests/xfs/859.out new file mode 100644 index 0000000..b83e963 --- /dev/null +++ b/tests/xfs/859.out @@ -0,0 +1,18 @@ +QA output created by 859 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/860 b/tests/xfs/860 new file mode 100755 index 0000000..cec7509 --- /dev/null +++ b/tests/xfs/860 @@ -0,0 +1,99 @@ +#! /bin/bash +# FS QA Test No. 860 +# +# Reflink a file with a few dozen extents and CoW a few blocks. +# Inject an error during extent freeing to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_error_injection +_require_xfs_io_error_injection "free_extent" + +rm -f $seqres.full + +blksz=65536 +blks=4 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +$XFS_IO_PROG -c "cowextsize $sz" $SCRATCH_MNT + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_pwrite_byte 0x66 $((sz / 2)) $((sz / 2)) $SCRATCH_MNT/file2 >> $seqres.full +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file2 0 $((sz / 2)) >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz 0 $sz" $SCRATCH_MNT/file1 >> $seqres.full +sync + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/860.out b/tests/xfs/860.out new file mode 100644 index 0000000..0a6d763 --- /dev/null +++ b/tests/xfs/860.out @@ -0,0 +1,16 @@ +QA output created by 860 +Format filesystem +Create files +Check files +cf41e243bf211225660f3fabe6db9eb6 SCRATCH_MNT/file1 +cf41e243bf211225660f3fabe6db9eb6 SCRATCH_MNT/file2 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +fe9070b9c9deb97ed53811efda5c4ad5 SCRATCH_MNT/file1 +cf41e243bf211225660f3fabe6db9eb6 SCRATCH_MNT/file2 +Done diff --git a/tests/xfs/861 b/tests/xfs/861 new file mode 100755 index 0000000..49d90bc --- /dev/null +++ b/tests/xfs/861 @@ -0,0 +1,100 @@ +#! /bin/bash +# FS QA Test No. 861 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Force XFS into "two refcount updates per transaction" mode. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_error_injection +_require_xfs_io_error_injection "refcount_continue_update" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_continue_update" + +echo "CoW all the blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz 0 $((blks * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/861.out b/tests/xfs/861.out new file mode 100644 index 0000000..d353526 --- /dev/null +++ b/tests/xfs/861.out @@ -0,0 +1,16 @@ +QA output created by 861 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW all the blocks +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/862 b/tests/xfs/862 new file mode 100755 index 0000000..167386c --- /dev/null +++ b/tests/xfs/862 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 862 +# +# Simulate rmap update errors with a file write and a file remove. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +test $is_rmap -gt 0 || _notrun "rmap not supported on scratch fs" + +echo "Create files" +touch $SCRATCH_MNT/file1 +_pwrite_byte 0x67 0 $sz $SCRATCH_MNT/file0 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file0 | _filter_scratch +md5sum $SCRATCH_MNT/file1 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "rmap_finish_one" + +echo "Write files" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz 0 $sz" $SCRATCH_MNT/file1 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file0 | _filter_scratch +md5sum $SCRATCH_MNT/file1 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/862.out b/tests/xfs/862.out new file mode 100644 index 0000000..1f6b47b --- /dev/null +++ b/tests/xfs/862.out @@ -0,0 +1,16 @@ +QA output created by 862 +Format filesystem +Create files +Check files +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file0 +d41d8cd98f00b204e9800998ecf8427e SCRATCH_MNT/file1 +Inject error +Write files +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file0 +d41d8cd98f00b204e9800998ecf8427e SCRATCH_MNT/file1 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/863 b/tests/xfs/863 new file mode 100755 index 0000000..5069245 --- /dev/null +++ b/tests/xfs/863 @@ -0,0 +1,93 @@ +#! /bin/bash +# FS QA Test No. 863 +# +# Simulate free extent errors with a file write and a file remove. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_scratch +_require_error_injection +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +touch $SCRATCH_MNT/file1 + +echo "Write files" +$XFS_IO_PROG -c "pwrite -S 0x67 0 $sz" $SCRATCH_MNT/file1 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 2>&1 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "Remove files" +rm -rf $SCRATCH_MNT/file1 +sync + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 2>&1 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/863.out b/tests/xfs/863.out new file mode 100644 index 0000000..718691f --- /dev/null +++ b/tests/xfs/863.out @@ -0,0 +1,15 @@ +QA output created by 863 +Format filesystem +Create files +Write files +Check files +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file1 +Inject error +Remove files +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +md5sum: SCRATCH_MNT/file1: No such file or directory +FS should be online, touch should succeed +Done diff --git a/tests/xfs/864 b/tests/xfs/864 new file mode 100755 index 0000000..928bd3b --- /dev/null +++ b/tests/xfs/864 @@ -0,0 +1,97 @@ +#! /bin/bash +# FS QA Test No. 864 +# +# Reflink a file. +# Inject an error during block remap to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "bmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_pwrite_byte 0x67 0 $sz $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "bmap_finish_one" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/864.out b/tests/xfs/864.out new file mode 100644 index 0000000..cd16235 --- /dev/null +++ b/tests/xfs/864.out @@ -0,0 +1,19 @@ +QA output created by 864 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/865 b/tests/xfs/865 new file mode 100755 index 0000000..043ce77 --- /dev/null +++ b/tests/xfs/865 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 865 +# +# Reflink a file. +# Inject an error during block remap to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "bmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks - 17)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "bmap_finish_one" + +echo "Try to reflink" +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 2>&1 | _filter_scratch + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/865.out b/tests/xfs/865.out new file mode 100644 index 0000000..9a2b04d --- /dev/null +++ b/tests/xfs/865.out @@ -0,0 +1,18 @@ +QA output created by 865 +Format filesystem +Create files +Check files +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file1 +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file2 +Inject error +Try to reflink +cp: failed to clone 'SCRATCH_MNT/file3' from 'SCRATCH_MNT/file1': Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file1 +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file2 +a98e7df2a7a456009a493e47411c58d1 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/866 b/tests/xfs/866 new file mode 100755 index 0000000..e4137a5 --- /dev/null +++ b/tests/xfs/866 @@ -0,0 +1,94 @@ +#! /bin/bash +# FS QA Test No. 866 +# +# Reflink a file. +# Inject an error during refcount update to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "refcount_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +$XFS_IO_PROG -f -c "truncate $sz" $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_finish_one" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/866.out b/tests/xfs/866.out new file mode 100644 index 0000000..f2ca58c --- /dev/null +++ b/tests/xfs/866.out @@ -0,0 +1,17 @@ +QA output created by 866 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +b5cfa9d6c8febd618f91ac2843d50a1c SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/867 b/tests/xfs/867 new file mode 100755 index 0000000..fcae947 --- /dev/null +++ b/tests/xfs/867 @@ -0,0 +1,97 @@ +#! /bin/bash +# FS QA Test No. 867 +# +# Reflink a file. +# Inject an error during rmap update to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "rmap_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +is_rmap=$(xfs_info $SCRATCH_MNT | grep -c "rmapbt=1") +test $is_rmap -gt 0 || _notrun "rmap not supported on scratch fs" + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +$XFS_IO_PROG -f -c "truncate $sz" $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "rmap_finish_one" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/867.out b/tests/xfs/867.out new file mode 100644 index 0000000..78a4e5a --- /dev/null +++ b/tests/xfs/867.out @@ -0,0 +1,17 @@ +QA output created by 867 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +b5cfa9d6c8febd618f91ac2843d50a1c SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/868 b/tests/xfs/868 new file mode 100755 index 0000000..b8303de --- /dev/null +++ b/tests/xfs/868 @@ -0,0 +1,94 @@ +#! /bin/bash +# FS QA Test No. 868 +# +# Reflink a file. +# Inject an error during extent free to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "free_extent" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_pwrite_byte 0x67 0 $sz $SCRATCH_MNT/file3 >> $seqres.full +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "Try to reflink" +_reflink_range $SCRATCH_MNT/file1 0 $SCRATCH_MNT/file3 0 $sz >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/868.out b/tests/xfs/868.out new file mode 100644 index 0000000..583b1f9 --- /dev/null +++ b/tests/xfs/868.out @@ -0,0 +1,17 @@ +QA output created by 868 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +4155b81ac6d45c0182fa2bc03960f230 SCRATCH_MNT/file3 +Inject error +Try to reflink +XFS_IOC_CLONE_RANGE: Input/output error +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file3 +FS should be online, touch should succeed +Done diff --git a/tests/xfs/869 b/tests/xfs/869 new file mode 100755 index 0000000..3ab2b0d --- /dev/null +++ b/tests/xfs/869 @@ -0,0 +1,101 @@ +#! /bin/bash +# FS QA Test No. 869 +# +# Reflink a file with a few dozen extents. +# Force XFS into "two refcount updates per transaction" mode. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_error_injection +_require_xfs_io_error_injection "refcount_continue_update" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "refcount_continue_update" + +echo "Reflink all the blocks" +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file4 + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch +md5sum $SCRATCH_MNT/file4 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/869.out b/tests/xfs/869.out new file mode 100644 index 0000000..1e7822e --- /dev/null +++ b/tests/xfs/869.out @@ -0,0 +1,17 @@ +QA output created by 869 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +Reflink all the blocks +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file4 +Done diff --git a/tests/xfs/870 b/tests/xfs/870 new file mode 100755 index 0000000..270e4a3 --- /dev/null +++ b/tests/xfs/870 @@ -0,0 +1,95 @@ +#! /bin/bash +# FS QA Test No. 870 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during extent freeing to test log recovery. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_error_injection +_require_xfs_io_error_injection "free_extent" + +rm -f $seqres.full + +blksz=65536 +blks=30 +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 $((blksz * blks)) $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Inject error" +_scratch_inject_error "free_extent" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full +rm $SCRATCH_MNT/file1 +sync + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file2 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/870.out b/tests/xfs/870.out new file mode 100644 index 0000000..49c4e4b --- /dev/null +++ b/tests/xfs/870.out @@ -0,0 +1,15 @@ +QA output created by 870 +Format filesystem +Create files +Check files +d5a0ed0305c8df4180cb2bf975ecffe8 SCRATCH_MNT/file1 +d5a0ed0305c8df4180cb2bf975ecffe8 SCRATCH_MNT/file2 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +7629bd70d19d7291b448221ac44b26d9 SCRATCH_MNT/file2 +Done diff --git a/tests/xfs/871 b/tests/xfs/871 new file mode 100755 index 0000000..03fa0ba --- /dev/null +++ b/tests/xfs/871 @@ -0,0 +1,109 @@ +#! /bin/bash +# FS QA Test No. 871 +# +# Reflink a file with a few dozen extents, CoW a few blocks, and rm. +# Inject an error during refcount updates to test log recovery. Use +# cowextsize so that the refcount failure is somewhere in the CoW remap +# instead of when we're stashing the CoW orphan record. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink +. ./common/inject + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink +_require_xfs_io_error_injection "refcount_finish_one" + +rm -f $seqres.full + +blksz=65536 +blks=64 +sz=$((blksz * blks)) +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +$XFS_IO_PROG -c "cowextsize $sz" $SCRATCH_MNT + +echo "Create files" +_pwrite_byte 0x66 0 $sz $SCRATCH_MNT/file1 >> $seqres.full +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file2 +_cp_reflink $SCRATCH_MNT/file1 $SCRATCH_MNT/file3 + +# Punch holes in file3 +seq 1 2 $blks | while read off; do + $XFS_IO_PROG -c "fpunch $((off * blksz)) $blksz" $SCRATCH_MNT/file3 >> $seqres.full +done +sync + +echo "Check files" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +$XFS_IO_PROG -c "pwrite -W -S 0x67 $((10 * blksz)) 1" $SCRATCH_MNT/file2 >> $seqres.full +sync + +echo "Inject error" +_scratch_inject_error "refcount_finish_one" + +echo "CoW a few blocks" +$XFS_IO_PROG -c "pwrite -W -S 0x67 -b $sz $((10 * blksz)) $((10 * blksz))" $SCRATCH_MNT/file2 >> $seqres.full + +echo "FS should be shut down, touch will fail" +touch $SCRATCH_MNT/badfs 2>&1 | _filter_scratch + +echo "Remount to replay log" +_scratch_inject_logprint >> $seqres.full + +echo "FS should be online, touch should succeed" +touch $SCRATCH_MNT/goodfs + +echo "Check files again" +md5sum $SCRATCH_MNT/file1 | _filter_scratch +md5sum $SCRATCH_MNT/file2 | _filter_scratch +md5sum $SCRATCH_MNT/file3 | _filter_scratch + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/871.out b/tests/xfs/871.out new file mode 100644 index 0000000..c0aba73 --- /dev/null +++ b/tests/xfs/871.out @@ -0,0 +1,18 @@ +QA output created by 871 +Format filesystem +Create files +Check files +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Inject error +CoW a few blocks +FS should be shut down, touch will fail +touch: cannot touch 'SCRATCH_MNT/badfs': Input/output error +Remount to replay log +FS should be online, touch should succeed +Check files again +2a4f043bf9730a9e8882c9264b9797b3 SCRATCH_MNT/file1 +1e108771fba35e2f2961d1ad23efbff7 SCRATCH_MNT/file2 +153498e22f8ff52d7f60b466a5e65285 SCRATCH_MNT/file3 +Done diff --git a/tests/xfs/group b/tests/xfs/group index 1ad37ff..0f94794 100644 --- a/tests/xfs/group +++ b/tests/xfs/group @@ -289,3 +289,18 @@ 854 auto quick clone 855 auto clone 856 auto quick clone rmap +857 auto quick clone +858 auto quick clone +859 auto quick clone +860 auto quick clone +861 auto quick clone +862 auto quick rmap +863 auto quick rw +864 auto quick clone +865 auto quick clone +866 auto quick clone +867 auto quick clone +868 auto quick clone +869 auto quick clone +870 auto quick clone +871 auto quick clone From darrick.wong@oracle.com Fri Jun 17 11:40:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id DC7FA7CBA for ; Fri, 17 Jun 2016 11:40:40 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9E0728F8049 for ; Fri, 17 Jun 2016 09:40:37 -0700 (PDT) X-ASG-Debug-ID: 1466181635-04bdf01e17b23f0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 1CXaA7ncoFMGHVwH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 09:40:35 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5HGeUGK018538 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 16:40:31 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5HGeUvn019178 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 16:40:30 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5HGeRUf022942; Fri, 17 Jun 2016 16:40:28 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 17 Jun 2016 09:40:27 -0700 Date: Fri, 17 Jun 2016 09:40:25 -0700 From: "Darrick J. Wong" To: david@fromorbit.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Subject: [PATCH v2 14/20] xfs: test clearing reflink inode flag Message-ID: <20160617164025.GF5740@birch.djwong.org> X-ASG-Orig-Subj: [PATCH v2 14/20] xfs: test clearing reflink inode flag References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> <146612805032.25024.3244105391915486280.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612805032.25024.3244105391915486280.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466181635 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4341 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30520 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Check that xfs_repair can clear the reflink inode flag. v2: This is a reflink test; use _require_scratch_reflink Signed-off-by: Darrick J. Wong --- tests/xfs/872 | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/xfs/872.out | 20 +++++++++++ tests/xfs/group | 1 + 3 files changed, 114 insertions(+) create mode 100755 tests/xfs/872 create mode 100644 tests/xfs/872.out diff --git a/tests/xfs/872 b/tests/xfs/872 new file mode 100755 index 0000000..e4c987e --- /dev/null +++ b/tests/xfs/872 @@ -0,0 +1,93 @@ +#! /bin/bash +# FS QA Test No. 872 +# +# Create 100 reflinked files, CoW them all, and see if xfs_repair will +# clear the reflink flag. There was a buffer handling bug in xfs_repair +# that (fortunately) triggered asserts in the rmap code when clearing +# the reflink flag. +# +#----------------------------------------------------------------------- +# Copyright (c) 2016, Oracle and/or its affiliates. All Rights Reserved. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it would be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +#----------------------------------------------------------------------- + +seq=`basename $0` +seqres=$RESULT_DIR/$seq +echo "QA output created by $seq" + +here=`pwd` +tmp=/tmp/$$ +status=1 # failure is the default! +trap "_cleanup; exit \$status" 0 1 2 3 15 + +_cleanup() +{ + cd / + umount $SCRATCH_MNT > /dev/null 2>&1 + rm -rf $tmp.* +} + +# get standard environment, filters and checks +. ./common/rc +. ./common/filter +. ./common/reflink + +# real QA test starts here +_supported_os Linux +_supported_fs xfs +_require_cp_reflink +_require_scratch_reflink + +rm -f $seqres.full + +nr=128 # spanning at least one inode chunk tickles a bug in xfs_repair +echo "Format filesystem" +_scratch_mkfs >/dev/null 2>&1 +_scratch_mount >> $seqres.full + +echo "Create files" +_pwrite_byte 0x66 0 1 $SCRATCH_MNT/file.0 >> $seqres.full +seq 1 $nr | while read i; do + _cp_reflink $SCRATCH_MNT/file.0 $SCRATCH_MNT/file.$i +done +sync + +echo "Check files" +for i in 0 $((nr / 2)) $nr; do + md5sum $SCRATCH_MNT/file.$i | _filter_scratch + $XFS_IO_PROG -c 'lsattr -v' $SCRATCH_MNT/file.$i | _filter_scratch +done + +echo "CoW all files" +seq 1 $nr | while read i; do + echo m >> $SCRATCH_MNT/file.$i +done + +echo "Repair filesystem" +_scratch_unmount +_repair_scratch_fs >> $seqres.full +_scratch_mount + +echo "Check files again" +for i in 0 $((nr / 2)) $nr; do + md5sum $SCRATCH_MNT/file.$i | _filter_scratch + $XFS_IO_PROG -c 'lsattr -v' $SCRATCH_MNT/file.$i | _filter_scratch +done + +echo "Done" + +# success, all done +status=0 +exit diff --git a/tests/xfs/872.out b/tests/xfs/872.out new file mode 100644 index 0000000..316cb0a --- /dev/null +++ b/tests/xfs/872.out @@ -0,0 +1,20 @@ +QA output created by 872 +Format filesystem +Create files +Check files +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.0 +[reflink] SCRATCH_MNT/file.0 +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.64 +[reflink] SCRATCH_MNT/file.64 +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.128 +[reflink] SCRATCH_MNT/file.128 +CoW all files +Repair filesystem +Check files again +8fa14cdd754f91cc6554c9e71929cce7 SCRATCH_MNT/file.0 +[] SCRATCH_MNT/file.0 +0f17fd72b7bbf5bda0ff433e6d1fc118 SCRATCH_MNT/file.64 +[] SCRATCH_MNT/file.64 +0f17fd72b7bbf5bda0ff433e6d1fc118 SCRATCH_MNT/file.128 +[] SCRATCH_MNT/file.128 +Done diff --git a/tests/xfs/group b/tests/xfs/group index 0f94794..ca36ad6 100644 --- a/tests/xfs/group +++ b/tests/xfs/group @@ -304,3 +304,4 @@ 869 auto quick clone 870 auto quick clone 871 auto quick clone +872 auto quick clone From sandeen@redhat.com Fri Jun 17 11:44:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 56D457CBA for ; Fri, 17 Jun 2016 11:44:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id D07FEAC001 for ; Fri, 17 Jun 2016 09:44:47 -0700 (PDT) X-ASG-Debug-ID: 1466181885-04cbb01fec873d0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id rhMRusR7GplLepdN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 09:44:46 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 45B948EB3C for ; Fri, 17 Jun 2016 16:44:45 +0000 (UTC) Received: from [IPv6:::1] (ovpn03.gateway.prod.ext.phx2.redhat.com [10.5.9.3]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5HGiiq2000615 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 17 Jun 2016 12:44:45 -0400 To: xfs-oss From: Eric Sandeen Subject: [PATCH] xfs_copy: fix minor sparse endian nit Message-ID: X-ASG-Orig-Subj: [PATCH] xfs_copy: fix minor sparse endian nit Date: Fri, 17 Jun 2016 11:44:44 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 17 Jun 2016 16:44:45 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466181886 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 644 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 The intermediate variable should not have been endian-annotated; it is the local cpu representation not the on-disk representation. Signed-off-by: Eric Sandeen --- diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c index 2119a0b..1bc5163 100644 --- a/copy/xfs_copy.c +++ b/copy/xfs_copy.c @@ -506,7 +506,7 @@ sb_update_uuid( */ if (!uuid_equal(&tcarg->uuid, &ag_hdr->xfs_sb->sb_uuid) && xfs_sb_version_hascrc(sb) && !xfs_sb_version_hasmetauuid(sb)) { - __be32 feat; + __uint32_t feat; feat = be32_to_cpu(ag_hdr->xfs_sb->sb_features_incompat); feat |= XFS_SB_FEAT_INCOMPAT_META_UUID; From darrick.wong@oracle.com Fri Jun 17 11:54:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 95C597CBA for ; Fri, 17 Jun 2016 11:54:33 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 65B918F8037 for ; Fri, 17 Jun 2016 09:54:33 -0700 (PDT) X-ASG-Debug-ID: 1466182470-04cbb01fed877d0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id mJDMa1Um3f7dA2sm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 09:54:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5HGs5Wd001962 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 17 Jun 2016 16:54:05 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5HGs449018201 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 16:54:05 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5HGs10f028586; Fri, 17 Jun 2016 16:54:03 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 17 Jun 2016 09:54:01 -0700 Date: Fri, 17 Jun 2016 09:54:00 -0700 From: "Darrick J. Wong" To: Brian Foster Cc: Christoph Hellwig , linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE Message-ID: <20160617165400.GC6376@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612628567.12839.3246258786290141903.stgit@birch.djwong.org> <20160617114117.GF19042@infradead.org> <20160617121604.GB23661@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617121604.GB23661@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466182470 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2848 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30522 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 17, 2016 at 08:16:05AM -0400, Brian Foster wrote: > On Fri, Jun 17, 2016 at 04:41:17AM -0700, Christoph Hellwig wrote: > > On Thu, Jun 16, 2016 at 06:18:05PM -0700, Darrick J. Wong wrote: > > > Introduce XFLAGs for the new XFS reflink inode flag and the CoW extent > > > size hint, and actually plumb the CoW extent size hint into the fsxattr > > > structure. > > > > > > Signed-off-by: Darrick J. Wong > > > > Should go behind all the updates that are useful without any new > > rmap or reflink functionality. In fact it would be great if you > > could send out a series with just those little fixes and cleanups > > first. > > > > I'd take that a step further and suggest the entire series be split into > independent feature series, as appropriate. Unless I'm missing > something, I don't think there's any reason these all need to be bundled > together. Further, my expectation is that they probably end up being > merged as independent units, so I think it's easier for everybody for > Darrick to carve that up on the logical boundaries rather than assume > all reviewers and maintainer are going to do so consistently. > > Note that I'm not saying this has to be reposted.. I think I can pull > off the rmap bits for the time being. I'm just suggesting that if a > repost is required from this point forward for any of the logical > subunits (deps, rmap, reflink, scrub), I'd suggest to post, version and > changelog those units independently. I'd thought about continuing my old practice of listing which patches go with which feature... but then got lazy. :( Cleanups/rmap/reflink/scrub actually are in their own contiguous sections of the patchbomb, though that isn't obvious from looking at it. You ought to be able to pull only as far as the end of the rmap series and still have a working XFS. I only did the intensive testing with the full patchset, but the quick xfstests group ran fine with just the rmap pieces. Kernel patches: =============== Cleanups, 1-11 rmap + dependencies, 12-49 Overlapped interval btree, 12-15 Deferred operations, 16-22 rmap, 23-49 reflink + dependencies, 50-111 AG reservations, 50-52 refcount btree, 53-68 deferred remap, 69-73 cow, 74-88 reflink, 89-111 getfsmapx, 112 scrub, 113-119 xfsprogs: ========= Cleanups, 1-15 rmap + deps, 16-70 Overlapped interval btree, 16-19 Deferred operations, 20-27 rmap, 28-70 reflink + dependencies, 71-135 AG reservations, 71-72 refcount btree, 73-85 deferred remap, 86-90 reflink, 91-135 getfsmapx, 136-138 scrub, 139-145 --D > > Brian > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From info@viestemarina.com Fri Jun 17 12:01:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE, T_KHOP_FOREIGN_CLICK autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 056607CBA for ; Fri, 17 Jun 2016 12:01:38 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 7F894AC007 for ; Fri, 17 Jun 2016 10:01:34 -0700 (PDT) X-ASG-Debug-ID: 1466182886-04bdf01e13b3630001-NocioJ Received: from imp.mgm.tiscali.it (smtp-out-1-sh.mgm.tiscali.com [213.205.37.11]) by cuda.sgi.com with ESMTP id BUJLP9lY7pdIcLKY for ; Fri, 17 Jun 2016 10:01:26 -0700 (PDT) X-Barracuda-Envelope-From: info@viestemarina.com X-Barracuda-Effective-Source-IP: smtp-out-1-sh.mgm.tiscali.com[213.205.37.11] X-Barracuda-Apparent-Source-IP: 213.205.37.11 Received: from host197-30-dynamic.52-79-r.retail.telecomitalia.it ([79.52.30.197]) by smtp-out-1.mgm.tiscali.com with id 7t1H1t00B4FAcPj01t1H5l; Fri, 17 Jun 2016 19:01:26 +0200 x-auth-user: info@viestemarina.com From: "Camping Village Vieste Marina" Subject: Vacanze Low Cost 2016 To: "xfs" X-ASG-Orig-Subj: Vacanze Low Cost 2016 Content-Type: multipart/related; boundary="rPu1PusGJaR2H3wT9yaaJ=_oALXqJgROTh" MIME-Version: 1.0 Organization: Camping Village Vieste Marina Date: Fri, 17 Jun 2016 19:01:26 +0200 X-Barracuda-Connect: smtp-out-1-sh.mgm.tiscali.com[213.205.37.11] X-Barracuda-Start-Time: 1466182886 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4770 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.14 X-Barracuda-Spam-Status: No, SCORE=0.14 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE, MISSING_MID X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30522 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 HTML_MESSAGE BODY: HTML included in message Message-Id: <20160617170134.24D93A420A0@cuda.sgi.com> This is a multi-part message in MIME format --rPu1PusGJaR2H3wT9yaaJ=_oALXqJgROTh Content-Type: multipart/alternative; boundary="uIalae1wE8CDi=_dCqh69GFg8NMEdOaTWt" --uIalae1wE8CDi=_dCqh69GFg8NMEdOaTWt Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Se non visualizzi correttamente la newsletter clicca qui =20 E' ritornata la FORMULA ANTICRISI Non rinunciate alle vostre vacanze. Anche per l'estate 2016 Vi proponiamo il nostro LOW COST =20 Contattateci telefonicamente ai numeri del VILLAGGIO VIESTE MARINA=20 0884706471 e-mail: viestemarina@tiscali.it =20 OFFERTA GIUGNO - LUGLIO - SETTEMBRE --uIalae1wE8CDi=_dCqh69GFg8NMEdOaTWt Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Vacanze Low Cost 2016
Se non visu= alizzi correttamente la newsletter clicca qui<= /font>
 
E' ritornata la FORMULA ANTICRISI

Non r= inunciate alle vostre vacanze.

Anche per l'estate 2016 Vi = proponiamo il nostro LOW COST

<= /span> 3D""

<= /span>

Contattateci telefonicamente ai numeri del VILLAGGIO VIESTE MARINA

= 0884706471

= e-mail: viest= emarina@tiscali.it

 

 OFFER= TA GIUGNO - LUGLIO - SETTEMBRE


3D""

3D""

--uIalae1wE8CDi=_dCqh69GFg8NMEdOaTWt-- --rPu1PusGJaR2H3wT9yaaJ=_oALXqJgROTh Content-Type: image/jpeg; name="viestemarina.jpg" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="viestemarina.jpg" Content-ID: <015522113@17062016-2880> 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 --rPu1PusGJaR2H3wT9yaaJ=_oALXqJgROTh Content-Type: image/jpeg; name="prezzicasevacanze.jpg" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="prezzicasevacanze.jpg" Content-ID: <015522113@17062016-2887> /9j/4AAQSkZJRgABAgEBLAEsAAD/4SDKRXhpZgAATU0AKgAAAAgABwESAAMAAAABAAEAAAEaAAUA AAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAExAAIAAAAUAAAAcgEyAAIAAAAUAAAAhodp AAQAAAABAAAAnAAAAMgAAAEsAAAAAQAAASwAAAABQWRvYmUgUGhvdG9zaG9wIDcuMAAyMDE2OjA2 OjE1IDE5OjQzOjI3AAAAAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAmOgAwAEAAAAAQAAAoEAAAAA AAAABgEDAAMAAAABAAYAAAEaAAUAAAABAAABFgEbAAUAAAABAAABHgEoAAMAAAABAAIAAAIBAAQA AAABAAABJgICAAQAAAABAAAfnAAAAAAAAABIAAAAAQAAAEgAAAAB/9j/4AAQSkZJRgABAgEASABI AAD/7QAMQWRvYmVfQ00AAf/uAA5BZG9iZQBkgAAAAAH/2wCEAAwICAgJCAwJCQwRCwoLERUPDAwP FRgTExUTExgRDAwMDAwMEQwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwBDQsLDQ4NEA4OEBQO Dg4UFA4ODg4UEQwMDAwMEREMDAwMDAwRDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDP/AABEI AIAAegMBIgACEQEDEQH/3QAEAAj/xAE/AAABBQEBAQEBAQAAAAAAAAADAAECBAUGBwgJCgsBAAEF AQEBAQEBAAAAAAAAAAEAAgMEBQYHCAkKCxAAAQQBAwIEAgUHBggFAwwzAQACEQMEIRIxBUFRYRMi cYEyBhSRobFCIyQVUsFiMzRygtFDByWSU/Dh8WNzNRaisoMmRJNUZEXCo3Q2F9JV4mXys4TD03Xj 80YnlKSFtJXE1OT0pbXF1eX1VmZ2hpamtsbW5vY3R1dnd4eXp7fH1+f3EQACAgECBAQDBAUGBwcG BTUBAAIRAyExEgRBUWFxIhMFMoGRFKGxQiPBUtHwMyRi4XKCkkNTFWNzNPElBhaisoMHJjXC0kST VKMXZEVVNnRl4vKzhMPTdePzRpSkhbSVxNTk9KW1xdXl9VZmdoaWprbG1ub2JzdHV2d3h5ent8f/ 2gAMAwEAAhEDEQA/APTL86ii413XVUe0FvqOAJklum5zFA9SwhE5mOJMD3t5DvRj+c/0zvS/4z2K l1ZmA/MIy8IZZ9Ostca32QGvfbt/RVXbf0lbP+NQKh05pFVWHY36UMb9pDTAvusMejsdv9fI/wCN su/4lPHBWvFf4I9V9HVfn4lbi2zLoY5pLSHOAII27m6v/ls/z07M7GsE15VDxMS1wOsOd2f+6x6y XHpgysi84JdkWu25FjW3uk1va36Xobdrba2fQ/8APSHk4HRchgycjpgeLyWai/cTa8bm2Vinc3db is3b/wD0akBj6mX2BXq8Hd+017/T9ereZ9sidDtPt3/vOVS/reFjv2W2ncWiwenTba0tP0XNfS17 Hbmqni9J6Zfa/Lo6cxtwtLnWufbVZ6hA3vHqVst98/pf9Jb/ADn6VYeT17pzb8nEbj5FLcN32Z7a 830GAVTQz0W763f4P81v/giBlhjXFKVHw6/85lw8vzGfiGKHGY6nXYbf1XrMvquLhiciwgRMspts HO36VLXt/so/rgNBfbWydROmnZ2rlxuZ9asLLJttouriqYqz21+2RZ7aq7W7rvZ9D+dW1TldO6vh 45yMWiz7RT6jKch+94q3elus/RWfSe/b9L/0YmxyYpUIkk/pf2Ls3KczhHFlx8MSeGJv9L/Bdp9o YYfbW346f9+UG5Etl9lbNTofAEsDvpfnLKtt6NmCk3Y2Hd9oHpY++TvDvTt2V7sf6P6SqxK+vpro Zm4mK6xlT4a924tors2f6B36Gt7q9qdUdNT46MGvg6WVTXeA23IdXA09Kx1R93mx/wDJ9qr04zdl xdn3fp3uI3WN9o9SwsFHtGyv9JtZ/wAGyn9I9VDb0W00vNOG/wBTbTT75kja9lQHo/TZ6tbv5CyM v6x9Gqz8nHyum1vuxHek+x72QWtfNTaw5u93pu27P0f6FNlLHGjKRF+DLh5fPnJjihxmI4iB+78r 0L+nN2VVv6jkD0w4uPqhrrN4DGvtc0D6G39F6XpM9RQx+mCkh56llEsdJFlocCAXNa14e36Fm5v/ AIGsHI+tfRLy3Iu6dRdZW3c2bai8Afp/bvA938j+c9RA/wCeXQ85zrrulte6ofTufWDt3bmNZu97 9rx+Z/NpnvYdLn+DYHwzniCRglo9I7pJAIPV8tpI3E+pXOsN3t3Vbf6v5it7Xf6Z/wBH0fpDj/uT x/O/y/oLlcj6z9EveMm/ptFtgbIJupLg1u6/v+d9P2fT9T9H+ejf8+8P/uFZ/Nev9Jn0P9Hx9FH3 sP7/AOCP9G87/mT9of/Q6z60N6g7qFfoWeliCkDJskAtJNoq2y6v3O/Sfn/+CLLcOrOrDbspprdF oADHguL31epX7ve3c2t/5n/gS6Lql4q6m1jraqm2Ut3my6yl21rnu3VGotrd/L9R1aB67zUwHIx2 10nR4zb9PcwW+rduZ9p/SOdXX6z0vZ4teMi+nFX4M8OZ4YiPs4ZV+lPHxTl+l6pcTj437SdbjV51 7P2bDjcd7Q5rS138y+vc9zfYz1P/AEWtos6HTuBy7mbJcQS785orfzV7t1f+u9DN7LHgMyKTZa4i loz8gBwHqOftDXfS3NZt2ez+e/0Sm17GZBryMipnua2xrc642CQPRayqywbLbLNn/Gf204YjEH1c XX1SBWZcvuEH24Y6FVijwR85fMytwui49rRbl3MtDQRNjidtbnMafoH2ssL1Cr6p9EvtPUqnXi7J cbjc2wtJL3erv2hrdvu9+3YtJuBS125oypmdciwjU7+HX7eyp/8AOrpQuvoHqvsxnvZcG1khrmuc 13u+j9JRy4NOOvDiX4PvPq+7+5t6/a4vl/r8DC36ndJuYa7nX2MeZc11pMmd3h+97ldw+l14uPVR j3WsroBZUP0bi1s/R3vqc/8ANVV31r6Uxhsc28Ma3eT6LtGf6T+or2Fn0ZWLVk0BzqrgX1kw0lpd zte4OSj7d+nhv+r2XZxzfAPe93g4tPc4+Dj/AML9NTem1sPssc2SCYZSNRwdKP5KjXhepXL7rHQ5 4G4VO/PLvzqP3mNcrAyGGIEyYHuZrx/L/lKFNwbV7mke6w6lo0D3Ty/zT2sx+wAkE3PloAb7atAD Ldv6D27VkWfVroX2i7MyLrKsm51j7LDd6ZLWPG+z27GtYx/pfR+h+jW4MhmmnJgas5Mfy/5SCGU2 Nd61O4k2sJdt+g5/6Rn0/wCbdtZvQlGMtwD5r8eXJjJOOcsZIo8EjC49jwuTZ0D6v3VvbbmWWV3n ZYHZMh7gWO2O/l7vRd/22h1/VD6tYZLw+zFed53euWnZW5u9/wDUrf6Xu/M9i2Bi9PEAYzI0geyJ aGhmm/3Oa0MaqF/Xuhtyb8PJDnX0b2XNNZMMsIe9m4e11b/ZuTJQxDWQiPMBsYs/PTuOLJmlQ4pR hLJt8vFIR/wUVnQPq7dU5tmZZZVcQx27JlriNr217v8Atp+3/i1H/mf0L/R28/Zv5x30ER/WPq3X WHuoIZ9MD0TB2jf6mwfS2V+7d+4o/wDO7oP+mf8AS+0/zb/5v97hD9Tf6H4L6+I1/l+G/wDWcPF8 r//R7zq7yzKd+n9BhqbJF7aHT+l97fVa5lmxqruyB6cvynNaXuAIzK53+1vp7tu38+x2z+RX/YN1 fb9sMtsc40gFtfpw5s2/oyzJa+u3c727P++IBdYAS0Wus1G0nHgMJq/S7fS9Ld+Z9H/Cf8Kkpd9x ONU12Q9tFhdOQMxgcBHuixrf0m1jWXez6HqKbbiP5q59rQSWuOWyHE1tbaz979Xr/Tf1/wBMoEvA qc11rny6aT9nG4jdtBd6O127+a/Qf6NKbHEuLrKiQPaPs/DRuFu8Ubneu72/8F/xaKmwxuBvaG9X e4+2B67TM7tn9bf7v668/vqY/wCsXVDtdbc3KtLKm0DIB/THU1utqb9LYxehi9xcAeluDdPdppJ9 +kfmrzm5tNnX+q1nF9Vrsq73mi23b+kf+ZTs/NLrFW5raHm7XwKVS5g3X6uPWv01ZuOBh2myl1AA n1PsXpgP/wBD63ru9Nr3fn7V2f1fdQzpmA92G6zIbhNjJFIILHWjbiC9z2+71dl3pf8AXVxOVXj1 41hZiNsisiTi5DCBMfaBY52xjq/+2/Z6fvXa/V9uT+xMA0Nr9L7M0Br6rC71DZ7nl4Y9rq/Q9TbX 7P0n+E9/6JnLD9Yf7v7Wf41K+Vx63+tPX+p+63KmdPbZhtb017HNc0Un0NKCGVbXOcLXNx/Zso9v +g9P6GxEvGO25zrsN+Rayi4m9lG6a/WaXYYs9RrnWW2Cu37P+f6aasdT3VeqyjaHfrG2q07mez+Z /Qt9J38/9P1P9H6n+FTubfqcRlbawy0NZZRbPrep+jc57Wu/Q+l6u9n0/wD0XceeRh2Fa/HLum3b hdtqc/HP6Nw9P9YdNv6Jjvaz1f8AglPP9JpHrNodLMj1nWsfP2Y21/a2sNZ9279D+jTMb1OavUbQ RvH2iKbdWQzc2j9H7H/z385v/wDSccotBrFLC33WljS62nfb6g9Gl9Yr221OZ6m//tv89JSMOxdz BfRUyt9kFhZYXAy30S+lzh77KX4/v/sLkOtVtd9aep7mOse0ggNqbbpFfu9O5wb9LYuvZY71qywi 66Tvqc4lu3e72s2s9X9F+mZ6f/F+p+mXHdXYx/1n6k0UGxhI/wAC60t0ZLvTDqtvt3uVbm/lj/e/ 7mTtfADWbPrX6k/+lcSPOxtuHcX0Pqhs2WHEqrDSNuxrbK7N7fUtNTPZ/wClq1Tn/wBsIVvLoYzE e5uGdGO2l2HZXu9o3P8AV9d+z0WOsyP69dX+Df8Ao68N8P8AvOnhVK9W3Tu7vF+rB4v0j+h/3D// 0vQOpYNuZkPayyusNrZHqVNt9x9YfRtDvb/VQD0N5r9MW0NBcSYx6tQSH+kR6e309zGrUcywZD3h u5rmsAII5abN3P8AXVHK6Zm3WutZ1DLxmF2706/RLQPZ7W+oxztn6P8A8ETogHc0gk9rRHojjXW0 WUNfVO20Y9W7X3aN9PYzZYXWexVbMM15Dq7qHX7iJyRh1Pa7axvpt3VtL/1Z3vq30/zv6P8ASV1r RZ07MZaH/bcpzQ4u9NxqLY7V6gv2N/reomPTc3fubnZTW6QwemQIAHL99nu/l2JwEOpB/wAZBJ7N NuZ1UVtu3ZjtWg1HGqDiQA/6Be13v9Xa/b/oLFhO+rVl2fmZRuvrrynuyLMe3GeGHdYHso/RZdT7 bf0nt2/mep/Nroh9X2wDa9+RcS42ZF1eO+x4LfTYyx2wN/RM+h7VI9Cr9Vlrw0tY1gsaaMf9Jskb rn7P3PR/mvT9L0P0aZkhiloY8VHQ3Jn5fmuY5cyOKfAZipemEtvV+lxPOXfVa6yprG5FtRtYNa6L SWMM/oLWHPe1ns/wT/8ABrTxcSvGw6ceyjJtdRR6DrPTdUCxh+1N9rrvTre+xvps2P8AUe/9H/o1 oDoLJBdDzu3EuoxpJ926S1jfpb/66TugtcZe4ukzZuoxTvIIczf+h/MhMjjhE3EV0X5+d5jPEQy5 DOMTxAERHq84xa9eJjtvq20XbqbnCtx3bGuBZvvdtd76LH1s+n9D/gPYlY6vIs/T42R6jg/HIDbK xsssbc536O79G3czd630/Srf/UVn9g16u5tcBuudRjF5d7/Ut3en/OWts2P/AJH9tNb9X6LHl20N PuI/QYxMuO5xl9bvzvf/AF0/RrtT7Ph1PpHo3n0HC2r6TtrwG+14Y/fZ/Rm+y71f89WDbkZDK7G/ aK22tcB6bXAN9Vzb/VsbVaf0mO6v0/7f+jejjozAQ6CHbq32Qyloe6sPa7e1rW/z/qv9X/Mr/Rp8 bpeRi1sroybmMYDLQ2mHOI273jb+b+5XsrS0UixsTMtpFnr20y/fttBbYI2tcz2vc1tT/T37P+EW XnfUu3M6lk57s2sDKIL8d1T3M9u385mRTv8AoLbbhZ8f07IdJaZ24/AEOGjP8J9JEoxc2p4dZk3Z DYMse2loJPfdU1jvZ/JTZwhMASF0zcvzWbl5GWGfBKQ4SajL03xfp8X7rzln1GsfW9jcyqoubsa9 lNssHt0r3ZjvpMb6fu/wdtqF/wAxnf8Ac4fzX2L+ZP8A27/Pf9BdhFn+jP3j+9D9O79z/C+pyOP/ ACSb93w/u/iWf/SvPVXvH/Fx/wDeP//T9PfkNZYa9r3uADjtaSADIb/1Co9YxaurdOtwLWWtZbtO 7YTBY5trXfSb9FzFca9rc20E6musgAEmAbfBE9eokAOkmSBBkgaO/wA1EEggjQjUKIvR5/J6NnW5 D7mZ+WA6qxjGPDoa9381ZtodWzZ7rfW9vqbPTrx/RTD6utERm9RbO5zwxxbuc7Zq5zP0n6Jteyrd Z9D0f9H7+hN9Q5MRqZBGnzT+szz/AM0/3J/vT7/gFvBHs4buisc+8nK6h6dwaGV73batgc39B+d+ f/hPUQm/V+oYP2N9uTaxrqnsbaz1K/0QLWsux7C6u6p27+b/AHKsb/DUesug9Zn8r/Nd/cl6zP5X +a7+5L3Z9+34K4I9nmf+aeKKGUNyc4MZvAcdXltm31d1h+k63b6d3s2W4/6L0v8ADKZ6Bk2Zd7rM 3KbhWABlFe8O1n1Wun9DVX7ttX2dv83/ADq6P1mfyv8ANd/cn9Zn8r/Nd/cj7+T978FcEezz1f1f YMY0uy89wgem8EhzCDW/1GbtzW2t9L06nbP0NX837/0j1kfV5l7MU/aMuu/ErurZkNaDZF07q2vs 3ubSydjGfzvpV1/p/wCcfbp3Yn2lzLW5eVjj0wz06dGaHd6kPqf+k1StwfU9L9dzGelX6Z2ab+P0 tv6H+e0+mzYiMstDx/gjhH7v4tD9jABwGVmusMuJsmxu7eyyiw1v/R/oPTfUxjP8HZ+k/SelYmxO htx7vUdk5todUarKn6scTWzHNj63bt737PVt9T1N93/B/olo3Uh+McXc613p1tL7Q6XbTq+w1NZ7 3bfzVQq6PbVXlMDaALxWG7W3gE1l7/036R37zf5v/hP30hMkG519FGI09LUx/q2cbHdQMzLbS1rW YzWNMVwNv0Hb2fTe70f8L/p8i+xOeg9ROXvdnXvxiGVurf6xeWBp9a4ifs/2q1x9H6HpfZvp+otL CxH4jrX2Nqa2w17fTZbv0eT+ksudZv8Apoww3fafXOZlFvqGz0AIZzIr/m/U9Nv/ABiJyys+sHTf hVwChp+LHpVDunY76X2ZOVusLw+1urQQ1vps2/mN2q39sZ+5ZzH0Tz+6q1mE514uGbl1/pBYa2j2 EA7vR2vqf+jd9F+xE3t8/wCfn6J/uUd+ri4td9uqa0qn/9T0bP6e/Lc+PSLXsDItYLBIdvn03t/7 8qo6AJk1YZG8uP6sySx30qfo/nu9z3rZSSU5NvScu6o022UWM3McGuoY5oDWuY5jWOG337/+t/Q/ PT0dLzsdsUW0VuII3Moa2J2atDNv5tbW7Veys3Ew2Nfl3MoY9wY11hDQXEF22T/Ja5ZHVrcPqeM3 Jxeo44xsUu+0uc+a2h00+uXVvbtycZzLPs/q+z1v+F9OytESqxEyXYxCUxGcxjHWR1r6N92P1Yv3 Ny2tbrDPTBGoG2XfS9rkahufW0i57L3E6O/m4ENEbQ1/54c9c3+zenF+5vVqnOdhZN432NJLbTH2 2z/utV+fd9P1P8MiDp2IywNyM/HrOYyzEoxpaW+uwV0zW9n2b1rcbIrf+g9Cv0n22en6d3qeo39Z /my2PZ5ar+8j/El3el3ZH7jP88/+k0t2R+4z/PP/AKTXNXV0jNyG4/UMGg1ZP2h1O73VNpqrZZ6t O5tb21Vt9f0n1+x9/wBo9en89jgOpIozc/DrFrLA5znn1215AZUbKLrn77HWend6V2T63p+p6Xq3 eml+s29sqGDBVnmYjQWOHUafK9A7HtdZRa5o3487QLXBp3DY7ezZtf8AyNyqP6MHNsZusDbXbyBe 7QyX/oz6e6tvu/M/qLPwcc05uLinrNd11b/tFVG4F93qsL8x1rA/3N22W34Pp/zX07PtCF1KoZec GDrOMLctwLMN+01uqBspwjVXv/T+nZZZbb6nqUZWYyqr9El+sr+blfbw7rRhwcfD95hw18/DP5v3 a/uPQXU3XMtrc0Bltfpkste14B3AuZaxgex/u+mz3oB6aTbjWgvDsRnp1gXO2uEbZurdWWWv/luW Hdhmx+Q1vVcX1cffZc/eWuLGPebMvqDQ/wBC1+Fd+i+z2V/Y6mepV+r+pR9lPn9EFjm/Z8yis9Qs eKw4Ohxspr/T4zK7W+rk4/oZWVjN/m2faLbP+EQJyD/JlcMHL2AeZjrevBI1X/fOviYNmHj+hVL2 7/Um21z3ctdt3Or+j7U1/TfXGUH7wM0NFu2942hg2D0IZ+g3fn+kr7RtaBJMCJPKdParnVdMdVey 8Oe51ZJAdaS3Ubfo+l9H+Sj+jkeDP5z1PpH/ADfoK0kkp//V9VSSSSU431pp6dZ0+qzqLbbKacio sro273WWE4dbWtf7n/0n/A/rH/cf9Ksi6/6s1Xvx3dUyX5BuLH0sYHPGRTkPz22OY3F9rsfKyH3V /wDaa6r/AAV9a659bLBtsaHjmHCRI+KY00ukOraZ1MgazB/761OGSYFA6BHCLunjrcn6luxb6czP vGLk2OdmU2GxrbbqvToynWWU1tc9+5tX2irGv+z+z+a9L11Zxuo/V/EqmrquTe3p9rLTQ5rS71Mp trqqX7sau2x+Q117/wBJZ6lf07H1fo1qdUxuuvvaelnEbQ2sxXe062l30n7GWfovS+j6fp+//wAC FZh/WHbX+s47yRiCxrg0Nc6q2y3O/wC073O+04pqpp/0NjPWr9P/AAhOSZFE6K4R2cfql/1Svx8v qd+RkZOLbe6uy+giKrbGMwnW4zq213/omdOZT+i9b1PU/wAPTfap9QyPqpn9Q6YczGvdk5lFTMYC PYx5sY+u/wBG39G/F99eS/8AwPq/oLN/0LleD9bYyB9sxLRsvGKGBrDXcbf1axzvst/8xjeyz9H+ f6X6X+lPerpv1lGRSftuJZQy+LqfTYJx2uBaytzKfZf6T7X/APB/zH/dxL3Z6VIitBSuAa2PNymP +rD7rbrH54uxJqfmbhMMe7pbrK/sh9N3p0v9JmXVT+j/AMBd+0/tSu9Ot+q4x+kYWBbfU7Mpc7p1 QO59LMh37Sa5/qerV+gu6dtqbb6/836P6WlXcfD+sfr32G3EFLsisY4ohpbjNtufkttc/Ft9XI9J 1TG1/o2erX/PV/pLL4ZGJ9YQ+j7Lm4wr9OiTbs3ODLPUz9mzFa30n4dnoUbNnp/9f9WpHLM7yKhA bAOR9t+p99L33HMaLm41WSHOLd7c8/avf6L/AEP0/wBlfkZt2Ls+0VfzVmRTZj1qwer/AFWfR0XP dXlbMWtpwrZMsa6yvpvp5dTLd271PpepX+l9Cz0fVu/QLSxcTr1uUbRk4zOnEsdTVVstIa22q+v9 J9lpa5t2L6lbP+43+kybf1ui/wBIw8yrBqHVfQuz2S2y6lga0tD3Po2N2s2ba/S9n5lv+el7kz+k ft7q4QOjzOJ/zdFuf1K/IvoNLzlX3OqY1jW32XP9FtOzIe+3Hj9byNnqbH+j632T9Wo63p+Dj9Pw qsPGkUUjbWDBO2dw9wA38/zj/wBLZ9O19lv6RFNFLpmtp3QHSBrtO5k/1HfRREJZJS3NqEQNlJJJ JqX/1vVUkll9V61b02+usYV+VW+t1m+gbiHNfTUKdv0fUsbfur3WM/m/+20p1ElzdH1vyLH1Nf0b OYHtp9RwrcWtsvNLfSDnMra/7N6tv2mz2en6P/Cfo7L/AKyW1G31OnZD2syrsZj6GPeC2mr7R672 vqpsZ61jXY1eyu2n1P5vIsq2PSU3erNZkYluAH1+tkMgU2WGouZLW3e+rda32O2b9ln/AAjLPoLn sfpwy8dl32rAfVfXtw72gD7N6pusx/sNbG41T8iyx1b/ALZsxLv0H80mv6jj9VyKMjL+reVde2z0 scuZFjGguuZbbv8ASrxmO9H/AE3+G9L/AAtiA6/oRpurd9V8w1OA9dhxztnErnHrsbPv91tlFPot uqf/ADn0EyWOMjZbGHm8uKJjChrxWRZvwT1YuDbksurzcDCfjkem3Eu3tqdWz0qrLHfoPWttff6W RVb6XrYnp0fpP5xEb0CkDZ9ow2ZL8M4m1sT6zrLd+x0tu9Oz9YxPb+sfzn+jSxum9OyOpnC/YbKc OzB9es5LHS99pr9bHe6basZ9e1n2tjv1h9v6X/jaOKxjcnC3dCqoe12HkVPbRe4tuyi2zPFlkNbj Px7f0n6X1q6/Q/Sfp/TqU0fh8pCwB8on8w2yfy/wF/8ApLmBtKthtfydLk6+HldLoxMw+thVHK2C vGY7digWNdh4wn06fWZkWYt/rWMp/m6fT/7Teos6rpeNj42Pn5mRiOwMx9doyHhz9lXqX9QFFNhr rrdVmVXuqvusbiV+l6n6G31Ur8ppxa7m9GGVmG14txvTuYbG02ZDsH0W2td6DchtuVmepez0X/rm L/O5KsOuxHdN6di5HQ7slwoc+qrHreKwMYOxsZj3Xmp1bMmi+2zGx8x3qVep+m/TJZeSlCIlMChI w+YXxdfR+7/WWw5/NHj4SBx8JOn7g4Ya/wBVsdBuxunZRw35uN6eaK7cbGY1zX77mvtG0v8A8D6V Po0N/wBFVR/N2fz3SLjqs/Afa3Jx/q9lvyKXtZiOuY9jiWC5lfuu3ek1v/Cf8fZ/M0PV/K+svUTg 234nTL6n05bMWw5Vb/ZWQ11md6FM25FDHu9P9Xd/w29NxYjKUccN5GhZYc2aWSZyTriO9Ctnoklh ZvWurY/VRiV4JsxnZFFQuayx36Kyu2zIu3MZ6e6i2tjVXxvrH1V9F1lmJufXjW21VCq6t1lzHObi 1t9Vr27syr3fZWepfif8P6v6GccnlMRIVRESPUP0/lY+IPSpLF6F1bqefa5mbi/ZwKa7I2WNIc7x dc1rHtyG/paq2fpsX+azP0y2k37tk932tOPf5hw9/mVYq3//2f/tJVBQaG90b3Nob3AgMy4wADhC SU0EJQAAAAAAEAAAAAAAAAAAAAAAAAAAAAA4QklNA+0AAAAAABABLAAAAAEAAgEsAAAAAQACOEJJ TQQmAAAAAAAOAAAAAAAAAAAAAD+AAAA4QklNBA0AAAAAAAQAAAAeOEJJTQQZAAAAAAAEAAAAHjhC SU0D8wAAAAAACQAAAAAAAAAAAQA4QklNBAoAAAAAAAEAADhCSU0nEAAAAAAACgABAAAAAAAAAAI4 QklNA/UAAAAAAEgAL2ZmAAEAbGZmAAYAAAAAAAEAL2ZmAAEAoZmaAAYAAAAAAAEAMgAAAAEAWgAA AAYAAAAAAAEANQAAAAEALQAAAAYAAAAAAAE4QklNA/gAAAAAAHAAAP////////////////////// //////8D6AAAAAD/////////////////////////////A+gAAAAA//////////////////////// /////wPoAAAAAP////////////////////////////8D6AAAOEJJTQQIAAAAAAAQAAAAAQAAAkAA AAJAAAAAADhCSU0EHgAAAAAABAAAAAA4QklNBBoAAAAAA0EAAAAGAAAAAAAAAAAAAAKBAAACYwAA AAYAcAByAGUAegB6AGkAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAmMAAAKBAAAA AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAEAAAAAAABudWxsAAAAAgAAAAZi b3VuZHNPYmpjAAAAAQAAAAAAAFJjdDEAAAAEAAAAAFRvcCBsb25nAAAAAAAAAABMZWZ0bG9uZwAA AAAAAAAAQnRvbWxvbmcAAAKBAAAAAFJnaHRsb25nAAACYwAAAAZzbGljZXNWbExzAAAAAU9iamMA AAABAAAAAAAFc2xpY2UAAAASAAAAB3NsaWNlSURsb25nAAAAAAAAAAdncm91cElEbG9uZwAAAAAA AAAGb3JpZ2luZW51bQAAAAxFU2xpY2VPcmlnaW4AAAANYXV0b0dlbmVyYXRlZAAAAABUeXBlZW51 bQAAAApFU2xpY2VUeXBlAAAAAEltZyAAAAAGYm91bmRzT2JqYwAAAAEAAAAAAABSY3QxAAAABAAA AABUb3AgbG9uZwAAAAAAAAAATGVmdGxvbmcAAAAAAAAAAEJ0b21sb25nAAACgQAAAABSZ2h0bG9u ZwAAAmMAAAADdXJsVEVYVAAAAAEAAAAAAABudWxsVEVYVAAAAAEAAAAAAABNc2dlVEVYVAAAAAEA AAAAAAZhbHRUYWdURVhUAAAAAQAAAAAADmNlbGxUZXh0SXNIVE1MYm9vbAEAAAAIY2VsbFRleHRU RVhUAAAAAQAAAAAACWhvcnpBbGlnbmVudW0AAAAPRVNsaWNlSG9yekFsaWduAAAAB2RlZmF1bHQA AAAJdmVydEFsaWduZW51bQAAAA9FU2xpY2VWZXJ0QWxpZ24AAAAHZGVmYXVsdAAAAAtiZ0NvbG9y VHlwZWVudW0AAAARRVNsaWNlQkdDb2xvclR5cGUAAAAATm9uZQAAAAl0b3BPdXRzZXRsb25nAAAA AAAAAApsZWZ0T3V0c2V0bG9uZwAAAAAAAAAMYm90dG9tT3V0c2V0bG9uZwAAAAAAAAALcmlnaHRP dXRzZXRsb25nAAAAAAA4QklNBBQAAAAAAAQAAAABOEJJTQQMAAAAAB+4AAAAAQAAAHoAAACAAAAB cAAAuAAAAB+cABgAAf/Y/+AAEEpGSUYAAQIBAEgASAAA/+0ADEFkb2JlX0NNAAH/7gAOQWRvYmUA ZIAAAAAB/9sAhAAMCAgICQgMCQkMEQsKCxEVDwwMDxUYExMVExMYEQwMDAwMDBEMDAwMDAwMDAwM DAwMDAwMDAwMDAwMDAwMDAwMAQ0LCw0ODRAODhAUDg4OFBQODg4OFBEMDAwMDBERDAwMDAwMEQwM DAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCACAAHoDASIAAhEBAxEB/90ABAAI/8QBPwAA AQUBAQEBAQEAAAAAAAAAAwABAgQFBgcICQoLAQABBQEBAQEBAQAAAAAAAAABAAIDBAUGBwgJCgsQ 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 sn8v8Bf/AKS5gbSrYbX8nS5Ovh5XS6MTMPrYVRytgrxmO3YoFjXYeMJ9On1mZFmLf61jKf5un0/+ 03qLOq6XjY+Nj5+ZkYjsDMfXaMh4c/ZV6l/UBRTYa663VZlV7qr7rG4lfpep+ht9VK/KacWu5vRh lZhteLcb07mGxtNmQ7B9FtrXeg3IbblZnqXs9F/65i/zuSrDrsR3TenYuR0O7JcKHPqqx63isDGD sbGY915qdWzJovtsxsfMd6lXqfpv0yWXkpQiJTAoSMPmF8XX0fu/1lsOfzR4+EgcfCTp+4OGGv8A VbHQbsbp2UcN+bjenmiu3GxmNc1++5r7RtL/APA+lT6NDf8ARVUfzdn890i46rPwH2tycf6vZb8i l7WYjrmPY4lguZX7rt3pNb/wn/H2fzND1fyvrL1E4Nt+J0y+p9OWzFsOVW/2VkNdZnehTNuRQx7v T/V3f8NvTcWIylHHDeRoWWHNmlkmck64jvQrZ6JJYWb1rq2P1UYleCbMZ2RRULmssd+isrtsyLtz GenuotrY1V8b6x9VfRdZZibn141ttVQqurdZcxzm4tbfVa9u7Mq932VnqX4n/D+r+hnHJ5TESFUR Ej1D9P5WPiD0qSxehdW6nn2uZm4v2cCmuyNljSHO8XXNax7chv6Wqtn6bF/msz9MtpN+7ZPd9rTj 3+YcPf5lWKt//9k4QklNBCEAAAAAAFUAAAABAQAAAA8AQQBkAG8AYgBlACAAUABoAG8AdABvAHMA aABvAHAAAAATAEEAZABvAGIAZQAgAFAAaABvAHQAbwBzAGgAbwBwACAANwAuADAAAAABADhCSU0E BgAAAAAABwAIAAEAAQEA/+ESSGh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0 IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPD9hZG9iZS14YXAt ZmlsdGVycyBlc2M9IkNSIj8+Cjx4OnhhcG1ldGEgeG1sbnM6eD0nYWRvYmU6bnM6bWV0YS8nIHg6 eGFwdGs9J1hNUCB0b29sa2l0IDIuOC4yLTMzLCBmcmFtZXdvcmsgMS41Jz4KPHJkZjpSREYgeG1s bnM6cmRmPSdodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjJyB4bWxu czppWD0naHR0cDovL25zLmFkb2JlLmNvbS9pWC8xLjAvJz4KCiA8cmRmOkRlc2NyaXB0aW9uIGFi b3V0PSd1dWlkOjlkZDg4ODhkLTMzMjAtMTFlNi04YmI4LWM2MzAxNjVmMmJiMicKICB4bWxuczp4 YXBNTT0naHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyc+CiAgPHhhcE1NOkRvY3VtZW50 SUQ+YWRvYmU6ZG9jaWQ6cGhvdG9zaG9wOjlkZDg4ODhiLTMzMjAtMTFlNi04YmI4LWM2MzAxNjVm MmJiMjwveGFwTU06RG9jdW1lbnRJRD4KIDwvcmRmOkRlc2NyaXB0aW9uPgoKPC9yZGY6UkRGPgo8 L3g6eGFwbWV0YT4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAK ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgCjw/eHBhY2tldCBlbmQ9J3cnPz7/4gxYSUNDX1BST0ZJTEUAAQEAAAxITGlubwIQAABtbnRy UkdCIFhZWiAHzgACAAkABgAxAABhY3NwTVNGVAAAAABJRUMgc1JHQgAAAAAAAAAAAAAAAAAA9tYA AQAAAADTLUhQICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ABFjcHJ0AAABUAAAADNkZXNjAAABhAAAAGx3dHB0AAAB8AAAABRia3B0AAACBAAAABRyWFlaAAAC GAAAABRnWFlaAAACLAAAABRiWFlaAAACQAAAABRkbW5kAAACVAAAAHBkbWRkAAACxAAAAIh2dWVk AAADTAAAAIZ2aWV3AAAD1AAAACRsdW1pAAAD+AAAABRtZWFzAAAEDAAAACR0ZWNoAAAEMAAAAAxy VFJDAAAEPAAACAxnVFJDAAAEPAAACAxiVFJDAAAEPAAACAx0ZXh0AAAAAENvcHlyaWdodCAoYykg MTk5OCBIZXdsZXR0LVBhY2thcmQgQ29tcGFueQAAZGVzYwAAAAAAAAASc1JHQiBJRUM2MTk2Ni0y LjEAAAAAAAAAAAAAABJzUkdCIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWFlaIAAAAAAAAPNRAAEAAAABFsxYWVogAAAAAAAAAAAA AAAAAAAAAFhZWiAAAAAAAABvogAAOPUAAAOQWFlaIAAAAAAAAGKZAAC3hQAAGNpYWVogAAAAAAAA JKAAAA+EAAC2z2Rlc2MAAAAAAAAAFklFQyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAFklF QyBodHRwOi8vd3d3LmllYy5jaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAABkZXNjAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFj ZSAtIHNSR0IAAAAAAAAAAAAAAC5JRUMgNjE5NjYtMi4xIERlZmF1bHQgUkdCIGNvbG91ciBzcGFj ZSAtIHNSR0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZGVzYwAAAAAAAAAsUmVmZXJlbmNlIFZpZXdp bmcgQ29uZGl0aW9uIGluIElFQzYxOTY2LTIuMQAAAAAAAAAAAAAALFJlZmVyZW5jZSBWaWV3aW5n IENvbmRpdGlvbiBpbiBJRUM2MTk2Ni0yLjEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHZpZXcA AAAAABOk/gAUXy4AEM8UAAPtzAAEEwsAA1yeAAAAAVhZWiAAAAAAAEwJVgBQAAAAVx/nbWVhcwAA AAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAo8AAAACc2lnIAAAAABDUlQgY3VydgAAAAAAAAQAAAAA BQAKAA8AFAAZAB4AIwAoAC0AMgA3ADsAQABFAEoATwBUAFkAXgBjAGgAbQByAHcAfACBAIYAiwCQ AJUAmgCfAKQAqQCuALIAtwC8AMEAxgDLANAA1QDbAOAA5QDrAPAA9gD7AQEBBwENARMBGQEfASUB KwEyATgBPgFFAUwBUgFZAWABZwFuAXUBfAGDAYsBkgGaAaEBqQGxAbkBwQHJAdEB2QHhAekB8gH6 AgMCDAIUAh0CJgIvAjgCQQJLAlQCXQJnAnECegKEAo4CmAKiAqwCtgLBAssC1QLgAusC9QMAAwsD FgMhAy0DOANDA08DWgNmA3IDfgOKA5YDogOuA7oDxwPTA+AD7AP5BAYEEwQgBC0EOwRIBFUEYwRx BH4EjASaBKgEtgTEBNME4QTwBP4FDQUcBSsFOgVJBVgFZwV3BYYFlgWmBbUFxQXVBeUF9gYGBhYG JwY3BkgGWQZqBnsGjAadBq8GwAbRBuMG9QcHBxkHKwc9B08HYQd0B4YHmQesB78H0gflB/gICwgf CDIIRghaCG4IggiWCKoIvgjSCOcI+wkQCSUJOglPCWQJeQmPCaQJugnPCeUJ+woRCicKPQpUCmoK gQqYCq4KxQrcCvMLCwsiCzkLUQtpC4ALmAuwC8gL4Qv5DBIMKgxDDFwMdQyODKcMwAzZDPMNDQ0m DUANWg10DY4NqQ3DDd4N+A4TDi4OSQ5kDn8Omw62DtIO7g8JDyUPQQ9eD3oPlg+zD88P7BAJECYQ QxBhEH4QmxC5ENcQ9RETETERTxFtEYwRqhHJEegSBxImEkUSZBKEEqMSwxLjEwMTIxNDE2MTgxOk E8UT5RQGFCcUSRRqFIsUrRTOFPAVEhU0FVYVeBWbFb0V4BYDFiYWSRZsFo8WshbWFvoXHRdBF2UX iReuF9IX9xgbGEAYZRiKGK8Y1Rj6GSAZRRlrGZEZtxndGgQaKhpRGncanhrFGuwbFBs7G2Mbihuy G9ocAhwqHFIcexyjHMwc9R0eHUcdcB2ZHcMd7B4WHkAeah6UHr4e6R8THz4faR+UH78f6iAVIEEg bCCYIMQg8CEcIUghdSGhIc4h+yInIlUigiKvIt0jCiM4I2YjlCPCI/AkHyRNJHwkqyTaJQklOCVo JZclxyX3JicmVyaHJrcm6CcYJ0kneierJ9woDSg/KHEooijUKQYpOClrKZ0p0CoCKjUqaCqbKs8r Ais2K2krnSvRLAUsOSxuLKIs1y0MLUEtdi2rLeEuFi5MLoIuty7uLyQvWi+RL8cv/jA1MGwwpDDb MRIxSjGCMbox8jIqMmMymzLUMw0zRjN/M7gz8TQrNGU0njTYNRM1TTWHNcI1/TY3NnI2rjbpNyQ3 YDecN9c4FDhQOIw4yDkFOUI5fzm8Ofk6Njp0OrI67zstO2s7qjvoPCc8ZTykPOM9Ij1hPaE94D4g PmA+oD7gPyE/YT+iP+JAI0BkQKZA50EpQWpBrEHuQjBCckK1QvdDOkN9Q8BEA0RHRIpEzkUSRVVF mkXeRiJGZ0arRvBHNUd7R8BIBUhLSJFI10kdSWNJqUnwSjdKfUrESwxLU0uaS+JMKkxyTLpNAk1K TZNN3E4lTm5Ot08AT0lPk0/dUCdQcVC7UQZRUFGbUeZSMVJ8UsdTE1NfU6pT9lRCVI9U21UoVXVV wlYPVlxWqVb3V0RXklfgWC9YfVjLWRpZaVm4WgdaVlqmWvVbRVuVW+VcNVyGXNZdJ114XcleGl5s Xr1fD19hX7NgBWBXYKpg/GFPYaJh9WJJYpxi8GNDY5dj62RAZJRk6WU9ZZJl52Y9ZpJm6Gc9Z5Nn 6Wg/aJZo7GlDaZpp8WpIap9q92tPa6dr/2xXbK9tCG1gbbluEm5rbsRvHm94b9FwK3CGcOBxOnGV cfByS3KmcwFzXXO4dBR0cHTMdSh1hXXhdj52m3b4d1Z3s3gReG54zHkqeYl553pGeqV7BHtje8J8 IXyBfOF9QX2hfgF+Yn7CfyN/hH/lgEeAqIEKgWuBzYIwgpKC9INXg7qEHYSAhOOFR4Wrhg6GcobX hzuHn4gEiGmIzokziZmJ/opkisqLMIuWi/yMY4zKjTGNmI3/jmaOzo82j56QBpBukNaRP5GokhGS epLjk02TtpQglIqU9JVflcmWNJaflwqXdZfgmEyYuJkkmZCZ/JpomtWbQpuvnByciZz3nWSd0p5A nq6fHZ+Ln/qgaaDYoUehtqImopajBqN2o+akVqTHpTilqaYapoum/adup+CoUqjEqTepqaocqo+r Aqt1q+msXKzQrUStuK4trqGvFq+LsACwdbDqsWCx1rJLssKzOLOutCW0nLUTtYq2AbZ5tvC3aLfg uFm40blKucK6O7q1uy67p7whvJu9Fb2Pvgq+hL7/v3q/9cBwwOzBZ8Hjwl/C28NYw9TEUcTOxUvF yMZGxsPHQce/yD3IvMk6ybnKOMq3yzbLtsw1zLXNNc21zjbOts83z7jQOdC60TzRvtI/0sHTRNPG 1EnUy9VO1dHWVdbY11zX4Nhk2OjZbNnx2nba+9uA3AXcit0Q3ZbeHN6i3ynfr+A24L3hROHM4lPi 2+Nj4+vkc+T85YTmDeaW5x/nqegy6LzpRunQ6lvq5etw6/vshu0R7ZzuKO6070DvzPBY8OXxcvH/ 8ozzGfOn9DT0wvVQ9d72bfb794r4Gfio+Tj5x/pX+uf7d/wH/Jj9Kf26/kv+3P9t////7gAOQWRv YmUAZEAAAAAB/9sAhAABAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB AgICAgICAgICAgIDAwMDAwMDAwMDAQEBAQEBAQEBAQECAgECAgMDAwMDAwMDAwMDAwMDAwMDAwMD AwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwP/wAARCAKBAmMDAREAAhEBAxEB/90ABABN/8QB JwABAAEEAgMBAAAAAAAAAAAAAAgGBwkKBAUBAgMLAQEAAQQDAQEAAAAAAAAAAAAAAQIFBgcDBAgJ ChAAAAYCAQIDAgcGCw0SCAEdAgMEBQYHAQgAEQkSExQhFTEWF5cYWApBItV315hRIzPUVrY3tzjY GXEycrJz0yS0VZWWVxphgZGxNHSFNnbWR0h4uMhZiclCUrMlNXW1Jieh0ZJDVEaC0lOUKDl5isHx YmNERYamZ4fHKUmpOhEAAQMDAgMEBAgGCA0ODAMJAQIDBAARBRIGIRMHMUEiCFFhcRTwgZHRMiMV CaGxwUJSFuFy0jPTlJUY8WKisyR01FYXN1c4GYKSskNzkzREVLR1tTZ2wlNjw8QlNVXFRoeIg6NF 1SZkZUco4ndY/9oADAMBAAIRAxEAPwDf44pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pT ilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOK U4pTilOKU4pTilOKU4pUW9udzddNHaocrf2PsiPQGOkopMKMtjo8MrbIrGkcZh7/ADgcBrxA+ObQ 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 qe6vmmde6ddOM+MfXGNY9POmM+LPsx/8EuPZj+ZzZ6UrKUkAWt8O6vD3H016fRT3V/6066vzY9PP yTcnS56B8Pipx9NPop7q/wDWnXV+bHp5+SbjS56B8Pipx9NPop7q/wDWnXV+bHp5+SbjS56B8Pip x9NPop7q/wDWnXV+bHp5+SbjS56B8Pipx9NPop7q/wDWnXV+bHp5+SbjS56B8Pipx9NPop7q/wDW nXV+bHp5+SbjS56B8Pipx9NPop7q/wDWnXV+bHp5+SbjS56B8Pipx9NPop7q/wDWnXV+bHp5+Sbj S56B8Pipx9NR3231h3CbNYL6cHnuaXFJGlHV8pUOLCq1u1LQJ3dKWhFkxActa6vRuSUtT7AiMINL NCHOchF1+GlQV4b27fyH1CnH01Iw7VPdXzTOvdNunGfGL2Y1j09zjHt+DH/wS49mP5mOEJXpTa1r fDupx9NfP6Ke6v8A1p11fmx6efkm5Vpc9A+HxU4+mn0U91f+tOur82PTz8k3Glz0D4fFTj6afRT3 V/6066vzY9PPyTcaXPQPh8VOPpp9FPdX/rTrq/Nj08/JNxpc9A+HxU4+mn0U91f+tOur82PTz8k3 Glz0D4fFTj6afRT3V/6066vzY9PPyTcaXPQPh8VOPpp9FPdX/rTrq/Nj08/JNxpc9A+HxU4+mn0U 91f+tOur82PTz8k3Glz0D4fFTj6ao2xdXNz0deT9Yf3RLmXEJIPLlJ6I3WbUIotWQRHnE05MM0iq SzywnlgyHIgCCPHXrjOM9M4ghYsTbtH4/ZVK0BaFIV9Eix9hrD5Uf2aCnJfU9XS0/cW/0B8priDS Q9ClhFODSozn2LtTqalTCPi4zskJxq8gB4xCF4cY65zn250y90D6eS3npTsSWXXFqUr+yCOKiSeG g99fSbEfewecnCYrF4XH7h26mBDjtsNg4ltRDbSEtoBPO4nSkXPC542q4P8Akv8AS/10Nh/8BqX/ AN6vOP8Am99OP+Ry/wCMn+Dq4f6XTzq/3x7c/khv+Gp/kv8AS/10Nhv8BqX/AN6vH83vpx/yOZ/G T/B1H+lz86h7dx7c/khv+Gp/kv8AS/Xr9NDYfrj4M/Eal+uP/wB1eP5vfTn/AJHM/jJ/g6f6XLzp 9v6xbbv/ANDt/wANT/JfqX+uhsN7OvT/ANxqX9nX4f8A51fu8fze+nP/ACOZ/GT/AAdR/pcfOkOI 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 Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI9NP ow379fq/fmq1G/i9ce+ver5KaR6afRhv36/V+/NVqN/F6499e9XyU0j00+jDfv1+r9+arUb+L1x7 696vkppHpp9GG/fr9X781Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1f vzVajfxeuPfXvV8lNI9NPow379fq/fmq1G/i9ce+ver5KaR6afRhv36/V+/NVqN/F6499e9XyU0j 00+jDfv1+r9+arUb+L1x7696vkppHpp9GG/fr9X781Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4v XHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI9NPow379fq/fmq1G/i9ce+ver5KaR6afRhv36 /V+/NVqN/F6499e9XyU0j00+jDfv1+r9+arUb+L1x7696vkppHpp9GG/fr9X781Wo38Xrj3171fJ TSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI9NPow379fq/fmq1G /i9ce+ver5KaR6afRhv36/V+/NVqN/F6499e9XyU0j00+jDfv1+r9+arUb+L1x7696vkppHpp9GG /fr9X781Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXv V8lNI9NPow379fq/fmq1G/i9ce+ver5KaR6afRhv36/V+/NVqN/F6499e9XyU0j00+jDfv1+r9+a rUb+L1x7696vkppHpp9GG/fr9X781Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn 0Yb9+v1fvzVajfxeuPfXvV8lNI9NPow379fq/fmq1G/i9ce+ver5KaR6afRhv36/V+/NVqN/F649 9e9XyU0j00+jDfv1+r9+arUb+L1x7696vkppHpp9GG/fr9X781Wo38Xrj3171fJTSPTT6MN+/X6v 35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI9NPow379fq/fmq1G/i9ce+ver5KaR 6afRhv36/V+/NVqN/F6499e9XyU0j00+jDfv1+r9+arUb+L1x7696vkppHpp9GG/fr9X781Wo38X rj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI9NPow379 fq/fmq1G/i9ce+ver5KaR6afRhv36/V+/NVqN/F6499e9XyU0j00+jDfv1+r9+arUb+L1x7696vk ppHpp9GG/fr9X781Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVaj fxeuPfXvV8lNI9NPow379fq/fmq1G/i9ce+ver5KaR6afRhv36/V+/NVqN/F6499e9XyU0j00+jD fv1+r9+arUb+L1x7696vkppHpp9GG/fr9X781Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3 q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI9NPow379fq/fmq1G/i9ce+ver5KaR6afRhv36/V+/N VqN/F6499e9XyU0j00+jDfv1+r9+arUb+L1x7696vkppHpp9GG/fr9X781Wo38Xrj3171fJTSPTT 6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI9NPow379fq/fmq1G/i9ce +ver5KaR6afRhv36/V+/NVqN/F6499e9XyU0j00+jDfv1+r9+arUb+L1x7696vkppHpp9GG/fr9X 781Wo38Xrj3171fJTSPTT6MN+/X6v35qtRv4vXHvr3q+Smkemn0Yb9+v1fvzVajfxeuPfXvV8lNI 9NPow379fq/fmq1G/i9ce+ver5KaR6a9gayX+WMAw7935gQBBGHOap1Fz98HOM49mdeumfbjlKpb yklJtYj0U0j01Zr+S4rP4u/Fn5ZLm9B9EL6Ivmdaz9T7r+VP5XPlW8z5O/B8onxk/SvJ8Pxf9J95 7t8X3/OHWr0/nX+Oq7mv/9bf44pTilOKU4pTilOKU4pTileM5xjHXOemMfDnPwY/zc/oYxxSqQZ7 DgEidVTFH5zD318ReZ6xmZpMyujqk8rOcG+pbkK09YR5ecZ8XiBjp93ndfxuRistyZMB5uOr6K1I UlJv6FEAH4jXA3KjOrU01IbU4O0BQJHtAN6rDnSrnpxSnFKcUpxSnFK4SdyblZ6hKkXolKlLnwqk ydUQcemF4sh6KCSxiMJz4g5x0FjHtx05WptxCUrW2oJPYSDY+z01SFoUSlKwVDt49lc3lFVU4pTi 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 EceJsMZKGC90CvHe5sWH2RKItXb+dp5pFoxuVVkcrmGs7MCbsCiNOMvMbIwaOIu8hEJaoWlvODmB eb6jIFmMZwPxbXcyHSPJx8Ecb1+yMTZMctOOYyQt91SuUsOJa1OfWJRwCeVZ5CdN2yeFsWMfd8dW RS/sKO7mXNaUSEJSm2pOnXZA5ZVxJ1XQePirNv2su1W2UJ2zwae7lQqHWKotWbO9o29WypVh/iqB yWOUYVRmMKXJvPKTvCuNEQhrPPPTmZT5cADwUM0oITB6D6vdYXtydVzvjY2Qfiphx0x4z4GhwpCX A44EkEpDhecSARfQRcJJIGwNn7PTjdrHD5yOhxb7pddRe6Qq6dIuO9OhKuHAK7CQLnIdNtEdPrHo iH6xznXuuZNRFeloS4HXDm0mGs8N93BUFojYwqApLeGNSSSrNL81MpLNEUYIAhZALOM6yx/UPe2L 3FN3Zj9yymtxSb819KvE7qtcOC2lYNgbKSRcAjiKymTt/Cy4DWMk45tcFv6KTfw9vFJvqB4niDfj Vq2ntRduRij0EjDNp9TLY01nLVE8g+UUfOTuzHMVRzWoNkYZEWtDIXB1waypMgNVKj8lemLwDw4D jHLw/wBYep8mTkZcje05b0tgMu3WClbQ1eDRbQlPjVcJSL6jftrqI2jtptLKUYdkctRUDY6rm3Eq vqP0U9pNrC3ZWQjmtayOnFKcUpxSnFK//9Lf44pVsrktqI0VWUutmd5ePipC28lwdSo8zLpE+qvV L0jWhQs7G2lmrnRyXuS8kgkkoORDMMxj2fDxSo5/Tbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xS n02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKf Tbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9N tu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn022 76rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbv qubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q 5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm 7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs /m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+ bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSukTb/wARWSB3 iiXW/dE6SMDWxvTyzh1sl2Fbe0yZQ+JGBwP8R4SRJ3VTGXAsrIBiz4khmBYD0x1Uru/ptt31XN2f zbZR+vOKU+m23fVc3Z/NtlH684pT6bbd9Vzdn822UfrzilPptt31XN2fzbZR+vOKU+m23fVc3Z/N tlH684pT6bbd9Vzdn822UfrzilPptt31XN2fzbZR+vOKU+m23fVc3Z/NtlH684pT6bbd9Vzdn822 UfrzilPptt31XN2fzbZR+vOKU+m23fVc3Z/NtlH684pXWot8404rXduQ607qKVrAsTt70nL1rlvj blqttQvCZMeIagJeTTmtyIPx4BCxgBoeucZ64wpXZfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15 xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnF KfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp 9Ntu+q5uz+bbKP15xSuiY+4DDpKJ6Cw647oOgo6+row+BTa2S7GWyQNpaY5e1KfOPK/slKUsKELI PEDOB46Cz7eKV3v02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276 rm7P5tso/XnFKfTbbvqubs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqu bs/m2yj9ecUp9Ntu+q5uz+bbKP15xSn02276rm7P5tso/XnFKfTbbvqubs/m2yj9ecUrqP5ROhvi p8dPi/dnuD5LflS9T8j0u87yvlo+QH5P/S+l8/5VvlL/ALE9w9PVeR/ZH6j99xSv/9Pf44pUJe4x /A1uT+hgH76UI4pU2uKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU 4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pUX4L/C82P/ABL6uftj2W4pUoOKU4pTilOK U4pTilOKU4pTilOKU4pVi6y/dT2R/wB30H/eZrzilX04pTilOKU4pTilOKU4pTileOuP0cfof5/w dP8AR5Fx6aV55NKcUqKmrf8AqnZj/lV2j/7JhvFKlXxSnFKcUpxSnFKcUpxSnFKcUpxSnFK1wf8A i1/7C/8AezcUr//U3+OKVCXuMfwNbk/oYB++lCOKVNrilOKU4pTilOKU4pTilOKU4pTilOKU4pTi lOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKVF+C/wvNj /wAS+rn7Y9luKVKDilUBHLXq2YSqVQSJWTAZRN4KYWTNodHZhHnuVQ400XgKLlMebXFS7x8wwf3o cKySc5F7Me3lxk4fLQocPIzMXJZx8gXadW0tLbo9La1JCV/6kmuq1NhPvPR2JbS5Df00pWkqT+2S DdPxgUW2vVzbiwsuFjwRFipEBLravqpcwEfJo2KGg2QJ3CfYMXhzD0Z7CQNaAxw9OAaQOTsZyXjx chGIyrn2aG8ZIV76opj2bWeeoK0EM8PrSFnQQjVZXhPHhRU2Gj3rVLbHIF3LqT9WCNQK+PhBHHxW 4ceyvm2W5VL1Mza4Z7Mr91sRPH0csPgLdMY6tmpEWcSyDUEkOiqZxMfSmFaUqKEUrERhOYEwGQjz gWOsu4fLsQE5V/FyUYsuFsPKaWGi4m90Bwp0FYsbpvqFjccKImwnJBiNy2lStOrQFJK9J7Fab3sb jja3GvtGbVq+ayOWQ6HWPA5ZLoEpJRTmLRmXx9+kcMWKcmBTpZWyNbgqc46oPEUPAALCiRCyAWMY 9meRKxOVgxYU6bjJDMKSCWXFtrQh0DtLa1AJWBcXKSRxqWpkOQ68wxKbW+2bLSlSSpB9CgCSn47V XvLfXZq3ALjqIyxTKgLtOuR20Ug96m1eCbxoViFtnp8K/eI4VhzzJAIfS5wb5uU3g8vPi6+H28uZ wmZGLGcOIlfYpVpEjlOcjVe2nm6dGq/C2q9+FdT7Qge9+4e+s+/Wvy9aeZbtvovqtbje1cKP3pSU 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 2e9+dzEcqtRjnsjgxPyuRo5qeGis1EUSTJQKQEVaYxIBtaqatpYS1CgoxQYfkJIR5LMwFSrmH6g+ mOynU7tbnJz8EHqckH3TCyjsJ0oCzVSjJZlbhHghMWaERg+nhAEWM5zjGccUqPF3tNI67J4+rtju C7ssSSUxSZTdhVt1iIJMlcYxAV8JbZS5kqI1ULqT4ECyw2gIQZzgZ+FORFYGEszIFKkPjUHqsUt+ N2tzsr0aYtYrQ4umF+sSpDciwUqUpvk384hMZkAvCMQcBz0z0z7OKV88ajlCTL1gd39yso2o1QS6 KsXZCcpm05GHA1ZS8/FceUjNSgzjJgTMhyDGeounFK5pGmqxSQSpTbn7rqEygos9OeRcUQOJPINB gwo4k0utBFmlGliwIIg5zgWM9ccUritmoeHpGW4s27m5rs3mmKSSl7ZdULXojTUak5ErKLVJa3NI GYlWJzCTMYFnIDSxAF0EHOMKVZ6sYBUNzz64azqruIbdz2X0G6xhhttFGrli7mhh0glzaud2dgWP hFXCZFb0FvbzBK0yZQcagH0KU4KN+8wpXeV/TMGs5LL1kP3w3UWpoLacupaSGrrVj7IFJZUHdcMs jjab3zVaHLkclc8+UUan80hTn2kjHj28Uqml8NpFsniisF/cf2xTT9LZUap0+KmXTGPehdnTCu19 sxuFiLxVmSvfLrXLWe7Fh8XgwlLz4hBHnAcqVcKG64NU5jcUlDRunvUgRzRtIdWBslVjM8OlByc9 NlXglbEZRU7TJWtwJTYyM1MpSlKCg4zkYA8UqrCtPTD1atARuvuicub8J8r0ZVzwwxWiwrAI1JlW nBW2Tk2FJYciL8eA+MOM5x1xxSvgbqOSQ7oo+du/uUS/OTe4uzcyG3ZCS3de1M6htSOzmibR1xhY qb2tU8oy1BwACLIMVkhHkOTQYEpXZfQucvrlbufO9E/yZ8Up9C5y+uVu5870T/JnxSn0LnL65W7n zvRP8mfFKfQucvrlbufO9E/yZ8Up9C5y+uVu5870T/JnxSn0LnL65W7nzvRP8mfFKfQucvrlbufO 9E/yZ8Up9C5y+uVu5870T/JnxSn0LnL65W7nzvRP8mfFKfQucvrlbufO9E/yZ8Up9C5y+uVu5870 T/JnxSn0LnL65W7nzvRP8mfFKfQucvrlbufO9E/yZ8Up9C5y+uVu5870T/JnxSn0LnL65W7nzvRP 8mfFKfQucvrlbufO9E/yZ8Up9C5y+uVu5870T/JnxSn0LnL65W7nzvRP8mfFKfQucvrlbufO9E/y Z8Up9C5y+uVu5870T/JnxSn0LnL65W7nzvRP8mfFKfQucvrlbufO9E/yZ8UqOsO1CcFG0d9NONut ziRNlQ64KhOZdtxb3iuw5yLYfAUio3NbeWJE3+h8ScGAYyAw84WRC8eMBUqRX0LnL65W7nzvRP8A JnxSn0LnL65W7nzvRP8AJnxSn0LnL65W7nzvRP8AJnxSn0LnL65W7nzvRP8AJnxSn0LnL65W7nzv RP8AJnxSn0LnL65W7nzvRP8AJnxSn0LnL65W7nzvRP8AJnxSn0LnL65W7nzvRP8AJnxSn0LnL65W 7nzvRP8AJnxSn0LnL65W7nzvRP8AJnxSn0LnL65W7nzvRP8AJnxSrPV7p+4q7FvtHjb/AHUT5a5v ECBKCbdigTF3qKmgSzB6rGazzgSgrB3lYFjpjJQAY6dcZzlSrw/QucvrlbufO9E/yZ8Up9C5y+uV u5870T/JnxSn0LnL65W7nzvRP8mfFKfQucvrlbufO9E/yZ8Up9C5y+uVu5870T/JnxSn0LnL65W7 nzvRP8mfFKfQucvrlbufO9E/yZ8Up9C5y+uVu5870T/JnxSn0LnL65W7nzvRP8mfFKfQucvrlbuf O9E/yZ8Up9C5y+uVu5870T/JnxSo2a5aiODqo2DwHbnc1v8AdmytjNYsobaixeV4kzXExZcFuR1s PxrT/N6Dzjwh6Bx0xjilST+hc5fXK3c+d6J/kz4pT6Fzl9crdz53on+TPilPoXOX1yt3Pneif5M+ KU+hc5fXK3c+d6J/kz4pT6Fzl9crdz53on+TPilPoXOX1yt3Pneif5M+KU+hc5fXK3c+d6J/kz4p T6Fzl9crdz53on+TPilPoXOX1yt3Pneif5M+KU+hc5fXK3c+d6J/kz4pT6Fzn9crdz53ol+TPilY VPk4N+jV0+U23f3IPk86/Gxs6+d/K0+P5Sevxb/dY+571/1N4fZ6Tilf/9Hf44pUJe4x/A1uT+hg H76UI4pXvvdS0numpoS2QCIN0nnMb2V08mxJ542JC5tEErvbyibQtJageHo9H6UhHCIIqWnpiDsH L/RAJLLNOyUXlSrXb/0xLbImWpk6MpJVtHSFO2VPn+6dbkI4ItVzEUmq9+itcWAniFoyCK15YBtW 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 4SsCyAAcYUrmM1Za1x+3Gu22nX/ugpDGDYFy2lj9dF1hPQ1a0XvIIY7wGVz4EYCmCrdFcojb+uKU JXBYsQphqzRoiUghcUrIP9N5r+q7u3+bPMP69xSn03mv6ru7f5s8w/r3FKfTea/qu7t/mzzD+vcU p9N5r+q7u3+bPMP69xSn03mv6ru7f5s8w/r3FKfTea/qu7t/mzzD+vcUp9N5r+q7u3+bPMP69xSn 03mv6ru7f5s8w/r3FKfTea/qu7t/mzzD+vcUp9N5r+q7u3+bPMP69xSn03mv6ru7f5s8w/r3FKfT ea/qu7t/mzzD+vcUp9N5r+q7u3+bPMP69xSrIRfaRW1bB3HYavVbdYEZmVaUZG2RVjXCTjOPd4M9 XWskJA0ha0aogtKmmrfkJhgABNyaLAMi8sXRSr3/AE3mv6ru7f5s8w/r3FKfTea/qu7t/mzzD+vc Up9N5r+q7u3+bPMP69xSn03mv6ru7f5s8w/r3FKfTea/qu7t/mzzD+vcUp9N5r+q7u3+bPMP69xS n03mv6ru7f5s8w/r3FKfTea/qu7t/mzzD+vcUp9N5r+q7u3+bPMP69xSn03mv6ru7f5s8w/r3FKf Tea/qu7t/mzzD+vcUq2EK20Exzm5X5fqzuwBBNJZF3ZjGDWyUmZPRNlbQ+OKjBgLWDNIGB1aDweE wIBZwHAsdQixnilXP+m81/Vd3b/NnmH9e4pT6bzX9V3dv82eYf17ilPpvNf1Xd2/zZ5h/XuKU+m8 1/Vd3b/NnmH9e4pT6bzX9V3dv82eYf17ilPpvNf1Xd2/zZ5h/XuKU+m81/Vd3b/NmmH9e4pT6bzX 9V3dv82eYf17ilPpvNf1Xd2/zZ5h/XuKU+m81/Vd3b/NnmH9e4pT6bzX9V3dv82eYf17ilWIo3aF dBDrqMkGqu6qcM2vmczxh8rXCTqcqI6+N8bTt6ozCZadlMYaa3G48ozwGhwHqIOOuOKVff6bzX9V 3dv82eYf17ilPpvNf1Xd2/zZ5h/XuKU+m81/Vd3b/NnmH9e4pT6bzX9V3dv82eYf17ilPpvNf1Xd 2/zZ5h/XuKU+m81/Vd3b/NnmH9e4pT6bzX9V3dv82eYf17ilPpvNf1Xd2/zZ5h/XuKU+m81/Vd3b /NnmH9e4pT6bzX9V3dv82eYf17ilMbvNf1Xt28fzdZ5h/XuKVi4+Il0fIL8W/o7337++R/5SPdXy f59X5P8AKTfKt8ROnvXy/lU+Tf8A88+4vF5/ovb4/H95xSv/1N/jilOKU4pTilOKU4pTilOKU4pT ilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOK U4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pT ilOKU4pTilOKU4pTilOKU4pTilOKV//V3+OKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOK U4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pT ilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOK U4pTilOKU4pX/9bf44pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilU7LpZHIHFpFNpg 8Io9FYmyOkjkb65G+Q3tDIzIjnBzcVh2cZ8tMjRpxjFnpnPQPsxnPTHOCTJjw40iZLeS3FaQpa1H gEpSLqJ9QAvV0weEy+5s1iNubfxzsvPZCS1HjMNjU48+8sNtNoHepa1BI9vHhWqOp347qHdAtObs Pbxai6XoWEOWW/M3XEx9qVqShiNy2qpjPJK2u4kz+8JeigDMwp8noyBh8/J2MeeLy4rfXU/qbk50 fp60IWBYVYunSCfQXHVpVZSh4uW0LpB43+lX3iY8qXkU8jmx9rZXziT17n6sZVnmCA2X3EINhzEx IUVxkKjsqu0Zk9zQ64Dyw2Tyh83DdDu3drqxa2W76qWy7dep0/hYnB7RDib6qIAWDzHPMbl8faGJ 9QypsbQiWkIXggSdxKJMAX4RYGcTC949WOmU/Gub7Umdt19zSVjlqI/S0OISlYWB4glwWWAQO8jk jeW/7v3zy7S3tF8pzL+1useKhc9uO4JTKF34N+8RZDr7C4rjlmXH4iw5HWtCl3BS25W3c7vzbqze 4zrnrBqdszJ6ji110zAHKNqmGRvEbiytfM3adOY5U7qI+iPeVOVbGzJglZwAYiwFhwAIPGZnPd6l 53d2S6h7c2vtXcrkOJNhtqQUKUhBLhcVrUUAqN0pFvQOy1zWN+SDpP5eNl+TjrP136+9EoW489tn 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 Uk9xArw70s6lbq6O9RNo9TtlSks7nwsxEhgqF0KIulbTqQQVNPNKWy6kEEtrUAQSCNZOA6gd7Ttu rZTW2nzpDb6oZe9q3tgSOKqCDSpzV3l+Y4Dik7fY4/RV9UBAHC0hsXKW840Pm4yMWcix5tgbS60d OlycbtFxifgVOFSAot2BPfocUhTav0ghRQTx4mvtfurzCfdl+cyPg96+YuFk9pdWmoiGJC2kTtSw 3eyPeoTEhiUykk8lchhuQhB0EJAANw6K7V+6u3uz7BtJ3VJA0iZYSa2Ko7TLe8MDx73w0q8uDXFx tcQULodEYAQ4dFC8klSoXOw8jAdjHmDO5cMH0x3lu7csfdHVJ9HJYKSiMFJVq0m6UWbJbbavxUAV KXxB7SqsN6peefy1eXnofmOhPkLxUkZLKh1MrNOsvslrmo5bskOS0oly5xb+rYWpptiKNK276Et1 tDACEAQgDjAQgDgIQhxgIcBDjGMYwHHTGMYxj4Mc9L+wcK+IZJJuSSfTXtxSnFKcUpxSnFKcUpxS nFKcUpxSnFKcUpxSnFKcUpxSv//R3+OKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pT ilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOK U4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pT ilOKU4pX/9Lf44pTilOKU4pTilOKU4pTilOKU4pTilOKVx1Zwk6VSeAOBjITnHBCLOcBEIssQwhz nHtxjOQ8lI1KSn0moUbJUR2gVop6xbp/aD+5Y53XYuql31ozNVLydAkda2LYakiKEkyRe/F7AwMI JhCH9TICvRMZpIjnR1B1GHGRGYyLIsfQzd2wvLT0oZwOL3jt+W49PZUUv65LivBoSta+U6gIN1gg Nt9nYOFq834bcHU/d6503DZFpDccpu2EtAeLVYDWg3HhP0lfGazJ9o/u3bDbdSDYXUzZummqI7p6 3Q99fDUaXBkPZp8ujbsGKujHKGNUNeCESVrla9vJVGpTVDcpTrfUEAJCX4B6K609F9tbJi7Z3ntL Orf2HlX0IBP1qmQtPMSpCxYuoU2lZSFALSUaVFRNxsDZO98pnHcphctASjcERtSrfRCykhJCgfok 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 TtZNy/EAb0Ox3aJmNMgbkJ6dAiijm5BJLy1eQzBTiCcpVnYL4pUuN0O/RaLT2+O21fulNWQZxv3u fT2K1RXKa3ljirrKn5qpWJorOUkmUNCtpPelDHYirDWiEYemJEnKPWmgHgn0xilVT2+O5d3FGvuk z7tPdy+Ma2yqzCqMxfFeXHq0VK0UZC1llNqwxjlDZKTQKspl7esPwUcYia1KVWlCARaolWQeBSsq PdO3LsfQ3Syz9hqcoyU7F2yzGsUcrusIxHZPJSVslkriBEW/SxHD0qt/JhcVbwqHBwER5QjQJwp8 HECOCcBSte9h7ufec0l2G7d6HujVdqY9UF3HJSxwqNtdDIJkyW1Sb9KHGEt6NPKkr46nove0ZMsd rOcG/AHUo9OFQSWuLVFffKVdvbjurd1G6d+txtRu05B9Zj4h29KpSzW+Zhf7bJ3N3sGc5awvK+v4 Jhmd0yJO4CM85rQJjyEwVC1tWGnOBBWSA8Uqb2offb18sXtFRLuhbVq0dOtTS4O9c2/HIc0SCUFp rlYX5QwEReDNBOHJ4U/HkrKJwbSVR+QIyHEAFSrASTFGVKjZ2Iu87sd3Vdqu4FF7TgDDVlP0v8nj 7RVfHRdazWbGYxNpBOUaFHZjuqc1BTzIT4+wITz/ACUycgtSaZ5XiKyDPFKj3ZPd57um6uzu8tf9 nyoNanGje3svcIrNpTeKOTvs22CsdlVyNAph1XIWh4bG0blJXKFuxTGgwAj1BCco5Q5EDWp04VK2 QNDbwvTYrVKo7Z2Z1+ker99SFmWJ7QpiSJzkp0bk7M6rmhQvZyVatc4ExmUEIy3NuKVmDWJkqsBB 4hGlDGJSpfcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSv/9Lf44pTilOK U4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pWjT29ah0z2S71vflB3OojSdk2 zEbXJb6eYdmMRxwZ2egELzYTGqeog0zc33MQUy1s3QoAXIoOFTa3nEjTmFAPNEJSoB9tG7dL9Ye2 f9oKl03q112G06BtlBK8gVSxOeSiFBtCDSeayyOVCyG2RH3BLJWGKq0JjcoXLwGmHGNxRgclqBG+ QapVkdwKen1Y2j2Q7Redce2Tp1H7L2UoWSURV+kyiSyHYxVXB8wqh6b5jsPbLuqUBsQtPlxRkpl2 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 IIlaxJHkT1UpyLCsf6T561MEQgYOxxSuVSdkTvuAd1Tu2dzPtyJ5PO4FWXbBkWt2rVuZh8gjbLZO 1CyGxWQxtoiCSZtbQpdXBgfo8qAIg5OX4DfRiOAElUSI1SsDcVX6zIdcO3qs0UaL1/yjNFt4sX3o WUzXWK1hPK+V2BmxzboRypPmFCizgS5s4DsFgCbhAYt94+Ev3j1Ur9UQnzfJK8/wYO8ovzsF9fLw b4MeZ5fX2+Dx9en+ZxSvrxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcU pxSv/9Pf44pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pXjPX2dM9Pb7fZ1646Z9nw46e3 ioIPCxtx4154qacUpxSnFKcUroXqKxeSiRDkcbYX8badlQ3DemdvdRIFGcgzk9EJcnPylOzksOfE X4Rfe49vs4pXZrUCFzRqW5xRpHBvWEDTK0C1OSqRqkxocgMTqUp4DCDyDAZ6CAIOQ5x8OOKV6JGx tQEpE6FvQok6BOBGhISJCExKJIUDyy0qQoksAEycsH3oQAwEOMezGOKV9PQovKGT6RL5Ix+YMr05 XlDM9n34y/B4RD9mPbnHX2cUriL2JkdT2xU6MzU5KWVVhczKF7ekWHtK0OMBwsbDVBJhiBVjAcYw YVkA+mPh4pXYFkEFCMGUSUUM4XjOEWWAAjR9c58Rgg4xkYuos+3PXPt4pXVPsbjsoSBb5KwssiQA OCoAifWtC7JAHgwIIDwpl5CgkJwAizjAsB8WMZz7eKV2pJBCcgpMQSUQmIKAQSnJLAWQSQWDBZZJ RQMBLLKLLDgIQ4xjGMY6Y9nFK6tljkfjSc5JHGJmYEqhQNWoTMrWiak56s3GMGqjiUJBBZqgzAce IYsZFnp7c8Urylj0fQubi9oWNnRvLvgoLs7JWxEnc3QJIcAJC4rySAKluCg46BwaMXhx8HFK+bXG Y2xpMoGWPsbOhypGtyia2lA3pMrDfaYrymSJySfUmf8AhGeHx5+7ni9K7cJBATRnhJKCcZjATDgl gwaYHHTGAjMxjxixjAcezOfucUr54Ro8EiT4SpsJxi8QiMEFYJELrjPiEV4fBkXUOM9c4+5xSuvc 47H3rLdl4YmZ2Ezqi1zRlzbES/LWtKxjBSxuyqINyiVF4x0CYV4R4xj2Z4pXYZRIxYOxlImzhQII 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 OQXwJ9J0r+Q+g1kPUMpOMxFu9w29mkfsVtlasonNt1j1ybnrA8PKCiKhRO2DQiAbhzS19HiF+DAi wEQR4VFj64zjGcZ58dOrciJK6rdTZUC3uLm4citu3Zy1THii3q0kVsCAFJgwkr+kGkX9ukVrHd9y 1WFo2ygEIvrvSWNpPQZdap1bXqLpPG7KV7fzyZOxykhvlEidK4TyARzA/rixloi3ctEhLTIfCnJM POPVY17XbqDfZf7he2lia6d+KkpXsjsNbMR1HoO1Zxq3aWwXvVl2eg5eYnfKBmUylyXOLnJmCTFE QxocBN6hcpEyOpJwU5gQizjilRdrVk7lOwHYPfu6tMu7TuawT7XHE8X0/WkJnbkwsL6xwy5QsD05 XNLErmVMLLmLi4ubkBCpXqTSG5rTIkYShlBGDilZhpzMLM3P7MGkXcm2I7p+xfb2S1hr7LX2+ZPr meFkOviVKpE3wtmUL2FpkcWLdZ28ukFyBpbUgMlnOL8cWUAkvOMBUqJv2eFo7m97MO0XcCvXcTb+ SaiNNXXTCdXYLfdmSeTvFpu+ETgYXap6BW9KWJtxW5TKBKUvRFGFqntQpLTHYAiO8xSo4a4d5bdf Xr7NLaG2Dpdc6t/aKcb1yPWmurduV/dLNkFfNkgryJSY12QnSs9zCsHG2ZldRtSdVk1GQ5LQnDKN AERI1Kyka/dqTvCVsk0924197v1qWzZc6b4PZG1dS7iTKfyrXqRsMvjDbJnaNwSJNSeXnYLIOWja ixDA3KgEjCsSK0JhQU+VKx0WVRNz7K/a092KZpnY+d6pHS/W2KE2TcNUomg61W6s0mu+uh7xH65e Hko4iIyGRyYLSQJ3JB6xGi8/JGcGCxxSrndvnuCbb9vW9u+rqvcOwll7p1x26KEsm8qRe78f3WTz Y6QwVxbkMfYXKTLl6t9Jj8rDMEAHVKFUNMnORCORAI80wI1KwttHdOuSW64SPeN470m6bL3OjZm4 y6F6dRmtLSU6jjjCKfktpNeqmpHGVNLYKcokUe6E/wA+2kgwUhUkjUZNUBUr9Hjtx7QvW6Wi2rm0 knYEsXllzVHHJRMY+gKVENrXMywHM8wTtRC4Q1pDR8ZWtUJIA0QzAJhAwIQs4yLKlaB/2gmspHA+ 76RNJ5Q83aK9s6SQp/j5MjvVKIm/2lnkaJqkz5EZcRhUCg2Zyz5bMQiNCIxlCmA5CD0UYDj9UX3b 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 KGUw3HsjN5qnI8dhPu8hHMSsnXKQ2nisirnn28rB23FCsuU5BtY1KSpQU6TqAQm1iTxHd+aTUx+5 f2l3Luh6W66wqRWCrrHaGjoxGpFEZ9JALXlEKZO0NjjdYcbneEQ8u40sidGYg4xwS5MVo1yMs4ID gZNJM0j5VvOOz5S+uvUncGH203lekmflyGJMJrS0v3VuS8uE9E1DlhTDbi0pZcs2406pBUg6FouO c28c9jIbS3uXPaSClR4i5A1BXfxI7RxBHf2VAnXrsc76XjuJSG1Xd12mr690WryWOpKngldhWLjZ Qog7tl+iRkvcBwOu2tE0gkuQubkZlK4Oj4aSAlUaAvOc89C9SPPv5edgdEN/dHvJV0iyW3Hd3OOq yMyfpTyEym+TJTFQJc1alli7DA5jTEUKU4yhS6tUPa2WlZKJP3FPQ6I4GhKe/TxFzpSO3ieBKuw1 MPu8dmqe7q2/S25+oNyNFA7qUNhkTR+SSYtfiIS1sij2rk8OMXL2lqfVzDJYo9rlHkKRNzilXo1I kqonywFiDpfyYed3AdCNmb86GdaNlP7j6Cbj5qn47BR7zGckNJYk8tDjjSHWZDSEakc9lxp1AeZc 1KUFXHcW2ncpIi5LHSQzlGrWJ7CAbp4gGxB9RBBsRVsO3B2YNlYFuzIe5X3L78h9/bVHNihBBGmA JlAorFVqyNfEkckclx8XhTf61ohPjbGtsbWlOgRAPMUZMNP8vJeV+ZzzydL9x9BsZ5VvKt06nbb6 NJfDktyaoe9SEpf96DCEh+UvQ5Ks/IffkLedKEthKG9Wrgwu2ZrOUXnM5LS9kLWSE/RHDTfsT2J4 AAWHb21sq8+XlZrTilOKU4pX/9ff44pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOK U4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilOKU4pTilQD7qX/ANrd3d/5 NVrftWX89DeUr/Oc6Df96cd/zhFWnPf+xcn/ALgr8VSO1m/g4UB+JWrf2jsfNX9S/wDGT1D/AOns h/zt6u5C/wCBRP8Ackf7EVe7mE12qcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnFKcUpxSnF KcUpxSnFKcUpxSnFKxS9zD90rtj/AP3QmvP3srT5608sH/ZjzUf/AOtpv/PsfWP5z9+wf9uJ/wBg usrXPJdZBTilOKU4pTilOKU4pTilf//Z --rPu1PusGJaR2H3wT9yaaJ=_oALXqJgROTh Content-Type: image/jpeg; name="offerte-vieste-marina.jpg" Content-Transfer-Encoding: base64 Content-Disposition: inline; filename="offerte-vieste-marina.jpg" Content-ID: <015522113@17062016-288E> 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 2vUP+r83X+j9ny/DqpVspXPI+Q+7yif/2Q== --rPu1PusGJaR2H3wT9yaaJ=_oALXqJgROTh-- From bfoster@redhat.com Fri Jun 17 12:34:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6B97B7CB1 for ; Fri, 17 Jun 2016 12:34:31 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id F3AE3AC001 for ; Fri, 17 Jun 2016 10:34:30 -0700 (PDT) X-ASG-Debug-ID: 1466184869-04bdf01e15b7860001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id Jm07AzBbtalhVc0p (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 10:34:29 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3F53370A9B; Fri, 17 Jun 2016 17:34:29 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5HHYSkJ008647; Fri, 17 Jun 2016 13:34:29 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 76C34123469; Fri, 17 Jun 2016 13:34:27 -0400 (EDT) Date: Fri, 17 Jun 2016 13:34:27 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 003/119] xfs: check offsets of variable length structures Message-ID: <20160617173426.GA46309@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 003/119] xfs: check offsets of variable length structures References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612629195.12839.14090954204243398929.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612629195.12839.14090954204243398929.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Fri, 17 Jun 2016 17:34:29 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466184869 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4006 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:18:12PM -0700, Darrick J. Wong wrote: > Some of the directory/attr structures contain variable-length objects, > so the enclosing structure doesn't have a meaningful fixed size at > compile time. We can check the offsets of the members before the > variable-length member, so do those. > > Signed-off-by: Darrick J. Wong > --- I'm missing why this is necessary. Is the intent still to catch alignment and/or padding issues? If so, isn't the size check sufficient, regardless of trailing variable size fields? Perhaps the goal here is to reduce the scope of checking from where it isn't needed..? For example, xfs_dir2_data_unused_t looks like it has a field where the offset in the structure is irrelevant, so that's a possible false positive if that changes down the road. On the flip side, that doesn't appear to be the case for other structures such as xfs_attr_leaf_name_[local|remote]_t. Brian > fs/xfs/xfs_ondisk.h | 25 +++++++++++++++++++++++-- > 1 file changed, 23 insertions(+), 2 deletions(-) > > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h > index 184c44e..0272301 100644 > --- a/fs/xfs/xfs_ondisk.h > +++ b/fs/xfs/xfs_ondisk.h > @@ -22,6 +22,11 @@ > BUILD_BUG_ON_MSG(sizeof(structname) != (size), "XFS: sizeof(" \ > #structname ") is wrong, expected " #size) > > +#define XFS_CHECK_OFFSET(structname, member, off) \ > + BUILD_BUG_ON_MSG(offsetof(structname, member) != (off), \ > + "XFS: offsetof(" #structname ", " #member ") is wrong, " \ > + "expected " #off) > + > static inline void __init > xfs_check_ondisk_structs(void) > { > @@ -75,15 +80,28 @@ xfs_check_ondisk_structs(void) > XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_remote_t, 12); > */ > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, valuelen, 0); > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, namelen, 2); > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, nameval, 3); > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valueblk, 0); > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valuelen, 4); > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, namelen, 8); > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, name, 9); > XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t, 40); > - XFS_CHECK_STRUCT_SIZE(xfs_attr_shortform_t, 8); > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.totsize, 0); > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.count, 2); > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].namelen, 4); > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].valuelen, 5); > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].flags, 6); > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].nameval, 7); > XFS_CHECK_STRUCT_SIZE(xfs_da_blkinfo_t, 12); > XFS_CHECK_STRUCT_SIZE(xfs_da_intnode_t, 16); > XFS_CHECK_STRUCT_SIZE(xfs_da_node_entry_t, 8); > XFS_CHECK_STRUCT_SIZE(xfs_da_node_hdr_t, 16); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_free_t, 4); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_hdr_t, 16); > - XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_unused_t, 6); > + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, freetag, 0); > + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, length, 2); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_hdr_t, 16); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_t, 16); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_ino4_t, 4); > @@ -94,6 +112,9 @@ xfs_check_ondisk_structs(void) > XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_t, 16); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_tail_t, 4); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_entry_t, 3); > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, namelen, 0); > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, offset, 1); > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, name, 3); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_hdr_t, 10); > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_off_t, 2); > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Fri Jun 17 12:38:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E5DDA7CB6 for ; Fri, 17 Jun 2016 12:38:52 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4C88BAC002 for ; Fri, 17 Jun 2016 10:38:51 -0700 (PDT) X-ASG-Debug-ID: 1466185129-04cbb01fed88910001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 6BhZAbFpkpkgtwyq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 10:38:50 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 734A763303; Fri, 17 Jun 2016 17:38:49 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5HHcn1n016380; Fri, 17 Jun 2016 13:38:49 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id AA7D5123469; Fri, 17 Jun 2016 13:38:47 -0400 (EDT) Date: Fri, 17 Jun 2016 13:38:47 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: Christoph Hellwig , linux-fsdevel@vger.kernel.org, xfs@oss.sgi.com, vishal.l.verma@intel.com Subject: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE Message-ID: <20160617173847.GB46309@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 002/119] vfs: support FS_XFLAG_REFLINK and FS_XFLAG_COWEXTSIZE References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612628567.12839.3246258786290141903.stgit@birch.djwong.org> <20160617114117.GF19042@infradead.org> <20160617121604.GB23661@bfoster.bfoster> <20160617165400.GC6376@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617165400.GC6376@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 17 Jun 2016 17:38:49 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466185130 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3731 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jun 17, 2016 at 09:54:00AM -0700, Darrick J. Wong wrote: > On Fri, Jun 17, 2016 at 08:16:05AM -0400, Brian Foster wrote: > > On Fri, Jun 17, 2016 at 04:41:17AM -0700, Christoph Hellwig wrote: > > > On Thu, Jun 16, 2016 at 06:18:05PM -0700, Darrick J. Wong wrote: > > > > Introduce XFLAGs for the new XFS reflink inode flag and the CoW extent > > > > size hint, and actually plumb the CoW extent size hint into the fsxattr > > > > structure. > > > > > > > > Signed-off-by: Darrick J. Wong > > > > > > Should go behind all the updates that are useful without any new > > > rmap or reflink functionality. In fact it would be great if you > > > could send out a series with just those little fixes and cleanups > > > first. > > > > > > > I'd take that a step further and suggest the entire series be split into > > independent feature series, as appropriate. Unless I'm missing > > something, I don't think there's any reason these all need to be bundled > > together. Further, my expectation is that they probably end up being > > merged as independent units, so I think it's easier for everybody for > > Darrick to carve that up on the logical boundaries rather than assume > > all reviewers and maintainer are going to do so consistently. > > > > Note that I'm not saying this has to be reposted.. I think I can pull > > off the rmap bits for the time being. I'm just suggesting that if a > > repost is required from this point forward for any of the logical > > subunits (deps, rmap, reflink, scrub), I'd suggest to post, version and > > changelog those units independently. > > I'd thought about continuing my old practice of listing which patches > go with which feature... but then got lazy. :( Cleanups/rmap/reflink/scrub > actually are in their own contiguous sections of the patchbomb, though that > isn't obvious from looking at it. > Yeah, I figured as much. I was able to surmise where the rmap stuff ends. It's not so clear where the line between cleanups vs. dependencies is, however, and as hch mentioned, some of that stuff apparently stands on its own (i.e, can be merged without being blocked on rmap review/test/dev cycles). > You ought to be able to pull only as far as the end of the rmap series and > still have a working XFS. I only did the intensive testing with the full > patchset, but the quick xfstests group ran fine with just the rmap pieces. > Ok. I'll probably end up testing more with just the rmap bits. > Kernel patches: > =============== > Cleanups, 1-11 > rmap + dependencies, 12-49 > Overlapped interval btree, 12-15 > Deferred operations, 16-22 > rmap, 23-49 Thanks. I still stand by my previous comment wrt to splitting any subsequent postings, if necessary, into separate series though. ;) Brian > reflink + dependencies, 50-111 > AG reservations, 50-52 > refcount btree, 53-68 > deferred remap, 69-73 > cow, 74-88 > reflink, 89-111 > getfsmapx, 112 > scrub, 113-119 > > xfsprogs: > ========= > Cleanups, 1-15 > rmap + deps, 16-70 > Overlapped interval btree, 16-19 > Deferred operations, 20-27 > rmap, 28-70 > reflink + dependencies, 71-135 > AG reservations, 71-72 > refcount btree, 73-85 > deferred remap, 86-90 > reflink, 91-135 > getfsmapx, 136-138 > scrub, 139-145 > > --D > > > > > Brian > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From vishal.l.verma@intel.com Fri Jun 17 14:27:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_FOLLOW1,T_FRT_FOLLOW2 autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 63F607CB0 for ; Fri, 17 Jun 2016 14:27:13 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 297128F8054 for ; Fri, 17 Jun 2016 12:27:10 -0700 (PDT) X-ASG-Debug-ID: 1466191628-04cbb01fec8b490001-NocioJ Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by cuda.sgi.com with ESMTP id 51dDgYiJFmDiLFLI for ; Fri, 17 Jun 2016 12:27:08 -0700 (PDT) X-Barracuda-Envelope-From: vishal.l.verma@intel.com X-Barracuda-Effective-Source-IP: mga03.intel.com[134.134.136.65] X-Barracuda-Apparent-Source-IP: 134.134.136.65 X-ASG-Whitelist: Client Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga103.jf.intel.com with ESMTP; 17 Jun 2016 12:27:08 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,484,1459839600"; d="scan'208";a="990031248" Received: from omniknight.lm.intel.com ([10.232.112.171]) by fmsmga001.fm.intel.com with ESMTP; 17 Jun 2016 12:27:07 -0700 Date: Fri, 17 Jun 2016 13:26:47 -0600 From: Vishal Verma To: "Darrick J. Wong" Cc: linux-nvdimm@ml01.01.org, xfs@oss.sgi.com, Jan Kara Subject: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks Message-ID: <20160617192647.GC5893@omniknight.lm.intel.com> X-ASG-Orig-Subj: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> <1466125419-17736-3-git-send-email-vishal.l.verma@intel.com> <20160617022606.GC11810@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617022606.GC11810@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Barracuda-Connect: mga03.intel.com[134.134.136.65] X-Barracuda-Start-Time: 1466191628 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8816 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On 06/16, Darrick J. Wong wrote: > On Thu, Jun 16, 2016 at 07:03:39PM -0600, Vishal Verma wrote: > > RFC/WIP commit. > > > > This adds the foollowing: > > 1. In xfs_mountfs(), get an initial badblocks list from gendisk's > > badblocks infrastructure. > > 2. Register with the badblocks notifier to get updates for this disk's > > badblocks > > > > TODO: > > 1. Add badblocks info to the reverse mapping tree (and remove if a > > badblock was cleared). > > Well... there are a number of things we /could/ do... theoretically one > could use the rmap info to find all the affected inodes and simply convert > that part of their extent trees to 'unwritten'. Reads will just get zeroes, Hm, not sure we can do that - if a block became bad at some point, subsequent reads _have to_ error out (-EIO) so that the user doesn't see silent data corruption. > and writes will remove the unwritten flag (for that file, anyway). Will a > successful write trigger the BB_CLEAR notifier? Currently, a successful write that goes through the driver (i.e. not DAX) will cause the badblock to get cleared, and trigger BB_CLEAR. DAX is trickier, and currently DAX writes won't clear errors. > > I guess you could punch out the bad blocks too... not clear if you'd want > all the owner files staying mapped to data they'll never get back. The block mappings don't have to be maintained, but some sort of a flag needs to be kept that will allow us to return errors on reads like I said above. > > We could also create another rmap "special owner" (XFS_RMAP_OWN_BAD?) for bad > blocks, so we'd know which parts are just plain bad. It might be useful to > know that kind of thing. > > I think earlier Dave was talking about adding a new 'badblocks' bit to both > the file extent records and the rmap records to signify that something's > wrong with the extent. I'll let him write about that. > > > 2. Before doing file IO, refer the rmap/badblocks to error out early if > > the IO will attempt wo read a bad sector > > 3. Figure out interactions with mmap/DAX. > > Woot. > > > Cc: Darrick J. Wong > > Cc: Dave Chinner > > Signed-off-by: Vishal Verma > > --- > > fs/xfs/xfs_linux.h | 1 + > > fs/xfs/xfs_mount.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > > fs/xfs/xfs_mount.h | 1 + > > 3 files changed, 106 insertions(+) > > > > diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h > > index 7e749be..f66d181 100644 > > --- a/fs/xfs/xfs_linux.h > > +++ b/fs/xfs/xfs_linux.h > > @@ -78,6 +78,7 @@ typedef __u32 xfs_nlink_t; > > #include > > #include > > #include > > +#include > > > > #include > > #include > > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c > > index 5e68b2c..1a47737 100644 > > --- a/fs/xfs/xfs_mount.c > > +++ b/fs/xfs/xfs_mount.c > > @@ -618,6 +618,96 @@ xfs_default_resblks(xfs_mount_t *mp) > > return resblks; > > } > > > > +STATIC int > > +xfs_notifier_call( > > + struct notifier_block *nb, > > + unsigned long action, > > + void *data) > > +{ > > + struct bb_notifier_data *bb_data = data; > > + struct xfs_mount *mp; > > + > > + mp = container_of(nb, struct xfs_mount, m_badblocks_nb); > > + /* TODO xfs_add_bb_to_rmap(mp, bb_data->sector, bb_data->count); */ > > + xfs_warn(mp, "xfs badblock %s sector %lu (count %d)\n", > > + (action == BB_ADD)?"added":"cleared", > > + bb_data->sector, bb_data->count); > > + return 0; > > Probably a xfs_rmapbt_query_range here? > > > +} > > + > > +STATIC int > > +xfs_init_badblocks(struct xfs_mount *mp) > > +{ > > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > > + int done = 0, error = 0; > > + ssize_t len, off = 0; > > + char *p; > > + > > + /* > > + * TODO: get a list of known badblocks so far and process it. > > + * Can we just parse the sysfs format that badblocks_show() > > + * returns? That should be the fastest way to get this. > > + * Something like: (Is this too hacky? Should we just do > > + * badblocks_check() in a (rather large) loop?) > > + */ > > + p = kzalloc(PAGE_SIZE, GFP_KERNEL); > > + len = badblocks_show(bb, p, 0); > > + while (len) { > > + int count, n; > > + sector_t s; > > + > > + /* > > + * The sysfs badblocks format is multiple lines of: > > + * " " > > + */ > > + n = sscanf(p + off, "%lu %d\n%n", &s, &count, &done); > > Ick, there's got to be a better way to iterate the badblocks list than this. > > It would be very nice to have a single function that deals with a change in > badness status, which would be called by both the notifier and the badblocks > iterator. > There is a function in block/badblocks.c - badblocks_check() which can tell you for a given range, what is the first bad sector in that range, and the number of bad sectors after that first sector. Using that would certainly be cleaner, as it uses the well-defined API, but it would be much slower, as you have to iterate through the entire address space. The above function - badblocks_show - just looks at the actual stored representation of the badblocks, and lists them out, which is quick (reading a 4K page from memory), and so in the above, I just parse it.. > > + if (n < 2 || done < 3) { > > + error = -1; > > + break; > > + } > > + off += done; > > + len -= done; > > + xfs_warn(mp, "got badblocks: sector %ld, count %d", s, count); > > + /* TODO xfs_add_bb_to_rmap(mp, s, count); */ > > + } > > + kfree(p); > > + if (error) > > + return error; > > + > > + mp->m_badblocks_nb.notifier_call = xfs_notifier_call; > > + error = bb_notifier_register(bb, &mp->m_badblocks_nb); > > + if (error) > > + return error; > > + > > + /* > > + * TODO: There is probably a TOCTOU race hiding here - what if the > > + * badblocks list gets updated before we register for notifications.. > > + * Can likely be solved by registering for notifications _first_ (the > > + * above xfs_add_bb_to_rmap function has to be ready to accept new > > + * blocks), then querying for the initial list (there could be overlap > > + * here, shich the above function could handle), and then setting the > > + * mount flag below. > > + */ > > (Yeah, pretty much. :)) > > > + > > + /* > > + * TODO: set some flag (mount flag?) in xfs so that xfs knows > > + * it will be doing error checking, and can possibly, later, > > + * tell the block layer (possibly using a REQ_ flag in its IO > > + * requests) not to do further badblock checking for those IOs. > > + */ > > + > > + /* mp->m_flags |= XFS_MOUNT_FS_BADBLOCKS; */ > > + return 0; > > +} > > + > > +STATIC void > > +xfs_badblocks_unmount(struct xfs_mount *mp) > > +{ > > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > > + > > + bb_notifier_unregister(bb, &mp->m_badblocks_nb); > > +} > > + > > /* > > * This function does the following on an initial mount of a file system: > > * - reads the superblock from disk and init the mount struct > > @@ -955,6 +1045,19 @@ xfs_mountfs( > > } > > > > /* > > + * Register with the badblocks notifier chain > > + */ > > + error = xfs_init_badblocks(mp); > > + if (error) { > > + xfs_warn(mp, "Unable to register to badblocks notifications\n"); > > + /* > > + * TODO is this a hard error or can we simply > > + * warn and continue? > > + */ > > + goto out_rtunmount; > > + } > > + > > + /* > > * Now we are mounted, reserve a small amount of unused space for > > * privileged transactions. This is needed so that transaction > > * space required for critical operations can dip into this pool > > @@ -1085,6 +1188,7 @@ xfs_unmountfs( > > xfs_log_unmount(mp); > > xfs_da_unmount(mp); > > xfs_uuid_unmount(mp); > > + xfs_badblocks_unmount(mp); > > > > #if defined(DEBUG) > > xfs_errortag_clearall(mp, 0); > > diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h > > index 0ca9244..f0d1111 100644 > > --- a/fs/xfs/xfs_mount.h > > +++ b/fs/xfs/xfs_mount.h > > @@ -139,6 +139,7 @@ typedef struct xfs_mount { > > /* low free space thresholds */ > > struct xfs_kobj m_kobj; > > struct xstats m_stats; /* per-fs stats */ > > + struct notifier_block m_badblocks_nb; /* disk badblocks notifier */ > > > > struct workqueue_struct *m_buf_workqueue; > > struct workqueue_struct *m_data_workqueue; > > -- > > 2.5.5 > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Fri Jun 17 14:53:58 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_FOLLOW1,T_FRT_FOLLOW2, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0C7AB7CA2 for ; Fri, 17 Jun 2016 14:53:58 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5EF0BAC002 for ; Fri, 17 Jun 2016 12:53:54 -0700 (PDT) X-ASG-Debug-ID: 1466193231-04cb6c54256da10001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id uTlO5Kc3NokzfZjO (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 12:53:51 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5HJrlsF005392 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 19:53:48 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5HJrleB031666 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 17 Jun 2016 19:53:47 GMT Received: from abhmp0005.oracle.com (abhmp0005.oracle.com [141.146.116.11]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5HJrkIu032479; Fri, 17 Jun 2016 19:53:47 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 17 Jun 2016 12:53:46 -0700 Date: Fri, 17 Jun 2016 12:53:45 -0700 From: "Darrick J. Wong" To: Vishal Verma Cc: linux-nvdimm@ml01.01.org, xfs@oss.sgi.com, Jan Kara Subject: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks Message-ID: <20160617195345.GA5046@birch.djwong.org> X-ASG-Orig-Subj: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> <1466125419-17736-3-git-send-email-vishal.l.verma@intel.com> <20160617022606.GC11810@birch.djwong.org> <20160617192647.GC5893@omniknight.lm.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617192647.GC5893@omniknight.lm.intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466193231 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9823 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30526 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 17, 2016 at 01:26:47PM -0600, Vishal Verma wrote: > On 06/16, Darrick J. Wong wrote: > > On Thu, Jun 16, 2016 at 07:03:39PM -0600, Vishal Verma wrote: > > > RFC/WIP commit. > > > > > > This adds the foollowing: > > > 1. In xfs_mountfs(), get an initial badblocks list from gendisk's > > > badblocks infrastructure. > > > 2. Register with the badblocks notifier to get updates for this disk's > > > badblocks > > > > > > TODO: > > > 1. Add badblocks info to the reverse mapping tree (and remove if a > > > badblock was cleared). > > > > Well... there are a number of things we /could/ do... theoretically one > > could use the rmap info to find all the affected inodes and simply convert > > that part of their extent trees to 'unwritten'. Reads will just get zeroes, > > Hm, not sure we can do that - if a block became bad at some point, > subsequent reads _have to_ error out (-EIO) so that the user doesn't see > silent data corruption. Ooh, right, forgot about that whole MCE-on-bad-read thing... > > and writes will remove the unwritten flag (for that file, anyway). Will a > > successful write trigger the BB_CLEAR notifier? > > Currently, a successful write that goes through the driver (i.e. not > DAX) will cause the badblock to get cleared, and trigger BB_CLEAR. DAX > is trickier, and currently DAX writes won't clear errors. Oh...? > > > > I guess you could punch out the bad blocks too... not clear if you'd want > > all the owner files staying mapped to data they'll never get back. > > The block mappings don't have to be maintained, but some sort of a flag > needs to be kept that will allow us to return errors on reads like I > said above. What happens if pmem signals a bad block and we try to read anyway? I know about the read-error-MCE thing, but what's the "more expensive" alternative? CPU exception? (Really what I'm digging at is, if the whole thing becomes a soft exception that we can handle in the OS by, say, 2020, do we care about reintroducing the whole ext2 badblocks thing?) (Beats me...) --D > > > > > We could also create another rmap "special owner" (XFS_RMAP_OWN_BAD?) for bad > > blocks, so we'd know which parts are just plain bad. It might be useful to > > know that kind of thing. > > > > I think earlier Dave was talking about adding a new 'badblocks' bit to both > > the file extent records and the rmap records to signify that something's > > wrong with the extent. I'll let him write about that. > > > > > 2. Before doing file IO, refer the rmap/badblocks to error out early if > > > the IO will attempt wo read a bad sector > > > 3. Figure out interactions with mmap/DAX. > > > > Woot. > > > > > Cc: Darrick J. Wong > > > Cc: Dave Chinner > > > Signed-off-by: Vishal Verma > > > --- > > > fs/xfs/xfs_linux.h | 1 + > > > fs/xfs/xfs_mount.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > > > fs/xfs/xfs_mount.h | 1 + > > > 3 files changed, 106 insertions(+) > > > > > > diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h > > > index 7e749be..f66d181 100644 > > > --- a/fs/xfs/xfs_linux.h > > > +++ b/fs/xfs/xfs_linux.h > > > @@ -78,6 +78,7 @@ typedef __u32 xfs_nlink_t; > > > #include > > > #include > > > #include > > > +#include > > > > > > #include > > > #include > > > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c > > > index 5e68b2c..1a47737 100644 > > > --- a/fs/xfs/xfs_mount.c > > > +++ b/fs/xfs/xfs_mount.c > > > @@ -618,6 +618,96 @@ xfs_default_resblks(xfs_mount_t *mp) > > > return resblks; > > > } > > > > > > +STATIC int > > > +xfs_notifier_call( > > > + struct notifier_block *nb, > > > + unsigned long action, > > > + void *data) > > > +{ > > > + struct bb_notifier_data *bb_data = data; > > > + struct xfs_mount *mp; > > > + > > > + mp = container_of(nb, struct xfs_mount, m_badblocks_nb); > > > + /* TODO xfs_add_bb_to_rmap(mp, bb_data->sector, bb_data->count); */ > > > + xfs_warn(mp, "xfs badblock %s sector %lu (count %d)\n", > > > + (action == BB_ADD)?"added":"cleared", > > > + bb_data->sector, bb_data->count); > > > + return 0; > > > > Probably a xfs_rmapbt_query_range here? > > > > > +} > > > + > > > +STATIC int > > > +xfs_init_badblocks(struct xfs_mount *mp) > > > +{ > > > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > > > + int done = 0, error = 0; > > > + ssize_t len, off = 0; > > > + char *p; > > > + > > > + /* > > > + * TODO: get a list of known badblocks so far and process it. > > > + * Can we just parse the sysfs format that badblocks_show() > > > + * returns? That should be the fastest way to get this. > > > + * Something like: (Is this too hacky? Should we just do > > > + * badblocks_check() in a (rather large) loop?) > > > + */ > > > + p = kzalloc(PAGE_SIZE, GFP_KERNEL); > > > + len = badblocks_show(bb, p, 0); > > > + while (len) { > > > + int count, n; > > > + sector_t s; > > > + > > > + /* > > > + * The sysfs badblocks format is multiple lines of: > > > + * " " > > > + */ > > > + n = sscanf(p + off, "%lu %d\n%n", &s, &count, &done); > > > > Ick, there's got to be a better way to iterate the badblocks list than this. > > > > It would be very nice to have a single function that deals with a change in > > badness status, which would be called by both the notifier and the badblocks > > iterator. > > > There is a function in block/badblocks.c - badblocks_check() which can > tell you for a given range, what is the first bad sector in that range, > and the number of bad sectors after that first sector. Using that would > certainly be cleaner, as it uses the well-defined API, but it would be > much slower, as you have to iterate through the entire address space. > The above function - badblocks_show - just looks at the actual stored > representation of the badblocks, and lists them out, which is quick > (reading a 4K page from memory), and so in the above, I just parse it.. > > > > + if (n < 2 || done < 3) { > > > + error = -1; > > > + break; > > > + } > > > + off += done; > > > + len -= done; > > > + xfs_warn(mp, "got badblocks: sector %ld, count %d", s, count); > > > + /* TODO xfs_add_bb_to_rmap(mp, s, count); */ > > > + } > > > + kfree(p); > > > + if (error) > > > + return error; > > > + > > > + mp->m_badblocks_nb.notifier_call = xfs_notifier_call; > > > + error = bb_notifier_register(bb, &mp->m_badblocks_nb); > > > + if (error) > > > + return error; > > > + > > > + /* > > > + * TODO: There is probably a TOCTOU race hiding here - what if the > > > + * badblocks list gets updated before we register for notifications.. > > > + * Can likely be solved by registering for notifications _first_ (the > > > + * above xfs_add_bb_to_rmap function has to be ready to accept new > > > + * blocks), then querying for the initial list (there could be overlap > > > + * here, shich the above function could handle), and then setting the > > > + * mount flag below. > > > + */ > > > > (Yeah, pretty much. :)) > > > > > + > > > + /* > > > + * TODO: set some flag (mount flag?) in xfs so that xfs knows > > > + * it will be doing error checking, and can possibly, later, > > > + * tell the block layer (possibly using a REQ_ flag in its IO > > > + * requests) not to do further badblock checking for those IOs. > > > + */ > > > + > > > + /* mp->m_flags |= XFS_MOUNT_FS_BADBLOCKS; */ > > > + return 0; > > > +} > > > + > > > +STATIC void > > > +xfs_badblocks_unmount(struct xfs_mount *mp) > > > +{ > > > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > > > + > > > + bb_notifier_unregister(bb, &mp->m_badblocks_nb); > > > +} > > > + > > > /* > > > * This function does the following on an initial mount of a file system: > > > * - reads the superblock from disk and init the mount struct > > > @@ -955,6 +1045,19 @@ xfs_mountfs( > > > } > > > > > > /* > > > + * Register with the badblocks notifier chain > > > + */ > > > + error = xfs_init_badblocks(mp); > > > + if (error) { > > > + xfs_warn(mp, "Unable to register to badblocks notifications\n"); > > > + /* > > > + * TODO is this a hard error or can we simply > > > + * warn and continue? > > > + */ > > > + goto out_rtunmount; > > > + } > > > + > > > + /* > > > * Now we are mounted, reserve a small amount of unused space for > > > * privileged transactions. This is needed so that transaction > > > * space required for critical operations can dip into this pool > > > @@ -1085,6 +1188,7 @@ xfs_unmountfs( > > > xfs_log_unmount(mp); > > > xfs_da_unmount(mp); > > > xfs_uuid_unmount(mp); > > > + xfs_badblocks_unmount(mp); > > > > > > #if defined(DEBUG) > > > xfs_errortag_clearall(mp, 0); > > > diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h > > > index 0ca9244..f0d1111 100644 > > > --- a/fs/xfs/xfs_mount.h > > > +++ b/fs/xfs/xfs_mount.h > > > @@ -139,6 +139,7 @@ typedef struct xfs_mount { > > > /* low free space thresholds */ > > > struct xfs_kobj m_kobj; > > > struct xstats m_stats; /* per-fs stats */ > > > + struct notifier_block m_badblocks_nb; /* disk badblocks notifier */ > > > > > > struct workqueue_struct *m_buf_workqueue; > > > struct workqueue_struct *m_data_workqueue; > > > -- > > > 2.5.5 > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs From Benjamin.Wirth@winmagic.com Fri Jun 17 15:07:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 2DF787CA2 for ; Fri, 17 Jun 2016 15:07:48 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id BA233AC001 for ; Fri, 17 Jun 2016 13:07:44 -0700 (PDT) X-ASG-Debug-ID: 1466194060-04bdf01e17bb6c0001-NocioJ Received: from mail1.bemta12.messagelabs.com (mail1.bemta12.messagelabs.com [216.82.251.8]) by cuda.sgi.com with ESMTP id wTvoVFPMnH2cNeYS for ; Fri, 17 Jun 2016 13:07:40 -0700 (PDT) X-Barracuda-Envelope-From: Benjamin.Wirth@winmagic.com X-Barracuda-Effective-Source-IP: mail1.bemta12.messagelabs.com[216.82.251.8] X-Barracuda-Apparent-Source-IP: 216.82.251.8 Received: from [216.82.251.34] by server-8.bemta-12.messagelabs.com id AF/5A-27267-C8854675; Fri, 17 Jun 2016 20:07:40 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrLIsWRWlGSWpSXmKPExsWSocJ5SbcnIiX c4HypxaK+W4wOjB6rL2xlDGCMYs3MS8qvSGDN+DjzNnvBIpWKvt6dzA2MyxW6GLk4hASmM0pc PvqUHcJZxygx78trti5GTg42ASOJlkPngRIcHCIC6hKP/1uDhIUFtCTO7pnDDmKLCOhLPDk7h xXC1pOY9esNC4jNIqAq0TfrCyOIzSsQJHGq+zBYnFFATOL7qTVMIDazgLjErSfzwWwJAQGJJX vOM0PYohIvH/9jhbDlJXq+rmWBqM+TmNl3jBVipqDEyZlPwOJCAhoS67YcgqoPlmjZ/JhlAqP QLCQrZiFpn4WkHSKuI7Fg9yc2CFtbYtnC18ww9pkDj5mQxRcwsq9i1ChOLSpLLdI1MtBLKspM zyjJTczM0TU0NNLLTS0uTkxPzUlMKtZLzs/dxAiMlnoGBsYdjLMavQ4xSnIwKYnyZjqmhAvxJ eWnVGYkFmfEF5XmpBYfYpTh4FCS4K0LB8oJFqWmp1akZeYA4xYmLcHBoyTCWwGS5i0uSMwtzk yHSJ1iVJQS53UCSQiAJDJK8+DaYKniEqOslDAvIwMDgxBPQWpRbmYJqvwrRnEORiVh3lSQKTy ZeSVw018BLWYCWqw5LxlkcUkiQkqqgTH21HPthuMV/Tq7Hd8F107dPb/LX8zo3TTZn5w7e30f NGS/UWaerZf6XGX3jenmHidqGpTajVYraTbdPmutWejb8NDKPzh4dWZFoKhmZPlak99/VFR7+ 9vmpUycfmzD0/vTnhd9X8u0PKfqrsPqoJ8ttp/5w4/d/7p2tlGqdG/cmVdPTRNvrFViKc5INN RiLipOBAAT5ReKEAMAAA== X-Env-Sender: Benjamin.Wirth@winmagic.com X-Msg-Ref: server-15.tower-145.messagelabs.com!1466194059!34409057!1 X-Originating-IP: [104.36.9.210] X-StarScan-Received: X-StarScan-Version: 8.46; banners=-,-,- X-VirusChecked: Checked Received: (qmail 128633 invoked from network); 17 Jun 2016 20:07:39 -0000 Received: from 104-36-9-210.dedicated.allstream.net (HELO mail.winmagic.com) (104.36.9.210) by server-15.tower-145.messagelabs.com with SMTP; 17 Jun 2016 20:07:39 -0000 Received: from WMSEXCHSVR01.winmagic.local ([10.10.2.27]) by mail.winmagic.com with Microsoft SMTPSVC(6.0.3790.4675); Fri, 17 Jun 2016 16:03:00 -0400 Received: from WMSEXCHSVR02.winmagic.local ([fe80::4dad:19a5:fc50:6d9f]) by wmsexchsvr01.winmagic.local ([::1]) with mapi id 14.03.0266.001; Fri, 17 Jun 2016 16:03:00 -0400 From: Benjamin Wirth To: "xfs@oss.sgi.com" Subject: on-disk free blocks B-Tree update Thread-Topic: on-disk free blocks B-Tree update X-ASG-Orig-Subj: on-disk free blocks B-Tree update Thread-Index: AdHI0z8GgoA47RyrS6SVx57OfVKdug== Date: Fri, 17 Jun 2016 20:02:59 +0000 Message-ID: <97A4F433DEE099488FE21C1718A641D213A0320A@wmsexchsvr02.winmagic.local> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.11.3.108] Content-Type: multipart/alternative; boundary="_000_97A4F433DEE099488FE21C1718A641D213A0320Awmsexchsvr02win_" MIME-Version: 1.0 X-OriginalArrivalTime: 17 Jun 2016 20:03:00.0381 (UTC) FILETIME=[3FC254D0:01D1C8D3] X-Barracuda-Connect: mail1.bemta12.messagelabs.com[216.82.251.8] X-Barracuda-Start-Time: 1466194060 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4253 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.62 X-Barracuda-Spam-Status: No, SCORE=0.62 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE, MARKETING_SUBJECT, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30526 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 HTML_MESSAGE BODY: HTML included in message --_000_97A4F433DEE099488FE21C1718A641D213A0320Awmsexchsvr02win_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hello XFS community, I have code that parses the free blocks B-Tree from the disk but it seems t= o me that the on-disk version of the B-Tree is not updated even when sync()= is called, so that the disk version of the B-Tree becomes outdated. Is tha= t correct? I have debug information from the kernel BIO layer where I see sectors/bloc= ks being flushed out by the sync but the B-Tree on disk still lists those b= locks as free. At what time is the on-disk B-Tree updated, only at umount? Is there any way to force the in-memory B-Tree to be flushed to disk? Thanks for any help, Ben Benjamin Wirth | Senior Software Developer WinMagic Inc. 5600A Cancross Court Mississauga, ON | L5R 3E9 | Canada --_000_97A4F433DEE099488FE21C1718A641D213A0320Awmsexchsvr02win_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable

Hello XFS community,

 

I have code that parses the free blocks B-Tree from = the disk but it seems to me that the on-disk version of the B-Tree is not u= pdated even when sync() is called, so that the disk version of the B-Tree b= ecomes outdated. Is that correct?

 

I have debug information from the kernel BIO layer w= here I see sectors/blocks being flushed out by the sync but the B-Tree on d= isk still lists those blocks as free. At what time is the on-disk B-Tree up= dated, only at umount?

 

Is there any way to force the in-memory B-Tree to be= flushed to disk?

 

Thanks for any help,

Ben

 

Benjamin Wirth | Senior Software Developer

WinMagic Inc.
5600A Cancross Court =

Mississauga, ON  |  L5R 3E9 |  Canada=

 

--_000_97A4F433DEE099488FE21C1718A641D213A0320Awmsexchsvr02win_-- From vishal.l.verma@intel.com Fri Jun 17 15:33:04 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_FRT_FOLLOW1,T_FRT_FOLLOW2 autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2C40F7CA2 for ; Fri, 17 Jun 2016 15:33:04 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id E59F38F8040 for ; Fri, 17 Jun 2016 13:33:00 -0700 (PDT) X-ASG-Debug-ID: 1466195578-04cbb01fee8d1b0001-NocioJ Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by cuda.sgi.com with ESMTP id CLyEOzpNioGMfQeH for ; Fri, 17 Jun 2016 13:32:59 -0700 (PDT) X-Barracuda-Envelope-From: vishal.l.verma@intel.com X-Barracuda-Effective-Source-IP: mga03.intel.com[134.134.136.65] X-Barracuda-Apparent-Source-IP: 134.134.136.65 X-ASG-Whitelist: Client Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga103.jf.intel.com with ESMTP; 17 Jun 2016 13:32:57 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,485,1459839600"; d="scan'208";a="830445478" Received: from omniknight.lm.intel.com ([10.232.112.171]) by orsmga003.jf.intel.com with ESMTP; 17 Jun 2016 13:32:57 -0700 Date: Fri, 17 Jun 2016 14:32:38 -0600 From: Vishal Verma To: "Darrick J. Wong" Cc: linux-nvdimm@ml01.01.org, xfs@oss.sgi.com, Jan Kara Subject: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks Message-ID: <20160617203237.GD5893@omniknight.lm.intel.com> X-ASG-Orig-Subj: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> <1466125419-17736-3-git-send-email-vishal.l.verma@intel.com> <20160617022606.GC11810@birch.djwong.org> <20160617192647.GC5893@omniknight.lm.intel.com> <20160617195345.GA5046@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617195345.GA5046@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Barracuda-Connect: mga03.intel.com[134.134.136.65] X-Barracuda-Start-Time: 1466195578 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12982 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On 06/17, Darrick J. Wong wrote: > On Fri, Jun 17, 2016 at 01:26:47PM -0600, Vishal Verma wrote: > > On 06/16, Darrick J. Wong wrote: > > > On Thu, Jun 16, 2016 at 07:03:39PM -0600, Vishal Verma wrote: > > > > RFC/WIP commit. > > > > > > > > This adds the foollowing: > > > > 1. In xfs_mountfs(), get an initial badblocks list from gendisk's > > > > badblocks infrastructure. > > > > 2. Register with the badblocks notifier to get updates for this disk's > > > > badblocks > > > > > > > > TODO: > > > > 1. Add badblocks info to the reverse mapping tree (and remove if a > > > > badblock was cleared). > > > > > > Well... there are a number of things we /could/ do... theoretically one > > > could use the rmap info to find all the affected inodes and simply convert > > > that part of their extent trees to 'unwritten'. Reads will just get zeroes, > > > > Hm, not sure we can do that - if a block became bad at some point, > > subsequent reads _have to_ error out (-EIO) so that the user doesn't see > > silent data corruption. > > Ooh, right, forgot about that whole MCE-on-bad-read thing... > > > > and writes will remove the unwritten flag (for that file, anyway). Will a > > > successful write trigger the BB_CLEAR notifier? > > > > Currently, a successful write that goes through the driver (i.e. not > > DAX) will cause the badblock to get cleared, and trigger BB_CLEAR. DAX > > is trickier, and currently DAX writes won't clear errors. > > Oh...? I should expand.. post 4.7, DAX and badblocks can co-exist, and there are a couple of scenarios: 1. When we take a DAX fault for the first time, we now check if the range we're faulting for has bad blocks (see the is_bad_pmem check in pmem_direct_access), and if it does, we signal a VM_FAULT_SIGBUS from the fault handler. 2. If a latent error develops in a region that has been mmapped and faulted in, then any attempts to load/store from/to it will cause a machine check. There isn't much that can be done for the second scenario - and the dax-error-handling stuff in 4.7 should handle everything for the first scenario (i.e. not cause a machine check induced crash). What we probably still have to do is have a well defined recovery flow for an application that gets a SIGBUS when accessing an mmaped file due to a known bad block. Currently (4.7), what works is deleting, truncating, or hole-punching the file, causing the sector (extent) to become free/unwritten, and then a subsequent zeroout of it before the next time it is used will go through the driver and clear the error. The one thing missing is that When a filesystem is mounted with DAX, all IO goes through dax_do_io, which is currently unable to clear any errors. The ideal user experience, IMO, should be: 1. Get a SIGBUS accessing a mmaped file 2. Be told of an (offset+length) of the file that is 'gone' 3. Be able to open(), seek(), and write() to that offset to restore data 4. Be able to mmap etc. again and go on as usual > > > > > > > I guess you could punch out the bad blocks too... not clear if you'd want > > > all the owner files staying mapped to data they'll never get back. > > > > The block mappings don't have to be maintained, but some sort of a flag > > needs to be kept that will allow us to return errors on reads like I > > said above. > > What happens if pmem signals a bad block and we try to read anyway? I know > about the read-error-MCE thing, but what's the "more expensive" alternative? > CPU exception? MCE is the CPU exception, and is what we want to avoid at all costs, as it can cause the machine to crash. Currently, the driver also checks every IO (every bvec in fact) for badblocks before reading/writing. Presumably, once we are able to push this checking into the filesystem, we can signal the driver to stop doing this extra check (Dan points out that it is good to have the redundant checking as a safety net till the filesystem implementation is fully baked/tested). But yes in either of these cases, we we know it is a bad block and choose to read (memcpy) from it anyway, we get the machine check exception. > > (Really what I'm digging at is, if the whole thing becomes a soft exception > that we can handle in the OS by, say, 2020, do we care about reintroducing > the whole ext2 badblocks thing?) Not sure if this is something the OS can just learn to handle as the machine check recovery stuff is a hardware/platform feature that only some CPUs have. ('machine check recovery' allows the mce code in linux to unmap the offending page(s) from the address space of any processes that have it mapped, and sends them a SIGBUS). On CPUs without this recovery feature, the CPU goes into a fault state and needs to be restarted. > > (Beats me...) > > --D > > > > > > > > > We could also create another rmap "special owner" (XFS_RMAP_OWN_BAD?) for bad > > > blocks, so we'd know which parts are just plain bad. It might be useful to > > > know that kind of thing. > > > > > > I think earlier Dave was talking about adding a new 'badblocks' bit to both > > > the file extent records and the rmap records to signify that something's > > > wrong with the extent. I'll let him write about that. > > > > > > > 2. Before doing file IO, refer the rmap/badblocks to error out early if > > > > the IO will attempt wo read a bad sector > > > > 3. Figure out interactions with mmap/DAX. > > > > > > Woot. > > > > > > > Cc: Darrick J. Wong > > > > Cc: Dave Chinner > > > > Signed-off-by: Vishal Verma > > > > --- > > > > fs/xfs/xfs_linux.h | 1 + > > > > fs/xfs/xfs_mount.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ > > > > fs/xfs/xfs_mount.h | 1 + > > > > 3 files changed, 106 insertions(+) > > > > > > > > diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h > > > > index 7e749be..f66d181 100644 > > > > --- a/fs/xfs/xfs_linux.h > > > > +++ b/fs/xfs/xfs_linux.h > > > > @@ -78,6 +78,7 @@ typedef __u32 xfs_nlink_t; > > > > #include > > > > #include > > > > #include > > > > +#include > > > > > > > > #include > > > > #include > > > > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c > > > > index 5e68b2c..1a47737 100644 > > > > --- a/fs/xfs/xfs_mount.c > > > > +++ b/fs/xfs/xfs_mount.c > > > > @@ -618,6 +618,96 @@ xfs_default_resblks(xfs_mount_t *mp) > > > > return resblks; > > > > } > > > > > > > > +STATIC int > > > > +xfs_notifier_call( > > > > + struct notifier_block *nb, > > > > + unsigned long action, > > > > + void *data) > > > > +{ > > > > + struct bb_notifier_data *bb_data = data; > > > > + struct xfs_mount *mp; > > > > + > > > > + mp = container_of(nb, struct xfs_mount, m_badblocks_nb); > > > > + /* TODO xfs_add_bb_to_rmap(mp, bb_data->sector, bb_data->count); */ > > > > + xfs_warn(mp, "xfs badblock %s sector %lu (count %d)\n", > > > > + (action == BB_ADD)?"added":"cleared", > > > > + bb_data->sector, bb_data->count); > > > > + return 0; > > > > > > Probably a xfs_rmapbt_query_range here? > > > > > > > +} > > > > + > > > > +STATIC int > > > > +xfs_init_badblocks(struct xfs_mount *mp) > > > > +{ > > > > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > > > > + int done = 0, error = 0; > > > > + ssize_t len, off = 0; > > > > + char *p; > > > > + > > > > + /* > > > > + * TODO: get a list of known badblocks so far and process it. > > > > + * Can we just parse the sysfs format that badblocks_show() > > > > + * returns? That should be the fastest way to get this. > > > > + * Something like: (Is this too hacky? Should we just do > > > > + * badblocks_check() in a (rather large) loop?) > > > > + */ > > > > + p = kzalloc(PAGE_SIZE, GFP_KERNEL); > > > > + len = badblocks_show(bb, p, 0); > > > > + while (len) { > > > > + int count, n; > > > > + sector_t s; > > > > + > > > > + /* > > > > + * The sysfs badblocks format is multiple lines of: > > > > + * " " > > > > + */ > > > > + n = sscanf(p + off, "%lu %d\n%n", &s, &count, &done); > > > > > > Ick, there's got to be a better way to iterate the badblocks list than this. > > > > > > It would be very nice to have a single function that deals with a change in > > > badness status, which would be called by both the notifier and the badblocks > > > iterator. > > > > > There is a function in block/badblocks.c - badblocks_check() which can > > tell you for a given range, what is the first bad sector in that range, > > and the number of bad sectors after that first sector. Using that would > > certainly be cleaner, as it uses the well-defined API, but it would be > > much slower, as you have to iterate through the entire address space. > > The above function - badblocks_show - just looks at the actual stored > > representation of the badblocks, and lists them out, which is quick > > (reading a 4K page from memory), and so in the above, I just parse it.. > > > > > > + if (n < 2 || done < 3) { > > > > + error = -1; > > > > + break; > > > > + } > > > > + off += done; > > > > + len -= done; > > > > + xfs_warn(mp, "got badblocks: sector %ld, count %d", s, count); > > > > + /* TODO xfs_add_bb_to_rmap(mp, s, count); */ > > > > + } > > > > + kfree(p); > > > > + if (error) > > > > + return error; > > > > + > > > > + mp->m_badblocks_nb.notifier_call = xfs_notifier_call; > > > > + error = bb_notifier_register(bb, &mp->m_badblocks_nb); > > > > + if (error) > > > > + return error; > > > > + > > > > + /* > > > > + * TODO: There is probably a TOCTOU race hiding here - what if the > > > > + * badblocks list gets updated before we register for notifications.. > > > > + * Can likely be solved by registering for notifications _first_ (the > > > > + * above xfs_add_bb_to_rmap function has to be ready to accept new > > > > + * blocks), then querying for the initial list (there could be overlap > > > > + * here, shich the above function could handle), and then setting the > > > > + * mount flag below. > > > > + */ > > > > > > (Yeah, pretty much. :)) > > > > > > > + > > > > + /* > > > > + * TODO: set some flag (mount flag?) in xfs so that xfs knows > > > > + * it will be doing error checking, and can possibly, later, > > > > + * tell the block layer (possibly using a REQ_ flag in its IO > > > > + * requests) not to do further badblock checking for those IOs. > > > > + */ > > > > + > > > > + /* mp->m_flags |= XFS_MOUNT_FS_BADBLOCKS; */ > > > > + return 0; > > > > +} > > > > + > > > > +STATIC void > > > > +xfs_badblocks_unmount(struct xfs_mount *mp) > > > > +{ > > > > + struct badblocks *bb = mp->m_super->s_bdev->bd_disk->bb; > > > > + > > > > + bb_notifier_unregister(bb, &mp->m_badblocks_nb); > > > > +} > > > > + > > > > /* > > > > * This function does the following on an initial mount of a file system: > > > > * - reads the superblock from disk and init the mount struct > > > > @@ -955,6 +1045,19 @@ xfs_mountfs( > > > > } > > > > > > > > /* > > > > + * Register with the badblocks notifier chain > > > > + */ > > > > + error = xfs_init_badblocks(mp); > > > > + if (error) { > > > > + xfs_warn(mp, "Unable to register to badblocks notifications\n"); > > > > + /* > > > > + * TODO is this a hard error or can we simply > > > > + * warn and continue? > > > > + */ > > > > + goto out_rtunmount; > > > > + } > > > > + > > > > + /* > > > > * Now we are mounted, reserve a small amount of unused space for > > > > * privileged transactions. This is needed so that transaction > > > > * space required for critical operations can dip into this pool > > > > @@ -1085,6 +1188,7 @@ xfs_unmountfs( > > > > xfs_log_unmount(mp); > > > > xfs_da_unmount(mp); > > > > xfs_uuid_unmount(mp); > > > > + xfs_badblocks_unmount(mp); > > > > > > > > #if defined(DEBUG) > > > > xfs_errortag_clearall(mp, 0); > > > > diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h > > > > index 0ca9244..f0d1111 100644 > > > > --- a/fs/xfs/xfs_mount.h > > > > +++ b/fs/xfs/xfs_mount.h > > > > @@ -139,6 +139,7 @@ typedef struct xfs_mount { > > > > /* low free space thresholds */ > > > > struct xfs_kobj m_kobj; > > > > struct xstats m_stats; /* per-fs stats */ > > > > + struct notifier_block m_badblocks_nb; /* disk badblocks notifier */ > > > > > > > > struct workqueue_struct *m_buf_workqueue; > > > > struct workqueue_struct *m_data_workqueue; > > > > -- > > > > 2.5.5 > > > > > > > > _______________________________________________ > > > > xfs mailing list > > > > xfs@oss.sgi.com > > > > http://oss.sgi.com/mailman/listinfo/xfs From dan.j.williams@intel.com Fri Jun 17 17:27:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5A54E7CA0 for ; Fri, 17 Jun 2016 17:27:57 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1B633304039 for ; Fri, 17 Jun 2016 15:27:54 -0700 (PDT) X-ASG-Debug-ID: 1466202471-04bdf01e17c0350001-NocioJ Received: from mail-oi0-f42.google.com (mail-oi0-f42.google.com [209.85.218.42]) by cuda.sgi.com with ESMTP id Q3oug9UrS36sYTsT (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Fri, 17 Jun 2016 15:27:52 -0700 (PDT) X-Barracuda-Envelope-From: dan.j.williams@intel.com X-Barracuda-Effective-Source-IP: mail-oi0-f42.google.com[209.85.218.42] X-Barracuda-Apparent-Source-IP: 209.85.218.42 Received: by mail-oi0-f42.google.com with SMTP id u201so137021672oie.0 for ; Fri, 17 Jun 2016 15:27:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc; bh=avvnQ+79SHDw2u6rvGVBu315pbfozh2fitCK3iHwdjU=; b=XWYDDVArJlAqjGxV9Sc/jdhxDS31H1TWLR3sVtuIFarhm1oeWzNFVA5kTW1O5bFaph KktLm35ckR1XfxWe+TRy4cKIYgf0z2iS22BvuON9kYCB8049rpkJg6q0fGgFWbCbfUe7 ZFR5VrOjexmoAXUmBrzlk+4WNOWgFsWH+Wxe05tkoqZst6mOCynCPbwgWDG28HsYp8rO Rgqq/vFrWAB5sFYIDNZUE5PupNLR8MRqDOYz/BRri21NqgJP67dzMpxuos5IlJKTZkFC J/N8T8Nl0MtySGOqo8LHEm7Aj4tvd/oYuAcQJgr9KyFmDBIqxfO/swNHM2lL3rS8Y20U mlFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc; bh=avvnQ+79SHDw2u6rvGVBu315pbfozh2fitCK3iHwdjU=; b=CD4ws4akIimaOeja/64vEDvJYKK1HPXQGXegHMLT9JOZhv/Y27dwV9/ApDg5l1dG24 yTqOFHMFzMBemadoooZngom+eer47GFmw6FmBKJF4FNzTT+giTneCiI+kHZfR3pcFBbK EaORNiO0MTNHs+TBLGm8gWInotcmJfJCDbPuD1TCt2ZZJ/iTBPyHmS/FLusN9uS4rzry S76Y1ZPr7EqfAWShYAFZ/v4YAy7KZk7w8s/MwOAXLOFR/3TMFWIzgLHBx1bO+AtF35GB XVCeeYzuHVMAUVEAkzk7HE5lQAGcgHQjsr13AwTURO6rRfWnTN33WaoStvBfiFJjrhRy 7Adg== X-Gm-Message-State: ALyK8tK+r1sjcHkGqcFuQ3hcgzXNoKGz0zrn2Ne4WPlxXNAVH7+z6BwKx65qsdZ9NWJ3n+NkPXdwl8MbPWPOffZl MIME-Version: 1.0 X-Received: by 10.157.60.42 with SMTP id q39mr3238432otc.189.1466202471432; Fri, 17 Jun 2016 15:27:51 -0700 (PDT) Received: by 10.157.46.129 with HTTP; Fri, 17 Jun 2016 15:27:51 -0700 (PDT) In-Reply-To: <20160617203237.GD5893@omniknight.lm.intel.com> References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> <1466125419-17736-3-git-send-email-vishal.l.verma@intel.com> <20160617022606.GC11810@birch.djwong.org> <20160617192647.GC5893@omniknight.lm.intel.com> <20160617195345.GA5046@birch.djwong.org> <20160617203237.GD5893@omniknight.lm.intel.com> Date: Fri, 17 Jun 2016 15:27:51 -0700 Message-ID: Subject: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks From: Dan Williams X-ASG-Orig-Subj: Re: [RFC PATCH 2/2] xfs: initial/partial support for badblocks To: Vishal Verma Cc: "Darrick J. Wong" , linux-nvdimm , Jan Kara , XFS Developers Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-oi0-f42.google.com[209.85.218.42] X-Barracuda-Start-Time: 1466202472 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 526 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_DOMAIN_MATCH, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30530 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient Domain On Fri, Jun 17, 2016 at 1:32 PM, Vishal Verma wrote: >> What happens if pmem signals a bad block and we try to read anyway? I know >> about the read-error-MCE thing, but what's the "more expensive" alternative? >> CPU exception? > > MCE is the CPU exception, and is what we want to avoid at all costs, as > it can cause the machine to crash. The MCE being fatal vs recoverable is the difference between platforms that must avoid badblocks vs those that can consume them and keep going. From sandeen@redhat.com Fri Jun 17 22:41:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E67067CA0 for ; Fri, 17 Jun 2016 22:41:10 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6F923AC002 for ; Fri, 17 Jun 2016 20:41:10 -0700 (PDT) X-ASG-Debug-ID: 1466221269-04bdf01e17ca3d0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id BQycTAJrz0mmuAIF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Fri, 17 Jun 2016 20:41:09 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 22F52D47B0 for ; Sat, 18 Jun 2016 03:41:09 +0000 (UTC) Received: from [IPv6:::1] (ovpn03.gateway.prod.ext.phx2.redhat.com [10.5.9.3]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5I3f777014582 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 17 Jun 2016 23:41:08 -0400 To: xfs-oss From: Eric Sandeen Subject: [PATCH] xfs_repair: set rsumino version to 2 Message-ID: X-ASG-Orig-Subj: [PATCH] xfs_repair: set rsumino version to 2 Date: Fri, 17 Jun 2016 22:41:07 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Sat, 18 Jun 2016 03:41:09 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466221269 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1441 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 If we run xfs/033 with "-m crc=0", the test fails with a repair output difference: Phase 7 - verify and correct link counts... +resetting inode INO nlinks from 0 to 1 done This is because when we zero out the realtime summary inode and rebuild it, we set its version to 1, then set its ip->i_d.di_nlink to 1. This is a little odd, because v1 inodes store their link count in di_onlink... Then, later in repair we call xfs_inode_from_disk(), which sees the version one inode, and converts it to version 2 in part by copying di_onlink to di_nlink. But we never *set* di_onlink, so di_nlink gets reset to zero, and this error is discovered later in repair. Interestingly, mk_rbmino() was changed in 138659f1 to set version 2; it looks like mk_rsumino was just missed. Signed-off-by: Eric Sandeen --- My only other point of confusion is that prior to ff105f7 libxfs: update to 3.16 kernel code the "resetting inode..." message wasn't emitted; I'm not sure what changed there to affect this. :/ diff --git a/repair/phase6.c b/repair/phase6.c index 0a71164..774e2cd 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -760,7 +760,7 @@ mk_rsumino(xfs_mount_t *mp) error); } - vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 1; + vers = xfs_sb_version_hascrc(&mp->m_sb) ? 3 : 2; memset(&ip->i_d, 0, sizeof(ip->i_d)); VFS_I(ip)->i_mode = S_IFREG; From gholami.f84@gmail.com Sat Jun 18 05:50:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_MESSAGE,T_DKIM_INVALID autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id AC94F7CA1 for ; Sat, 18 Jun 2016 05:50:06 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5CD92304032 for ; Sat, 18 Jun 2016 03:50:03 -0700 (PDT) X-ASG-Debug-ID: 1466246998-04bdf01e13d46e0001-NocioJ Received: from mail-io0-f176.google.com (mail-io0-f176.google.com [209.85.223.176]) by cuda.sgi.com with ESMTP id mKuwUZJXNOHpU6LP (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO); Sat, 18 Jun 2016 03:49:58 -0700 (PDT) X-Barracuda-Envelope-From: gholami.f84@gmail.com X-Barracuda-RBL-Trusted-Forwarder: 209.85.223.176 Received: by mail-io0-f176.google.com with SMTP id n127so96621141iof.3; Sat, 18 Jun 2016 03:49:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=hO27dmmx2GOvJzpuMkkD86JM3RzsXs5Ja741AD5w5eU=; b=PbrMyV2KQfhWGy4MiZLAHp5gC1pxHJH6LNac9PubCtOo/HVUQ6N5L1OfA+9sKBuuNB a0PqFXuqZovSBSPZrwj9Emp5uOVaYp66frLr1Qdq74krAurV+N2+JbZXBoixeh2QT0tH FO0kJ9yVque0X2nBgJPqC05JfLJsX/QYvWEQMoKDIO0trycIxY3sCIIYXv86m/j+Aguy tPBqxpsivPO1bilSoNTTxqB1cWQRrcWn7Q+yyklm1WxzTUcnw3iP+Ft8dsqIQKzV9z2e oV346ORpzg0Q4GzQ04oun9H2h3VAkF44/EaxjXBZFpozfJ+kB1jTtanoGP8BjN0vcSPR nupg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=hO27dmmx2GOvJzpuMkkD86JM3RzsXs5Ja741AD5w5eU=; b=BVZC4xI/aNgO8TQ3e4FO/stxxZUv5dXlC5XCXSpzH8GIangATyjPQEcKsvr27O9/Iy EG4KOzcA8KRmAiC61mVOlVNt1uMw0aZRbqFpUsGnvWrvSz4/XXckZaz2sIsf1nnWqKrC RYrH19kx7MVaVWX/XgGzdZfY28CCt/BbQY1Dyap7M47J9eSu00fAtTUA1c0YotHg/O4D Oet9FheX3ynBY/OPvmRvrHW/x4dJZb2hf+WnkfNxn465Tc3kPp9UcLIetQ8v07nagDiB S46RaP3roikkggooUUZ+NSztqaGQ3GYP2AMHJgeHysmiAV1iG0flh0bR/Pzv1IcIAV78 JGkQ== X-Gm-Message-State: ALyK8tIV3Le1LmBU6hsQXhefiWHyHGB244ZUHkYa5ktiTKR0tkkX2GDMeEWCsGB7UDgEErfASzRzR/gYWJmAQw== X-Received: by 10.107.32.148 with SMTP id g142mr8923886iog.117.1466246981562; Sat, 18 Jun 2016 03:49:41 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.133.217 with HTTP; Sat, 18 Jun 2016 03:49:41 -0700 (PDT) From: Fereydoun Gholami Date: Sat, 18 Jun 2016 15:19:41 +0430 Message-ID: Subject: xfs question To: xfs@oss.sgi.com, xfs-request@oss.sgi.com X-ASG-Orig-Subj: xfs question Content-Type: multipart/alternative; boundary=001a1141b05e7d3c2405358b3af3 X-Barracuda-Connect: mail-io0-f176.google.com[209.85.223.176] X-Barracuda-Start-Time: 1466246998 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1340 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30542 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --001a1141b05e7d3c2405358b3af3 Content-Type: text/plain; charset=UTF-8 Hello I'm java developer in Switch banking project. Recently, I started researching about xfs and j/xfs, to develop a ATM application base on XFS. Unfortunately, I do not know where to start it. i want to develop ATM application with java or c#. Is there a SDK to develop? Is there jar files or dll files of j/xfs or xfs libraries? Is there a ATM simulator for develop ATM application on my PC? please help me. Have A Good Time. --001a1141b05e7d3c2405358b3af3 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hello

I'm java d= eveloper in Switch banking project.
Re= cently, I started researching about xfs and j/xfs, to develop a ATM applica= tion base on XFS.
Unfortunately, I do = not know where to start it.
i want= to develop ATM application with java or c#.
Is there a SDK to develop?
Is t= here jar files or dll files of j/xfs or xfs libraries?
Is there a ATM simulator for develop ATM application on my= PC?
please help me.

Have A Go= od Time.
--001a1141b05e7d3c2405358b3af3-- From holger@applied-asynchrony.com Sat Jun 18 06:51:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 433AF7CA0 for ; Sat, 18 Jun 2016 06:51:59 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C2941AC001 for ; Sat, 18 Jun 2016 04:51:55 -0700 (PDT) X-ASG-Debug-ID: 1466250711-04bdf01e15d5c40001-NocioJ Received: from mail02.iobjects.de (mail02.iobjects.de [188.40.134.68]) by cuda.sgi.com with ESMTP id qFm7GzvjHuVbVp4A (version=TLSv1.2 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 04:51:53 -0700 (PDT) X-Barracuda-Envelope-From: holger@applied-asynchrony.com X-Barracuda-Effective-Source-IP: mail02.iobjects.de[188.40.134.68] X-Barracuda-Apparent-Source-IP: 188.40.134.68 Received: from tux.wizards.de (pD953E4E5.dip0.t-ipconnect.de [217.83.228.229]) by mail02.iobjects.de (Postfix) with ESMTPSA id 2080E416017E; Sat, 18 Jun 2016 13:51:51 +0200 (CEST) Received: from [192.168.100.223] (ragnarok [192.168.100.223]) by tux.wizards.de (Postfix) with ESMTP id AFD2511C01D3; Sat, 18 Jun 2016 13:51:50 +0200 (CEST) Subject: Re: xfs question To: Fereydoun Gholami , xfs@oss.sgi.com X-ASG-Orig-Subj: Re: xfs question References: From: =?UTF-8?Q?Holger_Hoffst=c3=a4tte?= Organization: Applied Asynchrony, Inc. Message-ID: <576535D6.6050403@applied-asynchrony.com> Date: Sat, 18 Jun 2016 13:51:50 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail02.iobjects.de[188.40.134.68] X-Barracuda-Start-Time: 1466250712 X-Barracuda-Encrypted: DHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 419 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30543 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 06/18/16 12:49, Fereydoun Gholami wrote: > I'm java developer in Switch banking project. > Recently, I started researching about xfs and j/xfs, to develop a ATM application base on XFS. > Unfortunately, I do not know where to start it. It looks like you took a wrong turn somewhere. This list is about the XFS filesystem in Linux and has nothing to do with Java or jXFS used for financial services. -h From bfoster@redhat.com Sat Jun 18 08:27:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 174F47CA0 for ; Sat, 18 Jun 2016 08:27:49 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id BCE4A304048 for ; Sat, 18 Jun 2016 06:27:48 -0700 (PDT) X-ASG-Debug-ID: 1466256464-04bdf01e17d9f70001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id hCkYCkJIBBhQx0yF (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 06:27:44 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 203CE46200; Sat, 18 Jun 2016 13:27:44 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5IDRhAF012792; Sat, 18 Jun 2016 09:27:43 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 9D865123469; Sat, 18 Jun 2016 09:27:42 -0400 (EDT) Date: Sat, 18 Jun 2016 09:27:42 -0400 From: Brian Foster To: Benjamin Wirth Cc: "xfs@oss.sgi.com" Subject: Re: on-disk free blocks B-Tree update Message-ID: <20160618132742.GB47303@bfoster.bfoster> X-ASG-Orig-Subj: Re: on-disk free blocks B-Tree update References: <97A4F433DEE099488FE21C1718A641D213A0320A@wmsexchsvr02.winmagic.local> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <97A4F433DEE099488FE21C1718A641D213A0320A@wmsexchsvr02.winmagic.local> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sat, 18 Jun 2016 13:27:44 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466256464 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1712 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jun 17, 2016 at 08:02:59PM +0000, Benjamin Wirth wrote: > Hello XFS community, > > I have code that parses the free blocks B-Tree from the disk but it seems to me that the on-disk version of the B-Tree is not updated even when sync() is called, so that the disk version of the B-Tree becomes outdated. Is that correct? > > I have debug information from the kernel BIO layer where I see sectors/blocks being flushed out by the sync but the B-Tree on disk still lists those blocks as free. At what time is the on-disk B-Tree updated, only at umount? > Calling sync() will first flush out all cached user data. This, in turn, may result in block allocation transactions, etc. sync() then calls into the fs superblock ->sync_fs() handler, which on XFS forces the log to disk. This means the metadata changes associated with the user data are persistent in the log, but not necessarily written back to disk. This occurs some time later according to the internal state of the fs. > Is there any way to force the in-memory B-Tree to be flushed to disk? > The only thing that comes to mind is to freeze ('fsfreeze -f ') the fs, which appears to push the AIL. This is really the only way to get a coherent view of the fs on disk while mounted, anyways. I also assume you're using direct I/O, as the underlying disk buffer/page cache is not coherent with XFS I/O. Brian > Thanks for any help, > Ben > > Benjamin Wirth | Senior Software Developer > WinMagic Inc. > 5600A Cancross Court > Mississauga, ON | L5R 3E9 | Canada > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From felix.janda@posteo.de Sat Jun 18 09:54:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0FA657CA0 for ; Sat, 18 Jun 2016 09:54:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 91904AC001 for ; Sat, 18 Jun 2016 07:53:58 -0700 (PDT) X-ASG-Debug-ID: 1466261633-04bdf01e10dfad0001-NocioJ Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by cuda.sgi.com with ESMTP id SXZM1tMChDWNmdM3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 07:53:54 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout01.posteo.de[185.67.36.65] X-Barracuda-Apparent-Source-IP: 185.67.36.65 Received: from dovecot03.posteo.de (dovecot03.posteo.de [172.16.0.13]) by mout01.posteo.de (Postfix) with ESMTPS id C452B209DB for ; Sat, 18 Jun 2016 16:53:52 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3rX0W44NDwz5vN5 for ; Sat, 18 Jun 2016 16:53:52 +0200 (CEST) Date: Sat, 18 Jun 2016 16:52:38 +0200 From: Felix Janda To: xfs@oss.sgi.com Subject: [PATCH 1/4] Remove off64_t from linux.h Message-ID: <20160618145238.GA17768@nyan> X-ASG-Orig-Subj: [PATCH 1/4] Remove off64_t from linux.h MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout01.posteo.de[185.67.36.65] X-Barracuda-Start-Time: 1466261634 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1573 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30546 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- The off64_t type is usually only conditionally exposed under the feature test macro _LARGEFILE64_SOURCE (also defined by _GNU_SOURCE). To make the public xfs headers more standalone therefore off64_t should be avoided. Enable transparent large file support via configure so that the standard off_t is the same as off64_t. Make compilation of linux programs using libxfs but without large file support fail. Now off64_t can safely be replaced by off_t in linux.h. Signed-off-by: Felix Janda --- configure.ac | 2 ++ include/linux.h | 7 ++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index a4a6cfa..2ea3e50 100644 --- a/configure.ac +++ b/configure.ac @@ -107,6 +107,8 @@ AC_PACKAGE_UTILITIES(xfsprogs) AC_MULTILIB($enable_lib64) AC_RT($enable_librt) +AC_SYS_LARGEFILE + AC_PACKAGE_NEED_UUID_H AC_PACKAGE_NEED_UUIDCOMPARE diff --git a/include/linux.h b/include/linux.h index cc0f70c..b94de81 100644 --- a/include/linux.h +++ b/include/linux.h @@ -142,7 +142,12 @@ platform_discard_blocks(int fd, uint64_t start, uint64_t len) #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ #define EFSBADCRC EBADMSG /* Bad CRC detected */ -typedef off64_t xfs_off_t; +/* Make compilation fail when off_t has 32 bits */ +struct __xfs_assert_64bit_off_t { + int assert_64bit_off_t[sizeof(off_t)-8]; +}; + +typedef off_t xfs_off_t; typedef __uint64_t xfs_ino_t; typedef __uint32_t xfs_dev_t; typedef __int64_t xfs_daddr_t; -- 2.7.3 From felix.janda@posteo.de Sat Jun 18 09:54:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C4B877CA0 for ; Sat, 18 Jun 2016 09:54:19 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 8508C304032 for ; Sat, 18 Jun 2016 07:54:16 -0700 (PDT) X-ASG-Debug-ID: 1466261651-04bdf01e13dfaf0001-NocioJ Received: from mout02.posteo.de (mout02.posteo.de [185.67.36.66]) by cuda.sgi.com with ESMTP id WAkQL21AZkT2L4Dg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 07:54:13 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout02.posteo.de[185.67.36.66] X-Barracuda-Apparent-Source-IP: 185.67.36.66 Received: from submission (posteo.de [89.146.220.130]) by mout02.posteo.de (Postfix) with ESMTPS id 6EB19209B7 for ; Sat, 18 Jun 2016 16:54:10 +0200 (CEST) Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 3rX0WM3N82zyfr for ; Sat, 18 Jun 2016 16:54:07 +0200 (CEST) Date: Sat, 18 Jun 2016 16:52:53 +0200 From: Felix Janda To: xfs@oss.sgi.com Subject: [PATCH 2/4] Simplify workaround for old glibc getsubopt() Message-ID: <20160618145253.GB17768@nyan> X-ASG-Orig-Subj: [PATCH 2/4] Simplify workaround for old glibc getsubopt() MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout02.posteo.de[185.67.36.66] X-Barracuda-Start-Time: 1466261653 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5228 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30546 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Signed-off-by: Felix Janda --- include/darwin.h | 1 - include/freebsd.h | 2 -- include/gnukfreebsd.h | 2 -- include/irix.h | 2 -- include/linux.h | 4 +--- mkfs/xfs_mkfs.c | 16 ++++++++-------- repair/xfs_repair.c | 4 ++-- 7 files changed, 11 insertions(+), 20 deletions(-) diff --git a/include/darwin.h b/include/darwin.h index a52030d..45e0c03 100644 --- a/include/darwin.h +++ b/include/darwin.h @@ -160,7 +160,6 @@ typedef int64_t xfs_daddr_t; #define EFSCORRUPTED 990 /* Filesystem is corrupted */ #define EFSBADCRC 991 /* Bad CRC detected */ -#define constpp char * const * #define HAVE_FID 1 diff --git a/include/freebsd.h b/include/freebsd.h index f7e0c75..6e77427 100644 --- a/include/freebsd.h +++ b/include/freebsd.h @@ -43,8 +43,6 @@ #define fdatasync fsync #define memalign(a,sz) valloc(sz) -#define constpp char * const * - #define EFSCORRUPTED 990 /* Filesystem is corrupted */ #define EFSBADCRC 991 /* Bad CRC detected */ diff --git a/include/gnukfreebsd.h b/include/gnukfreebsd.h index 64167b2..d55acfb 100644 --- a/include/gnukfreebsd.h +++ b/include/gnukfreebsd.h @@ -33,8 +33,6 @@ #include #include -#define constpp char * const * - #define EFSCORRUPTED 990 /* Filesystem is corrupted */ #define EFSBADCRC 991 /* Bad CRC detected */ diff --git a/include/irix.h b/include/irix.h index c2191ee..b92e01b 100644 --- a/include/irix.h +++ b/include/irix.h @@ -184,8 +184,6 @@ typedef struct xfs_efd_log_format_32 { #define inline __inline #endif -#define constpp char * const * - /*ARGSUSED*/ static __inline__ int xfsctl(const char *path, int fd, int cmd, void *arg) { diff --git a/include/linux.h b/include/linux.h index b94de81..f6d0f80 100644 --- a/include/linux.h +++ b/include/linux.h @@ -133,9 +133,7 @@ platform_discard_blocks(int fd, uint64_t start, uint64_t len) } #if (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 1)) -# define constpp const char * const * -#else -# define constpp char * const * +# define getsubopt(p, s, v) getsubopt(p, (const char * const *)s, v) #endif #define ENOATTR ENODATA /* Attribute not found */ diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 955dcfd..99c5eb5 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -1829,7 +1829,7 @@ main( char **subopts = (char **)bopts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case B_LOG: blocklog = getnum(value, &bopts, B_LOG); @@ -1853,7 +1853,7 @@ main( char **subopts = (char **)dopts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case D_AGCOUNT: agcount = getnum(value, &dopts, @@ -1933,7 +1933,7 @@ main( char **subopts = (char **)iopts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case I_ALIGN: sb_feat.inode_align = getnum(value, @@ -1983,7 +1983,7 @@ main( char **subopts = (char **)lopts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case L_AGNUM: logagno = getnum(value, &lopts, L_AGNUM); @@ -2055,7 +2055,7 @@ main( char **subopts = (char **)mopts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case M_CRC: sb_feat.crcs_enabled = @@ -2084,7 +2084,7 @@ main( char **subopts = (char **)nopts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case N_LOG: dirblocklog = getnum(value, &nopts, @@ -2140,7 +2140,7 @@ main( char **subopts = (char **)ropts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case R_EXTSIZE: rtextsize = getstr(value, &ropts, @@ -2173,7 +2173,7 @@ main( char **subopts = (char **)sopts.subopts; char *value; - switch (getsubopt(&p, (constpp)subopts, + switch (getsubopt(&p, subopts, &value)) { case S_LOG: case S_SECTLOG: diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index 9d91f2d..5a433ed 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -225,7 +225,7 @@ process_args(int argc, char **argv) while (*p != '\0') { char *val; - switch (getsubopt(&p, (constpp)o_opts, &val)) { + switch (getsubopt(&p, o_opts, &val)) { case ASSUME_XFS: if (val) noval('o', o_opts, ASSUME_XFS); @@ -276,7 +276,7 @@ process_args(int argc, char **argv) while (*p) { char *val; - switch (getsubopt(&p, (constpp)c_opts, &val)) { + switch (getsubopt(&p, c_opts, &val)) { case CONVERT_LAZY_COUNT: lazy_count = (int)strtol(val, NULL, 0); convert_lazy_count = 1; -- 2.7.3 From felix.janda@posteo.de Sat Jun 18 09:54:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 4479E7CAE for ; Sat, 18 Jun 2016 09:54:25 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 16ABF30404E for ; Sat, 18 Jun 2016 07:54:25 -0700 (PDT) X-ASG-Debug-ID: 1466261661-04cb6c54278e520001-NocioJ Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by cuda.sgi.com with ESMTP id 226YA186CyDFMJKc (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 07:54:23 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout01.posteo.de[185.67.36.65] X-Barracuda-Apparent-Source-IP: 185.67.36.65 Received: from dovecot03.posteo.de (dovecot03.posteo.de [172.16.0.13]) by mout01.posteo.de (Postfix) with ESMTPS id 6F5B9209F6 for ; Sat, 18 Jun 2016 16:54:21 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3rX0Wd238Pz5vMs for ; Sat, 18 Jun 2016 16:54:21 +0200 (CEST) Date: Sat, 18 Jun 2016 16:53:07 +0200 From: Felix Janda To: xfs@oss.sgi.com Subject: [PATCH 3/4] Make workaround for old glibc getsubopt() glibc-specific Message-ID: <20160618145307.GC17768@nyan> X-ASG-Orig-Subj: [PATCH 3/4] Make workaround for old glibc getsubopt() glibc-specific MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout01.posteo.de[185.67.36.65] X-Barracuda-Start-Time: 1466261662 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 621 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30546 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Signed-off-by: Felix Janda --- include/linux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux.h b/include/linux.h index f6d0f80..873b682 100644 --- a/include/linux.h +++ b/include/linux.h @@ -132,7 +132,7 @@ platform_discard_blocks(int fd, uint64_t start, uint64_t len) return 0; } -#if (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 1)) +#if defined(__GLIBC__) && ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ <= 1))) # define getsubopt(p, s, v) getsubopt(p, (const char * const *)s, v) #endif -- 2.7.3 From felix.janda@posteo.de Sat Jun 18 09:55:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3CB127CA0 for ; Sat, 18 Jun 2016 09:55:07 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id F241C304032 for ; Sat, 18 Jun 2016 07:55:06 -0700 (PDT) X-ASG-Debug-ID: 1466261703-04bdf01e13dfb80001-NocioJ Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by cuda.sgi.com with ESMTP id HUs9Eu0ujscLkLHm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 07:55:04 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout01.posteo.de[185.67.36.65] X-Barracuda-Apparent-Source-IP: 185.67.36.65 Received: from dovecot03.posteo.de (dovecot03.posteo.de [172.16.0.13]) by mout01.posteo.de (Postfix) with ESMTPS id 87CE520A88 for ; Sat, 18 Jun 2016 16:55:03 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3rX0XR2dKGz5vML; Sat, 18 Jun 2016 16:55:03 +0200 (CEST) Date: Sat, 18 Jun 2016 16:53:49 +0200 From: Felix Janda To: Christoph Hellwig Cc: xfs@oss.sgi.com Subject: Re: [PATCH 2/6] libxfs/linux.c: Replace use of ustat by stat Message-ID: <20160618145349.GA17760@nyan> X-ASG-Orig-Subj: Re: [PATCH 2/6] libxfs/linux.c: Replace use of ustat by stat References: <20160112195945.GC568@nyan> <20160113075501.GC21939@infradead.org> <20160113174241.GC10942@nyan> <20160114102009.GD27644@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160114102009.GD27644@infradead.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout01.posteo.de[185.67.36.65] X-Barracuda-Start-Time: 1466261704 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 996 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30546 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, 14 Jan 2016 at 02:20:09 -0800, Christoph Hellwig wrote: > On Wed, Jan 13, 2016 at 06:42:41PM +0100, Felix Janda wrote: > > Is this really performance relevant? > > I'm not entirely sure. There are systems with giant amounts of mounted > file systems, in which case iterating each of them and requiring > multiple syscalls each might not be a good idea. > > > Hmm, so we couldn't we use for linux just something like > > > > int > > platform_check_ismounted(char *name, char *block, struct stat64 *s, int verbose) > > { > > int fd = open(block, O_EXCL); > > int e = errno; > > > > if (fd != -1) close(fd); > > if (e == EBUSY) { > > if (verbose) > > fprintf(stderr, _("%s: %s contains a mounted filesystem\n"), progname, name); > > return 1; > > } > > > > return 0; > > Please give me a couple of days to come up with an idea to use O_EXCL > on Linux and work around it on other platforms in a more integrated way. Ping? Thanks, Felix From felix.janda@posteo.de Sat Jun 18 09:55:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A13677CA4 for ; Sat, 18 Jun 2016 09:55:11 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 610878F8037 for ; Sat, 18 Jun 2016 07:55:08 -0700 (PDT) X-ASG-Debug-ID: 1466261693-04bdf01e17dfb70001-NocioJ Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by cuda.sgi.com with ESMTP id SgJ7Yc5YOMK4ZsIu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 07:54:54 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout01.posteo.de[185.67.36.65] X-Barracuda-Apparent-Source-IP: 185.67.36.65 Received: from dovecot03.posteo.de (dovecot03.posteo.de [172.16.0.13]) by mout01.posteo.de (Postfix) with ESMTPS id 762A920B92 for ; Sat, 18 Jun 2016 16:54:53 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3rX0XD5fpyz5vML for ; Sat, 18 Jun 2016 16:54:52 +0200 (CEST) Date: Sat, 18 Jun 2016 16:53:30 +0200 From: Felix Janda To: xfs@oss.sgi.com Subject: [PATCH 4/4] Move to more stdint types Message-ID: <20160618145330.GD17768@nyan> X-ASG-Orig-Subj: [PATCH 4/4] Move to more stdint types MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout01.posteo.de[185.67.36.65] X-Barracuda-Start-Time: 1466261694 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 98642 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30546 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- The uint*_t and int*_t are defined by C99 and should be prefered over the less portable __uint*_t and __int*_t variants. The necessary include is in platformdefs.h, which gets included in most places via libxfs.h. For now, only replace all __uint*_t types to uint*_t and likewise for __int*_t outside the directories include/ and libxfs/. Signed-off-by: Felix Janda --- copy/xfs_copy.c | 14 ++++---- copy/xfs_copy.h | 2 +- db/attr.c | 8 ++--- db/attrshort.c | 4 +-- db/bit.c | 4 +-- db/bit.h | 2 +- db/block.c | 8 ++--- db/check.c | 18 +++++----- db/convert.c | 28 ++++++++-------- db/faddr.c | 14 ++++---- db/field.c | 44 ++++++++++++------------- db/fprint.c | 8 ++--- db/frag.c | 8 ++--- db/inode.c | 30 ++++++++--------- db/io.c | 4 +-- db/io.h | 8 ++--- db/metadump.c | 12 +++---- db/sb.c | 6 ++-- fsr/xfs_fsr.c | 2 +- libhandle/handle.c | 2 +- libhandle/jdm.c | 2 +- logprint/log_misc.c | 6 ++-- mdrestore/xfs_mdrestore.c | 2 +- mkfs/proto.c | 2 +- mkfs/xfs_mkfs.c | 84 +++++++++++++++++++++++------------------------ quota/edit.c | 64 ++++++++++++++++++------------------ quota/free.c | 44 ++++++++++++------------- quota/quot.c | 24 +++++++------- quota/quota.c | 4 +-- quota/quota.h | 12 +++---- quota/report.c | 4 +-- quota/state.c | 2 +- quota/util.c | 66 ++++++++++++++++++------------------- repair/README | 2 +- repair/agheader.h | 14 ++++---- repair/attr_repair.h | 26 +++++++-------- repair/avl64.c | 38 ++++++++++----------- repair/avl64.h | 18 +++++----- repair/dino_chunks.c | 2 +- repair/dinode.c | 38 ++++++++++----------- repair/dinode.h | 4 +-- repair/dir2.c | 2 +- repair/globals.h | 16 ++++----- repair/incore.c | 10 +++--- repair/incore.h | 42 ++++++++++++------------ repair/incore_ext.c | 6 ++-- repair/incore_ino.c | 72 ++++++++++++++++++++-------------------- repair/phase2.c | 2 +- repair/phase3.c | 6 ++-- repair/phase4.c | 4 +-- repair/phase5.c | 40 +++++++++++----------- repair/phase6.c | 16 ++++----- repair/phase7.c | 6 ++-- repair/progress.c | 30 ++++++++--------- repair/progress.h | 4 +-- repair/sb.c | 10 +++--- repair/scan.c | 42 ++++++++++++------------ repair/scan.h | 12 +++---- 58 files changed, 502 insertions(+), 502 deletions(-) diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c index 3c8998c..55ccf90 100644 --- a/copy/xfs_copy.c +++ b/copy/xfs_copy.c @@ -43,7 +43,7 @@ unsigned int source_sectorsize; /* source disk sectorsize */ xfs_agblock_t first_agbno; -__uint64_t barcount[11]; +uint64_t barcount[11]; unsigned int num_targets; target_control *target; @@ -313,7 +313,7 @@ usage(void) } void -init_bar(__uint64_t source_blocks) +init_bar(uint64_t source_blocks) { int i; @@ -322,7 +322,7 @@ init_bar(__uint64_t source_blocks) } int -bump_bar(int tenths, __uint64_t numblocks) +bump_bar(int tenths, uint64_t numblocks) { static char *bar[11] = { " 0% ", @@ -532,8 +532,8 @@ main(int argc, char **argv) xfs_off_t pos; size_t length; int c; - __uint64_t size, sizeb; - __uint64_t numblocks = 0; + uint64_t size, sizeb; + uint64_t numblocks = 0; int wblocks = 0; int num_threads = 0; struct dioattr d; @@ -949,8 +949,8 @@ main(int argc, char **argv) num_ags = mp->m_sb.sb_agcount; init_bar(mp->m_sb.sb_blocksize / BBSIZE - * ((__uint64_t)mp->m_sb.sb_dblocks - - (__uint64_t)mp->m_sb.sb_fdblocks + 10 * num_ags)); + * ((uint64_t)mp->m_sb.sb_dblocks + - (uint64_t)mp->m_sb.sb_fdblocks + 10 * num_ags)); kids = num_targets; diff --git a/copy/xfs_copy.h b/copy/xfs_copy.h index 2737068..53c6e42 100644 --- a/copy/xfs_copy.h +++ b/copy/xfs_copy.h @@ -76,7 +76,7 @@ typedef struct { typedef int thread_id; typedef int tm_index; /* index into thread mask array */ -typedef __uint32_t thread_mask; /* a thread mask */ +typedef uint32_t thread_mask; /* a thread mask */ typedef struct { char *name; diff --git a/db/attr.c b/db/attr.c index e26ac67..6f56953 100644 --- a/db/attr.c +++ b/db/attr.c @@ -77,16 +77,16 @@ const field_t attr_leaf_entry_flds[] = { { "nameidx", FLDT_UINT16D, OI(LEOFF(nameidx)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT8X, OI(LEOFF(flags)), C1, FLD_SKIPALL, TYP_NONE }, { "incomplete", FLDT_UINT1, - OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_INCOMPLETE_BIT - 1), C1, + OI(LEOFF(flags) + bitsz(uint8_t) - XFS_ATTR_INCOMPLETE_BIT - 1), C1, 0, TYP_NONE }, { "root", FLDT_UINT1, - OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_ROOT_BIT - 1), C1, 0, + OI(LEOFF(flags) + bitsz(uint8_t) - XFS_ATTR_ROOT_BIT - 1), C1, 0, TYP_NONE }, { "secure", FLDT_UINT1, - OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_SECURE_BIT - 1), C1, 0, + OI(LEOFF(flags) + bitsz(uint8_t) - XFS_ATTR_SECURE_BIT - 1), C1, 0, TYP_NONE }, { "local", FLDT_UINT1, - OI(LEOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_LOCAL_BIT - 1), C1, 0, + OI(LEOFF(flags) + bitsz(uint8_t) - XFS_ATTR_LOCAL_BIT - 1), C1, 0, TYP_NONE }, { "pad2", FLDT_UINT8X, OI(LEOFF(pad2)), C1, FLD_SKIPALL, TYP_NONE }, { NULL } diff --git a/db/attrshort.c b/db/attrshort.c index d82559c..2ef358f 100644 --- a/db/attrshort.c +++ b/db/attrshort.c @@ -51,10 +51,10 @@ const field_t attr_sf_entry_flds[] = { { "valuelen", FLDT_UINT8D, OI(EOFF(valuelen)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT8X, OI(EOFF(flags)), C1, FLD_SKIPALL, TYP_NONE }, { "root", FLDT_UINT1, - OI(EOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_ROOT_BIT - 1), C1, 0, + OI(EOFF(flags) + bitsz(uint8_t) - XFS_ATTR_ROOT_BIT - 1), C1, 0, TYP_NONE }, { "secure", FLDT_UINT1, - OI(EOFF(flags) + bitsz(__uint8_t) - XFS_ATTR_SECURE_BIT - 1), C1, 0, + OI(EOFF(flags) + bitsz(uint8_t) - XFS_ATTR_SECURE_BIT - 1), C1, 0, TYP_NONE }, { "name", FLDT_CHARNS, OI(EOFF(nameval)), attr_sf_entry_name_count, FLD_COUNT, TYP_NONE }, diff --git a/db/bit.c b/db/bit.c index 24872bf..f5ebf68 100644 --- a/db/bit.c +++ b/db/bit.c @@ -60,7 +60,7 @@ setbit( } } -__int64_t +int64_t getbitval( void *obj, int bitoff, @@ -70,7 +70,7 @@ getbitval( int bit; int i; char *p; - __int64_t rval; + int64_t rval; int signext; int z1, z2, z3, z4; diff --git a/db/bit.h b/db/bit.h index 80ba24c..9fd71f4 100644 --- a/db/bit.h +++ b/db/bit.h @@ -25,5 +25,5 @@ #define BVUNSIGNED 0 #define BVSIGNED 1 -extern __int64_t getbitval(void *obj, int bitoff, int nbits, int flags); +extern int64_t getbitval(void *obj, int bitoff, int nbits, int flags); extern void setbitval(void *obuf, int bitoff, int nbits, void *ibuf); diff --git a/db/block.c b/db/block.c index 4a357ce..5ecd687 100644 --- a/db/block.c +++ b/db/block.c @@ -98,7 +98,7 @@ ablock_f( } dfsbno = bm.startblock + (bno - bm.startoff); ASSERT(typtab[TYP_ATTR].typnm == TYP_ATTR); - set_cur(&typtab[TYP_ATTR], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), + set_cur(&typtab[TYP_ATTR], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), blkbb, DB_RING_ADD, NULL); return 0; } @@ -128,14 +128,14 @@ daddr_f( int argc, char **argv) { - __int64_t d; + int64_t d; char *p; if (argc == 1) { dbprintf(_("current daddr is %lld\n"), iocur_top->off >> BBSHIFT); return 0; } - d = (__int64_t)strtoull(argv[1], &p, 0); + d = (int64_t)strtoull(argv[1], &p, 0); if (*p != '\0' || d >= mp->m_sb.sb_dblocks << (mp->m_sb.sb_blocklog - BBSHIFT)) { dbprintf(_("bad daddr %s\n"), argv[1]); @@ -197,7 +197,7 @@ dblock_f( ASSERT(typtab[type].typnm == type); if (nex > 1) make_bbmap(&bbmap, nex, bmp); - set_cur(&typtab[type], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), + set_cur(&typtab[type], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), nb * blkbb, DB_RING_ADD, nex > 1 ? &bbmap : NULL); free(bmp); return 0; diff --git a/db/check.c b/db/check.c index 0871ed7..25c253d 100644 --- a/db/check.c +++ b/db/check.c @@ -112,8 +112,8 @@ typedef struct dirhash { static xfs_extlen_t agffreeblks; static xfs_extlen_t agflongest; -static __uint64_t agf_aggr_freeblks; /* aggregate count over all */ -static __uint32_t agfbtreeblks; +static uint64_t agf_aggr_freeblks; /* aggregate count over all */ +static uint32_t agfbtreeblks; static int lazycount; static xfs_agino_t agicount; static xfs_agino_t agifreecount; @@ -122,10 +122,10 @@ static int blist_size; static char **dbmap; /* really dbm_t:8 */ static dirhash_t **dirhash; static int error; -static __uint64_t fdblocks; -static __uint64_t frextents; -static __uint64_t icount; -static __uint64_t ifree; +static uint64_t fdblocks; +static uint64_t frextents; +static uint64_t icount; +static uint64_t ifree; static inodata_t ***inodata; static int inodata_hash_size; static inodata_t ***inomap; @@ -1173,7 +1173,7 @@ blocktrash_f( goto out; } for (i = 0; i < count; i++) { - randb = (xfs_rfsblock_t)((((__int64_t)random() << 32) | + randb = (xfs_rfsblock_t)((((int64_t)random() << 32) | random()) % blocks); for (bi = 0, agno = 0, done = 0; !done && agno < mp->m_sb.sb_agcount; @@ -2985,7 +2985,7 @@ process_leaf_node_dir_v2( } if (v) dbprintf(_("dir inode %lld block %u=%llu\n"), id->ino, - (__uint32_t)dbno, + (uint32_t)dbno, (xfs_fsblock_t)bmp->startblock); push_cur(); if (nex > 1) @@ -2998,7 +2998,7 @@ process_leaf_node_dir_v2( if (!sflag || v) dbprintf(_("can't read block %u for directory " "inode %lld\n"), - (__uint32_t)dbno, id->ino); + (uint32_t)dbno, id->ino); error++; pop_cur(); dbno += mp->m_dir_geo->fsbcount - 1; diff --git a/db/convert.c b/db/convert.c index a337abe..fa4f962 100644 --- a/db/convert.c +++ b/db/convert.c @@ -24,13 +24,13 @@ #define M(A) (1 << CT_ ## A) #define agblock_to_bytes(x) \ - ((__uint64_t)(x) << mp->m_sb.sb_blocklog) + ((uint64_t)(x) << mp->m_sb.sb_blocklog) #define agino_to_bytes(x) \ - ((__uint64_t)(x) << mp->m_sb.sb_inodelog) + ((uint64_t)(x) << mp->m_sb.sb_inodelog) #define agnumber_to_bytes(x) \ - agblock_to_bytes((__uint64_t)(x) * mp->m_sb.sb_agblocks) + agblock_to_bytes((uint64_t)(x) * mp->m_sb.sb_agblocks) #define daddr_to_bytes(x) \ - ((__uint64_t)(x) << BBSHIFT) + ((uint64_t)(x) << BBSHIFT) #define fsblock_to_bytes(x) \ (agnumber_to_bytes(XFS_FSB_TO_AGNO(mp, (x))) + \ agblock_to_bytes(XFS_FSB_TO_AGBNO(mp, (x)))) @@ -38,7 +38,7 @@ (agnumber_to_bytes(XFS_INO_TO_AGNO(mp, (x))) + \ agino_to_bytes(XFS_INO_TO_AGINO(mp, (x)))) #define inoidx_to_bytes(x) \ - ((__uint64_t)(x) << mp->m_sb.sb_inodelog) + ((uint64_t)(x) << mp->m_sb.sb_inodelog) typedef enum { CT_NONE = -1, @@ -68,7 +68,7 @@ typedef union { xfs_agnumber_t agnumber; int bboff; int blkoff; - __uint64_t byte; + uint64_t byte; xfs_daddr_t daddr; xfs_fsblock_t fsblock; xfs_ino_t ino; @@ -76,7 +76,7 @@ typedef union { int inooff; } cval_t; -static __uint64_t bytevalue(ctype_t ctype, cval_t *val); +static uint64_t bytevalue(ctype_t ctype, cval_t *val); static int convert_f(int argc, char **argv); static int getvalue(char *s, ctype_t ctype, cval_t *val); static ctype_t lookupcty(char *ctyname); @@ -118,7 +118,7 @@ static const cmdinfo_t convert_cmd = { "convert", NULL, convert_f, 3, 9, 0, "type num [type num]... type", "convert from one address form to another", NULL }; -static __uint64_t +static uint64_t bytevalue(ctype_t ctype, cval_t *val) { switch (ctype) { @@ -129,9 +129,9 @@ bytevalue(ctype_t ctype, cval_t *val) case CT_AGNUMBER: return agnumber_to_bytes(val->agnumber); case CT_BBOFF: - return (__uint64_t)val->bboff; + return (uint64_t)val->bboff; case CT_BLKOFF: - return (__uint64_t)val->blkoff; + return (uint64_t)val->blkoff; case CT_BYTE: return val->byte; case CT_DADDR: @@ -143,7 +143,7 @@ bytevalue(ctype_t ctype, cval_t *val) case CT_INOIDX: return inoidx_to_bytes(val->inoidx); case CT_INOOFF: - return (__uint64_t)val->inooff; + return (uint64_t)val->inooff; case CT_NONE: case NCTS: break; @@ -160,7 +160,7 @@ convert_f(int argc, char **argv) cval_t cvals[NCTS] = {}; int i; int mask; - __uint64_t v; + uint64_t v; ctype_t wtype; /* move past the "convert" command */ @@ -262,7 +262,7 @@ static int getvalue(char *s, ctype_t ctype, cval_t *val) { char *p; - __uint64_t v; + uint64_t v; v = strtoull(s, &p, 0); if (*p != '\0') { @@ -286,7 +286,7 @@ getvalue(char *s, ctype_t ctype, cval_t *val) val->blkoff = (int)v; break; case CT_BYTE: - val->byte = (__uint64_t)v; + val->byte = (uint64_t)v; break; case CT_DADDR: val->daddr = (xfs_daddr_t)v; diff --git a/db/faddr.c b/db/faddr.c index e368d0d..6ded295 100644 --- a/db/faddr.c +++ b/db/faddr.c @@ -79,11 +79,11 @@ fa_attrblock( typnm_t next) { bmap_ext_t bm; - __uint32_t bno; + uint32_t bno; xfs_fsblock_t dfsbno; int nex; - bno = (__uint32_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); + bno = (uint32_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == 0) { dbprintf(_("null attribute block number, cannot set new addr\n")); return; @@ -96,7 +96,7 @@ fa_attrblock( } dfsbno = bm.startblock + (bno - bm.startoff); ASSERT(typtab[next].typnm == next); - set_cur(&typtab[next], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), blkbb, + set_cur(&typtab[next], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), blkbb, DB_RING_ADD, NULL); } @@ -276,11 +276,11 @@ fa_dirblock( { bbmap_t bbmap; bmap_ext_t *bmp; - __uint32_t bno; + uint32_t bno; xfs_fsblock_t dfsbno; int nex; - bno = (__uint32_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); + bno = (uint32_t)getbitval(obj, bit, bitsz(bno), BVUNSIGNED); if (bno == 0) { dbprintf(_("null directory block number, cannot set new addr\n")); return; @@ -297,7 +297,7 @@ fa_dirblock( ASSERT(typtab[next].typnm == next); if (nex > 1) make_bbmap(&bbmap, nex, bmp); - set_cur(&typtab[next], (__int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), + set_cur(&typtab[next], (int64_t)XFS_FSB_TO_DADDR(mp, dfsbno), XFS_FSB_TO_BB(mp, mp->m_dir_geo->fsbcount), DB_RING_ADD, nex > 1 ? &bbmap : NULL); free(bmp); @@ -317,7 +317,7 @@ fa_drfsbno( return; } ASSERT(typtab[next].typnm == next); - set_cur(&typtab[next], (__int64_t)XFS_FSB_TO_BB(mp, bno), blkbb, + set_cur(&typtab[next], (int64_t)XFS_FSB_TO_BB(mp, bno), blkbb, DB_RING_ADD, NULL); } diff --git a/db/field.c b/db/field.c index 843c385..2c8d414 100644 --- a/db/field.c +++ b/db/field.c @@ -83,7 +83,7 @@ const ftattr_t ftattrtab[] = { attr_sf_entry_size, FTARG_SIZE, NULL, attr_sf_entry_flds }, { FLDT_ATTR_SF_HDR, "attr_sf_hdr", NULL, (char *)attr_sf_hdr_flds, SI(bitsz(struct xfs_attr_sf_hdr)), 0, NULL, attr_sf_hdr_flds }, - { FLDT_ATTRBLOCK, "attrblock", fp_num, "%u", SI(bitsz(__uint32_t)), 0, + { FLDT_ATTRBLOCK, "attrblock", fp_num, "%u", SI(bitsz(uint32_t)), 0, fa_attrblock, NULL }, { FLDT_ATTRSHORT, "attrshort", NULL, (char *)attr_shortform_flds, attrshort_size, FTARG_SIZE, NULL, attr_shortform_flds }, @@ -165,7 +165,7 @@ const ftattr_t ftattrtab[] = { SI(bitsz(xfs_alloc_rec_t)), 0, NULL, cntbt_rec_flds }, /* CRC field */ - { FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(__uint32_t)), + { FLDT_CRC, "crc", fp_crc, "%#x (%s)", SI(bitsz(uint32_t)), 0, NULL, NULL }, { FLDT_DEV, "dev", fp_num, "%#x", SI(bitsz(xfs_dev_t)), 0, NULL, NULL }, @@ -180,7 +180,7 @@ const ftattr_t ftattrtab[] = { { FLDT_DINODE_CORE, "dinode_core", NULL, (char *)inode_core_flds, SI(bitsz(xfs_dinode_t)), 0, NULL, inode_core_flds }, { FLDT_DINODE_FMT, "dinode_fmt", fp_dinode_fmt, NULL, - SI(bitsz(__int8_t)), 0, NULL, NULL }, + SI(bitsz(int8_t)), 0, NULL, NULL }, { FLDT_DINODE_U, "dinode_u", NULL, (char *)inode_u_flds, inode_u_size, FTARG_SIZE|FTARG_OKEMPTY, NULL, inode_u_flds }, { FLDT_DINODE_V3, "dinode_v3", NULL, (char *)inode_v3_flds, @@ -261,7 +261,7 @@ const ftattr_t ftattrtab[] = { { FLDT_DA3_NODE_HDR, "dir_node_hdr", NULL, (char *)da3_node_hdr_flds, SI(bitsz(struct xfs_da3_node_hdr)), 0, NULL, da3_node_hdr_flds }, - { FLDT_DIRBLOCK, "dirblock", fp_num, "%u", SI(bitsz(__uint32_t)), 0, + { FLDT_DIRBLOCK, "dirblock", fp_num, "%u", SI(bitsz(uint32_t)), 0, fa_dirblock, NULL }, { FLDT_DISK_DQUOT, "disk_dquot", NULL, (char *)disk_dquot_flds, SI(bitsz(xfs_disk_dquot_t)), 0, NULL, disk_dquot_flds }, @@ -301,15 +301,15 @@ const ftattr_t ftattrtab[] = { FTARG_SIZE, NULL, inode_crc_flds }, { FLDT_INOFREE, "inofree", fp_num, "%#llx", SI(bitsz(xfs_inofree_t)), 0, NULL, NULL }, - { FLDT_INT16D, "int16d", fp_num, "%d", SI(bitsz(__int16_t)), + { FLDT_INT16D, "int16d", fp_num, "%d", SI(bitsz(int16_t)), FTARG_SIGNED, NULL, NULL }, - { FLDT_INT32D, "int32d", fp_num, "%d", SI(bitsz(__int32_t)), + { FLDT_INT32D, "int32d", fp_num, "%d", SI(bitsz(int32_t)), FTARG_SIGNED, NULL, NULL }, - { FLDT_INT64D, "int64d", fp_num, "%lld", SI(bitsz(__int64_t)), + { FLDT_INT64D, "int64d", fp_num, "%lld", SI(bitsz(int64_t)), FTARG_SIGNED, NULL, NULL }, - { FLDT_INT8D, "int8d", fp_num, "%d", SI(bitsz(__int8_t)), FTARG_SIGNED, + { FLDT_INT8D, "int8d", fp_num, "%d", SI(bitsz(int8_t)), FTARG_SIGNED, NULL, NULL }, - { FLDT_NSEC, "nsec", fp_num, "%09d", SI(bitsz(__int32_t)), FTARG_SIGNED, + { FLDT_NSEC, "nsec", fp_num, "%09d", SI(bitsz(int32_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_QCNT, "qcnt", fp_num, "%llu", SI(bitsz(xfs_qcnt_t)), 0, NULL, NULL }, @@ -322,34 +322,34 @@ const ftattr_t ftattrtab[] = { { FLDT_SYMLINK_CRC, "symlink", NULL, (char *)symlink_crc_flds, symlink_size, FTARG_SIZE, NULL, symlink_crc_flds }, - { FLDT_TIME, "time", fp_time, NULL, SI(bitsz(__int32_t)), FTARG_SIGNED, + { FLDT_TIME, "time", fp_time, NULL, SI(bitsz(int32_t)), FTARG_SIGNED, NULL, NULL }, { FLDT_TIMESTAMP, "timestamp", NULL, (char *)timestamp_flds, SI(bitsz(xfs_timestamp_t)), 0, NULL, timestamp_flds }, { FLDT_UINT1, "uint1", fp_num, "%u", SI(1), 0, NULL, NULL }, - { FLDT_UINT16D, "uint16d", fp_num, "%u", SI(bitsz(__uint16_t)), 0, NULL, + { FLDT_UINT16D, "uint16d", fp_num, "%u", SI(bitsz(uint16_t)), 0, NULL, NULL }, - { FLDT_UINT16O, "uint16o", fp_num, "%#o", SI(bitsz(__uint16_t)), 0, + { FLDT_UINT16O, "uint16o", fp_num, "%#o", SI(bitsz(uint16_t)), 0, NULL, NULL }, - { FLDT_UINT16X, "uint16x", fp_num, "%#x", SI(bitsz(__uint16_t)), 0, + { FLDT_UINT16X, "uint16x", fp_num, "%#x", SI(bitsz(uint16_t)), 0, NULL, NULL }, - { FLDT_UINT32D, "uint32d", fp_num, "%u", SI(bitsz(__uint32_t)), 0, NULL, + { FLDT_UINT32D, "uint32d", fp_num, "%u", SI(bitsz(uint32_t)), 0, NULL, NULL }, - { FLDT_UINT32O, "uint32o", fp_num, "%#o", SI(bitsz(__uint32_t)), 0, + { FLDT_UINT32O, "uint32o", fp_num, "%#o", SI(bitsz(uint32_t)), 0, NULL, NULL }, - { FLDT_UINT32X, "uint32x", fp_num, "%#x", SI(bitsz(__uint32_t)), 0, + { FLDT_UINT32X, "uint32x", fp_num, "%#x", SI(bitsz(uint32_t)), 0, NULL, NULL }, - { FLDT_UINT64D, "uint64d", fp_num, "%llu", SI(bitsz(__uint64_t)), 0, + { FLDT_UINT64D, "uint64d", fp_num, "%llu", SI(bitsz(uint64_t)), 0, NULL, NULL }, - { FLDT_UINT64O, "uint64o", fp_num, "%#llo", SI(bitsz(__uint64_t)), 0, + { FLDT_UINT64O, "uint64o", fp_num, "%#llo", SI(bitsz(uint64_t)), 0, NULL, NULL }, - { FLDT_UINT64X, "uint64x", fp_num, "%#llx", SI(bitsz(__uint64_t)), 0, + { FLDT_UINT64X, "uint64x", fp_num, "%#llx", SI(bitsz(uint64_t)), 0, NULL, NULL }, - { FLDT_UINT8D, "uint8d", fp_num, "%u", SI(bitsz(__uint8_t)), 0, NULL, + { FLDT_UINT8D, "uint8d", fp_num, "%u", SI(bitsz(uint8_t)), 0, NULL, NULL }, - { FLDT_UINT8O, "uint8o", fp_num, "%#o", SI(bitsz(__uint8_t)), 0, NULL, + { FLDT_UINT8O, "uint8o", fp_num, "%#o", SI(bitsz(uint8_t)), 0, NULL, NULL }, - { FLDT_UINT8X, "uint8x", fp_num, "%#x", SI(bitsz(__uint8_t)), 0, NULL, + { FLDT_UINT8X, "uint8x", fp_num, "%#x", SI(bitsz(uint8_t)), 0, NULL, NULL }, { FLDT_UUID, "uuid", fp_uuid, NULL, SI(bitsz(uuid_t)), 0, NULL, NULL }, { FLDT_ZZZ, NULL } diff --git a/db/fprint.c b/db/fprint.c index f2b3794..1c49bdd 100644 --- a/db/fprint.c +++ b/db/fprint.c @@ -80,7 +80,7 @@ fp_num( int bitpos; int i; int isnull; - __int64_t val; + int64_t val; for (i = 0, bitpos = bit; i < count && !seenint(); @@ -100,7 +100,7 @@ fp_num( else if (size > 32) dbprintf(fmtstr, val); else - dbprintf(fmtstr, (__int32_t)val); + dbprintf(fmtstr, (int32_t)val); if (i < count - 1) dbprintf(" "); } @@ -203,7 +203,7 @@ fp_crc( { int bitpos; int i; - __int64_t val; + int64_t val; char *ok; switch (iocur_crc_valid()) { @@ -230,7 +230,7 @@ fp_crc( if (size > 32) dbprintf(fmtstr, val, ok); else - dbprintf(fmtstr, (__int32_t)val, ok); + dbprintf(fmtstr, (int32_t)val, ok); if (i < count - 1) dbprintf(" "); } diff --git a/db/frag.c b/db/frag.c index 36bb689..c36b315 100644 --- a/db/frag.c +++ b/db/frag.c @@ -42,8 +42,8 @@ typedef struct extmap { static int aflag; static int dflag; -static __uint64_t extcount_actual; -static __uint64_t extcount_ideal; +static uint64_t extcount_actual; +static uint64_t extcount_ideal; static int fflag; static int lflag; static int qflag; @@ -306,8 +306,8 @@ process_inode( xfs_agino_t agino, xfs_dinode_t *dip) { - __uint64_t actual; - __uint64_t ideal; + uint64_t actual; + uint64_t ideal; xfs_ino_t ino; int skipa; int skipd; diff --git a/db/inode.c b/db/inode.c index 442e6ea..3b2ee1a 100644 --- a/db/inode.c +++ b/db/inode.c @@ -119,49 +119,49 @@ const field_t inode_core_flds[] = { { "dmstate", FLDT_UINT16D, OI(COFF(dmstate)), C1, 0, TYP_NONE }, { "flags", FLDT_UINT16X, OI(COFF(flags)), C1, FLD_SKIPALL, TYP_NONE }, { "newrtbm", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NEWRTBM_BIT - 1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NEWRTBM_BIT - 1), C1, 0, TYP_NONE }, { "prealloc", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_PREALLOC_BIT - 1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_PREALLOC_BIT - 1), C1, 0, TYP_NONE }, { "realtime", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_REALTIME_BIT - 1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_REALTIME_BIT - 1), C1, 0, TYP_NONE }, { "immutable", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_IMMUTABLE_BIT-1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_IMMUTABLE_BIT-1), C1, 0, TYP_NONE }, { "append", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_APPEND_BIT - 1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_APPEND_BIT - 1), C1, 0, TYP_NONE }, { "sync", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_SYNC_BIT - 1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_SYNC_BIT - 1), C1, 0, TYP_NONE }, { "noatime", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NOATIME_BIT - 1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NOATIME_BIT - 1), C1, 0, TYP_NONE }, { "nodump", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NODUMP_BIT - 1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NODUMP_BIT - 1), C1, 0, TYP_NONE }, { "rtinherit", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_RTINHERIT_BIT-1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_RTINHERIT_BIT-1), C1, 0, TYP_NONE }, { "projinherit", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_PROJINHERIT_BIT-1),C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_PROJINHERIT_BIT-1),C1, 0, TYP_NONE }, { "nosymlinks", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NOSYMLINKS_BIT-1), C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NOSYMLINKS_BIT-1), C1, 0, TYP_NONE }, { "extsz", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_EXTSIZE_BIT-1),C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_EXTSIZE_BIT-1),C1, 0, TYP_NONE }, { "extszinherit", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_EXTSZINHERIT_BIT-1),C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_EXTSZINHERIT_BIT-1),C1, 0, TYP_NONE }, { "nodefrag", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_NODEFRAG_BIT-1),C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_NODEFRAG_BIT-1),C1, 0, TYP_NONE }, { "filestream", FLDT_UINT1, - OI(COFF(flags) + bitsz(__uint16_t) - XFS_DIFLAG_FILESTREAM_BIT-1),C1, + OI(COFF(flags) + bitsz(uint16_t) - XFS_DIFLAG_FILESTREAM_BIT-1),C1, 0, TYP_NONE }, { "gen", FLDT_UINT32D, OI(COFF(gen)), C1, 0, TYP_NONE }, { NULL } diff --git a/db/io.c b/db/io.c index 9452e07..bfb9e38 100644 --- a/db/io.c +++ b/db/io.c @@ -487,7 +487,7 @@ write_cur(void) void set_cur( const typ_t *t, - __int64_t d, + int64_t d, int c, int ring_flag, bbmap_t *bbmap) @@ -495,7 +495,7 @@ set_cur( struct xfs_buf *bp; xfs_ino_t dirino; xfs_ino_t ino; - __uint16_t mode; + uint16_t mode; const struct xfs_buf_ops *ops = t ? t->bops : NULL; if (iocur_sp < 0) { diff --git a/db/io.h b/db/io.h index 6201d7b..2b0dcc0 100644 --- a/db/io.h +++ b/db/io.h @@ -25,7 +25,7 @@ typedef struct bbmap { } bbmap_t; typedef struct iocur { - __int64_t bb; /* BB number in filesystem of buf */ + int64_t bb; /* BB number in filesystem of buf */ int blen; /* length of "buf", bb's */ int boff; /* data - buf */ void *buf; /* base address of buffer */ @@ -33,7 +33,7 @@ typedef struct iocur { xfs_ino_t dirino; /* current directory inode number */ xfs_ino_t ino; /* current inode number */ int len; /* length of "data", bytes */ - __uint16_t mode; /* current inode's mode */ + uint16_t mode; /* current inode's mode */ xfs_off_t off; /* fs offset of "data" in bytes */ const struct typ *typ; /* type of "data" */ bbmap_t *bbmap; /* map daddr if fragmented */ @@ -57,9 +57,9 @@ extern void off_cur(int off, int len); extern void pop_cur(void); extern void print_iocur(char *tag, iocur_t *ioc); extern void push_cur(void); -extern int read_buf(__int64_t daddr, int count, void *bufp); +extern int read_buf(int64_t daddr, int count, void *bufp); extern void write_cur(void); -extern void set_cur(const struct typ *t, __int64_t d, int c, int ring_add, +extern void set_cur(const struct typ *t, int64_t d, int c, int ring_add, bbmap_t *bbmap); extern void ring_add(void); extern void set_iocur_type(const struct typ *t); diff --git a/db/metadump.c b/db/metadump.c index d7ff6e5..60f69c4 100644 --- a/db/metadump.c +++ b/db/metadump.c @@ -175,7 +175,7 @@ write_index(void) static int write_buf_segment( char *data, - __int64_t off, + int64_t off, int len) { int i; @@ -1112,7 +1112,7 @@ process_sf_dir( { struct xfs_dir2_sf_hdr *sfp; xfs_dir2_sf_entry_t *sfep; - __uint64_t ino_dir_size; + uint64_t ino_dir_size; int i; sfp = (struct xfs_dir2_sf_hdr *)XFS_DFORK_DPTR(dip); @@ -1178,7 +1178,7 @@ process_sf_dir( static void obfuscate_path_components( char *buf, - __uint64_t len) + uint64_t len) { unsigned char *comp = (unsigned char *)buf; unsigned char *end = comp + len; @@ -1215,7 +1215,7 @@ static void process_sf_symlink( xfs_dinode_t *dip) { - __uint64_t len; + uint64_t len; char *buf; len = be64_to_cpu(dip->di_size); @@ -1487,7 +1487,7 @@ process_attr_block( xfs_attr_leaf_entry_t *entry; xfs_attr_leaf_name_local_t *local; xfs_attr_leaf_name_remote_t *remote; - __uint32_t bs = mp->m_sb.sb_blocksize; + uint32_t bs = mp->m_sb.sb_blocksize; char *first_name; @@ -2125,7 +2125,7 @@ done: return success; } -static __uint32_t inodes_copied = 0; +static uint32_t inodes_copied = 0; static int copy_inode_chunk( diff --git a/db/sb.c b/db/sb.c index 79a3c1d..e870aa6 100644 --- a/db/sb.c +++ b/db/sb.c @@ -606,7 +606,7 @@ version_help(void) } static int -do_version(xfs_agnumber_t agno, __uint16_t version, __uint32_t features) +do_version(xfs_agnumber_t agno, uint16_t version, uint32_t features) { xfs_sb_t tsb; @@ -708,8 +708,8 @@ version_f( int argc, char **argv) { - __uint16_t version = 0; - __uint32_t features = 0; + uint16_t version = 0; + uint32_t features = 0; xfs_agnumber_t ag; if (argc == 2) { /* WRITE VERSION */ diff --git a/fsr/xfs_fsr.c b/fsr/xfs_fsr.c index d75990a..b57996a 100644 --- a/fsr/xfs_fsr.c +++ b/fsr/xfs_fsr.c @@ -54,7 +54,7 @@ struct getbmap *outmap = NULL; int outmap_size = 0; int RealUid; int tmp_agi; -static __int64_t minimumfree = 2048; +static int64_t minimumfree = 2048; #define MNTTYPE_XFS "xfs" diff --git a/libhandle/handle.c b/libhandle/handle.c index 236ed22..00127b3 100644 --- a/libhandle/handle.c +++ b/libhandle/handle.c @@ -232,7 +232,7 @@ obj_to_handle( { char hbuf [MAXHANSIZ]; int ret; - __uint32_t handlen; + uint32_t handlen; xfs_fsop_handlereq_t hreq; if (opcode == XFS_IOC_FD_TO_HANDLE) { diff --git a/libhandle/jdm.c b/libhandle/jdm.c index e52f5d8..821061b 100644 --- a/libhandle/jdm.c +++ b/libhandle/jdm.c @@ -36,7 +36,7 @@ typedef struct filehandle { fshandle_t fh_fshandle; /* handle of fs containing this inode */ int16_t fh_sz_following; /* bytes in handle after this member */ char fh_pad[FILEHANDLE_SZ_PAD]; /* padding, must be zeroed */ - __uint32_t fh_gen; /* generation count */ + uint32_t fh_gen; /* generation count */ xfs_ino_t fh_ino; /* 64 bit ino */ } filehandle_t; diff --git a/logprint/log_misc.c b/logprint/log_misc.c index e6ee832..894a7d1 100644 --- a/logprint/log_misc.c +++ b/logprint/log_misc.c @@ -212,12 +212,12 @@ xlog_print_trans_header(char **ptr, int len) { xfs_trans_header_t *h; char *cptr = *ptr; - __uint32_t magic; + uint32_t magic; char *magic_c = (char *)&magic; *ptr += len; - magic=*(__uint32_t*)cptr; /* XXX be32_to_cpu soon */ + magic=*(uint32_t*)cptr; /* XXX be32_to_cpu soon */ if (len >= 4) { #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -247,7 +247,7 @@ xlog_print_trans_buffer(char **ptr, int len, int *i, int num_ops) int num, skip; int super_block = 0; int bucket, col, buckets; - __int64_t blkno; + int64_t blkno; xfs_buf_log_format_t lbuf; int size, blen, map_size, struct_size; __be64 x, y; diff --git a/mdrestore/xfs_mdrestore.c b/mdrestore/xfs_mdrestore.c index a22efc2..ecbce43 100644 --- a/mdrestore/xfs_mdrestore.c +++ b/mdrestore/xfs_mdrestore.c @@ -65,7 +65,7 @@ perform_restore( int mb_count; xfs_metablock_t tmb; xfs_sb_t sb; - __int64_t bytes_read; + int64_t bytes_read; /* * read in first blocks (superblock 0), set "inprogress" flag for it, diff --git a/mkfs/proto.c b/mkfs/proto.c index 09a9439..f4e238d 100644 --- a/mkfs/proto.c +++ b/mkfs/proto.c @@ -669,7 +669,7 @@ rtinit( mp->m_sb.sb_rbmino = rbmip->i_ino; rbmip->i_d.di_size = mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize; rbmip->i_d.di_flags = XFS_DIFLAG_NEWRTBM; - *(__uint64_t *)&VFS_I(rbmip)->i_atime = 0; + *(uint64_t *)&VFS_I(rbmip)->i_atime = 0; libxfs_trans_log_inode(tp, rbmip, XFS_ILOG_CORE); libxfs_log_sb(tp); mp->m_rbmip = rbmip; diff --git a/mkfs/xfs_mkfs.c b/mkfs/xfs_mkfs.c index 99c5eb5..8224bfc 100644 --- a/mkfs/xfs_mkfs.c +++ b/mkfs/xfs_mkfs.c @@ -702,9 +702,9 @@ struct opt_params mopts = { }, }; -#define TERABYTES(count, blog) ((__uint64_t)(count) << (40 - (blog))) -#define GIGABYTES(count, blog) ((__uint64_t)(count) << (30 - (blog))) -#define MEGABYTES(count, blog) ((__uint64_t)(count) << (20 - (blog))) +#define TERABYTES(count, blog) ((uint64_t)(count) << (40 - (blog))) +#define GIGABYTES(count, blog) ((uint64_t)(count) << (30 - (blog))) +#define MEGABYTES(count, blog) ((uint64_t)(count) << (20 - (blog))) /* * Use this macro before we have superblock and mount structure @@ -1099,7 +1099,7 @@ fixup_log_stripe_unit( xfs_rfsblock_t *logblocks, int blocklog) { - __uint64_t tmp_logblocks; + uint64_t tmp_logblocks; /* * Make sure that the log size is a multiple of the stripe unit @@ -1131,7 +1131,7 @@ fixup_internal_log_stripe( xfs_mount_t *mp, int lsflag, xfs_fsblock_t logstart, - __uint64_t agsize, + uint64_t agsize, int sunit, xfs_rfsblock_t *logblocks, int blocklog, @@ -1155,7 +1155,7 @@ fixup_internal_log_stripe( } void -validate_log_size(__uint64_t logblocks, int blocklog, int min_logblocks) +validate_log_size(uint64_t logblocks, int blocklog, int min_logblocks) { if (logblocks < min_logblocks) { fprintf(stderr, @@ -1180,7 +1180,7 @@ validate_log_size(__uint64_t logblocks, int blocklog, int min_logblocks) static int calc_default_imaxpct( int blocklog, - __uint64_t dblocks) + uint64_t dblocks) { /* * This returns the % of the disk space that is used for @@ -1203,12 +1203,12 @@ calc_default_imaxpct( void calc_default_ag_geometry( int blocklog, - __uint64_t dblocks, + uint64_t dblocks, int multidisk, - __uint64_t *agsize, - __uint64_t *agcount) + uint64_t *agsize, + uint64_t *agcount) { - __uint64_t blocks = 0; + uint64_t blocks = 0; int shift = 0; /* @@ -1276,9 +1276,9 @@ done: static void validate_ag_geometry( int blocklog, - __uint64_t dblocks, - __uint64_t agsize, - __uint64_t agcount) + uint64_t dblocks, + uint64_t agsize, + uint64_t agcount) { if (agsize < XFS_AG_MIN_BLOCKS(blocklog)) { fprintf(stderr, @@ -1354,7 +1354,7 @@ zero_old_xfs_structures( { void *buf; xfs_sb_t sb; - __uint32_t bsize; + uint32_t bsize; int i; xfs_off_t off; @@ -1407,8 +1407,8 @@ zero_old_xfs_structures( i != sb.sb_blocklog) goto done; - if (sb.sb_dblocks > ((__uint64_t)sb.sb_agcount * sb.sb_agblocks) || - sb.sb_dblocks < ((__uint64_t)(sb.sb_agcount - 1) * + if (sb.sb_dblocks > ((uint64_t)sb.sb_agcount * sb.sb_agblocks) || + sb.sb_dblocks < ((uint64_t)(sb.sb_agcount - 1) * sb.sb_agblocks + XFS_MIN_AG_BLOCKS)) goto done; @@ -1428,7 +1428,7 @@ done: } static void -discard_blocks(dev_t dev, __uint64_t nsectors) +discard_blocks(dev_t dev, uint64_t nsectors) { int fd; @@ -1684,11 +1684,11 @@ main( int argc, char **argv) { - __uint64_t agcount; + uint64_t agcount; xfs_agf_t *agf; xfs_agi_t *agi; xfs_agnumber_t agno; - __uint64_t agsize; + uint64_t agsize; xfs_alloc_rec_t *arec; struct xfs_btree_block *block; int blflag; @@ -1763,10 +1763,10 @@ main( char *rtsize; xfs_sb_t *sbp; int sectorlog; - __uint64_t sector_mask; + uint64_t sector_mask; int slflag; int ssflag; - __uint64_t tmp_agsize; + uint64_t tmp_agsize; uuid_t uuid; int worst_freelist; libxfs_init_t xi; @@ -2428,7 +2428,7 @@ _("sparse inodes not supported without CRC support\n")); if (dsize) { - __uint64_t dbytes; + uint64_t dbytes; dbytes = getnum(dsize, &dopts, D_SIZE); if (dbytes % XFS_MIN_BLOCKSIZE) { @@ -2460,7 +2460,7 @@ _("sparse inodes not supported without CRC support\n")); } if (logsize) { - __uint64_t logbytes; + uint64_t logbytes; logbytes = getnum(logsize, &lopts, L_SIZE); if (logbytes % XFS_MIN_BLOCKSIZE) { @@ -2477,7 +2477,7 @@ _("sparse inodes not supported without CRC support\n")); (long long)(logblocks << blocklog)); } if (rtsize) { - __uint64_t rtbytes; + uint64_t rtbytes; rtbytes = getnum(rtsize, &ropts, R_SIZE); if (rtbytes % XFS_MIN_BLOCKSIZE) { @@ -2497,7 +2497,7 @@ _("sparse inodes not supported without CRC support\n")); * If specified, check rt extent size against its constraints. */ if (rtextsize) { - __uint64_t rtextbytes; + uint64_t rtextbytes; rtextbytes = getnum(rtextsize, &ropts, R_EXTSIZE); if (rtextbytes % blocksize) { @@ -2513,8 +2513,8 @@ _("sparse inodes not supported without CRC support\n")); * and the underlying volume is striped, then set rtextblocks * to the stripe width. */ - __uint64_t rswidth; - __uint64_t rtextbytes; + uint64_t rswidth; + uint64_t rtextbytes; if (!norsflag && !xi.risfile && !(!rtsize && xi.disfile)) rswidth = ft.rtswidth; @@ -2592,10 +2592,10 @@ _("sparse inodes not supported without CRC support\n")); * multiple of the sector size, or 1024, whichever is larger. */ - sector_mask = (__uint64_t)-1 << (MAX(sectorlog, 10) - BBSHIFT); + sector_mask = (uint64_t)-1 << (MAX(sectorlog, 10) - BBSHIFT); xi.dsize &= sector_mask; xi.rtsize &= sector_mask; - xi.logBBsize &= (__uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT); + xi.logBBsize &= (uint64_t)-1 << (MAX(lsectorlog, 10) - BBSHIFT); /* don't do discards on print-only runs or on files */ @@ -2956,9 +2956,9 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), mp = &mbuf; sbp = &mp->m_sb; memset(mp, 0, sizeof(xfs_mount_t)); - sbp->sb_blocklog = (__uint8_t)blocklog; - sbp->sb_sectlog = (__uint8_t)sectorlog; - sbp->sb_agblklog = (__uint8_t)libxfs_log2_roundup((unsigned int)agsize); + sbp->sb_blocklog = (uint8_t)blocklog; + sbp->sb_sectlog = (uint8_t)sectorlog; + sbp->sb_agblklog = (uint8_t)libxfs_log2_roundup((unsigned int)agsize); sbp->sb_agblocks = (xfs_agblock_t)agsize; mp->m_blkbb_log = sbp->sb_blocklog - BBSHIFT; mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; @@ -3064,14 +3064,14 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), sbp->sb_agcount = (xfs_agnumber_t)agcount; sbp->sb_rbmblocks = nbmblocks; sbp->sb_logblocks = (xfs_extlen_t)logblocks; - sbp->sb_sectsize = (__uint16_t)sectorsize; - sbp->sb_inodesize = (__uint16_t)isize; - sbp->sb_inopblock = (__uint16_t)(blocksize / isize); - sbp->sb_sectlog = (__uint8_t)sectorlog; - sbp->sb_inodelog = (__uint8_t)inodelog; - sbp->sb_inopblog = (__uint8_t)(blocklog - inodelog); + sbp->sb_sectsize = (uint16_t)sectorsize; + sbp->sb_inodesize = (uint16_t)isize; + sbp->sb_inopblock = (uint16_t)(blocksize / isize); + sbp->sb_sectlog = (uint8_t)sectorlog; + sbp->sb_inodelog = (uint8_t)inodelog; + sbp->sb_inopblog = (uint8_t)(blocklog - inodelog); sbp->sb_rextslog = - (__uint8_t)(rtextents ? + (uint8_t)(rtextents ? libxfs_highbit32((unsigned int)rtextents) : 0); sbp->sb_inprogress = 1; /* mkfs is in progress */ sbp->sb_imax_pct = imaxpct; @@ -3099,8 +3099,8 @@ _("size %s specified for log subvolume is too large, maximum is %lld blocks\n"), } else sbp->sb_inoalignmt = 0; if (lsectorsize != BBSIZE || sectorsize != BBSIZE) { - sbp->sb_logsectlog = (__uint8_t)lsectorlog; - sbp->sb_logsectsize = (__uint16_t)lsectorsize; + sbp->sb_logsectlog = (uint8_t)lsectorlog; + sbp->sb_logsectsize = (uint16_t)lsectorsize; } else { sbp->sb_logsectlog = 0; sbp->sb_logsectsize = 0; diff --git a/quota/edit.c b/quota/edit.c index e5ddc8c..2626148 100644 --- a/quota/edit.c +++ b/quota/edit.c @@ -115,16 +115,16 @@ warn_help(void) static void set_limits( - __uint32_t id, + uint32_t id, uint type, uint mask, char *dev, - __uint64_t *bsoft, - __uint64_t *bhard, - __uint64_t *isoft, - __uint64_t *ihard, - __uint64_t *rtbsoft, - __uint64_t *rtbhard) + uint64_t *bsoft, + uint64_t *bhard, + uint64_t *isoft, + uint64_t *ihard, + uint64_t *rtbsoft, + uint64_t *rtbhard) { fs_disk_quota_t d; @@ -152,12 +152,12 @@ set_user_limits( char *name, uint type, uint mask, - __uint64_t *bsoft, - __uint64_t *bhard, - __uint64_t *isoft, - __uint64_t *ihard, - __uint64_t *rtbsoft, - __uint64_t *rtbhard) + uint64_t *bsoft, + uint64_t *bhard, + uint64_t *isoft, + uint64_t *ihard, + uint64_t *rtbsoft, + uint64_t *rtbhard) { uid_t uid = uid_from_string(name); @@ -175,12 +175,12 @@ set_group_limits( char *name, uint type, uint mask, - __uint64_t *bsoft, - __uint64_t *bhard, - __uint64_t *isoft, - __uint64_t *ihard, - __uint64_t *rtbsoft, - __uint64_t *rtbhard) + uint64_t *bsoft, + uint64_t *bhard, + uint64_t *isoft, + uint64_t *ihard, + uint64_t *rtbsoft, + uint64_t *rtbhard) { gid_t gid = gid_from_string(name); @@ -198,12 +198,12 @@ set_project_limits( char *name, uint type, uint mask, - __uint64_t *bsoft, - __uint64_t *bhard, - __uint64_t *isoft, - __uint64_t *ihard, - __uint64_t *rtbsoft, - __uint64_t *rtbhard) + uint64_t *bsoft, + uint64_t *bhard, + uint64_t *isoft, + uint64_t *ihard, + uint64_t *rtbsoft, + uint64_t *rtbhard) { prid_t prid = prid_from_string(name); @@ -224,7 +224,7 @@ extractb( int length, uint blocksize, uint sectorsize, - __uint64_t *value) + uint64_t *value) { long long v; char *s = string; @@ -238,7 +238,7 @@ extractb( progname, s); return 0; } - *value = (__uint64_t)v >> 9; /* syscalls use basic blocks */ + *value = (uint64_t)v >> 9; /* syscalls use basic blocks */ if (v > 0 && *value == 0) fprintf(stderr, _("%s: Warning: `%s' in quota blocks is 0 (unlimited).\n"), progname, s); return 1; @@ -252,7 +252,7 @@ extracti( char *string, const char *prefix, int length, - __uint64_t *value) + uint64_t *value) { char *sp, *s = string; @@ -270,7 +270,7 @@ limit_f( char **argv) { char *name; - __uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard; + uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard; int c, type = 0, mask = 0, flags = 0; uint bsize, ssize, endoptions; @@ -384,8 +384,8 @@ restore_file( char *dev = NULL; uint mask; int cnt; - __uint32_t id; - __uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard; + uint32_t id; + uint64_t bsoft, bhard, isoft, ihard, rtbsoft, rtbhard; while (fgets(buffer, sizeof(buffer), fp) != NULL) { if (strncmp("fs = ", buffer, 5) == 0) { @@ -546,7 +546,7 @@ timer_f( static void set_warnings( - __uint32_t id, + uint32_t id, uint type, uint mask, char *dev, diff --git a/quota/free.c b/quota/free.c index e9e0319..584c77c 100644 --- a/quota/free.c +++ b/quota/free.c @@ -48,20 +48,20 @@ free_help(void) static int mount_free_space_data( struct fs_path *mount, - __uint64_t *bcount, - __uint64_t *bused, - __uint64_t *bfree, - __uint64_t *icount, - __uint64_t *iused, - __uint64_t *ifree, - __uint64_t *rcount, - __uint64_t *rused, - __uint64_t *rfree) + uint64_t *bcount, + uint64_t *bused, + uint64_t *bfree, + uint64_t *icount, + uint64_t *iused, + uint64_t *ifree, + uint64_t *rcount, + uint64_t *rused, + uint64_t *rfree) { struct xfs_fsop_counts fscounts; struct xfs_fsop_geom fsgeo; struct statfs st; - __uint64_t logsize, count, free; + uint64_t logsize, count, free; int fd; if ((fd = open(mount->fs_dir, O_RDONLY)) < 0) { @@ -115,15 +115,15 @@ mount_free_space_data( static int projects_free_space_data( struct fs_path *path, - __uint64_t *bcount, - __uint64_t *bused, - __uint64_t *bfree, - __uint64_t *icount, - __uint64_t *iused, - __uint64_t *ifree, - __uint64_t *rcount, - __uint64_t *rused, - __uint64_t *rfree) + uint64_t *bcount, + uint64_t *bused, + uint64_t *bfree, + uint64_t *icount, + uint64_t *iused, + uint64_t *ifree, + uint64_t *rcount, + uint64_t *rused, + uint64_t *rfree) { fs_quota_stat_t qfs; fs_disk_quota_t d; @@ -209,9 +209,9 @@ free_space( fs_path_t *path, uint flags) { - __uint64_t bcount, bused, bfree; - __uint64_t icount, iused, ifree; - __uint64_t rcount, rused, rfree; + uint64_t bcount, bused, bfree; + uint64_t icount, iused, ifree; + uint64_t rcount, rused, rfree; char a[8], s[8], u[8], p[8]; int count; diff --git a/quota/quot.c b/quota/quot.c index 2e583e5..57eeeb2 100644 --- a/quota/quot.c +++ b/quota/quot.c @@ -25,17 +25,17 @@ typedef struct du { struct du *next; - __uint64_t blocks; - __uint64_t blocks30; - __uint64_t blocks60; - __uint64_t blocks90; - __uint64_t nfiles; - __uint32_t id; + uint64_t blocks; + uint64_t blocks30; + uint64_t blocks60; + uint64_t blocks90; + uint64_t nfiles; + uint32_t id; } du_t; #define TSIZE 500 -static __uint64_t sizes[TSIZE]; -static __uint64_t overflow; +static uint64_t sizes[TSIZE]; +static uint64_t overflow; #define NDU 60000 #define DUHASH 8209 @@ -83,8 +83,8 @@ quot_bulkstat_add( { du_t *dp; du_t **hp; - __uint64_t size; - __uint32_t i, id; + uint64_t size; + uint32_t i, id; if ((p->bs_mode & S_IFMT) == 0) return; @@ -202,7 +202,7 @@ qcompare( return 0; } -typedef char *(*idtoname_t)(__uint32_t); +typedef char *(*idtoname_t)(uint32_t); static void quot_report_mount_any_type( @@ -290,7 +290,7 @@ quot_histogram_mount( fs_path_t *mount, uint flags) { - __uint64_t t = 0; + uint64_t t = 0; int i; fprintf(fp, _("%s (%s):\n"), mount->fs_name, mount->fs_dir); diff --git a/quota/quota.c b/quota/quota.c index e0da7c0..16c90b2 100644 --- a/quota/quota.c +++ b/quota/quota.c @@ -51,7 +51,7 @@ quota_help(void) static int quota_mount( FILE *fp, - __uint32_t id, + uint32_t id, char *name, uint form, uint type, @@ -180,7 +180,7 @@ quota_mount( static void quota( FILE *fp, - __uint32_t id, + uint32_t id, char *name, uint form, uint type, diff --git a/quota/quota.h b/quota/quota.h index 4bde351..9ed28be 100644 --- a/quota/quota.h +++ b/quota/quota.h @@ -53,9 +53,9 @@ enum { extern char *type_to_string(uint __type); extern char *form_to_string(uint __form); extern char *time_to_string(time_t __time, uint __flags); -extern char *bbs_to_string(__uint64_t __v, char *__c, uint __size); -extern char *num_to_string(__uint64_t __v, char *__c, uint __size); -extern char *pct_to_string(__uint64_t __v, __uint64_t __t, char *__c, uint __s); +extern char *bbs_to_string(uint64_t __v, char *__c, uint __size); +extern char *num_to_string(uint64_t __v, char *__c, uint __size); +extern char *pct_to_string(uint64_t __v, uint64_t __t, char *__c, uint __s); extern FILE *fopen_write_secure(char *__filename); @@ -81,7 +81,7 @@ enum { * Identifier (uid/gid/prid) cache routines */ #define NMAX 32 -extern char *uid_to_name(__uint32_t __uid); -extern char *gid_to_name(__uint32_t __gid); -extern char *prid_to_name(__uint32_t __prid); +extern char *uid_to_name(uint32_t __uid); +extern char *gid_to_name(uint32_t __gid); +extern char *prid_to_name(uint32_t __prid); extern bool isdigits_only(const char *); diff --git a/quota/report.c b/quota/report.c index cc422d1..16cf6e0 100644 --- a/quota/report.c +++ b/quota/report.c @@ -327,9 +327,9 @@ report_header( static int report_mount( FILE *fp, - __uint32_t id, + uint32_t id, char *name, - __uint32_t *oid, + uint32_t *oid, uint form, uint type, fs_path_t *mount, diff --git a/quota/state.c b/quota/state.c index 8186762..82dd26d 100644 --- a/quota/state.c +++ b/quota/state.c @@ -135,7 +135,7 @@ static void state_timelimit( FILE *fp, uint form, - __uint32_t timelimit) + uint32_t timelimit) { fprintf(fp, _("%s grace time: %s\n"), form_to_string(form), diff --git a/quota/util.c b/quota/util.c index 7c43fbd..bc7f1d5 100644 --- a/quota/util.c +++ b/quota/util.c @@ -81,8 +81,8 @@ round_snprintf( size_t size, const char *fmt_round, const char *fmt_not_round, - __uint64_t value, - __uint64_t divisor) + uint64_t value, + uint64_t divisor) { double v = (double)value / divisor; @@ -94,23 +94,23 @@ round_snprintf( } /* Basic blocks (512) bytes are returned from quotactl */ -#define BBS_TO_EXABYTES(bbs) ((__uint64_t)(bbs)>>51) -#define BBS_TO_PETABYTES(bbs) ((__uint64_t)(bbs)>>41) -#define BBS_TO_TERABYTES(bbs) ((__uint64_t)(bbs)>>31) -#define BBS_TO_GIGABYTES(bbs) ((__uint64_t)(bbs)>>21) -#define BBS_TO_MEGABYTES(bbs) ((__uint64_t)(bbs)>>11) -#define BBS_TO_KILOBYTES(bbs) ((__uint64_t)(bbs)>>1) - -#define BBEXABYTE ((__uint64_t)1<<51) -#define BBPETABYTE ((__uint64_t)1<<41) -#define BBTERABYTE ((__uint64_t)1<<31) -#define BBGIGABYTE ((__uint64_t)1<<21) -#define BBMEGABYTE ((__uint64_t)1<<11) -#define BBKILOBYTE ((__uint64_t)1<< 1) +#define BBS_TO_EXABYTES(bbs) ((uint64_t)(bbs)>>51) +#define BBS_TO_PETABYTES(bbs) ((uint64_t)(bbs)>>41) +#define BBS_TO_TERABYTES(bbs) ((uint64_t)(bbs)>>31) +#define BBS_TO_GIGABYTES(bbs) ((uint64_t)(bbs)>>21) +#define BBS_TO_MEGABYTES(bbs) ((uint64_t)(bbs)>>11) +#define BBS_TO_KILOBYTES(bbs) ((uint64_t)(bbs)>>1) + +#define BBEXABYTE ((uint64_t)1<<51) +#define BBPETABYTE ((uint64_t)1<<41) +#define BBTERABYTE ((uint64_t)1<<31) +#define BBGIGABYTE ((uint64_t)1<<21) +#define BBMEGABYTE ((uint64_t)1<<11) +#define BBKILOBYTE ((uint64_t)1<< 1) char * bbs_to_string( - __uint64_t v, + uint64_t v, char *sp, uint size) { @@ -133,17 +133,17 @@ bbs_to_string( return sp; } -#define THOUSAND ((__uint64_t)1000) -#define MILLION ((__uint64_t)1000*1000) -#define BILLION ((__uint64_t)1000*1000*1000) -#define TRILLION ((__uint64_t)1000*1000*1000*1000) -#define GAZILLION ((__uint64_t)1000*1000*1000*1000*1000) -#define RIDICULOUS ((__uint64_t)1000*1000*1000*1000*1000*1000) -#define STOPALREADY ((__uint64_t)1000*1000*1000*1000*1000*1000*1000) +#define THOUSAND ((uint64_t)1000) +#define MILLION ((uint64_t)1000*1000) +#define BILLION ((uint64_t)1000*1000*1000) +#define TRILLION ((uint64_t)1000*1000*1000*1000) +#define GAZILLION ((uint64_t)1000*1000*1000*1000*1000) +#define RIDICULOUS ((uint64_t)1000*1000*1000*1000*1000*1000) +#define STOPALREADY ((uint64_t)1000*1000*1000*1000*1000*1000*1000) char * num_to_string( - __uint64_t v, + uint64_t v, char *sp, uint size) { @@ -170,8 +170,8 @@ num_to_string( char * pct_to_string( - __uint64_t portion, - __uint64_t whole, + uint64_t portion, + uint64_t whole, char *buf, uint size) { @@ -224,7 +224,7 @@ type_to_string( #define IDMASK (NID-1) typedef struct { - __uint32_t id; + uint32_t id; char name[NMAX+1]; } idcache_t; @@ -237,7 +237,7 @@ static int pentriesleft = NID; static idcache_t * getnextpwent( - __uint32_t id, + uint32_t id, int byid) { struct passwd *pw; @@ -253,7 +253,7 @@ getnextpwent( static idcache_t * getnextgrent( - __uint32_t id, + uint32_t id, int byid) { struct group *gr; @@ -268,7 +268,7 @@ getnextgrent( static idcache_t * getnextprent( - __uint32_t id, + uint32_t id, int byid) { fs_project_t *pr; @@ -283,7 +283,7 @@ getnextprent( char * uid_to_name( - __uint32_t id) + uint32_t id) { idcache_t *ncp, *idp; @@ -320,7 +320,7 @@ uid_to_name( char * gid_to_name( - __uint32_t id) + uint32_t id) { idcache_t *ncp, *idp; @@ -357,7 +357,7 @@ gid_to_name( char * prid_to_name( - __uint32_t id) + uint32_t id) { idcache_t *ncp, *idp; diff --git a/repair/README b/repair/README index 7f168e6..4692463 100644 --- a/repair/README +++ b/repair/README @@ -189,7 +189,7 @@ D - 0) look at usage of XFS_MAKE_IPTR(). It does the right D - 0) look at references to XFS_INODES_PER_CHUNK. change the - ones that really mean sizeof(__uint64_t)*NBBY to + ones that really mean sizeof(uint64_t)*NBBY to something else (like that only defined as a constant INOS_PER_IREC. this isn't as important since XFS_INODES_PER_CHUNK will never chang diff --git a/repair/agheader.h b/repair/agheader.h index 6b2974c..2f7246d 100644 --- a/repair/agheader.h +++ b/repair/agheader.h @@ -20,7 +20,7 @@ typedef struct fs_geometry { /* * these types should match the superblock types */ - __uint32_t sb_blocksize; /* blocksize (bytes) */ + uint32_t sb_blocksize; /* blocksize (bytes) */ xfs_rfsblock_t sb_dblocks; /* # data blocks */ xfs_rfsblock_t sb_rblocks; /* # realtime blocks */ xfs_rtblock_t sb_rextents; /* # realtime extents */ @@ -30,9 +30,9 @@ typedef struct fs_geometry { xfs_agnumber_t sb_agcount; /* # of ags */ xfs_extlen_t sb_rbmblocks; /* # of rt bitmap blocks */ xfs_extlen_t sb_logblocks; /* # of log blocks */ - __uint16_t sb_sectsize; /* volume sector size (bytes) */ - __uint16_t sb_inodesize; /* inode size (bytes) */ - __uint8_t sb_imax_pct; /* max % of fs for inode space */ + uint16_t sb_sectsize; /* volume sector size (bytes) */ + uint16_t sb_inodesize; /* inode size (bytes) */ + uint8_t sb_imax_pct; /* max % of fs for inode space */ /* * these don't have to match the superblock types but are placed @@ -49,10 +49,10 @@ typedef struct fs_geometry { /* * fields after this point have to be checked manually in compare_sb() */ - __uint8_t sb_shared_vn; /* shared version number */ + uint8_t sb_shared_vn; /* shared version number */ xfs_extlen_t sb_inoalignmt; /* inode chunk alignment, fsblocks */ - __uint32_t sb_unit; /* stripe or raid unit */ - __uint32_t sb_width; /* stripe or width unit */ + uint32_t sb_unit; /* stripe or raid unit */ + uint32_t sb_width; /* stripe or width unit */ /* * these don't have to match, they track superblock properties diff --git a/repair/attr_repair.h b/repair/attr_repair.h index 7010e4f..c37d88d 100644 --- a/repair/attr_repair.h +++ b/repair/attr_repair.h @@ -32,10 +32,10 @@ #define ACL_WRITE 02 #define ACL_EXECUTE 01 -typedef __uint16_t xfs_acl_perm_t; -typedef __int32_t xfs_acl_type_t; -typedef __int32_t xfs_acl_tag_t; -typedef __int32_t xfs_acl_id_t; +typedef uint16_t xfs_acl_perm_t; +typedef int32_t xfs_acl_type_t; +typedef int32_t xfs_acl_tag_t; +typedef int32_t xfs_acl_id_t; /* * "icacl" = in-core ACL. There is no equivalent in the XFS kernel code, @@ -50,7 +50,7 @@ struct xfs_icacl_entry { }; struct xfs_icacl { - __int32_t acl_cnt; + int32_t acl_cnt; struct xfs_icacl_entry acl_entry[0]; }; @@ -59,14 +59,14 @@ struct xfs_icacl { */ #define XFS_MAC_MAX_SETS 250 typedef struct xfs_mac_label { - __uint8_t ml_msen_type; /* MSEN label type */ - __uint8_t ml_mint_type; /* MINT label type */ - __uint8_t ml_level; /* Hierarchical level */ - __uint8_t ml_grade; /* Hierarchical grade */ - __uint16_t ml_catcount; /* Category count */ - __uint16_t ml_divcount; /* Division count */ + uint8_t ml_msen_type; /* MSEN label type */ + uint8_t ml_mint_type; /* MINT label type */ + uint8_t ml_level; /* Hierarchical level */ + uint8_t ml_grade; /* Hierarchical grade */ + uint16_t ml_catcount; /* Category count */ + uint16_t ml_divcount; /* Division count */ /* Category set, then Division set */ - __uint16_t ml_list[XFS_MAC_MAX_SETS]; + uint16_t ml_list[XFS_MAC_MAX_SETS]; } xfs_mac_label_t; /* MSEN label type names. Choose an upper case ASCII character. */ @@ -93,7 +93,7 @@ typedef struct xfs_mac_label { /* * Capabilities (IRIX) */ -typedef __uint64_t xfs_cap_value_t; +typedef uint64_t xfs_cap_value_t; typedef struct xfs_cap_set { xfs_cap_value_t cap_effective; /* use in capability checks */ diff --git a/repair/avl64.c b/repair/avl64.c index 51cd624..8f4a121 100644 --- a/repair/avl64.c +++ b/repair/avl64.c @@ -70,8 +70,8 @@ avl64_checktree( avl64node_t *root) { avl64node_t *nlast, *nnext, *np; - __uint64_t offset = 0; - __uint64_t end; + uint64_t offset = 0; + uint64_t end; nlast = nnext = root; @@ -583,8 +583,8 @@ attach: avl64node_t * avl64_findanyrange( avl64tree_desc_t *tree, - __uint64_t start, - __uint64_t end, + uint64_t start, + uint64_t end, int checklen) { avl64node_t *np = tree->avl_root; @@ -655,7 +655,7 @@ avl64_findanyrange( avl64node_t * avl64_findrange( avl64tree_desc_t *tree, - __uint64_t value) + uint64_t value) { avl64node_t *np = tree->avl_root; @@ -682,10 +682,10 @@ avl64_findrange( avl64node_t * avl64_find( avl64tree_desc_t *tree, - __uint64_t value) + uint64_t value) { avl64node_t *np = tree->avl_root; - __uint64_t nvalue; + uint64_t nvalue; while (np) { nvalue = AVL_START(tree, np); @@ -909,8 +909,8 @@ static avl64node_t * avl64_insert_find_growth( avl64tree_desc_t *tree, - __uint64_t start, /* range start at start, */ - __uint64_t end, /* exclusive */ + uint64_t start, /* range start at start, */ + uint64_t end, /* exclusive */ int *growthp) /* OUT */ { avl64node_t *root = tree->avl_root; @@ -963,7 +963,7 @@ avl64_insert_grow( int growth) { avl64node_t *nnext; - __uint64_t start = AVL_START(tree, newnode); + uint64_t start = AVL_START(tree, newnode); if (growth == AVL_BACK) { @@ -1005,8 +1005,8 @@ avl64_insert( avl64node_t *newnode) { avl64node_t *np; - __uint64_t start = AVL_START(tree, newnode); - __uint64_t end = AVL_END(tree, newnode); + uint64_t start = AVL_START(tree, newnode); + uint64_t end = AVL_END(tree, newnode); int growth; ASSERT(newnode); @@ -1159,16 +1159,16 @@ avl64ops_t avl_debug_ops = { avl_debug_end, } -static __uint64_t +static uint64_t avl64_debug_start(avl64node_t *node) { - return (__uint64_t)(struct avl_debug_node *)node->avl_start; + return (uint64_t)(struct avl_debug_node *)node->avl_start; } -static __uint64_t +static uint64_t avl64_debug_end(avl64node_t *node) { - return (__uint64_t) + return (uint64_t) ((struct avl_debug_node *)node->avl_start + (struct avl_debug_node *)node->avl_size); } @@ -1304,7 +1304,7 @@ main() avl64node_t * avl64_findadjacent( avl64tree_desc_t *tree, - __uint64_t value, + uint64_t value, int dir) { avl64node_t *np = tree->avl_root; @@ -1378,8 +1378,8 @@ avl64_findadjacent( void avl64_findranges( avl64tree_desc_t *tree, - __uint64_t start, - __uint64_t end, + uint64_t start, + uint64_t end, avl64node_t **startp, avl64node_t **endp) { diff --git a/repair/avl64.h b/repair/avl64.h index fd19321..cd079a0 100644 --- a/repair/avl64.h +++ b/repair/avl64.h @@ -32,8 +32,8 @@ typedef struct avl64node { * avl-tree operations */ typedef struct avl64ops { - __uint64_t (*avl_start)(avl64node_t *); - __uint64_t (*avl_end)(avl64node_t *); + uint64_t (*avl_start)(avl64node_t *); + uint64_t (*avl_end)(avl64node_t *); } avl64ops_t; /* @@ -89,32 +89,32 @@ avl64_init_tree( avl64node_t * avl64_findrange( avl64tree_desc_t *tree, - __uint64_t value); + uint64_t value); avl64node_t * avl64_find( avl64tree_desc_t *tree, - __uint64_t value); + uint64_t value); avl64node_t * avl64_findanyrange( avl64tree_desc_t *tree, - __uint64_t start, - __uint64_t end, + uint64_t start, + uint64_t end, int checklen); avl64node_t * avl64_findadjacent( avl64tree_desc_t *tree, - __uint64_t value, + uint64_t value, int dir); void avl64_findranges( avl64tree_desc_t *tree, - __uint64_t start, - __uint64_t end, + uint64_t start, + uint64_t end, avl64node_t **startp, avl64node_t **endp); diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index 7dbaca6..ecfd0f1 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -826,7 +826,7 @@ next_readbuf: * we do now, this is where to start. */ if (is_used) { - __uint16_t di_mode; + uint16_t di_mode; if (is_inode_free(ino_rec, irec_offset)) { if (verbose || no_modify) { diff --git a/repair/dinode.c b/repair/dinode.c index cbd4305..6b0a355 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -742,7 +742,7 @@ _("%s fork in ino %" PRIu64 " claims dup extent, " case XR_E_FREE1: do_warn( _("%s fork in ino %" PRIu64 " claims free block %" PRIu64 "\n"), - forkname, ino, (__uint64_t) b); + forkname, ino, (uint64_t) b); /* fall through ... */ case XR_E_UNKNOWN: set_bmap_ext(agno, agbno, blen, XR_E_INUSE); @@ -888,7 +888,7 @@ process_btinode( int type, int *dirty, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, blkmap_t **blkmapp, int whichfork, int check_dups) @@ -904,7 +904,7 @@ process_btinode( int level; int numrecs; bmap_cursor_t cursor; - __uint64_t magic; + uint64_t magic; dib = (xfs_bmdr_block_t *)XFS_DFORK_PTR(dip, whichfork); lino = XFS_AGINO_TO_INO(mp, agno, ino); @@ -1063,7 +1063,7 @@ process_exinode( int type, int *dirty, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, blkmap_t **blkmapp, int whichfork, int check_dups) @@ -1165,14 +1165,14 @@ process_symlink_extlist(xfs_mount_t *mp, xfs_ino_t lino, xfs_dinode_t *dino) do_warn( _("mismatch between format (%d) and size (%" PRId64 ") in symlink ino %" PRIu64 "\n"), dino->di_format, - (__int64_t)be64_to_cpu(dino->di_size), lino); + (int64_t)be64_to_cpu(dino->di_size), lino); return 1; } if (dino->di_format == XFS_DINODE_FMT_LOCAL) { do_warn( _("mismatch between format (%d) and size (%" PRId64 ") in symlink inode %" PRIu64 "\n"), dino->di_format, - (__int64_t)be64_to_cpu(dino->di_size), lino); + (int64_t)be64_to_cpu(dino->di_size), lino); return 1; } @@ -1414,22 +1414,22 @@ _("inode %" PRIu64 " has bad inode type (IFMNT)\n"), lino); case XR_INO_CHRDEV: do_warn( _("size of character device inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, - (__int64_t)be64_to_cpu(dino->di_size)); + (int64_t)be64_to_cpu(dino->di_size)); break; case XR_INO_BLKDEV: do_warn( _("size of block device inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, - (__int64_t)be64_to_cpu(dino->di_size)); + (int64_t)be64_to_cpu(dino->di_size)); break; case XR_INO_SOCK: do_warn( _("size of socket inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, - (__int64_t)be64_to_cpu(dino->di_size)); + (int64_t)be64_to_cpu(dino->di_size)); break; case XR_INO_FIFO: do_warn( _("size of fifo inode %" PRIu64 " != 0 (%" PRId64 " bytes)\n"), lino, - (__int64_t)be64_to_cpu(dino->di_size)); + (int64_t)be64_to_cpu(dino->di_size)); break; default: do_warn(_("Internal error - process_misc_ino_types, " @@ -1703,12 +1703,12 @@ _("found inode %" PRIu64 " claiming to be a real-time file\n"), lino); break; case XR_INO_RTBITMAP: - if (size != (__int64_t)mp->m_sb.sb_rbmblocks * + if (size != (int64_t)mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize) { do_warn( _("realtime bitmap inode %" PRIu64 " has bad size %" PRId64 " (should be %" PRIu64 ")\n"), lino, size, - (__int64_t) mp->m_sb.sb_rbmblocks * + (int64_t) mp->m_sb.sb_rbmblocks * mp->m_sb.sb_blocksize); return 1; } @@ -1777,8 +1777,8 @@ static int process_inode_blocks_and_extents( xfs_dinode_t *dino, xfs_rfsblock_t nblocks, - __uint64_t nextents, - __uint64_t anextents, + uint64_t nextents, + uint64_t anextents, xfs_ino_t lino, int *dirty) { @@ -1868,7 +1868,7 @@ process_inode_data_fork( int type, int *dirty, xfs_rfsblock_t *totblocks, - __uint64_t *nextents, + uint64_t *nextents, blkmap_t **dblkmap, int check_dups) { @@ -1977,7 +1977,7 @@ process_inode_attr_fork( int type, int *dirty, xfs_rfsblock_t *atotblocks, - __uint64_t *anextents, + uint64_t *anextents, int check_dups, int extra_attr_check, int *retval) @@ -2188,8 +2188,8 @@ process_dinode_int(xfs_mount_t *mp, int di_mode; int type; int retval = 0; - __uint64_t nextents; - __uint64_t anextents; + uint64_t nextents; + uint64_t anextents; xfs_ino_t lino; const int is_free = 0; const int is_used = 1; @@ -2306,7 +2306,7 @@ _("inode identifier %llu mismatch on inode %" PRIu64 "\n"), if (!uncertain) do_warn( _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), - (__int64_t)be64_to_cpu(dino->di_size), + (int64_t)be64_to_cpu(dino->di_size), lino); if (verify_mode) return 1; diff --git a/repair/dinode.h b/repair/dinode.h index 5aebf5b..42a526b 100644 --- a/repair/dinode.h +++ b/repair/dinode.h @@ -46,8 +46,8 @@ process_bmbt_reclist(xfs_mount_t *mp, xfs_ino_t ino, xfs_rfsblock_t *tot, struct blkmap **blkmapp, - __uint64_t *first_key, - __uint64_t *last_key, + uint64_t *first_key, + uint64_t *last_key, int whichfork); int diff --git a/repair/dir2.c b/repair/dir2.c index 61912d1..476103e 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -160,7 +160,7 @@ process_sf_dir2( int bad_sfnamelen; int i; int i8; - __int64_t ino_dir_size; + int64_t ino_dir_size; int ino_off; ino_tree_node_t *irec_p; int junkit; diff --git a/repair/globals.h b/repair/globals.h index efd1d03..1989e28 100644 --- a/repair/globals.h +++ b/repair/globals.h @@ -140,7 +140,7 @@ EXTERN int inodes_per_cluster; EXTERN unsigned int glob_agcount; EXTERN int chunks_pblock; /* # of 64-ino chunks per allocation */ EXTERN int max_symlink_blocks; -EXTERN __int64_t fs_max_file_offset; +EXTERN int64_t fs_max_file_offset; /* realtime info */ @@ -160,16 +160,16 @@ EXTERN int full_ino_ex_data;/* /* superblock counters */ -EXTERN __uint64_t sb_icount; /* allocated (made) inodes */ -EXTERN __uint64_t sb_ifree; /* free inodes */ -EXTERN __uint64_t sb_fdblocks; /* free data blocks */ -EXTERN __uint64_t sb_frextents; /* free realtime extents */ +EXTERN uint64_t sb_icount; /* allocated (made) inodes */ +EXTERN uint64_t sb_ifree; /* free inodes */ +EXTERN uint64_t sb_fdblocks; /* free data blocks */ +EXTERN uint64_t sb_frextents; /* free realtime extents */ /* superblock geometry info */ EXTERN xfs_extlen_t sb_inoalignmt; -EXTERN __uint32_t sb_unit; -EXTERN __uint32_t sb_width; +EXTERN uint32_t sb_unit; +EXTERN uint32_t sb_width; struct aglock { pthread_mutex_t lock __attribute__((__aligned__(64))); @@ -177,7 +177,7 @@ struct aglock { EXTERN struct aglock *ag_locks; EXTERN int report_interval; -EXTERN __uint64_t *prog_rpt_done; +EXTERN uint64_t *prog_rpt_done; EXTERN int ag_stride; EXTERN int thread_count; diff --git a/repair/incore.c b/repair/incore.c index cb57316..a9191ae 100644 --- a/repair/incore.c +++ b/repair/incore.c @@ -179,7 +179,7 @@ get_bmap_ext( static uint64_t *rt_bmap; static size_t rt_bmap_size; -/* block records fit into __uint64_t's units */ +/* block records fit into uint64_t's units */ #define XR_BB_UNIT 64 /* number of bits/unit */ #define XR_BB 4 /* bits per block record */ #define XR_BB_NUM (XR_BB_UNIT/XR_BB) /* number of records per unit */ @@ -203,8 +203,8 @@ set_rtbmap( { *(rt_bmap + bno / XR_BB_NUM) = ((*(rt_bmap + bno / XR_BB_NUM) & - (~((__uint64_t) XR_BB_MASK << ((bno % XR_BB_NUM) * XR_BB)))) | - (((__uint64_t) state) << ((bno % XR_BB_NUM) * XR_BB))); + (~((uint64_t) XR_BB_MASK << ((bno % XR_BB_NUM) * XR_BB)))) | + (((uint64_t) state) << ((bno % XR_BB_NUM) * XR_BB))); } static void @@ -222,9 +222,9 @@ init_rt_bmap( return; rt_bmap_size = roundup(mp->m_sb.sb_rextents / (NBBY / XR_BB), - sizeof(__uint64_t)); + sizeof(uint64_t)); - rt_bmap = memalign(sizeof(__uint64_t), rt_bmap_size); + rt_bmap = memalign(sizeof(uint64_t), rt_bmap_size); if (!rt_bmap) { do_error( _("couldn't allocate realtime block map, size = %" PRIu64 "\n"), diff --git a/repair/incore.h b/repair/incore.h index c92475e..8415211 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -261,7 +261,7 @@ typedef xfs_ino_t parent_entry_t; struct nlink_ops; typedef struct parent_list { - __uint64_t pmask; + uint64_t pmask; parent_entry_t *pentries; #ifdef DEBUG short cnt; @@ -269,14 +269,14 @@ typedef struct parent_list { } parent_list_t; union ino_nlink { - __uint8_t *un8; - __uint16_t *un16; - __uint32_t *un32; + uint8_t *un8; + uint16_t *un16; + uint32_t *un32; }; typedef struct ino_ex_data { - __uint64_t ino_reached; /* bit == 1 if reached */ - __uint64_t ino_processed; /* reference checked bit mask */ + uint64_t ino_reached; /* bit == 1 if reached */ + uint64_t ino_processed; /* reference checked bit mask */ parent_list_t *parents; union ino_nlink counted_nlinks;/* counted nlinks in P6 */ } ino_ex_data_t; @@ -285,20 +285,20 @@ typedef struct ino_tree_node { avlnode_t avl_node; xfs_agino_t ino_startnum; /* starting inode # */ xfs_inofree_t ir_free; /* inode free bit mask */ - __uint64_t ir_sparse; /* sparse inode bitmask */ - __uint64_t ino_confirmed; /* confirmed bitmask */ - __uint64_t ino_isa_dir; /* bit == 1 if a directory */ - __uint8_t nlink_size; + uint64_t ir_sparse; /* sparse inode bitmask */ + uint64_t ino_confirmed; /* confirmed bitmask */ + uint64_t ino_isa_dir; /* bit == 1 if a directory */ + uint8_t nlink_size; union ino_nlink disk_nlinks; /* on-disk nlinks, set in P3 */ union { ino_ex_data_t *ex_data; /* phases 6,7 */ parent_list_t *plist; /* phases 2-5 */ } ino_un; - __uint8_t *ftypes; /* phases 3,6 */ + uint8_t *ftypes; /* phases 3,6 */ } ino_tree_node_t; -#define INOS_PER_IREC (sizeof(__uint64_t) * NBBY) -#define IREC_MASK(i) ((__uint64_t)1 << (i)) +#define INOS_PER_IREC (sizeof(uint64_t) * NBBY) +#define IREC_MASK(i) ((uint64_t)1 << (i)) void add_ino_ex_data(xfs_mount_t *mp); @@ -509,10 +509,10 @@ static inline bool is_inode_sparse(struct ino_tree_node *irec, int offset) */ void add_inode_ref(struct ino_tree_node *irec, int offset); void drop_inode_ref(struct ino_tree_node *irec, int offset); -__uint32_t num_inode_references(struct ino_tree_node *irec, int offset); +uint32_t num_inode_references(struct ino_tree_node *irec, int offset); -void set_inode_disk_nlinks(struct ino_tree_node *irec, int offset, __uint32_t nlinks); -__uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int offset); +void set_inode_disk_nlinks(struct ino_tree_node *irec, int offset, uint32_t nlinks); +uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int offset); static inline int is_inode_reached(struct ino_tree_node *irec, int offset) { @@ -533,13 +533,13 @@ static inline void add_inode_reached(struct ino_tree_node *irec, int offset) static inline void set_inode_ftype(struct ino_tree_node *irec, int ino_offset, - __uint8_t ftype) + uint8_t ftype) { if (irec->ftypes) irec->ftypes[ino_offset] = ftype; } -static inline __uint8_t +static inline uint8_t get_inode_ftype( struct ino_tree_node *irec, int ino_offset) @@ -572,11 +572,11 @@ typedef struct bm_level_state { xfs_fsblock_t fsbno; xfs_fsblock_t left_fsbno; xfs_fsblock_t right_fsbno; - __uint64_t first_key; - __uint64_t last_key; + uint64_t first_key; + uint64_t last_key; /* int level; - __uint64_t prev_last_key; + uint64_t prev_last_key; xfs_buf_t *bp; xfs_bmbt_block_t *block; */ diff --git a/repair/incore_ext.c b/repair/incore_ext.c index 7e6786c..0a8138a 100644 --- a/repair/incore_ext.c +++ b/repair/incore_ext.c @@ -721,13 +721,13 @@ search_rt_dup_extent(xfs_mount_t *mp, xfs_rtblock_t bno) return(ret); } -static __uint64_t +static uint64_t avl64_rt_ext_start(avl64node_t *node) { return(((rt_extent_tree_node_t *) node)->rt_startblock); } -static __uint64_t +static uint64_t avl64_ext_end(avl64node_t *node) { return(((rt_extent_tree_node_t *) node)->rt_startblock + @@ -834,7 +834,7 @@ count_extents(xfs_agnumber_t agno, avltree_desc_t *tree, int whichtree) int count_bno_extents_blocks(xfs_agnumber_t agno, uint *numblocks) { - __uint64_t nblocks; + uint64_t nblocks; extent_tree_node_t *node; int i = 0; diff --git a/repair/incore_ino.c b/repair/incore_ino.c index 1898257..ba612bd 100644 --- a/repair/incore_ino.c +++ b/repair/incore_ino.c @@ -38,7 +38,7 @@ static avltree_desc_t **inode_uncertain_tree_ptrs; /* memory optimised nlink counting for all inodes */ static void * -alloc_nlink_array(__uint8_t nlink_size) +alloc_nlink_array(uint8_t nlink_size) { void *ptr; @@ -51,10 +51,10 @@ alloc_nlink_array(__uint8_t nlink_size) static void nlink_grow_8_to_16(ino_tree_node_t *irec) { - __uint16_t *new_nlinks; + uint16_t *new_nlinks; int i; - irec->nlink_size = sizeof(__uint16_t); + irec->nlink_size = sizeof(uint16_t); new_nlinks = alloc_nlink_array(irec->nlink_size); for (i = 0; i < XFS_INODES_PER_CHUNK; i++) @@ -76,10 +76,10 @@ nlink_grow_8_to_16(ino_tree_node_t *irec) static void nlink_grow_16_to_32(ino_tree_node_t *irec) { - __uint32_t *new_nlinks; + uint32_t *new_nlinks; int i; - irec->nlink_size = sizeof(__uint32_t); + irec->nlink_size = sizeof(uint32_t); new_nlinks = alloc_nlink_array(irec->nlink_size); for (i = 0; i < XFS_INODES_PER_CHUNK; i++) @@ -104,21 +104,21 @@ void add_inode_ref(struct ino_tree_node *irec, int ino_offset) ASSERT(irec->ino_un.ex_data != NULL); switch (irec->nlink_size) { - case sizeof(__uint8_t): + case sizeof(uint8_t): if (irec->ino_un.ex_data->counted_nlinks.un8[ino_offset] < 0xff) { irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]++; break; } nlink_grow_8_to_16(irec); /*FALLTHRU*/ - case sizeof(__uint16_t): + case sizeof(uint16_t): if (irec->ino_un.ex_data->counted_nlinks.un16[ino_offset] < 0xffff) { irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]++; break; } nlink_grow_16_to_32(irec); /*FALLTHRU*/ - case sizeof(__uint32_t): + case sizeof(uint32_t): irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]++; break; default: @@ -128,20 +128,20 @@ void add_inode_ref(struct ino_tree_node *irec, int ino_offset) void drop_inode_ref(struct ino_tree_node *irec, int ino_offset) { - __uint32_t refs = 0; + uint32_t refs = 0; ASSERT(irec->ino_un.ex_data != NULL); switch (irec->nlink_size) { - case sizeof(__uint8_t): + case sizeof(uint8_t): ASSERT(irec->ino_un.ex_data->counted_nlinks.un8[ino_offset] > 0); refs = --irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]; break; - case sizeof(__uint16_t): + case sizeof(uint16_t): ASSERT(irec->ino_un.ex_data->counted_nlinks.un16[ino_offset] > 0); refs = --irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]; break; - case sizeof(__uint32_t): + case sizeof(uint32_t): ASSERT(irec->ino_un.ex_data->counted_nlinks.un32[ino_offset] > 0); refs = --irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]; break; @@ -153,16 +153,16 @@ void drop_inode_ref(struct ino_tree_node *irec, int ino_offset) irec->ino_un.ex_data->ino_reached &= ~IREC_MASK(ino_offset); } -__uint32_t num_inode_references(struct ino_tree_node *irec, int ino_offset) +uint32_t num_inode_references(struct ino_tree_node *irec, int ino_offset) { ASSERT(irec->ino_un.ex_data != NULL); switch (irec->nlink_size) { - case sizeof(__uint8_t): + case sizeof(uint8_t): return irec->ino_un.ex_data->counted_nlinks.un8[ino_offset]; - case sizeof(__uint16_t): + case sizeof(uint16_t): return irec->ino_un.ex_data->counted_nlinks.un16[ino_offset]; - case sizeof(__uint32_t): + case sizeof(uint32_t): return irec->ino_un.ex_data->counted_nlinks.un32[ino_offset]; default: ASSERT(0); @@ -171,24 +171,24 @@ __uint32_t num_inode_references(struct ino_tree_node *irec, int ino_offset) } void set_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset, - __uint32_t nlinks) + uint32_t nlinks) { switch (irec->nlink_size) { - case sizeof(__uint8_t): + case sizeof(uint8_t): if (nlinks < 0xff) { irec->disk_nlinks.un8[ino_offset] = nlinks; break; } nlink_grow_8_to_16(irec); /*FALLTHRU*/ - case sizeof(__uint16_t): + case sizeof(uint16_t): if (nlinks < 0xffff) { irec->disk_nlinks.un16[ino_offset] = nlinks; break; } nlink_grow_16_to_32(irec); /*FALLTHRU*/ - case sizeof(__uint32_t): + case sizeof(uint32_t): irec->disk_nlinks.un32[ino_offset] = nlinks; break; default: @@ -196,14 +196,14 @@ void set_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset, } } -__uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset) +uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset) { switch (irec->nlink_size) { - case sizeof(__uint8_t): + case sizeof(uint8_t): return irec->disk_nlinks.un8[ino_offset]; - case sizeof(__uint16_t): + case sizeof(uint16_t): return irec->disk_nlinks.un16[ino_offset]; - case sizeof(__uint32_t): + case sizeof(uint32_t): return irec->disk_nlinks.un32[ino_offset]; default: ASSERT(0); @@ -211,11 +211,11 @@ __uint32_t get_inode_disk_nlinks(struct ino_tree_node *irec, int ino_offset) return 0; } -static __uint8_t * +static uint8_t * alloc_ftypes_array( struct xfs_mount *mp) { - __uint8_t *ptr; + uint8_t *ptr; if (!xfs_sb_version_hasftype(&mp->m_sb)) return NULL; @@ -260,23 +260,23 @@ alloc_ino_node( irec->ir_free = (xfs_inofree_t) - 1; irec->ir_sparse = 0; irec->ino_un.ex_data = NULL; - irec->nlink_size = sizeof(__uint8_t); + irec->nlink_size = sizeof(uint8_t); irec->disk_nlinks.un8 = alloc_nlink_array(irec->nlink_size); irec->ftypes = alloc_ftypes_array(mp); return irec; } static void -free_nlink_array(union ino_nlink nlinks, __uint8_t nlink_size) +free_nlink_array(union ino_nlink nlinks, uint8_t nlink_size) { switch (nlink_size) { - case sizeof(__uint8_t): + case sizeof(uint8_t): free(nlinks.un8); break; - case sizeof(__uint16_t): + case sizeof(uint16_t): free(nlinks.un16); break; - case sizeof(__uint32_t): + case sizeof(uint32_t): free(nlinks.un32); break; default: @@ -607,7 +607,7 @@ set_inode_parent( int i; int cnt; int target; - __uint64_t bitmask; + uint64_t bitmask; parent_entry_t *tmp; if (full_ino_ex_data) @@ -697,7 +697,7 @@ set_inode_parent( xfs_ino_t get_inode_parent(ino_tree_node_t *irec, int offset) { - __uint64_t bitmask; + uint64_t bitmask; parent_list_t *ptbl; int i; int target; @@ -738,15 +738,15 @@ alloc_ex_data(ino_tree_node_t *irec) irec->ino_un.ex_data->parents = ptbl; switch (irec->nlink_size) { - case sizeof(__uint8_t): + case sizeof(uint8_t): irec->ino_un.ex_data->counted_nlinks.un8 = alloc_nlink_array(irec->nlink_size); break; - case sizeof(__uint16_t): + case sizeof(uint16_t): irec->ino_un.ex_data->counted_nlinks.un16 = alloc_nlink_array(irec->nlink_size); break; - case sizeof(__uint32_t): + case sizeof(uint32_t): irec->ino_un.ex_data->counted_nlinks.un32 = alloc_nlink_array(irec->nlink_size); break; diff --git a/repair/phase2.c b/repair/phase2.c index e21ffa6..a2dfa0b 100644 --- a/repair/phase2.c +++ b/repair/phase2.c @@ -173,7 +173,7 @@ phase2( bad_ino_btree = 0; - set_progress_msg(PROG_FMT_SCAN_AG, (__uint64_t) glob_agcount); + set_progress_msg(PROG_FMT_SCAN_AG, (uint64_t) glob_agcount); scan_ags(mp, scan_threads); diff --git a/repair/phase3.c b/repair/phase3.c index 0890a27..17b1c28 100644 --- a/repair/phase3.c +++ b/repair/phase3.c @@ -122,7 +122,7 @@ phase3( else do_log(_(" - scan (but don't clear) agi unlinked lists...\n")); - set_progress_msg(PROG_FMT_AGI_UNLINKED, (__uint64_t) glob_agcount); + set_progress_msg(PROG_FMT_AGI_UNLINKED, (uint64_t) glob_agcount); /* first clear the agi unlinked AGI list */ if (!no_modify) { @@ -142,7 +142,7 @@ phase3( do_log(_( " - process known inodes and perform inode discovery...\n")); - set_progress_msg(PROG_FMT_PROCESS_INO, (__uint64_t) mp->m_sb.sb_icount); + set_progress_msg(PROG_FMT_PROCESS_INO, (uint64_t) mp->m_sb.sb_icount); process_ags(mp); @@ -152,7 +152,7 @@ phase3( * process newly discovered inode chunks */ do_log(_(" - process newly discovered inodes...\n")); - set_progress_msg(PROG_FMT_NEW_INODES, (__uint64_t) glob_agcount); + set_progress_msg(PROG_FMT_NEW_INODES, (uint64_t) glob_agcount); counts = calloc(sizeof(*counts), mp->m_sb.sb_agcount); if (!counts) { diff --git a/repair/phase4.c b/repair/phase4.c index 1a7d7b5..90386c2 100644 --- a/repair/phase4.c +++ b/repair/phase4.c @@ -175,7 +175,7 @@ phase4(xfs_mount_t *mp) do_log(_("Phase 4 - check for duplicate blocks...\n")); do_log(_(" - setting up duplicate extent list...\n")); - set_progress_msg(PROG_FMT_DUP_EXTENT, (__uint64_t) glob_agcount); + set_progress_msg(PROG_FMT_DUP_EXTENT, (uint64_t) glob_agcount); irec = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, mp->m_sb.sb_rootino), XFS_INO_TO_AGINO(mp, mp->m_sb.sb_rootino)); @@ -289,7 +289,7 @@ phase4(xfs_mount_t *mp) reset_bmaps(mp); do_log(_(" - check for inodes claiming duplicate blocks...\n")); - set_progress_msg(PROG_FMT_DUP_BLOCKS, (__uint64_t) mp->m_sb.sb_icount); + set_progress_msg(PROG_FMT_DUP_BLOCKS, (uint64_t) mp->m_sb.sb_icount); /* * ok, now process the inodes -- signal 2-pass check per inode. diff --git a/repair/phase5.c b/repair/phase5.c index 5d48848..1b7ed6d 100644 --- a/repair/phase5.c +++ b/repair/phase5.c @@ -83,9 +83,9 @@ struct agi_stat { xfs_agino_t freecount; }; -static __uint64_t *sb_icount_ag; /* allocated inodes per ag */ -static __uint64_t *sb_ifree_ag; /* free inodes per ag */ -static __uint64_t *sb_fdblocks_ag; /* free data blocks per ag */ +static uint64_t *sb_icount_ag; /* allocated inodes per ag */ +static uint64_t *sb_ifree_ag; /* free inodes per ag */ +static uint64_t *sb_fdblocks_ag; /* free data blocks per ag */ static int mk_incore_fstree(xfs_mount_t *mp, xfs_agnumber_t agno) @@ -618,14 +618,14 @@ calculate_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, static void prop_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, xfs_agblock_t startblock, - xfs_extlen_t blockcount, int level, __uint32_t magic) + xfs_extlen_t blockcount, int level, uint32_t magic) { struct xfs_btree_block *bt_hdr; xfs_alloc_key_t *bt_key; xfs_alloc_ptr_t *bt_ptr; xfs_agblock_t agbno; bt_stat_level_t *lptr; - __uint32_t crc_magic; + uint32_t crc_magic; if (magic == XFS_ABTB_MAGIC) crc_magic = XFS_ABTB_CRC_MAGIC; @@ -720,7 +720,7 @@ prop_freespace_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, */ static xfs_extlen_t build_freespace_tree(xfs_mount_t *mp, xfs_agnumber_t agno, - bt_status_t *btree_curs, __uint32_t magic) + bt_status_t *btree_curs, uint32_t magic) { xfs_agnumber_t i; xfs_agblock_t j; @@ -731,7 +731,7 @@ build_freespace_tree(xfs_mount_t *mp, xfs_agnumber_t agno, extent_tree_node_t *ext_ptr; bt_stat_level_t *lptr; xfs_extlen_t freeblks; - __uint32_t crc_magic; + uint32_t crc_magic; #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "in build_freespace_tree, agno = %d\n", agno); @@ -895,10 +895,10 @@ build_freespace_tree(xfs_mount_t *mp, xfs_agnumber_t agno, */ static void init_ino_cursor(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, - __uint64_t *num_inos, __uint64_t *num_free_inos, int finobt) + uint64_t *num_inos, uint64_t *num_free_inos, int finobt) { - __uint64_t ninos; - __uint64_t nfinos; + uint64_t ninos; + uint64_t nfinos; int rec_nfinos; int rec_ninos; ino_tree_node_t *ino_rec; @@ -1144,7 +1144,7 @@ build_agi(xfs_mount_t *mp, xfs_agnumber_t agno, bt_status_t *btree_curs, */ static void build_ino_tree(xfs_mount_t *mp, xfs_agnumber_t agno, - bt_status_t *btree_curs, __uint32_t magic, + bt_status_t *btree_curs, uint32_t magic, struct agi_stat *agi_stat, int finobt) { xfs_agnumber_t i; @@ -1573,10 +1573,10 @@ phase5_func( xfs_mount_t *mp, xfs_agnumber_t agno) { - __uint64_t num_inos; - __uint64_t num_free_inos; - __uint64_t finobt_num_inos; - __uint64_t finobt_num_free_inos; + uint64_t num_inos; + uint64_t num_free_inos; + uint64_t finobt_num_inos; + uint64_t finobt_num_free_inos; bt_status_t bno_btree_curs; bt_status_t bcnt_btree_curs; bt_status_t ino_btree_curs; @@ -1588,7 +1588,7 @@ phase5_func( xfs_extlen_t freeblks2; #endif xfs_agblock_t num_extents; - __uint32_t magic; + uint32_t magic; struct agi_stat agi_stat = {0,}; if (verbose) @@ -1772,7 +1772,7 @@ phase5(xfs_mount_t *mp) xfs_agnumber_t agno; do_log(_("Phase 5 - rebuild AG headers and trees...\n")); - set_progress_msg(PROG_FMT_REBUILD_AG, (__uint64_t )glob_agcount); + set_progress_msg(PROG_FMT_REBUILD_AG, (uint64_t )glob_agcount); #ifdef XR_BLD_FREE_TRACE fprintf(stderr, "inobt level 1, maxrec = %d, minrec = %d\n", @@ -1798,15 +1798,15 @@ phase5(xfs_mount_t *mp) keep_fsinos(mp); /* allocate per ag counters */ - sb_icount_ag = calloc(mp->m_sb.sb_agcount, sizeof(__uint64_t)); + sb_icount_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t)); if (sb_icount_ag == NULL) do_error(_("cannot alloc sb_icount_ag buffers\n")); - sb_ifree_ag = calloc(mp->m_sb.sb_agcount, sizeof(__uint64_t)); + sb_ifree_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t)); if (sb_ifree_ag == NULL) do_error(_("cannot alloc sb_ifree_ag buffers\n")); - sb_fdblocks_ag = calloc(mp->m_sb.sb_agcount, sizeof(__uint64_t)); + sb_fdblocks_ag = calloc(mp->m_sb.sb_agcount, sizeof(uint64_t)); if (sb_fdblocks_ag == NULL) do_error(_("cannot alloc sb_fdblocks_ag buffers\n")); diff --git a/repair/phase6.c b/repair/phase6.c index 0a71164..54b65c0 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -82,7 +82,7 @@ typedef struct dir_hash_ent { struct dir_hash_ent *nextbyhash; /* next in name bucket */ struct dir_hash_ent *nextbyorder; /* next in order added */ xfs_dahash_t hashval; /* hash value of name */ - __uint32_t address; /* offset of data entry */ + uint32_t address; /* offset of data entry */ xfs_ino_t inum; /* inode num of entry */ short junkit; /* name starts with / */ short seen; /* have seen leaf entry */ @@ -170,11 +170,11 @@ static int dir_hash_add( xfs_mount_t *mp, dir_hash_tab_t *hashtab, - __uint32_t addr, + uint32_t addr, xfs_ino_t inum, int namelen, unsigned char *name, - __uint8_t ftype) + uint8_t ftype) { xfs_dahash_t hash = 0; int byaddr; @@ -357,7 +357,7 @@ static void dir_hash_update_ftype( dir_hash_tab_t *hashtab, xfs_dir2_dataptr_t addr, - __uint8_t ftype) + uint8_t ftype) { int i; dir_hash_ent_t *p; @@ -1814,8 +1814,8 @@ longform_dir2_entry_check_data( /* validate ftype field if supported */ if (xfs_sb_version_hasftype(&mp->m_sb)) { - __uint8_t dir_ftype; - __uint8_t ino_ftype; + uint8_t dir_ftype; + uint8_t ino_ftype; dir_ftype = M_DIROPS(mp)->data_get_ftype(dep); ino_ftype = get_inode_ftype(irec, ino_offset); @@ -2725,8 +2725,8 @@ _("entry \"%s\" (ino %" PRIu64 ") in dir %" PRIu64 " is a duplicate name"), /* validate ftype field if supported */ if (xfs_sb_version_hasftype(&mp->m_sb)) { - __uint8_t dir_ftype; - __uint8_t ino_ftype; + uint8_t dir_ftype; + uint8_t ino_ftype; dir_ftype = M_DIROPS(mp)->sf_get_ftype(sfep); ino_ftype = get_inode_ftype(irec, ino_offset); diff --git a/repair/phase7.c b/repair/phase7.c index 3e234b9..8f1ed6c 100644 --- a/repair/phase7.c +++ b/repair/phase7.c @@ -32,7 +32,7 @@ static void update_inode_nlinks( xfs_mount_t *mp, xfs_ino_t ino, - __uint32_t nlinks) + uint32_t nlinks) { xfs_trans_t *tp; xfs_inode_t *ip; @@ -106,7 +106,7 @@ do_link_updates( { ino_tree_node_t *irec; int j; - __uint32_t nrefs; + uint32_t nrefs; for (irec = findfirst_inode_rec(agno); irec; irec = next_ino_rec(irec)) { @@ -145,7 +145,7 @@ phase7( else do_log(_("Phase 7 - verify link counts...\n")); - set_progress_msg(PROGRESS_FMT_CORR_LINK, (__uint64_t) glob_agcount); + set_progress_msg(PROGRESS_FMT_CORR_LINK, (uint64_t) glob_agcount); create_work_queue(&wq, mp, scan_threads); diff --git a/repair/progress.c b/repair/progress.c index 2a09b23..3a2e9a2 100644 --- a/repair/progress.c +++ b/repair/progress.c @@ -85,8 +85,8 @@ pthread_t report_thread; typedef struct msg_block_s { pthread_mutex_t mutex; progress_rpt_t *format; - __uint64_t *done; - __uint64_t *total; + uint64_t *done; + uint64_t *total; int count; int interval; } msg_block_t; @@ -96,14 +96,14 @@ typedef struct phase_times_s { time_t start; time_t end; time_t duration; - __uint64_t item_counts[4]; + uint64_t item_counts[4]; } phase_times_t; static phase_times_t phase_times[8]; static void *progress_rpt_thread(void *); static int current_phase; static int running; -static __uint64_t prog_rpt_total; +static uint64_t prog_rpt_total; void init_progress_rpt (void) @@ -113,11 +113,11 @@ init_progress_rpt (void) * allocate the done vector */ - if ((prog_rpt_done = (__uint64_t *) - malloc(sizeof(__uint64_t)*glob_agcount)) == NULL ) { + if ((prog_rpt_done = (uint64_t *) + malloc(sizeof(uint64_t)*glob_agcount)) == NULL ) { do_error(_("cannot malloc pointer to done vector\n")); } - bzero(prog_rpt_done, sizeof(__uint64_t)*glob_agcount); + bzero(prog_rpt_done, sizeof(uint64_t)*glob_agcount); /* * Setup comm block, start the thread @@ -165,10 +165,10 @@ progress_rpt_thread (void *p) timer_t timerid; struct itimerspec timespec; char *msgbuf; - __uint64_t *donep; - __uint64_t sum; + uint64_t *donep; + uint64_t sum; msg_block_t *msgp = (msg_block_t *)p; - __uint64_t percent; + uint64_t percent; /* It's possible to get here very early w/ no progress msg set */ if (!msgp->format) @@ -286,7 +286,7 @@ progress_rpt_thread (void *p) } int -set_progress_msg (int report, __uint64_t total) +set_progress_msg (int report, uint64_t total) { if (!ag_stride) @@ -300,7 +300,7 @@ set_progress_msg (int report, __uint64_t total) /* reset all the accumulative totals */ if (prog_rpt_done) - bzero(prog_rpt_done, sizeof(__uint64_t)*glob_agcount); + bzero(prog_rpt_done, sizeof(uint64_t)*glob_agcount); if (pthread_mutex_unlock(&global_msgs.mutex)) do_error(_("set_progress_msg: cannot unlock progress mutex\n")); @@ -308,14 +308,14 @@ set_progress_msg (int report, __uint64_t total) return (0); } -__uint64_t +uint64_t print_final_rpt(void) { int i; struct tm *tmp; time_t now; - __uint64_t *donep; - __uint64_t sum; + uint64_t *donep; + uint64_t sum; msg_block_t *msgp = &global_msgs; char msgbuf[DURATION_BUF_SIZE]; diff --git a/repair/progress.h b/repair/progress.h index 33db834..5152648 100644 --- a/repair/progress.h +++ b/repair/progress.h @@ -32,8 +32,8 @@ extern void init_progress_rpt(void); extern void stop_progress_rpt(void); extern void summary_report(void); -extern int set_progress_msg(int report, __uint64_t total); -extern __uint64_t print_final_rpt(void); +extern int set_progress_msg(int report, uint64_t total); +extern uint64_t print_final_rpt(void); extern char *timestamp(int end, int phase, char *buf); extern char *duration(int val, char *buf); extern int do_parallel; diff --git a/repair/sb.c b/repair/sb.c index 4eef14a..ea89ca9 100644 --- a/repair/sb.c +++ b/repair/sb.c @@ -41,7 +41,7 @@ copy_sb(xfs_sb_t *source, xfs_sb_t *dest) xfs_ino_t uquotino; xfs_ino_t gquotino; xfs_ino_t pquotino; - __uint16_t versionnum; + uint16_t versionnum; rootino = dest->sb_rootino; rbmino = dest->sb_rbmino; @@ -264,7 +264,7 @@ sb_validate_ino_align(struct xfs_sb *sb) int verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb) { - __uint32_t bsize; + uint32_t bsize; int i; /* check magic number and version number */ @@ -329,13 +329,13 @@ verify_sb(char *sb_buf, xfs_sb_t *sb, int is_primary_sb) if (sb->sb_dblocks == 0 || sb->sb_dblocks > - ((__uint64_t)sb->sb_agcount * sb->sb_agblocks) || + ((uint64_t)sb->sb_agcount * sb->sb_agblocks) || sb->sb_dblocks < - ((__uint64_t)(sb->sb_agcount - 1) * sb->sb_agblocks + ((uint64_t)(sb->sb_agcount - 1) * sb->sb_agblocks + XFS_MIN_AG_BLOCKS)) return(XR_BAD_FS_SIZE_DATA); - if (sb->sb_agblklog != (__uint8_t)libxfs_log2_roundup(sb->sb_agblocks)) + if (sb->sb_agblklog != (uint8_t)libxfs_log2_roundup(sb->sb_agblocks)) return(XR_BAD_FS_SIZE_DATA); if (sb->sb_inodesize < XFS_DINODE_MIN_SIZE || diff --git a/repair/scan.c b/repair/scan.c index 964ff06..5a79325 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -40,12 +40,12 @@ struct aghdr_cnts { xfs_agnumber_t agno; xfs_extlen_t agffreeblks; xfs_extlen_t agflongest; - __uint64_t agfbtreeblks; - __uint32_t agicount; - __uint32_t agifreecount; - __uint64_t fdblocks; - __uint64_t ifreecount; - __uint32_t fibtfreecount; + uint64_t agfbtreeblks; + uint32_t agicount; + uint32_t agifreecount; + uint64_t fdblocks; + uint64_t ifreecount; + uint32_t fibtfreecount; }; void @@ -67,10 +67,10 @@ scan_sbtree( xfs_agnumber_t agno, int suspect, int isroot, - __uint32_t magic, + uint32_t magic, void *priv), int isroot, - __uint32_t magic, + uint32_t magic, void *priv, const struct xfs_buf_ops *ops) { @@ -107,23 +107,23 @@ scan_lbtree( xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, - __uint64_t magic), + uint64_t magic), int type, int whichfork, xfs_ino_t ino, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, - __uint64_t magic, + uint64_t magic, const struct xfs_buf_ops *ops) { xfs_buf_t *bp; @@ -176,13 +176,13 @@ scan_bmapbt( xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, blkmap_t **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, - __uint64_t magic) + uint64_t magic) { int i; int err; @@ -528,7 +528,7 @@ scan_allocbt( xfs_agnumber_t agno, int suspect, int isroot, - __uint32_t magic, + uint32_t magic, void *priv) { struct aghdr_cnts *agcnts = priv; @@ -1243,7 +1243,7 @@ scan_inobt( xfs_agnumber_t agno, int suspect, int isroot, - __uint32_t magic, + uint32_t magic, void *priv) { struct aghdr_cnts *agcnts = priv; @@ -1479,7 +1479,7 @@ validate_agf( struct aghdr_cnts *agcnts) { xfs_agblock_t bno; - __uint32_t magic; + uint32_t magic; bno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]); if (bno != 0 && verify_agbno(mp, agno, bno)) { @@ -1530,7 +1530,7 @@ validate_agi( { xfs_agblock_t bno; int i; - __uint32_t magic; + uint32_t magic; bno = be32_to_cpu(agi->agi_root); if (bno != 0 && verify_agbno(mp, agno, bno)) { @@ -1756,9 +1756,9 @@ scan_ags( int scan_threads) { struct aghdr_cnts *agcnts; - __uint64_t fdblocks = 0; - __uint64_t icount = 0; - __uint64_t ifreecount = 0; + uint64_t fdblocks = 0; + uint64_t icount = 0; + uint64_t ifreecount = 0; xfs_agnumber_t i; work_queue_t wq; diff --git a/repair/scan.h b/repair/scan.h index ea8c0bf..9bbe1e6 100644 --- a/repair/scan.h +++ b/repair/scan.h @@ -30,23 +30,23 @@ int scan_lbtree( xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, - __uint64_t magic), + uint64_t magic), int type, int whichfork, xfs_ino_t ino, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, - __uint64_t magic, + uint64_t magic, const struct xfs_buf_ops *ops); int scan_bmapbt( @@ -57,13 +57,13 @@ int scan_bmapbt( xfs_fsblock_t bno, xfs_ino_t ino, xfs_rfsblock_t *tot, - __uint64_t *nex, + uint64_t *nex, struct blkmap **blkmapp, bmap_cursor_t *bm_cursor, int isroot, int check_dups, int *dirty, - __uint64_t magic); + uint64_t magic); void scan_ags( -- 2.7.3 From felix.janda@posteo.de Sat Jun 18 10:40:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8D0A87CA0 for ; Sat, 18 Jun 2016 10:40:18 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 22625AC002 for ; Sat, 18 Jun 2016 08:40:17 -0700 (PDT) X-ASG-Debug-ID: 1466264410-04bdf01e17e0ee0001-NocioJ Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by cuda.sgi.com with ESMTP id I6ccsaE77HDA0CGt (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 08:40:12 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout01.posteo.de[185.67.36.65] X-Barracuda-Apparent-Source-IP: 185.67.36.65 Received: from dovecot03.posteo.de (dovecot03.posteo.de [172.16.0.13]) by mout01.posteo.de (Postfix) with ESMTPS id A41C420B45 for ; Sat, 18 Jun 2016 17:40:10 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3rX1XV3S73z5vN8 for ; Sat, 18 Jun 2016 17:40:10 +0200 (CEST) Date: Sat, 18 Jun 2016 17:38:55 +0200 From: Felix Janda To: xfs@oss.sgi.com Subject: Re: [PATCH 2/4] Simplify workaround for old glibc getsubopt() Message-ID: <20160618153855.GA2091@nyan> X-ASG-Orig-Subj: Re: [PATCH 2/4] Simplify workaround for old glibc getsubopt() References: <20160618145253.GB17768@nyan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160618145253.GB17768@nyan> User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout01.posteo.de[185.67.36.65] X-Barracuda-Start-Time: 1466264411 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 400 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30547 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- Please ignore this patch and the next: The installed header linux.h should not redefine the standard function getsubopt(). Instead might it be possible to remove the workaround all together? glibc-2.2 (first version which does not need the workaround) was released in 2000 and even with older glibc when removing the workaround, it should only make the compiler emit a warning. Felix From darrick.wong@oracle.com Sat Jun 18 13:01:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B8DCC7CA0 for ; Sat, 18 Jun 2016 13:01:46 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 457D4AC001 for ; Sat, 18 Jun 2016 11:01:43 -0700 (PDT) X-ASG-Debug-ID: 1466272900-04bdf01e10e4db0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 0FBnrfkis1CD7s7D (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 11:01:40 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5II1bK7013911 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 18 Jun 2016 18:01:37 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5II1bb3028261 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 18 Jun 2016 18:01:37 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5II1YEb016459; Sat, 18 Jun 2016 18:01:35 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sat, 18 Jun 2016 11:01:34 -0700 Date: Sat, 18 Jun 2016 11:01:33 -0700 From: "Darrick J. Wong" To: Brian Foster Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 003/119] xfs: check offsets of variable length structures Message-ID: <20160618180133.GB5046@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 003/119] xfs: check offsets of variable length structures References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612629195.12839.14090954204243398929.stgit@birch.djwong.org> <20160617173426.GA46309@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617173426.GA46309@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466272900 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4511 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30549 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 17, 2016 at 01:34:27PM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:18:12PM -0700, Darrick J. Wong wrote: > > Some of the directory/attr structures contain variable-length objects, > > so the enclosing structure doesn't have a meaningful fixed size at > > compile time. We can check the offsets of the members before the > > variable-length member, so do those. > > > > Signed-off-by: Darrick J. Wong > > --- > > I'm missing why this is necessary. Is the intent still to catch > alignment and/or padding issues? If so, isn't the size check sufficient, > regardless of trailing variable size fields? > > Perhaps the goal here is to reduce the scope of checking from where it > isn't needed..? For example, xfs_dir2_data_unused_t looks like it has a > field where the offset in the structure is irrelevant, so that's a > possible false positive if that changes down the road. On the flip side, > that doesn't appear to be the case for other structures such as > xfs_attr_leaf_name_[local|remote]_t. ISTR making this change to work around behavioral variances in how much padding gcc adds to structures across its various targets. The macros that go along with the variable sized structures work fine, but testing the sizeof() doesn't work reliably. --D > > Brian > > > fs/xfs/xfs_ondisk.h | 25 +++++++++++++++++++++++-- > > 1 file changed, 23 insertions(+), 2 deletions(-) > > > > > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h > > index 184c44e..0272301 100644 > > --- a/fs/xfs/xfs_ondisk.h > > +++ b/fs/xfs/xfs_ondisk.h > > @@ -22,6 +22,11 @@ > > BUILD_BUG_ON_MSG(sizeof(structname) != (size), "XFS: sizeof(" \ > > #structname ") is wrong, expected " #size) > > > > +#define XFS_CHECK_OFFSET(structname, member, off) \ > > + BUILD_BUG_ON_MSG(offsetof(structname, member) != (off), \ > > + "XFS: offsetof(" #structname ", " #member ") is wrong, " \ > > + "expected " #off) > > + > > static inline void __init > > xfs_check_ondisk_structs(void) > > { > > @@ -75,15 +80,28 @@ xfs_check_ondisk_structs(void) > > XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_remote_t, 12); > > */ > > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, valuelen, 0); > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, namelen, 2); > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, nameval, 3); > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valueblk, 0); > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valuelen, 4); > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, namelen, 8); > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, name, 9); > > XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t, 40); > > - XFS_CHECK_STRUCT_SIZE(xfs_attr_shortform_t, 8); > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.totsize, 0); > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.count, 2); > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].namelen, 4); > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].valuelen, 5); > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].flags, 6); > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].nameval, 7); > > XFS_CHECK_STRUCT_SIZE(xfs_da_blkinfo_t, 12); > > XFS_CHECK_STRUCT_SIZE(xfs_da_intnode_t, 16); > > XFS_CHECK_STRUCT_SIZE(xfs_da_node_entry_t, 8); > > XFS_CHECK_STRUCT_SIZE(xfs_da_node_hdr_t, 16); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_free_t, 4); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_hdr_t, 16); > > - XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_unused_t, 6); > > + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, freetag, 0); > > + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, length, 2); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_hdr_t, 16); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_t, 16); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_ino4_t, 4); > > @@ -94,6 +112,9 @@ xfs_check_ondisk_structs(void) > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_t, 16); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_tail_t, 4); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_entry_t, 3); > > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, namelen, 0); > > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, offset, 1); > > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, name, 3); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_hdr_t, 10); > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_off_t, 2); > > > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Sat Jun 18 15:15:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id DD00F7CA0 for ; Sat, 18 Jun 2016 15:15:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 49451AC004 for ; Sat, 18 Jun 2016 13:15:48 -0700 (PDT) X-ASG-Debug-ID: 1466280942-04cbb01fefbe960001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id qP0wyjJEByWKjNOW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sat, 18 Jun 2016 13:15:43 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5IKFDfK004164 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 18 Jun 2016 20:15:14 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5IKFD5Q008464 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Sat, 18 Jun 2016 20:15:13 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5IKFB8a016595; Sat, 18 Jun 2016 20:15:11 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Sat, 18 Jun 2016 13:15:11 -0700 Date: Sat, 18 Jun 2016 13:15:10 -0700 From: "Darrick J. Wong" To: Christoph Hellwig Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 009/119] xfs: convert list of extents to free into a regular list Message-ID: <20160618201509.GA5042@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 009/119] xfs: convert list of extents to free into a regular list References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612632997.12839.18026491074892368053.stgit@birch.djwong.org> <20160617115930.GH19042@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617115930.GH19042@infradead.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466280942 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2351 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30550 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 17, 2016 at 04:59:30AM -0700, Christoph Hellwig wrote: > > { > > + struct xfs_bmap_free_item *new; /* new element */ > > #ifdef DEBUG > > xfs_agnumber_t agno; > > xfs_agblock_t agbno; > > @@ -597,17 +595,7 @@ xfs_bmap_add_free( > > new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); > > new->xbfi_startblock = bno; > > new->xbfi_blockcount = (xfs_extlen_t)len; > > + list_add(&new->xbfi_list, &flist->xbf_flist); > > flist->xbf_count++; > > Please kill xbf_count while you're at it, it's entirely superflous. The deferred ops conversion patch kills this off by moving the whole "defer an op to the next transaction by logging redo items" logic into a separate file and mechanism. This patch is just a cleanup to reduce some of the open coded list ugliness before starting on the rmap stuff. Once the deferred ops code lands, all three of these functions go away. > > @@ -617,14 +605,10 @@ xfs_bmap_add_free( > > */ > > void > > xfs_bmap_del_free( > > - xfs_bmap_free_t *flist, /* free item list header */ > > - xfs_bmap_free_item_t *prev, /* previous item on list, if any */ > > - xfs_bmap_free_item_t *free) /* list item to be freed */ > > + struct xfs_bmap_free *flist, /* free item list header */ > > + struct xfs_bmap_free_item *free) /* list item to be freed */ > > Which then also gets rid of the flist argument here. > > > @@ -634,17 +618,16 @@ xfs_bmap_del_free( > > */ > > void > > xfs_bmap_cancel( > > + struct xfs_bmap_free *flist) /* list of bmap_free_items */ > > { > > + struct xfs_bmap_free_item *free; /* free list item */ > > > > if (flist->xbf_count == 0) > > return; > > + while (!list_empty(&flist->xbf_flist)) { > > + free = list_first_entry(&flist->xbf_flist, > > + struct xfs_bmap_free_item, xbfi_list); > > while ((free = list_first_entry_or_null(...)) > > > + list_sort((*tp)->t_mountp, &flist->xbf_flist, xfs_bmap_free_list_cmp); > > Can you add a comment on why we are sorting the list? We sort the list so that we process the freed extents in AG order to avoid deadlocking. I'll add a comment to the deferred ops code if there isn't one already. --D > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From david@fromorbit.com Sun Jun 19 19:21:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9744F7CA0 for ; Sun, 19 Jun 2016 19:21:53 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3A5A98F8039 for ; Sun, 19 Jun 2016 17:21:53 -0700 (PDT) X-ASG-Debug-ID: 1466382105-04bdf01e13125ad0001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id RpubFsgj0hxZVoCp for ; Sun, 19 Jun 2016 17:21:46 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CnDACBNmdXEJgMLHlcgz6BU4ZvnyeMOIYGhAmGEQICAQECgSM8EQEBAQEBAQEGAQEBAQEBAQE+QIRLAQEBAwEnExwjBQsIAxgJJQ8FJQMHGhOIKAe/YAEBAQEGAgEkHoVBhRWBOYhiBZh2jiCPLI93NIIlAw0PgV4qMopIAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail05.adl6.internode.on.net with ESMTP; 20 Jun 2016 09:51:08 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bEmxf-000443-T7; Mon, 20 Jun 2016 10:21:07 +1000 Date: Mon, 20 Jun 2016 10:21:07 +1000 From: Dave Chinner To: "Darrick J. Wong" Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 006/119] xfs: port differences from xfsprogs libxfs Message-ID: <20160620002107.GG26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 006/119] xfs: port differences from xfsprogs libxfs References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612631079.12839.13685287438216197909.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612631079.12839.13685287438216197909.stgit@birch.djwong.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1466382106 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7842 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30580 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 16, 2016 at 06:18:30PM -0700, Darrick J. Wong wrote: > Port various differences between xfsprogs and the kernel. This > cleans up both so that we can develop rmap and reflink on the > same libxfs code. > > Signed-off-by: Darrick J. Wong Nak. I'm essentially trying to keep the little hacks needed in userspace out of the kernel libxfs tree. We quite regularly get people scanning the kernel tree and trying to remove things like exported function prototypes that are not used in kernel space, so the headers in userspace carry those simply to prevent people continually sending kernel patches that we have to look at and then ignore... > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c > index 99b077c..58bdca7 100644 > --- a/fs/xfs/libxfs/xfs_alloc.c > +++ b/fs/xfs/libxfs/xfs_alloc.c > @@ -2415,7 +2415,9 @@ xfs_alloc_read_agf( > be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); > spin_lock_init(&pag->pagb_lock); > pag->pagb_count = 0; > +#ifdef __KERNEL__ > pag->pagb_tree = RB_ROOT; > +#endif > pag->pagf_init = 1; > } > #ifdef DEBUG e.g. this is an indication that reminds us that there is functionality in the libxfs kernel tree that isn't in userspace... > diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h > index 4f2aed0..8ef420a 100644 > --- a/fs/xfs/libxfs/xfs_attr_leaf.h > +++ b/fs/xfs/libxfs/xfs_attr_leaf.h > @@ -51,7 +51,7 @@ int xfs_attr_shortform_getvalue(struct xfs_da_args *args); > int xfs_attr_shortform_to_leaf(struct xfs_da_args *args); > int xfs_attr_shortform_remove(struct xfs_da_args *args); > int xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp); > -int xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes); > +int xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes); > void xfs_attr_fork_remove(struct xfs_inode *ip, struct xfs_trans *tp); Things like this are fine... > > /* > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c > index 932381c..499e980 100644 > --- a/fs/xfs/libxfs/xfs_bmap.c > +++ b/fs/xfs/libxfs/xfs_bmap.c > @@ -1425,7 +1425,7 @@ xfs_bmap_search_multi_extents( > * Else, *lastxp will be set to the index of the found > * entry; *gotp will contain the entry. > */ > -STATIC xfs_bmbt_rec_host_t * /* pointer to found extent entry */ > +xfs_bmbt_rec_host_t * /* pointer to found extent entry */ > xfs_bmap_search_extents( > xfs_inode_t *ip, /* incore inode pointer */ > xfs_fileoff_t bno, /* block number searched for */ > diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h > index 423a34e..79e3ebe 100644 > --- a/fs/xfs/libxfs/xfs_bmap.h > +++ b/fs/xfs/libxfs/xfs_bmap.h > @@ -231,4 +231,10 @@ int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, > int num_exts); > int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); > > +struct xfs_bmbt_rec_host * > + xfs_bmap_search_extents(struct xfs_inode *ip, xfs_fileoff_t bno, > + int fork, int *eofp, xfs_extnum_t *lastxp, > + struct xfs_bmbt_irec *gotp, > + struct xfs_bmbt_irec *prevp); > + > #endif /* __XFS_BMAP_H__ */ But these are the sort of "clean up the kernel patches" that I was refering to. If there's a user in kernel space, then fine, otherwise it doesn't hurt to keep it only in userspace. There are relatively few of these.... > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 1f88e1c..105979d 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -2532,6 +2532,7 @@ error0: > return error; > } > > +#ifdef __KERNEL__ > struct xfs_btree_split_args { > struct xfs_btree_cur *cur; > int level; > @@ -2609,6 +2610,9 @@ xfs_btree_split( > destroy_work_on_stack(&args.work); > return args.result; > } > +#else /* !KERNEL */ > +#define xfs_btree_split __xfs_btree_split > +#endif Same again -this is 4 lines of code that is userspace only. It's a tiny amount compared to the original difference that these kernel-only stack splits required, and so not a huge issue. > --- a/fs/xfs/libxfs/xfs_dquot_buf.c > +++ b/fs/xfs/libxfs/xfs_dquot_buf.c > @@ -31,10 +31,16 @@ > #include "xfs_cksum.h" > #include "xfs_trace.h" > > +/* > + * XXX: kernel implementation causes ndquots calc to go real > + * bad. Just leaving the existing userspace calc here right now. > + */ > int > xfs_calc_dquots_per_chunk( > unsigned int nbblks) /* basic block units */ > { > +#ifdef __KERNEL__ > + /* kernel code that goes wrong in userspace! */ > unsigned int ndquots; > > ASSERT(nbblks > 0); > @@ -42,6 +48,10 @@ xfs_calc_dquots_per_chunk( > do_div(ndquots, sizeof(xfs_dqblk_t)); > > return ndquots; > +#else > + ASSERT(nbblks > 0); > + return BBTOB(nbblks) / sizeof(xfs_dqblk_t); > +#endif > } This is a clear case that we need to fix the code to be correct for both kernel and userspace without modification, not propagate the userspace hack back into the kernel code. > diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c > index 9d9559e..794fa66 100644 > --- a/fs/xfs/libxfs/xfs_inode_buf.c > +++ b/fs/xfs/libxfs/xfs_inode_buf.c > @@ -56,6 +56,17 @@ xfs_inobp_check( > } > #endif > > +bool > +xfs_dinode_good_version( > + struct xfs_mount *mp, > + __u8 version) > +{ > + if (xfs_sb_version_hascrc(&mp->m_sb)) > + return version == 3; > + > + return version == 1 || version == 2; > +} This xfs_dinode_good_version() change needs to be a separate patch > void xfs_inobp_check(struct xfs_mount *, struct xfs_buf *); > #else > diff --git a/fs/xfs/libxfs/xfs_log_format.h b/fs/xfs/libxfs/xfs_log_format.h > index e8f49c0..e5baba3 100644 > --- a/fs/xfs/libxfs/xfs_log_format.h > +++ b/fs/xfs/libxfs/xfs_log_format.h > @@ -462,8 +462,8 @@ static inline uint xfs_log_dinode_size(int version) > typedef struct xfs_buf_log_format { > unsigned short blf_type; /* buf log item type indicator */ > unsigned short blf_size; /* size of this item */ > - ushort blf_flags; /* misc state */ > - ushort blf_len; /* number of blocks in this buf */ > + unsigned short blf_flags; /* misc state */ > + unsigned short blf_len; /* number of blocks in this buf */ > __int64_t blf_blkno; /* starting blkno of this buf */ > unsigned int blf_map_size; /* used size of data bitmap in words */ > unsigned int blf_data_map[XFS_BLF_DATAMAP_SIZE]; /* dirty bitmap */ The removal of ushort/uint from the kernel code needs to be a separate patch that addresses all the users, not just the couple in shared headers.... > diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c > index 12ca867..09d6fd0 100644 > --- a/fs/xfs/libxfs/xfs_sb.c > +++ b/fs/xfs/libxfs/xfs_sb.c > @@ -261,6 +261,7 @@ xfs_mount_validate_sb( > /* > * Until this is fixed only page-sized or smaller data blocks work. > */ > +#ifdef __KERNEL__ > if (unlikely(sbp->sb_blocksize > PAGE_SIZE)) { > xfs_warn(mp, > "File system with blocksize %d bytes. " > @@ -268,6 +269,7 @@ xfs_mount_validate_sb( > sbp->sb_blocksize, PAGE_SIZE); > return -ENOSYS; > } > +#endif > > /* > * Currently only very few inode sizes are supported. > @@ -291,10 +293,12 @@ xfs_mount_validate_sb( > return -EFBIG; > } > > +#ifdef __KERNEL__ > if (check_inprogress && sbp->sb_inprogress) { > xfs_warn(mp, "Offline file system operation in progress!"); > return -EFSCORRUPTED; > } > +#endif > return 0; > } Again, I don't think this needs to be propagated back into the kernel code... -- Dave Chinner david@fromorbit.com From david@fromorbit.com Sun Jun 19 21:05:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id BAB2C7CA0 for ; Sun, 19 Jun 2016 21:05:05 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 73AE6304032 for ; Sun, 19 Jun 2016 19:05:02 -0700 (PDT) X-ASG-Debug-ID: 1466388299-04cbb01fef103910001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id 1AD0jMuuTG0G7HYo for ; Sun, 19 Jun 2016 19:04:59 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AyDABRTmdXEJgMLHlcgz6BU4ZvnyEGjDiGBoQJhhEEAgKBJj0QAQEBAQEBAQYBAQEBAQEBAT5AhEwBAQQ6HCMQCAMYCSUPBSUDBxoTiC+/XgELJR6FQYUVihsFmHaOIIFdjU9Ijy81hCEqMopIAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail05.adl6.internode.on.net with ESMTP; 20 Jun 2016 11:34:16 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bEoZS-0004E8-Ex; Mon, 20 Jun 2016 12:04:14 +1000 Date: Mon, 20 Jun 2016 12:04:14 +1000 From: Dave Chinner To: Felix Janda Cc: xfs@oss.sgi.com Subject: Re: [PATCH 1/4] Remove off64_t from linux.h Message-ID: <20160620020414.GH26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 1/4] Remove off64_t from linux.h References: <20160618145238.GA17768@nyan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160618145238.GA17768@nyan> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1466388299 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 653 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30581 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Sat, Jun 18, 2016 at 04:52:38PM +0200, Felix Janda wrote: > The off64_t type is usually only conditionally exposed under the > feature test macro _LARGEFILE64_SOURCE (also defined by _GNU_SOURCE). > To make the public xfs headers more standalone therefore off64_t should > be avoided. "more standalone"? What does that mean? And what does it mean for all the xfsprogs code that still uses off64_t? i.e. if you are going to make xfsprogs fail to compile on configs that don't define off64_t, then it makes no sense to leave all the users of off64_t in the xfsprogs code.... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Sun Jun 19 21:14:45 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BA79D7CA0 for ; Sun, 19 Jun 2016 21:14:45 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1B3BDAC001 for ; Sun, 19 Jun 2016 19:14:42 -0700 (PDT) X-ASG-Debug-ID: 1466388879-04cbb01fed104260001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id PJVEKui70ewnFucG for ; Sun, 19 Jun 2016 19:14:39 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CtDACFUGdXEJgMLHlcgz6BU4ZvnyEGjDiGBoQJhhECAgEBAoEmPRABAQEBAQEBBgEBAQEBAQEBPkCETAEBBDocIxAIAxgJJQ8FJQMHGhOIL79iATAehUGFFYobBZh2jiCPLI93NYQhKjKKSAEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail05.adl6.internode.on.net with ESMTP; 20 Jun 2016 11:42:27 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bEohO-0004FB-OP; Mon, 20 Jun 2016 12:12:26 +1000 Date: Mon, 20 Jun 2016 12:12:26 +1000 From: Dave Chinner To: Felix Janda Cc: xfs@oss.sgi.com Subject: Re: [PATCH 4/4] Move to more stdint types Message-ID: <20160620021226.GI26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 4/4] Move to more stdint types References: <20160618145330.GD17768@nyan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160618145330.GD17768@nyan> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1466388879 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 984 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30581 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Sat, Jun 18, 2016 at 04:53:30PM +0200, Felix Janda wrote: > The uint*_t and int*_t are defined by C99 and should be prefered > over the less portable __uint*_t and __int*_t variants. The > necessary include is in platformdefs.h, which gets > included in most places via libxfs.h. > > For now, only replace all __uint*_t types to uint*_t and likewise for > __int*_t outside the directories include/ and libxfs/. > > Signed-off-by: Felix Janda ..... > 58 files changed, 502 insertions(+), 502 deletions(-) Because of the amount of churn this will cause outstanding patchsets (e.g. the rmap/reflink work), this isn't the best time for us to be committing tree-wide cleanups like this. Once we get the major changes that are pending reviewed and committed I have no problems with making these changes, so perhaps you could regenerate the patch once those are merged? Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Sun Jun 19 21:29:57 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id D60E97CA0 for ; Sun, 19 Jun 2016 21:29:57 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4D258AC001 for ; Sun, 19 Jun 2016 19:29:57 -0700 (PDT) X-ASG-Debug-ID: 1466389793-04cbb01fec105120001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id 4nkl4TqlsZWSJG6c for ; Sun, 19 Jun 2016 19:29:54 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AyDAA2VGdXEJgMLHlcgz6BU4ZvnyIGjDiGBoQJhhEEAgKBJz0QAQEBAQEBAQYBAQEBAQEBAT5AhEwBAQQ6HCMQCAMOCgklDwUlAwcaE4gvv1IBAQgCJR6FQYUVihsBBJh2jiCBXQEVjTmGUIknNYQhKjKKSAEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail05.adl6.internode.on.net with ESMTP; 20 Jun 2016 11:59:52 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bEoyG-0004Hw-2z; Mon, 20 Jun 2016 12:29:52 +1000 Date: Mon, 20 Jun 2016 12:29:52 +1000 From: Dave Chinner To: Christoph Hellwig Cc: Jan Kara , rpeterso@redhat.com, linux-fsdevel@vger.kernel.org, xfs@oss.sgi.com Subject: Re: [PATCH 02/14] fs: introduce iomap infrastructure Message-ID: <20160620022952.GJ26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 02/14] fs: introduce iomap infrastructure References: <1464792297-13185-1-git-send-email-hch@lst.de> <1464792297-13185-3-git-send-email-hch@lst.de> <20160616161242.GB2106@quack2.suse.cz> <20160617120144.GA333@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617120144.GA333@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1466389793 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 436 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30582 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 17, 2016 at 02:01:44PM +0200, Christoph Hellwig wrote: > On Thu, Jun 16, 2016 at 06:12:42PM +0200, Jan Kara wrote: > > This is actually in 512-byte units, not in fs blocks as the comment > > suggests, right? > > Indeed, thanks for spotting this! I'll update the patches I've already tested, Christoph, so you don't have to post an update just for this. Cheers, Dave. -- Dave Chinner david@fromorbit.com From ceremonious06@mail.ru Mon Jun 20 00:32:40 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.5 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_FONT_SIZE_LARGE,HTML_MESSAGE,MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 48F157CA1 for ; Mon, 20 Jun 2016 00:32:40 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0B3CF8F8040 for ; Sun, 19 Jun 2016 22:32:36 -0700 (PDT) X-ASG-Debug-ID: 1466400752-04bdf01e171320e0001-NocioJ Received: from [122.170.205.113] ([122.170.205.113]) by cuda.sgi.com with ESMTP id J0iSRcOyb7NlFEIK for ; Sun, 19 Jun 2016 22:32:33 -0700 (PDT) X-Barracuda-Envelope-From: ceremonious06@mail.ru X-Barracuda-Effective-Source-IP: UNKNOWN[122.170.205.113] X-Barracuda-Apparent-Source-IP: 122.170.205.113 Date: Mon, 20 Jun 2016 10:53:53 +0530 Message-ID: <7039964.20160620105353@mail.ru> To: X-Priority: 3 (Normal) From: =?koi8-r?B?98zBxMnL?= Subject: =?koi8-r?B?7s/X2cUg2sHLwdreycvJIC0g09DP08/CINLB2s/C0sHU2NPRINMgzg==?= =?koi8-r?B?xc/QzMHexc7O2c3JIMTPzMfBzck=?= MIME-Version: 1.0 X-ASG-Orig-Subj: =?koi8-r?B?7s/X2cUg2sHLwdreycvJIC0g09DP08/CINLB2s/C0sHU2NPRINMgzg==?= =?koi8-r?B?xc/QzMHexc7O2c3JIMTPzMfBzck=?= Content-Type: text/html; charset=koi8-r Content-Transfer-Encoding: quoted-printable X-Barracuda-Connect: UNKNOWN[122.170.205.113] X-Barracuda-Start-Time: 1466400753 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 574 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, HTML_FONT_SIZE_LARGE, HTML_MESSAGE, MIME_HTML_ONLY, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30585 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_FONT_SIZE_LARGE BODY: HTML font size is large 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963

=E4=C1=CE=CE=D9= =CA =D3=D0=CF=D3=CF=C2 =D0=D2=CF=C4=D7=C9=D6=C5=CE=C9=D1 - =D2=C5=C1=CC= =D8=CE=CF =D0=D2=C9=D7=CF=C4=C9=D4 =CE=CF=D7=D9=C8 =CB=CC=C9=C5=CE=D4=CF= =D7

=EE=C5=C4=CF=D2= =CF=C7=CF


=FA=C1=CB=C1=D6=C9=D4=C5 =D2=C1=D3=D3=D9=CC=CB=D5 =D0=CF =D4=C5=CC=C5= =C6=CF=CE=D5:

\9 2 5\ 5 =EF 2 - 6 1 - 8 5=

From felix.janda@posteo.de Mon Jun 20 01:55:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EBB037CA1 for ; Mon, 20 Jun 2016 01:55:17 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 79A12AC001 for ; Sun, 19 Jun 2016 23:55:14 -0700 (PDT) X-ASG-Debug-ID: 1466405706-04bdf01e131350c0001-NocioJ Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by cuda.sgi.com with ESMTP id hS2wdU1wBbkcxW7o (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 19 Jun 2016 23:55:08 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout01.posteo.de[185.67.36.65] X-Barracuda-Apparent-Source-IP: 185.67.36.65 Received: from dovecot03.posteo.de (dovecot03.posteo.de [172.16.0.13]) by mout01.posteo.de (Postfix) with ESMTPS id 9F2C220C5A for ; Mon, 20 Jun 2016 08:55:05 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3rY1nj0d5Mz5vNS; Mon, 20 Jun 2016 08:55:04 +0200 (CEST) Date: Mon, 20 Jun 2016 08:53:48 +0200 From: Felix Janda To: Dave Chinner Cc: xfs@oss.sgi.com Subject: Re: [PATCH 1/4] Remove off64_t from linux.h Message-ID: <20160620065348.GA431@nyan> X-ASG-Orig-Subj: Re: [PATCH 1/4] Remove off64_t from linux.h References: <20160618145238.GA17768@nyan> <20160620020414.GH26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620020414.GH26977@dastard> User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout01.posteo.de[185.67.36.65] X-Barracuda-Start-Time: 1466405707 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1901 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30586 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Dave Chinner wrote: Thanks for asking for clarification. > On Sat, Jun 18, 2016 at 04:52:38PM +0200, Felix Janda wrote: > > The off64_t type is usually only conditionally exposed under the > > feature test macro _LARGEFILE64_SOURCE (also defined by _GNU_SOURCE). > > To make the public xfs headers more standalone therefore off64_t should > > be avoided. > > "more standalone"? > > What does that mean? Programs including the xfs headers while not defining _GNU_SOURCE or _LARGEFILE64_SOURCE will not fail with compile errors. My previous patch changing loff_t to off64_t had the unintented consequences that downstreams of xfs-progs like ceph had to define _LARGEFILE64_SOURCE on linux. > And what does it mean for all the xfsprogs code that still uses > off64_t? off_t and off64_t are now synomyms and 64 bit on all architectures. So no difference for code using off64_t. Under some conditions there can be a difference for code using off_t. > i.e. if you are going to make xfsprogs fail to compile on configs > that don't define off64_t, then it makes no sense to leave all the > users of off64_t in the xfsprogs code.... On all supported systems except for current default linux (glibc) configurations either there does not exist off64_t or it is the same as off_t. The configure test will define _FILE_OFFSET_BITS=64 on linux systems (i.e. enabling transparent large file support) with the result that now even on linux off_t is 64 bit wide in all cases. The "assert" ensures that programs using the xfs headers do not compile when the expectation sizeof(off_t)=8 is not met. This makes programs on 32 bit linux systems using the xfs headers but not defining _FILE_OFFSET_BITS=64 not compile. I would consider this as beneficial because such programs easily can have bugs regarding support of files of size >2GB on 32 bit systems. Felix From felix.janda@posteo.de Mon Jun 20 01:55:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A6FE17CA1 for ; Mon, 20 Jun 2016 01:55:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6C93A304039 for ; Sun, 19 Jun 2016 23:55:31 -0700 (PDT) X-ASG-Debug-ID: 1466405727-04cb6c5424d9f40001-NocioJ Received: from mout01.posteo.de (mout01.posteo.de [185.67.36.65]) by cuda.sgi.com with ESMTP id Hh0kbiHdqqocgDtJ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Sun, 19 Jun 2016 23:55:29 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout01.posteo.de[185.67.36.65] X-Barracuda-Apparent-Source-IP: 185.67.36.65 Received: from dovecot03.posteo.de (dovecot03.posteo.de [172.16.0.13]) by mout01.posteo.de (Postfix) with ESMTPS id 820D720AE6 for ; Mon, 20 Jun 2016 08:55:27 +0200 (CEST) Received: from mail.posteo.de (localhost [127.0.0.1]) by dovecot03.posteo.de (Postfix) with ESMTPSA id 3rY1p72P33z5vMw; Mon, 20 Jun 2016 08:55:27 +0200 (CEST) Date: Mon, 20 Jun 2016 08:54:10 +0200 From: Felix Janda To: Dave Chinner Cc: xfs@oss.sgi.com Subject: Re: [PATCH 4/4] Move to more stdint types Message-ID: <20160620065410.GB431@nyan> X-ASG-Orig-Subj: Re: [PATCH 4/4] Move to more stdint types References: <20160618145330.GD17768@nyan> <20160620021226.GI26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620021226.GI26977@dastard> User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout01.posteo.de[185.67.36.65] X-Barracuda-Start-Time: 1466405728 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1015 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30586 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Dave Chinner wrote: > On Sat, Jun 18, 2016 at 04:53:30PM +0200, Felix Janda wrote: > > The uint*_t and int*_t are defined by C99 and should be prefered > > over the less portable __uint*_t and __int*_t variants. The > > necessary include is in platformdefs.h, which gets > > included in most places via libxfs.h. > > > > For now, only replace all __uint*_t types to uint*_t and likewise for > > __int*_t outside the directories include/ and libxfs/. > > > > Signed-off-by: Felix Janda > ..... > > 58 files changed, 502 insertions(+), 502 deletions(-) > > Because of the amount of churn this will cause outstanding patchsets > (e.g. the rmap/reflink work), this isn't the best time for us to be > committing tree-wide cleanups like this. Once we get the major > changes that are pending reviewed and committed I have no problems > with making these changes, so perhaps you could regenerate the patch > once those are merged? Of course. Thanks, Felix From BATV+222cd9f711b61261916c+4684+infradead.org+hch@bombadil.srs.infradead.org Mon Jun 20 05:21:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9014C7CA1 for ; Mon, 20 Jun 2016 05:21:31 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 41D46304032 for ; Mon, 20 Jun 2016 03:21:28 -0700 (PDT) X-ASG-Debug-ID: 1466418085-04bdf01e1713ceb0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id eeXgNEQdgD5qRNXs (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 20 Jun 2016 03:21:26 -0700 (PDT) X-Barracuda-Envelope-From: BATV+222cd9f711b61261916c+4684+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.80.1 #2 (Red Hat Linux)) id 1bEwKY-0007kP-SB; Mon, 20 Jun 2016 10:21:22 +0000 Date: Mon, 20 Jun 2016 03:21:22 -0700 From: Christoph Hellwig To: Thorsten Leemhuis Cc: Linus Torvalds , Linux Kernel Mailing List , linux-fsdevel@vger.kernel.org, linux-ext4@vger.kernel.org, xfs@oss.sgi.com Subject: Re: Reported regressions for 4.7 as of Sunday, 2016-06-19 Message-ID: <20160620102122.GB23462@infradead.org> X-ASG-Orig-Subj: Re: Reported regressions for 4.7 as of Sunday, 2016-06-19 References: <7cc588b7-f1cf-62a8-e45b-ec7d863ba51e@leemhuis.info> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <7cc588b7-f1cf-62a8-e45b-ec7d863ba51e@leemhuis.info> User-Agent: Mutt/1.5.24 (2015-08-30) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466418086 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 306 X-ASG-Whitelist: Body =?UTF-8?B?aHR0cDovL21hcmNcLmluZm8vXD8=?= X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Another important one is the rename regression in XFS and ext4 that I suspect is due the VFS changes in 4.7: http://oss.sgi.com/pipermail/xfs/2016-June/049138.html http://oss.sgi.com/pipermail/xfs/2016-June/049309.html possibly related: http://marc.info/?l=linux-kernel&m=146605889024559&w=2 From cmaiolino@redhat.com Mon Jun 20 05:42:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1C3477CA1 for ; Mon, 20 Jun 2016 05:42:03 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 953FFAC002 for ; Mon, 20 Jun 2016 03:41:59 -0700 (PDT) X-ASG-Debug-ID: 1466419314-04cb6c5427e0530001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id SFHKyvBLFvP0D7Qf (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 03:41:55 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 76F5C46203 for ; Mon, 20 Jun 2016 10:41:54 +0000 (UTC) Received: from redhat.com (vpn-63-156.rdu2.redhat.com [10.10.63.156]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KAfoKH021317 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 20 Jun 2016 06:41:53 -0400 Date: Mon, 20 Jun 2016 12:41:50 +0200 From: Carlos Maiolino To: Eric Sandeen Cc: xfs-oss Subject: Re: [PATCH] xfs_copy: fix minor sparse endian nit Message-ID: <20160620104150.GA28212@redhat.com> X-ASG-Orig-Subj: Re: [PATCH] xfs_copy: fix minor sparse endian nit Mail-Followup-To: Eric Sandeen , xfs-oss References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Mon, 20 Jun 2016 10:41:54 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466419315 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 980 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jun 17, 2016 at 11:44:44AM -0500, Eric Sandeen wrote: > The intermediate variable should not have been endian-annotated; > it is the local cpu representation not the on-disk representation. > Looks good, you can add: Reviewed-by: Carlos Maiolino > Signed-off-by: Eric Sandeen > --- > > diff --git a/copy/xfs_copy.c b/copy/xfs_copy.c > index 2119a0b..1bc5163 100644 > --- a/copy/xfs_copy.c > +++ b/copy/xfs_copy.c > @@ -506,7 +506,7 @@ sb_update_uuid( > */ > if (!uuid_equal(&tcarg->uuid, &ag_hdr->xfs_sb->sb_uuid) && > xfs_sb_version_hascrc(sb) && !xfs_sb_version_hasmetauuid(sb)) { > - __be32 feat; > + __uint32_t feat; > > feat = be32_to_cpu(ag_hdr->xfs_sb->sb_features_incompat); > feat |= XFS_SB_FEAT_INCOMPAT_META_UUID; > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From hch@lst.de Mon Jun 20 07:22:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2277B7CA1 for ; Mon, 20 Jun 2016 07:22:52 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id E63A8304032 for ; Mon, 20 Jun 2016 05:22:48 -0700 (PDT) X-ASG-Debug-ID: 1466425364-04cbb01fec11e720001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id qerADLWi8AFZH5rx (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 05:22:45 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id B152F68C4F; Mon, 20 Jun 2016 14:22:43 +0200 (CEST) Date: Mon, 20 Jun 2016 14:22:43 +0200 From: Christoph Hellwig To: Dave Chinner Cc: Christoph Hellwig , Jan Kara , rpeterso@redhat.com, linux-fsdevel@vger.kernel.org, xfs@oss.sgi.com Subject: Re: [PATCH 02/14] fs: introduce iomap infrastructure Message-ID: <20160620122243.GB29059@lst.de> X-ASG-Orig-Subj: Re: [PATCH 02/14] fs: introduce iomap infrastructure References: <1464792297-13185-1-git-send-email-hch@lst.de> <1464792297-13185-3-git-send-email-hch@lst.de> <20160616161242.GB2106@quack2.suse.cz> <20160617120144.GA333@lst.de> <20160620022952.GJ26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620022952.GJ26977@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1466425365 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 516 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30589 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Mon, Jun 20, 2016 at 12:29:52PM +1000, Dave Chinner wrote: > On Fri, Jun 17, 2016 at 02:01:44PM +0200, Christoph Hellwig wrote: > > On Thu, Jun 16, 2016 at 06:12:42PM +0200, Jan Kara wrote: > > > This is actually in 512-byte units, not in fs blocks as the comment > > > suggests, right? > > > > Indeed, thanks for spotting this! > > I'll update the patches I've already tested, Christoph, so you don't > have to post an update just for this. Ok, thanks. Can't wait for the code to finally go in.. From bart.vanassche@gmail.com Mon Jun 20 07:35:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 647107CA7 for ; Mon, 20 Jun 2016 07:35:39 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id E2E41AC001 for ; Mon, 20 Jun 2016 05:35:35 -0700 (PDT) X-ASG-Debug-ID: 1466426132-04cbb01fee11eda0001-NocioJ Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by cuda.sgi.com with ESMTP id lWOtffyioyeByUHu (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 20 Jun 2016 05:35:32 -0700 (PDT) X-Barracuda-Envelope-From: bart.vanassche@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Apparent-Source-IP: 74.125.82.67 Received: by mail-wm0-f67.google.com with SMTP id a66so8634694wme.2 for ; Mon, 20 Jun 2016 05:35:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:subject:to:references:cc:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=t+FjJMJvzNGMW/yhrMw8baUaiRRnegFltP8OVGo4uPk=; b=e7tWwSzqxFydLyyJJnVWo5N27x6PyapIFl686H1E8EFXHpwzV4ZDAkxfxGzTo4yL5+ +yjfSP924maCcGvZNNpGp543qe/kgneOa+J6ZAMSprYRA54S41pDnQ0gRlALlM1fHGcu UsA+BK2A7Zhs4mqpGs2mwX1A3pv6c1QUK6O3admXM8QJCTtpC3W1Z31zPxWDnzweZscn hUqxapsGhEoqNbkDxqHj/hQH6l9Z7Zq+/uScmP7K5d3i2IIbdtTaHVYYzsJXUJVimQhY WgeFXkd/r0dAe7qdkpT7ymfZc+qvNJ5Je2XfscYCiVzzeoQw34elOoLksODEogQqI3zS O9qg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:subject:to:references:cc:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=t+FjJMJvzNGMW/yhrMw8baUaiRRnegFltP8OVGo4uPk=; b=TTZRRUy+6UlxXP8PVOo1jFV9/8BYSAWFdFRsHx2bdfvKx6hk/wEEEnaKuRvxH2tPza 9fenGyTNerxV5Gc3XM8MjUhBA4Lj+4IT6ojAMJ3XH5+JoFn28GBv4MpNDgQA9OoqOYl6 oNgeMIwX52Z7q7tDfC87YfYAFsOKnbmegApBuGxiQHOw/fuC7VtuWFGdCB1AyALtMWGv j56YYkge5I6fymhaTT5QzYziw7e+X8qyxTyv/+DGQd9GSyrzm2YZjDv+HM9KXsAHJsvT IexK32sPlyKu65AndJTNnWZ0LWbKNQUxqx1CAz/fYEewYJu7HOZ+vyTkEKGA99WoCRGa zQvw== X-Gm-Message-State: ALyK8tKdPYLjA2eMOZTBwmlGV6yguRYpwgl++ygcLt4fGrqVc+BUC4ufyRqsbvyEZ6QVPg== X-Received: by 10.194.120.167 with SMTP id ld7mr15541576wjb.69.1466426131756; Mon, 20 Jun 2016 05:35:31 -0700 (PDT) Received: from exp-402881.sandisk.com (178-117-55-239.access.telenet.be. [178.117.55.239]) by smtp.googlemail.com with ESMTPSA id kd7sm63481294wjc.33.2016.06.20.05.35.30 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 20 Jun 2016 05:35:30 -0700 (PDT) From: Bart Van Assche X-Google-Original-From: Bart Van Assche Subject: Re: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. To: "Darrick J. Wong" , "axboe@kernel.dk" X-ASG-Orig-Subj: Re: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> <146612625412.12764.6647932282740152837.stgit@birch.djwong.org> Cc: "linux-block@vger.kernel.org" , "tytso@mit.edu" , "martin.petersen@oracle.com" , "snitzer@redhat.com" , "linux-api@vger.kernel.org" , "bfoster@redhat.com" , "xfs@oss.sgi.com" , "hch@infradead.org" , "dm-devel@redhat.com" , "linux-fsdevel@vger.kernel.org" , Christoph Hellwig Message-ID: <7589fc01-a000-a912-f9b5-cf099cc2d27a@acm.org> Date: Mon, 20 Jun 2016 14:35:29 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <146612625412.12764.6647932282740152837.stgit@birch.djwong.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f67.google.com[74.125.82.67] X-Barracuda-Start-Time: 1466426132 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2539 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30589 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/17/2016 03:18 AM, Darrick J. Wong wrote: > Invalidate the page cache (as a regular O_DIRECT write would do) to avoid > returning stale cache contents at a later time. > > v5: Refactor the 4.4 refactoring of the ioctl code into separate functions. > Split the page invalidation and the new ioctl into separate patches. > > Signed-off-by: Darrick J. Wong > Reviewed-by: Christoph Hellwig > --- > block/ioctl.c | 29 +++++++++++++++++++++++------ > 1 file changed, 23 insertions(+), 6 deletions(-) > > > diff --git a/block/ioctl.c b/block/ioctl.c > index ed2397f..d001f52 100644 > --- a/block/ioctl.c > +++ b/block/ioctl.c > @@ -225,7 +225,9 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, > unsigned long arg) > { > uint64_t range[2]; > - uint64_t start, len; > + struct address_space *mapping; > + uint64_t start, end, len; > + int ret; > > if (!(mode & FMODE_WRITE)) > return -EBADF; > @@ -235,18 +237,33 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, > > start = range[0]; > len = range[1]; > + end = start + len - 1; > > if (start & 511) > return -EINVAL; > if (len & 511) > return -EINVAL; > - start >>= 9; > - len >>= 9; > - > - if (start + len > (i_size_read(bdev->bd_inode) >> 9)) > + if (end >= (uint64_t)i_size_read(bdev->bd_inode)) > + return -EINVAL; > + if (end < start) > return -EINVAL; > > - return blkdev_issue_zeroout(bdev, start, len, GFP_KERNEL, false); > + /* Invalidate the page cache, including dirty pages */ > + mapping = bdev->bd_inode->i_mapping; > + truncate_inode_pages_range(mapping, start, end); > + > + ret = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, > + false); > + if (ret) > + return ret; > + > + /* > + * Invalidate again; if someone wandered in and dirtied a page, > + * the caller will be given -EBUSY. > + */ > + return invalidate_inode_pages2_range(mapping, > + start >> PAGE_SHIFT, > + end >> PAGE_SHIFT); > } Hello Darrick, Maybe this has already been discussed, but anyway: in the POSIX spec (http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html) I found the following: "This volume of POSIX.1-2008 does not specify behavior of concurrent writes to a file from multiple processes. Applications should use some form of concurrency control." Do we really need the invalidate_inode_pages2_range() call? Thanks, Bart. From bart.vanassche@gmail.com Mon Jun 20 07:37:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 483FA7CB3 for ; Mon, 20 Jun 2016 07:37:19 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 1BB3F8F8049 for ; Mon, 20 Jun 2016 05:37:16 -0700 (PDT) X-ASG-Debug-ID: 1466426233-04cbb01fed11ee80001-NocioJ Received: from mail-wm0-f47.google.com (mail-wm0-f47.google.com [74.125.82.47]) by cuda.sgi.com with ESMTP id OjAwSwF3ADyGVdzn (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Mon, 20 Jun 2016 05:37:14 -0700 (PDT) X-Barracuda-Envelope-From: bart.vanassche@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f47.google.com[74.125.82.47] X-Barracuda-Apparent-Source-IP: 74.125.82.47 Received: by mail-wm0-f47.google.com with SMTP id r201so59819488wme.1 for ; Mon, 20 Jun 2016 05:37:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:subject:to:references:cc:message-id:date:user-agent :mime-version:in-reply-to:content-transfer-encoding; bh=TDoG6awL+Gq2OpAUQhA4JrABhkPqxhGi6H8LhPUu/+4=; b=cz9jTecdpZq3jBCSPl3rqF1gLnS8nOcPi8tKYl3qbxvlWXzZ3C8rMO1wknuxwxh7JG WyYyDB3x26FXJuZeZ4kC0b+1q7ZQ/D7NKvgRwser1heONvfQeaHHu8LorO+Oz+AKph+M ojojjeOc+UQt57WsyDvF9NqF+iMFDbcME2Aib8aQD2uhij0GI7qUnyZCoZi/VOaaray/ /UblNe8tPludtkleNUsfk6JaWF+2ReaC9bTkkU6/5aKAojWvNCXjuDEqokRhZnuaQx+1 tndpexOjg6DvP7TKA/IK8c2YWprjaxJ1JFLyIlpLawcNlaHALO1mwd8n+fD9+yG+gsft fSWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:subject:to:references:cc:message-id:date :user-agent:mime-version:in-reply-to:content-transfer-encoding; bh=TDoG6awL+Gq2OpAUQhA4JrABhkPqxhGi6H8LhPUu/+4=; b=GbtJw0QBApD6tyUN2zcw2/OEzZFXu6tXvNHJXBGMHZSTx4FFjFmDk/WXBnUcQfP5Rx nX/yIgd/LF3tSpCIPZdtyJKDoWYKKAsr8Oe3choGO/pAAy95QOh4zcKKuL5+tPKVH/kS 6hbA8JC/WGXfPRXeuMDYqtNTpePEW19tsGxGqMwIWY0ob5GmtbVYzuUNP5RPhuUxAMrn Mt5aTGzxzNLQCLc7bChmX5sgEjRk2EE/ls/AgZL/358PZQqzrHJiWYl50eAK/PcP+lDl YwnnDjQJLikiVnLkG0ogbrI7eYfaiaS5gwnYtloSrJ46GOpK1K+i/OKY+TGsDHsHxrF5 QvVQ== X-Gm-Message-State: ALyK8tIZT6ChL9WygR47LSNdtLCjHJRF1RBj2aM2BFTmYPPRYFiAsZrFNOC4I4VathUVBA== X-Received: by 10.28.126.2 with SMTP id z2mr11433246wmc.73.1466426228373; Mon, 20 Jun 2016 05:37:08 -0700 (PDT) Received: from exp-402881.sandisk.com (178-117-55-239.access.telenet.be. [178.117.55.239]) by smtp.googlemail.com with ESMTPSA id li10sm18914682wjb.5.2016.06.20.05.37.06 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 20 Jun 2016 05:37:07 -0700 (PDT) From: Bart Van Assche X-Google-Original-From: Bart Van Assche Subject: Re: [PATCH 2/3] block: require write_same and discard requests align to logical block size To: "Darrick J. Wong" , "axboe@kernel.dk" X-ASG-Orig-Subj: Re: [PATCH 2/3] block: require write_same and discard requests align to logical block size References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> <146612626092.12764.773833541076937471.stgit@birch.djwong.org> Cc: "linux-block@vger.kernel.org" , "tytso@mit.edu" , "martin.petersen@oracle.com" , "snitzer@redhat.com" , "linux-api@vger.kernel.org" , "bfoster@redhat.com" , "xfs@oss.sgi.com" , "hch@infradead.org" , "dm-devel@redhat.com" , "linux-fsdevel@vger.kernel.org" , Christoph Hellwig , Bart Van Assche Message-ID: <3470c511-59f5-ff7d-b4b0-22d7d8a2a6e7@acm.org> Date: Mon, 20 Jun 2016 14:37:06 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <146612626092.12764.773833541076937471.stgit@birch.djwong.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f47.google.com[74.125.82.47] X-Barracuda-Start-Time: 1466426234 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 543 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30589 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/17/2016 03:19 AM, Darrick J. Wong wrote: > Make sure that the offset and length arguments that we're using to > construct WRITE SAME and DISCARD requests are actually aligned to the > logical block size. Failure to do this causes other errors in other > parts of the block layer or the SCSI layer because disks don't support > partial logical block writes. > > Signed-off-by: Darrick J. Wong > Reviewed-by: Christoph Hellwig Reviewed-by: Bart Van Assche From bfoster@redhat.com Mon Jun 20 07:38:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B52BF7CB3 for ; Mon, 20 Jun 2016 07:38:42 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4E718AC003 for ; Mon, 20 Jun 2016 05:38:42 -0700 (PDT) X-ASG-Debug-ID: 1466426320-04bdf01e17141170001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id FWaEOb21qRq6zQlH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 05:38:41 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C527A80085; Mon, 20 Jun 2016 12:38:40 +0000 (UTC) Received: from laptop.bfoster (vpn-60-186.rdu2.redhat.com [10.10.60.186]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KCcbUL002162 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 20 Jun 2016 08:38:39 -0400 Date: Mon, 20 Jun 2016 08:38:36 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 003/119] xfs: check offsets of variable length structures Message-ID: <20160620123836.GA9474@laptop.bfoster> X-ASG-Orig-Subj: Re: [PATCH 003/119] xfs: check offsets of variable length structures References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612629195.12839.14090954204243398929.stgit@birch.djwong.org> <20160617173426.GA46309@bfoster.bfoster> <20160618180133.GB5046@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160618180133.GB5046@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Mon, 20 Jun 2016 12:38:40 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466426321 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5134 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Sat, Jun 18, 2016 at 11:01:33AM -0700, Darrick J. Wong wrote: > On Fri, Jun 17, 2016 at 01:34:27PM -0400, Brian Foster wrote: > > On Thu, Jun 16, 2016 at 06:18:12PM -0700, Darrick J. Wong wrote: > > > Some of the directory/attr structures contain variable-length objects, > > > so the enclosing structure doesn't have a meaningful fixed size at > > > compile time. We can check the offsets of the members before the > > > variable-length member, so do those. > > > > > > Signed-off-by: Darrick J. Wong > > > --- > > > > I'm missing why this is necessary. Is the intent still to catch > > alignment and/or padding issues? If so, isn't the size check sufficient, > > regardless of trailing variable size fields? > > > > Perhaps the goal here is to reduce the scope of checking from where it > > isn't needed..? For example, xfs_dir2_data_unused_t looks like it has a > > field where the offset in the structure is irrelevant, so that's a > > possible false positive if that changes down the road. On the flip side, > > that doesn't appear to be the case for other structures such as > > xfs_attr_leaf_name_[local|remote]_t. > > ISTR making this change to work around behavioral variances in how > much padding gcc adds to structures across its various targets. The > macros that go along with the variable sized structures work fine, > but testing the sizeof() doesn't work reliably. > Ok, I take that to mean that we may or may not have padding in some of the variable structures depending on architecture (and we really only care about certain fields in those structures). Fair enough, thanks! Brian > --D > > > > > Brian > > > > > fs/xfs/xfs_ondisk.h | 25 +++++++++++++++++++++++-- > > > 1 file changed, 23 insertions(+), 2 deletions(-) > > > > > > > > > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h > > > index 184c44e..0272301 100644 > > > --- a/fs/xfs/xfs_ondisk.h > > > +++ b/fs/xfs/xfs_ondisk.h > > > @@ -22,6 +22,11 @@ > > > BUILD_BUG_ON_MSG(sizeof(structname) != (size), "XFS: sizeof(" \ > > > #structname ") is wrong, expected " #size) > > > > > > +#define XFS_CHECK_OFFSET(structname, member, off) \ > > > + BUILD_BUG_ON_MSG(offsetof(structname, member) != (off), \ > > > + "XFS: offsetof(" #structname ", " #member ") is wrong, " \ > > > + "expected " #off) > > > + > > > static inline void __init > > > xfs_check_ondisk_structs(void) > > > { > > > @@ -75,15 +80,28 @@ xfs_check_ondisk_structs(void) > > > XFS_CHECK_STRUCT_SIZE(xfs_attr_leaf_name_remote_t, 12); > > > */ > > > > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, valuelen, 0); > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, namelen, 2); > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_local_t, nameval, 3); > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valueblk, 0); > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valuelen, 4); > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, namelen, 8); > > > + XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, name, 9); > > > XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t, 40); > > > - XFS_CHECK_STRUCT_SIZE(xfs_attr_shortform_t, 8); > > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.totsize, 0); > > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, hdr.count, 2); > > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].namelen, 4); > > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].valuelen, 5); > > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].flags, 6); > > > + XFS_CHECK_OFFSET(xfs_attr_shortform_t, list[0].nameval, 7); > > > XFS_CHECK_STRUCT_SIZE(xfs_da_blkinfo_t, 12); > > > XFS_CHECK_STRUCT_SIZE(xfs_da_intnode_t, 16); > > > XFS_CHECK_STRUCT_SIZE(xfs_da_node_entry_t, 8); > > > XFS_CHECK_STRUCT_SIZE(xfs_da_node_hdr_t, 16); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_free_t, 4); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_hdr_t, 16); > > > - XFS_CHECK_STRUCT_SIZE(xfs_dir2_data_unused_t, 6); > > > + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, freetag, 0); > > > + XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, length, 2); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_hdr_t, 16); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_t, 16); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_ino4_t, 4); > > > @@ -94,6 +112,9 @@ xfs_check_ondisk_structs(void) > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_t, 16); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_tail_t, 4); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_entry_t, 3); > > > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, namelen, 0); > > > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, offset, 1); > > > + XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, name, 3); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_hdr_t, 10); > > > XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_off_t, 2); > > > > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Mon Jun 20 09:31:56 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6D8617CA4 for ; Mon, 20 Jun 2016 09:31:56 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 22799304032 for ; Mon, 20 Jun 2016 07:31:53 -0700 (PDT) X-ASG-Debug-ID: 1466433111-04bdf01e131475a0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id jb6xkekIyD0VxPrU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 07:31:51 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5E7B1C08A402; Mon, 20 Jun 2016 14:31:51 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KEVoeG005432; Mon, 20 Jun 2016 10:31:50 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 8EA40123469; Mon, 20 Jun 2016 10:31:49 -0400 (EDT) Date: Mon, 20 Jun 2016 10:31:49 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 010/119] xfs: create a standard btree size calculator code Message-ID: <20160620143148.GA2465@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 010/119] xfs: create a standard btree size calculator code References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612633632.12839.13314497569643567486.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612633632.12839.13314497569643567486.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 20 Jun 2016 14:31:51 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466433111 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2670 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:18:56PM -0700, Darrick J. Wong wrote: > Create a helper to generate AG btree height calculator functions. > This will be used (much) later when we get to the refcount btree. > > v2: Use a helper function instead of a macro. > v3: We can (theoretically) store more than 2^32 records in a btree, so > widen the fields to accept that. > v4: Don't modify xfs_bmap_worst_indlen; the purpose of /that/ function > is to estimate the worst-case number of blocks needed for a bmbt > expansion, not to calculate the space required to store nr records. > > Signed-off-by: Darrick J. Wong > --- I think this one should probably be pushed out to where it is used (easier to review with an example imo). I don't see it used anywhere up through the rmapbt stuff, anyways... > fs/xfs/libxfs/xfs_btree.c | 27 +++++++++++++++++++++++++++ > fs/xfs/libxfs/xfs_btree.h | 3 +++ > 2 files changed, 30 insertions(+) > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 105979d..5eb4e40 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -4156,3 +4156,30 @@ xfs_btree_sblock_verify( > > return true; > } > + > +/* > + * Calculate the number of blocks needed to store a given number of records > + * in a short-format (per-AG metadata) btree. > + */ > +xfs_extlen_t > +xfs_btree_calc_size( > + struct xfs_mount *mp, > + uint *limits, > + unsigned long long len) > +{ > + int level; > + int maxrecs; > + xfs_extlen_t rval; > + > + maxrecs = limits[0]; > + for (level = 0, rval = 0; len > 0; level++) { len is unsigned, so len > 0 is kind of pointless. Perhaps check len > 1 and kill the check in the loop? Brian > + len += maxrecs - 1; > + do_div(len, maxrecs); > + rval += len; > + if (len == 1) > + return rval; > + if (level == 0) > + maxrecs = limits[1]; > + } > + return rval; > +} > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index 9a88839..b330f19 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -475,4 +475,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block) > bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp); > bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); > > +xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > + unsigned long long len); > + > #endif /* __XFS_BTREE_H__ */ > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Mon Jun 20 09:32:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8A2E07CA4 for ; Mon, 20 Jun 2016 09:32:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 249D5AC002 for ; Mon, 20 Jun 2016 07:32:02 -0700 (PDT) X-ASG-Debug-ID: 1466433121-04bdf01e171475d0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id il3MhwIUXQuFL7Hm (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 07:32:01 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 02BAADB02F; Mon, 20 Jun 2016 14:32:01 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KEW03Q013692; Mon, 20 Jun 2016 10:32:00 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 6C8A9123469; Mon, 20 Jun 2016 10:31:59 -0400 (EDT) Date: Mon, 20 Jun 2016 10:31:59 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 011/119] xfs: refactor btree maxlevels computation Message-ID: <20160620143158.GB2465@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 011/119] xfs: refactor btree maxlevels computation References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612634260.12839.10495592169777117935.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612634260.12839.10495592169777117935.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 20 Jun 2016 14:32:01 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466433121 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4546 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:02PM -0700, Darrick J. Wong wrote: > Create a common function to calculate the maximum height of a per-AG > btree. This will eventually be used by the rmapbt and refcountbt code > to calculate appropriate maxlevels values for each. This is important > because the verifiers and the transaction block reservations depend on > accurate estimates of many blocks are needed to satisfy a btree split. how many > > We were mistakenly using the max bnobt height for all the btrees, > which creates a dangerous situation since the larger records and keys > in an rmapbt make it very possible that the rmapbt will be taller than > the bnobt and so we can run out of transaction block reservation. > > Signed-off-by: Darrick J. Wong > --- Reviewed-by: Brian Foster > fs/xfs/libxfs/xfs_alloc.c | 15 ++------------- > fs/xfs/libxfs/xfs_btree.c | 19 +++++++++++++++++++ > fs/xfs/libxfs/xfs_btree.h | 2 ++ > fs/xfs/libxfs/xfs_ialloc.c | 19 +++++-------------- > 4 files changed, 28 insertions(+), 27 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c > index 1c76a0e..c366889 100644 > --- a/fs/xfs/libxfs/xfs_alloc.c > +++ b/fs/xfs/libxfs/xfs_alloc.c > @@ -1839,19 +1839,8 @@ void > xfs_alloc_compute_maxlevels( > xfs_mount_t *mp) /* file system mount structure */ > { > - int level; > - uint maxblocks; > - uint maxleafents; > - int minleafrecs; > - int minnoderecs; > - > - maxleafents = (mp->m_sb.sb_agblocks + 1) / 2; > - minleafrecs = mp->m_alloc_mnr[0]; > - minnoderecs = mp->m_alloc_mnr[1]; > - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; > - for (level = 1; maxblocks > 1; level++) > - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; > - mp->m_ag_maxlevels = level; > + mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr, > + (mp->m_sb.sb_agblocks + 1) / 2); > } > > /* > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 5eb4e40..046fbcf 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -4158,6 +4158,25 @@ xfs_btree_sblock_verify( > } > > /* > + * Calculate the number of btree levels needed to store a given number of > + * records in a short-format btree. > + */ > +uint > +xfs_btree_compute_maxlevels( > + struct xfs_mount *mp, > + uint *limits, > + unsigned long len) > +{ > + uint level; > + unsigned long maxblocks; > + > + maxblocks = (len + limits[0] - 1) / limits[0]; > + for (level = 1; maxblocks > 1; level++) > + maxblocks = (maxblocks + limits[1] - 1) / limits[1]; > + return level; > +} > + > +/* > * Calculate the number of blocks needed to store a given number of records > * in a short-format (per-AG metadata) btree. > */ > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index b330f19..b955e5d 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -477,5 +477,7 @@ bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); > > xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > unsigned long long len); > +uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, > + unsigned long len); > > #endif /* __XFS_BTREE_H__ */ > diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c > index 9d0003c..cda7269 100644 > --- a/fs/xfs/libxfs/xfs_ialloc.c > +++ b/fs/xfs/libxfs/xfs_ialloc.c > @@ -2394,20 +2394,11 @@ void > xfs_ialloc_compute_maxlevels( > xfs_mount_t *mp) /* file system mount structure */ > { > - int level; > - uint maxblocks; > - uint maxleafents; > - int minleafrecs; > - int minnoderecs; > - > - maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >> > - XFS_INODES_PER_CHUNK_LOG; > - minleafrecs = mp->m_inobt_mnr[0]; > - minnoderecs = mp->m_inobt_mnr[1]; > - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; > - for (level = 1; maxblocks > 1; level++) > - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; > - mp->m_in_maxlevels = level; > + uint inodes; > + > + inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG; > + mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr, > + inodes); > } > > /* > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Mon Jun 20 11:52:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 40DA47CA1 for ; Mon, 20 Jun 2016 11:52:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id AFC62AC001 for ; Mon, 20 Jun 2016 09:52:45 -0700 (PDT) X-ASG-Debug-ID: 1466441564-04cb6c5425ebf50001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 4p6bqeRtaMOQtVO2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 09:52:44 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 03BBBB5398 for ; Mon, 20 Jun 2016 16:52:44 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KGqh2U023008 for ; Mon, 20 Jun 2016 12:52:43 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 48666123469; Mon, 20 Jun 2016 12:52:42 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH 0/2] xfsprogs/db: fix up broken multi-record inode chunk support Date: Mon, 20 Jun 2016 12:52:40 -0400 X-ASG-Orig-Subj: [PATCH 0/2] xfsprogs/db: fix up broken multi-record inode chunk support Message-Id: <1466441562-12317-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Mon, 20 Jun 2016 16:52:44 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466441564 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2086 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 xfs_db/xfs_check doesn't currently handle filesystems with multi-record inode chunks correctly. For example, do the following on a 64k page size arch such as ppc64: # mkfs.xfs -f -b size=64k # xfs_db -c check bad magic number 0 for inode 1152 bad magic number 0 for inode 1153 bad magic number 0 for inode 1154 bad magic number 0 for inode 1155 bad magic number 0 for inode 1156 bad magic number 0 for inode 1157 ... This boils down to a regression in the inode record processing code (scanfunc_ino()) in db/check.c. Specifically, the cblocks value can end up being zero after it is shifted by mp->m_sb.sb_inopblog (i.e., 64 >> 7 == 0 for an -isize=512 -bsize=64k fs). The xfs_check sparse inode processing code takes a unique approach from similar code in other areas such as metadump and repair. This was sufficiently confusing for me that I decided to start with a revert of the patch that introduced the regression and follow up with a patch that updates the inode record processing code to take a similar approach as used in metadump, for example. This approach processes inode chunks a cluster at a time on sparse inode enabled filesystems and skips the regions that are sparse according to the record holemask. The two patches could probably be squashed into one if that is desired, but I'm posting separately as it describes my workflow. This survives my testing thus far on sparse inode filesystems as well as multi-record chunk configurations. These multi-rec configurations don't exactly have a high test pass rate ;P but I haven't hit any regressions. BTW, I have noticed that xfs_check seems to also have memory issues with quotas on multi-inode-rec fs', but that seems to go much farther back and may just be a limitation of check. Brian Brian Foster (2): Revert "xfs_db: make check work for sparse inodes" xfs_check: process sparse inode chunks correctly db/check.c | 274 +++++++++++++++++++++---------------------------------------- 1 file changed, 92 insertions(+), 182 deletions(-) -- 2.5.5 From bfoster@redhat.com Mon Jun 20 11:52:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C7E677CA3 for ; Mon, 20 Jun 2016 11:52:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 42DECAC004 for ; Mon, 20 Jun 2016 09:52:46 -0700 (PDT) X-ASG-Debug-ID: 1466441564-04cb6c5424ebf50001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id jwHQqaXtqmKDLTIO (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 09:52:44 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0C2CAC05FBD0 for ; Mon, 20 Jun 2016 16:52:44 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KGqhsq024839 for ; Mon, 20 Jun 2016 12:52:43 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 5F86B123632; Mon, 20 Jun 2016 12:52:42 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Date: Mon, 20 Jun 2016 12:52:42 -0400 X-ASG-Orig-Subj: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Message-Id: <1466441562-12317-3-git-send-email-bfoster@redhat.com> In-Reply-To: <1466441562-12317-1-git-send-email-bfoster@redhat.com> References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 20 Jun 2016 16:52:44 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466441564 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7198 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Update the inode btree scanning functions to process sparse inode chunks correctly. For filesystems with sparse inode support enabled, process each chunk a cluster at a time. Each cluster is checked against the inobt record to determine if it is a hole and skipped if so. Note that since xfs_check is deprecated in favor of xfs_repair, this adds the minimum support necessary to process sparse inode enabled filesystems. In other words, this adds no sparse inode specific checks or verifications. We only update the inobt scanning functions to extend the existing level of verification to sparse inode enabled filesystems (e.g., avoid incorrectly tracking sparse regions as inodes). Problems or corruptions associated with sparse inode records must be detected and recovered via xfs_repair. Signed-off-by: Brian Foster --- db/check.c | 143 +++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 41 deletions(-) diff --git a/db/check.c b/db/check.c index 750ecc1..25146e5 100644 --- a/db/check.c +++ b/db/check.c @@ -4324,10 +4324,24 @@ scanfunc_ino( int i; int isfree; int j; + int freecount; int nfree; int off; xfs_inobt_ptr_t *pp; xfs_inobt_rec_t *rp; + xfs_agblock_t agbno; + xfs_agblock_t end_agbno; + struct xfs_dinode *dip; + int blks_per_buf; + int inodes_per_buf; + int ioff; + + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) + blks_per_buf = xfs_icluster_size_fsb(mp); + else + blks_per_buf = mp->m_ialloc_blks; + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, + XFS_INODES_PER_CHUNK); if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC && be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) { @@ -4357,54 +4371,74 @@ scanfunc_ino( rp = XFS_INOBT_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { agino = be32_to_cpu(rp[i].ir_startino); - off = XFS_INO_TO_OFFSET(mp, agino); + agbno = XFS_AGINO_TO_AGBNO(mp, agino); + off = XFS_AGINO_TO_OFFSET(mp, agino); + end_agbno = agbno + mp->m_ialloc_blks; if (off == 0) { if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && mp->m_sb.sb_inoalignmt && (XFS_INO_TO_AGBNO(mp, agino) % mp->m_sb.sb_inoalignmt)) sbversion &= ~XFS_SB_VERSION_ALIGNBIT; - set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), - (xfs_extlen_t)MAX(1, - XFS_INODES_PER_CHUNK >> - mp->m_sb.sb_inopblog), - DBM_INODE, seqno, bno); } - icount += XFS_INODES_PER_CHUNK; - agicount += XFS_INODES_PER_CHUNK; - ifree += be32_to_cpu(rp[i].ir_u.f.ir_freecount); - agifreecount += be32_to_cpu(rp[i].ir_u.f.ir_freecount); + push_cur(); - set_cur(&typtab[TYP_INODE], - XFS_AGB_TO_DADDR(mp, seqno, - XFS_AGINO_TO_AGBNO(mp, agino)), - (int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks), - DB_RING_IGN, NULL); - if (iocur_top->data == NULL) { - if (!sflag) - dbprintf(_("can't read inode block " - "%u/%u\n"), - seqno, - XFS_AGINO_TO_AGBNO(mp, agino)); - error++; - pop_cur(); - continue; - } - for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; j++) { - isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j); - if (isfree) - nfree++; - process_inode(agf, agino + j, - (xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)), - isfree); + + ioff = 0; + nfree = 0; + while (agbno < end_agbno && + ioff < XFS_INODES_PER_CHUNK) { + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) + goto next_buf; + + if (off < XFS_INODES_PER_CHUNK) + set_dbmap(seqno, agbno, blks_per_buf, + DBM_INODE, seqno, bno); + + icount += inodes_per_buf; + agicount += inodes_per_buf; + + set_cur(&typtab[TYP_INODE], + XFS_AGB_TO_DADDR(mp, seqno, agbno), + XFS_FSB_TO_BB(mp, blks_per_buf), + DB_RING_IGN, NULL); + if (iocur_top->data == NULL) { + if (!sflag) + dbprintf(_("can't read inode block " + "%u/%u\n"), seqno, + agbno); + error++; + goto next_buf; + } + + for (j = 0; j < inodes_per_buf; j++) { + isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], ioff + j); + if (isfree) + nfree++; + dip = (xfs_dinode_t *)((char *)iocur_top->data + + ((off + j) << mp->m_sb.sb_inodelog)); + process_inode(agf, agino + ioff + j, dip, isfree); + } + +next_buf: + agbno += blks_per_buf; + ioff += inodes_per_buf; } - if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) { + + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) + freecount = rp[i].ir_u.sp.ir_freecount; + else + freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount); + + ifree += freecount; + agifreecount += freecount; + + if (nfree != freecount) { if (!sflag) dbprintf(_("ir_freecount/free mismatch, " "inode chunk %u/%u, freecount " "%d nfree %d\n"), - seqno, agino, - be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree); + seqno, agino, freecount, nfree); error++; } pop_cur(); @@ -4439,6 +4473,18 @@ scanfunc_fino( int off; xfs_inobt_ptr_t *pp; struct xfs_inobt_rec *rp; + xfs_agblock_t agbno; + xfs_agblock_t end_agbno; + int blks_per_buf; + int inodes_per_buf; + int ioff; + + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) + blks_per_buf = xfs_icluster_size_fsb(mp); + else + blks_per_buf = mp->m_ialloc_blks; + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, + XFS_INODES_PER_CHUNK); if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC && be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) { @@ -4468,19 +4514,34 @@ scanfunc_fino( rp = XFS_INOBT_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { agino = be32_to_cpu(rp[i].ir_startino); - off = XFS_INO_TO_OFFSET(mp, agino); + agbno = XFS_AGINO_TO_AGBNO(mp, agino); + off = XFS_AGINO_TO_OFFSET(mp, agino); + end_agbno = agbno + mp->m_ialloc_blks; if (off == 0) { if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && mp->m_sb.sb_inoalignmt && (XFS_INO_TO_AGBNO(mp, agino) % mp->m_sb.sb_inoalignmt)) sbversion &= ~XFS_SB_VERSION_ALIGNBIT; - check_set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), - (xfs_extlen_t)MAX(1, - XFS_INODES_PER_CHUNK >> - mp->m_sb.sb_inopblog), - DBM_INODE, DBM_INODE, seqno, bno); } + + ioff = 0; + while (agbno < end_agbno && + ioff < XFS_INODES_PER_CHUNK) { + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) + goto next_buf; + + check_set_dbmap(seqno, agbno, + (xfs_extlen_t)MAX(1, + inodes_per_buf >> + mp->m_sb.sb_inopblog), + DBM_INODE, DBM_INODE, seqno, bno); + +next_buf: + agbno += blks_per_buf; + ioff += inodes_per_buf; + } + } return; } -- 2.5.5 From bfoster@redhat.com Mon Jun 20 11:52:49 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 96C227CB1 for ; Mon, 20 Jun 2016 11:52:49 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 49F1A304032 for ; Mon, 20 Jun 2016 09:52:46 -0700 (PDT) X-ASG-Debug-ID: 1466441564-04bdf01e171518b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id CpPrjtAlkThOPQr0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 09:52:44 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1C80DC05FBD5 for ; Mon, 20 Jun 2016 16:52:44 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KGqhbr024837 for ; Mon, 20 Jun 2016 12:52:43 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 551511201C2; Mon, 20 Jun 2016 12:52:42 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH 1/2] Revert "xfs_db: make check work for sparse inodes" Date: Mon, 20 Jun 2016 12:52:41 -0400 X-ASG-Orig-Subj: [PATCH 1/2] Revert "xfs_db: make check work for sparse inodes" Message-Id: <1466441562-12317-2-git-send-email-bfoster@redhat.com> In-Reply-To: <1466441562-12317-1-git-send-email-bfoster@redhat.com> References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Mon, 20 Jun 2016 16:52:44 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466441564 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9147 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 This reverts commit bb2f98b78f20f4abbfbbd442162d9f535c84888a. Signed-off-by: Brian Foster --- db/check.c | 249 ++++++++++++------------------------------------------------- 1 file changed, 49 insertions(+), 200 deletions(-) diff --git a/db/check.c b/db/check.c index 0871ed7..750ecc1 100644 --- a/db/check.c +++ b/db/check.c @@ -4311,51 +4311,6 @@ scanfunc_cnt( scan_sbtree(agf, be32_to_cpu(pp[i]), level, 0, scanfunc_cnt, TYP_CNTBT); } -static bool -ino_issparse( - struct xfs_inobt_rec *rp, - int offset) -{ - if (!xfs_sb_version_hassparseinodes(&mp->m_sb)) - return false; - - return xfs_inobt_is_sparse_disk(rp, offset); -} - -static int -find_one_ino_bit( - __u16 mask, - int startino) -{ - int n; - int b; - - startino /= XFS_INODES_PER_HOLEMASK_BIT; - b = startino; - mask >>= startino; - for (n = startino; n < sizeof(mask) * NBBY && !(mask & 1); n++, mask >>= 1) - b++; - - return b * XFS_INODES_PER_HOLEMASK_BIT; -} - -static int -find_zero_ino_bit( - __u16 mask, - int startino) -{ - int n; - int b; - - startino /= XFS_INODES_PER_HOLEMASK_BIT; - b = startino; - mask >>= startino; - for (n = startino; n < sizeof(mask) * NBBY && (mask & 1); n++, mask >>= 1) - b++; - - return b * XFS_INODES_PER_HOLEMASK_BIT; -} - static void scanfunc_ino( struct xfs_btree_block *block, @@ -4373,13 +4328,6 @@ scanfunc_ino( int off; xfs_inobt_ptr_t *pp; xfs_inobt_rec_t *rp; - bool sparse, crc; - int inodes_per_chunk; - int freecount; - int startidx, endidx; - __u16 holemask; - xfs_agino_t rino; - xfs_extlen_t cblocks; if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC && be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) { @@ -4407,111 +4355,59 @@ scanfunc_ino( return; } rp = XFS_INOBT_REC_ADDR(mp, block, 1); - sparse = xfs_sb_version_hassparseinodes(&mp->m_sb); - crc = xfs_sb_version_hascrc(&mp->m_sb); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { - nfree = 0; - - /* First let's look at the inode chunk alignment */ agino = be32_to_cpu(rp[i].ir_startino); off = XFS_INO_TO_OFFSET(mp, agino); - if (off == 0 && - (sbversion & XFS_SB_VERSION_ALIGNBIT) && - mp->m_sb.sb_inoalignmt && - (XFS_INO_TO_AGBNO(mp, agino) % - mp->m_sb.sb_inoalignmt)) { - if (sparse || crc) { - dbprintf(_("incorrect record %u/%u " - "alignment in inobt block " - "%u/%u\n"), - seqno, agino, seqno, bno); - error++; - } else + if (off == 0) { + if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && + mp->m_sb.sb_inoalignmt && + (XFS_INO_TO_AGBNO(mp, agino) % + mp->m_sb.sb_inoalignmt)) sbversion &= ~XFS_SB_VERSION_ALIGNBIT; + set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), + (xfs_extlen_t)MAX(1, + XFS_INODES_PER_CHUNK >> + mp->m_sb.sb_inopblog), + DBM_INODE, seqno, bno); } - - /* Move on to examining the inode chunks */ - if (sparse) { - inodes_per_chunk = rp[i].ir_u.sp.ir_count; - freecount = rp[i].ir_u.sp.ir_freecount; - holemask = be16_to_cpu(rp[i].ir_u.sp.ir_holemask); - startidx = find_zero_ino_bit(holemask, 0); - } else { - inodes_per_chunk = XFS_INODES_PER_CHUNK; - freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount); - holemask = 0; - startidx = 0; - } - - /* For each allocated chunk, look at each inode. */ - endidx = find_one_ino_bit(holemask, startidx); - do { - rino = agino + startidx; - cblocks = (endidx - startidx) >> - mp->m_sb.sb_inopblog; - - /* Check the sparse chunk alignment */ - if (sparse && - (XFS_INO_TO_AGBNO(mp, rino) % - mp->m_sb.sb_spino_align)) { - dbprintf(_("incorrect chunk %u/%u " - "alignment in inobt block " + icount += XFS_INODES_PER_CHUNK; + agicount += XFS_INODES_PER_CHUNK; + ifree += be32_to_cpu(rp[i].ir_u.f.ir_freecount); + agifreecount += be32_to_cpu(rp[i].ir_u.f.ir_freecount); + push_cur(); + set_cur(&typtab[TYP_INODE], + XFS_AGB_TO_DADDR(mp, seqno, + XFS_AGINO_TO_AGBNO(mp, agino)), + (int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks), + DB_RING_IGN, NULL); + if (iocur_top->data == NULL) { + if (!sflag) + dbprintf(_("can't read inode block " "%u/%u\n"), - seqno, rino, seqno, bno); - error++; - } - - /* Check the block map */ - set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, rino), - cblocks, DBM_INODE, seqno, bno); - - push_cur(); - set_cur(&typtab[TYP_INODE], - XFS_AGB_TO_DADDR(mp, seqno, - XFS_AGINO_TO_AGBNO(mp, rino)), - (int)XFS_FSB_TO_BB(mp, cblocks), - DB_RING_IGN, NULL); - if (iocur_top->data == NULL) { - if (!sflag) - dbprintf(_("can't read inode block " - "%u/%u\n"), - seqno, - XFS_AGINO_TO_AGBNO(mp, agino)); - error++; - pop_cur(); - continue; - } - - /* Examine each inode in this chunk */ - for (j = startidx; j < endidx; j++) { - if (ino_issparse(&rp[i], j)) - continue; - isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j); - if (isfree) - nfree++; - process_inode(agf, agino + j, - (xfs_dinode_t *)((char *)iocur_top->data + ((j - startidx) << mp->m_sb.sb_inodelog)), - isfree); - } + seqno, + XFS_AGINO_TO_AGBNO(mp, agino)); + error++; pop_cur(); - - startidx = find_zero_ino_bit(holemask, endidx); - endidx = find_one_ino_bit(holemask, startidx); - } while (endidx < XFS_INODES_PER_CHUNK); - icount += inodes_per_chunk; - agicount += inodes_per_chunk; - ifree += freecount; - agifreecount += freecount; - - if (nfree != freecount) { + continue; + } + for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; j++) { + isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j); + if (isfree) + nfree++; + process_inode(agf, agino + j, + (xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)), + isfree); + } + if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) { if (!sflag) dbprintf(_("ir_freecount/free mismatch, " "inode chunk %u/%u, freecount " "%d nfree %d\n"), seqno, agino, - freecount, nfree); + be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree); error++; } + pop_cur(); } return; } @@ -4543,11 +4439,6 @@ scanfunc_fino( int off; xfs_inobt_ptr_t *pp; struct xfs_inobt_rec *rp; - bool sparse, crc; - int startidx, endidx; - __u16 holemask; - xfs_agino_t rino; - xfs_extlen_t cblocks; if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC && be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) { @@ -4575,63 +4466,21 @@ scanfunc_fino( return; } rp = XFS_INOBT_REC_ADDR(mp, block, 1); - sparse = xfs_sb_version_hassparseinodes(&mp->m_sb); - crc = xfs_sb_version_hascrc(&mp->m_sb); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { - /* First let's look at the inode chunk alignment */ agino = be32_to_cpu(rp[i].ir_startino); off = XFS_INO_TO_OFFSET(mp, agino); - if (off == 0 && - (sbversion & XFS_SB_VERSION_ALIGNBIT) && - mp->m_sb.sb_inoalignmt && - (XFS_INO_TO_AGBNO(mp, agino) % - mp->m_sb.sb_inoalignmt)) { - if (sparse || crc) { - dbprintf(_("incorrect record %u/%u " - "alignment in finobt block " - "%u/%u\n"), - seqno, agino, seqno, bno); - error++; - } else + if (off == 0) { + if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && + mp->m_sb.sb_inoalignmt && + (XFS_INO_TO_AGBNO(mp, agino) % + mp->m_sb.sb_inoalignmt)) sbversion &= ~XFS_SB_VERSION_ALIGNBIT; + check_set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), + (xfs_extlen_t)MAX(1, + XFS_INODES_PER_CHUNK >> + mp->m_sb.sb_inopblog), + DBM_INODE, DBM_INODE, seqno, bno); } - - /* Move on to examining the inode chunks */ - if (sparse) { - holemask = be16_to_cpu(rp[i].ir_u.sp.ir_holemask); - startidx = find_zero_ino_bit(holemask, 0); - } else { - holemask = 0; - startidx = 0; - } - - /* For each allocated chunk... */ - endidx = find_one_ino_bit(holemask, startidx); - do { - rino = agino + startidx; - cblocks = (endidx - startidx) >> - mp->m_sb.sb_inopblog; - - /* Check the sparse chunk alignment */ - if (sparse && - (XFS_INO_TO_AGBNO(mp, rino) % - mp->m_sb.sb_spino_align)) { - dbprintf(_("incorrect chunk %u/%u " - "alignment in finobt block " - "%u/%u\n"), - seqno, rino, seqno, bno); - error++; - } - - /* Check the block map */ - check_set_dbmap(seqno, - XFS_AGINO_TO_AGBNO(mp, rino), - cblocks, DBM_INODE, DBM_INODE, - seqno, bno); - - startidx = find_zero_ino_bit(holemask, endidx); - endidx = find_one_ino_bit(holemask, startidx); - } while (endidx < XFS_INODES_PER_CHUNK); } return; } -- 2.5.5 From bfoster@redhat.com Mon Jun 20 12:12:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0D4577CA3 for ; Mon, 20 Jun 2016 12:12:08 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id D38348F8040 for ; Mon, 20 Jun 2016 10:12:07 -0700 (PDT) X-ASG-Debug-ID: 1466442726-04cbb01fed12d890001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id nvE1DNysLEDmT9yn (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 10:12:06 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0C4B3DF203 for ; Mon, 20 Jun 2016 17:12:06 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KHC5VP028225 for ; Mon, 20 Jun 2016 13:12:05 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 40BE5123755; Mon, 20 Jun 2016 13:12:04 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH v2 1/3] xfs: create helper to delete multiple inobt records Date: Mon, 20 Jun 2016 13:12:02 -0400 X-ASG-Orig-Subj: [PATCH v2 1/3] xfs: create helper to delete multiple inobt records Message-Id: <1466442724-13544-2-git-send-email-bfoster@redhat.com> In-Reply-To: <1466442724-13544-1-git-send-email-bfoster@redhat.com> References: <1466442724-13544-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Mon, 20 Jun 2016 17:12:06 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466442726 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3816 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 In most cases an inode chunk is tracked by a single inode record. With large block size support up to 64k, however, XFS supports conditions where a single block might be large enough to allocate an inode chunk that requires multiple inobt records. For example, an inode record is fixed at 64 inodes. With a 64k block size, a 512b inode size results in 128-inode chunks and thus requires 2 inobt records per-chunk. This is handled appropriately at inode allocation time via insertion of multiple inobt records to span the chunk. We currently have no mechanism to delete multiple records nor broader chunk context for a particular record at inode deletion time. Therefore, inode chunks on such filesystems are never freed and result in non-recoverable space consumption for the lifetime of the filesystem. Create the xfs_inobt_delete() helper to remove several inobt records at a time. Call the helper from the appropriate locations instead of xfs_btree_delete(). Note that we still do not have the requisite chunk context at inode deletion time to delete multiple records and therefore can still only delete records that map to full chunks. This patch does not alter current behavior but provides a mechanism to be used by future work that provides the appropriate chunk context. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_ialloc.c | 56 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 22297f9..67a4f3f 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -200,6 +200,53 @@ xfs_inobt_insert( } /* + * Delete a series of records from the inode btree. Handle multiple records as + * an inode chunk might consist of more than one record for large block sizes. + */ +static int +xfs_inobt_delete( + struct xfs_mount *mp, + struct xfs_btree_cur *cur, + xfs_agnumber_t agno, + xfs_agino_t agino, + int ilen) +{ + struct xfs_inobt_rec_incore rec; + int error; + int i; + + ASSERT(ilen % XFS_INODES_PER_CHUNK == 0); + + while (ilen > 0) { + error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_EQ, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + /* make sure the record is what we expect */ + error = xfs_inobt_get_rec(cur, &rec, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + XFS_WANT_CORRUPTED_GOTO(mp, rec.ir_startino == agino, + out_error); + + error = xfs_btree_delete(cur, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + agino += XFS_INODES_PER_CHUNK; + ilen -= XFS_INODES_PER_CHUNK; + } + + return 0; + +out_error: + return error; +} + +/* * Verify that the number of free inodes in the AGI is correct. */ #ifdef DEBUG @@ -1971,8 +2018,10 @@ xfs_difree_inobt( xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen); xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1)); - if ((error = xfs_btree_delete(cur, &i))) { - xfs_warn(mp, "%s: xfs_btree_delete returned error %d.", + error = xfs_inobt_delete(mp, cur, agno, rec.ir_startino, + XFS_INODES_PER_CHUNK); + if (error) { + xfs_warn(mp, "%s: xfs_inobt_delete returned error %d.", __func__, error); goto error0; } @@ -2089,7 +2138,8 @@ xfs_difree_finobt( if (rec.ir_free == XFS_INOBT_ALL_FREE && mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK && !(mp->m_flags & XFS_MOUNT_IKEEP)) { - error = xfs_btree_delete(cur, &i); + error = xfs_inobt_delete(mp, cur, agno, rec.ir_startino, + XFS_INODES_PER_CHUNK); if (error) goto error; ASSERT(i == 1); -- 2.5.5 From bfoster@redhat.com Mon Jun 20 12:12:10 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A88AE7CAF for ; Mon, 20 Jun 2016 12:12:10 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 67FC98F8037 for ; Mon, 20 Jun 2016 10:12:07 -0700 (PDT) X-ASG-Debug-ID: 1466442725-04bdf01e13152410001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 9rIxVUgyCuoR5W3R (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 10:12:06 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C80332D2F0A for ; Mon, 20 Jun 2016 17:12:05 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KHC5UT007093 for ; Mon, 20 Jun 2016 13:12:05 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 1FB4F123469; Mon, 20 Jun 2016 13:12:04 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH v2 0/3] xfs: support removal of multi-record inode chunks Date: Mon, 20 Jun 2016 13:12:01 -0400 X-ASG-Orig-Subj: [PATCH v2 0/3] xfs: support removal of multi-record inode chunks Message-Id: <1466442724-13544-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 20 Jun 2016 17:12:05 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466442726 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 962 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Hi all, This is an old series I'm dusting off that helps extend XFS' typical dynamic inode chunk behavior to large block size filesystems. While XFS currently supports such large block sizes, we don't ever remove inode records on filesystems with a block size large enough such that a single block covers more than one inode chunk. This has been tested on ppc64 with a 64k block size and on other arches (x86-64, i386) with more standard 4k blocksize configurations. Brian v2: - Rebase to latest for-next. v1: http://oss.sgi.com/pipermail/xfs/2015-May/041814.html Brian Foster (3): xfs: create helper to delete multiple inobt records xfs: remove entire inode chunks when all inodes are free xfs: inobt record insert/delete tracepoints fs/xfs/libxfs/xfs_ialloc.c | 270 +++++++++++++++++++++++++++++++++++++++++---- fs/xfs/xfs_trace.h | 32 ++++++ 2 files changed, 281 insertions(+), 21 deletions(-) -- 2.5.5 From bfoster@redhat.com Mon Jun 20 12:12:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0E8747CB1 for ; Mon, 20 Jun 2016 12:12:11 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id C3D35304048 for ; Mon, 20 Jun 2016 10:12:10 -0700 (PDT) X-ASG-Debug-ID: 1466442726-04cb6c5425ec7b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id p4pHsfo6gDQDmrp9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 10:12:06 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 0B0E9A1288 for ; Mon, 20 Jun 2016 17:12:06 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KHC5LA009623 for ; Mon, 20 Jun 2016 13:12:05 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 4D6DD123632; Mon, 20 Jun 2016 13:12:04 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH v2 3/3] xfs: inobt record insert/delete tracepoints Date: Mon, 20 Jun 2016 13:12:04 -0400 X-ASG-Orig-Subj: [PATCH v2 3/3] xfs: inobt record insert/delete tracepoints Message-Id: <1466442724-13544-4-git-send-email-bfoster@redhat.com> In-Reply-To: <1466442724-13544-1-git-send-email-bfoster@redhat.com> References: <1466442724-13544-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.27]); Mon, 20 Jun 2016 17:12:06 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466442726 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3742 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Add tracepoints for inobt record insert and delete. Be sure to distinguish between the inobt and finobt in the tracepoints as the record lifecycles differ between the trees. Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_ialloc.c | 16 +++++++++++++--- fs/xfs/xfs_trace.h | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index fdaeee8..114b020 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -186,6 +186,8 @@ xfs_inobt_insert( } ASSERT(i == 0); + trace_xfs_irec_insert(mp, btnum, agno, thisino, + XFS_INODES_PER_CHUNK); error = xfs_inobt_insert_rec(cur, XFS_INOBT_HOLEMASK_FULL, XFS_INODES_PER_CHUNK, XFS_INODES_PER_CHUNK, @@ -234,6 +236,8 @@ xfs_inobt_delete( XFS_WANT_CORRUPTED_GOTO(mp, rec.ir_startino == agino, out_error); + trace_xfs_irec_delete(mp, cur->bc_btnum, agno, rec.ir_startino, + rec.ir_count); error = xfs_btree_delete(cur, &i); if (error) goto out_error; @@ -729,6 +733,8 @@ xfs_inobt_insert_sprec( goto error; /* if nothing there, insert a new record and return */ if (i == 0) { + trace_xfs_irec_insert(mp, btnum, agno, nrec->ir_startino, + nrec->ir_count); error = xfs_inobt_insert_rec(cur, nrec->ir_holemask, nrec->ir_count, nrec->ir_freecount, nrec->ir_free, &i); @@ -1789,10 +1795,13 @@ xfs_dialloc_ag( */ rec.ir_free &= ~XFS_INOBT_MASK(offset); rec.ir_freecount--; - if (rec.ir_freecount) + if (rec.ir_freecount) { error = xfs_inobt_update(cur, &rec); - else + } else { + trace_xfs_irec_delete(mp, cur->bc_btnum, agno, rec.ir_startino, + rec.ir_count); error = xfs_btree_delete(cur, &i); + } if (error) goto error_cur; @@ -2261,7 +2270,8 @@ xfs_difree_finobt( * something is out of sync. */ XFS_WANT_CORRUPTED_GOTO(mp, ibtrec->ir_freecount == 1, error); - + trace_xfs_irec_insert(mp, cur->bc_btnum, agno, + ibtrec->ir_startino, ibtrec->ir_count); error = xfs_inobt_insert_rec(cur, ibtrec->ir_holemask, ibtrec->ir_count, ibtrec->ir_freecount, diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index ea94ee0..3e27cdc 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -786,6 +786,38 @@ TRACE_EVENT(xfs_irec_merge_post, __entry->holemask) ) +DECLARE_EVENT_CLASS(xfs_irec_class, + TP_PROTO(struct xfs_mount *mp, xfs_btnum_t btnum, xfs_agnumber_t agno, + xfs_agino_t agino, int count), + TP_ARGS(mp, btnum, agno, agino, count), + TP_STRUCT__entry( + __field(dev_t, dev) + __field(xfs_btnum_t, btnum) + __field(xfs_agnumber_t, agno) + __field(xfs_agino_t, agino) + __field(int, count) + ), + TP_fast_assign( + __entry->dev = mp->m_super->s_dev; + __entry->btnum = btnum; + __entry->agno = agno; + __entry->agino = agino; + __entry->count = count; + ), + TP_printk("dev %d:%d %s agno %d agino 0x%x count %d", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->btnum == XFS_BTNUM_INOi ? "ibt" : "fibt", + __entry->agno, __entry->agino, __entry->count) +) + +#define DEFINE_IREC_EVENT(name) \ +DEFINE_EVENT(xfs_irec_class, name, \ + TP_PROTO(struct xfs_mount *mp, xfs_btnum_t btnum, xfs_agnumber_t agno, \ + xfs_agino_t agino, int count), \ + TP_ARGS(mp, btnum, agno, agino, count)) +DEFINE_IREC_EVENT(xfs_irec_insert); +DEFINE_IREC_EVENT(xfs_irec_delete); + #define DEFINE_IREF_EVENT(name) \ DEFINE_EVENT(xfs_iref_class, name, \ TP_PROTO(struct xfs_inode *ip, unsigned long caller_ip), \ -- 2.5.5 From bfoster@redhat.com Mon Jun 20 12:12:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7554F7CAF for ; Mon, 20 Jun 2016 12:12:11 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 49F118F8040 for ; Mon, 20 Jun 2016 10:12:11 -0700 (PDT) X-ASG-Debug-ID: 1466442726-04cb6c5426ec7b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id HlU6bcqxB2BA6xCt (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 10:12:06 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id ED12AD5715 for ; Mon, 20 Jun 2016 17:12:05 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-179.bos.redhat.com [10.18.41.179]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5KHC5UE030976 for ; Mon, 20 Jun 2016 13:12:05 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 3023D1201C2; Mon, 20 Jun 2016 13:12:04 -0400 (EDT) From: Brian Foster To: xfs@oss.sgi.com Subject: [PATCH v2 2/3] xfs: remove entire inode chunks when all inodes are free Date: Mon, 20 Jun 2016 13:12:03 -0400 X-ASG-Orig-Subj: [PATCH v2 2/3] xfs: remove entire inode chunks when all inodes are free Message-Id: <1466442724-13544-3-git-send-email-bfoster@redhat.com> In-Reply-To: <1466442724-13544-1-git-send-email-bfoster@redhat.com> References: <1466442724-13544-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 20 Jun 2016 17:12:05 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466442726 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10525 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Inode chunks are typically removed when the last allocated inode tracked by the inobt record is freed. However, this only occurs under circumstances where a chunk is tracked by a single inobt record because only the context for the single record is available at the time an inode is freed. Add infrastructure to detect whether the overall chunk that happens to own a particular inobt record is free. The xfs_inobt_ischunkfree() helper first considers the more likely single-record-per-chunk case to avoid unnecessary overhead. Otherwise, it uses the xfs_inobt_peek() low level helper to tally the total real and free inode count over a set of records that map to a chunk. If the entire chunk is free, the starting agino of the chunk is returned. We can remove multiple inobt records of a chunk now that chunk free state is available. Update the xfs_inobt_delete() callers to free an entire chunk at a time based on the variable inode allocation count in the mount structure. Note that this is safe from a transaction standpoint due to the same reasoning that multiple inode record insertion is safe from xfs_inobt_insert(). Specifically, the transaction reservation covers enough for a single bottom-to-top tree split or merge. We can safely insert or remove ~50% of an inobt leaf block's worth of records under this reservation and the maximum possible ratio of inode records to inode chunks is 4:1 (i.e., maximum 64k block size with minimum 256b inode size). Signed-off-by: Brian Foster --- fs/xfs/libxfs/xfs_ialloc.c | 206 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 187 insertions(+), 19 deletions(-) diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index 67a4f3f..fdaeee8 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -40,6 +40,9 @@ #include "xfs_trace.h" #include "xfs_log.h" +STATIC int +xfs_ialloc_next_rec(struct xfs_btree_cur *, struct xfs_inobt_rec_incore *, + int *, int); /* * Allocation group level functions. @@ -247,6 +250,155 @@ out_error: } /* + * Peek forward in the provided inobt cursor and sum up the real and free inode + * counts. The returned count covers the range of [agino,agino+len). Absent + * records do not affect the count. + */ +static int +xfs_inobt_peek( + struct xfs_mount *mp, + struct xfs_btree_cur *cur, + xfs_agino_t agino, /* start agino */ + int ilen, /* range length */ + int *count, /* out: inode count */ + int *freecount) /* out: free count */ +{ + struct xfs_inobt_rec_incore rec; + xfs_agino_t agino_end; + int error; + int i; + + ASSERT(ilen % XFS_INODES_PER_CHUNK == 0); + agino_end = agino + ilen; + *count = *freecount = 0; + + /* + * Look up the first at or beyond the start of the range. Note that + * records for legitimate inode chunks might not exist if we're looking + * at the finobt. + */ + error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_GE, &i); + if (error) + goto out_error; + if (i == 0) + return 0; + + error = xfs_inobt_get_rec(cur, &rec, &i); + if (error) + goto out_error; + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); + + /* + * Sum the real and free inode counts across all records in the range. + */ + while (rec.ir_startino < agino_end) { + *count += rec.ir_count; + *freecount += rec.ir_freecount; + + error = xfs_ialloc_next_rec(cur, &rec, &i, 0); + if (error) + goto out_error; + if (i) /* done */ + break; + } + + return 0; + +out_error: + return error; +} + +/* + * Determine whether an inode chunk covered by a particular inobt record is + * free. This handles large block size cases where the inode chunk requires + * multiple inobt records by mapping from the inode offset of the first inode in + * the provided record to the record with inode offset 0 in the chunk. From + * there we determine whether each record in the chunk is completely free. + * + * An in-core record of the chunk to check is passed in rec. Any record that + * covers a portion of the chunk is suitable. The in-core record must be + * modified in advance if an inode is being freed. The expected free inode count + * for a free chunk is passed in icount. This is generally mp->m_ialloc_inos, + * but the caller must account for when an inode to be freed is not yet + * reflected as such in the inobt. + * + * If the chunk is free, the starting agino of the chunk is returned in + * freeagino. Otherwise, freeagino is set to NULLAGINO. + */ +static int +xfs_inobt_ischunkfree( + struct xfs_mount *mp, + struct xfs_btree_cur *ocur, + struct xfs_inobt_rec_incore *rec, + int icount,/* icount for free chunk */ + xfs_agino_t *freeagino)/* out: first free agino */ +{ + struct xfs_btree_cur *cur; + xfs_agino_t agino; + xfs_agblock_t agbno; + int count; + int freecount; + int error; + + ASSERT(icount <= mp->m_ialloc_inos); + + *freeagino = NULLAGINO; + + /* if the record isn't free, the chunk certainly isn't */ + if (rec->ir_free != XFS_INOBT_ALL_FREE) + return 0; + + /* + * The record is free so if the chunk corresponds to a single record, it + * is free as well. + */ + if (mp->m_ialloc_inos == XFS_INODES_PER_CHUNK) { + ASSERT(rec->ir_free == XFS_INOBT_ALL_FREE); + *freeagino = rec->ir_startino; + return 0; + } + + /* + * A chunk corresponds to multiple inobt records. This typically occurs + * for large block sizes where a single block of inodes requires + * multiple records. + * + * Get the record that is aligned to the start of the block and verify + * whether all inodes across the chunk are free. Dup the cursor so we + * don't affect the caller's inobt update operation in progress and sum + * the free inodes across the chunk. + */ + ASSERT(mp->m_ialloc_inos > XFS_INODES_PER_CHUNK); + error = xfs_btree_dup_cursor(ocur, &cur); + if (error) + return error; + + /* get the agblock and the inode at offset 0 */ + agbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); + agino = XFS_OFFBNO_TO_AGINO(mp, agbno, 0); + + error = xfs_inobt_peek(mp, cur, agino, mp->m_ialloc_inos, &count, + &freecount); + if (error) + goto out_cur; + + /* + * Check the free inode count against the count that indicates a free + * chunk. Sparse records are irrelevant in this context since this is a + * single block allocation. + */ + if (freecount == icount) + *freeagino = agino; + + xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR); + return 0; + +out_cur: + xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); + return error; +} + +/* * Verify that the number of free inodes in the AGI is correct. */ #ifdef DEBUG @@ -1950,6 +2102,7 @@ xfs_difree_inobt( int error; int i; int off; + xfs_agino_t freeagino; ASSERT(agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC)); ASSERT(XFS_AGINO_TO_AGBNO(mp, agino) < be32_to_cpu(agi->agi_length)); @@ -1992,23 +2145,38 @@ xfs_difree_inobt( rec.ir_freecount++; /* - * When an inode chunk is free, it becomes eligible for removal. Don't - * remove the chunk if the block size is large enough for multiple inode - * chunks (that might not be free). + * An inode chunk becomes eligible for removal when it is free. Check + * whether this chunk is free while taking into consideration that the + * chunk might consist of multiple records. + * + * Note that the free chunk inode count parameter must account for the + * fact that this inode has not yet been freed in the inobt's... */ - if (!(mp->m_flags & XFS_MOUNT_IKEEP) && - rec.ir_free == XFS_INOBT_ALL_FREE && - mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK) { + error = xfs_inobt_ischunkfree(mp, cur, &rec, mp->m_ialloc_inos - 1, + &freeagino); + if (error) + goto error0; + + if (!(mp->m_flags & XFS_MOUNT_IKEEP) && freeagino != NULLAGINO) { xic->deleted = 1; - xic->first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino); + xic->first_ino = XFS_AGINO_TO_INO(mp, agno, freeagino); xic->alloc = xfs_inobt_irec_to_allocmask(&rec); /* + * Use the freecount if the record is sparse. Otherwise use the + * chunk inode allocation count as the chunk could be larger + * than a single record. + */ + if (xfs_inobt_issparse(rec.ir_holemask)) + ilen = rec.ir_freecount; + else + ilen = mp->m_ialloc_inos; + + /* * Remove the inode cluster from the AGI B+Tree, adjust the * AGI and Superblock inode counts, and mark the disk space * to be freed when the transaction is committed. */ - ilen = rec.ir_freecount; be32_add_cpu(&agi->agi_count, -ilen); be32_add_cpu(&agi->agi_freecount, -(ilen - 1)); xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT); @@ -2018,8 +2186,8 @@ xfs_difree_inobt( xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen); xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1)); - error = xfs_inobt_delete(mp, cur, agno, rec.ir_startino, - XFS_INODES_PER_CHUNK); + error = xfs_inobt_delete(mp, cur, agno, freeagino, + mp->m_ialloc_inos); if (error) { xfs_warn(mp, "%s: xfs_inobt_delete returned error %d.", __func__, error); @@ -2079,6 +2247,7 @@ xfs_difree_finobt( int offset = agino - ibtrec->ir_startino; int error; int i; + xfs_agino_t freeagino; cur = xfs_inobt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_FINO); @@ -2130,16 +2299,15 @@ xfs_difree_finobt( * free inode. Hence, if all of the inodes are free and we aren't * keeping inode chunks permanently on disk, remove the record. * Otherwise, update the record with the new information. - * - * Note that we currently can't free chunks when the block size is large - * enough for multiple chunks. Leave the finobt record to remain in sync - * with the inobt. */ - if (rec.ir_free == XFS_INOBT_ALL_FREE && - mp->m_sb.sb_inopblock <= XFS_INODES_PER_CHUNK && - !(mp->m_flags & XFS_MOUNT_IKEEP)) { - error = xfs_inobt_delete(mp, cur, agno, rec.ir_startino, - XFS_INODES_PER_CHUNK); + error = xfs_inobt_ischunkfree(mp, cur, &rec, mp->m_ialloc_inos - 1, + &freeagino); + if (error) + goto error; + + if (!(mp->m_flags & XFS_MOUNT_IKEEP) && freeagino != NULLAGINO) { + error = xfs_inobt_delete(mp, cur, agno, freeagino, + mp->m_ialloc_inos); if (error) goto error; ASSERT(i == 1); -- 2.5.5 From darrick.wong@oracle.com Mon Jun 20 13:23:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9F8977CA3 for ; Mon, 20 Jun 2016 13:23:29 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 72978304032 for ; Mon, 20 Jun 2016 11:23:26 -0700 (PDT) X-ASG-Debug-ID: 1466447003-04cb6c5425eeab0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id X4adREbH9BB3pjrW (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 11:23:23 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5KINKQK030013 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 20 Jun 2016 18:23:20 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5KINJq5010625 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 20 Jun 2016 18:23:20 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5KINILP016810; Mon, 20 Jun 2016 18:23:19 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 20 Jun 2016 11:23:18 -0700 Date: Mon, 20 Jun 2016 11:23:16 -0700 From: "Darrick J. Wong" To: Brian Foster Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 011/119] xfs: refactor btree maxlevels computation Message-ID: <20160620182316.GA29055@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 011/119] xfs: refactor btree maxlevels computation References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612634260.12839.10495592169777117935.stgit@birch.djwong.org> <20160620143158.GB2465@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620143158.GB2465@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466447003 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4923 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30600 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 20, 2016 at 10:31:59AM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:19:02PM -0700, Darrick J. Wong wrote: > > Create a common function to calculate the maximum height of a per-AG > > btree. This will eventually be used by the rmapbt and refcountbt code > > to calculate appropriate maxlevels values for each. This is important > > because the verifiers and the transaction block reservations depend on > > accurate estimates of many blocks are needed to satisfy a btree split. > > how many Got it, will change for the next posting. --D > > > > > We were mistakenly using the max bnobt height for all the btrees, > > which creates a dangerous situation since the larger records and keys > > in an rmapbt make it very possible that the rmapbt will be taller than > > the bnobt and so we can run out of transaction block reservation. > > > > Signed-off-by: Darrick J. Wong > > --- > > Reviewed-by: Brian Foster > > > fs/xfs/libxfs/xfs_alloc.c | 15 ++------------- > > fs/xfs/libxfs/xfs_btree.c | 19 +++++++++++++++++++ > > fs/xfs/libxfs/xfs_btree.h | 2 ++ > > fs/xfs/libxfs/xfs_ialloc.c | 19 +++++-------------- > > 4 files changed, 28 insertions(+), 27 deletions(-) > > > > > > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c > > index 1c76a0e..c366889 100644 > > --- a/fs/xfs/libxfs/xfs_alloc.c > > +++ b/fs/xfs/libxfs/xfs_alloc.c > > @@ -1839,19 +1839,8 @@ void > > xfs_alloc_compute_maxlevels( > > xfs_mount_t *mp) /* file system mount structure */ > > { > > - int level; > > - uint maxblocks; > > - uint maxleafents; > > - int minleafrecs; > > - int minnoderecs; > > - > > - maxleafents = (mp->m_sb.sb_agblocks + 1) / 2; > > - minleafrecs = mp->m_alloc_mnr[0]; > > - minnoderecs = mp->m_alloc_mnr[1]; > > - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; > > - for (level = 1; maxblocks > 1; level++) > > - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; > > - mp->m_ag_maxlevels = level; > > + mp->m_ag_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_alloc_mnr, > > + (mp->m_sb.sb_agblocks + 1) / 2); > > } > > > > /* > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > index 5eb4e40..046fbcf 100644 > > --- a/fs/xfs/libxfs/xfs_btree.c > > +++ b/fs/xfs/libxfs/xfs_btree.c > > @@ -4158,6 +4158,25 @@ xfs_btree_sblock_verify( > > } > > > > /* > > + * Calculate the number of btree levels needed to store a given number of > > + * records in a short-format btree. > > + */ > > +uint > > +xfs_btree_compute_maxlevels( > > + struct xfs_mount *mp, > > + uint *limits, > > + unsigned long len) > > +{ > > + uint level; > > + unsigned long maxblocks; > > + > > + maxblocks = (len + limits[0] - 1) / limits[0]; > > + for (level = 1; maxblocks > 1; level++) > > + maxblocks = (maxblocks + limits[1] - 1) / limits[1]; > > + return level; > > +} > > + > > +/* > > * Calculate the number of blocks needed to store a given number of records > > * in a short-format (per-AG metadata) btree. > > */ > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > index b330f19..b955e5d 100644 > > --- a/fs/xfs/libxfs/xfs_btree.h > > +++ b/fs/xfs/libxfs/xfs_btree.h > > @@ -477,5 +477,7 @@ bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); > > > > xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > > unsigned long long len); > > +uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, > > + unsigned long len); > > > > #endif /* __XFS_BTREE_H__ */ > > diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c > > index 9d0003c..cda7269 100644 > > --- a/fs/xfs/libxfs/xfs_ialloc.c > > +++ b/fs/xfs/libxfs/xfs_ialloc.c > > @@ -2394,20 +2394,11 @@ void > > xfs_ialloc_compute_maxlevels( > > xfs_mount_t *mp) /* file system mount structure */ > > { > > - int level; > > - uint maxblocks; > > - uint maxleafents; > > - int minleafrecs; > > - int minnoderecs; > > - > > - maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >> > > - XFS_INODES_PER_CHUNK_LOG; > > - minleafrecs = mp->m_inobt_mnr[0]; > > - minnoderecs = mp->m_inobt_mnr[1]; > > - maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs; > > - for (level = 1; maxblocks > 1; level++) > > - maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs; > > - mp->m_in_maxlevels = level; > > + uint inodes; > > + > > + inodes = (1LL << XFS_INO_AGINO_BITS(mp)) >> XFS_INODES_PER_CHUNK_LOG; > > + mp->m_in_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_inobt_mnr, > > + inodes); > > } > > > > /* > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From vishal.l.verma@intel.com Mon Jun 20 13:48:52 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9A0497CA1 for ; Mon, 20 Jun 2016 13:48:52 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5C32D8F8037 for ; Mon, 20 Jun 2016 11:48:49 -0700 (PDT) X-ASG-Debug-ID: 1466448528-04bdf01e15156aa0001-NocioJ Received: from mga11.intel.com ([192.55.52.93]) by cuda.sgi.com with ESMTP id n7ROS310f2nhu5Tb for ; Mon, 20 Jun 2016 11:48:48 -0700 (PDT) X-Barracuda-Envelope-From: vishal.l.verma@intel.com X-Barracuda-Effective-Source-IP: UNKNOWN[192.55.52.93] X-Barracuda-Apparent-Source-IP: 192.55.52.93 X-ASG-Whitelist: Client Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga102.fm.intel.com with ESMTP; 20 Jun 2016 11:48:48 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,499,1459839600"; d="scan'208";a="722417695" Received: from omniknight.lm.intel.com ([10.232.112.171]) by FMSMGA003.fm.intel.com with ESMTP; 20 Jun 2016 11:48:47 -0700 Date: Mon, 20 Jun 2016 12:48:27 -0600 From: Vishal Verma To: linux-nvdimm@lists.01.org, xfs@oss.sgi.com Cc: Dave Chinner , Jan Kara , "Darrick J. Wong" Subject: Re: [RFC PATCH 0/2] Initial support for badblock checking in xfs Message-ID: <20160620184812.GA21878@omniknight.lm.intel.com> X-ASG-Orig-Subj: Re: [RFC PATCH 0/2] Initial support for badblock checking in xfs References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Barracuda-Connect: UNKNOWN[192.55.52.93] X-Barracuda-Start-Time: 1466448528 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3319 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On 06/16, Vishal Verma wrote: > These are early/RFC patches to add badblock support in xfs. > > Patch 1 should be relatively straightforward - it adds a notifier chain > to badblocks that filesystems can register with. > > Patch 2 is the beginnings of xfs support. So far, I have the notifier > registration and building the initial badblock list happening in > xfs_mountfs. The next steps (and I may need some help with this as I'm > no (x)fs developer :)) are to add this badblocks info to the reverse > mapping tree, and then to check for it before accessing the media. > > Right now, this just prints the sector numbers/counts/{added, removed} > to the kernel log, for both the initial list, and subsequent notifier > hits. > > While I've tested this with a fake pmem device using libnvdimm's > nfit_test framework, it should also work using badblock injection with > any block device: > > # mkfs.xfs -f /dev/ > # echo 122 1 > /sys/block//badblocks > # echo 124 1 > /sys/block//badblocks > # mount -t xfs /dev/ /mnt > ... in log: > [ +8.803776] XFS (pmem7): Mounting V4 Filesystem > [ +0.009633] XFS (pmem7): Ending clean mount > [ +0.001655] XFS (pmem7): got badblocks: sector 122, count 1 > [ +0.002018] XFS (pmem7): got badblocks: sector 124, count 1 > > # echo 132 5 | > /sys/block//badblocks > [Jun16 18:56] XFS (pmem7): xfs badblock added sector 132 (count 5) > > This is all based on Darrik's rmap work at: > https://github.com/djwong/linux/tree/rmap-reflink-devel > > Since this is based on a v4.5-rc kernel, it lacks pmem support for > clearing badblocks on zeroing/writing, so those parts can't easily > be tested yet. The clearing work is in 4.7-rs kernels, and once we > rebase to that, that should also be available. Just fyi, These patches should also cleanly apply to Darrick's for-next rebase: https://github.com/djwong/linux/tree/djwong-devel With this, I can now test badblock clearing also: $ cat /sys/block/pmem7/badblocks 122 1 124 1 126 1 128 1 $ sudo dd if=/dev/zero of=/dev/pmem7 bs=512 count=8 seek=120 oflag=direct 8+0 records in 8+0 records out 4096 bytes (4.1 kB) copied, 0.0206735 s, 198 kB/s [ +9.510106] nd_pmem namespace7.0: pmem_clear_poison: 78 clear 1 sector [ +0.001827] XFS (pmem7): xfs badblock cleared sector 120 (count 1) [ +0.002772] nd_pmem namespace7.0: pmem_clear_poison: 7a clear 1 sector [ +0.002527] XFS (pmem7): xfs badblock cleared sector 122 (count 1) [ +0.003004] nd_pmem namespace7.0: pmem_clear_poison: 7c clear 1 sector [ +0.002215] XFS (pmem7): xfs badblock cleared sector 124 (count 1) [ +0.003063] nd_pmem namespace7.0: pmem_clear_poison: 7e clear 1 sector [ +0.002307] XFS (pmem7): xfs badblock cleared sector 126 (count 1) > > > Vishal Verma (2): > block, badblocks: add a notifier for badblocks > xfs: initial/partial support for badblocks > > block/badblocks.c | 79 +++++++++++++++++++++++++++++++++-- > fs/xfs/xfs_linux.h | 1 + > fs/xfs/xfs_mount.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/xfs_mount.h | 1 + > include/linux/badblocks.h | 19 +++++++++ > 5 files changed, 201 insertions(+), 3 deletions(-) > > -- > 2.5.5 > From darrick.wong@oracle.com Mon Jun 20 14:34:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E3E127CA1 for ; Mon, 20 Jun 2016 14:34:51 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id B7F93304039 for ; Mon, 20 Jun 2016 12:34:48 -0700 (PDT) X-ASG-Debug-ID: 1466451286-04cbb01fec1333f0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id UCeMnFPRWQAPg8ps (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Mon, 20 Jun 2016 12:34:47 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5KJYeZS013223 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 20 Jun 2016 19:34:41 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5KJYeab024971 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 20 Jun 2016 19:34:40 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5KJYY6f021613; Mon, 20 Jun 2016 19:34:39 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 20 Jun 2016 12:34:34 -0700 Date: Mon, 20 Jun 2016 12:34:32 -0700 From: "Darrick J. Wong" To: Brian Foster Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 010/119] xfs: create a standard btree size calculator code Message-ID: <20160620193432.GB29055@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 010/119] xfs: create a standard btree size calculator code References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612633632.12839.13314497569643567486.stgit@birch.djwong.org> <20160620143148.GA2465@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620143148.GA2465@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466451286 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3124 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30601 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 20, 2016 at 10:31:49AM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:18:56PM -0700, Darrick J. Wong wrote: > > Create a helper to generate AG btree height calculator functions. > > This will be used (much) later when we get to the refcount btree. > > > > v2: Use a helper function instead of a macro. > > v3: We can (theoretically) store more than 2^32 records in a btree, so > > widen the fields to accept that. > > v4: Don't modify xfs_bmap_worst_indlen; the purpose of /that/ function > > is to estimate the worst-case number of blocks needed for a bmbt > > expansion, not to calculate the space required to store nr records. > > > > Signed-off-by: Darrick J. Wong > > --- > > I think this one should probably be pushed out to where it is used > (easier to review with an example imo). I don't see it used anywhere up > through the rmapbt stuff, anyways... Oh, heh, you're right. At one point I was using it for the rmapbt, but nowadays it's only used for per-AG reservations (reflink+rmap) as you point out, so it could move. > > > fs/xfs/libxfs/xfs_btree.c | 27 +++++++++++++++++++++++++++ > > fs/xfs/libxfs/xfs_btree.h | 3 +++ > > 2 files changed, 30 insertions(+) > > > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > index 105979d..5eb4e40 100644 > > --- a/fs/xfs/libxfs/xfs_btree.c > > +++ b/fs/xfs/libxfs/xfs_btree.c > > @@ -4156,3 +4156,30 @@ xfs_btree_sblock_verify( > > > > return true; > > } > > + > > +/* > > + * Calculate the number of blocks needed to store a given number of records > > + * in a short-format (per-AG metadata) btree. > > + */ > > +xfs_extlen_t > > +xfs_btree_calc_size( > > + struct xfs_mount *mp, > > + uint *limits, > > + unsigned long long len) > > +{ > > + int level; > > + int maxrecs; > > + xfs_extlen_t rval; > > + > > + maxrecs = limits[0]; > > + for (level = 0, rval = 0; len > 0; level++) { > > len is unsigned, so len > 0 is kind of pointless. Perhaps check len > 1 > and kill the check in the loop? Yup. Thank you for pointing that out. --D > > Brian > > > + len += maxrecs - 1; > > + do_div(len, maxrecs); > > + rval += len; > > + if (len == 1) > > + return rval; > > + if (level == 0) > > + maxrecs = limits[1]; > > + } > > + return rval; > > +} > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > index 9a88839..b330f19 100644 > > --- a/fs/xfs/libxfs/xfs_btree.h > > +++ b/fs/xfs/libxfs/xfs_btree.h > > @@ -475,4 +475,7 @@ static inline int xfs_btree_get_level(struct xfs_btree_block *block) > > bool xfs_btree_sblock_v5hdr_verify(struct xfs_buf *bp); > > bool xfs_btree_sblock_verify(struct xfs_buf *bp, unsigned int max_recs); > > > > +xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > > + unsigned long long len); > > + > > #endif /* __XFS_BTREE_H__ */ > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From david@fromorbit.com Mon Jun 20 18:19:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3C6F57CA0 for ; Mon, 20 Jun 2016 18:19:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id AB8A6AC004 for ; Mon, 20 Jun 2016 16:18:59 -0700 (PDT) X-ASG-Debug-ID: 1466464709-04cbb01fed13d610001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id jPCZPzcAwZGKqdDN for ; Mon, 20 Jun 2016 16:18:30 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CfEgDDeGhXEJgMLHlcgz6BU4Zvny8BAQEBAQEGjDiGBoQJhhEEAgKBME0BAQEBAQEHAQEBAQEBAQE+QIRLAQEBAwE6HCMQCAMYCSUPBSUDBxoTiCgHwVgBCyUehUGFFYobBZh2jiCPLEiPL4RWKjKKSAEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 21 Jun 2016 08:48:05 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bF8SC-0006vJ-I3; Tue, 21 Jun 2016 09:18:04 +1000 Date: Tue, 21 Jun 2016 09:18:04 +1000 From: Dave Chinner To: Felix Janda Cc: xfs@oss.sgi.com Subject: Re: [PATCH 1/4] Remove off64_t from linux.h Message-ID: <20160620231804.GK26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 1/4] Remove off64_t from linux.h References: <20160618145238.GA17768@nyan> <20160620020414.GH26977@dastard> <20160620065348.GA431@nyan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620065348.GA431@nyan> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466464709 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1656 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30610 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Mon, Jun 20, 2016 at 08:53:48AM +0200, Felix Janda wrote: > Dave Chinner wrote: > > Thanks for asking for clarification. > > > On Sat, Jun 18, 2016 at 04:52:38PM +0200, Felix Janda wrote: > > > The off64_t type is usually only conditionally exposed under the > > > feature test macro _LARGEFILE64_SOURCE (also defined by _GNU_SOURCE). > > > To make the public xfs headers more standalone therefore off64_t should > > > be avoided. > > > > "more standalone"? > > > > What does that mean? > > Programs including the xfs headers while not defining _GNU_SOURCE or > _LARGEFILE64_SOURCE will not fail with compile errors. My previous > patch changing loff_t to off64_t had the unintented consequences that > downstreams of xfs-progs like ceph had to define _LARGEFILE64_SOURCE > on linux. That needs to be in the patch description - it's the motivation for the change (i.e. that downstream apps need to add new defines). > > And what does it mean for all the xfsprogs code that still uses > > off64_t? > > off_t and off64_t are now synomyms and 64 bit on all architectures. > So no difference for code using off64_t. > > Under some conditions there can be a difference for code using > off_t. Right, I understand that there is a difference - what I'm asking for is a description of the difference and an explanation of why: $ git grep off64_t | wc -l 62 $ the other ~60 uses of off64_t in the xfsprogs code are not being removed, too. i.e. if the code now won't compile if off_t isn't 64 bits, then why keep off64_t at all in any of the code? Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Mon Jun 20 19:47:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 266897CA4 for ; Mon, 20 Jun 2016 19:47:42 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 95821AC001 for ; Mon, 20 Jun 2016 17:47:38 -0700 (PDT) X-ASG-Debug-ID: 1466470053-04cbb01fed141b70001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id 2nBMjmLsVm8B1U7e for ; Mon, 20 Jun 2016 17:47:34 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2A2EgDkjWhXEJgMLHlUCIM+gVOGb58vAQEBAQEHjDiGBoQJhhEEAgKBNE0BAQEBAQEHAQEBAQEBAQE+QIRMAQEEOhwjEAgDDgoJJQ8FJQMHGhOIL8FQAQEIAiUehUGFFYE5gmWFfQWYdo4gjyyPd4JpgW0qMopIAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 21 Jun 2016 10:17:33 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bF9qm-00073m-1P; Tue, 21 Jun 2016 10:47:32 +1000 Date: Tue, 21 Jun 2016 10:47:32 +1000 From: Dave Chinner To: Christoph Hellwig Cc: "Darrick J. Wong" , linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 004/119] xfs: enable buffer deadlock postmortem diagnosis via ftrace Message-ID: <20160621004731.GL26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 004/119] xfs: enable buffer deadlock postmortem diagnosis via ftrace References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612629822.12839.7938642541078923297.stgit@birch.djwong.org> <20160617113423.GC19042@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617113423.GC19042@infradead.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466470053 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 847 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30612 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 17, 2016 at 04:34:23AM -0700, Christoph Hellwig wrote: > > diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c > > index efa2a73..2333db7 100644 > > --- a/fs/xfs/xfs_buf.c > > +++ b/fs/xfs/xfs_buf.c > > @@ -947,7 +947,8 @@ xfs_buf_trylock( > > if (locked) > > XB_SET_OWNER(bp); > > > > - trace_xfs_buf_trylock(bp, _RET_IP_); > > + locked ? trace_xfs_buf_trylock(bp, _RET_IP_) : > > + trace_xfs_buf_trylock_fail(bp, _RET_IP_); > > return locked; > > I think this should be something like: > > if (locked) { > XB_SET_OWNER(bp); > trace_xfs_buf_trylock(bp, _RET_IP_); > } else { > trace_xfs_buf_trylock_fail(bp, _RET_IP_); > } > > otherwise this looks good and can go in without the rest of the series. I'll fix that up on commit. Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Mon Jun 20 19:48:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id AC7CD7CA4 for ; Mon, 20 Jun 2016 19:48:34 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 48697AC001 for ; Mon, 20 Jun 2016 17:48:34 -0700 (PDT) X-ASG-Debug-ID: 1466470111-04bdf01e10163d30001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id QXwm5r1n2cuEgvuD for ; Mon, 20 Jun 2016 17:48:32 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2A2EgDkjWhXEJgMLHlcgz6BU4Zvny8BAQEBAQeMOIYGhAmGEQQCAoE0TQEBAQEBAQcBAQEBAQEBAT5AhEwBAQQnExwjEAgDDgoJJQ8FJQMHGhOIL8FQAQEIAiUehUGFFYE5iGIBBJh2jiCPLI93gmmBbSoyikgBAQE Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 21 Jun 2016 10:18:31 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bF9ri-00073x-JP; Tue, 21 Jun 2016 10:48:30 +1000 Date: Tue, 21 Jun 2016 10:48:30 +1000 From: Dave Chinner To: Christoph Hellwig Cc: "Darrick J. Wong" , linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 008/119] xfs: separate freelist fixing into a separate helper Message-ID: <20160621004830.GM26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 008/119] xfs: separate freelist fixing into a separate helper References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612632363.12839.15504324533944246285.stgit@birch.djwong.org> <20160617115204.GG19042@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617115204.GG19042@infradead.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466470111 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 992 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30613 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 17, 2016 at 04:52:04AM -0700, Christoph Hellwig wrote: > > +/* Ensure that the freelist is at full capacity. */ > > +int > > +xfs_free_extent_fix_freelist( > > + struct xfs_trans *tp, > > + xfs_agnumber_t agno, > > + struct xfs_buf **agbp) > > { > > - xfs_alloc_arg_t args; > > - int error; > > + xfs_alloc_arg_t args; > > Use struct xfs_alloc_arg if you change this anyway. > > > + int error; > > > > - ASSERT(len != 0); > > memset(&args, 0, sizeof(xfs_alloc_arg_t)); > > Same here. > > > - if (args.agbno + len > > > - be32_to_cpu(XFS_BUF_TO_AGF(args.agbp)->agf_length)) { > > - error = -EFSCORRUPTED; > > - goto error0; > > - } > > + XFS_WANT_CORRUPTED_GOTO(mp, > > + agbno + len <= be32_to_cpu(XFS_BUF_TO_AGF(agbp)->agf_length), > > + err); > > This introduces an overly long line. > > But except for these nitpicks this looks fine: I'll clean them up on commit. -Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Mon Jun 20 19:57:20 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 7DB8D7CA7 for ; Mon, 20 Jun 2016 19:57:20 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 301A2304032 for ; Mon, 20 Jun 2016 17:57:17 -0700 (PDT) X-ASG-Debug-ID: 1466470634-04bdf01e101641d0001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id I935urc9xf6yP5jy for ; Mon, 20 Jun 2016 17:57:14 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2A1EgA9kGhXEJgMLHlcgz6BU4Zvny8BAQEBAQeMOIYGhAmGEQQCAoE0TQEBAQEBAQcBAQEBAQEBAT5AhEwBAQQnExwjEAgDGAklDwUlAwcaE4gvwU8BAQgCJR6FQYQSgQOBOYhiBZh2iH6FIoFzhFKIZ493gmmBbSoyikgBAQE Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 21 Jun 2016 10:27:13 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFA08-00075J-Vk; Tue, 21 Jun 2016 10:57:13 +1000 Date: Tue, 21 Jun 2016 10:57:12 +1000 From: Dave Chinner To: "Darrick J. Wong" Cc: Christoph Hellwig , linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 009/119] xfs: convert list of extents to free into a regular list Message-ID: <20160621005712.GN26977@dastard> X-ASG-Orig-Subj: Re: [PATCH 009/119] xfs: convert list of extents to free into a regular list References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612632997.12839.18026491074892368053.stgit@birch.djwong.org> <20160617115930.GH19042@infradead.org> <20160618201509.GA5042@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160618201509.GA5042@birch.djwong.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466470634 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1714 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30614 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Sat, Jun 18, 2016 at 01:15:10PM -0700, Darrick J. Wong wrote: > On Fri, Jun 17, 2016 at 04:59:30AM -0700, Christoph Hellwig wrote: > > > { > > > + struct xfs_bmap_free_item *new; /* new element */ > > > #ifdef DEBUG > > > xfs_agnumber_t agno; > > > xfs_agblock_t agbno; > > > @@ -597,17 +595,7 @@ xfs_bmap_add_free( > > > new = kmem_zone_alloc(xfs_bmap_free_item_zone, KM_SLEEP); > > > new->xbfi_startblock = bno; > > > new->xbfi_blockcount = (xfs_extlen_t)len; > > > + list_add(&new->xbfi_list, &flist->xbf_flist); > > > flist->xbf_count++; > > > > Please kill xbf_count while you're at it, it's entirely superflous. > > The deferred ops conversion patch kills this off by moving the whole > "defer an op to the next transaction by logging redo items" logic > into a separate file and mechanism. > > This patch is just a cleanup to reduce some of the open coded list ugliness > before starting on the rmap stuff. Once the deferred ops code lands, all > three of these functions go away. Ok, so because all these functions go away, I'll take this patch now without the suggested cleanups so that you don't have to rework it. .... > > > + list_sort((*tp)->t_mountp, &flist->xbf_flist, xfs_bmap_free_list_cmp); > > > > Can you add a comment on why we are sorting the list? > > We sort the list so that we process the freed extents in AG order to > avoid deadlocking. > > I'll add a comment to the deferred ops code if there isn't one already. This seems best - add the clean up to the later patches rather than have to rework lots of patches because of minor mods to early patches... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Mon Jun 20 20:41:19 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 147D87CA4 for ; Mon, 20 Jun 2016 20:41:19 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id D87308F8037 for ; Mon, 20 Jun 2016 18:41:18 -0700 (PDT) X-ASG-Debug-ID: 1466473273-04cbb01fec143a40001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id or8xjhhfKL3TXHn8 for ; Mon, 20 Jun 2016 18:41:13 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DpEgCOmmhXEJgMLHlcgz6BU4Zvny8BAQEBAQeMOIYGhAmGEQICAQECgTRNAQEBAQEBBwEBAQEBAQEBPkCESwEBAQQ6HCMQCAMVAwklDwUlAwcaE4gvwUQBAQEBBgIBJB6FQYUVgTmGM4IvBZh2jiCBXY1Pj3eCaYFtKjKKSAEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 21 Jun 2016 11:10:40 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFAgA-00079o-1U; Tue, 21 Jun 2016 11:40:38 +1000 Date: Tue, 21 Jun 2016 11:40:38 +1000 From: Dave Chinner To: "Darrick J. Wong" Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 008/119] xfs: separate freelist fixing into a separate helper Message-ID: <20160621014037.GA27480@dastard> X-ASG-Orig-Subj: Re: [PATCH 008/119] xfs: separate freelist fixing into a separate helper References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612632363.12839.15504324533944246285.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612632363.12839.15504324533944246285.stgit@birch.djwong.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466473273 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 482 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30614 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 16, 2016 at 06:18:43PM -0700, Darrick J. Wong wrote: > From: Dave Chinner > > Break up xfs_free_extent() into a helper that fixes the freelist. > This helper will be used subsequently to ensure the freelist during > deferred rmap processing. > > Signed-off-by: Dave Chinner Just noticed - should be from/sob dchinner@redhat.com. I'll fix this up, too. Cheers, Dave. -- Dave Chinner david@fromorbit.com From cmaiolino@redhat.com Tue Jun 21 04:02:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E553E7CA1 for ; Tue, 21 Jun 2016 04:02:05 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 5106AAC001 for ; Tue, 21 Jun 2016 02:02:05 -0700 (PDT) X-ASG-Debug-ID: 1466499719-04cb6c542610b3d0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id HLJUkFCeUn04wmkX (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 21 Jun 2016 02:02:00 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9301473059 for ; Tue, 21 Jun 2016 09:01:59 +0000 (UTC) Received: from redhat.com (vpn-60-35.rdu2.redhat.com [10.10.60.35]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5L91s3h015473 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 21 Jun 2016 05:01:57 -0400 Date: Tue, 21 Jun 2016 11:01:53 +0200 From: Carlos Maiolino To: Brian Foster Cc: xfs@oss.sgi.com Subject: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Message-ID: <20160621090153.GB28212@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Mail-Followup-To: Brian Foster , xfs@oss.sgi.com References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> <1466441562-12317-3-git-send-email-bfoster@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466441562-12317-3-git-send-email-bfoster@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 21 Jun 2016 09:01:59 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466499720 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8036 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 20, 2016 at 12:52:42PM -0400, Brian Foster wrote: > Update the inode btree scanning functions to process sparse inode chunks > correctly. For filesystems with sparse inode support enabled, process > each chunk a cluster at a time. Each cluster is checked against the > inobt record to determine if it is a hole and skipped if so. > > Note that since xfs_check is deprecated in favor of xfs_repair, this > adds the minimum support necessary to process sparse inode enabled > filesystems. In other words, this adds no sparse inode specific checks > or verifications. We only update the inobt scanning functions to extend > the existing level of verification to sparse inode enabled filesystems > (e.g., avoid incorrectly tracking sparse regions as inodes). Problems > or corruptions associated with sparse inode records must be detected and > recovered via xfs_repair. > Hi, I'm not quite sure, but a while ago, I thought I've heard some rumors about deprecating xfs_check, is this true or something that my mind made up for some weird reason? > Signed-off-by: Brian Foster > --- > db/check.c | 143 +++++++++++++++++++++++++++++++++++++++++++------------------ > 1 file changed, 102 insertions(+), 41 deletions(-) > > diff --git a/db/check.c b/db/check.c > index 750ecc1..25146e5 100644 > --- a/db/check.c > +++ b/db/check.c > @@ -4324,10 +4324,24 @@ scanfunc_ino( > int i; > int isfree; > int j; > + int freecount; > int nfree; > int off; > xfs_inobt_ptr_t *pp; > xfs_inobt_rec_t *rp; > + xfs_agblock_t agbno; > + xfs_agblock_t end_agbno; > + struct xfs_dinode *dip; > + int blks_per_buf; > + int inodes_per_buf; > + int ioff; > + > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > + blks_per_buf = xfs_icluster_size_fsb(mp); > + else > + blks_per_buf = mp->m_ialloc_blks; > + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, > + XFS_INODES_PER_CHUNK); > > if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC && > be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) { > @@ -4357,54 +4371,74 @@ scanfunc_ino( > rp = XFS_INOBT_REC_ADDR(mp, block, 1); > for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { > agino = be32_to_cpu(rp[i].ir_startino); > - off = XFS_INO_TO_OFFSET(mp, agino); > + agbno = XFS_AGINO_TO_AGBNO(mp, agino); > + off = XFS_AGINO_TO_OFFSET(mp, agino); > + end_agbno = agbno + mp->m_ialloc_blks; > if (off == 0) { > if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && > mp->m_sb.sb_inoalignmt && > (XFS_INO_TO_AGBNO(mp, agino) % > mp->m_sb.sb_inoalignmt)) > sbversion &= ~XFS_SB_VERSION_ALIGNBIT; > - set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), > - (xfs_extlen_t)MAX(1, > - XFS_INODES_PER_CHUNK >> > - mp->m_sb.sb_inopblog), > - DBM_INODE, seqno, bno); > } > - icount += XFS_INODES_PER_CHUNK; > - agicount += XFS_INODES_PER_CHUNK; > - ifree += be32_to_cpu(rp[i].ir_u.f.ir_freecount); > - agifreecount += be32_to_cpu(rp[i].ir_u.f.ir_freecount); > + > push_cur(); > - set_cur(&typtab[TYP_INODE], > - XFS_AGB_TO_DADDR(mp, seqno, > - XFS_AGINO_TO_AGBNO(mp, agino)), > - (int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks), > - DB_RING_IGN, NULL); > - if (iocur_top->data == NULL) { > - if (!sflag) > - dbprintf(_("can't read inode block " > - "%u/%u\n"), > - seqno, > - XFS_AGINO_TO_AGBNO(mp, agino)); > - error++; > - pop_cur(); > - continue; > - } > - for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; j++) { > - isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j); > - if (isfree) > - nfree++; > - process_inode(agf, agino + j, > - (xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)), > - isfree); > + > + ioff = 0; > + nfree = 0; > + while (agbno < end_agbno && > + ioff < XFS_INODES_PER_CHUNK) { > + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) > + goto next_buf; > + > + if (off < XFS_INODES_PER_CHUNK) > + set_dbmap(seqno, agbno, blks_per_buf, > + DBM_INODE, seqno, bno); > + > + icount += inodes_per_buf; > + agicount += inodes_per_buf; > + > + set_cur(&typtab[TYP_INODE], > + XFS_AGB_TO_DADDR(mp, seqno, agbno), > + XFS_FSB_TO_BB(mp, blks_per_buf), > + DB_RING_IGN, NULL); > + if (iocur_top->data == NULL) { > + if (!sflag) > + dbprintf(_("can't read inode block " > + "%u/%u\n"), seqno, > + agbno); > + error++; > + goto next_buf; > + } > + > + for (j = 0; j < inodes_per_buf; j++) { > + isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], ioff + j); > + if (isfree) > + nfree++; > + dip = (xfs_dinode_t *)((char *)iocur_top->data + > + ((off + j) << mp->m_sb.sb_inodelog)); > + process_inode(agf, agino + ioff + j, dip, isfree); > + } > + > +next_buf: > + agbno += blks_per_buf; > + ioff += inodes_per_buf; > } > - if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) { > + > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > + freecount = rp[i].ir_u.sp.ir_freecount; > + else > + freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount); > + > + ifree += freecount; > + agifreecount += freecount; > + > + if (nfree != freecount) { > if (!sflag) > dbprintf(_("ir_freecount/free mismatch, " > "inode chunk %u/%u, freecount " > "%d nfree %d\n"), > - seqno, agino, > - be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree); > + seqno, agino, freecount, nfree); > error++; > } > pop_cur(); > @@ -4439,6 +4473,18 @@ scanfunc_fino( > int off; > xfs_inobt_ptr_t *pp; > struct xfs_inobt_rec *rp; > + xfs_agblock_t agbno; > + xfs_agblock_t end_agbno; > + int blks_per_buf; > + int inodes_per_buf; > + int ioff; > + > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > + blks_per_buf = xfs_icluster_size_fsb(mp); > + else > + blks_per_buf = mp->m_ialloc_blks; > + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, > + XFS_INODES_PER_CHUNK); > > if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC && > be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) { > @@ -4468,19 +4514,34 @@ scanfunc_fino( > rp = XFS_INOBT_REC_ADDR(mp, block, 1); > for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { > agino = be32_to_cpu(rp[i].ir_startino); > - off = XFS_INO_TO_OFFSET(mp, agino); > + agbno = XFS_AGINO_TO_AGBNO(mp, agino); > + off = XFS_AGINO_TO_OFFSET(mp, agino); > + end_agbno = agbno + mp->m_ialloc_blks; > if (off == 0) { > if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && > mp->m_sb.sb_inoalignmt && > (XFS_INO_TO_AGBNO(mp, agino) % > mp->m_sb.sb_inoalignmt)) > sbversion &= ~XFS_SB_VERSION_ALIGNBIT; > - check_set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), > - (xfs_extlen_t)MAX(1, > - XFS_INODES_PER_CHUNK >> > - mp->m_sb.sb_inopblog), > - DBM_INODE, DBM_INODE, seqno, bno); > } > + > + ioff = 0; > + while (agbno < end_agbno && > + ioff < XFS_INODES_PER_CHUNK) { > + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) > + goto next_buf; > + > + check_set_dbmap(seqno, agbno, > + (xfs_extlen_t)MAX(1, > + inodes_per_buf >> > + mp->m_sb.sb_inopblog), > + DBM_INODE, DBM_INODE, seqno, bno); > + > +next_buf: > + agbno += blks_per_buf; > + ioff += inodes_per_buf; > + } > + > } > return; > } > -- > 2.5.5 > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From bfoster@redhat.com Tue Jun 21 05:48:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E736E7CA4 for ; Tue, 21 Jun 2016 05:48:22 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id B90AC304039 for ; Tue, 21 Jun 2016 03:48:19 -0700 (PDT) X-ASG-Debug-ID: 1466506097-04cb6c542410ed40001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id HQ13buoEbFn4doAu (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 21 Jun 2016 03:48:18 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 68569D2EC9 for ; Tue, 21 Jun 2016 10:48:17 +0000 (UTC) Received: from laptop.bfoster (dhcp-41-198.bos.redhat.com [10.18.41.198]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5LAmF6h019730 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 21 Jun 2016 06:48:17 -0400 Date: Tue, 21 Jun 2016 06:48:15 -0400 From: Brian Foster To: xfs@oss.sgi.com Subject: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Message-ID: <20160621104815.GA3108@laptop.bfoster> X-ASG-Orig-Subj: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> <1466441562-12317-3-git-send-email-bfoster@redhat.com> <20160621090153.GB28212@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160621090153.GB28212@redhat.com> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 21 Jun 2016 10:48:17 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466506098 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9026 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Tue, Jun 21, 2016 at 11:01:53AM +0200, Carlos Maiolino wrote: > On Mon, Jun 20, 2016 at 12:52:42PM -0400, Brian Foster wrote: > > Update the inode btree scanning functions to process sparse inode chunks > > correctly. For filesystems with sparse inode support enabled, process > > each chunk a cluster at a time. Each cluster is checked against the > > inobt record to determine if it is a hole and skipped if so. > > > > Note that since xfs_check is deprecated in favor of xfs_repair, this > > adds the minimum support necessary to process sparse inode enabled > > filesystems. In other words, this adds no sparse inode specific checks > > or verifications. We only update the inobt scanning functions to extend > > the existing level of verification to sparse inode enabled filesystems > > (e.g., avoid incorrectly tracking sparse regions as inodes). Problems > > or corruptions associated with sparse inode records must be detected and > > recovered via xfs_repair. > > > > Hi, > > I'm not quite sure, but a while ago, I thought I've heard some rumors about > deprecating xfs_check, is this true or something that my mind made up for some > weird reason? > I actually thought it already was. :) xfstests still runs check in certain cases, however, and these patches just fix a regression. Personally, I'd be fine with just dumping an "fs has sparse inodes, use repair" message from xfs_check, but the basic sparse inode support had already been added. Brian > > > Signed-off-by: Brian Foster > > --- > > db/check.c | 143 +++++++++++++++++++++++++++++++++++++++++++------------------ > > 1 file changed, 102 insertions(+), 41 deletions(-) > > > > diff --git a/db/check.c b/db/check.c > > index 750ecc1..25146e5 100644 > > --- a/db/check.c > > +++ b/db/check.c > > @@ -4324,10 +4324,24 @@ scanfunc_ino( > > int i; > > int isfree; > > int j; > > + int freecount; > > int nfree; > > int off; > > xfs_inobt_ptr_t *pp; > > xfs_inobt_rec_t *rp; > > + xfs_agblock_t agbno; > > + xfs_agblock_t end_agbno; > > + struct xfs_dinode *dip; > > + int blks_per_buf; > > + int inodes_per_buf; > > + int ioff; > > + > > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > > + blks_per_buf = xfs_icluster_size_fsb(mp); > > + else > > + blks_per_buf = mp->m_ialloc_blks; > > + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, > > + XFS_INODES_PER_CHUNK); > > > > if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC && > > be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) { > > @@ -4357,54 +4371,74 @@ scanfunc_ino( > > rp = XFS_INOBT_REC_ADDR(mp, block, 1); > > for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { > > agino = be32_to_cpu(rp[i].ir_startino); > > - off = XFS_INO_TO_OFFSET(mp, agino); > > + agbno = XFS_AGINO_TO_AGBNO(mp, agino); > > + off = XFS_AGINO_TO_OFFSET(mp, agino); > > + end_agbno = agbno + mp->m_ialloc_blks; > > if (off == 0) { > > if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && > > mp->m_sb.sb_inoalignmt && > > (XFS_INO_TO_AGBNO(mp, agino) % > > mp->m_sb.sb_inoalignmt)) > > sbversion &= ~XFS_SB_VERSION_ALIGNBIT; > > - set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), > > - (xfs_extlen_t)MAX(1, > > - XFS_INODES_PER_CHUNK >> > > - mp->m_sb.sb_inopblog), > > - DBM_INODE, seqno, bno); > > } > > - icount += XFS_INODES_PER_CHUNK; > > - agicount += XFS_INODES_PER_CHUNK; > > - ifree += be32_to_cpu(rp[i].ir_u.f.ir_freecount); > > - agifreecount += be32_to_cpu(rp[i].ir_u.f.ir_freecount); > > + > > push_cur(); > > - set_cur(&typtab[TYP_INODE], > > - XFS_AGB_TO_DADDR(mp, seqno, > > - XFS_AGINO_TO_AGBNO(mp, agino)), > > - (int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks), > > - DB_RING_IGN, NULL); > > - if (iocur_top->data == NULL) { > > - if (!sflag) > > - dbprintf(_("can't read inode block " > > - "%u/%u\n"), > > - seqno, > > - XFS_AGINO_TO_AGBNO(mp, agino)); > > - error++; > > - pop_cur(); > > - continue; > > - } > > - for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; j++) { > > - isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j); > > - if (isfree) > > - nfree++; > > - process_inode(agf, agino + j, > > - (xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)), > > - isfree); > > + > > + ioff = 0; > > + nfree = 0; > > + while (agbno < end_agbno && > > + ioff < XFS_INODES_PER_CHUNK) { > > + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) > > + goto next_buf; > > + > > + if (off < XFS_INODES_PER_CHUNK) > > + set_dbmap(seqno, agbno, blks_per_buf, > > + DBM_INODE, seqno, bno); > > + > > + icount += inodes_per_buf; > > + agicount += inodes_per_buf; > > + > > + set_cur(&typtab[TYP_INODE], > > + XFS_AGB_TO_DADDR(mp, seqno, agbno), > > + XFS_FSB_TO_BB(mp, blks_per_buf), > > + DB_RING_IGN, NULL); > > + if (iocur_top->data == NULL) { > > + if (!sflag) > > + dbprintf(_("can't read inode block " > > + "%u/%u\n"), seqno, > > + agbno); > > + error++; > > + goto next_buf; > > + } > > + > > + for (j = 0; j < inodes_per_buf; j++) { > > + isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], ioff + j); > > + if (isfree) > > + nfree++; > > + dip = (xfs_dinode_t *)((char *)iocur_top->data + > > + ((off + j) << mp->m_sb.sb_inodelog)); > > + process_inode(agf, agino + ioff + j, dip, isfree); > > + } > > + > > +next_buf: > > + agbno += blks_per_buf; > > + ioff += inodes_per_buf; > > } > > - if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) { > > + > > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > > + freecount = rp[i].ir_u.sp.ir_freecount; > > + else > > + freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount); > > + > > + ifree += freecount; > > + agifreecount += freecount; > > + > > + if (nfree != freecount) { > > if (!sflag) > > dbprintf(_("ir_freecount/free mismatch, " > > "inode chunk %u/%u, freecount " > > "%d nfree %d\n"), > > - seqno, agino, > > - be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree); > > + seqno, agino, freecount, nfree); > > error++; > > } > > pop_cur(); > > @@ -4439,6 +4473,18 @@ scanfunc_fino( > > int off; > > xfs_inobt_ptr_t *pp; > > struct xfs_inobt_rec *rp; > > + xfs_agblock_t agbno; > > + xfs_agblock_t end_agbno; > > + int blks_per_buf; > > + int inodes_per_buf; > > + int ioff; > > + > > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > > + blks_per_buf = xfs_icluster_size_fsb(mp); > > + else > > + blks_per_buf = mp->m_ialloc_blks; > > + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, > > + XFS_INODES_PER_CHUNK); > > > > if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC && > > be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) { > > @@ -4468,19 +4514,34 @@ scanfunc_fino( > > rp = XFS_INOBT_REC_ADDR(mp, block, 1); > > for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { > > agino = be32_to_cpu(rp[i].ir_startino); > > - off = XFS_INO_TO_OFFSET(mp, agino); > > + agbno = XFS_AGINO_TO_AGBNO(mp, agino); > > + off = XFS_AGINO_TO_OFFSET(mp, agino); > > + end_agbno = agbno + mp->m_ialloc_blks; > > if (off == 0) { > > if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && > > mp->m_sb.sb_inoalignmt && > > (XFS_INO_TO_AGBNO(mp, agino) % > > mp->m_sb.sb_inoalignmt)) > > sbversion &= ~XFS_SB_VERSION_ALIGNBIT; > > - check_set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), > > - (xfs_extlen_t)MAX(1, > > - XFS_INODES_PER_CHUNK >> > > - mp->m_sb.sb_inopblog), > > - DBM_INODE, DBM_INODE, seqno, bno); > > } > > + > > + ioff = 0; > > + while (agbno < end_agbno && > > + ioff < XFS_INODES_PER_CHUNK) { > > + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) > > + goto next_buf; > > + > > + check_set_dbmap(seqno, agbno, > > + (xfs_extlen_t)MAX(1, > > + inodes_per_buf >> > > + mp->m_sb.sb_inopblog), > > + DBM_INODE, DBM_INODE, seqno, bno); > > + > > +next_buf: > > + agbno += blks_per_buf; > > + ioff += inodes_per_buf; > > + } > > + > > } > > return; > > } > > -- > > 2.5.5 > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs > > -- > Carlos > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From eguan@redhat.com Tue Jun 21 07:02:59 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 926817CA1 for ; Tue, 21 Jun 2016 07:02:59 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6186F304032 for ; Tue, 21 Jun 2016 05:02:56 -0700 (PDT) X-ASG-Debug-ID: 1466510574-04cb6c5424110cc0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id VAE7BjvyJhz7PJ9J (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 21 Jun 2016 05:02:55 -0700 (PDT) X-Barracuda-Envelope-From: eguan@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C595063E14; Tue, 21 Jun 2016 12:02:54 +0000 (UTC) Received: from localhost (dhcp12-144.nay.redhat.com [10.66.12.144] (may be forged)) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5LC2rR5004173; Tue, 21 Jun 2016 08:02:54 -0400 From: Eryu Guan To: fstests@vger.kernel.org Cc: xfs@oss.sgi.com, Eryu Guan Subject: [PATCH] xfs/186: run test on expected XFS configuration Date: Tue, 21 Jun 2016 20:01:47 +0800 X-ASG-Orig-Subj: [PATCH] xfs/186: run test on expected XFS configuration Message-Id: <1466510507-17548-1-git-send-email-eguan@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 21 Jun 2016 12:02:54 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466510575 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1902 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Usually xfs/186 _notrun on crc enabled XFS because of _require_attr_v1, since v2 attr format is always enabled on v5 XFS. But when testing on 512B block size XFS, i.e. MKFS_OPTIONS="-m crc=0 -b size=512", test fails. This is because crc enalbed XFS was created in the end, not 512B block size XFS with crc disabled, and that's not what we want to test. The reason why _scratch_mkfs_xfs creates a different XFS than expected is that, it may ignore $MKFS_OPTIONS if mkfs fails due to conflicts between $MKFS_OPTIONS and the provided mkfs options. In the case of xfs/186, "-b size=512" conflicts with "-i size=512", and the first mkfs fails, then it ends up with a 4k block size XFS with crc enabled (the default config). Fix it by checking crc enablement status and attr version in the test, to make sure it's testing on expected XFS. Signed-off-by: Eryu Guan --- tests/xfs/186 | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/xfs/186 b/tests/xfs/186 index 9b64d6c..192a8c8 100755 --- a/tests/xfs/186 +++ b/tests/xfs/186 @@ -156,7 +156,20 @@ _require_attr_v1 rm -f $seqres.full -_scratch_mkfs -i attr=2,size=512 -l lazy-count=1 >/dev/null 2>&1 +_scratch_mkfs -i attr=2,size=512 -l lazy-count=1 | _filter_mkfs \ + >>$seqres.full 2>$tmp.mkfs +# import crc status and attr version +. $tmp.mkfs + +# _scratch_mkfs may ignore $MKFS_OPTIONS if mkfs fails due to conflicts between +# $MKFS_OPTIONS and the provided mkfs options, which could result in creating +# an XFS we don't want. Check crc status and attr version to be sure. +if [ $_fs_has_crcs -eq 1 ]; then + _notrun "attr v1 not supported on $SCRATCH_DEV" +fi +if [ $attr -ne 2 ]; then + _notrun "need attr v2 on $SCRATCH_DEV" +fi # set inum to root dir ino # we'll add in dirents and EAs into the root directory -- 2.5.5 From cmaiolino@redhat.com Tue Jun 21 07:05:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 914A47CA1 for ; Tue, 21 Jun 2016 07:05:22 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5CB5B8F804C for ; Tue, 21 Jun 2016 05:05:22 -0700 (PDT) X-ASG-Debug-ID: 1466510718-04cb6c5426110d80001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id JdCnrZGl7NF0M6Y4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 21 Jun 2016 05:05:19 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id ABBB163312 for ; Tue, 21 Jun 2016 12:05:18 +0000 (UTC) Received: from redhat.com (vpn-60-35.rdu2.redhat.com [10.10.60.35]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5LC5DOP026878 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 21 Jun 2016 08:05:17 -0400 Date: Tue, 21 Jun 2016 14:05:13 +0200 From: Carlos Maiolino To: Brian Foster Cc: xfs@oss.sgi.com Subject: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Message-ID: <20160621120513.GD28212@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Mail-Followup-To: Brian Foster , xfs@oss.sgi.com References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> <1466441562-12317-3-git-send-email-bfoster@redhat.com> <20160621090153.GB28212@redhat.com> <20160621104815.GA3108@laptop.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160621104815.GA3108@laptop.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 21 Jun 2016 12:05:18 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466510719 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9880 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Tue, Jun 21, 2016 at 06:48:15AM -0400, Brian Foster wrote: > On Tue, Jun 21, 2016 at 11:01:53AM +0200, Carlos Maiolino wrote: > > On Mon, Jun 20, 2016 at 12:52:42PM -0400, Brian Foster wrote: > > > Update the inode btree scanning functions to process sparse inode chunks > > > correctly. For filesystems with sparse inode support enabled, process > > > each chunk a cluster at a time. Each cluster is checked against the > > > inobt record to determine if it is a hole and skipped if so. > > > > > > Note that since xfs_check is deprecated in favor of xfs_repair, this > > > adds the minimum support necessary to process sparse inode enabled > > > filesystems. In other words, this adds no sparse inode specific checks > > > or verifications. We only update the inobt scanning functions to extend > > > the existing level of verification to sparse inode enabled filesystems > > > (e.g., avoid incorrectly tracking sparse regions as inodes). Problems > > > or corruptions associated with sparse inode records must be detected and > > > recovered via xfs_repair. > > > > > > > Hi, > > > > I'm not quite sure, but a while ago, I thought I've heard some rumors about > > deprecating xfs_check, is this true or something that my mind made up for some > > weird reason? > > > > I actually thought it already was. :) xfstests still runs check in > certain cases, however, and these patches just fix a regression. > Personally, I'd be fine with just dumping an "fs has sparse inodes, use > repair" message from xfs_check, but the basic sparse inode support had > already been added. > :) I had no objection about the patch, just to make it clear. I was just curious about how much we still care about xfs_check :) > Brian > > > > > > Signed-off-by: Brian Foster > > > --- > > > db/check.c | 143 +++++++++++++++++++++++++++++++++++++++++++------------------ > > > 1 file changed, 102 insertions(+), 41 deletions(-) > > > > > > diff --git a/db/check.c b/db/check.c > > > index 750ecc1..25146e5 100644 > > > --- a/db/check.c > > > +++ b/db/check.c > > > @@ -4324,10 +4324,24 @@ scanfunc_ino( > > > int i; > > > int isfree; > > > int j; > > > + int freecount; > > > int nfree; > > > int off; > > > xfs_inobt_ptr_t *pp; > > > xfs_inobt_rec_t *rp; > > > + xfs_agblock_t agbno; > > > + xfs_agblock_t end_agbno; > > > + struct xfs_dinode *dip; > > > + int blks_per_buf; > > > + int inodes_per_buf; > > > + int ioff; > > > + > > > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > > > + blks_per_buf = xfs_icluster_size_fsb(mp); > > > + else > > > + blks_per_buf = mp->m_ialloc_blks; > > > + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, > > > + XFS_INODES_PER_CHUNK); > > > > > > if (be32_to_cpu(block->bb_magic) != XFS_IBT_MAGIC && > > > be32_to_cpu(block->bb_magic) != XFS_IBT_CRC_MAGIC) { > > > @@ -4357,54 +4371,74 @@ scanfunc_ino( > > > rp = XFS_INOBT_REC_ADDR(mp, block, 1); > > > for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { > > > agino = be32_to_cpu(rp[i].ir_startino); > > > - off = XFS_INO_TO_OFFSET(mp, agino); > > > + agbno = XFS_AGINO_TO_AGBNO(mp, agino); > > > + off = XFS_AGINO_TO_OFFSET(mp, agino); > > > + end_agbno = agbno + mp->m_ialloc_blks; > > > if (off == 0) { > > > if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && > > > mp->m_sb.sb_inoalignmt && > > > (XFS_INO_TO_AGBNO(mp, agino) % > > > mp->m_sb.sb_inoalignmt)) > > > sbversion &= ~XFS_SB_VERSION_ALIGNBIT; > > > - set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), > > > - (xfs_extlen_t)MAX(1, > > > - XFS_INODES_PER_CHUNK >> > > > - mp->m_sb.sb_inopblog), > > > - DBM_INODE, seqno, bno); > > > } > > > - icount += XFS_INODES_PER_CHUNK; > > > - agicount += XFS_INODES_PER_CHUNK; > > > - ifree += be32_to_cpu(rp[i].ir_u.f.ir_freecount); > > > - agifreecount += be32_to_cpu(rp[i].ir_u.f.ir_freecount); > > > + > > > push_cur(); > > > - set_cur(&typtab[TYP_INODE], > > > - XFS_AGB_TO_DADDR(mp, seqno, > > > - XFS_AGINO_TO_AGBNO(mp, agino)), > > > - (int)XFS_FSB_TO_BB(mp, mp->m_ialloc_blks), > > > - DB_RING_IGN, NULL); > > > - if (iocur_top->data == NULL) { > > > - if (!sflag) > > > - dbprintf(_("can't read inode block " > > > - "%u/%u\n"), > > > - seqno, > > > - XFS_AGINO_TO_AGBNO(mp, agino)); > > > - error++; > > > - pop_cur(); > > > - continue; > > > - } > > > - for (j = 0, nfree = 0; j < XFS_INODES_PER_CHUNK; j++) { > > > - isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], j); > > > - if (isfree) > > > - nfree++; > > > - process_inode(agf, agino + j, > > > - (xfs_dinode_t *)((char *)iocur_top->data + ((off + j) << mp->m_sb.sb_inodelog)), > > > - isfree); > > > + > > > + ioff = 0; > > > + nfree = 0; > > > + while (agbno < end_agbno && > > > + ioff < XFS_INODES_PER_CHUNK) { > > > + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) > > > + goto next_buf; > > > + > > > + if (off < XFS_INODES_PER_CHUNK) > > > + set_dbmap(seqno, agbno, blks_per_buf, > > > + DBM_INODE, seqno, bno); > > > + > > > + icount += inodes_per_buf; > > > + agicount += inodes_per_buf; > > > + > > > + set_cur(&typtab[TYP_INODE], > > > + XFS_AGB_TO_DADDR(mp, seqno, agbno), > > > + XFS_FSB_TO_BB(mp, blks_per_buf), > > > + DB_RING_IGN, NULL); > > > + if (iocur_top->data == NULL) { > > > + if (!sflag) > > > + dbprintf(_("can't read inode block " > > > + "%u/%u\n"), seqno, > > > + agbno); > > > + error++; > > > + goto next_buf; > > > + } > > > + > > > + for (j = 0; j < inodes_per_buf; j++) { > > > + isfree = XFS_INOBT_IS_FREE_DISK(&rp[i], ioff + j); > > > + if (isfree) > > > + nfree++; > > > + dip = (xfs_dinode_t *)((char *)iocur_top->data + > > > + ((off + j) << mp->m_sb.sb_inodelog)); > > > + process_inode(agf, agino + ioff + j, dip, isfree); > > > + } > > > + > > > +next_buf: > > > + agbno += blks_per_buf; > > > + ioff += inodes_per_buf; > > > } > > > - if (nfree != be32_to_cpu(rp[i].ir_u.f.ir_freecount)) { > > > + > > > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > > > + freecount = rp[i].ir_u.sp.ir_freecount; > > > + else > > > + freecount = be32_to_cpu(rp[i].ir_u.f.ir_freecount); > > > + > > > + ifree += freecount; > > > + agifreecount += freecount; > > > + > > > + if (nfree != freecount) { > > > if (!sflag) > > > dbprintf(_("ir_freecount/free mismatch, " > > > "inode chunk %u/%u, freecount " > > > "%d nfree %d\n"), > > > - seqno, agino, > > > - be32_to_cpu(rp[i].ir_u.f.ir_freecount), nfree); > > > + seqno, agino, freecount, nfree); > > > error++; > > > } > > > pop_cur(); > > > @@ -4439,6 +4473,18 @@ scanfunc_fino( > > > int off; > > > xfs_inobt_ptr_t *pp; > > > struct xfs_inobt_rec *rp; > > > + xfs_agblock_t agbno; > > > + xfs_agblock_t end_agbno; > > > + int blks_per_buf; > > > + int inodes_per_buf; > > > + int ioff; > > > + > > > + if (xfs_sb_version_hassparseinodes(&mp->m_sb)) > > > + blks_per_buf = xfs_icluster_size_fsb(mp); > > > + else > > > + blks_per_buf = mp->m_ialloc_blks; > > > + inodes_per_buf = min(blks_per_buf << mp->m_sb.sb_inopblog, > > > + XFS_INODES_PER_CHUNK); > > > > > > if (be32_to_cpu(block->bb_magic) != XFS_FIBT_MAGIC && > > > be32_to_cpu(block->bb_magic) != XFS_FIBT_CRC_MAGIC) { > > > @@ -4468,19 +4514,34 @@ scanfunc_fino( > > > rp = XFS_INOBT_REC_ADDR(mp, block, 1); > > > for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++) { > > > agino = be32_to_cpu(rp[i].ir_startino); > > > - off = XFS_INO_TO_OFFSET(mp, agino); > > > + agbno = XFS_AGINO_TO_AGBNO(mp, agino); > > > + off = XFS_AGINO_TO_OFFSET(mp, agino); > > > + end_agbno = agbno + mp->m_ialloc_blks; > > > if (off == 0) { > > > if ((sbversion & XFS_SB_VERSION_ALIGNBIT) && > > > mp->m_sb.sb_inoalignmt && > > > (XFS_INO_TO_AGBNO(mp, agino) % > > > mp->m_sb.sb_inoalignmt)) > > > sbversion &= ~XFS_SB_VERSION_ALIGNBIT; > > > - check_set_dbmap(seqno, XFS_AGINO_TO_AGBNO(mp, agino), > > > - (xfs_extlen_t)MAX(1, > > > - XFS_INODES_PER_CHUNK >> > > > - mp->m_sb.sb_inopblog), > > > - DBM_INODE, DBM_INODE, seqno, bno); > > > } > > > + > > > + ioff = 0; > > > + while (agbno < end_agbno && > > > + ioff < XFS_INODES_PER_CHUNK) { > > > + if (xfs_inobt_is_sparse_disk(&rp[i], ioff)) > > > + goto next_buf; > > > + > > > + check_set_dbmap(seqno, agbno, > > > + (xfs_extlen_t)MAX(1, > > > + inodes_per_buf >> > > > + mp->m_sb.sb_inopblog), > > > + DBM_INODE, DBM_INODE, seqno, bno); > > > + > > > +next_buf: > > > + agbno += blks_per_buf; > > > + ioff += inodes_per_buf; > > > + } > > > + > > > } > > > return; > > > } > > > -- > > > 2.5.5 > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > -- > > Carlos > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From bfoster@redhat.com Tue Jun 21 08:00:51 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A3EF27CA0 for ; Tue, 21 Jun 2016 08:00:51 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3C305AC001 for ; Tue, 21 Jun 2016 06:00:48 -0700 (PDT) X-ASG-Debug-ID: 1466514046-04bdf01e1517a1c0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id g8E7rYzEjBCCEoSO (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 21 Jun 2016 06:00:46 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4C25978226; Tue, 21 Jun 2016 13:00:46 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-2.bos.redhat.com [10.18.41.2]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5LD0j99024234; Tue, 21 Jun 2016 09:00:45 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 416631201DB; Tue, 21 Jun 2016 09:00:45 -0400 (EDT) Date: Tue, 21 Jun 2016 09:00:45 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion Message-ID: <20160621130043.GA62352@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612634887.12839.6210102273046676244.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612634887.12839.6210102273046676244.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.28]); Tue, 21 Jun 2016 13:00:46 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466514046 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9489 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:08PM -0700, Darrick J. Wong wrote: > When a btree block has to be split, we pass the new block's ptr from > xfs_btree_split() back to xfs_btree_insert() via a pointer parameter; > however, we pass the block's key through the cursor's record. It is a > little weird to "initialize" a record from a key since the non-key > attributes will have garbage values. > > When we go to add support for interval queries, we have to be able to > pass the lowest and highest keys accessible via a pointer. There's no > clean way to pass this back through the cursor's record field. > Therefore, pass the key directly back to xfs_btree_insert() the same > way that we pass the btree_ptr. > > As a bonus, we no longer need init_rec_from_key and can drop it from the > codebase. > > Signed-off-by: Darrick J. Wong > --- > fs/xfs/libxfs/xfs_alloc_btree.c | 12 ---------- > fs/xfs/libxfs/xfs_bmap_btree.c | 12 ---------- > fs/xfs/libxfs/xfs_btree.c | 44 +++++++++++++++++++------------------- > fs/xfs/libxfs/xfs_btree.h | 2 -- > fs/xfs/libxfs/xfs_ialloc_btree.c | 10 --------- > 5 files changed, 22 insertions(+), 58 deletions(-) > > ... > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 046fbcf..a096539 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c ... > @@ -2929,16 +2927,16 @@ xfs_btree_insrec( > struct xfs_btree_cur *cur, /* btree cursor */ > int level, /* level to insert record at */ > union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ > - union xfs_btree_rec *recp, /* i/o: record data inserted */ > + union xfs_btree_key *key, /* i/o: block key for ptrp */ > struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ > int *stat) /* success/failure */ > { > struct xfs_btree_block *block; /* btree block */ > struct xfs_buf *bp; /* buffer for block */ > - union xfs_btree_key key; /* btree key */ > union xfs_btree_ptr nptr; /* new block ptr */ > struct xfs_btree_cur *ncur; /* new btree cursor */ > - union xfs_btree_rec nrec; /* new record count */ > + union xfs_btree_key nkey; /* new block key */ > + union xfs_btree_rec rec; /* record to insert */ > int optr; /* old key/record index */ > int ptr; /* key/record index */ > int numrecs;/* number of records */ > @@ -2947,8 +2945,14 @@ xfs_btree_insrec( > int i; > #endif > > + /* Make a key out of the record data to be inserted, and save it. */ > + if (level == 0) { > + cur->bc_ops->init_rec_from_cur(cur, &rec); > + cur->bc_ops->init_key_from_rec(key, &rec); > + } The level == 0 check looks a bit hacky to me. IOW, I think it's cleaner that the key is initialized once in the caller rather than check for a particular iteration down in xfs_btree_insrec(). That said, xfs_btree_insrec() still needs rec initialized in the level == 0 case. I wonder if we could create an inline xfs_btree_init_key_from_cur() helper to combine the above calls, invoke it once in xfs_btree_insert(), then push down the ->init_rec_from_cur() calls to the contexts further down in this function where rec is actually required. There are only two and one of them is DEBUG code. Thoughts? > + > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > - XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp); > + XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, &rec); > So these look like unimplemented dummy tracing hooks. It sounds like previously rec could have a junk value after a btree split, but now it looks like rec is junk for every non-zero level. Kind of annoying, I wonder if we can just kill these.. :/ Brian > ncur = NULL; > > @@ -2973,9 +2977,6 @@ xfs_btree_insrec( > return 0; > } > > - /* Make a key out of the record data to be inserted, and save it. */ > - cur->bc_ops->init_key_from_rec(&key, recp); > - > optr = ptr; > > XFS_BTREE_STATS_INC(cur, insrec); > @@ -2992,10 +2993,10 @@ xfs_btree_insrec( > /* Check that the new entry is being inserted in the right place. */ > if (ptr <= numrecs) { > if (level == 0) { > - ASSERT(cur->bc_ops->recs_inorder(cur, recp, > + ASSERT(cur->bc_ops->recs_inorder(cur, &rec, > xfs_btree_rec_addr(cur, ptr, block))); > } else { > - ASSERT(cur->bc_ops->keys_inorder(cur, &key, > + ASSERT(cur->bc_ops->keys_inorder(cur, key, > xfs_btree_key_addr(cur, ptr, block))); > } > } > @@ -3008,7 +3009,7 @@ xfs_btree_insrec( > xfs_btree_set_ptr_null(cur, &nptr); > if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) { > error = xfs_btree_make_block_unfull(cur, level, numrecs, > - &optr, &ptr, &nptr, &ncur, &nrec, stat); > + &optr, &ptr, &nptr, &ncur, &nkey, stat); > if (error || *stat == 0) > goto error0; > } > @@ -3058,7 +3059,7 @@ xfs_btree_insrec( > #endif > > /* Now put the new data in, bump numrecs and log it. */ > - xfs_btree_copy_keys(cur, kp, &key, 1); > + xfs_btree_copy_keys(cur, kp, key, 1); > xfs_btree_copy_ptrs(cur, pp, ptrp, 1); > numrecs++; > xfs_btree_set_numrecs(block, numrecs); > @@ -3079,7 +3080,7 @@ xfs_btree_insrec( > xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1); > > /* Now put the new data in, bump numrecs and log it. */ > - xfs_btree_copy_recs(cur, rp, recp, 1); > + xfs_btree_copy_recs(cur, rp, &rec, 1); > xfs_btree_set_numrecs(block, ++numrecs); > xfs_btree_log_recs(cur, bp, ptr, numrecs); > #ifdef DEBUG > @@ -3095,7 +3096,7 @@ xfs_btree_insrec( > > /* If we inserted at the start of a block, update the parents' keys. */ > if (optr == 1) { > - error = xfs_btree_updkey(cur, &key, level + 1); > + error = xfs_btree_updkey(cur, key, level + 1); > if (error) > goto error0; > } > @@ -3105,7 +3106,7 @@ xfs_btree_insrec( > * we are at the far right edge of the tree, update it. > */ > if (xfs_btree_is_lastrec(cur, block, level)) { > - cur->bc_ops->update_lastrec(cur, block, recp, > + cur->bc_ops->update_lastrec(cur, block, &rec, > ptr, LASTREC_INSREC); > } > > @@ -3115,7 +3116,7 @@ xfs_btree_insrec( > */ > *ptrp = nptr; > if (!xfs_btree_ptr_is_null(cur, &nptr)) { > - *recp = nrec; > + *key = nkey; > *curp = ncur; > } > > @@ -3146,14 +3147,13 @@ xfs_btree_insert( > union xfs_btree_ptr nptr; /* new block number (split result) */ > struct xfs_btree_cur *ncur; /* new cursor (split result) */ > struct xfs_btree_cur *pcur; /* previous level's cursor */ > - union xfs_btree_rec rec; /* record to insert */ > + union xfs_btree_key key; /* key of block to insert */ > > level = 0; > ncur = NULL; > pcur = cur; > > xfs_btree_set_ptr_null(cur, &nptr); > - cur->bc_ops->init_rec_from_cur(cur, &rec); > > /* > * Loop going up the tree, starting at the leaf level. > @@ -3165,7 +3165,7 @@ xfs_btree_insert( > * Insert nrec/nptr into this level of the tree. > * Note if we fail, nptr will be null. > */ > - error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i); > + error = xfs_btree_insrec(pcur, level, &nptr, &key, &ncur, &i); > if (error) { > if (pcur != cur) > xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index b955e5d..b99c018 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -158,8 +158,6 @@ struct xfs_btree_ops { > /* init values of btree structures */ > void (*init_key_from_rec)(union xfs_btree_key *key, > union xfs_btree_rec *rec); > - void (*init_rec_from_key)(union xfs_btree_key *key, > - union xfs_btree_rec *rec); > void (*init_rec_from_cur)(struct xfs_btree_cur *cur, > union xfs_btree_rec *rec); > void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, > diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c > index 89c21d7..88da2ad 100644 > --- a/fs/xfs/libxfs/xfs_ialloc_btree.c > +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c > @@ -146,14 +146,6 @@ xfs_inobt_init_key_from_rec( > } > > STATIC void > -xfs_inobt_init_rec_from_key( > - union xfs_btree_key *key, > - union xfs_btree_rec *rec) > -{ > - rec->inobt.ir_startino = key->inobt.ir_startino; > -} > - > -STATIC void > xfs_inobt_init_rec_from_cur( > struct xfs_btree_cur *cur, > union xfs_btree_rec *rec) > @@ -314,7 +306,6 @@ static const struct xfs_btree_ops xfs_inobt_ops = { > .get_minrecs = xfs_inobt_get_minrecs, > .get_maxrecs = xfs_inobt_get_maxrecs, > .init_key_from_rec = xfs_inobt_init_key_from_rec, > - .init_rec_from_key = xfs_inobt_init_rec_from_key, > .init_rec_from_cur = xfs_inobt_init_rec_from_cur, > .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, > .key_diff = xfs_inobt_key_diff, > @@ -336,7 +327,6 @@ static const struct xfs_btree_ops xfs_finobt_ops = { > .get_minrecs = xfs_inobt_get_minrecs, > .get_maxrecs = xfs_inobt_get_maxrecs, > .init_key_from_rec = xfs_inobt_init_key_from_rec, > - .init_rec_from_key = xfs_inobt_init_rec_from_key, > .init_rec_from_cur = xfs_inobt_init_rec_from_cur, > .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, > .key_diff = xfs_inobt_key_diff, > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From sandeen@sandeen.net Tue Jun 21 08:54:12 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 4F9E27CA1 for ; Tue, 21 Jun 2016 08:54:12 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0199C304032 for ; Tue, 21 Jun 2016 06:54:08 -0700 (PDT) X-ASG-Debug-ID: 1466517245-04bdf01e1017c5f0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id YwFLXFijV1C11yzb for ; Tue, 21 Jun 2016 06:54:05 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 6BFA215B13 for ; Tue, 21 Jun 2016 08:54:05 -0500 (CDT) Subject: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> <1466441562-12317-3-git-send-email-bfoster@redhat.com> <20160621090153.GB28212@redhat.com> From: Eric Sandeen Message-ID: Date: Tue, 21 Jun 2016 08:54:04 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160621090153.GB28212@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1466517245 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1664 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30627 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/21/16 4:01 AM, Carlos Maiolino wrote: > On Mon, Jun 20, 2016 at 12:52:42PM -0400, Brian Foster wrote: >> Update the inode btree scanning functions to process sparse inode chunks >> correctly. For filesystems with sparse inode support enabled, process >> each chunk a cluster at a time. Each cluster is checked against the >> inobt record to determine if it is a hole and skipped if so. >> >> Note that since xfs_check is deprecated in favor of xfs_repair, this >> adds the minimum support necessary to process sparse inode enabled >> filesystems. In other words, this adds no sparse inode specific checks >> or verifications. We only update the inobt scanning functions to extend >> the existing level of verification to sparse inode enabled filesystems >> (e.g., avoid incorrectly tracking sparse regions as inodes). Problems >> or corruptions associated with sparse inode records must be detected and >> recovered via xfs_repair. >> > > Hi, > > I'm not quite sure, but a while ago, I thought I've heard some rumors about > deprecating xfs_check, is this true or something that my mind made up for some > weird reason? Yes, like Brian said above. ;) bfc541e xfsprogs: remove xfs_check 12a48f5 xfsprogs: remove xfs_check references from fsck.xfs script & manpage However, we still run check inside xfs_db in xfstests as an independent verification step: 187bccd xfstests: Remove dependence of xfs_check script +# xfs_check script is planned to be deprecated. But, we want to +# be able to invoke "xfs_check" behavior in xfstests in order to +# maintain the current verification levels. +_xfs_check() -Eric From mstsxfx@gmail.com Tue Jun 21 09:26:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 953B37CA1 for ; Tue, 21 Jun 2016 09:26:36 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 679A48F8033 for ; Tue, 21 Jun 2016 07:26:33 -0700 (PDT) X-ASG-Debug-ID: 1466519189-04cbb01fef162510001-NocioJ Received: from mail-lb0-f171.google.com (mail-lb0-f171.google.com [209.85.217.171]) by cuda.sgi.com with ESMTP id InAVDj9EUFFd1oNx (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 21 Jun 2016 07:26:31 -0700 (PDT) X-Barracuda-Envelope-From: mstsxfx@gmail.com X-Barracuda-Effective-Source-IP: mail-lb0-f171.google.com[209.85.217.171] X-Barracuda-Apparent-Source-IP: 209.85.217.171 Received: by mail-lb0-f171.google.com with SMTP id oe3so12199435lbb.1 for ; Tue, 21 Jun 2016 07:26:31 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=n3xGpSOrF1RBo8MpNSzwHpB5kUeWm3tJYtJEgvu1TiE=; b=Pr7qQRVoAVWB+qM3dO7RH6Fk8SpMiR1bTTp8R2ELBWfWTQcMKOQTGClmnOiP0IYL1P gmzNH+W/gxFCpFatP7DQGuQQuf0YF46CRA5lsA06DSjCU0fiZb+6hFy4l6dv8M/yugCS W/B6utxEd3wdV2bRXSXxL7b2RXakGLYDok8+c5pLgjt3TyLODAROGe4HOOP/vYtrduda MhYUk9dxOFKbjH6PvEZ46Y9wrz29ddrdzZRLlTzeYL1BBnGB03JK8bMoX48nHspkKXFY S62+ahZfvitCk3/8TUiGhNwo7l2TVdI0BpqUmfU4SKdKAZVj2mXRVHjBlfOe83hQYcaW wk2A== X-Gm-Message-State: ALyK8tKAn6SsqM2D8QTD/F2EzDfbrmEKYK+P5OV+y1hi5O3GQiGTL0lfmy9XMY/dFYPOmA== X-Received: by 10.194.205.233 with SMTP id lj9mr16321567wjc.10.1466519189515; Tue, 21 Jun 2016 07:26:29 -0700 (PDT) Received: from localhost ([80.188.202.66]) by smtp.gmail.com with ESMTPSA id o129sm3199467wmb.17.2016.06.21.07.26.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Jun 2016 07:26:28 -0700 (PDT) Date: Tue, 21 Jun 2016 16:26:28 +0200 From: Michal Hocko To: Dave Chinner Cc: Peter Zijlstra , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160621142628.GG30848@dhcp22.suse.cz> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160519081146.GS3193@twins.programming.kicks-ass.net> <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> <20160602232254.GR12670@dastard> <20160606122022.GH11895@dhcp22.suse.cz> <20160615072154.GF26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160615072154.GF26977@dastard> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: mail-lb0-f171.google.com[209.85.217.171] X-Barracuda-Start-Time: 1466519190 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2286 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30627 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed 15-06-16 17:21:54, Dave Chinner wrote: [...] > Hopefully you can see the complexity of the issue - for an allocation > in the bmap btree code that could occur outside both inside and > outside of a transaction context, we've got to work out which of > those ~60 high level entry points would need to be annotated. And > then we have to ensure that in future we don't miss adding or > removing an annotation as we change the code deep inside the btree > implementation. It's the latter that is the long term maintainence > problem the hihg-level annotation approach introduces. Sure I can see the complexity here. I might still see this over simplified but I originally thought that the annotation would be used at the highest level which never gets called from the transaction or other NOFS context. So all the layers down would inherit that automatically. I guess that such a place can be identified from the lockdep report by a trained eye. > > > I think such an annotation approach really requires per-alloc site > > > annotation, the reason for it should be more obvious from the > > > context. e.g. any function that does memory alloc and takes an > > > optional transaction context needs annotation. Hence, from an XFS > > > perspective, I think it makes more sense to add a new KM_ flag to > > > indicate this call site requirement, then jump through whatever > > > lockdep hoop is required within the kmem_* allocation wrappers. > > > e.g, we can ignore the new KM_* flag if we are in a transaction > > > context and so the flag is only activated in the situations were > > > we currently enforce an external GFP_NOFS context from the call > > > site..... > > > > Hmm, I thought we would achive this by using the scope GFP_NOFS usage > > which would mark those transaction related conctexts and no lockdep > > specific workarounds would be needed... > > There are allocations outside transaction context which need to be > GFP_NOFS - this is what KM_NOFS was originally intended for. Is it feasible to mark those by the scope NOFS api as well and drop the direct KM_NOFS usage? This should help to identify those that are lockdep only and use the annotation to prevent from the false positives. -- Michal Hocko SUSE Labs From grace15@offer.com Tue Jun 21 10:49:05 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_MESSAGE,MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 86A457CA1 for ; Tue, 21 Jun 2016 10:49:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 467CF304032 for ; Tue, 21 Jun 2016 08:49:02 -0700 (PDT) X-ASG-Debug-ID: 1466524079-04bdf05e6b02af0001-NocioJ Received: from offer.com ([223.73.2.38]) by cuda.sgi.com with SMTP id lWcu42HnZwyBfFcE for ; Tue, 21 Jun 2016 08:48:30 -0700 (PDT) X-Barracuda-Envelope-From: grace15@offer.com X-Barracuda-Effective-Source-IP: UNKNOWN[223.73.2.38] X-Barracuda-Apparent-Source-IP: 223.73.2.38 Received: from DESKTOP-9S5QUR1[127.0.0.1] by DESKTOP-9S5QUR1[127.0.0.1] (SMTPD32); Tue, 21 Jun 2016 23:45:59 +0800 From: "liguoyan2@163.com" Subject: re:cell phone anti lost alarm To: xfs@oss.sgi.com X-ASG-Orig-Subj: re:cell phone anti lost alarm MIME-Version: 1.0 Sender: grace15@offer.com Reply-To: liguoyan2@163.com Date: Tue, 21 Jun 2016 23:45:59 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline X-Barracuda-Connect: UNKNOWN[223.73.2.38] X-Barracuda-Start-Time: 1466524109 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3530 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.74 X-Barracuda-Spam-Status: No, SCORE=0.74 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, HTML_MESSAGE, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30629 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160621154901.CBD58A420A0@cuda.sgi.com> PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVU Ri04IiBodHRwLWVxdWl2PWNvbnRlbnQtdHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCAxMS4wMC4xMDU4Ni4wIj48L0hFQUQ+DQo8Qk9EWT4NCjxQIGNsYXNzPU1zb05v cm1hbCBzdHlsZT0iTUFSR0lOOiAwcHQiPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTJwdDsg Rk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZv bnQta2VybmluZzogMS4wMDAwcHQiPmhpIA0KZnJpZW5kPEJSPjwvU1BBTj48U1BBTiANCnN0eWxl PSJGT05ULVNJWkU6IDEycHQ7IEZPTlQtRkFNSUxZOiBWZXJkYW5hOyBtc28tc3BhY2VydW46ICYj Mzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDEuMDAwMHB0Ij48QlI+PC9TUEFOPjxTUEFO IA0Kc3R5bGU9IkZPTlQtU0laRTogMTJwdDsgRk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1zby1zcGFj ZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQiPkdsYWQgDQp0 byBoZWFyIHRoYXQgeW91JiMzOTtyZSBvbiB0aGUgbWFya2V0IGZvciBwcm9tb3Rpb25hbCBpdGVt cy48L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMnB0OyBGT05ULUZBTUlMWTogVmVy ZGFuYTsgbXNvLXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAxLjAw MDBwdCI+PEJSPjwvU1BBTj48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEycHQ7IEZPTlQtRkFN SUxZOiBWZXJkYW5hOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1mb250LWtlcm5p bmc6IDEuMDAwMHB0Ij48QlI+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTJwdDsg Rk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZv bnQta2VybmluZzogMS4wMDAwcHQiPlRoaXMgDQppcyZuYnNwO0dyYWNlIGxpJm5ic3A7ZnJvbSZu YnNwO3NoZW56aGVuIGpveXdheSB0ZWNobm9sb2d5IGNvLjwvU1BBTj48U1BBTiANCnN0eWxlPSJG T05ULVNJWkU6IDEycHQ7IEZPTlQtRkFNSUxZOiBWZXJkYW5hOyBtc28tc3BhY2VydW46ICYjMzk7 eWVzJiMzOTs7IG1zby1mb250LWtlcm5pbmc6IDEuMDAwMHB0Ij4mbmJzcDtMdGQgDQppbiBDaGlu YS4gV2Ugc3BlY2lhbGl6ZWQgaW4mbmJzcDtwcm9tb3Rpb25hbCBpdGVtcyBmb3ImbmJzcDttYW55 IHllYXJzLCANCjxTVFJPTkc+d2l0aCB0aGUgYmx1ZXRvb3RoIGtleWZpbmRlciwgaWJlYWNvbiwg cGVyc29uYWwgYWxhcm08L1NUUk9ORz4gYW5kIGhvcGUgDQp0byBmaW5kIGEgd2F5IHRvIGNvb3Bl cmF0ZSB3aXRoIHlvdSE8L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMnB0OyBGT05U LUZBTUlMWTogVmVyZGFuYTsgbXNvLXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28tZm9udC1r ZXJuaW5nOiAxLjAwMDBwdCI+PEJSPjwvU1BBTj48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEy cHQ7IEZPTlQtRkFNSUxZOiBWZXJkYW5hOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1z by1mb250LWtlcm5pbmc6IDEuMDAwMHB0Ij48QlI+PC9TUEFOPjxTUEFOIA0Kc3R5bGU9IkZPTlQt U0laRTogMTJwdDsgRk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMm IzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQiPkZSRUUgDQpTQU1QTEVTIGNhbiBiZSBz ZW50IG9uIHJlcXVlc3QuIENhbGwgbWUsIGxldCYjMzk7cyB0YWxrIG1vcmUhPC9TUEFOPjxTUEFO IA0Kc3R5bGU9IkZPTlQtU0laRTogMTJwdDsgRk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1zby1zcGFj ZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQiPjxCUj48L1NQ QU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMnB0OyBGT05ULUZBTUlMWTogVmVyZGFuYTsg bXNvLXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAxLjAwMDBwdCI+ Umdkcyw8L1NQQU4+PFNQQU4gDQpzdHlsZT0iRk9OVC1TSVpFOiAxMnB0OyBGT05ULUZBTUlMWTog 5a6L5L2TOyBtc28tc3BhY2VydW46ICYjMzk7eWVzJiMzOTs7IG1zby1hc2NpaS1mb250LWZhbWls eTogVmVyZGFuYTsgbXNvLWhhbnNpLWZvbnQtZmFtaWx5OiBWZXJkYW5hOyBtc28tZm9udC1rZXJu aW5nOiAxLjAwMDBwdCI+PD94bWw6bmFtZXNwYWNlIA0KcHJlZml4ID0gIm8iIG5zID0gInVybjpz Y2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9mZmljZSIgDQovPjxvOnA+PC9vOnA+PC9TUEFO PjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0iTUFSR0lOOiAwcHQiPjxTUEFOIA0Kc3R5 bGU9IkZPTlQtU0laRTogMTJwdDsgRk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1zby1zcGFjZXJ1bjog JiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQiPjxvOnA+Jm5ic3A7PC9v OnA+PC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0iTUFSR0lOOiAwcHQiPjxT UEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTJwdDsgRk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1zby1z cGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQiPkdyYWNl IA0KbGkgPC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0iTUFSR0lOOiAwcHQi PjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTJwdDsgRk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1z by1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQiPjwv U1BBTj4mbmJzcDs8L1A+DQo8UCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9Ik1BUkdJTjogMHB0Ij48 U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEwLjVwdDsgRk9OVC1GQU1JTFk6IFZlcmRhbmE7IG1z by1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4wMDAwcHQiPnNr eXBlOiANCmdyYWNlX2Jlc3RvbmVyPC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCBzdHls ZT0iTUFSR0lOOiAwcHQiPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0OyBGT05ULUZB TUlMWTogVmVyZGFuYTsgbXNvLXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28tZm9udC1rZXJu aW5nOiAxLjAwMDBwdCI+d2VjaGF0L21vYmlsZS93aGF0c2FwcDowMDg2LTEzNTEwNzI2NzE2PC9T UEFOPjwvUD4NCjxQIGNsYXNzPU1zb05vcm1hbCBzdHlsZT0iTUFSR0lOOiAwcHQiPjxTUEFOIA0K c3R5bGU9IkZPTlQtU0laRTogMTAuNXB0OyBGT05ULUZBTUlMWTogVmVyZGFuYTsgbXNvLXNwYWNl cnVuOiAmIzM5O3llcyYjMzk7OyBtc28tZm9udC1rZXJuaW5nOiAxLjAwMDBwdCI+PC9TUEFOPiZu YnNwOzwvUD4NCjxQPjwhLS1FbmRGcmFnbWVudC0tPjwvUD48L0JPRFk+PC9IVE1MPg0KDQo= From felix.janda@posteo.de Tue Jun 21 15:09:07 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 44F1D7CA1 for ; Tue, 21 Jun 2016 15:09:07 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id CCF01AC002 for ; Tue, 21 Jun 2016 13:09:03 -0700 (PDT) X-ASG-Debug-ID: 1466539739-04bdf05e6b0e180001-NocioJ Received: from mout02.posteo.de (mout02.posteo.de [185.67.36.66]) by cuda.sgi.com with ESMTP id 4avL0mknIlHZLT9m (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Tue, 21 Jun 2016 13:09:00 -0700 (PDT) X-Barracuda-Envelope-From: felix.janda@posteo.de X-Barracuda-Effective-Source-IP: mout02.posteo.de[185.67.36.66] X-Barracuda-Apparent-Source-IP: 185.67.36.66 Received: from submission (posteo.de [89.146.220.130]) by mout02.posteo.de (Postfix) with ESMTPS id BF48C20988 for ; Tue, 21 Jun 2016 22:08:58 +0200 (CEST) Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 3rYzMD32Y6z104v; Tue, 21 Jun 2016 22:08:55 +0200 (CEST) Date: Tue, 21 Jun 2016 22:07:34 +0200 From: Felix Janda To: Dave Chinner Cc: xfs@oss.sgi.com Subject: Re: [PATCH 1/4] Remove off64_t from linux.h Message-ID: <20160621200734.GA1151@nyan> X-ASG-Orig-Subj: Re: [PATCH 1/4] Remove off64_t from linux.h References: <20160618145238.GA17768@nyan> <20160620020414.GH26977@dastard> <20160620065348.GA431@nyan> <20160620231804.GK26977@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620231804.GK26977@dastard> User-Agent: Mutt/1.6.1 (2016-04-27) X-Barracuda-Connect: mout02.posteo.de[185.67.36.66] X-Barracuda-Start-Time: 1466539740 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2948 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30638 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Dave Chinner wrote: > On Mon, Jun 20, 2016 at 08:53:48AM +0200, Felix Janda wrote: > > Dave Chinner wrote: > > > > Thanks for asking for clarification. > > > > > On Sat, Jun 18, 2016 at 04:52:38PM +0200, Felix Janda wrote: > > > > The off64_t type is usually only conditionally exposed under the > > > > feature test macro _LARGEFILE64_SOURCE (also defined by _GNU_SOURCE). > > > > To make the public xfs headers more standalone therefore off64_t should > > > > be avoided. > > > > > > "more standalone"? > > > > > > What does that mean? > > > > Programs including the xfs headers while not defining _GNU_SOURCE or > > _LARGEFILE64_SOURCE will not fail with compile errors. My previous > > patch changing loff_t to off64_t had the unintented consequences that > > downstreams of xfs-progs like ceph had to define _LARGEFILE64_SOURCE > > on linux. > > That needs to be in the patch description - it's the motivation for > the change (i.e. that downstream apps need to add new defines). Sure. > > > And what does it mean for all the xfsprogs code that still uses > > > off64_t? > > > > off_t and off64_t are now synomyms and 64 bit on all architectures. > > So no difference for code using off64_t. > > > > Under some conditions there can be a difference for code using > > off_t. > > Right, I understand that there is a difference - what I'm asking for > is a description of the difference and an explanation of why: > > $ git grep off64_t | wc -l > 62 > $ > > the other ~60 uses of off64_t in the xfsprogs code are not being > removed, too. i.e. if the code now won't compile if off_t isn't 64 > bits, then why keep off64_t at all in any of the code? On 32bit systems using glibc the following changes happen: 1. off_t is now 64 bit instead of 32 bit 2. all functions and structures using off_t are mapped to versions using the 64 bit off_t 1. means that off_t and off64_t are now equivalents, whereas 2. means that struct stat and struct stat64, open() and open64() and many others become equivalent. Because, in addition to off64_t, "64"-functions and structures are used very consistently in the code I have hold off sending a patch changing these. I recall also seeing in some commit messages that at some sites off64_t was changed to int64_t (or __int64_t...) for header portability; for these sites it might be nice to change back to off_t. Grepping the code I found one occurence in fsr/xfs_fsr.c of off_t (not off64_t) which will be affected by the change (on 32bit linux). Right now the F_GETLK fcntl with the struct flock is used there instead of F_GETLK64 with struct flock64. The current usage is ok because the off_t arguments are only used for the value 0 which happily fits into variables of any size. After the change, the fcntl F_GETLK64, struct flock64 and off64_t will be used instead, leading to no visible change in behavior. Felix From david@fromorbit.com Tue Jun 21 18:30:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F25CF7CA1 for ; Tue, 21 Jun 2016 18:30:05 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8C952AC003 for ; Tue, 21 Jun 2016 16:30:05 -0700 (PDT) X-ASG-Debug-ID: 1466551798-04bdf05e6d15b20001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id iKLowmN0Y1VJ4Jja for ; Tue, 21 Jun 2016 16:29:59 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AUDgBazWlXEJgMLHldgz6BU4J2g3mfNQaMOIYGhAmGEQQCAoE1TQEBAQEBAQcBAQEBAQECPkCETAEBBDocFgoDEAgDGAklDwUlAwcaE4gvwmkBAQgCJR6FQYUVihsFmHmJAIUigXONOkiGCYknglwcgV4qMopIAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 22 Jun 2016 08:59:42 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFV6y-0001ZY-8F; Wed, 22 Jun 2016 09:29:40 +1000 Date: Wed, 22 Jun 2016 09:29:40 +1000 From: Dave Chinner To: Eric Sandeen Cc: xfs@oss.sgi.com Subject: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Message-ID: <20160621232940.GQ12670@dastard> X-ASG-Orig-Subj: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> <1466441562-12317-3-git-send-email-bfoster@redhat.com> <20160621090153.GB28212@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466551798 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2393 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30643 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 21, 2016 at 08:54:04AM -0500, Eric Sandeen wrote: > > > On 6/21/16 4:01 AM, Carlos Maiolino wrote: > > On Mon, Jun 20, 2016 at 12:52:42PM -0400, Brian Foster wrote: > >> Update the inode btree scanning functions to process sparse inode chunks > >> correctly. For filesystems with sparse inode support enabled, process > >> each chunk a cluster at a time. Each cluster is checked against the > >> inobt record to determine if it is a hole and skipped if so. > >> > >> Note that since xfs_check is deprecated in favor of xfs_repair, this > >> adds the minimum support necessary to process sparse inode enabled > >> filesystems. In other words, this adds no sparse inode specific checks > >> or verifications. We only update the inobt scanning functions to extend > >> the existing level of verification to sparse inode enabled filesystems > >> (e.g., avoid incorrectly tracking sparse regions as inodes). Problems > >> or corruptions associated with sparse inode records must be detected and > >> recovered via xfs_repair. > >> > > > > Hi, > > > > I'm not quite sure, but a while ago, I thought I've heard some rumors about > > deprecating xfs_check, is this true or something that my mind made up for some > > weird reason? > > Yes, like Brian said above. ;) > > bfc541e xfsprogs: remove xfs_check > 12a48f5 xfsprogs: remove xfs_check references from fsck.xfs script & manpage > > However, we still run check inside xfs_db in xfstests as an independent > verification step: > > 187bccd xfstests: Remove dependence of xfs_check script > > +# xfs_check script is planned to be deprecated. But, we want to > +# be able to invoke "xfs_check" behavior in xfstests in order to > +# maintain the current verification levels. > +_xfs_check() Right - it's a secondary set of code that effectively tells us whether repair is detecting all the problems it should. i.e. if check fails and repair doesn't, then we've got a bug in repair that needs fixing. Also, the check code is really just an "addon" to other functionality in xfs_db (e.g. blockget) that we have to keep, so removing check doesn't really gain us all that much in terms of reduced maintenance overhead. So long as we can easily keep check up to date with new features I think we shoul dbe keeping it... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Tue Jun 21 18:47:23 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1624B7CA1 for ; Tue, 21 Jun 2016 18:47:23 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id CC093304039 for ; Tue, 21 Jun 2016 16:47:19 -0700 (PDT) X-ASG-Debug-ID: 1466552837-04bdf05e6d16390001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id EbnQ7wGgI9BVUH5q for ; Tue, 21 Jun 2016 16:47:17 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CiDgAX0WlXEJgMLHldgz6BU4J2g3mfNgaMOIYGhAmGEQICAQECgTVNAQEBAQEBBwEBAQEBAQI+QIRLAQEBAwE6HCMFCwgDDgoJJQ8FJQMHGhOIKAfCaAEBAQEGAQEBASMehUGFFYdsgi8Fk0iFMY4ijy2PeIRWKjKKSAEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 22 Jun 2016 09:17:18 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFVO0-0001bL-8s; Wed, 22 Jun 2016 09:47:16 +1000 Date: Wed, 22 Jun 2016 09:47:16 +1000 From: Dave Chinner To: Eryu Guan Cc: fstests@vger.kernel.org, xfs@oss.sgi.com Subject: Re: [PATCH] xfs/186: run test on expected XFS configuration Message-ID: <20160621234716.GC27480@dastard> X-ASG-Orig-Subj: Re: [PATCH] xfs/186: run test on expected XFS configuration References: <1466510507-17548-1-git-send-email-eguan@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466510507-17548-1-git-send-email-eguan@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466552837 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1124 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30643 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 21, 2016 at 08:01:47PM +0800, Eryu Guan wrote: > Usually xfs/186 _notrun on crc enabled XFS because of > _require_attr_v1, since v2 attr format is always enabled on v5 XFS. > > But when testing on 512B block size XFS, i.e. MKFS_OPTIONS="-m crc=0 > -b size=512", test fails. This is because crc enalbed XFS was *enabled > created in the end, not 512B block size XFS with crc disabled, and > that's not what we want to test. > > The reason why _scratch_mkfs_xfs creates a different XFS than > expected is that, it may ignore $MKFS_OPTIONS if mkfs fails due to > conflicts between $MKFS_OPTIONS and the provided mkfs options. > > In the case of xfs/186, "-b size=512" conflicts with "-i size=512", > and the first mkfs fails, then it ends up with a 4k block size XFS > with crc enabled (the default config). > > Fix it by checking crc enablement status and attr version in the > test, to make sure it's testing on expected XFS. > > Signed-off-by: Eryu Guan Looks fine. Reviewed-by: Dave Chinner -- Dave Chinner david@fromorbit.com From david@fromorbit.com Tue Jun 21 19:29:50 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D85657CA1 for ; Tue, 21 Jun 2016 19:29:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 955AA8F8033 for ; Tue, 21 Jun 2016 17:29:50 -0700 (PDT) X-ASG-Debug-ID: 1466555386-04cb6c063c11790001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id zzA175SMvb7bNK6I for ; Tue, 21 Jun 2016 17:29:46 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 22 Jun 2016 09:59:19 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFW2f-0001hd-7b; Wed, 22 Jun 2016 10:29:17 +1000 Date: Wed, 22 Jun 2016 10:29:17 +1000 From: Dave Chinner To: xfs@oss.sgi.com Cc: linux-fsdevel@vger.kernel.org, rpeterso@redhat.com Subject: [ANNOUNCE] xfs: for-next branch updated to f477ced Message-ID: <20160622002917.GH27480@dastard> X-ASG-Orig-Subj: [ANNOUNCE] xfs: for-next branch updated to f477ced MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="xHFwDpU9dbj6ez1V" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466555386 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4611 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30645 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- --xHFwDpU9dbj6ez1V Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi folks, The for-next branch of the xfs kernel repository at git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git has just been updated. This update includes the long-awaited iomap-based IO path infrastructure changes that Christoph has finished off, along with a few bug fixes and the first handful of miscellaneous changes from Darrick's mega-rmap patchset. The iomap infrastructure patches are in their own separate branch - fs-4.8-iomap-infrastructure - so it can be considered a stable branch and hence can be merged into other fs trees so they can start adding their own iomap-based work. It will be included in the linux-next build by the merge into the XFS tree's for-next branch. Any bug fixes that are needed will be appended to this branch, so please cc me on bug reports so I see them quickly. Cheers, Dave. The new head of the for-next branch is commit: f477ced Merge branch 'xfs-4.8-misc-fixes-2' into for-next New Commits: Brian Foster (2): [fa5a4f5] xfs: cancel eofblocks background trimming on remount read-o= nly [408fd48] xfs: refactor xfs_reserve_blocks() to handle ENOSPC correct= ly Christoph Hellwig (14): [199a31c] fs: move struct iomap from exportfs.h to a separate header [ae259a9] fs: introduce iomap infrastructure [9a286f0] fs: support DAX based iomap zeroing [8be9f56] fs: iomap based fiemap implementation [3b3dce0] xfs: make xfs_bmbt_to_iomap available outside of xfs_pnfs.c [f0c6bcb] xfs: reorder zeroing and flushing sequence in truncate [68a9f5e] xfs: implement iomap based buffered write path [6e8a27a] xfs: remove buffered write support from __xfs_get_blocks [d2bb140] xfs: use iomap fiemap implementation [459f0fb] xfs: use iomap infrastructure for DAX zeroing [7bb41db] xfs: handle 64-bit length in xfs_iozero [570b621] xfs: use xfs_zero_range in xfs_zero_eof [bdb0d04] xfs: split xfs_free_file_space in manageable pieces [3c2bdc9] xfs: kill xfs_zero_remaining_bytes Darrick J. Wong (6): [3f94c44] xfs: check offsets of variable length structures [479c641] xfs: enable buffer deadlock postmortem diagnosis via ftrace [128f24d] xfs: check for a valid error_tag in errortag_add [59bad07] xfs: rearrange xfs_bmap_add_free parameters [e66a4c6] xfs: convert list of extents to free into a regular list [19b54ee] xfs: refactor btree maxlevels computation Dave Chinner (4): [07931b7] Merge branch 'fs-4.8-iomap-infrastructure' into for-next [9b7fad2] Merge branch 'xfs-4.8-iomap-write' into for-next [4d89e20] xfs: separate freelist fixing into a separate helper [f477ced] Merge branch 'xfs-4.8-misc-fixes-2' into for-next Code Diffstat: fs/Kconfig | 3 + fs/Makefile | 1 + fs/buffer.c | 76 ++++++- fs/internal.h | 3 + fs/iomap.c | 497 +++++++++++++++++++++++++++++++++++++= +++++++ fs/nfsd/blocklayout.c | 1 + fs/nfsd/blocklayoutxdr.c | 1 + fs/xfs/Kconfig | 1 + fs/xfs/libxfs/xfs_alloc.c | 99 +++++---- fs/xfs/libxfs/xfs_alloc.h | 2 + fs/xfs/libxfs/xfs_bmap.c | 51 ++--- fs/xfs/libxfs/xfs_bmap.h | 18 +- fs/xfs/libxfs/xfs_bmap_btree.c | 2 +- fs/xfs/libxfs/xfs_btree.c | 19 ++ fs/xfs/libxfs/xfs_btree.h | 2 + fs/xfs/libxfs/xfs_ialloc.c | 28 +-- fs/xfs/xfs_aops.c | 283 ++----------------------- fs/xfs/xfs_bmap_util.c | 375 ++++++++++++++------------------- fs/xfs/xfs_bmap_util.h | 1 - fs/xfs/xfs_buf.c | 8 +- fs/xfs/xfs_error.c | 3 + fs/xfs/xfs_file.c | 193 ++--------------- fs/xfs/xfs_fsops.c | 105 ++++++---- fs/xfs/xfs_icache.c | 2 +- fs/xfs/xfs_icache.h | 1 + fs/xfs/xfs_inode.h | 3 +- fs/xfs/xfs_iomap.c | 171 +++++++++++++++ fs/xfs/xfs_iomap.h | 7 + fs/xfs/xfs_iops.c | 113 ++-------- fs/xfs/xfs_ondisk.h | 25 ++- fs/xfs/xfs_pnfs.c | 27 +-- fs/xfs/xfs_super.c | 13 +- fs/xfs/xfs_trace.h | 4 + include/linux/exportfs.h | 16 +- include/linux/iomap.h | 70 +++++++ 35 files changed, 1262 insertions(+), 962 deletions(-) create mode 100644 fs/iomap.c create mode 100644 include/linux/iomap.h --=20 Dave Chinner david@fromorbit.com --xHFwDpU9dbj6ez1V Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJXadvcAAoJEK3oKUf0dfodOCwP/A/v/EkPWznzgoFP5+9f87VO i+PgKeaupZWg6GqLxvjg2s56RVZXB7nhAfmmssiPaZ/riB7JZvumKedrX7/2E7DY nkd7/O4nAY6ELW9kHzKsRUkaqzScpNBCrDRfjcGmCRC73sgrh2kfvetY8qgY6iXm oGUNb7T8IEXHPP6ZSeiP1AsaZjHkoEK/BOwScYHmiVhRfj80+Afd+1wOQh9wNexv XiRPrJ99oxXbQVLSWkEadu66S0bsvZb1TgV7h43/hsgXDne9JkTJGV/een9sgX2N Cg+GpHhGbcfpMJCNUtRM0XSRnEuLL3exyab1SefKzJLKo59AkOjziJMN1YNvO8br EOD18+VGCykwIeBN9PTZa1krHOpkcAFvcoUVQFZRtRey/0EyykK6Vh4f3CNjRPGr GcqPfIxB2qKhqRCEztoTDYiCb3p4bjiguMfEAz4qK6J/tQptte74X402caISLAbY 0wT9CnupBUUe0ZGUi1x9MI4VcLbBiWnVOW3B9CA6ApJqZzoOXQ++hALXJRX4I8Zs i+TDowiBwNNL55odniv1XC3Dlm/K4TkItl2ESB1GBr8Qn0c0nCsq93X9muC3NOyu oba/XwwkMoXcuYH4oNJYDtIS/KZ/rlrUJ/P78Qt72YQ9H0/YoF0mqotGmARl9j/F vwNcCGRp3mlIFp570ZHq =ahkn -----END PGP SIGNATURE----- --xHFwDpU9dbj6ez1V-- From david@fromorbit.com Tue Jun 21 20:03:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B704F7CA3 for ; Tue, 21 Jun 2016 20:03:28 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8774F8F8035 for ; Tue, 21 Jun 2016 18:03:25 -0700 (PDT) X-ASG-Debug-ID: 1466557402-04cbb027381a2d0001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id GkDOMVdEEkIZRKTT for ; Tue, 21 Jun 2016 18:03:22 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AiDQDK4mlXEJgMLHlTCoM+gVOGb58wAQEBAQEBBow4ig+GEQQCAoE2TQEBAQEBAQcBAQEBAQEBAT5AhE0BAQQ6HCMQCAMOCgklDwUlAwcaExuIFMJaAQEBBwIlHoVBhRWEGIYDBZh8jiOPLY96glwcgV4qMopxAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 22 Jun 2016 10:33:21 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFWZc-0001lZ-DD; Wed, 22 Jun 2016 11:03:20 +1000 Date: Wed, 22 Jun 2016 11:03:20 +1000 From: Dave Chinner To: Michal Hocko Cc: Peter Zijlstra , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160622010320.GR12670@dastard> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160520001714.GC26977@dastard> <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> <20160602232254.GR12670@dastard> <20160606122022.GH11895@dhcp22.suse.cz> <20160615072154.GF26977@dastard> <20160621142628.GG30848@dhcp22.suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160621142628.GG30848@dhcp22.suse.cz> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466557402 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3169 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30646 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 21, 2016 at 04:26:28PM +0200, Michal Hocko wrote: > On Wed 15-06-16 17:21:54, Dave Chinner wrote: > [...] > > Hopefully you can see the complexity of the issue - for an allocation > > in the bmap btree code that could occur outside both inside and > > outside of a transaction context, we've got to work out which of > > those ~60 high level entry points would need to be annotated. And > > then we have to ensure that in future we don't miss adding or > > removing an annotation as we change the code deep inside the btree > > implementation. It's the latter that is the long term maintainence > > problem the hihg-level annotation approach introduces. > > Sure I can see the complexity here. I might still see this over > simplified but I originally thought that the annotation would be used at > the highest level which never gets called from the transaction or other > NOFS context. So all the layers down would inherit that automatically. I > guess that such a place can be identified from the lockdep report by a > trained eye. Which, as I said before, effectively becomes "turn off lockdep reclaim context checking at all XFS entry points". Yes, we could do that, but it's a "big hammer" solution and there are more entry points than there are memory allocations that need annotations.... > > > > I think such an annotation approach really requires per-alloc site > > > > annotation, the reason for it should be more obvious from the > > > > context. e.g. any function that does memory alloc and takes an > > > > optional transaction context needs annotation. Hence, from an XFS > > > > perspective, I think it makes more sense to add a new KM_ flag to > > > > indicate this call site requirement, then jump through whatever > > > > lockdep hoop is required within the kmem_* allocation wrappers. > > > > e.g, we can ignore the new KM_* flag if we are in a transaction > > > > context and so the flag is only activated in the situations were > > > > we currently enforce an external GFP_NOFS context from the call > > > > site..... > > > > > > Hmm, I thought we would achive this by using the scope GFP_NOFS usage > > > which would mark those transaction related conctexts and no lockdep > > > specific workarounds would be needed... > > > > There are allocations outside transaction context which need to be > > GFP_NOFS - this is what KM_NOFS was originally intended for. > > Is it feasible to mark those by the scope NOFS api as well and drop > the direct KM_NOFS usage? This should help to identify those that are > lockdep only and use the annotation to prevent from the false positives. I don't understand what you are suggesting here. This all started because we use GFP_NOFS in a handful of places to shut up lockdep and you didn't want us to use GFP_NOFS like that. Now it sounds to me like you are advocating setting unconditional GFP_NOFS allocation contexts for entire XFS code paths - whether it's necessary or not - to avoid problems with lockdep false positives. I'm clearly not understanding something here.... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Tue Jun 21 20:43:03 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 50EF37CA3 for ; Tue, 21 Jun 2016 20:43:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id AC85BAC002 for ; Tue, 21 Jun 2016 18:42:59 -0700 (PDT) X-ASG-Debug-ID: 1466559776-04cbb027371bb70001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id b8pKdXImHb0UmRol for ; Tue, 21 Jun 2016 18:42:56 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2D2DQAQ7GlXEJgMLHldgz5WfYZvnzEBAQEBAQEGiEuDbYoPGoV3AgIBAQKBOE0BAQEBAQEHAQEBAQEBAQE+QIRNAQEEOhwjEAgDGAklDwUNGAMHGhOIFgMWvmUNg3UBAQgCASQehUGFFYJDh1gFmEg0hgiGK4FwgXONOoZRgTqHb4RWKjKKcQEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 22 Jun 2016 11:12:54 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFXBt-0001q0-B4; Wed, 22 Jun 2016 11:42:53 +1000 Date: Wed, 22 Jun 2016 11:42:53 +1000 From: Dave Chinner To: Reinoud Koornstra Cc: Eric Sandeen , Christoph Hellwig , Daniel Wagner , viro@zeniv.linux.org.uk, xfs@oss.sgi.com Subject: Re: crash in xfs in current Message-ID: <20160622014253.GS12670@dastard> X-ASG-Orig-Subj: Re: crash in xfs in current References: <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> <20160609022238.GY26977@dastard> <00bbe658-a891-3771-ca1d-5661a8b6ab61@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466559776 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1595 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30646 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 14, 2016 at 11:40:23PM -0600, Reinoud Koornstra wrote: > On Wed, Jun 8, 2016 at 9:42 PM, Reinoud Koornstra > wrote: > > On Wed, Jun 8, 2016 at 8:56 PM, Eric Sandeen wrote: > >> On 6/8/16 9:53 PM, Reinoud Koornstra wrote: > >> > >>>> In your Linus git tree: > >>>> > >>>> $ git remote add xfsdev git://git.kernel.org/git/dgc/linux-xfs.git > >>>> $ git remote update > >>>> $ git checkout -b xfsdev-merge v4.6 > >>>> $ git merge xfsdev/xfs-for-linus-4.7-rc1 > >>> > >>> Tried to do this: > >>> > >>> reinoud@router-dev:~/Downloads/kernel_current$ git remote add xfsdev > >>> git://git.kernel.org/git/dgc/linux-xfs.git > >> > >> I think that should be: > >> > >> git://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git > > > > Ok That worked better indeed. :) > > I've tested the way you and Dave described. > Indeed, I do not see the issues appearing in that xfsdev tree. > So it works good there. > For verification, I tried when I was upon this state (so this is a good state): Ok, that's good to hear. Now for some more testing: Al Viro just pushed some fixes to the parallel lookup code that may fix this problem. Al asked this question: | Can that be triggered on 4e82901 + cherry-pick of e7d6ef979? | Same for 9f541801 + e7d6ef979? Those commits are all in the current Linus tree - would you be able to test them? (i.e. check out tree to 4e82901, then just cherry pick the single commit (e7d6ef979) on top of that). Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Tue Jun 21 21:04:01 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EFD5F7CA3 for ; Tue, 21 Jun 2016 21:04:00 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 56F0AAC002 for ; Tue, 21 Jun 2016 19:03:57 -0700 (PDT) X-ASG-Debug-ID: 1466561030-04cb6c063f13ea0001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id GdBwwgcuSsOy3y8b for ; Tue, 21 Jun 2016 19:03:51 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CEHQDh8GlXEJgMLHldgz4iNH2Gb58ZAhYBAQEBAQEGgQ+LKSqFXIQJFwOFdwICAYE5TQEBAQEBAQcBAQEBAQEBAT5AhSk7JDQFJQMHLYgvojWgTg4ehUGJJQ0KgmILQIJHBYgTkGmGCIgbgXNOhAWIZQKGUYkpggsLAQEBQxyBXioyiS0BJYEeAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 22 Jun 2016 11:32:44 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFXV5-0001tY-QM for xfs@oss.sgi.com; Wed, 22 Jun 2016 12:02:43 +1000 Date: Wed, 22 Jun 2016 12:02:43 +1000 From: Dave Chinner To: xfs@oss.sgi.com Subject: [ANNOUNCE] xfsprogs: master branch updated to v4.7.0-rc1 Message-ID: <20160622020243.GT12670@dastard> X-ASG-Orig-Subj: [ANNOUNCE] xfsprogs: master branch updated to v4.7.0-rc1 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="GxcwvYAGnODwn7V8" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466561030 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4956 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30647 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- --GxcwvYAGnODwn7V8 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi Folks, The xfsprogs repository at: git://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git has just been updated and tagged as v4.7.0-rc1. This is the first candidate release of v4.7.0 with the libxfs codebase up to date with the kernel 4.7-rc4 code base. Please test and report any problems you find. -Dave. The new head of the master branch is commit: fb2595e xfsprogs: Release v4.7-rc1 New Commits: Alex Lyakas (1): [4d9e732] xfs: optimise xfs_iext_destroy Bill O'Donnell (3): [82c3a17] libxcmd: generalize topology functions [1b1b535] xfs_repair: new secondary superblock search method [ef12e07] xfs_repair: further improvement on secondary superblock sea= rch method Brian Foster (5): [09c93e5] xfs_db: Revert "xfs_db: make check work for sparse inodes" [ea8a48f] xfs_check: process sparse inode chunks correctly [8359e0b] xfs: update freeblocks counter after extent deletion [01d1b78] xfs: refactor delalloc indlen reservation split into helper [731ccdf] xfs: borrow indirect blocks from freed extent when available Christoph Hellwig (9): [721948f] xfs.h: define XFS_IOC_FREEZE even if FIFREEZE is defined [2be9e93] linux.h: include [0268fdc] xfs: remove xfs_trans_get_block_res [d2fd405] xfs: always set rvalp in xfs_dir2_node_trim_free [219eec7] xfs: factor out a helper to initialize a local format inode= fork [4cab415] xfs: optimize inline symlinks [9074815] xfs: better xfs_trans_alloc interface [8e95425] xfs: remove transaction types [408c66d] xfs: improve kmem_realloc Darrick J. Wong (1): [d9b2595] xfs: fix computation of inode btree maxlevels Dave Chinner (3): [86769b3] xfs_db: allow recalculating CRCs on invalid metadata [0ebbf1d] db: limit AGFL bno array printing [fb2595e] xfsprogs: Release v4.7-rc1 Eric Sandeen (5): [027e6ef] xfs_db: defang frag command [a8b6f52] xfs_quota: check report_mount return value [ce211a6] mkfs.xfs: annotate fallthrough cases in cvtnum [f61be1b] xfs_quota: only round up timer reporting > 1 day [643f6ac] xfs_repair: set rsumino version to 2 Jan Tulak (4): [2942ff4] mkfs: fix -l su minval [0b514e3] mkfs: update manpage for -i size [ef92dd5] mkfs: better error with incorrect b/s value suffix usage [587636b] mkfs: test that -l su is a multiple of block size Kirill A. Shutemov (1): [b2327e1] mm, fs: get rid of PAGE_CACHE_* and page_cache_{get,release= } macros Luis de Bethencourt (1): [4d4a192] xfs: remove impossible condition Code Diffstat: Makefile | 3 +- VERSION | 4 +- configure.ac | 2 +- db/check.c | 274 ++++++++++++----------------------- db/fprint.c | 2 +- db/frag.c | 4 + db/io.c | 7 + db/io.h | 1 + db/print.c | 7 +- db/type.c | 137 ++++++++++-------- db/type.h | 2 + db/write.c | 59 ++++++-- debian/rules | 2 +- doc/CHANGES | 20 +++ include/Makefile | 1 + include/kmem.h | 2 +- include/libxcmd.h | 56 ++++++++ include/linux.h | 1 + include/xfs_trans.h | 7 +- libxcmd/Makefile | 2 +- libxcmd/topology.c | 342 ++++++++++++++++++++++++++++++++++++++++++= ++ libxfs/kmem.c | 2 +- libxfs/libxfs_api_defs.h | 1 - libxfs/libxfs_priv.h | 3 +- libxfs/trans.c | 53 +++---- libxfs/util.c | 5 +- libxfs/xfs_attr.c | 58 ++------ libxfs/xfs_bmap.c | 192 ++++++++++++++++--------- libxfs/xfs_bmap_btree.c | 4 +- libxfs/xfs_dir2_node.c | 4 +- libxfs/xfs_dir2_sf.c | 9 +- libxfs/xfs_fs.h | 8 +- libxfs/xfs_ialloc.c | 4 +- libxfs/xfs_inode_fork.c | 101 ++++++++----- libxfs/xfs_inode_fork.h | 1 + libxfs/xfs_log_format.h | 5 + libxfs/xfs_sb.c | 8 +- libxfs/xfs_shared.h | 102 +------------ libxlog/xfs_log_recover.c | 2 +- man/man8/mkfs.xfs.8 | 2 +- mkfs/Makefile | 4 +- mkfs/proto.c | 51 ++++--- mkfs/xfs_mkfs.c | 380 ++++++------------------------------------= ------- quota/report.c | 6 +- quota/util.c | 12 ++ repair/Makefile | 5 +- repair/phase5.c | 8 +- repair/phase6.c | 85 ++++------- repair/phase7.c | 4 +- repair/sb.c | 122 ++++++++++++---- 50 files changed, 1142 insertions(+), 1034 deletions(-) create mode 100644 include/libxcmd.h create mode 100644 libxcmd/topology.c --=20 Dave Chinner david@fromorbit.com --GxcwvYAGnODwn7V8 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJXafHDAAoJEK3oKUf0dfodgkgP/013xoU4rehexw/ENszeDqaH ap+YG4mHURFxCzQNixGWYCweKSu7RKQEXGDqpj6WxPrCuPCPIOsxTENKhZNkJA1j RsYl24Lyrv4A46xM/s5l44gGWEeSsX1HJvOSMo2x8GOZ0bMvg5KOoGeAJMoINCdl Kcj86mpyutXGuvSnOqh3GoXSriREcy+YO5IqVgfmF78RhJ67WEPE+rvEm5J50/rh MI91USGVw0/Wi680Rqzt5HdH2ZpI8/9Nh6esVUs0eHrWlLwQk2w7XX81ppnVQat6 ehhz2NTKMYZJ1Yron97pgYIE68r0emSZYjwAygxZB9dfdYzzJNQr92ODXfc2DCIs FvorIosazf0p0aO7F/8KYTnEAa7acrxgHeboKgBhQ2J5iGtmbmJ3/P+R7Wfiny6Y R+AOVls2Kntq2ABcpzpu1cKZgmP9Pfl8vYu8uzZ5AgZg6fo84ighEUI+EZKCN8wl MP+zdtFwNLPMdbFBtOkkAWYgjq/WQsT74+99d7C1cDsFpq/i1Ra8VGiRvYGIeDiz vGhgH9tXWt3PndSFVn8Ds0baNhEaeNL46Us3bnYGFEqutgXLxAVFO2buO+m9zhok iRQrtgKyJG2aHuqPlaoDHMtMbWtEzcNwZcjwou/eFeH9BexSyERpB6GGNAQ+tnfp G9MjuvGvr0lRGKJEB1Tb =JS/4 -----END PGP SIGNATURE----- --GxcwvYAGnODwn7V8-- From ngkaho1234@gmail.com Tue Jun 21 21:50:55 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,T_DKIM_INVALID autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6DA037CA3 for ; Tue, 21 Jun 2016 21:50:55 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id D2596AC001 for ; Tue, 21 Jun 2016 19:50:54 -0700 (PDT) X-ASG-Debug-ID: 1466563852-04cb6c063e15070001-NocioJ Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by cuda.sgi.com with ESMTP id QykmijlWdM90JXWR (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 21 Jun 2016 19:50:52 -0700 (PDT) X-Barracuda-Envelope-From: ngkaho1234@gmail.com X-Barracuda-Effective-Source-IP: mail-pf0-f195.google.com[209.85.192.195] X-Barracuda-Apparent-Source-IP: 209.85.192.195 Received: by mail-pf0-f195.google.com with SMTP id i123so2688153pfg.3 for ; Tue, 21 Jun 2016 19:50:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:from:date:message-id:subject:to; bh=whk1osEFe944YkALkqCaorOYObHCjBrN+2t9Tpbh+pw=; b=zmS9NvhrCXjkn/PHVmLiLpSoT8eQSGF8i8ci8G7nLRWnRIXGivr4wT1LAFHg305bES 4XfRINxVSV5fK8v1ZEVopAvjlrGyrd3yLBHR0yogyNcLDLhCTTSe3JofN0ewVnc55AcK TQmiJ/bGj4wG9nD/KtNe1soa44mOf+/5jEgQVp/4tlj5Qn+7D31TEKKoL9EvHPYjn7yo TkZzG6cRMb8C/OocaJvOmWNlDHXuqozzQy4KS/YN0X0K31xEmM9Kknyg5v18hDNJ28MO RYKefobohTk+b4YWuxrV227W47zYkQwcoCYTABfFonX3ECwUt62FX0EtCFzM7Foqdlzr eIcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=whk1osEFe944YkALkqCaorOYObHCjBrN+2t9Tpbh+pw=; b=ALnsop5VpTB4i1IjUKTSTuLuM/th7i0aLOfj3q8HS9VeNx4+YHE9L1X23J5QY2OcWN CZMEQJ0Ok18vQeXjRosKpfgdiH/+AszQnzCHlPunOHdUgzhn4kPouuOFF/44ovV+hu7L bPoGYCbYM6WADlZ2SzmO4lecPTlFnmSKxSllx6VVNmwx6l1HzfAvDk6VYo/qiBCY78Iw pnBnjN2Go+BwOZoMvWLFQ5yTzucdQ/plsM89KLSE+5UjEm/ygCeRNKic6T4m5cbmRlx3 oEW/HUHJgu+sHyF4Q9oeDDJ6mTDUxLJ5+VqgvYW0+VhsqzxAt7gRV1CZbe3XWfBh3kUj vvjA== X-Gm-Message-State: ALyK8tL6W6R+5oizgoxQWwwFEgV9Lxq3/L3vMIbdTPISF4FKXrmNi2RTCPoaujgBig9dEQcrCcDxr0YM58++cg== X-Received: by 10.98.80.134 with SMTP id g6mr31835829pfj.60.1466563851791; Tue, 21 Jun 2016 19:50:51 -0700 (PDT) MIME-Version: 1.0 Received: by 10.66.66.37 with HTTP; Tue, 21 Jun 2016 19:50:51 -0700 (PDT) From: Kaho Ng Date: Wed, 22 Jun 2016 10:50:51 +0800 Message-ID: Subject: [PATCH] xfs: indentation fix in xfs_btree_get_iroot() To: xfs@oss.sgi.com X-ASG-Orig-Subj: [PATCH] xfs: indentation fix in xfs_btree_get_iroot() Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-pf0-f195.google.com[209.85.192.195] X-Barracuda-Start-Time: 1466563852 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 881 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, MAILTO_TO_SPAM_ADDR X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30648 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 MAILTO_TO_SPAM_ADDR URI: Includes a link to a likely spammer email Spacebars are converted to tabs Signed-off-by: Kaho Ng --- fs/xfs/libxfs/xfs_btree.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 1f88e1c..41724be 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -543,12 +543,12 @@ xfs_btree_ptr_addr( */ STATIC struct xfs_btree_block * xfs_btree_get_iroot( - struct xfs_btree_cur *cur) + struct xfs_btree_cur *cur) { - struct xfs_ifork *ifp; + struct xfs_ifork *ifp; - ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); - return (struct xfs_btree_block *)ifp->if_broot; + ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); + return (struct xfs_btree_block *)ifp->if_broot; } /* -- 2.9.0 From ngkaho1234@gmail.com Tue Jun 21 23:11:43 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,T_DKIM_INVALID autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C7A747CA3 for ; Tue, 21 Jun 2016 23:11:43 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4297DAC001 for ; Tue, 21 Jun 2016 21:11:43 -0700 (PDT) X-ASG-Debug-ID: 1466568700-04cbb0273721610001-NocioJ Received: from mail-pa0-f65.google.com (mail-pa0-f65.google.com [209.85.220.65]) by cuda.sgi.com with ESMTP id Bl0Okn1be2tlxf1D (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Tue, 21 Jun 2016 21:11:41 -0700 (PDT) X-Barracuda-Envelope-From: ngkaho1234@gmail.com X-Barracuda-Effective-Source-IP: mail-pa0-f65.google.com[209.85.220.65] X-Barracuda-Apparent-Source-IP: 209.85.220.65 Received: by mail-pa0-f65.google.com with SMTP id hf6so2821422pac.2 for ; Tue, 21 Jun 2016 21:11:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:subject:from:to:cc:date:mime-version :content-transfer-encoding; bh=KY6I7xq1UA8ba54ctQxxasSJ/haZP64FHlKQ2l0Cfj8=; b=DgWGcZPr4KTA5pY/7q1aesL4PJ9VZXXktRb6v+9hi3W/k2CTj0N74t9KwL/d2WHHL+ zGvi+Gd1w4zAlgdqGqNjF8mTka1eBzZI2wiAXBuh4XApAmz4LmM/Yd3MEa62SqRa3v16 WpueFbLG5iM2QPUUegt1hqDcmFv1cwqdJXXhqUaVMmq8xpBoR0/TjJSBul/2Q+MKmEJ7 qNTKv/r3mMCJuKyLzEO/1fGfKYJ/glCQwm0kAtQ/A1SXiyk88wHLPIYzYLTasBzdXozj GKfLfjAmajPacTeyAyOCZ+lDJYqHz+2qZEyPrK2OGQT3cbEtBZ8+YRh/EozDWS/codF/ I2sA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:subject:from:to:cc:date:mime-version :content-transfer-encoding; bh=KY6I7xq1UA8ba54ctQxxasSJ/haZP64FHlKQ2l0Cfj8=; b=XKtwl/pCjj2WPvA8VxQVGOiJVvgzdtAHXdYGtG+Bd1AdKH7ZNOO3EGLpNkHYwRcF5M /eL1AZtoJL+ppmoKnfU2FQGdoh5i1fwDGV+X21CJCxgkz/UD0ER+wGJM7JFqnLJYPrBz sZ+45cWXUFukmWJqiLDf3K869vthMHtOahqNE9iWyQnzdyvwCCvVSqTPGHSJjxKkQueW y5fQss1XyzEwjPYnYu+/yN3xv7/Z9fAP36C6HFJ1D+RH8Y3+3rGlyQbv6Uy1B2jXSR30 V11CbWwh+RlRu3e33XgZYwTlf0PhSfGBe237Cp7rMi6wzWcHASCzr0cvRkP5GZrTu1/O 0WVw== X-Gm-Message-State: ALyK8tJA89u8BrD98Bo58jM20ipn5aPn3mYOgssho9dylZUaFhaVr0lj9SoaU+PqLO2qDQ== X-Received: by 10.66.86.103 with SMTP id o7mr10369582paz.5.1466568700225; Tue, 21 Jun 2016 21:11:40 -0700 (PDT) Received: from zenbook.lan (119246003029.ctinets.com. [119.246.3.29]) by smtp.googlemail.com with ESMTPSA id x67sm99254550pff.47.2016.06.21.21.11.38 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 21 Jun 2016 21:11:39 -0700 (PDT) Message-ID: <1466568697.14061.1.camel@gmail.com> Subject: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() From: Kaho Ng X-ASG-Orig-Subj: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() To: "xfs@oss.sgi.com" Cc: david@fromorbit.com Date: Wed, 22 Jun 2016 12:11:37 +0800 Content-Type: text/plain; charset="UTF-8" X-Mailer: Evolution 3.20.3 Mime-Version: 1.0 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: mail-pa0-f65.google.com[209.85.220.65] X-Barracuda-Start-Time: 1466568701 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1040 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, MAILTO_TO_SPAM_ADDR X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30649 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 MAILTO_TO_SPAM_ADDR URI: Includes a link to a likely spammer email The indentation in this function is different from the other functions. Those spacebars are converted to tabs to improve readability. Signed-off-by: Kaho Ng ---  fs/xfs/libxfs/xfs_btree.c | 8 ++++----  1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 1f88e1c..4f84dde 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -543,12 +543,12 @@ xfs_btree_ptr_addr(   */  STATIC struct xfs_btree_block *  xfs_btree_get_iroot( -       struct xfs_btree_cur    *cur) + struct xfs_btree_cur *cur)  { -       struct xfs_ifork        *ifp; + struct xfs_ifork *ifp;   -       ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- >bc_private.b.whichfork); -       return (struct xfs_btree_block *)ifp->if_broot; + ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- >bc_private.b.whichfork); + return (struct xfs_btree_block *)ifp->if_broot;  }    /* --  2.9.0 From fengguang.wu@intel.com Wed Jun 22 01:03:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.9 required=5.0 tests=MISSING_HEADERS autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E661C7CA1 for ; Wed, 22 Jun 2016 01:03:27 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id A72B8304039 for ; Tue, 21 Jun 2016 23:03:24 -0700 (PDT) X-ASG-Debug-ID: 1466575399-04bdf05e6e240e0001-NocioJ Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by cuda.sgi.com with ESMTP id hXR6X42jGCftxE2Z for ; Tue, 21 Jun 2016 23:03:19 -0700 (PDT) X-Barracuda-Envelope-From: fengguang.wu@intel.com X-Barracuda-Effective-Source-IP: mga03.intel.com[134.134.136.65] X-Barracuda-Apparent-Source-IP: 134.134.136.65 X-ASG-Whitelist: Client Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP; 21 Jun 2016 23:03:18 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.26,508,1459839600"; d="gz'50?scan'50,208,50";a="980900652" Received: from bee.sh.intel.com (HELO bee) ([10.239.97.14]) by orsmga001.jf.intel.com with ESMTP; 21 Jun 2016 23:02:56 -0700 Received: from kbuild by bee with local (Exim 4.83) (envelope-from ) id 1bFbFO-000XLv-GK; Wed, 22 Jun 2016 14:02:46 +0800 Date: Wed, 22 Jun 2016 14:06:49 +0800 From: kbuild test robot Cc: kbuild-all@01.org, xfs@oss.sgi.com, Dave Chinner , "Darrick J. Wong" , Christoph Hellwig Subject: [xfs:xfs-4.8-misc-fixes-2 3/9] fs/xfs/xfs_ondisk.h:116:2: error: call to '__compiletime_assert_116' declared with attribute error: XFS: offsetof(xfs_dir2_sf_entry_t, offset) is wrong, expected 1 Message-ID: <201606221448.UGgis4S6%fengguang.wu@intel.com> X-ASG-Orig-Subj: [xfs:xfs-4.8-misc-fixes-2 3/9] fs/xfs/xfs_ondisk.h:116:2: error: call to '__compiletime_assert_116' declared with attribute error: XFS: offsetof(xfs_dir2_sf_entry_t, offset) is wrong, expected 1 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="wRRV7LY7NUeQGEoC" Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) X-SA-Exim-Connect-IP: X-SA-Exim-Mail-From: fengguang.wu@intel.com X-SA-Exim-Scanned: No (on bee); SAEximRunCond expanded to false X-Barracuda-Connect: mga03.intel.com[134.134.136.65] X-Barracuda-Start-Time: 1466575399 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2450 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 --wRRV7LY7NUeQGEoC Content-Type: text/plain; charset=us-ascii Content-Disposition: inline tree: https://git.kernel.org/pub/scm/linux/kernel/git/dgc/linux-xfs.git xfs-4.8-misc-fixes-2 head: 19b54ee66c4c5de8f8db74d5914d9a97161460bf commit: 3f94c441e2c3dea029a46a2326b2170acf2c7713 [3/9] xfs: check offsets of variable length structures config: openrisc-allmodconfig (attached as .config) compiler: or32-linux-gcc (GCC) 4.5.1-or32-1.0rc1 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git checkout 3f94c441e2c3dea029a46a2326b2170acf2c7713 # save the attached .config to linux build tree make.cross ARCH=openrisc All errors (new ones prefixed by >>): In file included from fs/xfs/xfs_super.c:48:0: In function 'xfs_check_ondisk_structs', inlined from 'init_xfs_fs' at fs/xfs/xfs_super.c:1855:26: fs/xfs/xfs_ondisk.h:114:2: error: call to '__compiletime_assert_114' declared with attribute error: XFS: sizeof(xfs_dir2_sf_entry_t) is wrong, expected 3 >> fs/xfs/xfs_ondisk.h:116:2: error: call to '__compiletime_assert_116' declared with attribute error: XFS: offsetof(xfs_dir2_sf_entry_t, offset) is wrong, expected 1 >> fs/xfs/xfs_ondisk.h:117:2: error: call to '__compiletime_assert_117' declared with attribute error: XFS: offsetof(xfs_dir2_sf_entry_t, name) is wrong, expected 3 fs/xfs/xfs_ondisk.h:118:2: error: call to '__compiletime_assert_118' declared with attribute error: XFS: sizeof(xfs_dir2_sf_hdr_t) is wrong, expected 10 vim +/__compiletime_assert_116 +116 fs/xfs/xfs_ondisk.h 108 XFS_CHECK_STRUCT_SIZE(xfs_dir2_ino8_t, 8); 109 XFS_CHECK_STRUCT_SIZE(xfs_dir2_inou_t, 8); 110 XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_entry_t, 8); 111 XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_hdr_t, 16); 112 XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_t, 16); 113 XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_tail_t, 4); > 114 XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_entry_t, 3); 115 XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, namelen, 0); > 116 XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, offset, 1); > 117 XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, name, 3); 118 XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_hdr_t, 10); 119 XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_off_t, 2); 120 --- 0-DAY kernel test infrastructure Open Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation --wRRV7LY7NUeQGEoC Content-Type: application/octet-stream Content-Disposition: attachment; filename=".config.gz" Content-Transfer-Encoding: base64 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 --wRRV7LY7NUeQGEoC-- From david@fromorbit.com Wed Jun 22 01:39:53 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 92FBB7CA3 for ; Wed, 22 Jun 2016 01:39:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id E2F26AC002 for ; Tue, 21 Jun 2016 23:39:49 -0700 (PDT) X-ASG-Debug-ID: 1466577586-04cbb0273626220001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id LvQftz0TtDpMGNMj for ; Tue, 21 Jun 2016 23:39:47 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2A4DgCnMWpXEJgMLHlegz6BU4ZvnzcGiEuDbYNhgiWECYYRAgIBAQKBME0BAQEBAQEHAQEBAQEBAj5AhE0BAQQnCwEjIxAIAxgJJQ8FDRgDBxoTiBYDFr5wDYN1AQEBBwIBJB6FQYQSgQOCQ4FPEQGFdwEEmEg0jDOBcI8tSIdEh2+EVioyiS0HCBeBHgEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 22 Jun 2016 16:09:45 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFbpA-0002Kn-0e; Wed, 22 Jun 2016 16:39:44 +1000 Date: Wed, 22 Jun 2016 16:39:43 +1000 From: Dave Chinner To: Kaho Ng Cc: "xfs@oss.sgi.com" Subject: Re: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() Message-ID: <20160622063943.GU12670@dastard> X-ASG-Orig-Subj: Re: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() References: <1466568697.14061.1.camel@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <1466568697.14061.1.camel@gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466577586 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1638 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MAILTO_TO_SPAM_ADDR X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30651 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 MAILTO_TO_SPAM_ADDR URI: Includes a link to a likely spammer email On Wed, Jun 22, 2016 at 12:11:37PM +0800, Kaho Ng wrote: > The indentation in this function is different from the other functions. > Those spacebars are converted to tabs to improve readability. > > Signed-off-by: Kaho Ng > --- > fs/xfs/libxfs/xfs_btree.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 1f88e1c..4f84dde 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -543,12 +543,12 @@ xfs_btree_ptr_addr( > */ > STATIC struct xfs_btree_block * > xfs_btree_get_iroot( > -struct xfs_btree_cur*cur) > + struct xfs_btree_cur *cur) > { > -struct xfs_ifork*ifp; > + struct xfs_ifork *ifp; > > -ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- > >bc_private.b.whichfork); > -return (struct xfs_btree_block *)ifp->if_broot; > + ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- > >bc_private.b.whichfork); > + return (struct xfs_btree_block *)ifp->if_broot; > } That's better, but your mailer is still doing weird things to the patch. It line wrapped it this time, and converted all the spaces to some wierd multi-byte character instead of a plain ascii space. What you should do is send the patch to yourself, extract it from the email you receive, and try to apply it to a clean tree. If you can do that, then the patch is not getting mangled when you send it. See Documentation/SubmittingPatches and Documentation/email-clients.txt for help. Cheers, Dave. -- Dave Chinner david@fromorbit.com From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 02:42:39 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8A2C87CA3 for ; Wed, 22 Jun 2016 02:42:39 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 04061AC003 for ; Wed, 22 Jun 2016 00:42:35 -0700 (PDT) X-ASG-Debug-ID: 1466581352-04cbb0273528600001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id 3OHdHFQpatoRUfTA (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 00:42:33 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFcnu-0003bT-4H; Wed, 22 Jun 2016 07:42:30 +0000 Date: Wed, 22 Jun 2016 00:42:30 -0700 From: Christoph Hellwig To: kbuild test robot Cc: "Darrick J. Wong" , kbuild-all@01.org, jonas@southpole.se, xfs@oss.sgi.com Subject: Re: [xfs:xfs-4.8-misc-fixes-2 3/9] fs/xfs/xfs_ondisk.h:116:2: error: call to '__compiletime_assert_116' declared with attribute error: XFS: offsetof(xfs_dir2_sf_entry_t, offset) is wrong, expected 1 Message-ID: <20160622074230.GA9508@infradead.org> X-ASG-Orig-Subj: Re: [xfs:xfs-4.8-misc-fixes-2 3/9] fs/xfs/xfs_ondisk.h:116:2: error: call to '__compiletime_assert_116' declared with attribute error: XFS: offsetof(xfs_dir2_sf_entry_t, offset) is wrong, expected 1 References: <201606221448.UGgis4S6%fengguang.wu@intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <201606221448.UGgis4S6%fengguang.wu@intel.com> User-Agent: Mutt/1.6.1 (2016-04-27) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466581353 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4235 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30653 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS On Wed, Jun 22, 2016 at 02:06:49PM +0800, kbuild test robot wrote: > config: openrisc-allmodconfig (attached as .config) > compiler: or32-linux-gcc (GCC) 4.5.1-or32-1.0rc1 This looks openrisc copied it's weird packing rules from the old ARM ABI and would need to define __arch_pack similar to ARM. Alternatively we could try to get rid of our struct types that wrap the char arrays for the unaligned fields. For the SF dir offset that would looks something like this (untested): diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index 8d4d8bc..e1d8e59 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -192,12 +192,6 @@ typedef __uint16_t xfs_dir2_data_off_t; typedef uint xfs_dir2_data_aoff_t; /* argument form */ /* - * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. - * Only need 16 bits, this is the byte offset into the single block form. - */ -typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t; - -/* * Offset in data space of a data entry. */ typedef __uint32_t xfs_dir2_dataptr_t; @@ -251,7 +245,7 @@ typedef struct xfs_dir2_sf_hdr { typedef struct xfs_dir2_sf_entry { __u8 namelen; /* actual name length */ - xfs_dir2_sf_off_t offset; /* saved offset */ + __u8 offset[2]; /* saved offset */ __u8 name[]; /* name, variable size */ /* * A single byte containing the file type field follows the inode @@ -272,13 +266,13 @@ static inline int xfs_dir2_sf_hdr_size(int i8count) static inline xfs_dir2_data_aoff_t xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) { - return get_unaligned_be16(&sfep->offset.i); + return get_unaligned_be16(sfep->offset); } static inline void xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) { - put_unaligned_be16(off, &sfep->offset.i); + put_unaligned_be16(off, sfep->offset); } static inline struct xfs_dir2_sf_entry * diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c index e5bb9cc..18cc6c7 100644 --- a/fs/xfs/libxfs/xfs_dir2_sf.c +++ b/fs/xfs/libxfs/xfs_dir2_sf.c @@ -126,11 +126,10 @@ xfs_dir2_block_sfsize( /* * Calculate the new size, see if we should give up yet. */ - size = xfs_dir2_sf_hdr_size(i8count) + /* header */ - count + /* namelen */ - count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */ - namelen + /* name */ - (i8count ? /* inumber */ + size = xfs_dir2_sf_hdr_size(i8count) + /* header */ + count * 3 * sizeof(u8) + /* namelen + offset */ + namelen + /* name */ + (i8count ? /* inumber */ (uint)sizeof(xfs_dir2_ino8_t) * count : (uint)sizeof(xfs_dir2_ino4_t) * count); if (size > XFS_IFORK_DSIZE(dp)) @@ -1048,7 +1047,8 @@ xfs_dir2_sf_toino4( i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; - sfep->offset = oldsfep->offset; + sfep->offset[0] = oldsfep->offset[0]; + sfep->offset[1] = oldsfep->offset[1]; memcpy(sfep->name, oldsfep->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, dp->d_ops->sf_get_ino(oldsfp, oldsfep)); @@ -1124,7 +1124,8 @@ xfs_dir2_sf_toino8( i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; - sfep->offset = oldsfep->offset; + sfep->offset[0] = oldsfep->offset[0]; + sfep->offset[1] = oldsfep->offset[1]; memcpy(sfep->name, oldsfep->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, dp->d_ops->sf_get_ino(oldsfp, oldsfep)); diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 0272301..3cbc1f8 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -116,7 +116,6 @@ xfs_check_ondisk_structs(void) XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, offset, 1); XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, name, 3); XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_hdr_t, 10); - XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_off_t, 2); /* log structures */ XFS_CHECK_STRUCT_SIZE(struct xfs_dq_logformat, 24); From cmaiolino@redhat.com Wed Jun 22 03:03:34 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0510C7CA3 for ; Wed, 22 Jun 2016 03:03:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id CC0F88F8035 for ; Wed, 22 Jun 2016 01:03:30 -0700 (PDT) X-ASG-Debug-ID: 1466582609-04cb6c063e1bd90001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id i30ZpFMWbJC5Njme (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 01:03:29 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 33E6D8F232 for ; Wed, 22 Jun 2016 08:03:29 +0000 (UTC) Received: from redhat.com (unused [10.10.51.227] (may be forged)) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5M83PTV029362 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 04:03:28 -0400 Date: Wed, 22 Jun 2016 10:03:24 +0200 From: Carlos Maiolino To: xfs@oss.sgi.com Subject: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Message-ID: <20160622080324.GG28212@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Mail-Followup-To: xfs@oss.sgi.com References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> <1466441562-12317-3-git-send-email-bfoster@redhat.com> <20160621090153.GB28212@redhat.com> <20160621232940.GQ12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160621232940.GQ12670@dastard> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 22 Jun 2016 08:03:29 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466582609 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2715 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 22, 2016 at 09:29:40AM +1000, Dave Chinner wrote: > On Tue, Jun 21, 2016 at 08:54:04AM -0500, Eric Sandeen wrote: > > > > > > On 6/21/16 4:01 AM, Carlos Maiolino wrote: > > > On Mon, Jun 20, 2016 at 12:52:42PM -0400, Brian Foster wrote: > > >> Update the inode btree scanning functions to process sparse inode chunks > > >> correctly. For filesystems with sparse inode support enabled, process > > >> each chunk a cluster at a time. Each cluster is checked against the > > >> inobt record to determine if it is a hole and skipped if so. > > >> > > >> Note that since xfs_check is deprecated in favor of xfs_repair, this > > >> adds the minimum support necessary to process sparse inode enabled > > >> filesystems. In other words, this adds no sparse inode specific checks > > >> or verifications. We only update the inobt scanning functions to extend > > >> the existing level of verification to sparse inode enabled filesystems > > >> (e.g., avoid incorrectly tracking sparse regions as inodes). Problems > > >> or corruptions associated with sparse inode records must be detected and > > >> recovered via xfs_repair. > > >> > > > > > > Hi, > > > > > > I'm not quite sure, but a while ago, I thought I've heard some rumors about > > > deprecating xfs_check, is this true or something that my mind made up for some > > > weird reason? > > > > Yes, like Brian said above. ;) > > > > bfc541e xfsprogs: remove xfs_check > > 12a48f5 xfsprogs: remove xfs_check references from fsck.xfs script & manpage > > > > However, we still run check inside xfs_db in xfstests as an independent > > verification step: > > > > 187bccd xfstests: Remove dependence of xfs_check script > > > > +# xfs_check script is planned to be deprecated. But, we want to > > +# be able to invoke "xfs_check" behavior in xfstests in order to > > +# maintain the current verification levels. > > +_xfs_check() > > Right - it's a secondary set of code that effectively tells us > whether repair is detecting all the problems it should. i.e. if > check fails and repair doesn't, then we've got a bug in repair that > needs fixing. > Just out of curiosity here, have we hit any case like that for the past few versions? > Also, the check code is really just an "addon" to other > functionality in xfs_db (e.g. blockget) that we have to keep, so > removing check doesn't really gain us all that much in terms of > reduced maintenance overhead. So long as we can easily keep check up > to date with new features I think we shoul dbe keeping it... > Good to know. Cheers o/ > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com > -- Carlos From cmaiolino@redhat.com Wed Jun 22 03:23:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 5B3777CA1 for ; Wed, 22 Jun 2016 03:23:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2D122304032 for ; Wed, 22 Jun 2016 01:23:39 -0700 (PDT) X-ASG-Debug-ID: 1466583817-04cb6c063d1c240001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id GOiclbrQccDHQ0eb (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 01:23:38 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6E63F3F729; Wed, 22 Jun 2016 08:23:37 +0000 (UTC) Received: from redhat.com (unused [10.10.51.227] (may be forged)) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5M8NWWN015471 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 22 Jun 2016 04:23:35 -0400 Date: Wed, 22 Jun 2016 10:23:32 +0200 From: Carlos Maiolino To: Dave Chinner Cc: Kaho Ng , "xfs@oss.sgi.com" Subject: Re: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() Message-ID: <20160622082332.GH28212@redhat.com> X-ASG-Orig-Subj: Re: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() Mail-Followup-To: Dave Chinner , Kaho Ng , "xfs@oss.sgi.com" References: <1466568697.14061.1.camel@gmail.com> <20160622063943.GU12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20160622063943.GU12670@dastard> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 22 Jun 2016 08:23:37 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466583818 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2081 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 22, 2016 at 04:39:43PM +1000, Dave Chinner wrote: > On Wed, Jun 22, 2016 at 12:11:37PM +0800, Kaho Ng wrote: > > The indentation in this function is different from the other functions. > > Those spacebars are converted to tabs to improve readability. > > > > Signed-off-by: Kaho Ng > > --- > > fs/xfs/libxfs/xfs_btree.c | 8 ++++---- > > 1 file changed, 4 insertions(+), 4 deletions(-) > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > index 1f88e1c..4f84dde 100644 > > --- a/fs/xfs/libxfs/xfs_btree.c > > +++ b/fs/xfs/libxfs/xfs_btree.c > > @@ -543,12 +543,12 @@ xfs_btree_ptr_addr( > > */ > > STATIC struct xfs_btree_block * > > xfs_btree_get_iroot( > > -struct xfs_btree_cur*cur) > > + struct xfs_btree_cur *cur) > > { > > -struct xfs_ifork*ifp; > > + struct xfs_ifork *ifp; > > > > -ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- > > >bc_private.b.whichfork); > > -return (struct xfs_btree_block *)ifp->if_broot; > > + ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- > > >bc_private.b.whichfork); > > + return (struct xfs_btree_block *)ifp->if_broot; > > } > > That's better, but your mailer is still doing weird things to the > patch. It line wrapped it this time, and converted all the spaces to > some wierd multi-byte character instead of a plain ascii space. > > What you should do is send the patch to yourself, extract it from > the email you receive, and try to apply it to a clean tree. If you > can do that, then the patch is not getting mangled when you send it. > See Documentation/SubmittingPatches and > Documentation/email-clients.txt for help. > This is a problem when sending patches from a gmail account. It's converted to a base64 format, instead of pure clean text. I'd setup git to send the patch through the gmail smtp using git send-email. So it won't screw up with the file format. Well, at least, that's what I do when I need to send patches through a gmail account :) -- Carlos From advoynyakova@list.ru Wed Jun 22 03:33:18 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.6 required=5.0 tests=HTML_MESSAGE,MIME_HTML_MOSTLY, MPART_ALT_DIFF autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 2F98D7CA1 for ; Wed, 22 Jun 2016 03:33:18 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8C6EAAC002 for ; Wed, 22 Jun 2016 01:33:14 -0700 (PDT) X-ASG-Debug-ID: 1466584380-04cbb0273829c60001-NocioJ Received: from mxs.mail.ru (91-220-97-217.ip.startechnology.pl [91.220.97.217]) by cuda.sgi.com with ESMTP id HGHQhuK7Fnfi6PlK for ; Wed, 22 Jun 2016 01:33:04 -0700 (PDT) X-Barracuda-Envelope-From: advoynyakova@list.ru X-Barracuda-Effective-Source-IP: 91-220-97-217.ip.startechnology.pl[91.220.97.217] X-Barracuda-Apparent-Source-IP: 91.220.97.217 Message-ID: From: "=?utf-8?B?0KPQv9GA0LDQstC70LXQvdC40LUg0L/QtdGA0YHQvtC90LDQu9C+0Lw=?=" To: Subject: =?utf-8?B?0KPQv9GA0LDQstC70LXQvdC40LUg0L/QtdGA0YHQvtC90LDQu9C+0LwuINCa0LDQtNGA0YsuINCi0YDRg9C00L7QstCw0Y8g0LjQvdGB0L/QtdC60YbQuNGPLg==?= Date: Wed, 22 Jun 2016 11:33:05 +0300 X-ASG-Orig-Subj: =?utf-8?B?0KPQv9GA0LDQstC70LXQvdC40LUg0L/QtdGA0YHQvtC90LDQu9C+0LwuINCa0LDQtNGA0YsuINCi0YDRg9C00L7QstCw0Y8g0LjQvdGB0L/QtdC60YbQuNGPLg==?= MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_008C_01D1CC79.D7DF4DA0" X-Priority: 3 X-MSMail-Priority: Normal Importance: Normal X-Mailer: Microsoft Windows Live Mail 15.4.3555.308 X-MimeOLE: Produced By Microsoft MimeOLE V15.4.3555.308 X-Barracuda-Connect: 91-220-97-217.ip.startechnology.pl[91.220.97.217] X-Barracuda-Start-Time: 1466584381 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9330 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.74 X-Barracuda-Spam-Status: No, SCORE=0.74 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, HTML_MESSAGE, MIME_HTML_MOSTLY, MPART_ALT_DIFF, RDNS_DYNAMIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30654 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 MIME_HTML_MOSTLY BODY: Multipart message mostly text/html MIME 0.00 HTML_MESSAGE BODY: HTML included in message 0.14 MPART_ALT_DIFF BODY: HTML and text parts are different 0.10 RDNS_DYNAMIC Delivered to trusted network by host with dynamic-looking rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 MIME. ------=_NextPart_000_008C_01D1CC79.D7DF4DA0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable =20 =20 ------=_NextPart_000_008C_01D1CC79.D7DF4DA0 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable
------=_NextPart_000_008C_01D1CC79.D7DF4DA0-- From ngkaho1234@gmail.com Wed Jun 22 05:31:02 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,T_DKIM_INVALID autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 39A337CA1 for ; Wed, 22 Jun 2016 05:31:02 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id A7940AC001 for ; Wed, 22 Jun 2016 03:30:58 -0700 (PDT) X-ASG-Debug-ID: 1466591456-04cb6c063f1ed60001-NocioJ Received: from mail-pa0-f65.google.com (mail-pa0-f65.google.com [209.85.220.65]) by cuda.sgi.com with ESMTP id AAFnmwpQ9RW4Uxb2 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 03:30:56 -0700 (PDT) X-Barracuda-Envelope-From: ngkaho1234@gmail.com X-Barracuda-Effective-Source-IP: mail-pa0-f65.google.com[209.85.220.65] X-Barracuda-Apparent-Source-IP: 209.85.220.65 Received: by mail-pa0-f65.google.com with SMTP id fg1so3672767pad.3 for ; Wed, 22 Jun 2016 03:30:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to; bh=//zVeauuaUtDrjf92Jfx2QgPbdXSosh8h0hkI231uuo=; b=DrIWvaiFYX7CVi3jWOblPeHXQ81NzGRhiShlG+L/MMnSTr09h95twfKy3IJW4tPvxl 20EA8o1r4zVtFPi3Te+F/IlPa83OeaG5y2kF3MV4BONi0xHGiHIXQ7mX8OotlZRIUgwa EhSMYZ5xe2khQtskILt2e7upy+nBqjAxF6v3POvsrtf2bTVN3dRYYfy1hIdu33GCrY+7 7OFA9IIKmoQzcfnBnqtdRYtXx1+bu0cxsPkFN1Fa/95GJCeHlFzik0WrhEUVpovW/FN4 yaDKi2FRylFY2OE9zh0bfByNmoBPzK2TVrTU24myUoRnVwI6BGFFfCqye6yTYrjWel2e 79pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=//zVeauuaUtDrjf92Jfx2QgPbdXSosh8h0hkI231uuo=; b=MGGLBQipnEHKU2TJUPb9gnoVhiuPprkNlYp7MxKU8asmbCXffZ1Ji+vZKuH/8M3MOT ydnO6vxRgexalwXsmv9PsoeNXZCmPrsamr4uw0DY9szy4FW21+TQv2GehSoRExCfewiw M1jWPEJ/AOj4ZNck3kzBSLxC2z8TQB3g/x9cmUkUbiBoc7gQdhIpAXBNXYacWnKj29Rj nAzG7np+79/buJSglBoIDn37mT5AHL12YSRsvOTWxV8FhT3bO4hTDecbPAOjuDj3W19e b5nAPPLVfsS9TiwT5HYIBcM16/GmVutVjMeEYwx9QBDs9VYKOoehhuU78PKyZWpaPMjO XN0Q== X-Gm-Message-State: ALyK8tI1DZMQA1PrCL3XC+m3+W0ZBDvukXuJpSECPwr0ysRIduKbVV4ZMb6Mx2xLHQn0yqnrmp0GZ1yoQ2LMzA== X-Received: by 10.67.5.134 with SMTP id cm6mr33819226pad.93.1466591455823; Wed, 22 Jun 2016 03:30:55 -0700 (PDT) MIME-Version: 1.0 Received: by 10.66.66.37 with HTTP; Wed, 22 Jun 2016 03:30:55 -0700 (PDT) In-Reply-To: <20160622082332.GH28212@redhat.com> References: <1466568697.14061.1.camel@gmail.com> <20160622063943.GU12670@dastard> <20160622082332.GH28212@redhat.com> From: Kaho Ng Date: Wed, 22 Jun 2016 18:30:55 +0800 Message-ID: Subject: Re: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() To: Dave Chinner , Kaho Ng , "xfs@oss.sgi.com" , cmaiolino@redhat.com X-ASG-Orig-Subj: Re: [PATCH v2] xfs: indentation fix in xfs_btree_get_iroot() Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-pa0-f65.google.com[209.85.220.65] X-Barracuda-Start-Time: 1466591456 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2297 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED, MAILTO_TO_SPAM_ADDR X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30656 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 MAILTO_TO_SPAM_ADDR URI: Includes a link to a likely spammer email Thanks for the suggestion. I am going to tidy up the things and resend it. 2016-06-22 16:23 GMT+08:00 Carlos Maiolino : > On Wed, Jun 22, 2016 at 04:39:43PM +1000, Dave Chinner wrote: >> On Wed, Jun 22, 2016 at 12:11:37PM +0800, Kaho Ng wrote: >> > The indentation in this function is different from the other functions. >> > Those spacebars are converted to tabs to improve readability. >> > >> > Signed-off-by: Kaho Ng >> > --- >> > fs/xfs/libxfs/xfs_btree.c | 8 ++++---- >> > 1 file changed, 4 insertions(+), 4 deletions(-) >> > >> > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c >> > index 1f88e1c..4f84dde 100644 >> > --- a/fs/xfs/libxfs/xfs_btree.c >> > +++ b/fs/xfs/libxfs/xfs_btree.c >> > @@ -543,12 +543,12 @@ xfs_btree_ptr_addr( >> > */ >> > STATIC struct xfs_btree_block * >> > xfs_btree_get_iroot( >> > - struct xfs_btree_cur *cur) >> > + struct xfs_btree_cur *cur) >> > { >> > - struct xfs_ifork *ifp; >> > + struct xfs_ifork *ifp; >> > >> > - ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- >> > >bc_private.b.whichfork); >> > - return (struct xfs_btree_block *)ifp->if_broot; >> > + ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur- >> > >bc_private.b.whichfork); >> > + return (struct xfs_btree_block *)ifp->if_broot; >> > } >> >> That's better, but your mailer is still doing weird things to the >> patch. It line wrapped it this time, and converted all the spaces to >> some wierd multi-byte character instead of a plain ascii space. >> >> What you should do is send the patch to yourself, extract it from >> the email you receive, and try to apply it to a clean tree. If you >> can do that, then the patch is not getting mangled when you send it. >> See Documentation/SubmittingPatches and >> Documentation/email-clients.txt for help. >> > > This is a problem when sending patches from a gmail account. It's converted to a > base64 format, instead of pure clean text. > > I'd setup git to send the patch through the gmail smtp using git send-email. So > it won't screw up with the file format. Well, at least, that's what I do when I > need to send patches through a gmail account :) > > -- > Carlos From ngkaho1234@gmail.com Wed Jun 22 06:11:48 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,T_DKIM_INVALID autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6F6BE7CA1 for ; Wed, 22 Jun 2016 06:11:48 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3380B304032 for ; Wed, 22 Jun 2016 04:11:45 -0700 (PDT) X-ASG-Debug-ID: 1466593902-04cbb027373b550001-NocioJ Received: from mail-pa0-f66.google.com (mail-pa0-f66.google.com [209.85.220.66]) by cuda.sgi.com with ESMTP id OGsEbKNy42GiQyRL (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 04:11:43 -0700 (PDT) X-Barracuda-Envelope-From: ngkaho1234@gmail.com X-Barracuda-Effective-Source-IP: mail-pa0-f66.google.com[209.85.220.66] X-Barracuda-Apparent-Source-IP: 209.85.220.66 Received: by mail-pa0-f66.google.com with SMTP id us13so3756996pab.1 for ; Wed, 22 Jun 2016 04:11:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:to:cc:subject:message-id:mime-version :content-transfer-encoding; bh=c8dFHHnG+lQwL6ZWwonh3QuO0f6i2NutgpL5WoXK6VU=; b=yqH2/8B0UsbALVogqfFOGwEsrzCfki1ORv2IZTwfK8M05oqahV7AEqytn3g/5nPQC7 S1+zQgxDKdaMV0skR0KUhEPKbDOkgFNsEkA6ng6bCt3zsQOujkq4HnO6yMXNceJz/YsQ 56HBvBqeo0BEJMTc9+WGWw3HzvEBclT42pCflNiDWHD6IeqDMuvCxerBg0ZAhIX3jJM6 9qK9CK2gyU5Yd2VRZ+59DRrDkuP1F3NzMXfoSZOSSf87QOpFY3OthV7HLOId8dkpkMrY 9DU2jht8kmwRpGnOHcV3OxW+aicXZ/gIN4dsGQrRuP8Ow+ufvCtfexCIEOvM2X+UdDy3 JhBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:mime-version :content-transfer-encoding; bh=c8dFHHnG+lQwL6ZWwonh3QuO0f6i2NutgpL5WoXK6VU=; b=JrOtbzQ3Dc6iuyXfVECUPLXkLzB3y/AsJAudwys6rDLpe9KAm2RNMNIrF+dUVkv3PB XJqTy10ABD0qDAM/fGb5RAn9E/Cno0iwh7gnI7uW48YeQp059a4Ea1QTqdSZqsEDbqKi CstsnOrGgdeD43osbnm0VR8BB/gLH8qaEe3uj+9HXxZNvnvOGIZyGFeeT/4xLgd00BIc gdcPcHKcp0Q3LQZBGwdSkh0vao+KOkmxvlzu5imDIvzZErOZFx73vIbbHARXyjin7nt6 0LRHzCOruOuJ1QGDpR7ulA1cmlA30/5vQomJgHabYaA8jO+jvSUbPqO8GpnmKgTSWcv1 tK4Q== X-Gm-Message-State: ALyK8tJOx9xOi1RaHsOFlbTxgp9PCebvIjyJSRLlkIOdYYuKuAUhAs2eTiKjkjzqy6bXTQ== X-Received: by 10.66.150.105 with SMTP id uh9mr33947985pab.73.1466593902370; Wed, 22 Jun 2016 04:11:42 -0700 (PDT) Received: from zenbook.lan (119246003029.ctinets.com. [119.246.3.29]) by smtp.gmail.com with ESMTPSA id 4sm40303066pfi.24.2016.06.22.04.11.41 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Wed, 22 Jun 2016 04:11:42 -0700 (PDT) Date: Wed, 22 Jun 2016 19:11:37 +0800 From: Kaho Ng To: xfs@oss.sgi.com Cc: david@fromorbit.com Subject: [PATCH v3] xfs: indentation fix in xfs_btree_get_iroot() Message-ID: <20160622191137.26d0725d@zenbook.lan> X-ASG-Orig-Subj: [PATCH v3] xfs: indentation fix in xfs_btree_get_iroot() X-Mailer: Claws Mail 3.13.2 (GTK+ 2.24.30; x86_64-unknown-linux-gnu) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-pa0-f66.google.com[209.85.220.66] X-Barracuda-Start-Time: 1466593903 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 985 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, MAILTO_TO_SPAM_ADDR X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30656 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 MAILTO_TO_SPAM_ADDR URI: Includes a link to a likely spammer email The indentation in this function is different from the other functions. Those spacebars are converted to tabs to improve readability. Signed-off-by: Kaho Ng --- fs/xfs/libxfs/xfs_btree.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c index 1f88e1c..4f84dde 100644 --- a/fs/xfs/libxfs/xfs_btree.c +++ b/fs/xfs/libxfs/xfs_btree.c @@ -543,12 +543,12 @@ xfs_btree_ptr_addr( */ STATIC struct xfs_btree_block * xfs_btree_get_iroot( - struct xfs_btree_cur *cur) + struct xfs_btree_cur *cur) { - struct xfs_ifork *ifp; + struct xfs_ifork *ifp; - ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); - return (struct xfs_btree_block *)ifp->if_broot; + ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); + return (struct xfs_btree_block *)ifp->if_broot; } /* -- 2.9.0 From cmaiolino@redhat.com Wed Jun 22 06:25:32 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D62287CA1 for ; Wed, 22 Jun 2016 06:25:32 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9AEDF8F8033 for ; Wed, 22 Jun 2016 04:25:29 -0700 (PDT) X-ASG-Debug-ID: 1466594727-04cbb027383ff50001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id ZxGQCeowBTHShbjG (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 04:25:28 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A5AF437E71; Wed, 22 Jun 2016 11:25:27 +0000 (UTC) Received: from redhat.com (unused [10.10.51.227] (may be forged)) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5MBPNXg029932 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 22 Jun 2016 07:25:26 -0400 Date: Wed, 22 Jun 2016 13:25:23 +0200 From: Carlos Maiolino To: Kaho Ng Cc: xfs@oss.sgi.com Subject: Re: [PATCH v3] xfs: indentation fix in xfs_btree_get_iroot() Message-ID: <20160622112523.GA27894@redhat.com> X-ASG-Orig-Subj: Re: [PATCH v3] xfs: indentation fix in xfs_btree_get_iroot() Mail-Followup-To: Kaho Ng , xfs@oss.sgi.com References: <20160622191137.26d0725d@zenbook.lan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622191137.26d0725d@zenbook.lan> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Wed, 22 Jun 2016 11:25:27 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466594728 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1334 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Wed, Jun 22, 2016 at 07:11:37PM +0800, Kaho Ng wrote: > The indentation in this function is different from the other functions. > Those spacebars are converted to tabs to improve readability. > > Signed-off-by: Kaho Ng Ah, much better. Reviewed-by: Carlos Maiolino > --- > fs/xfs/libxfs/xfs_btree.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 1f88e1c..4f84dde 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -543,12 +543,12 @@ xfs_btree_ptr_addr( > */ > STATIC struct xfs_btree_block * > xfs_btree_get_iroot( > - struct xfs_btree_cur *cur) > + struct xfs_btree_cur *cur) > { > - struct xfs_ifork *ifp; > + struct xfs_ifork *ifp; > > - ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); > - return (struct xfs_btree_block *)ifp->if_broot; > + ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); > + return (struct xfs_btree_block *)ifp->if_broot; > } > > /* > -- > 2.9.0 > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From mstsxfx@gmail.com Wed Jun 22 07:38:31 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 828C47CA1 for ; Wed, 22 Jun 2016 07:38:31 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id C8CC8AC001 for ; Wed, 22 Jun 2016 05:38:27 -0700 (PDT) X-ASG-Debug-ID: 1466599104-04cbb0273652360001-NocioJ Received: from mail-wm0-f45.google.com (mail-wm0-f45.google.com [74.125.82.45]) by cuda.sgi.com with ESMTP id nX9qBDvVVKgO9jTk (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 05:38:25 -0700 (PDT) X-Barracuda-Envelope-From: mstsxfx@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f45.google.com[74.125.82.45] X-Barracuda-Apparent-Source-IP: 74.125.82.45 Received: by mail-wm0-f45.google.com with SMTP id a66so4122665wme.0 for ; Wed, 22 Jun 2016 05:38:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=b3Tu3OiiWYGSWDCEOn+XJ4wzO3In8Vpk+Mw8WxEGB1g=; b=PclJl18GwZJCmwCHH0owVLJkgsMawwgqPk5qqfuv5yWl3Rq/Ux1HkzNSXxGgco23rf BHrzFfdsn7Zu0IZRadl+P4FLmx8BcFEZvhX0psQB6H/mI4eMpFG46PoNlSy1ELu/KYvR WpLnhO+wtJJ2FxnpwpZC5xw5ceuPXLKsWzrrBFY8D8cKXsios+93yOlSiyWbMMjAspjP okE/i3GMoE7l+1xwKHYQ3DF/4p59I64WubAbiLVL0nI1JHuEFizXTIeUvTV3C7d8k2XP RQbDvCye/lb3n7qbdLtmD9mCvAyT1TiyeiGNRJ+DPAHL+EbHvN0PbW6KUeMNyxGUcqbf xElg== X-Gm-Message-State: ALyK8tLw8v2pPltqedxOwYY7tQiMS1MSUFQLmZZ5nR0e7sn6dxj9A9QiLgyvrlBeLLmJ7g== X-Received: by 10.28.216.21 with SMTP id p21mr8306701wmg.55.1466599104396; Wed, 22 Jun 2016 05:38:24 -0700 (PDT) Received: from localhost ([80.188.202.66]) by smtp.gmail.com with ESMTPSA id o10sm73717192wjz.37.2016.06.22.05.38.23 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Jun 2016 05:38:23 -0700 (PDT) Date: Wed, 22 Jun 2016 14:38:22 +0200 From: Michal Hocko To: Dave Chinner Cc: Peter Zijlstra , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160622123822.GG9208@dhcp22.suse.cz> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160601131758.GO26601@dhcp22.suse.cz> <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> <20160602232254.GR12670@dastard> <20160606122022.GH11895@dhcp22.suse.cz> <20160615072154.GF26977@dastard> <20160621142628.GG30848@dhcp22.suse.cz> <20160622010320.GR12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622010320.GR12670@dastard> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: mail-wm0-f45.google.com[74.125.82.45] X-Barracuda-Start-Time: 1466599105 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1517 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30658 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed 22-06-16 11:03:20, Dave Chinner wrote: > On Tue, Jun 21, 2016 at 04:26:28PM +0200, Michal Hocko wrote: > > On Wed 15-06-16 17:21:54, Dave Chinner wrote: [...] > > > There are allocations outside transaction context which need to be > > > GFP_NOFS - this is what KM_NOFS was originally intended for. > > > > Is it feasible to mark those by the scope NOFS api as well and drop > > the direct KM_NOFS usage? This should help to identify those that are > > lockdep only and use the annotation to prevent from the false positives. > > I don't understand what you are suggesting here. This all started > because we use GFP_NOFS in a handful of places to shut up lockdep > and you didn't want us to use GFP_NOFS like that. Now it sounds to > me like you are advocating setting unconditional GFP_NOFS allocation > contexts for entire XFS code paths - whether it's necessary or > not - to avoid problems with lockdep false positives. No, I meant only those paths which need GFP_NOFS for other than lockdep purposes would use the scope api. Anyway, it seems that we are not getting closer to a desired solution here. Or I am not following it at least... It seems that we have effectively two possibilities (from the MM/lockdep) POV. Either add an explicit API to disable the reclaim lockdep machinery for all allocation in a certain scope or a GFP mask to to achieve the same for a particular allocation. Which one would work better for the xfs usecase? -- Michal Hocko SUSE Labs From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 07:45:47 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9243B7CA1 for ; Wed, 22 Jun 2016 07:45:47 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1C20AAC001 for ; Wed, 22 Jun 2016 05:45:47 -0700 (PDT) X-ASG-Debug-ID: 1466599542-04bdf05e6d51490001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id EkFxfBekEh4A1LWT (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 05:45:42 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFhXI-0006Za-69; Wed, 22 Jun 2016 12:45:40 +0000 Date: Wed, 22 Jun 2016 05:45:40 -0700 From: Christoph Hellwig To: Felix Janda Cc: xfs@oss.sgi.com Subject: Re: [PATCH 2/4] Simplify workaround for old glibc getsubopt() Message-ID: <20160622124540.GA6293@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 2/4] Simplify workaround for old glibc getsubopt() References: <20160618145253.GB17768@nyan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160618145253.GB17768@nyan> User-Agent: Mutt/1.6.1 (2016-04-27) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466599542 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 141 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30658 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS I think we should simply kill that workaround. I even have vague memories of killing it, but maybe I didn't end up sending out the patch. From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 07:59:36 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D6C3F7CA1 for ; Wed, 22 Jun 2016 07:59:36 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9C3DE8F8037 for ; Wed, 22 Jun 2016 05:59:33 -0700 (PDT) X-ASG-Debug-ID: 1466600371-04cbb0273556e40001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id jCghfKBC5FCF7hB9 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 05:59:32 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from hch by bombadil.infradead.org with local (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFhkg-0003My-Kl; Wed, 22 Jun 2016 12:59:30 +0000 Date: Wed, 22 Jun 2016 05:59:30 -0700 From: Christoph Hellwig To: Felix Janda Cc: Christoph Hellwig , xfs@oss.sgi.com Subject: Re: [PATCH 2/6] libxfs/linux.c: Replace use of ustat by stat Message-ID: <20160622125930.GA11203@infradead.org> X-ASG-Orig-Subj: Re: [PATCH 2/6] libxfs/linux.c: Replace use of ustat by stat References: <20160112195945.GC568@nyan> <20160113075501.GC21939@infradead.org> <20160113174241.GC10942@nyan> <20160114102009.GD27644@infradead.org> <20160618145349.GA17760@nyan> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160618145349.GA17760@nyan> User-Agent: Mutt/1.6.1 (2016-04-27) X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466600371 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 334 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.10 X-Barracuda-Spam-Status: No, SCORE=0.10 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30658 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS Sorr for not getting back to you. It turns out that simply using O_EXCL is fairly easy, but fitting it into a portabilitity framework isn't. So I think I'll have to give up on that attempt for now. That being said I think ustat fits pretty well for this use case, so getting rid of it might need a little more justification. From damien.gombault@recia.fr Wed Jun 22 09:45:25 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 710507CA1 for ; Wed, 22 Jun 2016 09:45:25 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2068F8F8089 for ; Wed, 22 Jun 2016 07:45:25 -0700 (PDT) X-ASG-Debug-ID: 1466606720-04bdf05e6c77520001-NocioJ Received: from mx.recia.fr (mx.recia.fr [95.128.41.47]) by cuda.sgi.com with ESMTP id dHj8CG4jASOfdOkU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 07:45:21 -0700 (PDT) X-Barracuda-Envelope-From: damien.gombault@recia.fr X-Barracuda-Effective-Source-IP: mx.recia.fr[95.128.41.47] X-Barracuda-Apparent-Source-IP: 95.128.41.47 Received: from e6530-damien.recia.fr (unknown [37.58.188.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: F12A086p) by mx.recia.fr (Postfix) with ESMTPSA id 6AEE422627D for ; Wed, 22 Jun 2016 16:45:19 +0200 (CEST) To: xfs@oss.sgi.com From: Damien Gombault Subject: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed Organization: GIP Recia X-ASG-Orig-Subj: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed Message-ID: Date: Wed, 22 Jun 2016 16:45:19 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------F434849E7690777ADAA2AB96" X-Barracuda-Connect: mx.recia.fr[95.128.41.47] X-Barracuda-Start-Time: 1466606721 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4780 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30660 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 HTML_MESSAGE BODY: HTML included in message This is a multi-part message in MIME format. --------------F434849E7690777ADAA2AB96 Content-Type: multipart/alternative; boundary="------------575139A6589BF4421BE0A6D9" --------------575139A6589BF4421BE0A6D9 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Hi. I have reported few weeks ago a bug on the Red Hat Bugzilla for CentOS 7 : https://bugzilla.redhat.com/show_bug.cgi?id=1341126 I had to restore a level0+level1 dump for my ownCloud server, but during the level1 restoration, xfsrestore showed many warnings and some directories/files were not restored. I recently tried to restore a more recent level0+level1 dump and I get the same results with other directories/files. I tried to figure out why and now I am able to reproduce the problem with a minimal test case. Here is the test case : Create a new XFS filesystem, mount it as "/mnt/test" Then in "/mnt/test" Create a directory "dira/" Create a file "filea" in directory "dira/" You should get : . └── dira └── filea Make a level 0 dump : xfsdump -l 0 -f /root/test0.dump /mnt/test Rename "dira/" to "dirA/" Create a directory "dirb/" in "dirA/" Create a file "fileb" in "dirb/" You should get : . └── dirA ├── dirb │ └── fileb └── filea Make a level 1 dump : xfsdump -l 1 -f /root/test1.dump /mnt/test Create a new XFS filesystem, mount it as "/mnt/restore" Restore (cumulative mode) level 0 dump : xfsrestore -r -f /root/test0.dump /mnt/restore/ Restore (cumulative mode) level 1 dump : xfsrestore -r -f /root/test1.dump /mnt/restore/ You get a WARNING : xfsrestore: WARNING: open of dirA/dirb/fileb failed: Aucun fichier ou dossier de ce type: discarding ino 526337 (No such file or directory in English) Directory "dirb" and file "fileb" is not restored : . ├── dirA │ └── filea └── xfsrestorehousekeepingdir ├── dirattr ├── dirextattr ├── namreg ├── state └── tree I attached test0.dump (level 0 dump), test1.dump (level 1 dump), debug0.txt (xfsrestore level 0 debug trace), debug1.txt (xfsrestore level 1 debug trace). I can reproduce it on CentOS 7 and Fedora 24. On Fedora 24, I used : xfsprogs-4.5.0-1.fc24.x86_64 xfsdump-3.1.6-2.fc24.x86_64 kernel-4.5.7-300.fc24.x86_64 Is there a bug in xfsdump/xfsrestore tools and cumulative restoration feature ? --------------575139A6589BF4421BE0A6D9 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: 8bit
Hi.

I have reported few weeks ago a bug on the Red Hat Bugzilla for CentOS 7 : https://bugzilla.redhat.com/show_bug.cgi?id=1341126
I had to restore a level0+level1 dump for my ownCloud server, but during the level1 restoration, xfsrestore showed many warnings and some directories/files were not restored.
I recently tried to restore a more recent level0+level1 dump and I get the same results with other directories/files.
I tried to figure out why and now I am able to reproduce the problem with a minimal test case.

Here is the test case :

Create a new XFS filesystem, mount it as "/mnt/test"
Then in "/mnt/test"
Create a directory "dira/"
Create a file "filea" in directory "dira/"
You should get :

.
└── dira
    └── filea

Make a level 0 dump :
xfsdump -l 0 -f /root/test0.dump /mnt/test

Rename "dira/" to "dirA/"
Create a directory "dirb/" in "dirA/"
Create a file "fileb" in "dirb/"
You should get :

.
└── dirA
    ├── dirb
    │   └── fileb
    └── filea

Make a level 1 dump :
xfsdump -l 1 -f /root/test1.dump /mnt/test

Create a new XFS filesystem, mount it as "/mnt/restore"

Restore (cumulative mode) level 0 dump :
xfsrestore -r -f /root/test0.dump /mnt/restore/

Restore (cumulative mode) level 1 dump :
xfsrestore -r -f /root/test1.dump /mnt/restore/

You get a WARNING :
xfsrestore: WARNING: open of dirA/dirb/fileb failed: Aucun fichier ou dossier de ce type: discarding ino 526337 (No such file or directory in English)
Directory "dirb" and file "fileb" is not restored :

.
├── dirA
│   └── filea
└── xfsrestorehousekeepingdir
    ├── dirattr
    ├── dirextattr
    ├── namreg
    ├── state
    └── tree

I attached test0.dump (level 0 dump), test1.dump (level 1 dump), debug0.txt (xfsrestore level 0 debug trace), debug1.txt (xfsrestore level 1 debug trace).

I can reproduce it on CentOS 7 and Fedora 24.
On Fedora 24, I used :
xfsprogs-4.5.0-1.fc24.x86_64
xfsdump-3.1.6-2.fc24.x86_64
kernel-4.5.7-300.fc24.x86_64

Is there a bug in xfsdump/xfsrestore tools and cumulative restoration feature ?
--------------575139A6589BF4421BE0A6D9-- --------------F434849E7690777ADAA2AB96 Content-Type: text/plain; charset=UTF-8; name="debug0.txt" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="debug0.txt" eGZzcmVzdG9yZTogcmFpc2luZyBzdGFjayBzaXplIHNvZnQgbGltaXQgZnJvbSAweDgwMDAw MCB0byAweDIwMDAwMDAKeGZzcmVzdG9yZTogZ2V0cGFnZXNpemUoICkgcmV0dXJucyA0MDk2 Cnhmc3Jlc3RvcmU6IHBhcmVudCB0aWQgaXMgMTQwNTQ3NzA5OTQxNjMyCnhmc3Jlc3RvcmU6 IHVzaW5nIGZpbGUgZHVtcCAoZHJpdmVfc2ltcGxlKSBzdHJhdGVneQp4ZnNyZXN0b3JlOiB2 ZXJzaW9uIDMuMS40IChkdW1wIGZvcm1hdCAzLjApCnhmc3Jlc3RvcmU6IHRocmVhZCAxNDA1 NDc1ODcwMDgyNTYgY3JlYXRlZCBmb3Igc3RyZWFtIDAKeGZzcmVzdG9yZTogTWVkaWFfY3Jl YXRlCnhmc3Jlc3RvcmU6IGNoZWNraW5nIGFuZCB2YWxpZGF0aW5nIGNvbW1hbmQgbGluZSBk dW1wIGlkL2xhYmVsCnhmc3Jlc3RvcmU6IHNlYXJjaGluZyBtZWRpYSBmb3IgZHVtcAp4ZnNy ZXN0b3JlOiBNZWRpYV9tZmlsZV9uZXh0OiBwdXJwPT0wIHBvcz09MAp4ZnNyZXN0b3JlOiBl eGFtaW5pbmcgbWVkaWEgZmlsZSAwCnhmc3Jlc3RvcmU6IGZpbGUgMCBpbiBvYmplY3QgMCBv ZiBzdHJlYW0gMAp4ZnNyZXN0b3JlOiBmaWxlIDAgaW4gc3RyZWFtLCBmaWxlIDAgb2YgZHVt cCAwIG9uIG9iamVjdAp4ZnNyZXN0b3JlOiBkdW1wIGZvdW5kOiBjaGVja2luZwp4ZnNyZXN0 b3JlOiBkdW1wIGRlc2NyaXB0aW9uOiAKeGZzcmVzdG9yZTogaG9zdG5hbWU6IGhvc3RyZWNp YTEucmVjaWEuZnIKeGZzcmVzdG9yZTogbW91bnQgcG9pbnQ6IC9tbnQvdGVzdAp4ZnNyZXN0 b3JlOiB2b2x1bWU6IC9kZXYvbWFwcGVyL2NlbnRvc19ob3N0cmVjaWExLXRlc3QKeGZzcmVz dG9yZTogc2Vzc2lvbiB0aW1lOiBXZWQgSnVuIDIyIDEyOjE5OjI2IDIwMTYKeGZzcmVzdG9y ZTogbGV2ZWw6IDAKeGZzcmVzdG9yZTogc2Vzc2lvbiBsYWJlbDogInRlc3QiCnhmc3Jlc3Rv cmU6IG1lZGlhIGxhYmVsOiAidGVzdCIKeGZzcmVzdG9yZTogZmlsZSBzeXN0ZW0gaWQ6IGE4 MWZhODZiLTkyZGQtNDFlYS04NjJhLWRjMmEzZTQ1ZDBiOAp4ZnNyZXN0b3JlOiBzZXNzaW9u IGlkOiA4MTdmMmYyMS1iYzA2LTQ2ZDUtYjZhNC1mNDlkMWEwNTllZmUKeGZzcmVzdG9yZTog bWVkaWEgaWQ6IGY5M2U4ZjAzLTc2MDYtNDA2OS1iNzU0LWUxOGIyOTcyMzIyYwp4ZnNyZXN0 b3JlOiB1c2luZyBvbmxpbmUgc2Vzc2lvbiBpbnZlbnRvcnkKeGZzcmVzdG9yZTogc2VhcmNo aW5nIG1lZGlhIGZvciBkaXJlY3RvcnkgZHVtcAp4ZnNyZXN0b3JlOiBNZWRpYV9tZmlsZV9u ZXh0OiBwdXJwPT0xIHBvcz09MQp4ZnNyZXN0b3JlOiBkdW1wIHNlc3Npb24gbGFiZWw6ICJ0 ZXN0Igp4ZnNyZXN0b3JlOiBkdW1wIHNlc3Npb24gaWQ6IDgxN2YyZjIxLWJjMDYtNDZkNS1i NmE0LWY0OWQxYTA1OWVmZQp4ZnNyZXN0b3JlOiBzdHJlYW0gMCwgb2JqZWN0IDAsIGZpbGUg MAp4ZnNyZXN0b3JlOiBpbml0aWFsaXppbmcgZGlyZWN0b3J5IGF0dHJpYnV0ZXMgcmVnaXN0 cnkKeGZzcmVzdG9yZTogaW5pdGlhbGl6aW5nIGRpcmVjdG9yeSBlbnRyeSBuYW1lIHJlZ2lz dHJ5Cnhmc3Jlc3RvcmU6IGluaXRpYWxpemluZyBkaXJlY3RvcnkgaGllcmFyY2h5IGltYWdl Cnhmc3Jlc3RvcmU6IG5vZGVfaW5pdDogdm1zeiA9IDQ2MTE2ODYwMTg0MjczNTkyMzEgKDB4 M2ZmZmZmZmZmZmZmOGZmZikgc2Vnc3ogPSA1ODcyMDI1NiAoMHgzODAwMDAwKSBub2Rlc3Bl cnNlZyA9IDEwNDg1NzYgKDB4MTAwMDAwKSB3aW5tYXBtYXggPSA0MDk2ICgweDEwMDApCnhm c3Jlc3RvcmU6IHByZS1ncm93aW5nIG5ldyBub2RlIGFycmF5IHNlZ21lbnQgYXQgMzI3Njgg c2l6ZSA1ODcyMDI1Ngp4ZnNyZXN0b3JlOiByZWFkaW5nIGRpcmVjdG9yaWVzCnhmc3Jlc3Rv cmU6IHJlYWRpbmcgdGhlIGlubyBtYXAKeGZzcmVzdG9yZTogcmVhZGluZyB0aGUgZGlyZWN0 b3JpZXMgCnhmc3Jlc3RvcmU6IGRpcmVjdG9yeSAyMDQ4IDAgKDApOiB1cGRhdGluZwp4ZnNy ZXN0b3JlOiBkaXJlbnQgZGlyYSAyMDUxIDA6IGFkZGluZyAobmV3KQp4ZnNyZXN0b3JlOiBk aXJlY3RvcnkgMjA1MSAwICgwKTogdXBncmFkaW5nIHRvIGRpcgp4ZnNyZXN0b3JlOiBkaXJl bnQgZmlsZWEgMjA1MiAwOiBhZGRpbmcgKG5ldykKeGZzcmVzdG9yZTogMiBkaXJlY3Rvcmll cyBhbmQgMiBlbnRyaWVzIHByb2Nlc3NlZAp4ZnNyZXN0b3JlOiBudW1iZXIgb2YgbW1hcCBj YWxscyBmb3Igd2luZG93cyA9IDEKeGZzcmVzdG9yZTogTWVkaWFfYXRub25kaXIKeGZzcmVz dG9yZTogZGlyZWN0b3J5IHBvc3QtcHJvY2Vzc2luZwp4ZnNyZXN0b3JlOiBhZGp1c3Rpbmcg ZGlyZW50IHJlZiBmbGFncwp4ZnNyZXN0b3JlOiBhcHBseWluZyBzdWJ0cmVlIHNlbGVjdGlv bnMKeGZzcmVzdG9yZTogbWFraW5nIG5ldyBkaXJlY3Rvcmllcwp4ZnNyZXN0b3JlOiBta2Rp ciBkaXJhCnhmc3Jlc3RvcmU6IGdldHRpbmcgbmV4dCBtZWRpYSBmaWxlIGZvciBub24tZGly IHJlc3RvcmUKeGZzcmVzdG9yZTogTWVkaWFfbWZpbGVfbmV4dDogcHVycD09MiBwb3M9PTMK eGZzcmVzdG9yZTogZHVtcCBzZXNzaW9uIGxhYmVsOiAidGVzdCIKeGZzcmVzdG9yZTogZHVt cCBzZXNzaW9uIGlkOiA4MTdmMmYyMS1iYzA2LTQ2ZDUtYjZhNC1mNDlkMWEwNTllZmUKeGZz cmVzdG9yZTogc3RyZWFtIDAsIG9iamVjdCAwLCBmaWxlIDAKeGZzcmVzdG9yZTogcmVzdG9y aW5nIG5vbi1kaXJlY3RvcnkgZmlsZXMKeGZzcmVzdG9yZTogbWVkaWEgZmlsZSAwIGluIG9i amVjdCAwIG9mIHN0cmVhbSAwCnhmc3Jlc3RvcmU6IGZpbGUgMCBpbiBzdHJlYW0sIGZpbGUg MCBpbiBkdW1wIDAgb24gb2JqZWN0Cnhmc3Jlc3RvcmU6IHJlc3RvcmluZyBkaXJhL2ZpbGVh ICgyMDUyIDApCnhmc3Jlc3RvcmU6IHJlc3RvcmluZyByZWd1bGFyIGZpbGUgaW5vIDIwNTIg ZGlyYS9maWxlYQp4ZnNyZXN0b3JlOiBNZWRpYV9lbmQ6IHBvcz09Mwp4ZnNyZXN0b3JlOiBn ZXR0aW5nIG5leHQgbWVkaWEgZmlsZSBmb3Igbm9uLWRpciByZXN0b3JlCnhmc3Jlc3RvcmU6 IE1lZGlhX21maWxlX25leHQ6IHB1cnA9PTIgcG9zPT0wCnhmc3Jlc3RvcmU6IHRyZWUgZmlu YWxpemUKeGZzcmVzdG9yZTogY29udGVudC5jOiAyNjA1OiBtbG9nX2V4aXQgY2FsbGVkOiBl eGl0X2NvZGU6IFNVQ0NFU1MgcmV0dXJuOiBPSyAoc3VjY2VzcykKeGZzcmVzdG9yZTogYWxs IGNoaWxkcmVuIGhhdmUgZXhpdGVkCnhmc3Jlc3RvcmU6IHJlc3RvcmUgY29tcGxldGU6IDAg c2Vjb25kcyBlbGFwc2VkCnhmc3Jlc3RvcmU6IG1haW4uYzogODcxOiBtbG9nX2V4aXQgY2Fs bGVkOiBleGl0X2NvZGU6IFNVQ0NFU1MgcmV0dXJuOiBVTktOT1dOICh1bmtub3duIGVycm9y KQp4ZnNyZXN0b3JlOiBSZXN0b3JlIFN1bW1hcnk6Cnhmc3Jlc3RvcmU6ICAgc3RyZWFtIDAg L3Jvb3QvdGVzdDAuZHVtcCBPSyAoc3VjY2VzcykKeGZzcmVzdG9yZTogUmVzdG9yZSBTdGF0 dXM6IFNVQ0NFU1MK --------------F434849E7690777ADAA2AB96 Content-Type: text/plain; charset=UTF-8; name="debug1.txt" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="debug1.txt" eGZzcmVzdG9yZTogcmFpc2luZyBzdGFjayBzaXplIHNvZnQgbGltaXQgZnJvbSAweDgwMDAw MCB0byAweDIwMDAwMDAKeGZzcmVzdG9yZTogZ2V0cGFnZXNpemUoICkgcmV0dXJucyA0MDk2 Cnhmc3Jlc3RvcmU6IHBhcmVudCB0aWQgaXMgMTM5ODkzNjEwMjMxNjgwCnhmc3Jlc3RvcmU6 IHVzaW5nIGZpbGUgZHVtcCAoZHJpdmVfc2ltcGxlKSBzdHJhdGVneQp4ZnNyZXN0b3JlOiB2 ZXJzaW9uIDMuMS40IChkdW1wIGZvcm1hdCAzLjApCnhmc3Jlc3RvcmU6IHRocmVhZCAxMzk4 OTM0ODcyOTgzMDQgY3JlYXRlZCBmb3Igc3RyZWFtIDAKeGZzcmVzdG9yZTogTWVkaWFfY3Jl YXRlCnhmc3Jlc3RvcmU6IGNoZWNraW5nIGFuZCB2YWxpZGF0aW5nIGNvbW1hbmQgbGluZSBk dW1wIGlkL2xhYmVsCnhmc3Jlc3RvcmU6IHNlYXJjaGluZyBtZWRpYSBmb3IgZHVtcAp4ZnNy ZXN0b3JlOiBNZWRpYV9tZmlsZV9uZXh0OiBwdXJwPT0wIHBvcz09MAp4ZnNyZXN0b3JlOiBl eGFtaW5pbmcgbWVkaWEgZmlsZSAwCnhmc3Jlc3RvcmU6IGZpbGUgMCBpbiBvYmplY3QgMCBv ZiBzdHJlYW0gMAp4ZnNyZXN0b3JlOiBmaWxlIDAgaW4gc3RyZWFtLCBmaWxlIDAgb2YgZHVt cCAwIG9uIG9iamVjdAp4ZnNyZXN0b3JlOiBkdW1wIGZvdW5kOiBjaGVja2luZwp4ZnNyZXN0 b3JlOiBkdW1wIGRlc2NyaXB0aW9uOiAKeGZzcmVzdG9yZTogaG9zdG5hbWU6IGhvc3RyZWNp YTEucmVjaWEuZnIKeGZzcmVzdG9yZTogbW91bnQgcG9pbnQ6IC9tbnQvdGVzdAp4ZnNyZXN0 b3JlOiB2b2x1bWU6IC9kZXYvbWFwcGVyL2NlbnRvc19ob3N0cmVjaWExLXRlc3QKeGZzcmVz dG9yZTogc2Vzc2lvbiB0aW1lOiBXZWQgSnVuIDIyIDEyOjIwOjQyIDIwMTYKeGZzcmVzdG9y ZTogbGV2ZWw6IDEKeGZzcmVzdG9yZTogc2Vzc2lvbiBsYWJlbDogInRlc3QiCnhmc3Jlc3Rv cmU6IG1lZGlhIGxhYmVsOiAidGVzdCIKeGZzcmVzdG9yZTogZmlsZSBzeXN0ZW0gaWQ6IGE4 MWZhODZiLTkyZGQtNDFlYS04NjJhLWRjMmEzZTQ1ZDBiOAp4ZnNyZXN0b3JlOiBzZXNzaW9u IGlkOiAyNzYwNmM1Ny03YjNiLTQzZmYtODNiOS02OTE1OGU3NWY2MTIKeGZzcmVzdG9yZTog bWVkaWEgaWQ6IDFmY2I3YzljLTQ0YjItNDI3ZC1iZWNjLWQxMDgxNmUyYzQzMAp4ZnNyZXN0 b3JlOiB1c2luZyBvbmxpbmUgc2Vzc2lvbiBpbnZlbnRvcnkKeGZzcmVzdG9yZTogc2VhcmNo aW5nIG1lZGlhIGZvciBkaXJlY3RvcnkgZHVtcAp4ZnNyZXN0b3JlOiBNZWRpYV9tZmlsZV9u ZXh0OiBwdXJwPT0xIHBvcz09MQp4ZnNyZXN0b3JlOiBkdW1wIHNlc3Npb24gbGFiZWw6ICJ0 ZXN0Igp4ZnNyZXN0b3JlOiBkdW1wIHNlc3Npb24gaWQ6IDI3NjA2YzU3LTdiM2ItNDNmZi04 M2I5LTY5MTU4ZTc1ZjYxMgp4ZnNyZXN0b3JlOiBzdHJlYW0gMCwgb2JqZWN0IDAsIGZpbGUg MAp4ZnNyZXN0b3JlOiBpbml0aWFsaXppbmcgZGlyZWN0b3J5IGF0dHJpYnV0ZXMgcmVnaXN0 cnkKeGZzcmVzdG9yZTogcmVhZGluZyBkaXJlY3Rvcmllcwp4ZnNyZXN0b3JlOiByZWFkaW5n IHRoZSBpbm8gbWFwCnhmc3Jlc3RvcmU6IHJlYWRpbmcgdGhlIGRpcmVjdG9yaWVzIAp4ZnNy ZXN0b3JlOiBkaXJlY3RvcnkgMjA0OCAwICgwKTogdXBkYXRpbmcKeGZzcmVzdG9yZTogZGly ZW50IGRpckEgMjA1MSAwOiByZW5hbWluZyAobmFtZSkKeGZzcmVzdG9yZTogZGlyZWN0b3J5 IDIwNTEgMCAoMCk6IHVwZGF0aW5nCnhmc3Jlc3RvcmU6IGRpcmVudCBmaWxlYSAyMDUyIDA6 IHJldGFpbmluZyAobm9uZGlyKQp4ZnNyZXN0b3JlOiBkaXJlbnQgZGlyYiA1MjYzMzYgMTI4 MzAwNjUwMjogYWRkaW5nIChuZXcpCnhmc3Jlc3RvcmU6IGRpcmVjdG9yeSA1MjYzMzYgMTI4 MzAwNjUwMiAoMTI4MzAwNjUwMik6IHVwZ3JhZGluZyB0byBkaXIKeGZzcmVzdG9yZTogZGly ZW50IGZpbGViIDUyNjMzNyAxMjgzMDA2NTAyOiBhZGRpbmcgKG5ldykKeGZzcmVzdG9yZTog MyBkaXJlY3RvcmllcyBhbmQgNCBlbnRyaWVzIHByb2Nlc3NlZAp4ZnNyZXN0b3JlOiBudW1i ZXIgb2YgbW1hcCBjYWxscyBmb3Igd2luZG93cyA9IDEKeGZzcmVzdG9yZTogTWVkaWFfYXRu b25kaXIKeGZzcmVzdG9yZTogZGlyZWN0b3J5IHBvc3QtcHJvY2Vzc2luZwp4ZnNyZXN0b3Jl OiBhZGp1c3RpbmcgZGlyZW50IHJlZiBmbGFncwp4ZnNyZXN0b3JlOiBhcHBseWluZyBzdWJ0 cmVlIHNlbGVjdGlvbnMKeGZzcmVzdG9yZTogZWxpbWluYXRpbmcgdW5yZWZlcmVuY2VkIGRp cmVjdG9yeSBlbnRyaWVzCnhmc3Jlc3RvcmU6IHJlbmFtZSBkaXIgZGlyYSB0byBvcnBoYW5h Z2UvMjA1MS4wCnhmc3Jlc3RvcmU6IG1ha2luZyBuZXcgZGlyZWN0b3JpZXMKeGZzcmVzdG9y ZTogcGVyZm9ybWluZyBkaXJlY3RvcnkgcmVuYW1lcwp4ZnNyZXN0b3JlOiByZW5hbWUgZGly IG9ycGhhbmFnZS8yMDUxLjAgdG8gZGlyQQp4ZnNyZXN0b3JlOiBwcm9jZXNzaW5nIGhhcmQg bGlua3MKeGZzcmVzdG9yZTogcHJvY2Vzc2luZyBoYXJkbGlua3MgdG8gMjA1MiAwCnhmc3Jl c3RvcmU6IHByb2Nlc3NpbmcgaGFyZGxpbmtzIHRvIDUyNjMzNyAxMjgzMDA2NTAyCnhmc3Jl c3RvcmU6IGdldHRpbmcgbmV4dCBtZWRpYSBmaWxlIGZvciBub24tZGlyIHJlc3RvcmUKeGZz cmVzdG9yZTogTWVkaWFfbWZpbGVfbmV4dDogcHVycD09MiBwb3M9PTMKeGZzcmVzdG9yZTog ZHVtcCBzZXNzaW9uIGxhYmVsOiAidGVzdCIKeGZzcmVzdG9yZTogZHVtcCBzZXNzaW9uIGlk OiAyNzYwNmM1Ny03YjNiLTQzZmYtODNiOS02OTE1OGU3NWY2MTIKeGZzcmVzdG9yZTogc3Ry ZWFtIDAsIG9iamVjdCAwLCBmaWxlIDAKeGZzcmVzdG9yZTogcmVzdG9yaW5nIG5vbi1kaXJl Y3RvcnkgZmlsZXMKeGZzcmVzdG9yZTogbWVkaWEgZmlsZSAwIGluIG9iamVjdCAwIG9mIHN0 cmVhbSAwCnhmc3Jlc3RvcmU6IGZpbGUgMCBpbiBzdHJlYW0sIGZpbGUgMCBpbiBkdW1wIDAg b24gb2JqZWN0Cnhmc3Jlc3RvcmU6IHJlc3RvcmluZyBkaXJBL2RpcmIvZmlsZWIgKDUyNjMz NyAxMjgzMDA2NTAyKQp4ZnNyZXN0b3JlOiByZXN0b3JpbmcgcmVndWxhciBmaWxlIGlubyA1 MjYzMzcgZGlyQS9kaXJiL2ZpbGViCnhmc3Jlc3RvcmU6IFdBUk5JTkc6IG9wZW4gb2YgZGly QS9kaXJiL2ZpbGViIGZhaWxlZDogQXVjdW4gZmljaGllciBvdSBkb3NzaWVyIGRlIGNlIHR5 cGU6IGRpc2NhcmRpbmcgaW5vIDUyNjMzNwp4ZnNyZXN0b3JlOiBNZWRpYV9lbmQ6IHBvcz09 Mwp4ZnNyZXN0b3JlOiBnZXR0aW5nIG5leHQgbWVkaWEgZmlsZSBmb3Igbm9uLWRpciByZXN0 b3JlCnhmc3Jlc3RvcmU6IE1lZGlhX21maWxlX25leHQ6IHB1cnA9PTIgcG9zPT0wCnhmc3Jl c3RvcmU6IHRyZWUgZmluYWxpemUKeGZzcmVzdG9yZTogY29udGVudC5jOiAyNjA1OiBtbG9n X2V4aXQgY2FsbGVkOiBleGl0X2NvZGU6IFNVQ0NFU1MgcmV0dXJuOiBPSyAoc3VjY2VzcykK eGZzcmVzdG9yZTogYWxsIGNoaWxkcmVuIGhhdmUgZXhpdGVkCnhmc3Jlc3RvcmU6IHJlc3Rv cmUgY29tcGxldGU6IDAgc2Vjb25kcyBlbGFwc2VkCnhmc3Jlc3RvcmU6IG1haW4uYzogODcx OiBtbG9nX2V4aXQgY2FsbGVkOiBleGl0X2NvZGU6IFNVQ0NFU1MgcmV0dXJuOiBVTktOT1dO ICh1bmtub3duIGVycm9yKQp4ZnNyZXN0b3JlOiBSZXN0b3JlIFN1bW1hcnk6Cnhmc3Jlc3Rv cmU6ICAgc3RyZWFtIDAgL3Jvb3QvdGVzdDEuZHVtcCBPSyAoc3VjY2VzcykKeGZzcmVzdG9y ZTogUmVzdG9yZSBTdGF0dXM6IFNVQ0NFU1MK --------------F434849E7690777ADAA2AB96 Content-Type: application/octet-stream; name="test0.dump" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="test0.dump" eEZTZHVtcDAAAAADlQtRDVdqZi4AAAAA/////6jA5y2Bfy8hvAZG1bak9J0aBZ7+AAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhvc3RyZWNpYTEucmVj aWEuZnIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXN0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAD5Po8DdgZAabdU4YspcjIsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL21udC90 ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9kZXYvbWFwcGVyL2NlbnRvc19o b3N0cmVjaWExLXRlc3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAeGZzAAAAAAAAAAAAAAAAAKgfqGuS3UHqhircKj5F0LgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIBAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAABAAAAAAAAAAIAAAAAAAAAAQAA AAAAAAgAAAAAAAAACD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA AAAAAAAAAAkAAAAAAAAACQAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACD8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKlYKosAAAAAAAACAAAAEHtAAAAAwAAAAAAAAAA AAAAAAAAEAAAAAAAAAAAEVdqZRobF1xnV2plGRykOA9XamUZHKQ4DwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAACAMAAAAAlpuWcwAYZGlyYQAAAAAAAAAAAAAAAAAA////6AAYAAAAAAAAAAAAAAAA AAAAAAACU+nv+wAAAAAAAAgDAABB7QAAAAIAAAAAAAAAAAAAAAAAABAAAAAAAAAAABJXamUx NlGCMFdqZRw3woIzV2plHDfCgjMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAAAAAJY4kngAGGZp bGVhAAAAAAAAAAAAAAAAAP///+gAGAAAAAAAAAAAAAAAAAAAAAAAAlJ4sGgAAAAAAAAIBAAA gaQAAAABAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAV2plHDfCgjNXamUcN8KCM1dqZRw3woIz AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/////AAAAAAAAAAAAAAAA AAAAB/////kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= --------------F434849E7690777ADAA2AB96 Content-Type: application/octet-stream; name="test1.dump" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="test1.dump" eEZTZHVtcDAAAAADnqRomFdqZnoAAAAA/////6jA5y0nYGxXeztD/4O5aRWOdfYSAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGhvc3RyZWNpYTEucmVj aWEuZnIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU6gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB0ZXN0 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAfy3ycRLJCfb7M0QgW4sQwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL21udC90 ZXN0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC9kZXYvbWFwcGVyL2NlbnRvc19o b3N0cmVjaWExLXRlc3QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAeGZzAAAAAAAAAAAAAAAAAKgfqGuS3UHqhircKj5F0LgAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/MAAAAAQAAAABXamYuAAAAAAAAAAAAAAgAgX8vIbwG RtW2pPSdGgWe/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIAQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAQAAAAAAAAACAAAAAAAAAAMAAAAAAAAAAQAA AAAAAAgAAAAAAAAICD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgA AAAAAAAAAAkAAAAAAAAAGQAAAAAAAAAAAAAAAAAICAAAAAAAAAAAAQAAAAAAAAABAAAAAAAA AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICD8AAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKnUUR3AAAAAAAACAAAAEHtAAAAAwAAAAAAAAAA AAAAAAAAEAAAAAAAAAAAEVdqZjoxaZRsV2pmOhCCzTZXamY6EILNNgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAACAMAAAAAlpu2cwAYZGlyQQAAAAAAAAAAAAAAAAAA////6AAYAAAAAAAAAAAAAAAA AAAAAAACx7JwrAAAAAAAAAgDAABB7QAAAAMAAAAAAAAAAAAAAAAAABAAAAAAAAAAAB1XamZE AS//UFdqZkMYbwGUV2pmQxhvAZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgEAAAAAJY4kngAGGZp bGVhAAAAAAAACAgATHkgJkoadVAAGGRpcmIAAAAAAAAAAAAAAAAAAP///+gAGAAAAAAAAAAA AAAAAAAAAAAAApnlYkwAAAAAAAgIAAAAQe0AAAACAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAS V2pmTA8SM1FXamZGAiPesVdqZkYCI96xAAAAAAAAAAAAAAAAAAAAAAAAAABMeSAmAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIAUx5ICZJtnJV ABhmaWxlYgAAAAAAAAAAAAAAAAD////oABgAAAAAAAAAAAAAAAAAAAAAAAKmpbCoAAAAAAAI CAEAAIGkAAAAAQAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAFdqZkYCMyDoV2pmRgIzIOhXamZG AjMg6AAAAAAAAAAAAAAAAAAAAAAAAAAATHkgJgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/////wAAAAAAAAAA AAAAAAAAAAf////5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --------------F434849E7690777ADAA2AB96-- From bfoster@redhat.com Wed Jun 22 10:17:13 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 571BE7CA0 for ; Wed, 22 Jun 2016 10:17:13 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 06D7D8F8059 for ; Wed, 22 Jun 2016 08:17:12 -0700 (PDT) X-ASG-Debug-ID: 1466608628-04bdf05e6d818b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id v5GBcrYUe05xjLcn (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 08:17:08 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 76B293B730; Wed, 22 Jun 2016 15:17:08 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-2.bos.redhat.com [10.18.41.2]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5MFH7r7009795; Wed, 22 Jun 2016 11:17:08 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id B706B1201DB; Wed, 22 Jun 2016 11:17:06 -0400 (EDT) Date: Wed, 22 Jun 2016 11:17:06 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys Message-ID: <20160622151706.GB5423@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612635526.12839.13865365567940815077.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612635526.12839.13865365567940815077.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 22 Jun 2016 15:17:08 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466608628 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 29831 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:15PM -0700, Darrick J. Wong wrote: > On a filesystem with both reflink and reverse mapping enabled, it's > possible to have multiple rmap records referring to the same blocks on > disk. When overlapping intervals are possible, querying a classic > btree to find all records intersecting a given interval is inefficient > because we cannot use the left side of the search interval to filter > out non-matching records the same way that we can use the existing > btree key to filter out records coming after the right side of the > search interval. This will become important once we want to use the > rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl. > > (For the non-overlapping case, we can perform such queries trivially > by starting at the left side of the interval and walking the tree > until we pass the right side.) > > Therefore, extend the btree code to come closer to supporting > intervals as a first-class record attribute. This involves widening > the btree node's key space to store both the lowest key reachable via > the node pointer (as the btree does now) and the highest key reachable > via the same pointer and teaching the btree modifying functions to > keep the highest-key records up to date. > > This behavior can be turned on via a new btree ops flag so that btrees > that cannot store overlapping intervals don't pay the overhead costs > in terms of extra code and disk format changes. > > v2: When we're deleting a record in a btree that supports overlapped > interval records and the deletion results in two btree blocks being > joined, we defer updating the high/low keys until after all possible > joining (at higher levels in the tree) have finished. At this point, > the btree pointers at all levels have been updated to remove the empty > blocks and we can update the low and high keys. > > When we're doing this, we must be careful to update the keys of all > node pointers up to the root instead of stopping at the first set of > keys that don't need updating. This is because it's possible for a > single deletion to cause joining of multiple levels of tree, and so > we need to update everything going back to the root. > > Signed-off-by: Darrick J. Wong > --- I think I get the gist of this and it mostly looks Ok to me. A few questions and minor comments... > fs/xfs/libxfs/xfs_btree.c | 379 +++++++++++++++++++++++++++++++++++++++++---- > fs/xfs/libxfs/xfs_btree.h | 16 ++ > fs/xfs/xfs_trace.h | 36 ++++ > 3 files changed, 395 insertions(+), 36 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index a096539..afcafd6 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -52,6 +52,11 @@ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { > xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] > > > +struct xfs_btree_double_key { > + union xfs_btree_key low; > + union xfs_btree_key high; > +}; > + > STATIC int /* error (0 or EFSCORRUPTED) */ > xfs_btree_check_lblock( > struct xfs_btree_cur *cur, /* btree cursor */ > @@ -428,6 +433,30 @@ xfs_btree_dup_cursor( > * into a btree block (xfs_btree_*_offset) or return a pointer to the given > * record, key or pointer (xfs_btree_*_addr). Note that all addressing > * inside the btree block is done using indices starting at one, not zero! > + * > + * If XFS_BTREE_OVERLAPPING is set, then this btree supports keys containing > + * overlapping intervals. In such a tree, records are still sorted lowest to > + * highest and indexed by the smallest key value that refers to the record. > + * However, nodes are different: each pointer has two associated keys -- one > + * indexing the lowest key available in the block(s) below (the same behavior > + * as the key in a regular btree) and another indexing the highest key > + * available in the block(s) below. Because records are /not/ sorted by the > + * highest key, all leaf block updates require us to compute the highest key > + * that matches any record in the leaf and to recursively update the high keys > + * in the nodes going further up in the tree, if necessary. Nodes look like > + * this: > + * > + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ > + * Non-Leaf: | header | lo1 | hi1 | lo2 | hi2 | ... | ptr 1 | ptr 2 | ... | > + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ > + * > + * To perform an interval query on an overlapped tree, perform the usual > + * depth-first search and use the low and high keys to decide if we can skip > + * that particular node. If a leaf node is reached, return the records that > + * intersect the interval. Note that an interval query may return numerous > + * entries. For a non-overlapped tree, simply search for the record associated > + * with the lowest key and iterate forward until a non-matching record is > + * found. > */ > > /* > @@ -445,6 +474,17 @@ static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur) > return XFS_BTREE_SBLOCK_LEN; > } > > +/* Return size of btree block keys for this btree instance. */ > +static inline size_t xfs_btree_key_len(struct xfs_btree_cur *cur) > +{ > + size_t len; > + > + len = cur->bc_ops->key_len; > + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) > + len *= 2; > + return len; > +} > + > /* > * Return size of btree block pointers for this btree instance. > */ > @@ -475,7 +515,19 @@ xfs_btree_key_offset( > int n) > { > return xfs_btree_block_len(cur) + > - (n - 1) * cur->bc_ops->key_len; > + (n - 1) * xfs_btree_key_len(cur); > +} > + > +/* > + * Calculate offset of the n-th high key in a btree block. > + */ > +STATIC size_t > +xfs_btree_high_key_offset( > + struct xfs_btree_cur *cur, > + int n) > +{ > + return xfs_btree_block_len(cur) + > + (n - 1) * xfs_btree_key_len(cur) + cur->bc_ops->key_len; > } > > /* > @@ -488,7 +540,7 @@ xfs_btree_ptr_offset( > int level) > { > return xfs_btree_block_len(cur) + > - cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len + > + cur->bc_ops->get_maxrecs(cur, level) * xfs_btree_key_len(cur) + > (n - 1) * xfs_btree_ptr_len(cur); > } > > @@ -519,6 +571,19 @@ xfs_btree_key_addr( > } > > /* > + * Return a pointer to the n-th high key in the btree block. > + */ > +STATIC union xfs_btree_key * > +xfs_btree_high_key_addr( > + struct xfs_btree_cur *cur, > + int n, > + struct xfs_btree_block *block) > +{ > + return (union xfs_btree_key *) > + ((char *)block + xfs_btree_high_key_offset(cur, n)); > +} > + > +/* > * Return a pointer to the n-th block pointer in the btree block. > */ > STATIC union xfs_btree_ptr * > @@ -1217,7 +1282,7 @@ xfs_btree_copy_keys( > int numkeys) > { > ASSERT(numkeys >= 0); > - memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len); > + memcpy(dst_key, src_key, numkeys * xfs_btree_key_len(cur)); > } > > /* > @@ -1263,8 +1328,8 @@ xfs_btree_shift_keys( > ASSERT(numkeys >= 0); > ASSERT(dir == 1 || dir == -1); > > - dst_key = (char *)key + (dir * cur->bc_ops->key_len); > - memmove(dst_key, key, numkeys * cur->bc_ops->key_len); > + dst_key = (char *)key + (dir * xfs_btree_key_len(cur)); > + memmove(dst_key, key, numkeys * xfs_btree_key_len(cur)); > } > > /* > @@ -1879,6 +1944,180 @@ error0: > return error; > } > > +/* Determine the low and high keys of a leaf block */ > +STATIC void > +xfs_btree_find_leaf_keys( > + struct xfs_btree_cur *cur, > + struct xfs_btree_block *block, > + union xfs_btree_key *low, > + union xfs_btree_key *high) > +{ > + int n; > + union xfs_btree_rec *rec; > + union xfs_btree_key max_hkey; > + union xfs_btree_key hkey; > + > + rec = xfs_btree_rec_addr(cur, 1, block); > + cur->bc_ops->init_key_from_rec(low, rec); > + > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > + return; > + > + cur->bc_ops->init_high_key_from_rec(&max_hkey, rec); > + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { > + rec = xfs_btree_rec_addr(cur, n, block); > + cur->bc_ops->init_high_key_from_rec(&hkey, rec); > + if (cur->bc_ops->diff_two_keys(cur, &max_hkey, &hkey) > 0) > + max_hkey = hkey; > + } > + > + *high = max_hkey; > +} > + > +/* Determine the low and high keys of a node block */ > +STATIC void > +xfs_btree_find_node_keys( > + struct xfs_btree_cur *cur, > + struct xfs_btree_block *block, > + union xfs_btree_key *low, > + union xfs_btree_key *high) > +{ > + int n; > + union xfs_btree_key *hkey; > + union xfs_btree_key *max_hkey; > + > + *low = *xfs_btree_key_addr(cur, 1, block); > + > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > + return; > + > + max_hkey = xfs_btree_high_key_addr(cur, 1, block); > + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { > + hkey = xfs_btree_high_key_addr(cur, n, block); > + if (cur->bc_ops->diff_two_keys(cur, max_hkey, hkey) > 0) > + max_hkey = hkey; > + } > + > + *high = *max_hkey; > +} > + > +/* > + * Update parental low & high keys from some block all the way back to the > + * root of the btree. > + */ > +STATIC int > +__xfs_btree_updkeys( > + struct xfs_btree_cur *cur, > + int level, > + struct xfs_btree_block *block, > + struct xfs_buf *bp0, > + bool force_all) > +{ > + union xfs_btree_key lkey; /* keys from current level */ > + union xfs_btree_key hkey; > + union xfs_btree_key *nlkey; /* keys from the next level up */ > + union xfs_btree_key *nhkey; > + struct xfs_buf *bp; > + int ptr = -1; ptr doesn't appear to require initialization. > + > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > + return 0; > + > + if (level + 1 >= cur->bc_nlevels) > + return 0; This could use a comment to indicate we're checking for a parent level to update. > + > + trace_xfs_btree_updkeys(cur, level, bp0); > + > + if (level == 0) > + xfs_btree_find_leaf_keys(cur, block, &lkey, &hkey); > + else > + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); > + for (level++; level < cur->bc_nlevels; level++) { > + block = xfs_btree_get_block(cur, level, &bp); > + trace_xfs_btree_updkeys(cur, level, bp); > + ptr = cur->bc_ptrs[level]; > + nlkey = xfs_btree_key_addr(cur, ptr, block); > + nhkey = xfs_btree_high_key_addr(cur, ptr, block); > + if (!(cur->bc_ops->diff_two_keys(cur, nlkey, &lkey) != 0 || > + cur->bc_ops->diff_two_keys(cur, nhkey, &hkey) != 0) && > + !force_all) > + break; > + memcpy(nlkey, &lkey, cur->bc_ops->key_len); > + memcpy(nhkey, &hkey, cur->bc_ops->key_len); > + xfs_btree_log_keys(cur, bp, ptr, ptr); > + if (level + 1 >= cur->bc_nlevels) > + break; > + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); > + } > + > + return 0; > +} > + > +/* > + * Update all the keys from a sibling block at some level in the cursor back > + * to the root, stopping when we find a key pair that doesn't need updating. > + */ > +STATIC int > +xfs_btree_sibling_updkeys( > + struct xfs_btree_cur *cur, > + int level, > + int ptr, > + struct xfs_btree_block *block, > + struct xfs_buf *bp0) > +{ > + struct xfs_btree_cur *ncur; > + int stat; > + int error; > + > + error = xfs_btree_dup_cursor(cur, &ncur); > + if (error) > + return error; > + > + if (level + 1 >= ncur->bc_nlevels) > + error = -EDOM; > + else if (ptr == XFS_BB_RIGHTSIB) > + error = xfs_btree_increment(ncur, level + 1, &stat); > + else if (ptr == XFS_BB_LEFTSIB) > + error = xfs_btree_decrement(ncur, level + 1, &stat); > + else > + error = -EBADE; So we inc/dec the cursor at the next level up the tree, then update the keys up that path with the __xfs_btree_updkeys() call below. The inc/dec calls explicitly say that they don't alter the cursor below the level, so it looks like we'd end up with a weird cursor path here. Digging around further, it looks like we pass the sibling bp/block pointers from the caller and thus __xfs_btree_updkeys() should do the correct thing, but this is not very clear. If I'm on the right track, I'd suggest to add a big fat comment here. :) > + if (error || !stat) > + return error; Looks like a potential cursor leak on error. > + > + error = __xfs_btree_updkeys(ncur, level, block, bp0, false); > + xfs_btree_del_cursor(ncur, XFS_BTREE_NOERROR); > + return error; > +} > + > +/* > + * Update all the keys from some level in cursor back to the root, stopping > + * when we find a key pair that don't need updating. > + */ > +STATIC int > +xfs_btree_updkeys( > + struct xfs_btree_cur *cur, > + int level) > +{ > + struct xfs_buf *bp; > + struct xfs_btree_block *block; > + > + block = xfs_btree_get_block(cur, level, &bp); > + return __xfs_btree_updkeys(cur, level, block, bp, false); > +} > + > +/* Update all the keys from some level in cursor back to the root. */ > +STATIC int > +xfs_btree_updkeys_force( > + struct xfs_btree_cur *cur, > + int level) > +{ > + struct xfs_buf *bp; > + struct xfs_btree_block *block; > + > + block = xfs_btree_get_block(cur, level, &bp); > + return __xfs_btree_updkeys(cur, level, block, bp, true); > +} > + > /* > * Update keys at all levels from here to the root along the cursor's path. > */ > @@ -1893,6 +2132,9 @@ xfs_btree_updkey( > union xfs_btree_key *kp; > int ptr; > > + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) > + return 0; > + > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > XFS_BTREE_TRACE_ARGIK(cur, level, keyp); > > @@ -1970,7 +2212,8 @@ xfs_btree_update( > ptr, LASTREC_UPDATE); > } > > - /* Updating first rec in leaf. Pass new key value up to our parent. */ > + /* Pass new key value up to our parent. */ > + xfs_btree_updkeys(cur, 0); > if (ptr == 1) { > union xfs_btree_key key; > > @@ -2149,7 +2392,9 @@ xfs_btree_lshift( > rkp = &key; > } > > - /* Update the parent key values of right. */ > + /* Update the parent key values of left and right. */ > + xfs_btree_sibling_updkeys(cur, level, XFS_BB_LEFTSIB, left, lbp); > + xfs_btree_updkeys(cur, level); > error = xfs_btree_updkey(cur, rkp, level + 1); > if (error) > goto error0; > @@ -2321,6 +2566,9 @@ xfs_btree_rshift( > if (error) > goto error1; > > + /* Update left and right parent pointers */ > + xfs_btree_updkeys(cur, level); > + xfs_btree_updkeys(tcur, level); In this case, we grab the last record of the block, increment from there and update using the cursor. This is much more straightforward, imo. Could we use this approach in the left shift case as well? > error = xfs_btree_updkey(tcur, rkp, level + 1); > if (error) > goto error1; > @@ -2356,7 +2604,7 @@ __xfs_btree_split( > struct xfs_btree_cur *cur, > int level, > union xfs_btree_ptr *ptrp, > - union xfs_btree_key *key, > + struct xfs_btree_double_key *key, > struct xfs_btree_cur **curp, > int *stat) /* success/failure */ > { > @@ -2452,9 +2700,6 @@ __xfs_btree_split( > > xfs_btree_log_keys(cur, rbp, 1, rrecs); > xfs_btree_log_ptrs(cur, rbp, 1, rrecs); > - > - /* Grab the keys to the entries moved to the right block */ > - xfs_btree_copy_keys(cur, key, rkp, 1); > } else { > /* It's a leaf. Move records. */ > union xfs_btree_rec *lrp; /* left record pointer */ > @@ -2465,12 +2710,8 @@ __xfs_btree_split( > > xfs_btree_copy_recs(cur, rrp, lrp, rrecs); > xfs_btree_log_recs(cur, rbp, 1, rrecs); > - > - cur->bc_ops->init_key_from_rec(key, > - xfs_btree_rec_addr(cur, 1, right)); > } > > - > /* > * Find the left block number by looking in the buffer. > * Adjust numrecs, sibling pointers. > @@ -2484,6 +2725,12 @@ __xfs_btree_split( > xfs_btree_set_numrecs(left, lrecs); > xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs); > > + /* Find the low & high keys for the new block. */ > + if (level > 0) > + xfs_btree_find_node_keys(cur, right, &key->low, &key->high); > + else > + xfs_btree_find_leaf_keys(cur, right, &key->low, &key->high); > + Why not push these into the above if/else where the previous key copy/init calls were removed from? > xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS); > xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); > > @@ -2499,6 +2746,10 @@ __xfs_btree_split( > xfs_btree_set_sibling(cur, rrblock, &rptr, XFS_BB_LEFTSIB); > xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB); > } > + > + /* Update the left block's keys... */ > + xfs_btree_updkeys(cur, level); > + > /* > * If the cursor is really in the right block, move it there. > * If it's just pointing past the last entry in left, then we'll > @@ -2537,7 +2788,7 @@ struct xfs_btree_split_args { > struct xfs_btree_cur *cur; > int level; > union xfs_btree_ptr *ptrp; > - union xfs_btree_key *key; > + struct xfs_btree_double_key *key; > struct xfs_btree_cur **curp; > int *stat; /* success/failure */ > int result; > @@ -2586,7 +2837,7 @@ xfs_btree_split( > struct xfs_btree_cur *cur, > int level, > union xfs_btree_ptr *ptrp, > - union xfs_btree_key *key, > + struct xfs_btree_double_key *key, > struct xfs_btree_cur **curp, > int *stat) /* success/failure */ > { > @@ -2806,27 +3057,27 @@ xfs_btree_new_root( > bp = lbp; > nptr = 2; > } > + > /* Fill in the new block's btree header and log it. */ > xfs_btree_init_block_cur(cur, nbp, cur->bc_nlevels, 2); > xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS); > ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) && > !xfs_btree_ptr_is_null(cur, &rptr)); > - ? > /* Fill in the key data in the new root. */ > if (xfs_btree_get_level(left) > 0) { > - xfs_btree_copy_keys(cur, > + xfs_btree_find_node_keys(cur, left, > xfs_btree_key_addr(cur, 1, new), > - xfs_btree_key_addr(cur, 1, left), 1); > - xfs_btree_copy_keys(cur, > + xfs_btree_high_key_addr(cur, 1, new)); > + xfs_btree_find_node_keys(cur, right, > xfs_btree_key_addr(cur, 2, new), > - xfs_btree_key_addr(cur, 1, right), 1); > + xfs_btree_high_key_addr(cur, 2, new)); > } else { > - cur->bc_ops->init_key_from_rec( > - xfs_btree_key_addr(cur, 1, new), > - xfs_btree_rec_addr(cur, 1, left)); > - cur->bc_ops->init_key_from_rec( > - xfs_btree_key_addr(cur, 2, new), > - xfs_btree_rec_addr(cur, 1, right)); > + xfs_btree_find_leaf_keys(cur, left, > + xfs_btree_key_addr(cur, 1, new), > + xfs_btree_high_key_addr(cur, 1, new)); > + xfs_btree_find_leaf_keys(cur, right, > + xfs_btree_key_addr(cur, 2, new), > + xfs_btree_high_key_addr(cur, 2, new)); > } > xfs_btree_log_keys(cur, nbp, 1, 2); > > @@ -2837,6 +3088,7 @@ xfs_btree_new_root( > xfs_btree_ptr_addr(cur, 2, new), &rptr, 1); > xfs_btree_log_ptrs(cur, nbp, 1, 2); > > + Extra line. > /* Fix up the cursor. */ > xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); > cur->bc_ptrs[cur->bc_nlevels] = nptr; > @@ -2862,7 +3114,7 @@ xfs_btree_make_block_unfull( > int *index, /* new tree index */ > union xfs_btree_ptr *nptr, /* new btree ptr */ > struct xfs_btree_cur **ncur, /* new btree cursor */ > - union xfs_btree_key *key, /* key of new block */ > + struct xfs_btree_double_key *key, /* key of new block */ > int *stat) > { > int error = 0; > @@ -2918,6 +3170,22 @@ xfs_btree_make_block_unfull( > return 0; > } > > +/* Copy a double key into a btree block. */ > +static void > +xfs_btree_copy_double_keys( > + struct xfs_btree_cur *cur, > + int ptr, > + struct xfs_btree_block *block, > + struct xfs_btree_double_key *key) > +{ > + memcpy(xfs_btree_key_addr(cur, ptr, block), &key->low, > + cur->bc_ops->key_len); > + > + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) > + memcpy(xfs_btree_high_key_addr(cur, ptr, block), &key->high, > + cur->bc_ops->key_len); > +} > + > /* > * Insert one record/level. Return information to the caller > * allowing the next level up to proceed if necessary. > @@ -2927,7 +3195,7 @@ xfs_btree_insrec( > struct xfs_btree_cur *cur, /* btree cursor */ > int level, /* level to insert record at */ > union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ > - union xfs_btree_key *key, /* i/o: block key for ptrp */ > + struct xfs_btree_double_key *key, /* i/o: block key for ptrp */ > struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ > int *stat) /* success/failure */ > { > @@ -2935,7 +3203,7 @@ xfs_btree_insrec( > struct xfs_buf *bp; /* buffer for block */ > union xfs_btree_ptr nptr; /* new block ptr */ > struct xfs_btree_cur *ncur; /* new btree cursor */ > - union xfs_btree_key nkey; /* new block key */ > + struct xfs_btree_double_key nkey; /* new block key */ > union xfs_btree_rec rec; /* record to insert */ > int optr; /* old key/record index */ > int ptr; /* key/record index */ > @@ -2944,11 +3212,12 @@ xfs_btree_insrec( > #ifdef DEBUG > int i; > #endif > + xfs_daddr_t old_bn; > > /* Make a key out of the record data to be inserted, and save it. */ > if (level == 0) { > cur->bc_ops->init_rec_from_cur(cur, &rec); > - cur->bc_ops->init_key_from_rec(key, &rec); > + cur->bc_ops->init_key_from_rec(&key->low, &rec); > } > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > @@ -2983,6 +3252,7 @@ xfs_btree_insrec( > > /* Get pointers to the btree buffer and block. */ > block = xfs_btree_get_block(cur, level, &bp); > + old_bn = bp ? bp->b_bn : XFS_BUF_DADDR_NULL; > numrecs = xfs_btree_get_numrecs(block); > > #ifdef DEBUG > @@ -2996,7 +3266,7 @@ xfs_btree_insrec( > ASSERT(cur->bc_ops->recs_inorder(cur, &rec, > xfs_btree_rec_addr(cur, ptr, block))); > } else { > - ASSERT(cur->bc_ops->keys_inorder(cur, key, > + ASSERT(cur->bc_ops->keys_inorder(cur, &key->low, > xfs_btree_key_addr(cur, ptr, block))); > } > } > @@ -3059,7 +3329,7 @@ xfs_btree_insrec( > #endif > > /* Now put the new data in, bump numrecs and log it. */ > - xfs_btree_copy_keys(cur, kp, key, 1); > + xfs_btree_copy_double_keys(cur, ptr, block, key); > xfs_btree_copy_ptrs(cur, pp, ptrp, 1); > numrecs++; > xfs_btree_set_numrecs(block, numrecs); > @@ -3095,8 +3365,24 @@ xfs_btree_insrec( > xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); > > /* If we inserted at the start of a block, update the parents' keys. */ This comment is associated with the codeblock that has been pushed further down, no? > + if (ncur && bp->b_bn != old_bn) { > + /* > + * We just inserted into a new tree block, which means that > + * the key for the block is in nkey, not the tree. > + */ > + if (level == 0) > + xfs_btree_find_leaf_keys(cur, block, &nkey.low, > + &nkey.high); > + else > + xfs_btree_find_node_keys(cur, block, &nkey.low, > + &nkey.high); > + } else { > + /* Updating the left block, do it the standard way. */ > + xfs_btree_updkeys(cur, level); > + } > + Not quite sure I follow the purpose of this hunk. Is this for the case where a btree split occurs, nkey is filled in for the new/right block and then (after nkey is filled in) the new record ends up being added to the new block? If so, what about the case where ncur is not created? (It looks like that's possible from the code, but I could easily be missing some context as to why that's not the case.) In any event, I think we could elaborate a bit in the comment on why this is necessary. I'd also move it above the top-level if/else. > if (optr == 1) { > - error = xfs_btree_updkey(cur, key, level + 1); > + error = xfs_btree_updkey(cur, &key->low, level + 1); > if (error) > goto error0; > } > @@ -3147,7 +3433,7 @@ xfs_btree_insert( > union xfs_btree_ptr nptr; /* new block number (split result) */ > struct xfs_btree_cur *ncur; /* new cursor (split result) */ > struct xfs_btree_cur *pcur; /* previous level's cursor */ > - union xfs_btree_key key; /* key of block to insert */ > + struct xfs_btree_double_key key; /* key of block to insert */ Probably should fix up the function param alignment here and the couple other or so places we make this change. Brian > > level = 0; > ncur = NULL; > @@ -3552,6 +3838,7 @@ xfs_btree_delrec( > * If we deleted the leftmost entry in the block, update the > * key values above us in the tree. > */ > + xfs_btree_updkeys(cur, level); > if (ptr == 1) { > error = xfs_btree_updkey(cur, keyp, level + 1); > if (error) > @@ -3882,6 +4169,16 @@ xfs_btree_delrec( > if (level > 0) > cur->bc_ptrs[level]--; > > + /* > + * We combined blocks, so we have to update the parent keys if the > + * btree supports overlapped intervals. However, bc_ptrs[level + 1] > + * points to the old block so that the caller knows which record to > + * delete. Therefore, the caller must be savvy enough to call updkeys > + * for us if we return stat == 2. The other exit points from this > + * function don't require deletions further up the tree, so they can > + * call updkeys directly. > + */ > + > XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); > /* Return value means the next level up has something to do. */ > *stat = 2; > @@ -3907,6 +4204,7 @@ xfs_btree_delete( > int error; /* error return value */ > int level; > int i; > + bool joined = false; > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > @@ -3920,8 +4218,17 @@ xfs_btree_delete( > error = xfs_btree_delrec(cur, level, &i); > if (error) > goto error0; > + if (i == 2) > + joined = true; > } > > + /* > + * If we combined blocks as part of deleting the record, delrec won't > + * have updated the parent keys so we have to do that here. > + */ > + if (joined) > + xfs_btree_updkeys_force(cur, 0); > + > if (i == 0) { > for (level = 1; level < cur->bc_nlevels; level++) { > if (cur->bc_ptrs[level] == 0) { > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index b99c018..a5ec6c7 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -126,6 +126,9 @@ struct xfs_btree_ops { > size_t key_len; > size_t rec_len; > > + /* flags */ > + uint flags; > + > /* cursor operations */ > struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); > void (*update_cursor)(struct xfs_btree_cur *src, > @@ -162,11 +165,21 @@ struct xfs_btree_ops { > union xfs_btree_rec *rec); > void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, > union xfs_btree_ptr *ptr); > + void (*init_high_key_from_rec)(union xfs_btree_key *key, > + union xfs_btree_rec *rec); > > /* difference between key value and cursor value */ > __int64_t (*key_diff)(struct xfs_btree_cur *cur, > union xfs_btree_key *key); > > + /* > + * Difference between key2 and key1 -- positive if key2 > key1, > + * negative if key2 < key1, and zero if equal. > + */ > + __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur, > + union xfs_btree_key *key1, > + union xfs_btree_key *key2); > + > const struct xfs_buf_ops *buf_ops; > > #if defined(DEBUG) || defined(XFS_WARN) > @@ -182,6 +195,9 @@ struct xfs_btree_ops { > #endif > }; > > +/* btree ops flags */ > +#define XFS_BTREE_OPS_OVERLAPPING (1<<0) /* overlapping intervals */ > + > /* > * Reasons for the update_lastrec method to be called. > */ > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > index 68f27f7..ffea28c 100644 > --- a/fs/xfs/xfs_trace.h > +++ b/fs/xfs/xfs_trace.h > @@ -38,6 +38,7 @@ struct xlog_recover_item; > struct xfs_buf_log_format; > struct xfs_inode_log_format; > struct xfs_bmbt_irec; > +struct xfs_btree_cur; > > DECLARE_EVENT_CLASS(xfs_attr_list_class, > TP_PROTO(struct xfs_attr_list_context *ctx), > @@ -2183,6 +2184,41 @@ DEFINE_DISCARD_EVENT(xfs_discard_toosmall); > DEFINE_DISCARD_EVENT(xfs_discard_exclude); > DEFINE_DISCARD_EVENT(xfs_discard_busy); > > +/* btree cursor events */ > +DECLARE_EVENT_CLASS(xfs_btree_cur_class, > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), > + TP_ARGS(cur, level, bp), > + TP_STRUCT__entry( > + __field(dev_t, dev) > + __field(xfs_btnum_t, btnum) > + __field(int, level) > + __field(int, nlevels) > + __field(int, ptr) > + __field(xfs_daddr_t, daddr) > + ), > + TP_fast_assign( > + __entry->dev = cur->bc_mp->m_super->s_dev; > + __entry->btnum = cur->bc_btnum; > + __entry->level = level; > + __entry->nlevels = cur->bc_nlevels; > + __entry->ptr = cur->bc_ptrs[level]; > + __entry->daddr = bp->b_bn; > + ), > + TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx", > + MAJOR(__entry->dev), MINOR(__entry->dev), > + __entry->btnum, > + __entry->level, > + __entry->nlevels, > + __entry->ptr, > + (unsigned long long)__entry->daddr) > +) > + > +#define DEFINE_BTREE_CUR_EVENT(name) \ > +DEFINE_EVENT(xfs_btree_cur_class, name, \ > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > + TP_ARGS(cur, level, bp)) > +DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > + > #endif /* _TRACE_XFS_H */ > > #undef TRACE_INCLUDE_PATH > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Wed Jun 22 10:18:08 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id CDA987CA0 for ; Wed, 22 Jun 2016 10:18:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 353FAAC007 for ; Wed, 22 Jun 2016 08:18:05 -0700 (PDT) X-ASG-Debug-ID: 1466608682-04cb6c063e78510001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 8ZBpNMZNVnhQpDFP (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 08:18:03 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5EC1B7AE94; Wed, 22 Jun 2016 15:18:02 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-2.bos.redhat.com [10.18.41.2]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5MFI1Ff024827; Wed, 22 Jun 2016 11:18:02 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id A2E3D1201DB; Wed, 22 Jun 2016 11:18:00 -0400 (EDT) Date: Wed, 22 Jun 2016 11:18:00 -0400 From: Brian Foster To: "Darrick J. Wong" Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 014/119] xfs: introduce interval queries on btrees Message-ID: <20160622151800.GC5423@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 014/119] xfs: introduce interval queries on btrees References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612636170.12839.675596870201079078.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612636170.12839.675596870201079078.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 22 Jun 2016 15:18:02 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466608682 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12207 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:21PM -0700, Darrick J. Wong wrote: > Create a function to enable querying of btree records mapping to a > range of keys. This will be used in subsequent patches to allow > querying the reverse mapping btree to find the extents mapped to a > range of physical blocks, though the generic code can be used for > any range query. > > v2: add some shortcuts so that we can jump out of processing once > we know there won't be any more records to find. > > Signed-off-by: Darrick J. Wong > --- > fs/xfs/libxfs/xfs_btree.c | 249 +++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/libxfs/xfs_btree.h | 22 +++- > fs/xfs/xfs_trace.h | 1 > 3 files changed, 267 insertions(+), 5 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index afcafd6..5f5cf23 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -4509,3 +4509,252 @@ xfs_btree_calc_size( > } > return rval; > } > + > +/* Query a regular btree for all records overlapping a given interval. */ Can you elaborate on the search algorithm used? (More for reference against the overlapped query, as that one is more complex). > +STATIC int > +xfs_btree_simple_query_range( > + struct xfs_btree_cur *cur, > + union xfs_btree_irec *low_rec, > + union xfs_btree_irec *high_rec, > + xfs_btree_query_range_fn fn, > + void *priv) > +{ > + union xfs_btree_rec *recp; > + union xfs_btree_rec rec; > + union xfs_btree_key low_key; > + union xfs_btree_key high_key; > + union xfs_btree_key rec_key; > + __int64_t diff; > + int stat; > + bool firstrec = true; > + int error; > + > + ASSERT(cur->bc_ops->init_high_key_from_rec); > + > + /* Find the keys of both ends of the interval. */ > + cur->bc_rec = *high_rec; > + cur->bc_ops->init_rec_from_cur(cur, &rec); > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > + > + cur->bc_rec = *low_rec; > + cur->bc_ops->init_rec_from_cur(cur, &rec); > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > + > + /* Find the leftmost record. */ > + stat = 0; > + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat); > + if (error) > + goto out; > + > + while (stat) { > + /* Find the record. */ > + error = xfs_btree_get_rec(cur, &recp, &stat); > + if (error || !stat) > + break; > + > + /* Can we tell if this record is too low? */ > + if (firstrec) { > + cur->bc_rec = *low_rec; > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > + diff = cur->bc_ops->key_diff(cur, &rec_key); > + if (diff < 0) > + goto advloop; > + } > + firstrec = false; This could move up into the if block. > + > + /* Have we gone past the end? */ > + cur->bc_rec = *high_rec; > + cur->bc_ops->init_key_from_rec(&rec_key, recp); I'd move this up to immediately after the xfs_btree_get_rec() call and eliminate the duplicate in the 'if (firstrec)' block above. > + diff = cur->bc_ops->key_diff(cur, &rec_key); > + if (diff > 0) > + break; > + > + /* Callback */ > + error = fn(cur, recp, priv); > + if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) > + break; > + > +advloop: > + /* Move on to the next record. */ > + error = xfs_btree_increment(cur, 0, &stat); > + if (error) > + break; > + } > + > +out: > + return error; > +} > + > +/* > + * Query an overlapped interval btree for all records overlapping a given > + * interval. > + */ Same comment here, can you elaborate on the search algorithm? Also, I think an example or generic description of the rules around what records this query returns (e.g., low_rec/high_rec vs. record low/high keys) would be useful, particularly since I, at least, don't have much context on the rmap+reflink scenarios quite yet. > +STATIC int > +xfs_btree_overlapped_query_range( > + struct xfs_btree_cur *cur, > + union xfs_btree_irec *low_rec, > + union xfs_btree_irec *high_rec, > + xfs_btree_query_range_fn fn, > + void *priv) > +{ > + union xfs_btree_ptr ptr; > + union xfs_btree_ptr *pp; > + union xfs_btree_key rec_key; > + union xfs_btree_key low_key; > + union xfs_btree_key high_key; > + union xfs_btree_key *lkp; > + union xfs_btree_key *hkp; > + union xfs_btree_rec rec; > + union xfs_btree_rec *recp; > + struct xfs_btree_block *block; > + __int64_t ldiff; > + __int64_t hdiff; > + int level; > + struct xfs_buf *bp; > + int i; > + int error; > + > + /* Find the keys of both ends of the interval. */ > + cur->bc_rec = *high_rec; > + cur->bc_ops->init_rec_from_cur(cur, &rec); > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > + > + cur->bc_rec = *low_rec; > + cur->bc_ops->init_rec_from_cur(cur, &rec); > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > + > + /* Load the root of the btree. */ > + level = cur->bc_nlevels - 1; > + cur->bc_ops->init_ptr_from_cur(cur, &ptr); > + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); > + if (error) > + return error; > + xfs_btree_get_block(cur, level, &bp); > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > +#ifdef DEBUG > + error = xfs_btree_check_block(cur, block, level, bp); > + if (error) > + goto out; > +#endif > + cur->bc_ptrs[level] = 1; > + > + while (level < cur->bc_nlevels) { > + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); > + > + if (level == 0) { > + /* End of leaf, pop back towards the root. */ > + if (cur->bc_ptrs[level] > > + be16_to_cpu(block->bb_numrecs)) { > +leaf_pop_up: > + if (level < cur->bc_nlevels - 1) > + cur->bc_ptrs[level + 1]++; > + level++; > + continue; > + } > + > + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); > + > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, > + &rec_key); > + > + cur->bc_ops->init_key_from_rec(&rec_key, recp); > + hdiff = cur->bc_ops->diff_two_keys(cur, &rec_key, > + &high_key); > + This looked a little funny to me because I expected diff_two_keys() to basically be param1 - param2. Looking ahead at the rmapbt code, it is in fact the other way around. I'm not sure we have precedent for either way, tbh. I still have to stare at this some more, but I wonder if a "does record overlap" helper (with comments) would help clean this up a bit. > + /* If the record matches, callback */ > + if (ldiff >= 0 && hdiff >= 0) { > + error = fn(cur, recp, priv); > + if (error < 0 || > + error == XFS_BTREE_QUERY_RANGE_ABORT) > + break; > + } else if (hdiff < 0) { > + /* Record is larger than high key; pop. */ > + goto leaf_pop_up; > + } > + cur->bc_ptrs[level]++; > + continue; > + } > + > + /* End of node, pop back towards the root. */ > + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { > +node_pop_up: > + if (level < cur->bc_nlevels - 1) > + cur->bc_ptrs[level + 1]++; > + level++; > + continue; Looks like same code as leaf_pop_up. I wonder if we can bury this at the end of the loop with a common label. > + } > + > + lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); > + hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); > + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); > + > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, hkp); > + hdiff = cur->bc_ops->diff_two_keys(cur, lkp, &high_key); > + > + /* If the key matches, drill another level deeper. */ > + if (ldiff >= 0 && hdiff >= 0) { > + level--; > + error = xfs_btree_lookup_get_block(cur, level, pp, > + &block); > + if (error) > + goto out; > + xfs_btree_get_block(cur, level, &bp); > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > +#ifdef DEBUG > + error = xfs_btree_check_block(cur, block, level, bp); > + if (error) > + goto out; > +#endif > + cur->bc_ptrs[level] = 1; > + continue; > + } else if (hdiff < 0) { > + /* The low key is larger than the upper range; pop. */ > + goto node_pop_up; > + } > + cur->bc_ptrs[level]++; > + } > + > +out: > + /* > + * If we don't end this function with the cursor pointing at a record > + * block, a subsequent non-error cursor deletion will not release > + * node-level buffers, causing a buffer leak. This is quite possible > + * with a zero-results range query, so release the buffers if we > + * failed to return any results. > + */ > + if (cur->bc_bufs[0] == NULL) { > + for (i = 0; i < cur->bc_nlevels; i++) { > + if (cur->bc_bufs[i]) { > + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); > + cur->bc_bufs[i] = NULL; > + cur->bc_ptrs[i] = 0; > + cur->bc_ra[i] = 0; > + } > + } > + } > + > + return error; > +} > + > +/* > + * Query a btree for all records overlapping a given interval of keys. The > + * supplied function will be called with each record found; return one of the > + * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error > + * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a > + * negative error code. > + */ > +int > +xfs_btree_query_range( > + struct xfs_btree_cur *cur, > + union xfs_btree_irec *low_rec, > + union xfs_btree_irec *high_rec, > + xfs_btree_query_range_fn fn, > + void *priv) > +{ > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > + return xfs_btree_simple_query_range(cur, low_rec, > + high_rec, fn, priv); > + return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, > + fn, priv); > +} > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index a5ec6c7..898fee5 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -206,6 +206,12 @@ struct xfs_btree_ops { > #define LASTREC_DELREC 2 > > > +union xfs_btree_irec { > + xfs_alloc_rec_incore_t a; > + xfs_bmbt_irec_t b; > + xfs_inobt_rec_incore_t i; > +}; > + We might as well kill off the typedef usage here. Brian > /* > * Btree cursor structure. > * This collects all information needed by the btree code in one place. > @@ -216,11 +222,7 @@ typedef struct xfs_btree_cur > struct xfs_mount *bc_mp; /* file system mount struct */ > const struct xfs_btree_ops *bc_ops; > uint bc_flags; /* btree features - below */ > - union { > - xfs_alloc_rec_incore_t a; > - xfs_bmbt_irec_t b; > - xfs_inobt_rec_incore_t i; > - } bc_rec; /* current insert/search record value */ > + union xfs_btree_irec bc_rec; /* current insert/search record value */ > struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ > int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ > __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ > @@ -494,4 +496,14 @@ xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, > unsigned long len); > > +/* return codes */ > +#define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */ > +#define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */ > +typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur, > + union xfs_btree_rec *rec, void *priv); > + > +int xfs_btree_query_range(struct xfs_btree_cur *cur, > + union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, > + xfs_btree_query_range_fn fn, void *priv); > + > #endif /* __XFS_BTREE_H__ */ > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > index ffea28c..f0ac9c9 100644 > --- a/fs/xfs/xfs_trace.h > +++ b/fs/xfs/xfs_trace.h > @@ -2218,6 +2218,7 @@ DEFINE_EVENT(xfs_btree_cur_class, name, \ > TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > TP_ARGS(cur, level, bp)) > DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > +DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); > > #endif /* _TRACE_XFS_H */ > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:26 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3F1957CA0 for ; Wed, 22 Jun 2016 10:27:26 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id F04B9304084 for ; Wed, 22 Jun 2016 08:27:25 -0700 (PDT) X-ASG-Debug-ID: 1466609242-04cbb0273882b30001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id IWxgWOFQNwrpNmTm (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:23 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk3m-0006W4-4l; Wed, 22 Jun 2016 15:27:22 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 1/8] xfs: don't pass ioflags around in the ioctl path Date: Wed, 22 Jun 2016 17:27:09 +0200 X-ASG-Orig-Subj: [PATCH 1/8] xfs: don't pass ioflags around in the ioctl path Message-Id: <1466609236-23801-2-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609243 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3867 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Instead check the file pointer for the invisble I/O flag directly, and use the chance to drop redundant arguments from the xfs_ioc_space prototype. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_ioctl.c | 22 ++++++++-------------- fs/xfs/xfs_ioctl.h | 3 --- fs/xfs/xfs_ioctl32.c | 6 +----- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index dbca737..6ab5a24 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -595,13 +595,12 @@ xfs_attrmulti_by_handle( int xfs_ioc_space( - struct xfs_inode *ip, - struct inode *inode, struct file *filp, - int ioflags, unsigned int cmd, xfs_flock64_t *bf) { + struct inode *inode = file_inode(filp); + struct xfs_inode *ip = XFS_I(inode); struct iattr iattr; enum xfs_prealloc_flags flags = 0; uint iolock = XFS_IOLOCK_EXCL; @@ -626,7 +625,7 @@ xfs_ioc_space( if (filp->f_flags & O_DSYNC) flags |= XFS_PREALLOC_SYNC; - if (ioflags & XFS_IO_INVIS) + if (filp->f_mode & FMODE_NOCMTIME) flags |= XFS_PREALLOC_INVISIBLE; error = mnt_want_write_file(filp); @@ -1464,8 +1463,7 @@ xfs_getbmap_format(void **ap, struct getbmapx *bmv, int *full) STATIC int xfs_ioc_getbmap( - struct xfs_inode *ip, - int ioflags, + struct file *file, unsigned int cmd, void __user *arg) { @@ -1479,10 +1477,10 @@ xfs_ioc_getbmap( return -EINVAL; bmx.bmv_iflags = (cmd == XFS_IOC_GETBMAPA ? BMV_IF_ATTRFORK : 0); - if (ioflags & XFS_IO_INVIS) + if (file->f_mode & FMODE_NOCMTIME) bmx.bmv_iflags |= BMV_IF_NO_DMAPI_READ; - error = xfs_getbmap(ip, &bmx, xfs_getbmap_format, + error = xfs_getbmap(XFS_I(file_inode(file)), &bmx, xfs_getbmap_format, (__force struct getbmap *)arg+1); if (error) return error; @@ -1619,12 +1617,8 @@ xfs_file_ioctl( struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; void __user *arg = (void __user *)p; - int ioflags = 0; int error; - if (filp->f_mode & FMODE_NOCMTIME) - ioflags |= XFS_IO_INVIS; - trace_xfs_file_ioctl(ip); switch (cmd) { @@ -1643,7 +1637,7 @@ xfs_file_ioctl( if (copy_from_user(&bf, arg, sizeof(bf))) return -EFAULT; - return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); + return xfs_ioc_space(filp, cmd, &bf); } case XFS_IOC_DIOINFO: { struct dioattr da; @@ -1702,7 +1696,7 @@ xfs_file_ioctl( case XFS_IOC_GETBMAP: case XFS_IOC_GETBMAPA: - return xfs_ioc_getbmap(ip, ioflags, cmd, arg); + return xfs_ioc_getbmap(filp, cmd, arg); case XFS_IOC_GETBMAPX: return xfs_ioc_getbmapx(ip, arg); diff --git a/fs/xfs/xfs_ioctl.h b/fs/xfs/xfs_ioctl.h index 77c02c7..8b52881 100644 --- a/fs/xfs/xfs_ioctl.h +++ b/fs/xfs/xfs_ioctl.h @@ -20,10 +20,7 @@ extern int xfs_ioc_space( - struct xfs_inode *ip, - struct inode *inode, struct file *filp, - int ioflags, unsigned int cmd, xfs_flock64_t *bf); diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index 1a05d8a..321f577 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c @@ -532,12 +532,8 @@ xfs_file_compat_ioctl( struct xfs_inode *ip = XFS_I(inode); struct xfs_mount *mp = ip->i_mount; void __user *arg = (void __user *)p; - int ioflags = 0; int error; - if (filp->f_mode & FMODE_NOCMTIME) - ioflags |= XFS_IO_INVIS; - trace_xfs_file_compat_ioctl(ip); switch (cmd) { @@ -589,7 +585,7 @@ xfs_file_compat_ioctl( if (xfs_compat_flock64_copyin(&bf, arg)) return -EFAULT; cmd = _NATIVE_IOC(cmd, struct xfs_flock64); - return xfs_ioc_space(ip, inode, filp, ioflags, cmd, &bf); + return xfs_ioc_space(filp, cmd, &bf); } case XFS_IOC_FSGEOMETRY_V1_32: return xfs_compat_ioc_fsgeometry_v1(mp, arg); -- 2.1.4 From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=LOCALPART_IN_SUBJECT autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 326267CA0 for ; Wed, 22 Jun 2016 10:27:27 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 043F0304066 for ; Wed, 22 Jun 2016 08:27:23 -0700 (PDT) X-ASG-Debug-ID: 1466609240-04cb6c063f7b6a0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id cF8cj3dSHHwbXDoG (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:20 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk3j-0006TZ-GC; Wed, 22 Jun 2016 15:27:19 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: xfs: untangle the direct I/O and DAX path, fix DAX locking Date: Wed, 22 Jun 2016 17:27:08 +0200 X-ASG-Orig-Subj: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-Id: <1466609236-23801-1-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609240 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 610 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 1.60 X-Barracuda-Spam-Status: No, SCORE=1.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, LOCALPART_IN_SUBJECT, LOCALPART_IN_SUBJECT_2, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 LOCALPART_IN_SUBJECT Local part of To: address appears in Subject 1.00 LOCALPART_IN_SUBJECT_2 Local part of To: address appears in Subject 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 The last patch is what started the series: XFS currently uses the direct I/O locking strategy for DAX because DAX was overloaded onto the direct I/O path. For XFS this means that we only take a shared inode lock instead of the normal exclusive one for writes IFF they are properly aligned. While this is fine for O_DIRECT which requires explicit opt-in from the application it's not fine for DAX where we'll suddenly lose expected and required synchronization of the file system happens to use DAX undeneath. Patches 1-7 just untangle the code so that we can deal with DAX on it's own easily. From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:28 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6F9ED7CB1 for ; Wed, 22 Jun 2016 10:27:28 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 410A0304066 for ; Wed, 22 Jun 2016 08:27:28 -0700 (PDT) X-ASG-Debug-ID: 1466609245-04cb6c063e7b750001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id nL40nXmHE3aXr0Ff (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:26 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk3o-0006Ya-O6; Wed, 22 Jun 2016 15:27:25 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 2/8] xfs: kill ioflags Date: Wed, 22 Jun 2016 17:27:10 +0200 X-ASG-Orig-Subj: [PATCH 2/8] xfs: kill ioflags Message-Id: <1466609236-23801-3-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609245 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5553 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Now that we have the direct I/O kiocb flag there is no real need to sample the value inside of XFS, and the invis flag was always just partially used and isn't worth keeping this infrastructure around for. This also splits the read tracepoint into buffered vs direct as we've done for writes a long time ago. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 26 +++++++++----------------- fs/xfs/xfs_inode.h | 10 ---------- fs/xfs/xfs_trace.h | 19 ++++++++----------- 3 files changed, 17 insertions(+), 38 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 713991c..b32e6b0 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -249,18 +249,12 @@ xfs_file_read_iter( struct xfs_mount *mp = ip->i_mount; size_t size = iov_iter_count(to); ssize_t ret = 0; - int ioflags = 0; xfs_fsize_t n; loff_t pos = iocb->ki_pos; XFS_STATS_INC(mp, xs_read_calls); - if (unlikely(iocb->ki_flags & IOCB_DIRECT)) - ioflags |= XFS_IO_ISDIRECT; - if (file->f_mode & FMODE_NOCMTIME) - ioflags |= XFS_IO_INVIS; - - if ((ioflags & XFS_IO_ISDIRECT) && !IS_DAX(inode)) { + if ((iocb->ki_flags & IOCB_DIRECT) && !IS_DAX(inode)) { xfs_buftarg_t *target = XFS_IS_REALTIME_INODE(ip) ? mp->m_rtdev_targp : mp->m_ddev_targp; @@ -293,7 +287,7 @@ xfs_file_read_iter( * serialisation. */ xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); - if ((ioflags & XFS_IO_ISDIRECT) && inode->i_mapping->nrpages) { + if ((iocb->ki_flags & IOCB_DIRECT) && inode->i_mapping->nrpages) { xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); @@ -327,7 +321,10 @@ xfs_file_read_iter( xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); } - trace_xfs_file_read(ip, size, pos, ioflags); + if (iocb->ki_flags & IOCB_DIRECT) + trace_xfs_file_direct_read(ip, size, pos); + else + trace_xfs_file_buffered_read(ip, size, pos); ret = generic_file_read_iter(iocb, to); if (ret > 0) @@ -346,18 +343,14 @@ xfs_file_splice_read( unsigned int flags) { struct xfs_inode *ip = XFS_I(infilp->f_mapping->host); - int ioflags = 0; ssize_t ret; XFS_STATS_INC(ip->i_mount, xs_read_calls); - if (infilp->f_mode & FMODE_NOCMTIME) - ioflags |= XFS_IO_INVIS; - if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return -EIO; - trace_xfs_file_splice_read(ip, count, *ppos, ioflags); + trace_xfs_file_splice_read(ip, count, *ppos); /* * DAX inodes cannot ues the page cache for splice, so we have to push @@ -620,7 +613,7 @@ xfs_file_dio_aio_write( iolock = XFS_IOLOCK_SHARED; } - trace_xfs_file_direct_write(ip, count, iocb->ki_pos, 0); + trace_xfs_file_direct_write(ip, count, iocb->ki_pos); data = *from; ret = mapping->a_ops->direct_IO(iocb, &data); @@ -670,8 +663,7 @@ xfs_file_buffered_aio_write( current->backing_dev_info = inode_to_bdi(inode); write_retry: - trace_xfs_file_buffered_write(ip, iov_iter_count(from), - iocb->ki_pos, 0); + trace_xfs_file_buffered_write(ip, iov_iter_count(from), iocb->ki_pos); ret = iomap_file_buffered_write(iocb, from, &xfs_iomap_ops); if (likely(ret >= 0)) iocb->ki_pos += ret; diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 0c19d3d..8eb78ec 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -473,14 +473,4 @@ do { \ extern struct kmem_zone *xfs_inode_zone; -/* - * Flags for read/write calls - */ -#define XFS_IO_ISDIRECT 0x00001 /* bypass page cache */ -#define XFS_IO_INVIS 0x00002 /* don't update inode timestamps */ - -#define XFS_IO_FLAGS \ - { XFS_IO_ISDIRECT, "DIRECT" }, \ - { XFS_IO_INVIS, "INVIS"} - #endif /* __XFS_INODE_H__ */ diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 6787a9f..2504f94 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1135,15 +1135,14 @@ TRACE_EVENT(xfs_log_assign_tail_lsn, ) DECLARE_EVENT_CLASS(xfs_file_class, - TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), - TP_ARGS(ip, count, offset, flags), + TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset), + TP_ARGS(ip, count, offset), TP_STRUCT__entry( __field(dev_t, dev) __field(xfs_ino_t, ino) __field(xfs_fsize_t, size) __field(loff_t, offset) __field(size_t, count) - __field(int, flags) ), TP_fast_assign( __entry->dev = VFS_I(ip)->i_sb->s_dev; @@ -1151,23 +1150,21 @@ DECLARE_EVENT_CLASS(xfs_file_class, __entry->size = ip->i_d.di_size; __entry->offset = offset; __entry->count = count; - __entry->flags = flags; ), - TP_printk("dev %d:%d ino 0x%llx size 0x%llx " - "offset 0x%llx count 0x%zx ioflags %s", + TP_printk("dev %d:%d ino 0x%llx size 0x%llx offset 0x%llx count 0x%zx", MAJOR(__entry->dev), MINOR(__entry->dev), __entry->ino, __entry->size, __entry->offset, - __entry->count, - __print_flags(__entry->flags, "|", XFS_IO_FLAGS)) + __entry->count) ) #define DEFINE_RW_EVENT(name) \ DEFINE_EVENT(xfs_file_class, name, \ - TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset, int flags), \ - TP_ARGS(ip, count, offset, flags)) -DEFINE_RW_EVENT(xfs_file_read); + TP_PROTO(struct xfs_inode *ip, size_t count, loff_t offset), \ + TP_ARGS(ip, count, offset)) +DEFINE_RW_EVENT(xfs_file_buffered_read); +DEFINE_RW_EVENT(xfs_file_direct_read); DEFINE_RW_EVENT(xfs_file_buffered_write); DEFINE_RW_EVENT(xfs_file_direct_write); DEFINE_RW_EVENT(xfs_file_splice_read); -- 2.1.4 From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:29 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D95A57CB1 for ; Wed, 22 Jun 2016 10:27:29 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id AB82E304066 for ; Wed, 22 Jun 2016 08:27:29 -0700 (PDT) X-ASG-Debug-ID: 1466609247-04cbb0273682bd0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id msMqZAuC0pC3fUFz (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:28 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk3r-0006aR-CI; Wed, 22 Jun 2016 15:27:27 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 3/8] xfs: remove s_maxbytes enforcement in xfs_file_read_iter Date: Wed, 22 Jun 2016 17:27:11 +0200 X-ASG-Orig-Subj: [PATCH 3/8] xfs: remove s_maxbytes enforcement in xfs_file_read_iter Message-Id: <1466609236-23801-4-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609248 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 889 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 All the three low-level read implementations that we might call already take care of not overflowing the maximum supported bytes, no need to duplicate it here. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index b32e6b0..09a5a78 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -249,7 +249,6 @@ xfs_file_read_iter( struct xfs_mount *mp = ip->i_mount; size_t size = iov_iter_count(to); ssize_t ret = 0; - xfs_fsize_t n; loff_t pos = iocb->ki_pos; XFS_STATS_INC(mp, xs_read_calls); @@ -266,13 +265,6 @@ xfs_file_read_iter( } } - n = mp->m_super->s_maxbytes - pos; - if (n <= 0 || size == 0) - return 0; - - if (n < size) - size = n; - if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; -- 2.1.4 From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:33 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 70A007CBC for ; Wed, 22 Jun 2016 10:27:33 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 239B28F8081 for ; Wed, 22 Jun 2016 08:27:33 -0700 (PDT) X-ASG-Debug-ID: 1466609250-04bdf05e6d849d0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id RUJqa4CCYJBawx7G (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:30 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk3t-0006cv-Uw; Wed, 22 Jun 2016 15:27:30 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 4/8] xfs: split xfs_file_read_iter into buffered and direct I/O helpers Date: Wed, 22 Jun 2016 17:27:12 +0200 X-ASG-Orig-Subj: [PATCH 4/8] xfs: split xfs_file_read_iter into buffered and direct I/O helpers Message-Id: <1466609236-23801-5-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609250 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4466 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Similar to what we did on the write side a while ago. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 83 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 57 insertions(+), 26 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 09a5a78..e584333 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -239,35 +239,33 @@ xfs_file_fsync( } STATIC ssize_t -xfs_file_read_iter( +xfs_file_dio_aio_read( struct kiocb *iocb, struct iov_iter *to) { - struct file *file = iocb->ki_filp; - struct inode *inode = file->f_mapping->host; + struct address_space *mapping = iocb->ki_filp->f_mapping; + struct inode *inode = mapping->host; struct xfs_inode *ip = XFS_I(inode); - struct xfs_mount *mp = ip->i_mount; - size_t size = iov_iter_count(to); + size_t count = iov_iter_count(to); + struct xfs_buftarg *target; ssize_t ret = 0; - loff_t pos = iocb->ki_pos; - XFS_STATS_INC(mp, xs_read_calls); + trace_xfs_file_direct_read(ip, count, iocb->ki_pos); - if ((iocb->ki_flags & IOCB_DIRECT) && !IS_DAX(inode)) { - xfs_buftarg_t *target = - XFS_IS_REALTIME_INODE(ip) ? - mp->m_rtdev_targp : mp->m_ddev_targp; + if (XFS_IS_REALTIME_INODE(ip)) + target = ip->i_mount->m_rtdev_targp; + else + target = ip->i_mount->m_ddev_targp; + + if (!IS_DAX(inode)) { /* DIO must be aligned to device logical sector size */ - if ((pos | size) & target->bt_logical_sectormask) { - if (pos == i_size_read(inode)) + if ((iocb->ki_pos | count) & target->bt_logical_sectormask) { + if (iocb->ki_pos == i_size_read(inode)) return 0; return -EINVAL; } } - if (XFS_FORCED_SHUTDOWN(mp)) - return -EIO; - /* * Locking is a bit tricky here. If we take an exclusive lock for direct * IO, we effectively serialise all new concurrent read IO to this file @@ -279,7 +277,7 @@ xfs_file_read_iter( * serialisation. */ xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); - if ((iocb->ki_flags & IOCB_DIRECT) && inode->i_mapping->nrpages) { + if (mapping->nrpages) { xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); xfs_rw_ilock(ip, XFS_IOLOCK_EXCL); @@ -294,8 +292,8 @@ xfs_file_read_iter( * flush and reduce the chances of repeated iolock cycles going * forward. */ - if (inode->i_mapping->nrpages) { - ret = filemap_write_and_wait(VFS_I(ip)->i_mapping); + if (mapping->nrpages) { + ret = filemap_write_and_wait(mapping); if (ret) { xfs_rw_iunlock(ip, XFS_IOLOCK_EXCL); return ret; @@ -306,23 +304,56 @@ xfs_file_read_iter( * we fail to invalidate a page, but this should never * happen on XFS. Warn if it does fail. */ - ret = invalidate_inode_pages2(VFS_I(ip)->i_mapping); + ret = invalidate_inode_pages2(mapping); WARN_ON_ONCE(ret); ret = 0; } xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); } + ret = generic_file_read_iter(iocb, to); + xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); + + return ret; +} + +STATIC ssize_t +xfs_file_buffered_aio_read( + struct kiocb *iocb, + struct iov_iter *to) +{ + struct xfs_inode *ip = XFS_I(file_inode(iocb->ki_filp)); + ssize_t ret; + + trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos); + + xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); + ret = generic_file_read_iter(iocb, to); + xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); + + return ret; +} + +STATIC ssize_t +xfs_file_read_iter( + struct kiocb *iocb, + struct iov_iter *to) +{ + struct xfs_mount *mp = XFS_I(file_inode(iocb->ki_filp))->i_mount; + ssize_t ret = 0; + + XFS_STATS_INC(mp, xs_read_calls); + + if (XFS_FORCED_SHUTDOWN(mp)) + return -EIO; + if (iocb->ki_flags & IOCB_DIRECT) - trace_xfs_file_direct_read(ip, size, pos); + ret = xfs_file_dio_aio_read(iocb, to); else - trace_xfs_file_buffered_read(ip, size, pos); + ret = xfs_file_buffered_aio_read(iocb, to); - ret = generic_file_read_iter(iocb, to); if (ret > 0) XFS_STATS_ADD(mp, xs_read_bytes, ret); - - xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); return ret; } @@ -578,7 +609,7 @@ xfs_file_dio_aio_write( end = iocb->ki_pos + count - 1; /* - * See xfs_file_read_iter() for why we do a full-file flush here. + * See xfs_file_dio_aio_read() for why we do a full-file flush here. */ if (mapping->nrpages) { ret = filemap_write_and_wait(VFS_I(ip)->i_mapping); -- 2.1.4 From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:35 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A2C887CB1 for ; Wed, 22 Jun 2016 10:27:35 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 73CB98F8059 for ; Wed, 22 Jun 2016 08:27:35 -0700 (PDT) X-ASG-Debug-ID: 1466609253-04cbb0273582c10001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id PBSa1jlfKcxDviFT (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:33 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk3w-0006ek-H7; Wed, 22 Jun 2016 15:27:32 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 5/8] xfs: stop using generic_file_read_iter for direct I/O Date: Wed, 22 Jun 2016 17:27:13 +0200 X-ASG-Orig-Subj: [PATCH 5/8] xfs: stop using generic_file_read_iter for direct I/O Message-Id: <1466609236-23801-6-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609253 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1888 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 XFS already implement it's own flushing of the pagecache because it implements proper synchronization for direct I/O reads. This means calling generic_file_read_iter for direct I/O is rather useless, as it doesn't do much but updating the atime and iocb position for us. This also gets rid of the buffered I/O fallback that isn't used for XFS. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index e584333..f761f49 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -246,12 +246,17 @@ xfs_file_dio_aio_read( struct address_space *mapping = iocb->ki_filp->f_mapping; struct inode *inode = mapping->host; struct xfs_inode *ip = XFS_I(inode); + loff_t isize = i_size_read(inode); size_t count = iov_iter_count(to); + struct iov_iter data; struct xfs_buftarg *target; ssize_t ret = 0; trace_xfs_file_direct_read(ip, count, iocb->ki_pos); + if (!count) + return 0; /* skip atime */ + if (XFS_IS_REALTIME_INODE(ip)) target = ip->i_mount->m_rtdev_targp; else @@ -260,7 +265,7 @@ xfs_file_dio_aio_read( if (!IS_DAX(inode)) { /* DIO must be aligned to device logical sector size */ if ((iocb->ki_pos | count) & target->bt_logical_sectormask) { - if (iocb->ki_pos == i_size_read(inode)) + if (iocb->ki_pos == isize) return 0; return -EINVAL; } @@ -311,9 +316,15 @@ xfs_file_dio_aio_read( xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); } - ret = generic_file_read_iter(iocb, to); + data = *to; + ret = mapping->a_ops->direct_IO(iocb, &data); + if (ret > 0) { + iocb->ki_pos += ret; + iov_iter_advance(to, ret); + } xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); + file_accessed(iocb->ki_filp); return ret; } -- 2.1.4 From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:38 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5A3767CCE for ; Wed, 22 Jun 2016 10:27:38 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 266DC8F8059 for ; Wed, 22 Jun 2016 08:27:38 -0700 (PDT) X-ASG-Debug-ID: 1466609255-04cb6c063d7b840001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id kBQ3pru0URxQkmiI (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:36 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk3z-0006gq-2M; Wed, 22 Jun 2016 15:27:35 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 6/8] xfs: direct calls in the direct I/O path Date: Wed, 22 Jun 2016 17:27:14 +0200 X-ASG-Orig-Subj: [PATCH 6/8] xfs: direct calls in the direct I/O path Message-Id: <1466609236-23801-7-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609256 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3164 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 We control both the callers and callees of ->direct_IO, so remove the indirect calls. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_aops.c | 24 +++++------------------- fs/xfs/xfs_aops.h | 3 +++ fs/xfs/xfs_file.c | 17 +++++++++++++++-- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 80714eb..b368277 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -1303,7 +1303,7 @@ xfs_get_blocks_dax_fault( * whereas if we have flags set we will always be called in task context * (i.e. from a workqueue). */ -STATIC int +int xfs_end_io_direct_write( struct kiocb *iocb, loff_t offset, @@ -1374,24 +1374,10 @@ xfs_vm_direct_IO( struct kiocb *iocb, struct iov_iter *iter) { - struct inode *inode = iocb->ki_filp->f_mapping->host; - dio_iodone_t *endio = NULL; - int flags = 0; - struct block_device *bdev; - - if (iov_iter_rw(iter) == WRITE) { - endio = xfs_end_io_direct_write; - flags = DIO_ASYNC_EXTEND; - } - - if (IS_DAX(inode)) { - return dax_do_io(iocb, inode, iter, - xfs_get_blocks_direct, endio, 0); - } - - bdev = xfs_find_bdev_for_inode(inode); - return __blockdev_direct_IO(iocb, inode, bdev, iter, - xfs_get_blocks_direct, endio, NULL, flags); + /* + * We just need the method present so that open/fcntl allow direct I/O. + */ + return -EINVAL; } STATIC sector_t diff --git a/fs/xfs/xfs_aops.h b/fs/xfs/xfs_aops.h index 814aab7..bf2d9a1 100644 --- a/fs/xfs/xfs_aops.h +++ b/fs/xfs/xfs_aops.h @@ -60,6 +60,9 @@ int xfs_get_blocks_direct(struct inode *inode, sector_t offset, int xfs_get_blocks_dax_fault(struct inode *inode, sector_t offset, struct buffer_head *map_bh, int create); +int xfs_end_io_direct_write(struct kiocb *iocb, loff_t offset, + ssize_t size, void *private); + extern void xfs_count_page_state(struct page *, int *, int *); extern struct block_device *xfs_find_bdev_for_inode(struct inode *); diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index f761f49..24b267d 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -317,7 +317,13 @@ xfs_file_dio_aio_read( } data = *to; - ret = mapping->a_ops->direct_IO(iocb, &data); + if (IS_DAX(inode)) { + ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct, + NULL, 0); + } else { + ret = __blockdev_direct_IO(iocb, inode, target->bt_bdev, &data, + xfs_get_blocks_direct, NULL, NULL, 0); + } if (ret > 0) { iocb->ki_pos += ret; iov_iter_advance(to, ret); @@ -650,7 +656,14 @@ xfs_file_dio_aio_write( trace_xfs_file_direct_write(ip, count, iocb->ki_pos); data = *from; - ret = mapping->a_ops->direct_IO(iocb, &data); + if (IS_DAX(inode)) { + ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct, + xfs_end_io_direct_write, 0); + } else { + ret = __blockdev_direct_IO(iocb, inode, target->bt_bdev, &data, + xfs_get_blocks_direct, xfs_end_io_direct_write, + NULL, DIO_ASYNC_EXTEND); + } /* see generic_file_direct_write() for why this is necessary */ if (mapping->nrpages) { -- 2.1.4 From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:41 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E7ED17CB5 for ; Wed, 22 Jun 2016 10:27:41 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id B00D9304084 for ; Wed, 22 Jun 2016 08:27:41 -0700 (PDT) X-ASG-Debug-ID: 1466609258-04cb6c063c7b880001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id tSAfwONIKtpJZsMS (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:38 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk41-0006iS-KQ; Wed, 22 Jun 2016 15:27:38 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 7/8] xfs: split direct I/O and DAX path Date: Wed, 22 Jun 2016 17:27:15 +0200 X-ASG-Orig-Subj: [PATCH 7/8] xfs: split direct I/O and DAX path Message-Id: <1466609236-23801-8-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609258 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7112 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 So far the DAX code overloaded the direct I/O code path. There is very little in common between the two, and untangling them allows to clean up both variants. As a ѕide effect we also get separate trace points for both I/O types. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 139 ++++++++++++++++++++++++++++++++++++++++++----------- fs/xfs/xfs_trace.h | 2 + 2 files changed, 112 insertions(+), 29 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 24b267d..0e74325 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -262,13 +262,11 @@ xfs_file_dio_aio_read( else target = ip->i_mount->m_ddev_targp; - if (!IS_DAX(inode)) { - /* DIO must be aligned to device logical sector size */ - if ((iocb->ki_pos | count) & target->bt_logical_sectormask) { - if (iocb->ki_pos == isize) - return 0; - return -EINVAL; - } + /* DIO must be aligned to device logical sector size */ + if ((iocb->ki_pos | count) & target->bt_logical_sectormask) { + if (iocb->ki_pos == isize) + return 0; + return -EINVAL; } /* @@ -317,13 +315,37 @@ xfs_file_dio_aio_read( } data = *to; - if (IS_DAX(inode)) { - ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct, - NULL, 0); - } else { - ret = __blockdev_direct_IO(iocb, inode, target->bt_bdev, &data, - xfs_get_blocks_direct, NULL, NULL, 0); + ret = __blockdev_direct_IO(iocb, inode, target->bt_bdev, &data, + xfs_get_blocks_direct, NULL, NULL, 0); + if (ret > 0) { + iocb->ki_pos += ret; + iov_iter_advance(to, ret); } + xfs_rw_iunlock(ip, XFS_IOLOCK_SHARED); + + file_accessed(iocb->ki_filp); + return ret; +} + +STATIC ssize_t +xfs_file_dax_read( + struct kiocb *iocb, + struct iov_iter *to) +{ + struct address_space *mapping = iocb->ki_filp->f_mapping; + struct inode *inode = mapping->host; + struct xfs_inode *ip = XFS_I(inode); + struct iov_iter data = *to; + size_t count = iov_iter_count(to); + ssize_t ret = 0; + + trace_xfs_file_dax_read(ip, count, iocb->ki_pos); + + if (!count) + return 0; /* skip atime */ + + xfs_rw_ilock(ip, XFS_IOLOCK_SHARED); + ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct, NULL, 0); if (ret > 0) { iocb->ki_pos += ret; iov_iter_advance(to, ret); @@ -356,7 +378,8 @@ xfs_file_read_iter( struct kiocb *iocb, struct iov_iter *to) { - struct xfs_mount *mp = XFS_I(file_inode(iocb->ki_filp))->i_mount; + struct inode *inode = file_inode(iocb->ki_filp); + struct xfs_mount *mp = XFS_I(inode)->i_mount; ssize_t ret = 0; XFS_STATS_INC(mp, xs_read_calls); @@ -364,7 +387,9 @@ xfs_file_read_iter( if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; - if (iocb->ki_flags & IOCB_DIRECT) + if (IS_DAX(inode)) + ret = xfs_file_dax_read(iocb, to); + else if (iocb->ki_flags & IOCB_DIRECT) ret = xfs_file_dio_aio_read(iocb, to); else ret = xfs_file_buffered_aio_read(iocb, to); @@ -586,8 +611,7 @@ xfs_file_dio_aio_write( mp->m_rtdev_targp : mp->m_ddev_targp; /* DIO must be aligned to device logical sector size */ - if (!IS_DAX(inode) && - ((iocb->ki_pos | count) & target->bt_logical_sectormask)) + if ((iocb->ki_pos | count) & target->bt_logical_sectormask) return -EINVAL; /* "unaligned" here means not aligned to a filesystem block */ @@ -656,14 +680,9 @@ xfs_file_dio_aio_write( trace_xfs_file_direct_write(ip, count, iocb->ki_pos); data = *from; - if (IS_DAX(inode)) { - ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct, - xfs_end_io_direct_write, 0); - } else { - ret = __blockdev_direct_IO(iocb, inode, target->bt_bdev, &data, - xfs_get_blocks_direct, xfs_end_io_direct_write, - NULL, DIO_ASYNC_EXTEND); - } + ret = __blockdev_direct_IO(iocb, inode, target->bt_bdev, &data, + xfs_get_blocks_direct, xfs_end_io_direct_write, + NULL, DIO_ASYNC_EXTEND); /* see generic_file_direct_write() for why this is necessary */ if (mapping->nrpages) { @@ -680,10 +699,70 @@ out: xfs_rw_iunlock(ip, iolock); /* - * No fallback to buffered IO on errors for XFS. DAX can result in - * partial writes, but direct IO will either complete fully or fail. + * No fallback to buffered IO on errors for XFS, direct IO will either + * complete fully or fail. + */ + ASSERT(ret < 0 || ret == count); + return ret; +} + +STATIC ssize_t +xfs_file_dax_write( + struct kiocb *iocb, + struct iov_iter *from) +{ + struct address_space *mapping = iocb->ki_filp->f_mapping; + struct inode *inode = mapping->host; + struct xfs_inode *ip = XFS_I(inode); + struct xfs_mount *mp = ip->i_mount; + ssize_t ret = 0; + int unaligned_io = 0; + int iolock; + struct iov_iter data; + + /* "unaligned" here means not aligned to a filesystem block */ + if ((iocb->ki_pos & mp->m_blockmask) || + ((iocb->ki_pos + iov_iter_count(from)) & mp->m_blockmask)) { + unaligned_io = 1; + iolock = XFS_IOLOCK_EXCL; + } else if (mapping->nrpages) { + iolock = XFS_IOLOCK_EXCL; + } else { + iolock = XFS_IOLOCK_SHARED; + } + xfs_rw_ilock(ip, iolock); + + ret = xfs_file_aio_write_checks(iocb, from, &iolock); + if (ret) + goto out; + + /* + * Yes, even DAX files can have page cache attached to them: A zeroed + * page is inserted into the pagecache when we have to serve a write + * fault on a hole. It should never be dirtied and can simply be + * dropped from the pagecache once we get real data for the page. */ - ASSERT(ret < 0 || ret == count || IS_DAX(VFS_I(ip))); + if (mapping->nrpages) { + ret = invalidate_inode_pages2(mapping); + WARN_ON_ONCE(ret); + } + + if (iolock == XFS_IOLOCK_EXCL && !unaligned_io) { + xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); + iolock = XFS_IOLOCK_SHARED; + } + + trace_xfs_file_dax_write(ip, iov_iter_count(from), iocb->ki_pos); + + data = *from; + ret = dax_do_io(iocb, inode, &data, xfs_get_blocks_direct, + xfs_end_io_direct_write, 0); + if (ret > 0) { + iocb->ki_pos += ret; + iov_iter_advance(from, ret); + } +out: + xfs_rw_iunlock(ip, iolock); return ret; } @@ -765,7 +844,9 @@ xfs_file_write_iter( if (XFS_FORCED_SHUTDOWN(ip->i_mount)) return -EIO; - if ((iocb->ki_flags & IOCB_DIRECT) || IS_DAX(inode)) + if (IS_DAX(inode)) + ret = xfs_file_dax_write(iocb, from); + else if (iocb->ki_flags & IOCB_DIRECT) ret = xfs_file_dio_aio_write(iocb, from); else ret = xfs_file_buffered_aio_write(iocb, from); diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 2504f94..1451690 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -1165,8 +1165,10 @@ DEFINE_EVENT(xfs_file_class, name, \ TP_ARGS(ip, count, offset)) DEFINE_RW_EVENT(xfs_file_buffered_read); DEFINE_RW_EVENT(xfs_file_direct_read); +DEFINE_RW_EVENT(xfs_file_dax_read); DEFINE_RW_EVENT(xfs_file_buffered_write); DEFINE_RW_EVENT(xfs_file_direct_write); +DEFINE_RW_EVENT(xfs_file_dax_write); DEFINE_RW_EVENT(xfs_file_splice_read); DECLARE_EVENT_CLASS(xfs_page_class, -- 2.1.4 From BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org Wed Jun 22 10:27:42 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 849A07CB5 for ; Wed, 22 Jun 2016 10:27:42 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 3CBDB8F8059 for ; Wed, 22 Jun 2016 08:27:42 -0700 (PDT) X-ASG-Debug-ID: 1466609260-04bdf05e6e84ae0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id R6uOXHgAaWKoA5nZ (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:27:40 -0700 (PDT) X-Barracuda-Envelope-From: BATV+33f16d706b64780ffb45+4686+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [83.175.99.196] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bFk44-0006kD-5H; Wed, 22 Jun 2016 15:27:40 +0000 From: Christoph Hellwig To: xfs@oss.sgi.com Cc: linux-nvdimm@ml01.01.org, linux-fsdevel@vger.kernel.org Subject: [PATCH 8/8] xfs: fix locking for DAX writes Date: Wed, 22 Jun 2016 17:27:16 +0200 X-ASG-Orig-Subj: [PATCH 8/8] xfs: fix locking for DAX writes Message-Id: <1466609236-23801-9-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> References: <1466609236-23801-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466609260 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1910 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30662 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 So far DAX writes inherited the locking from direct I/O writes, but the direct I/O model of using shared locks for writes is actually wrong for DAX. For direct I/O we're out of any standards and don't have to provide the Posix required exclusion between writers, but for DAX which gets transparently enable on applications without any knowledge of it we can't simply drop the requirement. Even worse this only happens for aligned writes and thus doesn't show up for many typical use cases. Signed-off-by: Christoph Hellwig --- fs/xfs/xfs_file.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 0e74325..413c9e0 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c @@ -714,24 +714,11 @@ xfs_file_dax_write( struct address_space *mapping = iocb->ki_filp->f_mapping; struct inode *inode = mapping->host; struct xfs_inode *ip = XFS_I(inode); - struct xfs_mount *mp = ip->i_mount; ssize_t ret = 0; - int unaligned_io = 0; - int iolock; + int iolock = XFS_IOLOCK_EXCL; struct iov_iter data; - /* "unaligned" here means not aligned to a filesystem block */ - if ((iocb->ki_pos & mp->m_blockmask) || - ((iocb->ki_pos + iov_iter_count(from)) & mp->m_blockmask)) { - unaligned_io = 1; - iolock = XFS_IOLOCK_EXCL; - } else if (mapping->nrpages) { - iolock = XFS_IOLOCK_EXCL; - } else { - iolock = XFS_IOLOCK_SHARED; - } xfs_rw_ilock(ip, iolock); - ret = xfs_file_aio_write_checks(iocb, from, &iolock); if (ret) goto out; @@ -747,11 +734,6 @@ xfs_file_dax_write( WARN_ON_ONCE(ret); } - if (iolock == XFS_IOLOCK_EXCL && !unaligned_io) { - xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); - iolock = XFS_IOLOCK_SHARED; - } - trace_xfs_file_dax_write(ip, iov_iter_count(from), iocb->ki_pos); data = *from; -- 2.1.4 From danny@zadarastorage.com Wed Jun 22 10:58:22 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C41D97CA3 for ; Wed, 22 Jun 2016 10:58:22 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 37CC2AC007 for ; Wed, 22 Jun 2016 08:58:22 -0700 (PDT) X-ASG-Debug-ID: 1466611098-04cb6c063f84340001-NocioJ Received: from mail-lf0-f53.google.com (mail-lf0-f53.google.com [209.85.215.53]) by cuda.sgi.com with ESMTP id VZ2sYOJMU3j3TUIi (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 08:58:19 -0700 (PDT) X-Barracuda-Envelope-From: danny@zadarastorage.com X-Barracuda-Effective-Source-IP: mail-lf0-f53.google.com[209.85.215.53] X-Barracuda-Apparent-Source-IP: 209.85.215.53 Received: by mail-lf0-f53.google.com with SMTP id q132so77396658lfe.3 for ; Wed, 22 Jun 2016 08:58:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zadarastorage-com.20150623.gappssmtp.com; s=20150623; h=mime-version:from:date:message-id:subject:to; bh=BXsQM6F2JtqLKjogyC8+Ax4rhDd9AOfS6nCmh0JnT9Y=; b=o8LODhcImBF/iQUgMgeO0BvzwCsn1q7d+Zra8jvUI91dcBC1ewRC9y4jj9iYm8vyCI 252F8+kbqO6jACfD295mniF/HWLewL10Tk5iWNVaIBOK7AspWiUQppsTQqYFAYnN81EZ qi11gbu5g4GDWx1z2OQZvM38RLrzcwWzXA3pPJhr0iR8f8esBNCh47oukck1pT2H/Kzv A/+V49POpd/vdsH4fRz3w37jl9UmL+EZlRF3GLtc5TlXYFCGpV0dNdpYMDGLdbGUshDf caDYq0OubacCmOcxTtY6TffK7MTOjJWc5gAlkH309U60e5CoVJzctbPe+u1k2n6RhyLz 7ElQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=BXsQM6F2JtqLKjogyC8+Ax4rhDd9AOfS6nCmh0JnT9Y=; b=SQSwoxOg+oDT3FDECJ4trRsEcvD/VA5l5j3n3KLSZivufnhQUC2wC7cMN+h2opj7lI +X794SaL1+4nwD1y/aNm8TfkWuMxyH5bJ0crS8QQSBVbHTHBdkLCzK+fmxrUDauhF42z zvgbAKw7F6TWkMnZLqEdgtITeFFj95WmItaCUCQLzouE4/oY1PZlMa08DOCwKdM37710 DW8RGjWhLwEBj3ov3otx7BCBmICQv38TrdqqruW5MUuFNkiZxtzRLvABpqR2VzdWvj0x fzEwwY2kVbJOpxTsoQRaUT2O5nAbLEkmb5HXtCj2FXfGSH7HvE+t+MqwvOJf0hvS+iO4 YHXQ== X-Gm-Message-State: ALyK8tI9GqwgMaGLRdycgL/P3kkp8anglk7TqWEpBWQ9k/ht0x5iBPTrMEx/CmvE7xNW5y/jRtn0LwslON6iUw== X-Received: by 10.25.2.195 with SMTP id 186mr9858034lfc.36.1466611097787; Wed, 22 Jun 2016 08:58:17 -0700 (PDT) MIME-Version: 1.0 Received: by 10.114.5.37 with HTTP; Wed, 22 Jun 2016 08:58:16 -0700 (PDT) From: Danny Shavit Date: Wed, 22 Jun 2016 18:58:16 +0300 Message-ID: Subject: xfs metadata overhead To: xfs@oss.sgi.com X-ASG-Orig-Subj: xfs metadata overhead Content-Type: multipart/alternative; boundary=001a113ca6068203c20535e00154 X-Barracuda-Connect: mail-lf0-f53.google.com[209.85.215.53] X-Barracuda-Start-Time: 1466611099 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 934 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30663 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --001a113ca6068203c20535e00154 Content-Type: text/plain; charset=UTF-8 Hi, We are looking for a method to estimate the size of metadata overhead for a given file system. We would like to use this value as indicator for the amount of cache memory a system for faster operation. Are there any counters that are maintained in the on-disk data structures like free space for examples? -- Thank you, Danny Shavit Zadarastorage --001a113ca6068203c20535e00154 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hi,

We are looking for a method to esti= mate the size of metadata overhead for a given file system.
We wo= uld like to use this value as indicator for the amount of cache memory a sy= stem for faster operation.
Are there any counters that are mainta= ined in the on-disk data structures=C2=A0like free space for examples?

--
Thank you,
Danny Shavit=
Zadarastorage
--001a113ca6068203c20535e00154-- From darrick.wong@oracle.com Wed Jun 22 12:40:37 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3DA537CA1 for ; Wed, 22 Jun 2016 12:40:37 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 03A26304048 for ; Wed, 22 Jun 2016 10:40:33 -0700 (PDT) X-ASG-Debug-ID: 1466617231-04cb6c063ea3e30001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id voN1or8ECsRRWeok (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for ; Wed, 22 Jun 2016 10:40:31 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5MHeUWw013790 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 22 Jun 2016 17:40:30 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5MHeUqo010674 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 22 Jun 2016 17:40:30 GMT Received: from abhmp0004.oracle.com (abhmp0004.oracle.com [141.146.116.10]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5MHeSSJ031954 for ; Wed, 22 Jun 2016 17:40:29 GMT Received: from localhost (/173.240.251.56) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 22 Jun 2016 10:40:26 -0700 Date: Wed, 22 Jun 2016 10:40:25 -0700 From: "Darrick J. Wong" To: xfs@oss.sgi.com Subject: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly Message-ID: <20160622174025.GB5042@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 2/2] xfs_check: process sparse inode chunks correctly References: <1466441562-12317-1-git-send-email-bfoster@redhat.com> <1466441562-12317-3-git-send-email-bfoster@redhat.com> <20160621090153.GB28212@redhat.com> <20160621232940.GQ12670@dastard> <20160622080324.GG28212@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622080324.GG28212@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466617231 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3350 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30667 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Wed, Jun 22, 2016 at 10:03:24AM +0200, Carlos Maiolino wrote: > On Wed, Jun 22, 2016 at 09:29:40AM +1000, Dave Chinner wrote: > > On Tue, Jun 21, 2016 at 08:54:04AM -0500, Eric Sandeen wrote: > > > > > > > > > On 6/21/16 4:01 AM, Carlos Maiolino wrote: > > > > On Mon, Jun 20, 2016 at 12:52:42PM -0400, Brian Foster wrote: > > > >> Update the inode btree scanning functions to process sparse inode chunks > > > >> correctly. For filesystems with sparse inode support enabled, process > > > >> each chunk a cluster at a time. Each cluster is checked against the > > > >> inobt record to determine if it is a hole and skipped if so. > > > >> > > > >> Note that since xfs_check is deprecated in favor of xfs_repair, this > > > >> adds the minimum support necessary to process sparse inode enabled > > > >> filesystems. In other words, this adds no sparse inode specific checks > > > >> or verifications. We only update the inobt scanning functions to extend > > > >> the existing level of verification to sparse inode enabled filesystems > > > >> (e.g., avoid incorrectly tracking sparse regions as inodes). Problems > > > >> or corruptions associated with sparse inode records must be detected and > > > >> recovered via xfs_repair. > > > >> > > > > > > > > Hi, > > > > > > > > I'm not quite sure, but a while ago, I thought I've heard some rumors about > > > > deprecating xfs_check, is this true or something that my mind made up for some > > > > weird reason? > > > > > > Yes, like Brian said above. ;) > > > > > > bfc541e xfsprogs: remove xfs_check > > > 12a48f5 xfsprogs: remove xfs_check references from fsck.xfs script & manpage > > > > > > However, we still run check inside xfs_db in xfstests as an independent > > > verification step: > > > > > > 187bccd xfstests: Remove dependence of xfs_check script > > > > > > +# xfs_check script is planned to be deprecated. But, we want to > > > +# be able to invoke "xfs_check" behavior in xfstests in order to > > > +# maintain the current verification levels. > > > +_xfs_check() > > > > Right - it's a secondary set of code that effectively tells us > > whether repair is detecting all the problems it should. i.e. if > > check fails and repair doesn't, then we've got a bug in repair that > > needs fixing. > > > > Just out of curiosity here, have we hit any case like that for the past few > versions? I have, while writing reflink. Granted, that only happened /once/. While we're talking about repair/xfstests, I also started running xfs_repair and then xfs_repair -n to _check_xfs_filesystem, which helped me find some cases where the rmapbt rebuild wasn't quite right. --D > > > Also, the check code is really just an "addon" to other > > functionality in xfs_db (e.g. blockget) that we have to keep, so > > removing check doesn't really gain us all that much in terms of > > reduced maintenance overhead. So long as we can easily keep check up > > to date with new features I think we shoul dbe keeping it... > > > > Good to know. > > Cheers o/ > > > Cheers, > > > > Dave. > > -- > > Dave Chinner > > david@fromorbit.com > > > > -- > Carlos > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From am7314012@gmail.com Wed Jun 22 15:34:06 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.4 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HDRS_LCASE,HTML_MESSAGE,T_FRT_CONTACT autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EB7D27CA1 for ; Wed, 22 Jun 2016 15:34:06 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id A7FA08F8033 for ; Wed, 22 Jun 2016 13:34:03 -0700 (PDT) X-ASG-Debug-ID: 1466627639-04cbb02736d6de0001-NocioJ Received: from vps33700.lws-hosting.com (vps33700.lws-hosting.com [91.234.194.100]) by cuda.sgi.com with ESMTP id gRmB02vGNlB21GPC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 22 Jun 2016 13:34:00 -0700 (PDT) X-Barracuda-Envelope-From: am7314012@gmail.com X-Barracuda-Effective-Source-IP: vps33700.lws-hosting.com[91.234.194.100] X-Barracuda-Apparent-Source-IP: 91.234.194.100 Received: from localhost (localhost.localdomain [127.0.0.1]) by vps33700.lws-hosting.com (Postfix) with ESMTP id 38659361BEE; Wed, 22 Jun 2016 22:33:46 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at vps33700.lws-hosting.com Received: from vps33700.lws-hosting.com ([127.0.0.1]) by localhost (vps33700.lws-hosting.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EKtMITgeVspZ; Wed, 22 Jun 2016 22:33:45 +0200 (CEST) Received: from [93.113.206.29] (vps-16173.fhnet.fr [93.113.206.29]) (Authenticated sender: infos-schafer@anja.ch) by vps33700.lws-hosting.com (Postfix) with ESMTPSA id EBD80361BC9; Wed, 22 Jun 2016 22:33:11 +0200 (CEST) Message-Id: Mime-Version: 1.0 From: Anja To: Undisclosed-Recipients:; Reply-To: anjas-chafer@jaschke.be Subject: =?iso-8859-1?Q?Ernst__und_sehr_vertraulich__/s=E9rieux_et_tr=E8s_confidentielle_?= Date: Wed, 22 Jun 2016 22:33:37 +0200 X-ASG-Orig-Subj: =?iso-8859-1?Q?Ernst__und_sehr_vertraulich__/s=E9rieux_et_tr=E8s_confidentielle_?= Content-type: multipart/alternative; Boundary="--=BOUNDARY_6222233_WHAC_LMDS_ETMT_VRDS" X-Barracuda-Connect: vps33700.lws-hosting.com[91.234.194.100] X-Barracuda-Start-Time: 1466627640 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5706 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30670 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message Ce message est au format MIME. Comme votre logiciel de courrier ne comprendpas ce format, tout ou partie de ce message pourrait être illisible. ----=BOUNDARY_6222233_WHAC_LMDS_ETMT_VRDS Content-type: text/plain; charset=iso-8859-1; format=flowed Content-transfer-encoding: quoted-printable Hallo Wenn Sie diese Nachricht senden wollte, ist dies nicht einfach Zufall= =2E Und zwar deshalb, weil Ihre e-Mail-Adresse durch den elektronischen Rob= oter sicherte sich meine WX=2E7AR BW ausgew=E4hlt wurde=2E Zun=E4chst m=F6chte ich f=FCr dieses Eindringen in Ihr Leben zu entschuldig= en, obwohl ich zugeben, dass es mir sehr wichtig ist=2E Mein Name ist Anja = Schafer=2E Ich leide an einer Dysfunktion des Herzen und totale L=E4hmung m= einer Mitglieder seit nun mehr als 7 Jahre und eine halbe und es leider, me= in Arzt hat nur informierte mich, dass ich bin voll unheilbar und, dass mei= ne Tage, weil meine etwas gez=E4hlt sind abgebaut Gesundheits-Zustand= =2E Ich bin eine Witwe und ich habe nicht Kind, das ich fange an zu bitter = bereuen=2E In der Tat ist der Grund warum ich Sie kontaktiere m=F6chte ich einen Teil = meines Eigentums zu spenden, weil ich niemand haben die Erben k=F6nnte= =2E Ich verkaufte fast alle meine Sachen, einschlie=DFlich einer Ausfuhr vo= n Holz und Kautschuk und eine Stahlindustrie in Europa, wo ich mehr als 10 = Jahren Leben=2E Ein Gro=DFteil dieser Mittel, die gesammelt wurden untersch= iedliche Assoziationen auf humanit=E4re Zeichen =FCberall auf der Welt Kontaktieren Sie mich und erhalten meine Spende f=FCr Ihre Projekte zu Gott m=F6ge Sie segnen Anja =2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E= =2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E Bonjour , Si j'ai voulu vous envoyer ce message, ce n'est pas un simple hasard= =2E C'est parce que votre E-mail a =E9t=E9 s=E9lectionn=E9 par le Robot = =E9lectronique bien s=E9curis=E9 de mon P=2EC WX=2E7AR=2E Je tiens dans un premier temps =E0 m'excuser pour cette intrusion dans votr= e vie m=EAme si j'avoue que cela est tr=E8s important pour moi=2E Je m'appe= lle anja schafer =2E Je souffre d'un dysfonctionnement de Cour et la paral= ysie totale des mes membres depuis maintenant plus de 7 ans et demi et l= =E0 malheureusement, mon m=E9decin traitant vient de m'informer que je suis= en pleine phase terminale et que mes jours sont compt=E9s du fait de mon = =E9tat de sant=E9 assez d=E9grad=E9=2E Je suis veuve et je n'ai pas eu d'en= fant ce que je commence =E0 regretter am=E8rement=2E Au fait, la raison pour laquelle je vous contacte est que je souhaite faire= Don d'une partie de mes biens vu que je n'ai personne qui pourrait en h= =E9riter=2E J'ai presque vendu toutes mes affaires dont une entreprise d'e= xportation de bois et d'h=E9v=E9a et une Sid=E9rurgie en Europe o=F9 je vis= depuis maintenant plus de 10 ans=2E Une grosse partie de tous ces fonds r= =E9colt=E9s a =E9t=E9 vers=E9e aupr=E8s de diff=E9rentes associations = =E0 caract=E8res humanitaires un peu partout dans le monde Contactez moi et b=E9n=E9ficier de ma donation pour vos projets Que Dieu vous B=E9nis ----=BOUNDARY_6222233_WHAC_LMDS_ETMT_VRDS Content-type: text/html; charset=iso-8859-1 Content-transfer-encoding: quoted-printable HTML Message
Hallo
Wenn Sie diese Nachricht senden= wollte, ist dies nicht einfach Zufall=2E Und zwar deshalb, weil Ihre e-Mai= l-Adresse durch den elektronischen Roboter sicherte sich meine WX=2E7AR BW = ausgew=E4hlt wurde=2E
Zun=E4chst m=F6chte ich f=FCr dieses Eindringen in= Ihr Leben zu entschuldigen, obwohl ich zugeben, dass es mir sehr wichtig i= st=2E Mein Name ist Anja Schafer=2E Ich leide an einer Dysfunktion des Herz= en und totale L=E4hmung meiner Mitglieder seit nun mehr als 7 Jahre und ein= e halbe und es leider, mein Arzt hat nur informierte mich, dass ich bin vol= l unheilbar und, dass meine Tage, weil meine etwas gez=E4hlt sind abgebaut = Gesundheits-Zustand=2E Ich bin eine Witwe und ich habe nicht Kind, das ich = fange an zu bitter bereuen=2E
In der Tat ist der Grund warum ich Sie kon= taktiere m=F6chte ich einen Teil meines Eigentums zu spenden, weil ich niem= and haben die Erben k=F6nnte=2E Ich verkaufte fast alle meine Sachen, einsc= hließlich einer Ausfuhr von Holz und Kautschuk und eine Stahlindustri= e in Europa, wo ich mehr als 10 Jahren Leben=2E Ein Großteil dieser M= ittel, die gesammelt wurden unterschiedliche Assoziationen auf humanit= =E4re Zeichen =FCberall auf der Welt
Kontaktieren Sie mich und erhalten= meine Spende f=FCr Ihre Projekte zu
Gott m=F6ge Sie segnen
Anja
=
=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E= =2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E=2E
Bonjour ,

Si = j'ai voulu vous envoyer ce message, ce n'est pas un simple hasard=2E C'est = parce que votre E-mail a =E9t=E9 s=E9lectionn=E9 par le Robot =E9lectroniqu= e bien s=E9curis=E9 de mon P=2EC WX=2E7AR=2E

Je tiens dans un premie= r temps =E0 m'excuser pour cette intrusion dans votre vie m=EAme si j'avoue= que cela est tr=E8s important pour moi=2E Je m'appelle anja schafer = =2E Je souffre d'un dysfonctionnement de Cœur et la paralysie totale d= es mes membres depuis maintenant plus de 7 ans et demi et l=E0 malheureuse= ment, mon m=E9decin traitant vient de m'informer que je suis en pleine phas= e terminale et que mes jours sont compt=E9s du fait de mon =E9tat de sant= =E9 assez d=E9grad=E9=2E Je suis veuve et je n'ai pas eu d'enfant ce que je= commence =E0 regretter am=E8rement=2E

Au fait, la raison pour laque= lle je vous contacte est que je souhaite faire Don d'une partie de mes bien= s vu que je n'ai personne qui pourrait en h=E9riter=2E J'ai presque vendu t= outes mes affaires dont une entreprise d'exportation de bois et d'h= =E9v=E9a et une Sid=E9rurgie en Europe o=F9 je vis depuis maintenant plus d= e 10 ans=2E Une grosse partie de tous ces fonds r=E9colt=E9s a =E9t=E9 vers= =E9e aupr=E8s de diff=E9rentes associations =E0 caract=E8res humanitaires u= n peu partout dans le monde
Contactez moi et b=E9n=E9ficier de ma donat= ion pour vos projets
Que Dieu vous B=E9nis
----=BOUNDARY_6222233_WHAC_LMDS_ETMT_VRDS-- From david@fromorbit.com Wed Jun 22 17:11:11 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C66047CA1 for ; Wed, 22 Jun 2016 17:11:11 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4E7A9AC003 for ; Wed, 22 Jun 2016 15:11:11 -0700 (PDT) X-ASG-Debug-ID: 1466633463-04cb6c063ced800001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id k1MR51CaOJwDrHh5 for ; Wed, 22 Jun 2016 15:11:03 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CtFwCo7GpXEJgMLHlegz5WfYJ2omYBAQEGjDuKDyKFbwICAQECgS9NAQEBAQEBBwEBAQEBAQEBPkCETAEBAQMBOhwjBQsIAxgJGgsPBSUDBxoTiCgHD8UHAQEBAQEFAgEfBR6FQYUVhBIRAQYJhUsdBYgNhWuBMoQghTOGCIgbgXOEU4hnj3yDD4FHKjIBiS4NF4EeAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 23 Jun 2016 07:40:00 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFqLP-0004FV-Eo; Thu, 23 Jun 2016 08:09:59 +1000 Date: Thu, 23 Jun 2016 08:09:59 +1000 From: Dave Chinner To: Damien Gombault Cc: xfs@oss.sgi.com Subject: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed Message-ID: <20160622220959.GV12670@dastard> X-ASG-Orig-Subj: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466633463 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3217 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30673 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header [please line wrap your email at 68-72 columns] On Wed, Jun 22, 2016 at 04:45:19PM +0200, Damien Gombault wrote: > Hi. > > I have reported few weeks ago a bug on the Red Hat Bugzilla for > CentOS 7 : https://bugzilla.redhat.com/show_bug.cgi?id=1341126 I > had to restore a level0+level1 dump for my ownCloud server, but > during the level1 restoration, xfsrestore showed many warnings and > some directories/files were not restored. I recently tried to > restore a more recent level0+level1 dump and I get the same > results with other directories/files. I tried to figure out why > and now I am able to reproduce the problem with a minimal test > case. > > Here is the test case : It's hard to understand xfsrestore problems without the xfsdump output that generated the dumps being restored. What is the (verbose) output of xfsdump under this test? .... > xfsrestore: level: 0 > xfsrestore: session label: "test" > xfsrestore: media label: "test" ... > xfsrestore: directory 2048 0 (0): updating > xfsrestore: dirent dira 2051 0: adding (new) > xfsrestore: directory 2051 0 (0): upgrading to dir > xfsrestore: dirent filea 2052 0: adding (new) > xfsrestore: 2 directories and 2 entries processed Which is correct. .... > xfsrestore: level: 1 > xfsrestore: session label: "test" > xfsrestore: media label: "test" .... > xfsrestore: directory 2048 0 (0): updating > xfsrestore: dirent dirA 2051 0: renaming (name) > xfsrestore: directory 2051 0 (0): updating > xfsrestore: dirent filea 2052 0: retaining (nondir) > xfsrestore: dirent dirb 526336 1283006502: adding (new) > xfsrestore: directory 526336 1283006502 (1283006502): upgrading to dir > xfsrestore: dirent fileb 526337 1283006502: adding (new) > xfsrestore: 3 directories and 4 entries processed So the inventory looks ok.... > xfsrestore: rename dir dira to orphanage/2051.0 > xfsrestore: making new directories > xfsrestore: performing directory renames > xfsrestore: rename dir orphanage/2051.0 to dirA And the rename occurs... > xfsrestore: processing hard links > xfsrestore: processing hardlinks to 2052 0 > xfsrestore: processing hardlinks to 526337 1283006502 > xfsrestore: getting next media file for non-dir restore > xfsrestore: Media_mfile_next: purp==2 pos==3 > xfsrestore: dump session label: "test" > xfsrestore: dump session id: 27606c57-7b3b-43ff-83b9-69158e75f612 > xfsrestore: stream 0, object 0, file 0 > xfsrestore: restoring non-directory files > xfsrestore: media file 0 in object 0 of stream 0 > xfsrestore: file 0 in stream, file 0 in dump 0 on object > xfsrestore: restoring dirA/dirb/fileb (526337 1283006502) > xfsrestore: restoring regular file ino 526337 dirA/dirb/fileb > xfsrestore: WARNING: open of dirA/dirb/fileb failed: Aucun fichier ou dossier de ce type: discarding ino 526337 But it seems that dirb hasn't been created before the file in it is being restored. THis can happen because the inventory is not correct, whichmay in fact be a problem with dump rather than restore... I'll have a bit of a play around here, see if I can reproduce it. Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Wed Jun 22 17:23:37 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 581767CA1 for ; Wed, 22 Jun 2016 17:23:37 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 19F0F8F8035 for ; Wed, 22 Jun 2016 15:23:37 -0700 (PDT) X-ASG-Debug-ID: 1466634209-04cbb02735e66a0001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id qmSeFZkIHGcWdndC for ; Wed, 22 Jun 2016 15:23:30 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DLFgCo7GpXEJgMLHlegz6BU4J2g3mebQEBAQaMO4oPhhEEAgKBL00BAQEBAQEHAQEBAQEBAQE+QIRNAQEEOhwjEAgDGAkaCw8FJQMHGhOIL8UWAQEIAiUehUGFFYl+HQEEmH2OI4FdjVCPfIMPgUcqMopxAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 23 Jun 2016 07:53:29 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFqYS-0004Hx-DR; Thu, 23 Jun 2016 08:23:28 +1000 Date: Thu, 23 Jun 2016 08:23:28 +1000 From: Dave Chinner To: Damien Gombault Cc: xfs@oss.sgi.com Subject: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed Message-ID: <20160622222328.GW12670@dastard> X-ASG-Orig-Subj: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed References: <20160622220959.GV12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622220959.GV12670@dastard> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466634209 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 465 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30674 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 23, 2016 at 08:09:59AM +1000, Dave Chinner wrote: > But it seems that dirb hasn't been created before the file in it > is being restored. THis can happen because the inventory is not > correct, whichmay in fact be a problem with dump rather than > restore... > > I'll have a bit of a play around here, see if I can reproduce it. Yes, i can reproduce it, so I'll have a deeper look. Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Wed Jun 22 17:51:27 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 039D27CA1 for ; Wed, 22 Jun 2016 17:51:26 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id AEB688F8033 for ; Wed, 22 Jun 2016 15:51:26 -0700 (PDT) X-ASG-Debug-ID: 1466635878-04cbb02738e7760001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id Bd1YE2oCSHou6AB0 for ; Wed, 22 Jun 2016 15:51:18 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AeNACo7GpXEJgMLHlegz6BU4J2g3mebQEBAQaMO4oPhhEEAgKBL00BAQEBAQEHAQEBAQEBAQE+QEEBBAkBg30BAQQ6HCMQCAMYCSUPBSUDBxoTiC/FFgEBCAIlHoVBhRWKGwWYfY4jjy2PfIRWKjKINiCCGwEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 23 Jun 2016 08:21:18 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFqzN-0004MH-4j; Thu, 23 Jun 2016 08:51:17 +1000 Date: Thu, 23 Jun 2016 08:51:17 +1000 From: Dave Chinner To: Danny Shavit Cc: xfs@oss.sgi.com Subject: Re: xfs metadata overhead Message-ID: <20160622225117.GX12670@dastard> X-ASG-Orig-Subj: Re: xfs metadata overhead References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466635878 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 852 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30674 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 22, 2016 at 06:58:16PM +0300, Danny Shavit wrote: > Hi, > > We are looking for a method to estimate the size of metadata overhead for a > given file system. > We would like to use this value as indicator for the amount of cache memory > a system for faster operation. > Are there any counters that are maintained in the on-disk data > structures like free space for examples? No. Right now, you'll need to take a metadump of the filesystem to measure it. The size of the dump file will be a close indication of the amount of metadata in the filesystem as it only contains the filesystem metadata. In future, querying the rmap will enable us to calculate it on the fly, (i.e. not requiring the filesystem to be snapshotted/taken off line to do a metadump). Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Wed Jun 22 17:58:24 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 2BC127CA1 for ; Wed, 22 Jun 2016 17:58:24 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id ECB00304032 for ; Wed, 22 Jun 2016 15:58:20 -0700 (PDT) X-ASG-Debug-ID: 1466636298-04cb6c063feead0001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id EvAkowORjjvMtSIK for ; Wed, 22 Jun 2016 15:58:18 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DLFgCo7GpXEJgMLHlUCoM+gVOCdoN5nm0BAQEGjDuKD4YRBAICgS9NAQEBAQEBBwEBAQEBAQEBPkCETQEBBDocIxAIAw4KCSUPBSUDBxoTG4gUxRYBAQEHAiUehUGFFYQYhgMFmH2OI48tj3yCXByBXioyinEBAQE Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 23 Jun 2016 08:28:17 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from ) id 1bFr68-0004O5-Ns; Thu, 23 Jun 2016 08:58:16 +1000 Date: Thu, 23 Jun 2016 08:58:16 +1000 From: Dave Chinner To: Michal Hocko Cc: Peter Zijlstra , "Darrick J. Wong" , Qu Wenruo , xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160622225816.GY12670@dastard> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160601181617.GV3190@twins.programming.kicks-ass.net> <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> <20160602232254.GR12670@dastard> <20160606122022.GH11895@dhcp22.suse.cz> <20160615072154.GF26977@dastard> <20160621142628.GG30848@dhcp22.suse.cz> <20160622010320.GR12670@dastard> <20160622123822.GG9208@dhcp22.suse.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622123822.GG9208@dhcp22.suse.cz> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466636298 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2173 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30674 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 22, 2016 at 02:38:22PM +0200, Michal Hocko wrote: > On Wed 22-06-16 11:03:20, Dave Chinner wrote: > > On Tue, Jun 21, 2016 at 04:26:28PM +0200, Michal Hocko wrote: > > > On Wed 15-06-16 17:21:54, Dave Chinner wrote: > [...] > > > > There are allocations outside transaction context which need to be > > > > GFP_NOFS - this is what KM_NOFS was originally intended for. > > > > > > Is it feasible to mark those by the scope NOFS api as well and drop > > > the direct KM_NOFS usage? This should help to identify those that are > > > lockdep only and use the annotation to prevent from the false positives. > > > > I don't understand what you are suggesting here. This all started > > because we use GFP_NOFS in a handful of places to shut up lockdep > > and you didn't want us to use GFP_NOFS like that. Now it sounds to > > me like you are advocating setting unconditional GFP_NOFS allocation > > contexts for entire XFS code paths - whether it's necessary or > > not - to avoid problems with lockdep false positives. > > No, I meant only those paths which need GFP_NOFS for other than lockdep > purposes would use the scope api. > > Anyway, it seems that we are not getting closer to a desired solution > here. Or I am not following it at least... > > It seems that we have effectively two possibilities (from the > MM/lockdep) POV. Either add an explicit API to disable the reclaim > lockdep machinery for all allocation in a certain scope or a GFP mask > to to achieve the same for a particular allocation. Which one would work > better for the xfs usecase? As I've said - if we annotate the XFS call sites appropriately (e.g. KM_NOLOCKDEP rather than KM_NOFS), we don't care what lockdep mechanism is used to turn off warnings as it will be wholly encapsulated inside kmem_alloc() and friends. This will end up similar to how we are currently encapsulate the memalloc_noio_save() wrappers in kmem_zalloc_large(). IOWs, it doesn't matter to XFS whether it be a GFP flag or a PF flag here, because it's not going to be exposed to the higher level code. Cheers, Dave. -- Dave Chinner david@fromorbit.com From bounces+2504343-36b9-xfs=oss.sgi.com@sendgrid.net Wed Jun 22 19:06:46 2016 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_MESSAGE,MIME_HTML_ONLY, SPOOFED_URL_HOST,T_DKIM_INVALID autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 53B047CA1 for ; Wed, 22 Jun 2016 19:06:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 26C5E8F8033 for ; Wed, 22 Jun 2016 17:06:43 -0700 (PDT) X-ASG-Debug-ID: 1466640392-04cb6c063df0e00001-NocioJ Received: from o3.server2.stampready.net (o3.server2.stampready.net [167.89.25.94]) by cuda.sgi.com with ESMTP id dWj7yYDYAtundBEh (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for ; Wed, 22 Jun 2016 17:06:34 -0700 (PDT) X-Barracuda-Envelope-From: bounces+2504343-36b9-xfs=oss.sgi.com@sendgrid.net X-Barracuda-Effective-Source-IP: o3.server2.stampready.net[167.89.25.94] X-Barracuda-Apparent-Source-IP: 167.89.25.94 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sendgrid.net; h=content-transfer-encoding:content-type:from:mime-version:subject:to; s=smtpapi; bh=Z+oc85ZGm9/QGW2vthoKUfVQbSE=; b=tkdu2eXH33HdAXn8tv Hs5M2v0aaukfDUuzk5j84yszqeZek2T7zRqzfK15CNa6ytWKjkgK894NHMhgACpB 8jkZrY3Yy24eqOdgxSp5GkpVM+4aBv4dwqQrnIZbXC1PFn1bdL1WXJund/QoZQhd 4LOJ+OjIFzuu/AGcm+WA8n1CU= Received: by filter0917p1mdw1.sendgrid.net with SMTP id filter0917p1mdw1.10439.576B27ADB 2016-06-23 00:05:01.155503046 +0000 UTC Received: from MjUwNDM0Mw (srv1.n-i-c-e.nl [128.140.221.60]) by ismtpd0004p1lon1.sendgrid.net (SG) with HTTP id g4cX8s-IT_WNr4kSgEvJNA for ; Thu, 23 Jun 2016 00:05:01.127 +0000 (UTC) Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=UTF-8 Date: Thu, 23 Jun 2016 00:05:01 +0000 From: "KOA CCTV" Mime-Version: 1.0 Subject: LUTRON RadioRA LEVEL 1 TRAINING To: xfs@oss.sgi.com X-ASG-Orig-Subj: LUTRON RadioRA LEVEL 1 TRAINING Message-ID: X-SG-EID: GPcH5AR4FNxUx3/k94obBuFzds479X57W1U837jaM3fPtknDfBnfo1Ms8DtnglH3nK1Tw7XHPO/ziV BUqbc/Ug7rJEt0hG8HQohxJVQknd2e6UYz2Ypua3Hx8r+Ha6qqTF4hmAtkBIK6Agf1egimleduVSg2 E0TZ+2A6KwiVu+60QRT2YZasq3icY5/wH5TuXpmYkgO2IS+DVYUB8QzjrA== X-SG-ID: R3ufbdLo2r/cRGFtfGlyBq+N0UDQ5m5Z60LaabNaXKW5+lK72FcpRRRzdBOxM0egvVzmCYQcbiS3Ej NvwXoMIYbaYIp5bKk+nyabZ/ZT3hN/mOkypxAsUcSMD80mzbq90a2usJOBndcDlqwKWEBQE4rDp7Fh pBa0SsMyJqWkvDaBEzSdRf5a+q+5MgnLvMq3jLSfk/er8WEyeJ22YTD53w== X-Barracuda-Connect: o3.server2.stampready.net[167.89.25.94] X-Barracuda-Start-Time: 1466640393 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 65510 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE, MIME_HTML_ONLY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30676 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message Cuneo</tit= le><meta http-equiv=3D"X-UA-Compatible" content=3D"IE=3Dedge"><meta http-eq= uiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8"><meta name=3D"v= iewport" content=3D"width=3Ddevice-width, initial-scale=3D1, minimum-scale= =3D1, maximum-scale=3D1"><style type=3D"text/css"> .ReadMsgBody { width: 100%; background-color: #FFFFFF; } .ExternalClass { width: 100%; background-color: #FFFFFF; } .ExternalClass, .ExternalClass p, .ExternalClass span, .ExternalClass font,= .ExternalClass td, .ExternalClass div { line-height: 100%; } html { width: 100%; } body { -webkit-text-size-adjust: none; -ms-text-size-adjust: none; margin: = 0; padding: 0; font-family: 'Open Sans', Arial, Sans-serif !important; } table { border-spacing: 0; table-layout: fixed; margin: 0 auto; } table table table { table-layout: auto; } img { display: block !important; over-flow: hidden !important; } table td { border-collapse: collapse; } .yshortcuts a { border-bottom: none !important; } a { color: #FF6363; text-decoration: none; } img:hover { opacity: 0.9 !important; } /*Responsive*/ @media only screen and (max-width: 640px) { body { width: auto !important; font-family: 'Open Sans', Arial, Sans-serif = !important; } table[class=3D"table-inner"] { width: 90% !important; } table[class=3D"table-full"] { width: 100% !important; text-align: center !i= mportant; } /* Image */ img[class=3D"img1"] { width: 100% !important; height: auto !important; } } @media only screen and (max-width: 479px) { body { width: auto !important; font-family: 'Open Sans', Arial, Sans-serif = !important; } table[class=3D"table-inner"] { width: 90% !important; text-align: center !i= mportant; } table[class=3D"table-full"] { width: 100% !important; text-align: center !i= mportant; } /* image */ img[class=3D"img1"] { width: 100% !important; height: auto !important; } } </style></head><body><span style=3D"display: none!important; font-size: 1px= ; color: #FFF; opacity: 0; text-indent: -9999px;">LUTRON RadioRA LEVEL 1 TR= AINING</span> =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09 <table data-thumb=3D"http://www.stampready.net/dashboard/templates/cune= o/thumbnails/header-bar.jpg" data-module=3D"header-bar" data-bgcolor=3D"Hea= der-Bar BG" width=3D"100%" bgcolor=3D"#FFFFFF" align=3D"center" border=3D"0= " cellspacing=3D"0" cellpadding=3D"0"> <tr> <td align=3D"center"> <table align=3D"center" class=3D"table-inner" width=3D"600" border= =3D"0" cellspacing=3D"0" cellpadding=3D"0"> <tr> <td height=3D"30"></td> </tr> <tr> <td> <!--logo--> <table class=3D"table-full" border=3D"0" align=3D"left" cellp= adding=3D"0" cellspacing=3D"0"> <tr> <td align=3D"center" style=3D"line-height: 0px;"><a href= =3D"https://u2504343.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2Ft= PTyM19wokIJyrfdoRqkibU-3D_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5= gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2B= o8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpo= Q5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQb= JAyzCY4fQG37H3Y5PD3PEuJCf-2B4V35PVa-2BvA4y7JBanUApMOyVlIX01hlmCLRYzPsf2iozu= QgrXU4rql96ufidw-2FMKVb7KdVsDPjSQ7CuJayXeM5AK7-2FpNirR3vnr-2BaJZayCPYZJPd4b= Zn1z199WzXGuptxh8T67Wah4F6c-3D"><img data-crop=3D"false" style=3D"display:b= lock; line-height:0px; font-size:0px; border:0px;" src=3D"http://www.stampr= eady.net/dashboard/editor/user_uploads/image_uploads/2016/06/22/fwnKGQXMNk0= CSFVhdTqmBtzx76WZ9vcr.png" alt=3D"arrow"></a></td> </tr> </table> <!--end logo--> <!--Space--> <table width=3D"1" border=3D"0" cellpadding=3D"0" cellspacing= =3D"0" align=3D"left"> <tr> <td height=3D"15" style=3D"font-size: 0;line-height: 0px;= border-collapse: collapse;"> <p style=3D"padding-left: 24px;"> </p> </td> </tr> </table> <!--End Space--> <!--menu--> <table class=3D"table-full" align=3D"right" border=3D"0" cell= spacing=3D"0" cellpadding=3D"0"> <tr> <td data-link-style=3D"text-decoration:none; color:#9B9B9= B;" data-link-color=3D"Menu Link Color" data-size=3D"Menu" data-color=3D"Me= nu" data-min=3D"12" data-max=3D"22" style=3D"font-family: 'Open Sans', Aria= l, sans-serif; color:#9B9B9B; font-size:13px;"><b><a href=3D"https://u25043= 43.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2FtDHCVkT67-2B3VLOpmF= 03i5oY-3D_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2= tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1X= vUaG8nA095yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1= HbMmXC5SxFNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5= PALJh-2BAs59bNlmQRGvNnOf3lPi46cTOmO5KeujZAXyMfSyfDm-2FcjEBVlAuN3Ha9-2BFQCUc= xrKJIAsZ34ObF9za7TCfWILiNVOZPaKKk8i0ay-2Fp2TaRfm2I04CdAhttPBidf-2BirDGo-2FQ= TV7qwmgE-2FYXvc-3D" style=3D"text-decoration:none; color:#9B9B9B;" data-col= or=3D"Menu Link Color">NEWS</a></b><span style=3D"padding-left:5px;padding-= right:8px;">/</span><b><a href=3D"https://u2504343.ct.sendgrid.net/wf/click= ?upn=3D0vK3KXYTBabZQHrA6gI-2FtIDBewdj0aAmMI0lG3PTpcBPfvfK6XeW4t3P-2FwfUAYpq= _hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ= 30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA09= 5yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5Sx= FNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PLQOmu3tm= DL9zu2ywpAsKpvqzO5DwKUh3C7x6K7jGmnNGjNzfzn7Q1XsaCkrvanUyKtFmUbiF3HB8Bkhm1VU= TpS6-2FIjSemfPYH6s7rvEzlhn9DuAE6XcbGCYDCWoeE3J2kwcsannTgGpYA6q5yXEZlM-3D" s= tyle=3D"text-decoration:none; color:#9B9B9B;" data-color=3D"Menu Link Color= ">SPECIALS</a></b><span style=3D"padding-left:5px;padding-right:8px;">/</sp= an><a href=3D"https://u2504343.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQ= HrA6gI-2FtIDBewdj0aAmMI0lG3PTpcA-3D_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabP= xkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idB= Eq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3= GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEK= k5jctGWiQbJAyzCY4fQG37H3Y5PHK2x3BmdC2I-2BGHrKWIKiEwa9mf5SCZ5x88bXC5GY1SPg9r= ugb9phJfpK7b3ChqUMZJC9boqjtooOHqGcHlKYJa92yGCNwayvhp6d2aZv7NFrXtNz191MSqFGj= 7viCPZQxnQRySFIhTrkfYJoaWX1v8-3D" style=3D"text-decoration:none; color:#9B9= B9B;" data-color=3D"Menu Link Color"><b>PRODUCTS</b></a></td> </tr> </table> <!--end menu--> </td> </tr> <tr> <td height=3D"20"></td> </tr> </table> </td> </tr> </table><table data-thumb=3D"http://www.stampready.net/dashboard/template= s/cuneo/thumbnails/1-1-content.jpg" data-module=3D"1-1-content" data-bgcolo= r=3D"Main BG" bgcolor=3D"#F9F9F9" align=3D"center" width=3D"100%" border=3D= "0" cellspacing=3D"0" cellpadding=3D"0" style=3D"background-color: rgb(255,= 255, 255);"> <tr> <td height=3D"25"></td> </tr> <tr> <td align=3D"center"> <table align=3D"center" width=3D"600" class=3D"table-inner" border= =3D"0" cellspacing=3D"0" cellpadding=3D"0"> <!--title--> <tr> <td data-link-style=3D"text-decoration:none; color:#4A4A4A;" da= ta-link-color=3D"Title" data-size=3D"Title" data-color=3D"Title" data-min= =3D"12" data-max=3D"36" align=3D"center" style=3D"font-family: "Centur= y Gothic", Arial, sans-serif; color: rgb(171, 7, 7); font-size: 30px; = font-weight: bold; letter-spacing: 1px;">LUTRON RadioRA LEVEL 1 TRAINING</t= d> </tr> <!--end title--> <tr> <td height=3D"20"></td> </tr> <!--dot--> <tr> <td align=3D"center"> <table border=3D"0" align=3D"center" cellpadding=3D"0" cellsp= acing=3D"0"> <tr> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" = style=3D"border-radius:10px;" bgcolor=3D"#FF6363"></td> <td width=3D"15"></td> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" = style=3D"border-radius:10px;" bgcolor=3D"#FF6363"></td> <td width=3D"15"></td> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" = style=3D"border-radius:10px;" bgcolor=3D"#FF6363"></td> </tr> </table> </td> </tr> <!--end dot--> <tr> <td height=3D"15"></td> </tr> <!--content--> <tr> <td data-link-style=3D"text-decoration:none; color:#FF6363;" da= ta-link-color=3D"Content" data-size=3D"Content" data-color=3D"Content" data= -min=3D"12" data-max=3D"22" align=3D"center" style=3D"font-family: "Op= en Sans", Arial, sans-serif; color: rgb(0, 0, 0); font-size: 15px; lin= e-height: 28px;"><b><span>KOA CCTV</span> is glad to announce Lutron Traini= ng Day <br> JUNE 30th 2016,  8:00AM To 4:00PM at NOHO location. </b><br> Everyone is expected to attend and take notes since the things learned shall be a huge help to=20 boost the productivity of your business. <br> <b>Training Day Special - 10% off on all Lutron Producs<br><i>F= ree Food & Drinks will be provided</i></b></td> </tr> <!--end content--> </table> </td> </tr> <tr> <td height=3D"25"></td> </tr> </table><table data-module=3D"header" data-bgcolor=3D"Main BG" bgcolor=3D= "#f8f8f8" width=3D"100%" align=3D"center" border=3D"0" cellspacing=3D"0" ce= llpadding=3D"0" style=3D"background-color: rgb(255, 255, 255);"> <tr> <td data-bg=3D"Header BG" data-bgcolor=3D"Header BG" data-border-bottom-= color=3D"Header Border" data-border-top-color=3D"Header Border" align=3D"ce= nter" background=3D"http://www.stampready.net/dashboard/editor/user_uploads= /image_uploads/2016/06/22/0Mm3jhPyKbZtNrqfs4DY291c68XTdGQl.jpg" bgcolor=3D"= #2A2A2A" style=3D"border-bottom-width: 3px; padding-top: 80px; border-botto= m-style: solid; border-bottom-color: rgb(255, 255, 255); border-top-width: = 3px; border-top-style: solid; border-top-color: rgb(255, 255, 255); backgro= und-image: url("http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/06/22/0Mm3jhPyKbZtNrqfs4DY291c68XTdGQl.jpg"); bac= kground-size: cover; background-position: center center;"> <table align=3D"center" width=3D"600" class=3D"table-inner" border=3D"0= " cellspacing=3D"0" cellpadding=3D"0"> <tr> <td> <table align=3D"left" width=3D"275" class=3D"table-full" border=3D"0= " cellspacing=3D"0" cellpadding=3D"0"> <tr> <td height=3D"40"> </td> </tr> <!--sub headline--> <tr> <td data-link-style=3D"text-decoration:none; color:#FFFFFF;" data-= link-color=3D"SubHeader" data-color=3D"SubHeader" data-size=3D"SubHeader" d= ata-min=3D"12" data-max=3D"22" align=3D"center" style=3D"font-family: 'Cent= ury gothic', Arial, sans-serif; color:#FFFFFF; font-size:13px; letter-spaci= ng:2px;"> <br><br><br><b>GET CERTIFIED</b></td> </tr> <!--end sub headline--> <tr> <td height=3D"10"> </td> </tr> <!--dot--> <tr> <td align=3D"center"> <table border=3D"0" align=3D"center" cellpadding=3D"0" cellspacin= g=3D"0"> <tr> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" style= =3D"border-radius:10px;" bgcolor=3D"#FF6363"> </td> <td width=3D"15"> </td> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" style= =3D"border-radius:10px;" bgcolor=3D"#FF6363"> </td> <td width=3D"15"> </td> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" style= =3D"border-radius:10px;" bgcolor=3D"#FF6363"> </td> </tr> </table> </td> </tr> <!--end dot--> <tr> <td height=3D"10"> </td> </tr> <!--headline--> <tr> <td data-link-style=3D"text-decoration:none; color:#FFFFFF;" data-= link-color=3D"Header" data-color=3D"Header" data-size=3D"Header" data-min= =3D"12" data-max=3D"36" align=3D"center" style=3D"font-family: 'Century got= hic', Arial, sans-serif; color:#ffffff; font-size:30px;letter-spacing: 1px;= font-weight: lighter;"> Register for<br><b>Lutron Training<br>CERTIFICATION</b></td> </tr> <!--end headline--> <tr> <td height=3D"20"> </td> </tr> <!--button--> <tr> <td align=3D"left"> <table data-bgcolor=3D"Button" data-border-bottom-color=3D"Button= Shadow" border=3D"0" align=3D"center" cellpadding=3D"0" cellspacing=3D"0" = bgcolor=3D"#FF6363" style=3D"border-radius: 5px; border-bottom-width: 2px; = border-bottom-style: solid; border-bottom-color: rgb(201, 43, 43); backgrou= nd-color: rgb(203, 11, 11);"> <tr> <td align=3D"center" style=3D"padding-left:15px;"> <img src=3D"http://www.stampready.net/dashboard/templates/cune= o/images/bt-check.png" width=3D"12" height=3D"10" alt=3D"img"> </td> <td data-link-style=3D"text-decoration:none; color:#ffffff;" da= ta-link-color=3D"Button Link" data-size=3D"Button" data-min=3D"12" data-max= =3D"22" height=3D"45" align=3D"center" style=3D"font-family:Century Gothic,= Arial, Sans-serif; font-size:16px; color:#ffffff;padding-left:15px;padding= -right:15px;"> <a href=3D"https://u2504343.ct.sendgrid.net/wf/click?upn=3D0vK= 3KXYTBabZQHrA6gI-2FtI8lzmFjeJGtmSQeYvFdllLLC84g-2F0WmzhAmNZe1FBgj_hfGZgfQXn= vNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4= YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72= cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX= 3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PIGrTeRzNCTfu6VSDmN= ug-2BrSyBgIGBxFTRY2xfMS2FCdlpeKYJS9rhr8U8gX6iUlTH4JpaA-2B6J4-2BdFGIS7pSdzoH= UpQ-2BoOKpaPq4A8MZupoJiav6o-2Fpm5X3sszshABcnBMqb5doq9LDBFmI98tSIjtE-3D" sty= le=3D"text-decoration:none; color:#ffffff" data-color=3D"Button Link">Regis= ter now</a> </td> </tr> </table><br><br><br><br> </td> </tr> <!--end button--> </table> <!--Space--> <table width=3D"1" border=3D"0" cellpadding=3D"0" cellspacing=3D"0" = align=3D"left"> <tr> <td style=3D"font-size: 0;line-height: 0px;border-collapse: collap= se;"> <p style=3D"padding-left: 24px;">   </p> </td> </tr> </table> <!--End Space--> <!--img--> <table class=3D"table-full" width=3D"262" border=3D"0" align=3D"righ= t" cellpadding=3D"0" cellspacing=3D"0"> <tr> <td align=3D"center" valign=3D"bottom" style=3D"line-height: 0px;"> <img data-crop=3D"false" src=3D"http://www.stampready.net/dashboa= rd/editor/user_uploads/image_uploads/2016/06/22/jg67zmsHqNS0R9MKrB51CYXZ2w8= 3Jhnp.png" alt=3D"img" class=3D"img1" style=3D"display:block;line-height:0p= x;font-size:0px;border:0px;padding-top: 88px;padding-left: 15px;"> </td> </tr> </table> <!--end img--> </td> </tr> </table> </td> </tr> <tr> <td height=3D"25"> </td> </tr> </table><table data-module=3D"headline" data-bgcolor=3D"Main BG" bgcolor= =3D"#F9F9F9" align=3D"center" width=3D"100%" border=3D"0" cellspacing=3D"0"= cellpadding=3D"0" style=3D"background-color: rgb(255, 255, 255);"> <tr> <td height=3D"25"> </td> </tr> <tr> <td align=3D"center"> <table align=3D"center" width=3D"600" class=3D"table-inner" border=3D"0= " cellspacing=3D"0" cellpadding=3D"0"> <!--SubHeader--> <tr> <td data-link-style=3D"text-decoration:none; color:#9B9B9B;" data-lin= k-color=3D"SubHeader" data-size=3D"SubHeader" data-color=3D"SubHeader" data= -min=3D"12" data-max=3D"28" align=3D"center" style=3D"font-family: 'Open Sa= ns', Arial, sans-serif; color:#9B9B9B; font-size:13px;letter-spacing: 2px;"> </td> </tr> <!--end SubHeader--> <tr> <td height=3D"10"> </td> </tr> <!--title--> <tr> <td data-link-style=3D"text-decoration:none; color:#4A4A4A;" data-lin= k-color=3D"Title" data-size=3D"Title" data-color=3D"Title" data-min=3D"12" = data-max=3D"36" align=3D"center" style=3D"font-family: Impact, Haettenschwe= iler, "Franklin Gothic Bold", "Arial Black", sans-serif= ; color: rgb(171, 7, 7); font-size: 30px; letter-spacing: 1px;"> New Line-up Products<br>CAT5e CAT6<br>RISER & PLENIUM LAN CABLES </td> </tr> <!--end title--> <tr> <td height=3D"20"> </td> </tr> <!--dot--> <tr> <td align=3D"center"> <table border=3D"0" align=3D"center" cellpadding=3D"0" cellspacing= =3D"0"> <tr> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" style=3D"= border-radius:10px;" bgcolor=3D"#FF6363"> </td> <td width=3D"15"> </td> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" style=3D"= border-radius:10px;" bgcolor=3D"#FF6363"> </td> <td width=3D"15"> </td> <td data-bgcolor=3D"Dotted" height=3D"5px" width=3D"5px" style=3D"= border-radius:10px;" bgcolor=3D"#FF6363"> </td> </tr> </table> </td> </tr> <!--end dot--> </table> </td> </tr> <tr> <td height=3D"25"> </td> </tr> </table><table data-thumb=3D"http://www.stampready.net/dashboard/templates= /cuneo/thumbnails/2-2-panel.jpg" data-module=3D"2-2-panel" data-bgcolor=3D"= Main BG" bgcolor=3D"#F9F9F9" align=3D"center" width=3D"100%" border=3D"0" c= ellspacing=3D"0" cellpadding=3D"0"> <tr> <td height=3D"25"></td> </tr> <tr> <td align=3D"center"> <table align=3D"center" class=3D"table-inner" width=3D"600" border= =3D"0" cellpadding=3D"0" cellspacing=3D"0"> <tr> <td> <!--left--> <table data-bgcolor=3D"Boxed" bgcolor=3D"#FFFFFF" style=3D"bo= rder-radius:5px; border:1px solid #F1F1F1; border-bottom:2px solid #ECEDF0;= " align=3D"left" width=3D"275" class=3D"table-full" border=3D"0" cellspacin= g=3D"0" cellpadding=3D"0"> <tr> <td height=3D"25"></td> </tr> <tr> <!--title--> <td align=3D"center"> <table width=3D"225" align=3D"center" class=3D"table-in= ner" border=3D"0" cellpadding=3D"0" cellspacing=3D"0"> <tr> <td data-link-style=3D"text-decoration:none; color:= #3b3b3b;" data-link-color=3D"Title" data-size=3D"Title" data-color=3D"Title= " min=3D"" data-min=3D"12" data-max=3D"28" align=3D"left" style=3D"font-fam= ily: "Open sans", Arial, sans-serif; color: rgb(171, 7, 7); font-= size: 18px; font-weight: bold; line-height: 28px; text-align: center;">Cat5= E Riser Lan Cable</td> </tr> </table> </td> </tr> <!--end title--> <tr> <td height=3D"15"></td> </tr> <!--img--> <tr> <td align=3D"center" style=3D"line-height: 0px;"><img dat= a-crop=3D"false" class=3D"img1" style=3D"display:block; line-height:0px; fo= nt-size:0px; border:0px;" src=3D"http://www.stampready.net/dashboard/editor= /user_uploads/image_uploads/2016/06/22/7Cgkl92tZrW8vnFXyH05JSTLcQpqfsRY.jpg= " alt=3D"img"></td> </tr> <!--end img--> <tr> <td height=3D"15"></td> </tr> <tr> <td align=3D"center"> <table align=3D"center" class=3D"table-inner" width=3D"= 225" border=3D"0" cellspacing=3D"0" cellpadding=3D"0"> <!--content--> <tr> <td data-link-style=3D"text-decoration:none; color:= #FF6363;" data-link-color=3D"Content" data-size=3D"Content" data-color=3D"C= ontent" data-min=3D"12" data-max=3D"22" align=3D"left" style=3D"font-family= : 'Open Sans', Arial, sans-serif; color:#9B9B9B; font-size:14px;font-weight= : normal;line-height: 28px;">24AWG 4 CORE UTP <br>1000FT 350MHZ <br>PULL BOX PACKAGE</td> </tr> <!--end content--> <tr> <td height=3D"15"></td> </tr> <!--button--> <tr> <td align=3D"left"> <table data-bgcolor=3D"Button" data-border-bottom= -color=3D"Button Shadow" bgcolor=3D"#FF6363" border=3D"0" align=3D"left" ce= llpadding=3D"0" cellspacing=3D"0" style=3D"border-radius: 5px; border-botto= m-width: 2px; border-bottom-style: solid; border-bottom-color: rgb(199, 71,= 71); background-color: rgb(203, 11, 11);"> <tr> <td data-link-style=3D"text-decoration:none; = color:#ffffff;" data-link-color=3D"Button Link" data-size=3D"Button" data-m= in=3D"12" data-max=3D"22" height=3D"40" align=3D"center" style=3D"font-fami= ly: 'Century gothic', Arial, sans-serif; color:#4A4A4A; font-size:14px; let= ter-spacing: 1px;padding-left: 15px;padding-right: 15px;"><a href=3D"https:= //u2504343.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2FtCGqna7fgNw= C8Pb4zUVqyk98IfhPMKLrMReVGUJmHTg5imR4c1X9NXbQJMjzMsSu2Q-3D-3D_hfGZgfQXnvNAO= QK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1= Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8= g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8= fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PCJY3oLWnHb7mizrPQ-2BcT= q7116silA5siPXweSctdyMgidteBeQc-2BWmWQteGAFaBb9-2FDZ4grxqO4LLy0thVB-2Fb8fc2= b-2B2I-2Bpj1qrmSvD5ovLR-2FiJ-2BXEEp9jA85atO0Gto1u0oBdON0E6hMIYwOL76f4-3D" s= tyle=3D"text-decoration:none; color:#ffffff" data-color=3D"Button Link">REA= D MORE</a></td> </tr> </table> </td> </tr> <!--end button--> </table> </td> </tr> <tr> <td height=3D"25"></td> </tr> </table> <!--end left--> <!--Space--> <table width=3D"1" border=3D"0" cellpadding=3D"0" cellspacing= =3D"0" align=3D"left"> <tr> <td height=3D"50" style=3D"font-size: 0;line-height: 0px;= border-collapse: collapse;"> <p style=3D"padding-left: 24px;"> </p> </td> </tr> </table> <!--End Space--> <!--right--> <table data-bgcolor=3D"Boxed" bgcolor=3D"#FFFFFF" style=3D"bo= rder-radius:5px; border:1px solid #F1F1F1; border-bottom:2px solid #ECEDF0;= " align=3D"right" width=3D"275" class=3D"table-full" border=3D"0" cellspaci= ng=3D"0" cellpadding=3D"0"> <tr> <td height=3D"25"></td> </tr> <tr> <!--title--> <td align=3D"center"> <table width=3D"225" align=3D"center" class=3D"table-in= ner" border=3D"0" cellpadding=3D"0" cellspacing=3D"0"> <tr> <td data-link-style=3D"text-decoration:none; color:= #3b3b3b;" data-link-color=3D"Title" data-size=3D"Title" data-color=3D"Title= " min=3D"" data-min=3D"12" data-max=3D"28" align=3D"left" style=3D"font-fam= ily: "Open sans", Arial, sans-serif; color: rgb(171, 7, 7); font-= size: 18px; font-weight: bold; line-height: 28px; text-align: center;">Cat6= Riser Lan Cable</td> </tr> </table> </td> </tr> <!--end title--> <tr> <td height=3D"15"></td> </tr> <!--img--> <tr> <td align=3D"center" style=3D"line-height: 0px;"><img dat= a-crop=3D"false" class=3D"img1" style=3D"display:block; line-height:0px; fo= nt-size:0px; border:0px;" src=3D"http://www.stampready.net/dashboard/editor= /user_uploads/image_uploads/2016/06/22/hkzpHgCd2QvyKjcZfMr54mYWX6RnF0NV.jpg= " alt=3D"img"></td> </tr> <!--end img--> <tr> <td height=3D"15"></td> </tr> <tr> <td align=3D"center"> <table align=3D"center" class=3D"table-inner" width=3D"= 225" border=3D"0" cellspacing=3D"0" cellpadding=3D"0"> <!--content--> <tr> <td data-link-style=3D"text-decoration:none; color:= #FF6363;" data-link-color=3D"Content" data-size=3D"Content" data-color=3D"C= ontent" data-min=3D"12" data-max=3D"22" align=3D"left" style=3D"font-family= : 'Open Sans', Arial, sans-serif; color:#9B9B9B; font-size:14px;font-weight= : normal;line-height: 28px;">23AWG 4 CORE UTP <br>1000FT 550MHZ <br>PULL BOX PACKAGE</td> </tr> <!--end content--> <tr> <td height=3D"15"></td> </tr> <!--button--> <tr> <td align=3D"left"> <table data-bgcolor=3D"Button" data-border-bottom= -color=3D"Button Shadow" bgcolor=3D"#FF6363" border=3D"0" align=3D"left" ce= llpadding=3D"0" cellspacing=3D"0" style=3D"border-radius: 5px; border-botto= m-width: 2px; border-bottom-style: solid; border-bottom-color: rgb(199, 71,= 71); background-color: rgb(203, 11, 11);"> <tr> <td data-link-style=3D"text-decoration:none; = color:#ffffff;" data-link-color=3D"Button Link" data-size=3D"Button" data-m= in=3D"12" data-max=3D"22" height=3D"40" align=3D"center" style=3D"font-fami= ly: 'Century gothic', Arial, sans-serif; color:#4A4A4A; font-size:14px; let= ter-spacing: 1px;padding-left: 15px;padding-right: 15px;"><a href=3D"https:= //u2504343.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2FtGfQOC1FIDL= -2FCMqTDYwGqKocjuFRj1pJPTLYqBfC6WPw_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabP= xkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idB= Eq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3= GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEK= k5jctGWiQbJAyzCY4fQG37H3Y5PFUMEnRRpteO7kpPFhmfJ3aJGdlK0cO6dZ7KVKoISvHSq37Bj= K9014Ezsy-2FNsEsrOOjNUQG7EwM2QN4BO04xb9hjyH7ARCN-2FS7SeAMgC2Wdd3ggbxr2wPArR= clNNIlcfu0O9UqoE0nyJCcV-2BDFfnQ1o-3D" style=3D"text-decoration:none; color:= #ffffff" data-color=3D"Button Link">READ MORE</a></td> </tr> </table> </td> </tr> <!--end button--> </table> </td> </tr> <tr> <td height=3D"25"></td> </tr> </table> <!--end right--> </td> </tr> </table> </td> </tr> <tr> <td height=3D"25"></td> </tr> </table><table data-thumb=3D"http://www.stampready.net/dashboard/template= s/cuneo/thumbnails/2-2-panel.jpg" data-module=3D"2-2-panel" data-bgcolor=3D= "Main BG" bgcolor=3D"#F9F9F9" align=3D"center" width=3D"100%" border=3D"0" = cellspacing=3D"0" cellpadding=3D"0"> <tr> <td height=3D"25"></td> </tr> <tr> <td align=3D"center"> <table align=3D"center" class=3D"table-inner" width=3D"600" border= =3D"0" cellpadding=3D"0" cellspacing=3D"0"> <tr> <td> <!--left--> <table data-bgcolor=3D"Boxed" bgcolor=3D"#FFFFFF" style=3D"bo= rder-radius:5px; border:1px solid #F1F1F1; border-bottom:2px solid #ECEDF0;= " align=3D"left" width=3D"275" class=3D"table-full" border=3D"0" cellspacin= g=3D"0" cellpadding=3D"0"> <tr> <td height=3D"25"></td> </tr> <tr> <!--title--> <td align=3D"center"> <table width=3D"225" align=3D"center" class=3D"table-in= ner" border=3D"0" cellpadding=3D"0" cellspacing=3D"0"> <tr> <td data-link-style=3D"text-decoration:none; color:= #3b3b3b;" data-link-color=3D"Title" data-size=3D"Title" data-color=3D"Title= " min=3D"" data-min=3D"12" data-max=3D"28" align=3D"left" style=3D"font-fam= ily: "Open sans", Arial, sans-serif; color: rgb(171, 7, 7); font-= size: 18px; font-weight: bold; line-height: 28px; text-align: center;">Cat5= E Plenium Lan Cable</td> </tr> </table> </td> </tr> <!--end title--> <tr> <td height=3D"15"></td> </tr> <!--img--> <tr> <td align=3D"center" style=3D"line-height: 0px;"><img dat= a-crop=3D"false" class=3D"img1" style=3D"display:block; line-height:0px; fo= nt-size:0px; border:0px;" src=3D"http://www.stampready.net/dashboard/editor= /user_uploads/image_uploads/2016/06/22/Lqd3RYlpxjzPFrVG78T51yXsZfWH0nh4.jpg= " alt=3D"img"></td> </tr> <!--end img--> <tr> <td height=3D"15"></td> </tr> <tr> <td align=3D"center"> <table align=3D"center" class=3D"table-inner" width=3D"= 225" border=3D"0" cellspacing=3D"0" cellpadding=3D"0"> <!--content--> <tr> <td data-link-style=3D"text-decoration:none; color:= #FF6363;" data-link-color=3D"Content" data-size=3D"Content" data-color=3D"C= ontent" data-min=3D"12" data-max=3D"22" align=3D"left" style=3D"font-family= : 'Open Sans', Arial, sans-serif; color:#9B9B9B; font-size:14px;font-weight= : normal;line-height: 28px;">24AWG 4 CORE UTP <br>1000FT 350MHZ <br>PULL BOX PACKAGE</td> </tr> <!--end content--> <tr> <td height=3D"15"></td> </tr> <!--button--> <tr> <td align=3D"left"> <table data-bgcolor=3D"Button" data-border-bottom= -color=3D"Button Shadow" bgcolor=3D"#FF6363" border=3D"0" align=3D"left" ce= llpadding=3D"0" cellspacing=3D"0" style=3D"border-radius: 5px; border-botto= m-width: 2px; border-bottom-style: solid; border-bottom-color: rgb(199, 71,= 71); background-color: rgb(203, 11, 11);"> <tr> <td data-link-style=3D"text-decoration:none; = color:#ffffff;" data-link-color=3D"Button Link" data-size=3D"Button" data-m= in=3D"12" data-max=3D"22" height=3D"40" align=3D"center" style=3D"font-fami= ly: 'Century gothic', Arial, sans-serif; color:#4A4A4A; font-size:14px; let= ter-spacing: 1px;padding-left: 15px;padding-right: 15px;"><a href=3D"https:= //u2504343.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2FtCGqna7fgNw= C8Pb4zUVqyk-2F2JP2tFNVd4hIlW5mQMoekKmW6BbGiBFkgOG0CPjcKtw-3D-3D_hfGZgfQXnvN= AOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4Yw= Z1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cG= F8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3n= f8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PJzab8Y36iU0XsfARi-2B= xosIeRQtGJztJ2nPBE7PoUYtRyfg5Rq9SuSPipmpnrBAIJ1WnGqyMwjtwOuSmMxKDKUfNAj-2FG= P4KkrFbzrq7sZJHyn0R8c5o6gA0QPXbn9SSz8NtaLjp04-2BAooRF5FwyWsCA-3D" style=3D"= text-decoration:none; color:#ffffff" data-color=3D"Button Link">READ MORE</= a></td> </tr> </table> </td> </tr> <!--end button--> </table> </td> </tr> <tr> <td height=3D"25"></td> </tr> </table> <!--end left--> <!--Space--> <table width=3D"1" border=3D"0" cellpadding=3D"0" cellspacing= =3D"0" align=3D"left"> <tr> <td height=3D"50" style=3D"font-size: 0;line-height: 0px;= border-collapse: collapse;"> <p style=3D"padding-left: 24px;"> </p> </td> </tr> </table> <!--End Space--> <!--right--> <table data-bgcolor=3D"Boxed" bgcolor=3D"#FFFFFF" style=3D"bo= rder-radius:5px; border:1px solid #F1F1F1; border-bottom:2px solid #ECEDF0;= " align=3D"right" width=3D"275" class=3D"table-full" border=3D"0" cellspaci= ng=3D"0" cellpadding=3D"0"> <tr> <td height=3D"25"></td> </tr> <tr> <!--title--> <td align=3D"center"> <table width=3D"225" align=3D"center" class=3D"table-in= ner" border=3D"0" cellpadding=3D"0" cellspacing=3D"0"> <tr> <td data-link-style=3D"text-decoration:none; color:= #3b3b3b;" data-link-color=3D"Title" data-size=3D"Title" data-color=3D"Title= " min=3D"" data-min=3D"12" data-max=3D"28" align=3D"left" style=3D"font-fam= ily: "Open sans", Arial, sans-serif; color: rgb(171, 7, 7); font-= size: 18px; font-weight: bold; line-height: 28px; text-align: center;">Cat6= Plenium Lan Cable</td> </tr> </table> </td> </tr> <!--end title--> <tr> <td height=3D"15"></td> </tr> <!--img--> <tr> <td align=3D"center" style=3D"line-height: 0px;"><img dat= a-crop=3D"false" class=3D"img1" style=3D"display:block; line-height:0px; fo= nt-size:0px; border:0px;" src=3D"http://www.stampready.net/dashboard/editor= /user_uploads/image_uploads/2016/06/22/xQrcBhYb6zHNgCw1GWdjPs8XfR5lD9vy.jpg= " alt=3D"img"></td> </tr> <!--end img--> <tr> <td height=3D"15"></td> </tr> <tr> <td align=3D"center"> <table align=3D"center" class=3D"table-inner" width=3D"= 225" border=3D"0" cellspacing=3D"0" cellpadding=3D"0"> <!--content--> <tr> <td data-link-style=3D"text-decoration:none; color:= #FF6363;" data-link-color=3D"Content" data-size=3D"Content" data-color=3D"C= ontent" data-min=3D"12" data-max=3D"22" align=3D"left" style=3D"font-family= : 'Open Sans', Arial, sans-serif; color:#9B9B9B; font-size:14px;font-weight= : normal;line-height: 28px;">23AWG 4 CORE UTP <br>1000FT 550MHZ <br>PULL BOX PACKAGE</td> </tr> <!--end content--> <tr> <td height=3D"15"></td> </tr> <!--button--> <tr> <td align=3D"left"> <table data-bgcolor=3D"Button" data-border-bottom= -color=3D"Button Shadow" bgcolor=3D"#FF6363" border=3D"0" align=3D"left" ce= llpadding=3D"0" cellspacing=3D"0" style=3D"border-radius: 5px; border-botto= m-width: 2px; border-bottom-style: solid; border-bottom-color: rgb(199, 71,= 71); background-color: rgb(203, 11, 11);"> <tr> <td data-link-style=3D"text-decoration:none; = color:#ffffff;" data-link-color=3D"Button Link" data-size=3D"Button" data-m= in=3D"12" data-max=3D"22" height=3D"40" align=3D"center" style=3D"font-fami= ly: 'Century gothic', Arial, sans-serif; color:#4A4A4A; font-size:14px; let= ter-spacing: 1px;padding-left: 15px;padding-right: 15px;"><a href=3D"https:= //u2504343.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2FtGfQOC1FIDL= -2FCMqTDYwGqKoj9ecQ1ShZEyPpHgnET6jlSPfAKMIuLiINUOT5VvJcRw-3D-3D_hfGZgfQXnvN= AOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4Yw= Z1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cG= F8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3n= f8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PLpPvjtCVZ2TMZlVEMRrF= heitSb5tL42BU-2F4-2Bv4sinlbGkVw47pnqzZglSMt9pn3juxbD6a-2FkAQoLZE4Yrx0AzxLzz= FXonJTrwUCLchnKHZBwmfXFD1Iec-2BsqmzeTh-2FvZe-2F65g7DZ1abUJm2BDLbdAo-3D" sty= le=3D"text-decoration:none; color:#ffffff" data-color=3D"Button Link">READ = MORE</a></td> </tr> </table> </td> </tr> <!--end button--> </table> </td> </tr> <tr> <td height=3D"25"></td> </tr> </table> <!--end right--> </td> </tr> </table> </td> </tr> <tr> <td height=3D"25"></td> </tr> </table> =09=09=09 =09=09 =09=09 =09=09=09 =09=09=09 =09=09 <table width=3D"100%" border=3D"0" cellspacing=3D"0" cellpadding=3D"0" ali= gn=3D"center" data-module=3D"layout-16" style=3D"position: relative; opacit= y: 1; z-index: 0;"> <!-- START LAYOUT-16 --> <tr> <td align=3D"center" valign=3D"top" class=3D"fix-box" style=3D"backgroun= d-color: rgb(255, 255, 255);" data-bgcolor=3D"all-bgcolor"> <!-- start container width 600px --> <table width=3D"100%" align=3D"center" border=3D"0" cellspacing=3D"0" c= ellpadding=3D"0" class=3D"container" style=3D"background-color: #ffffff; " = data-bgcolor=3D"layout-16"> <!--start space height --> <tr> <td height=3D"10"> </td> </tr> <!--end space height --> <tr> <td valign=3D"top"> <!-- start logo footer and address --> <table width=3D"100%" align=3D"center" border=3D"0" cellspacing=3D"0= " cellpadding=3D"0"> <tr> <td valign=3D"top"> <!--start icon socail navigation --> <table border=3D"0" align=3D"center" cellpadding=3D"0" cellspacin= g=3D"0" class=3D"container"> <tr> <td valign=3D"top" align=3D"left"> <table width=3D"100%" border=3D"0" align=3D"left" cellpadding= =3D"0" cellspacing=3D"0" class=3D"container"> <tr> <td height=3D"30" align=3D"center" valign=3D"middle" class= =3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/do/uploads/2015/09/01/103319= 4204img1.png" width=3D"90" alt=3D"icon-facebook" style=3D"max-width:90px;" = border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/qGDF0RmL5s9xZgVhfPn8rWw4yjKJNv67.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/do/uploads/2015/09/01/405343= 18img2.png" width=3D"90" alt=3D"icon-twitter" style=3D"max-width:90px;" bor= der=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/02/13/B4zVkhJGQKs93LgpXft82WOZbP7xDunU.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/02/13/EgaosxJjc5dyiVvAK9PTC0IOmR1qrwFB.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/02/13/TwJsWEGSn59NQt3BODmVAqhrpYz1dHPa.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/do/uploads/2015/09/01/112944= 598img3.png" width=3D"90" alt=3D"icon-googleplus" style=3D"max-width:90px;"= border=3D"0"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/06/01/mGbWfRp3KPqDrxJFXs5VQh8MjZT97gN0.png" width=3D"9= 0" alt=3D"icon-rss" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> </tr> </table> </td> </tr> </table> <!--end icon socail navigation --> </td> </tr> </table> <!-- end logo footer and address --> </td> </tr> <!--start space height --> <tr> <td height=3D"10"> </td> </tr> <!--end space height --> </table> </td> </tr> <!-- END LAYOUT-16--> </table><table width=3D"100%" border=3D"0" cellspacing=3D"0" cellpadding= =3D"0" align=3D"center" data-module=3D"layout-16"> <!-- START LAYOUT-16 --> <tr> <td align=3D"center" valign=3D"top" class=3D"fix-box" style=3D"backgroun= d-color: rgb(255, 255, 255);" data-bgcolor=3D"all-bgcolor"> <!-- start container width 600px --> <table width=3D"100%" align=3D"center" border=3D"0" cellspacing=3D"0" c= ellpadding=3D"0" class=3D"container" style=3D"background-color: #ffffff; " = data-bgcolor=3D"layout-16"> <!--start space height --> <tr> <td height=3D"10"> </td> </tr> <!--end space height --> <tr> <td valign=3D"top"> <!-- start logo footer and address --> <table width=3D"100%" align=3D"center" border=3D"0" cellspacing=3D"0= " cellpadding=3D"0"> <tr> <td valign=3D"top"> <!--start icon socail navigation --> <table border=3D"0" align=3D"center" cellpadding=3D"0" cellspacin= g=3D"0" class=3D"container"> <tr> <td valign=3D"top" align=3D"left"> <table width=3D"100%" border=3D"0" align=3D"left" cellpadding= =3D"0" cellspacing=3D"0" class=3D"container"> <tr> <td height=3D"30" align=3D"center" valign=3D"middle" class= =3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/do/uploads/2015/09/01/151940= 8065img4.png" width=3D"90" alt=3D"icon-facebook" style=3D"max-width:90px;" = border=3D"0"></a> </td> <td height=3D"30" align=3D"center" valign=3D"middle" class= =3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/Dfys3HGTxlCWv5JbFP9M4pq1gcXjtS2N.png" width=3D"9= 0" alt=3D"icon-facebook" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/Y45Q8XLj9s10kRxdyFt3pPlwvKZ2bBmN.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/J208HQ467RgF9jBMGtKvZb3xXDzTYSml.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/gy4FjxPw8lb3BLKTtMfRWZnVdrCkDNYX.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/XglM2jCfxkwLJ4v98rBsQctGTbn5ZmDd.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/yxl5TKsMJgD12rNjBHpwzFPZS4vfhY0k.png" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/K65fZLWrHTCm0DSGVltz2F1y7xpdNBYX.png" width=3D"9= 0" alt=3D"icon-googleplus" style=3D"max-width:90px;" border=3D"0"></a> </td> =09=09=09=09=09=09=09=09=09=09=09=09=09=09 <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> </tr> </table> </td> </tr> </table> <!--end icon socail navigation --> </td> </tr> </table> <!-- end logo footer and address --> </td> </tr> <!--start space height --> <tr> <td height=3D"10"> </td> </tr> <!--end space height --> </table> </td> </tr> <!-- END LAYOUT-16--> </table><table width=3D"100%" border=3D"0" cellspacing=3D"0" cellpadding= =3D"0" align=3D"center" data-module=3D"layout-16" style=3D"position: relati= ve; opacity: 1; z-index: 0;"> <!-- START LAYOUT-16 --> <tr> <td align=3D"center" valign=3D"top" class=3D"fix-box" style=3D"backgroun= d-color: rgb(255, 255, 255);" data-bgcolor=3D"all-bgcolor"> <!-- start container width 600px --> <table width=3D"100%" align=3D"center" border=3D"0" cellspacing=3D"0" c= ellpadding=3D"0" class=3D"container" style=3D"background-color: #ffffff; " = data-bgcolor=3D"layout-16"> <!--start space height --> <tr> <td height=3D"10"> </td> </tr> <!--end space height --> <tr> <td valign=3D"top"> <!-- start logo footer and address --> <table width=3D"100%" align=3D"center" border=3D"0" cellspacing=3D"0= " cellpadding=3D"0"> <tr> <td valign=3D"top"> <!--start icon socail navigation --> <table border=3D"0" align=3D"center" cellpadding=3D"0" cellspacin= g=3D"0" class=3D"container"> <tr> <td valign=3D"top" align=3D"left"> <a href=3D"#" style=3D"text-decoration: none;"></a> <table width=3D"100%" border=3D"0" align=3D"left" cellpadding= =3D"0" cellspacing=3D"0" class=3D"container"> <tr> <td style=3D"pad= ding-left:5px;" height=3D"30" align=3D"center" valign=3D"middle" class=3D"c= lear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/03/09/W5HgJvBNnDQCLmKXFVf0c6y2ptPx8j91.png" width=3D"9= 0" alt=3D"icon-rss" style=3D"max-width:90px;" border=3D"0"></a> </td> <td height=3D"30" align=3D"center" valign=3D"middle" class= =3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/06/01/C7nwPcLz0XWd25Jf3QrNZx46Slg19tKm.png" width=3D"9= 0" alt=3D"icon-facebook" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:15px; " height=3D"30" align=3D"cen= ter" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/06/01/txC6F7g9p3Mkwr5W4dj0QKLTlDVnyNmv.jpg" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:15px; " height=3D"30" align=3D"cen= ter" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/06/01/xpdFDVlYhsg46zTHyjSQLJBRG2wt807W.jpg" width=3D"9= 0" alt=3D"icon-twitter" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px; " height=3D"30" align=3D"cent= er" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/04/28/1Sd4fjsKYtGVqL0mhpP5nzxwT9b8Cc2v.png" width=3D"9= 0" alt=3D"icon-vimeo" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"><img data-c= rop=3D"false" src=3D"http://www.stampready.net/dashboard/editor/user_upload= s/image_uploads/2016/06/22/xKpWNJtzbrFVjh25dYSqGQZMDCn74fBH.png" width=3D"9= 0" alt=3D"icon-vimeo" style=3D"max-width:90px;" border=3D"0"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> <td style=3D"padding-left:5px;" height=3D"30" align=3D"cente= r" valign=3D"middle" class=3D"clear-padding"> <a href=3D"#" style=3D"text-decoration: none;"></a> </td> </tr> </table> </td> </tr> </table> <!--end icon socail navigation --> </td> </tr> </table> <!-- end logo footer and address --> </td> </tr> <!--start space height --> <tr> <td height=3D"10"> </td> </tr> <!--end space height --> </table> </td> </tr> <!-- END LAYOUT-16--> </table><table data-thumb=3D"http://www.stampready.net/dashboard/templates= /cuneo/thumbnails/footer.jpg" data-module=3D"footer" data-bgcolor=3D"Main B= G" align=3D"center" width=3D"100%" bgcolor=3D"#F8F8F8" border=3D"0" cellspa= cing=3D"0" cellpadding=3D"0" style=3D"position: relative; opacity: 1; z-ind= ex: 0; top: 0px; left: 0px; background-color: rgb(255, 255, 255);"> <tr> <td height=3D"25"></td> </tr> <tr> <td data-bgcolor=3D"Footer" bgcolor=3D"#4A4A4A" align=3D"center"> <table class=3D"table-inner" width=3D"600" border=3D"0" cellspacing= =3D"0" cellpadding=3D"0"> <tr> <td height=3D"40"></td> </tr> <tr> <td> <!--logo--> <table class=3D"table-full" border=3D"0" align=3D"left" cellp= adding=3D"0" cellspacing=3D"0"> <tr> <td align=3D"center" style=3D"line-height: 0px;"></td> </tr> </table> <!--end logo--> <!--Space--> <table class=3D"table-full" width=3D"1" border=3D"0" cellpadd= ing=3D"0" cellspacing=3D"0" align=3D"left"> <tr> <td height=3D"15" style=3D"font-size: 0;line-height: 0px;= border-collapse: collapse;"> <p style=3D"padding-left: 24px;"> </p> </td> </tr> </table> <!--End Space--> <!--footer link--> <table width=3D"0" border=3D"0" align=3D"right" cellpadding= =3D"0" cellspacing=3D"0" class=3D"table-full"> <tr> <td data-link-style=3D"text-decoration:none; color:#A9A9A= 9;" data-link-color=3D"Footer" data-size=3D"Footer" data-color=3D"Footer" d= ata-min=3D"12" data-max=3D"22" style=3D"font-family: "Century Gothic&q= uot;, Arial, sans-serif; color: rgb(255, 255, 255); font-size: 12px; font-w= eight: normal; letter-spacing: 1px;"><a href=3D"https://u2504343.ct.sendgri= d.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2FtHPnU6AormdJfgj4kVQnZoY-3D_hfGZg= fQXnvNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHa= AdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFD= QM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj2= 9WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PIsPN01IXDwMrog= 2I6DXC8FomlgizTxaLPB0ZkwRwiI4jIQKDUoMS1aUfwsP8z4AdQX9G0gcutcp9ye82bELjcuoH9= m-2F81PvWK6NyLTFQHVGTKPScPuTNRDGE8n7s8sFphSSU6tPHmsZF8pMfosR8T8-3D" style= =3D"color: rgb(255, 255, 255);">HOME</a> / <a href=3D"https://u25= 04343.ct.sendgrid.net/wf/click?upn=3D0vK3KXYTBabZQHrA6gI-2FtDHCVkT67-2B3VLO= pmF03i5oY-3D_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4py= RA2tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1A= a1XvUaG8nA095yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7X= pS1HbMmXC5SxFNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H= 3Y5PKGr-2BhzGPaAD2niNscc1-2FGEDm0ULYRHGwWfZUlP0JIgQPwDVFi-2BGEluTKLitebvW44= 61R4g-2Bue6ZVUykmuc0OfnjZ8KWAfezaB3M1FVgEobbZOLpzTSiAClALh-2F-2Fz3dWfcBFp13= rWFTBKEttkHbBuCc-3D" style=3D"text-decoration:none; color:#A9A9A9;" data-co= lor=3D"Footer">NEWS</a><span style=3D"color:#FFFFFF;padding-left:5px;paddin= g-right:8px;">/</span><a href=3D"https://u2504343.ct.sendgrid.net/wf/click?= upn=3D0vK3KXYTBabZQHrA6gI-2FtIDBewdj0aAmMI0lG3PTpcA-3D_hfGZgfQXnvNAOQK4XCkf= 0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4= svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2cIjoc= Q-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn3gN9= 1-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PL6F-2FI9rzi3CipyjskV6DUhdGrQf= 5r4qq3KQje0XeAzaIbK3TnEtVhY-2Fiy6Rmwnn37VyA-2BeoMFmBz4UCDqEO-2Fln0-2FoCqN2K= Y4ZKHdB1PD6mo3E44aaiLLW-2FMyqBtjgSoth-2BsWHufKuvBbH0rcF9hZOY-3D" style=3D"c= olor: rgb(255, 255, 255);">PRODUCTS</a> <span style=3D"color:#FFFFFF;paddin= g-left:5px;padding-right:8px;">/</span><a href=3D"https://u2504343.ct.sendg= rid.net/wf/click?upn=3DJu55RIkF1ZYjZsSuq-2BHlp3590ALJRWPIrEzF5qsEJLMIlAb6rU= NUBdnbU1ntSjiP2k1ule6oiR6iEi-2F4PSvRkQ-3D-3D_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZu= p1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8m= d-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2cIjocQ-2F3YtMXj= NCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn3gN91-2B4ru2-2= FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PGVtn45s3nLg8mmI2KTsuzpBs2zoKHlf0lCxNoG1= ofoV6ta4zP-2BlcUeZeBB0uiLnYI8LH9PaZteFpsepI7I7PIKR5EBP5iQc-2BT5Wi-2FgBdLbwi= TtF1iCiIJTbV8BUeTBOKuXGGu5ImaUpRkCKTlSXjpQ-3D" style=3D"color: rgb(255, 255= , 255);">WEBVERSION</a> <span style=3D"color:#FFFFFF;padding-left:5px;paddi= ng-right:8px;">/</span><a href=3D"https://u2504343.ct.sendgrid.net/wf/click= ?upn=3DJu55RIkF1ZYjZsSuq-2BHlp3590ALJRWPIrEzF5qsEJLN2o-2B2wUmpqDoMooykfgvjT= 3wnqi4js0Ia7k6Zjc0lR-2FTA4lULvGxc-2FzDIi9lP9SzIWcz028CpwLYTrmgDLEsBXE99Xbwz= iQm9PrInH7M1qEw-3D-3D_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgp= t8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PW= ASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xX= AFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyz= CY4fQG37H3Y5PI9OPOBKiPSQb8OLq7xhXLBMLG5qanlMmn1MNG-2ByJ12Vi6l2oGAF5uKpCb6Wz= P55IXxrEz-2B3Q4JBRkPf10YRrFvs-2BWk-2FINXyxZpr68snwNGwz1i2kO2piSOKdy2JFKkHwR= oU9LCbrzBskQNIGJgf1iE-3D" style=3D"color: rgb(255, 255, 255);">UNSUBSCRIBE<= /a></td> </tr> </table> <!--end footer link--> </td> </tr> <tr> <td height=3D"40"></td> </tr> </table> </td> </tr> <tr> <td data-bgcolor=3D"Copyright" bgcolor=3D"#545454"> <table align=3D"center" class=3D"table-inner" width=3D"600" border= =3D"0" cellspacing=3D"0" cellpadding=3D"0"> <tr> <td height=3D"15"></td> </tr> <tr> <td> <!--copyright--> <table width=3D"0" border=3D"0" align=3D"left" cellpadding=3D= "0" cellspacing=3D"0" class=3D"table-full"> <tr> <td data-link-style=3D"text-decoration:none; color:#FFFFF= F;" data-link-color=3D"Copyright" data-size=3D"Copyright" data-color=3D"Cop= yright" data-min=3D"12" data-max=3D"22" style=3D"font-family: 'Open Sans', = Arial, sans-serif; color:#FFFFFF; font-size:12px;">=C2=A9 Copyright 2016 Al= l rights reserved</td> </tr> </table> <!--end copyright--> <!--Space--> <table class=3D"table-full" width=3D"1" border=3D"0" cellpadd= ing=3D"0" cellspacing=3D"0" align=3D"left"> <tr> <td height=3D"15" style=3D"font-size: 0;line-height: 0px;= border-collapse: collapse;"> <p style=3D"padding-left: 24px;"> </p> </td> </tr> </table> <!--End Space--> <!--social--> <table align=3D"right" class=3D"table-full" border=3D"0" cell= spacing=3D"0" cellpadding=3D"0"> <tr> <td align=3D"center"> <table border=3D"0" align=3D"center" cellpadding=3D"0" = cellspacing=3D"0"> <tr> <td align=3D"center" style=3D"line-height: 0px;"><i= mg data-crop=3D"false" style=3D"display:block; line-height:0px; font-size:0= px; border:0px;" src=3D"http://www.stampready.net/dashboard/templates/cuneo= /images/fb.png" alt=3D"img"></td> <td width=3D"15"></td> <td align=3D"center" style=3D"line-height: 0px;"><i= mg data-crop=3D"false" style=3D"display:block; line-height:0px; font-size:0= px; border:0px;" src=3D"http://www.stampready.net/dashboard/templates/cuneo= /images/tw.png" alt=3D"img"></td> <td width=3D"15"></td> <td align=3D"center" style=3D"line-height: 0px;"><i= mg data-crop=3D"false" style=3D"display:block; line-height:0px; font-size:0= px; border:0px;" src=3D"http://www.stampready.net/dashboard/templates/cuneo= /images/gg.png" alt=3D"img"></td> </tr> </table> </td> </tr> </table> <!--end social--> </td> </tr> <tr> <td height=3D"15"></td> </tr> </table> </td> </tr> </table>=09=09=09=09 =09=09=09=09=09 =09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09 =09=09=09=09=09=09=09=09 =09=09=09=09=09 =09=09=09=09 <table height=3D"100%" width=3D"600" border=3D"0" cellspacing=3D"0" cel= lpadding=3D"0" align=3D"center" style=3D"font-family: Helvetica, Arial, san= s-serif; font-size: 13px; line-height: 23px!important color: #858585;" vali= gn=3D"top"><tbody><tr></tr><td height=3D"40"></td><tr><td valign=3D"top" si= g-output=3D"name" style=3D"line-height: 23px!important; height: 25px!import= ant;">KOACCTV</td></tr><tr><td valign=3D"top" sig-output=3D"street_address_= 1" style=3D"line-height: 23px!important; height: 25px!important;">7306 COLD= WATER CANYON AVE</td></tr><tr><td valign=3D"top" sig-output=3D"street_addre= ss_2" style=3D"line-height: 23px!important; height: 25px!important;">Unit 1= </td></tr><tr><td valign=3D"top" style=3D"line-height: 23px!important; heig= ht: 25px!important;"><span sig-output=3D"city">North Hollywood</span><span = sig-output=3D"state">, CA</span> <span sig-output=3D"zip_code">91605</span>= </td></tr><tr><td valign=3D"top" sig-output=3D"website" style=3D"line-heigh= t: 23px!important; height: 25px!important;"><a href=3D"https://u2504343.ct.= sendgrid.net/wf/click?upn=3DJu55RIkF1ZYjZsSuq-2BHlpzZ4EpIG5nqLoSQ0s6uGxgc-3= D_hfGZgfQXnvNAOQK4XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQ= J30lGHaAdE4YwZ1Q8QXHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA0= 95yoEFDQM72cGF8g2cIjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5S= xFNaLj29WqX3nf8fKn3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PMNPkOkl= y6SPO-2Fdfrb23ps4U8wJIZvM-2BEEsAiX7oZDh5FD0dBKjrQq7EbWTbJHB-2B1Lij1FYKpQfkG= fmxmYOc-2F-2F5A-2Fu5KGep9KRczucFUr-2Fz-2FNwRpV3TDW79HRhOok7sl69jm-2BHyuAnoq= uomQNo6DRC8-3D" style=3D"color: #343434;">http://www.koacctv.com</a></td></= tr><tr><td valign=3D"top" sig-output=3D"unsubscribe" style=3D"padding-top: = 20px; line-height: 23px!important; height: 25px!important;"><a href=3D"http= s://u2504343.ct.sendgrid.net/wf/click?upn=3DJu55RIkF1ZYjZsSuq-2BHlp3590ALJR= WPIrEzF5qsEJLN2o-2B2wUmpqDoMooykfgvjT3wnqi4js0Ia7k6Zjc0lR-2FTA4lULvGxc-2FzD= Ii9lP9SzIWcz028CpwLYTrmgDLEsBXE99XbwziQm9PrInH7M1qEw-3D-3D_hfGZgfQXnvNAOQK4= XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8Q= XHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2c= IjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn= 3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PMCP6Au011hkAje1aFXQcSVfgL= eI82stPngHI7XHCsV7owaz1Qpclw0qdI4dmcO9VzK2fW9jPXjZMpZkPkHQdWAh-2F1GH4HGK0QM= xHlG4Clxa2Zm14nX03xPR6UPrDcXdgjgl3HthkUyWL5Ka7gQObRU-3D" style=3D"color: #3= 43434; text-decoration: none;">Unsubscribe</a></td></tr><tr><td sig-output= =3D"referral" style=3D"padding-top: 20px; line-height: 23px!important; heig= ht: 25px!important;"></td></tr><tr><td height=3D"40"></td><tr></tbody></tab= le> <img src=3D"https://u2504343.ct.sendgrid.net/wf/open?upn=3DhfGZgfQXnvNAOQK4= XCkf0lCxP9ygZup1We0MabPxkbJsqxxM5gIgpt8anbL4pyRA2tUO-2FUQJ30lGHaAdE4YwZ1Q8Q= XHB4svBNVwWh8md-2Bc9idBEq-2B5y-2Bo8PWASbjhIi1Aa1XvUaG8nA095yoEFDQM72cGF8g2c= IjocQ-2F3YtMXjNCFnlxhq3GaNhjDFRpoQ5xXAFmRvAr7XpS1HbMmXC5SxFNaLj29WqX3nf8fKn= 3gN91-2B4ru2-2FpTvG9ZEKk5jctGWiQbJAyzCY4fQG37H3Y5PJNRb6ZHI1xmFQ6S7W0uZhIT7t= RoxJ-2FzveP59FKT-2BvTLtVBJ9q5bsIZ3-2BWAgs9x0dbBE8yF49QflYHUTEYUBZc6j4qEbQ4l= -2Bk6TxdR1MidMYS2zcxyl28hD-2Bj5B5CbHJijnre0fjZt9BswmhnhbwJ-2BmHQCLnsBINSzXC= DPsZ27ze" alt=3D"" width=3D"1" height=3D"1" border=3D"0" style=3D"height:1p= x !important;width:1px !important;border-width:0 !important;margin-top:0 !i= mportant;margin-bottom:0 !important;margin-right:0 !important;margin-left:0= !important;padding-top:0 !important;padding-bottom:0 !important;padding-ri= ght:0 !important;padding-left:0 !important;"/> </body></html> From david@fromorbit.com Wed Jun 22 20:42:25 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 356477CA1 for <xfs@oss.sgi.com>; Wed, 22 Jun 2016 20:42:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id E6832304032 for <xfs@oss.sgi.com>; Wed, 22 Jun 2016 18:42:24 -0700 (PDT) X-ASG-Debug-ID: 1466646140-04cbb02736ee190001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id HdXUCrCdcCoyEzuo for <xfs@oss.sgi.com>; Wed, 22 Jun 2016 18:42:21 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DdFwC/PWtXEJgMLHldgz6BU4J2g3meZgEBAQEBAQaMO4oPhhECAgEBAoEwTQEBAQEBAQcBAQEBAQEBAT5AhEwBAQEEJxMcIxAIAxUDCRoLDwUlAwcaE4gvxU0BAQEHAgEkHoVBgyaBb4l+HQWIDQeHFolTiQCFI48tj3yDD4FHKjKKJAEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 23 Jun 2016 11:12:19 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bFter-0004oh-NE; Thu, 23 Jun 2016 11:42:17 +1000 Date: Thu, 23 Jun 2016 11:42:17 +1000 From: Dave Chinner <david@fromorbit.com> To: Damien Gombault <damien.gombault@recia.fr> Cc: xfs@oss.sgi.com Subject: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed Message-ID: <20160623014217.GZ12670@dastard> X-ASG-Orig-Subj: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed References: <a08ae222-7654-4a6f-d9ba-f70017784f74@recia.fr> <20160622220959.GV12670@dastard> <20160622222328.GW12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622222328.GW12670@dastard> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466646140 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6881 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30677 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 23, 2016 at 08:23:28AM +1000, Dave Chinner wrote: > On Thu, Jun 23, 2016 at 08:09:59AM +1000, Dave Chinner wrote: > > But it seems that dirb hasn't been created before the file in it > > is being restored. THis can happen because the inventory is not > > correct, whichmay in fact be a problem with dump rather than > > restore... > > > > I'll have a bit of a play around here, see if I can reproduce it. > > Yes, i can reproduce it, so I'll have a deeper look. Can you try this patch? -Dave -- Dave Chinner david@fromorbit.com restore: make new directories after renames From: Dave Chinner <dchinner@redhat.com> Damien Gombault reported that restores of cumulative dumps with renamed directories were throwing an error and were incomplete: xfsrestore: file 0 in stream, file 0 in dump 0 on object xfsrestore: restoring dirA/dirb/fileb (526337 1283006502) xfsrestore: restoring regular file ino 526337 dirA/dirb/fileb xfsrestore: WARNING: open of dirA/dirb/fileb failed: Aucun fichier ou dossier de ce type: discarding ino 526337 This was triggered by a level 1 dump containing a directory rename and a new directory being created inside the renamed directory. i.e: $ mv dira dirA $ mkdir dirA/dirb $ echo foo > dirA/dirb/fileb xfs_restore handles directory renames by first moving the old directory to the orphanage, then renaming it from the orphanage to it's new location. This, in itself is fine. The problem is that restore creates the new directories between these two steps. Hence any new directory created in a renamed directory cannot be restored from a cumulative dump because when restore tries to create the new directory neither the old directory path nor the new directory path exists. Hence it silently drops the new directory, resulting in subsequent errors tryin gto restore files within that new directory. The simple fix - just change the order of operations in tree_post() so that new directories are created after all the renames are processed - is not useful. All that does is break the case of renames into newly created directories. However, because the making of directories that already exist or can't be made silently fails, and the create process does not modify the internal directory tree, we can run the directory creation function multiple times. Hence we can run directory creation both before and after the directory rename step, hence ensuring both new parents and new child directories are created appropriately. This still may not be sufficient for complex directory reorganisations, but it does address the reported problem in a manner that is unlikely to cause regresssions. This is important, because this code has not changed at all since it was first publicly released in early 2001. Hence the minimum change we can make to fix the reported problem is the least risky approach we can take. Signed-off-by: Dave Chinner <dchinner@redhat.com> --- restore/tree.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/restore/tree.c b/restore/tree.c index 0336e77..8e6fab1 100644 --- a/restore/tree.c +++ b/restore/tree.c @@ -1163,15 +1163,35 @@ tree_subtree_parse( bool_t sensepr, char *path ) return BOOL_TRUE; } -/* tree_post - called after the dirdump has been applied. - * first phase is to eliminate all unreferenced dirents. - * done by recursive depth-wise descent of the tree. on the way - * up, unlink or orphan unreferenced nondirs, unlink unreferenced - * dirs, orphan dirs to be renamed. if a dir is unreferenced, but +/* tree_post - called after the dirdump has been applied. first phase is to + * eliminate all unreferenced dirents. done by recursive depth-wise descent of + * the tree. on the way up, unlink or orphan unreferenced nondirs, unlink + * unreferenced dirs, orphan dirs to be renamed. if a dir is unreferenced, but * contains referenced dirents, orphan those dirents. orphan unreferenced * nondirs if they are the last link to an inode referenced but not real * somewhere else in the tree. next, make new directories. then rename * directories. finally, create hardlinks from orphanage. + * + * Note: the way renamed directories are handled by first orphaning them leads + * to a chicken and egg problem - the directory does not exist when we try to + * make a new directory inside the renamed directory destination. This fails + * silently, leaving us with ENOENT errors when trying to restore files within + * that new directory. + * + * To prevent this from happening, we need to create new subdirectories *after* + * we have processed all the renamed directories. However, so that the renames + * succeed, we also have to create any new parent directories that the renames + * depend on. + * + * Hence we have to do two mkdir passes: one before the renames to create new + * ancestors for rename destinations and one after the rename to create new + * children in rename destinations. + * + * NOTE: a simple before/after creation as done below may be too simple for + * complex directory structure manipulations. e.g. rename into a new child in + * the destination of another rename. This may have to become an iterative loop + * that runs until all renames and mkdirs are resolved. We'll cross that bridge + * when we need to, not now. */ static bool_t noref_elim_recurse( nh_t parh, nh_t cldh, @@ -1216,7 +1236,14 @@ tree_post( char *path1, char *path2 ) } } - /* make new directories +#ifdef TREE_CHK + assert( tree_chk( )); +#endif /* TREE_CHK */ + + /* + * make new directories to ensure rename destination ancestors are + * present before attempting the renames. This will silently skip all + * the creations that are in rename destinations. */ mlog( MLOG_DEBUG | MLOG_TREE, "making new directories\n" ); @@ -1228,10 +1255,6 @@ tree_post( char *path1, char *path2 ) return BOOL_FALSE; } -#ifdef TREE_CHK - assert( tree_chk( )); -#endif /* TREE_CHK */ - /* rename directories */ if ( ! persp->p_fullpr ) { @@ -1250,6 +1273,24 @@ tree_post( char *path1, char *path2 ) assert( tree_chk( )); #endif /* TREE_CHK */ + /* + * Repeat making new directories to create directories in rename + * destinations that were skipped in the first pass. + */ + mlog( MLOG_DEBUG | MLOG_TREE, + "making new directories in renamed ancestors\n" ); + rootp = Node_map( persp->p_rooth ); + cldh = rootp->n_cldh; + Node_unmap( persp->p_rooth, &rootp ); + ok = mkdirs_recurse( persp->p_rooth, cldh, path1 ); + if ( ! ok ) { + return BOOL_FALSE; + } + +#ifdef TREE_CHK + assert( tree_chk( )); +#endif /* TREE_CHK */ + /* process hard links */ if ( ! persp->p_fullpr ) { From houtao1@huawei.com Wed Jun 22 22:17:32 2016 Return-Path: <houtao1@huawei.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D3A787CA1 for <xfs@oss.sgi.com>; Wed, 22 Jun 2016 22:17:32 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 982EB8F8037 for <xfs@oss.sgi.com>; Wed, 22 Jun 2016 20:17:29 -0700 (PDT) X-ASG-Debug-ID: 1466651843-04cbb02737f2bd0001-NocioJ Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [119.145.14.65]) by cuda.sgi.com with ESMTP id Q3qXb05W3yoOpxs2 (version=TLSv1 cipher=RC4-SHA bits=128 verify=NO) for <xfs@oss.sgi.com>; Wed, 22 Jun 2016 20:17:26 -0700 (PDT) X-Barracuda-Envelope-From: houtao1@huawei.com X-Barracuda-Effective-Source-IP: szxga02-in.huawei.com[119.145.14.65] X-Barracuda-Apparent-Source-IP: 119.145.14.65 Received: from 172.24.1.137 (EHLO szxeml433-hub.china.huawei.com) ([172.24.1.137]) by szxrg02-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DJF07425; Thu, 23 Jun 2016 11:16:29 +0800 (CST) Received: from huawei.com (10.175.124.28) by szxeml433-hub.china.huawei.com (10.82.67.210) with Microsoft SMTP Server id 14.3.235.1; Thu, 23 Jun 2016 11:16:23 +0800 From: Hou Tao <houtao1@huawei.com> To: <xfs@oss.sgi.com> CC: <david@fromorbit.com> Subject: [PATCH] xfs: remove the magic numbers in xfs_btree_block-related len macros Date: Thu, 23 Jun 2016 11:10:20 +0800 X-ASG-Orig-Subj: [PATCH] xfs: remove the magic numbers in xfs_btree_block-related len macros Message-ID: <1466651420-126472-1-git-send-email-houtao1@huawei.com> X-Mailer: git-send-email 2.5.5 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.175.124.28] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020206.576B548F.00FB,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 6707775c8dc98455f9eb530030c38f13 X-Barracuda-Connect: szxga02-in.huawei.com[119.145.14.65] X-Barracuda-Start-Time: 1466651846 X-Barracuda-Encrypted: RC4-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3557 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30679 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- replace the magic numbers by offsetof(...) and sizeof(...), and add two extra checks on xfs_check_ondisk_structs() Signed-off-by: Hou Tao <houtao1@huawei.com> --- fs/xfs/libxfs/xfs_format.h | 66 ++++++++++++++++++++++++++++------------------ fs/xfs/xfs_ondisk.h | 2 ++ 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index dc97eb21..d3069be 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1435,41 +1435,57 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; * with the crc feature bit, and all accesses to them must be conditional on * that flag. */ +/* short form block */ +struct xfs_btree_sblock_part { + __be32 bb_leftsib; + __be32 bb_rightsib; + + __be64 bb_blkno; + __be64 bb_lsn; + uuid_t bb_uuid; + __be32 bb_owner; + __le32 bb_crc; +}; + +/* long form block */ +struct xfs_btree_lblock_part { + __be64 bb_leftsib; + __be64 bb_rightsib; + + __be64 bb_blkno; + __be64 bb_lsn; + uuid_t bb_uuid; + __be64 bb_owner; + __le32 bb_crc; + __be32 bb_pad; /* padding for alignment */ +}; + struct xfs_btree_block { __be32 bb_magic; /* magic number for block type */ __be16 bb_level; /* 0 is a leaf */ __be16 bb_numrecs; /* current # of data records */ union { - struct { - __be32 bb_leftsib; - __be32 bb_rightsib; - - __be64 bb_blkno; - __be64 bb_lsn; - uuid_t bb_uuid; - __be32 bb_owner; - __le32 bb_crc; - } s; /* short form pointers */ - struct { - __be64 bb_leftsib; - __be64 bb_rightsib; - - __be64 bb_blkno; - __be64 bb_lsn; - uuid_t bb_uuid; - __be64 bb_owner; - __le32 bb_crc; - __be32 bb_pad; /* padding for alignment */ - } l; /* long form pointers */ + struct xfs_btree_sblock_part s; + struct xfs_btree_lblock_part l; } bb_u; /* rest */ }; -#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */ -#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */ +/* size of a short form block */ +#define XFS_BTREE_SBLOCK_LEN \ + (offsetof(struct xfs_btree_block, bb_u) + \ + offsetof(struct xfs_btree_sblock_part, bb_blkno)) +/* size of a long form block */ +#define XFS_BTREE_LBLOCK_LEN \ + (offsetof(struct xfs_btree_block, bb_u) + \ + offsetof(struct xfs_btree_lblock_part, bb_blkno)) /* sizes of CRC enabled btree blocks */ -#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40) -#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48) +#define XFS_BTREE_SBLOCK_CRC_LEN \ + (offsetof(struct xfs_btree_block, bb_u) + \ + sizeof(struct xfs_btree_sblock_part)) +#define XFS_BTREE_LBLOCK_CRC_LEN \ + (offsetof(struct xfs_btree_block, bb_u) + \ + sizeof(struct xfs_btree_lblock_part)) #define XFS_BTREE_SBLOCK_CRC_OFF \ offsetof(struct xfs_btree_block, bb_u.s.bb_crc) diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 184c44e..6f06c48 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -34,6 +34,8 @@ xfs_check_ondisk_structs(void) XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_key, 8); XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_rec, 16); XFS_CHECK_STRUCT_SIZE(struct xfs_bmdr_block, 4); + XFS_CHECK_STRUCT_SIZE(struct xfs_btree_sblock_part, 48); + XFS_CHECK_STRUCT_SIZE(struct xfs_btree_lblock_part, 64); XFS_CHECK_STRUCT_SIZE(struct xfs_btree_block, 72); XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176); XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104); -- 2.5.5 From cmaiolino@redhat.com Thu Jun 23 05:21:46 2016 Return-Path: <cmaiolino@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id E694D7CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 05:21:46 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id B9861304032 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 03:21:43 -0700 (PDT) X-ASG-Debug-ID: 1466677301-04cb6c063d104630001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 8EeH5KEwRT8Hu4qk (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 03:21:42 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8FEF67305C; Thu, 23 Jun 2016 10:21:41 +0000 (UTC) Received: from redhat.com (unused [10.10.50.65] (may be forged)) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5NALcIZ014106 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 23 Jun 2016 06:21:40 -0400 Date: Thu, 23 Jun 2016 12:21:37 +0200 From: Carlos Maiolino <cmaiolino@redhat.com> To: Hou Tao <houtao1@huawei.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs: remove the magic numbers in xfs_btree_block-related len macros Message-ID: <20160623102137.GH27894@redhat.com> X-ASG-Orig-Subj: Re: [PATCH] xfs: remove the magic numbers in xfs_btree_block-related len macros Mail-Followup-To: Hou Tao <houtao1@huawei.com>, xfs@oss.sgi.com References: <1466651420-126472-1-git-send-email-houtao1@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466651420-126472-1-git-send-email-houtao1@huawei.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 23 Jun 2016 10:21:41 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466677302 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4224 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 23, 2016 at 11:10:20AM +0800, Hou Tao wrote: > replace the magic numbers by offsetof(...) and sizeof(...), and add two > extra checks on xfs_check_ondisk_structs() > > Signed-off-by: Hou Tao <houtao1@huawei.com> > --- > fs/xfs/libxfs/xfs_format.h | 66 ++++++++++++++++++++++++++++------------------ > fs/xfs/xfs_ondisk.h | 2 ++ > 2 files changed, 43 insertions(+), 25 deletions(-) > Particularly I liked the idea of defining the short and long block structures outside of xfs_btree_block and removing magic numbers is a good thing too. you can consider it Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> > diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h > index dc97eb21..d3069be 100644 > --- a/fs/xfs/libxfs/xfs_format.h > +++ b/fs/xfs/libxfs/xfs_format.h > @@ -1435,41 +1435,57 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; > * with the crc feature bit, and all accesses to them must be conditional on > * that flag. > */ > +/* short form block */ > +struct xfs_btree_sblock_part { > + __be32 bb_leftsib; > + __be32 bb_rightsib; > + > + __be64 bb_blkno; > + __be64 bb_lsn; > + uuid_t bb_uuid; > + __be32 bb_owner; > + __le32 bb_crc; > +}; > + > +/* long form block */ > +struct xfs_btree_lblock_part { > + __be64 bb_leftsib; > + __be64 bb_rightsib; > + > + __be64 bb_blkno; > + __be64 bb_lsn; > + uuid_t bb_uuid; > + __be64 bb_owner; > + __le32 bb_crc; > + __be32 bb_pad; /* padding for alignment */ > +}; > + > struct xfs_btree_block { > __be32 bb_magic; /* magic number for block type */ > __be16 bb_level; /* 0 is a leaf */ > __be16 bb_numrecs; /* current # of data records */ > union { > - struct { > - __be32 bb_leftsib; > - __be32 bb_rightsib; > - > - __be64 bb_blkno; > - __be64 bb_lsn; > - uuid_t bb_uuid; > - __be32 bb_owner; > - __le32 bb_crc; > - } s; /* short form pointers */ > - struct { > - __be64 bb_leftsib; > - __be64 bb_rightsib; > - > - __be64 bb_blkno; > - __be64 bb_lsn; > - uuid_t bb_uuid; > - __be64 bb_owner; > - __le32 bb_crc; > - __be32 bb_pad; /* padding for alignment */ > - } l; /* long form pointers */ > + struct xfs_btree_sblock_part s; > + struct xfs_btree_lblock_part l; > } bb_u; /* rest */ > }; > > -#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */ > -#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */ > +/* size of a short form block */ > +#define XFS_BTREE_SBLOCK_LEN \ > + (offsetof(struct xfs_btree_block, bb_u) + \ > + offsetof(struct xfs_btree_sblock_part, bb_blkno)) > +/* size of a long form block */ > +#define XFS_BTREE_LBLOCK_LEN \ > + (offsetof(struct xfs_btree_block, bb_u) + \ > + offsetof(struct xfs_btree_lblock_part, bb_blkno)) > > /* sizes of CRC enabled btree blocks */ > -#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40) > -#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48) > +#define XFS_BTREE_SBLOCK_CRC_LEN \ > + (offsetof(struct xfs_btree_block, bb_u) + \ > + sizeof(struct xfs_btree_sblock_part)) > +#define XFS_BTREE_LBLOCK_CRC_LEN \ > + (offsetof(struct xfs_btree_block, bb_u) + \ > + sizeof(struct xfs_btree_lblock_part)) > > #define XFS_BTREE_SBLOCK_CRC_OFF \ > offsetof(struct xfs_btree_block, bb_u.s.bb_crc) > diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h > index 184c44e..6f06c48 100644 > --- a/fs/xfs/xfs_ondisk.h > +++ b/fs/xfs/xfs_ondisk.h > @@ -34,6 +34,8 @@ xfs_check_ondisk_structs(void) > XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_key, 8); > XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_rec, 16); > XFS_CHECK_STRUCT_SIZE(struct xfs_bmdr_block, 4); > + XFS_CHECK_STRUCT_SIZE(struct xfs_btree_sblock_part, 48); > + XFS_CHECK_STRUCT_SIZE(struct xfs_btree_lblock_part, 64); > XFS_CHECK_STRUCT_SIZE(struct xfs_btree_block, 72); > XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176); > XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104); > -- > 2.5.5 > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From mstsxfx@gmail.com Thu Jun 23 06:35:24 2016 Return-Path: <mstsxfx@gmail.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AEA187CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 06:35:24 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8165A8F8033 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 04:35:21 -0700 (PDT) X-ASG-Debug-ID: 1466681718-04cbb0273510c110001-NocioJ Received: from mail-wm0-f45.google.com (mail-wm0-f45.google.com [74.125.82.45]) by cuda.sgi.com with ESMTP id uVYBG4NEpJhBBYtt (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 04:35:19 -0700 (PDT) X-Barracuda-Envelope-From: mstsxfx@gmail.com X-Barracuda-Effective-Source-IP: mail-wm0-f45.google.com[74.125.82.45] X-Barracuda-Apparent-Source-IP: 74.125.82.45 Received: by mail-wm0-f45.google.com with SMTP id a66so45718561wme.0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 04:35:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=udd6qFQB+u8ChcMMg202RpLcYPq9N+sj5oA+lhVzsYE=; b=ji1YFDcRWqewc6qe20pmFwPQzfyCJwb+APO3iTu276MCStznIwkxMvpdpBYJWL7Tyw wgoWQKGedRXHioAl6ig4DoxGAH8zj7NeKtU2+xFFxCKKpdQFn8TFwIT/uSWNovgvRycD SxQ35zI41GT+z5BK/n1kFi7iEY4L2voA2i8/OrFZ2vijFQS6swKlNoYJ5b6nb3LA3+wp keuL6ovVN4Pc4Z5PTNO+dmTzfMsEquVmutbAA66OV/yWU+BGHbTpmSngE8hUwrcRfRnG 0LpBSO0/6JU6c7sbh86ntDLXFwTCh2MGcGhRSUEZ6xAQRIsbw/CEViCHuZpyXFHnVeIt ZFuA== X-Gm-Message-State: ALyK8tKEeDdzQHYLkZ88FhS7uFhs6L5R2lhjRWNfxALYIPk3vDseokDUoNXv8csGvKk5tQ== X-Received: by 10.194.104.196 with SMTP id gg4mr32963669wjb.112.1466681718042; Thu, 23 Jun 2016 04:35:18 -0700 (PDT) Received: from localhost ([80.188.202.66]) by smtp.gmail.com with ESMTPSA id zb9sm3952113wjc.34.2016.06.23.04.35.16 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 Jun 2016 04:35:17 -0700 (PDT) Date: Thu, 23 Jun 2016 13:35:16 +0200 From: Michal Hocko <mhocko@kernel.org> To: Peter Zijlstra <peterz@infradead.org>, Dave Chinner <david@fromorbit.com> Cc: "Darrick J. Wong" <darrick.wong@oracle.com>, Qu Wenruo <quwenruo@cn.fujitsu.com>, xfs@oss.sgi.com, linux-mm@kvack.org, Ingo Molnar <mingo@kernel.org> Subject: Re: Xfs lockdep warning with for-dave-for-4.6 branch Message-ID: <20160623113516.GG30077@dhcp22.suse.cz> X-ASG-Orig-Subj: Re: Xfs lockdep warning with for-dave-for-4.6 branch References: <20160602145048.GS1995@dhcp22.suse.cz> <20160602151116.GD3190@twins.programming.kicks-ass.net> <20160602154619.GU1995@dhcp22.suse.cz> <20160602232254.GR12670@dastard> <20160606122022.GH11895@dhcp22.suse.cz> <20160615072154.GF26977@dastard> <20160621142628.GG30848@dhcp22.suse.cz> <20160622010320.GR12670@dastard> <20160622123822.GG9208@dhcp22.suse.cz> <20160622225816.GY12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622225816.GY12670@dastard> User-Agent: Mutt/1.6.0 (2016-04-01) X-Barracuda-Connect: mail-wm0-f45.google.com[74.125.82.45] X-Barracuda-Start-Time: 1466681719 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2259 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30687 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu 23-06-16 08:58:16, Dave Chinner wrote: > On Wed, Jun 22, 2016 at 02:38:22PM +0200, Michal Hocko wrote: > > On Wed 22-06-16 11:03:20, Dave Chinner wrote: > > > On Tue, Jun 21, 2016 at 04:26:28PM +0200, Michal Hocko wrote: > > > > On Wed 15-06-16 17:21:54, Dave Chinner wrote: > > [...] > > > > > There are allocations outside transaction context which need to be > > > > > GFP_NOFS - this is what KM_NOFS was originally intended for. > > > > > > > > Is it feasible to mark those by the scope NOFS api as well and drop > > > > the direct KM_NOFS usage? This should help to identify those that are > > > > lockdep only and use the annotation to prevent from the false positives. > > > > > > I don't understand what you are suggesting here. This all started > > > because we use GFP_NOFS in a handful of places to shut up lockdep > > > and you didn't want us to use GFP_NOFS like that. Now it sounds to > > > me like you are advocating setting unconditional GFP_NOFS allocation > > > contexts for entire XFS code paths - whether it's necessary or > > > not - to avoid problems with lockdep false positives. > > > > No, I meant only those paths which need GFP_NOFS for other than lockdep > > purposes would use the scope api. > > > > Anyway, it seems that we are not getting closer to a desired solution > > here. Or I am not following it at least... > > > > It seems that we have effectively two possibilities (from the > > MM/lockdep) POV. Either add an explicit API to disable the reclaim > > lockdep machinery for all allocation in a certain scope or a GFP mask > > to to achieve the same for a particular allocation. Which one would work > > better for the xfs usecase? > > As I've said - if we annotate the XFS call sites appropriately (e.g. > KM_NOLOCKDEP rather than KM_NOFS), we don't care what lockdep > mechanism is used to turn off warnings as it will be wholly > encapsulated inside kmem_alloc() and friends. This will end up > similar to how we are currently encapsulate the memalloc_noio_save() > wrappers in kmem_zalloc_large(). OK, I see. So which way do we go Peter? Are you going to send the GFP one or is there a way to bribe you to go with a thread flag? -- Michal Hocko SUSE Labs From slghu@slgthomas.hu Thu Jun 23 06:40:41 2016 Return-Path: <slghu@slgthomas.hu> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FSL_MISSP_REPLYTO,T_HK_NAME_DR autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C005B7CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 06:40:41 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 849338F8039 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 04:40:41 -0700 (PDT) X-ASG-Debug-ID: 1466682038-04cb6c063f109530001-NocioJ Received: from ns1.powered-hosting.com (ns1.powered-hosting.com [69.162.109.218]) by cuda.sgi.com with ESMTP id 8MOEZosFXkZw4Eqt for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 04:40:38 -0700 (PDT) X-Barracuda-Envelope-From: slghu@slgthomas.hu X-Barracuda-Effective-Source-IP: ns1.powered-hosting.com[69.162.109.218] X-Barracuda-Apparent-Source-IP: 69.162.109.218 Received: from [106.196.171.145] ([106.196.171.145]) (authenticated bits=0) by ns1.powered-hosting.com (8.14.5/8.14.5) with ESMTP id u5NB79Zi000845; Thu, 23 Jun 2016 08:07:54 -0300 Message-Id: <201606231107.u5NB79Zi000845@ns1.powered-hosting.com> Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body Subject: Supply Deal! To: Recipients <slghu@slgthomas.hu> X-ASG-Orig-Subj: Supply Deal! From: "Dr.Peter Nuwman"<slghu@slgthomas.hu> Date: Thu, 23 Jun 2016 17:10:12 +0530 Reply-To: info_nuwmanp@beniger.com X-Antivirus/AntiSpam-MailScanner-Information: Please contact the ISP for more information X-Antivirus/AntiSpam-MailScanner-ID: u5NB79Zi000845 X-Antivirus/AntiSpam-MailScanner: Not scanned: please contact your Internet E-Mail Service Provider for details X-Antivirus/AntiSpam-MailScanner-From: slghu@slgthomas.hu X-Barracuda-Connect: ns1.powered-hosting.com[69.162.109.218] X-Barracuda-Start-Time: 1466682038 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 0 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.50 X-Barracuda-Spam-Status: No, SCORE=0.50 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_ADDR_MATCH X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30687 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.50 BSF_SC0_SA_TO_FROM_ADDR_MATCH Sender Address Matches Recipient Address Respected Sir/Madam, I work with a production Pharmaceutical raw materials based in USA. I am = seeking the immediate assistance of a reliable and trustworthy partner in Asia, India Precisely profitable for our mutual benefit in a supply deal. If you agree to work with me, kindly Indicate your interest for more details regards Dr.Peter Nuwman From billodo@redhat.com Thu Jun 23 09:17:54 2016 Return-Path: <billodo@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9A3F97CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 09:17:54 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 67B528F8035 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 07:17:54 -0700 (PDT) X-ASG-Debug-ID: 1466691472-04cbb02735118ab0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id XRx1s5hqTAqKHVWN (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 07:17:53 -0700 (PDT) X-Barracuda-Envelope-From: billodo@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 22D9263163; Thu, 23 Jun 2016 14:17:52 +0000 (UTC) Received: from redhat.com (vpn-49-102.rdu2.redhat.com [10.10.49.102]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5NEHn5X007343 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 23 Jun 2016 10:17:51 -0400 Date: Thu, 23 Jun 2016 09:17:49 -0500 From: "Bill O'Donnell" <billodo@redhat.com> To: Dave Chinner <david@fromorbit.com> Cc: Damien Gombault <damien.gombault@recia.fr>, xfs@oss.sgi.com Subject: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed Message-ID: <20160623141749.GA25075@redhat.com> X-ASG-Orig-Subj: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed References: <a08ae222-7654-4a6f-d9ba-f70017784f74@recia.fr> <20160622220959.GV12670@dastard> <20160622222328.GW12670@dastard> <20160623014217.GZ12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160623014217.GZ12670@dastard> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 23 Jun 2016 14:17:52 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466691473 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7520 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 23, 2016 at 11:42:17AM +1000, Dave Chinner wrote: > On Thu, Jun 23, 2016 at 08:23:28AM +1000, Dave Chinner wrote: > > On Thu, Jun 23, 2016 at 08:09:59AM +1000, Dave Chinner wrote: > > > But it seems that dirb hasn't been created before the file in it > > > is being restored. THis can happen because the inventory is not > > > correct, whichmay in fact be a problem with dump rather than > > > restore... > > > > > > I'll have a bit of a play around here, see if I can reproduce it. > > > > Yes, i can reproduce it, so I'll have a deeper look. > > Can you try this patch? FWIW, I tried it on a RHEL7 box and it works fine with Damien's test case. Thanks- Bill > > -Dave > -- > Dave Chinner > david@fromorbit.com > > restore: make new directories after renames > > From: Dave Chinner <dchinner@redhat.com> > > Damien Gombault reported that restores of cumulative dumps with > renamed directories were throwing an error and were incomplete: > > xfsrestore: file 0 in stream, file 0 in dump 0 on object > xfsrestore: restoring dirA/dirb/fileb (526337 1283006502) > xfsrestore: restoring regular file ino 526337 dirA/dirb/fileb > xfsrestore: WARNING: open of dirA/dirb/fileb failed: Aucun fichier ou dossier de > ce type: discarding ino 526337 > > This was triggered by a level 1 dump containing a directory rename > and a new directory being created inside the renamed directory. i.e: > > $ mv dira dirA > $ mkdir dirA/dirb > $ echo foo > dirA/dirb/fileb > > xfs_restore handles directory renames by first moving the old > directory to the orphanage, then renaming it from the orphanage to > it's new location. This, in itself is fine. > > The problem is that restore creates the new directories between > these two steps. Hence any new directory created in a renamed > directory cannot be restored from a cumulative dump because when > restore tries to create the new directory neither the old directory > path nor the new directory path exists. Hence it silently drops the > new directory, resulting in subsequent errors tryin gto restore > files within that new directory. > > The simple fix - just change the order of operations > in tree_post() so that new directories are created after all the > renames are processed - is not useful. All that does is break the > case of renames into newly created directories. > > However, because the making of directories that already exist or > can't be made silently fails, and the create process does not modify > the internal directory tree, we can run the directory creation > function multiple times. Hence we can run directory creation both > before and after the directory rename step, hence ensuring both > new parents and new child directories are created appropriately. > > This still may not be sufficient for complex directory > reorganisations, but it does address the reported problem in a > manner that is unlikely to cause regresssions. This is important, > because this code has not changed at all since it was first publicly > released in early 2001. Hence the minimum change we can make to fix > the reported problem is the least risky approach we can take. > > Signed-off-by: Dave Chinner <dchinner@redhat.com> > --- > restore/tree.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++---------- > 1 file changed, 51 insertions(+), 10 deletions(-) > > diff --git a/restore/tree.c b/restore/tree.c > index 0336e77..8e6fab1 100644 > --- a/restore/tree.c > +++ b/restore/tree.c > @@ -1163,15 +1163,35 @@ tree_subtree_parse( bool_t sensepr, char *path ) > return BOOL_TRUE; > } > > -/* tree_post - called after the dirdump has been applied. > - * first phase is to eliminate all unreferenced dirents. > - * done by recursive depth-wise descent of the tree. on the way > - * up, unlink or orphan unreferenced nondirs, unlink unreferenced > - * dirs, orphan dirs to be renamed. if a dir is unreferenced, but > +/* tree_post - called after the dirdump has been applied. first phase is to > + * eliminate all unreferenced dirents. done by recursive depth-wise descent of > + * the tree. on the way up, unlink or orphan unreferenced nondirs, unlink > + * unreferenced dirs, orphan dirs to be renamed. if a dir is unreferenced, but > * contains referenced dirents, orphan those dirents. orphan unreferenced > * nondirs if they are the last link to an inode referenced but not real > * somewhere else in the tree. next, make new directories. then rename > * directories. finally, create hardlinks from orphanage. > + * > + * Note: the way renamed directories are handled by first orphaning them leads > + * to a chicken and egg problem - the directory does not exist when we try to > + * make a new directory inside the renamed directory destination. This fails > + * silently, leaving us with ENOENT errors when trying to restore files within > + * that new directory. > + * > + * To prevent this from happening, we need to create new subdirectories *after* > + * we have processed all the renamed directories. However, so that the renames > + * succeed, we also have to create any new parent directories that the renames > + * depend on. > + * > + * Hence we have to do two mkdir passes: one before the renames to create new > + * ancestors for rename destinations and one after the rename to create new > + * children in rename destinations. > + * > + * NOTE: a simple before/after creation as done below may be too simple for > + * complex directory structure manipulations. e.g. rename into a new child in > + * the destination of another rename. This may have to become an iterative loop > + * that runs until all renames and mkdirs are resolved. We'll cross that bridge > + * when we need to, not now. > */ > static bool_t noref_elim_recurse( nh_t parh, > nh_t cldh, > @@ -1216,7 +1236,14 @@ tree_post( char *path1, char *path2 ) > } > } > > - /* make new directories > +#ifdef TREE_CHK > + assert( tree_chk( )); > +#endif /* TREE_CHK */ > + > + /* > + * make new directories to ensure rename destination ancestors are > + * present before attempting the renames. This will silently skip all > + * the creations that are in rename destinations. > */ > mlog( MLOG_DEBUG | MLOG_TREE, > "making new directories\n" ); > @@ -1228,10 +1255,6 @@ tree_post( char *path1, char *path2 ) > return BOOL_FALSE; > } > > -#ifdef TREE_CHK > - assert( tree_chk( )); > -#endif /* TREE_CHK */ > - > /* rename directories > */ > if ( ! persp->p_fullpr ) { > @@ -1250,6 +1273,24 @@ tree_post( char *path1, char *path2 ) > assert( tree_chk( )); > #endif /* TREE_CHK */ > > + /* > + * Repeat making new directories to create directories in rename > + * destinations that were skipped in the first pass. > + */ > + mlog( MLOG_DEBUG | MLOG_TREE, > + "making new directories in renamed ancestors\n" ); > + rootp = Node_map( persp->p_rooth ); > + cldh = rootp->n_cldh; > + Node_unmap( persp->p_rooth, &rootp ); > + ok = mkdirs_recurse( persp->p_rooth, cldh, path1 ); > + if ( ! ok ) { > + return BOOL_FALSE; > + } > + > +#ifdef TREE_CHK > + assert( tree_chk( )); > +#endif /* TREE_CHK */ > + > /* process hard links > */ > if ( ! persp->p_fullpr ) { > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From boaz@plexistor.com Thu Jun 23 09:22:51 2016 Return-Path: <boaz@plexistor.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 00D037CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 09:22:51 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id BAACC304032 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 07:22:47 -0700 (PDT) X-ASG-Debug-ID: 1466691763-04cbb02738119040001-NocioJ Received: from mail-wm0-f47.google.com (mail-wm0-f47.google.com [74.125.82.47]) by cuda.sgi.com with ESMTP id GYpXWz1fxGkE5Sai (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 07:22:44 -0700 (PDT) X-Barracuda-Envelope-From: boaz@plexistor.com X-Barracuda-Effective-Source-IP: mail-wm0-f47.google.com[74.125.82.47] X-Barracuda-Apparent-Source-IP: 74.125.82.47 Received: by mail-wm0-f47.google.com with SMTP id 187so4091534wmz.1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 07:22:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=plexistor-com.20150623.gappssmtp.com; s=20150623; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-transfer-encoding; bh=pM8Rxcs2v/vBWSRsudXUDwkk8WadGtF7T132FX267IY=; b=dSb1VemiIyZ0Zp0kLe0IoHqfrA87ykNs9V9ip6J2JnoO0nXGGFMucuMNpqHD+Gx8Bm k3A3qIYqAF09wuiyHBozZfGp6B6cCZPDOjtvityHHS7+nUnIAjlm1ThY1d0dS/m8rVkB wS8F96SHdEI8jDRqT1PR80RufexRsSJf1qPpsw6OyzMEVZsXfH0nmPUcIZv0a8qJrqh4 ZmHW8nvKzkgkzc5LJYovaeQhDJeyNY9Bd0q/K4RaVc14iliTpeb6GQI+HRA3GoQ6ZRjX bvyoYYWeKSxfw1AWqACZf9T0bfx88WhyaCXmJnVl5w6i+YMGREcN+5AB7kAgBsiJaz4g 53GA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-transfer-encoding; bh=pM8Rxcs2v/vBWSRsudXUDwkk8WadGtF7T132FX267IY=; b=T0EbpNqDpzJuuX8CZJaY8krMjNg8qzuEzsySMM4CFxG+k8sK5mPJA84CeEb9WltY9l yxir/jKrN/dsirkz5ONOR8/6zA4J8+tJ60n3A+VHCF9PZcdh9ermbMcK0c/enHgc0HfA 2tqDjj4zKFMN65i5XFbJr2A2XVgInVb5A6e5g+rE8JBd3rgD2UpivTr3LFXrILBt9iJV kQqDCkNdws9kIvxrwHYJDdzyg3xYShYf63eDg1RqXBZZ5SXJMebPzi/57gZH/HXkZtXd E27URSH4DFrsh8RIxrqHJyfZY0aD3WNBGpkGYqb69AfmBlAqof62S1KqZ0Ce/avNaGCj zeRw== X-Gm-Message-State: ALyK8tKaiyGPme4OVuJCCYQl5Bz0ShMaTCXMwCjXO90Kq2h+UnGz2B74J6rELPPcyZ9cIg== X-Received: by 10.194.235.4 with SMTP id ui4mr32206254wjc.23.1466691762782; Thu, 23 Jun 2016 07:22:42 -0700 (PDT) Received: from [10.0.0.5] ([207.232.55.62]) by smtp.googlemail.com with ESMTPSA id kd7sm376360wjc.33.2016.06.23.07.22.41 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 23 Jun 2016 07:22:42 -0700 (PDT) Message-ID: <576BF0B0.5080904@plexistor.com> Date: Thu, 23 Jun 2016 17:22:40 +0300 From: Boaz Harrosh <boaz@plexistor.com> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Christoph Hellwig <hch@lst.de>, xfs@oss.sgi.com CC: linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: [PATCH 8/8] xfs: fix locking for DAX writes References: <1466609236-23801-1-git-send-email-hch@lst.de> <1466609236-23801-9-git-send-email-hch@lst.de> X-ASG-Orig-Subj: Re: [PATCH 8/8] xfs: fix locking for DAX writes In-Reply-To: <1466609236-23801-9-git-send-email-hch@lst.de> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f47.google.com[74.125.82.47] X-Barracuda-Start-Time: 1466691764 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3969 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30690 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/22/2016 06:27 PM, Christoph Hellwig wrote: > So far DAX writes inherited the locking from direct I/O writes, but the direct > I/O model of using shared locks for writes is actually wrong for DAX. For > direct I/O we're out of any standards and don't have to provide the Posix > required exclusion between writers, but for DAX which gets transparently > enable on applications without any knowledge of it we can't simply drop the > requirement. Even worse this only happens for aligned writes and thus > doesn't show up for many typical use cases. > Hi Sir Christoph You raise a very interesting point and I would please like to ask questions. Is this a theoretical standards problem or a real applications problem that you know of? You say above: " Posix required exclusion between writers" As I understand, what it means is that if two threads/processes A & B write to the same offset-length, in parallel. then a consistent full version will hold of either A or B, which ever comes last. But never a torn version of both. Is this really POSIX. I mean I knew POSIX is silly but so much so? What about NFS CEPH Luster and all these network shared stuff. Does POSIX say "On a single Node?". (Trond been yelling about file locks for *any* kind of synchronization for years.) And even with the write-lock to serialize writers (Or i_mute in case of ext4) I do not see how this serialization works, because in a cached environment a write_back can start and crash while the second thread above starts his memcopy and on disk we still get a torn version of the record that was half from A half from B. (Or maybe I do not understand what your automicity means) Is not a rant I would really like to know what application uses this "single-writer" facility and how does it actually works for them? I honestly don't see how it works. (And do they really check that they are only working on a local file system?) Sorry for my slowness please explain? BTW: I think that all the patches except this one makes a lot of sense because of all the hidden quirks of direct_IO code paths. Just for example the difference between "aligned and none align writes" as you mentioned above. My $0.017: Who In the real world would actually break without this patch, which is not already broken? And why sacrifice the vast majority of good applications for the sake of an already broken (theoretical?) applications. Thank you Boaz > Signed-off-by: Christoph Hellwig <hch@lst.de> > --- > fs/xfs/xfs_file.c | 20 +------------------- > 1 file changed, 1 insertion(+), 19 deletions(-) > > diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c > index 0e74325..413c9e0 100644 > --- a/fs/xfs/xfs_file.c > +++ b/fs/xfs/xfs_file.c > @@ -714,24 +714,11 @@ xfs_file_dax_write( > struct address_space *mapping = iocb->ki_filp->f_mapping; > struct inode *inode = mapping->host; > struct xfs_inode *ip = XFS_I(inode); > - struct xfs_mount *mp = ip->i_mount; > ssize_t ret = 0; > - int unaligned_io = 0; > - int iolock; > + int iolock = XFS_IOLOCK_EXCL; > struct iov_iter data; > > - /* "unaligned" here means not aligned to a filesystem block */ > - if ((iocb->ki_pos & mp->m_blockmask) || > - ((iocb->ki_pos + iov_iter_count(from)) & mp->m_blockmask)) { > - unaligned_io = 1; > - iolock = XFS_IOLOCK_EXCL; > - } else if (mapping->nrpages) { > - iolock = XFS_IOLOCK_EXCL; > - } else { > - iolock = XFS_IOLOCK_SHARED; > - } > xfs_rw_ilock(ip, iolock); > - > ret = xfs_file_aio_write_checks(iocb, from, &iolock); > if (ret) > goto out; > @@ -747,11 +734,6 @@ xfs_file_dax_write( > WARN_ON_ONCE(ret); > } > > - if (iolock == XFS_IOLOCK_EXCL && !unaligned_io) { > - xfs_rw_ilock_demote(ip, XFS_IOLOCK_EXCL); > - iolock = XFS_IOLOCK_SHARED; > - } > - > trace_xfs_file_dax_write(ip, iov_iter_count(from), iocb->ki_pos); > > data = *from; > From danny@zadarastorage.com Thu Jun 23 10:04:55 2016 Return-Path: <danny@zadarastorage.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C818B7CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 10:04:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 956CD304039 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 08:04:52 -0700 (PDT) X-ASG-Debug-ID: 1466694288-04cbb02737123b10001-NocioJ Received: from mail-lf0-f50.google.com (mail-lf0-f50.google.com [209.85.215.50]) by cuda.sgi.com with ESMTP id uwxKlHV6ndzzYL6y (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 08:04:49 -0700 (PDT) X-Barracuda-Envelope-From: danny@zadarastorage.com X-Barracuda-Effective-Source-IP: mail-lf0-f50.google.com[209.85.215.50] X-Barracuda-Apparent-Source-IP: 209.85.215.50 Received: by mail-lf0-f50.google.com with SMTP id f6so97418525lfg.0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 08:04:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zadarastorage-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=J0iPNra+g/vlKC5Ju1gxzbCRQbimekiMl2u6Xd5oCTM=; b=AoCp/mFLccsdmfwVC1clPEVndBW5cyMCs+VnHsRGVOybcXGKyYd7RYdmHPYOn/aADu L9fT+1WUOUJSExHYTHXdhI2vVnGNY3+zkBPRXvm+ltmUViMCr2Xa7k44qph0LW/3b2dg HtRQ3fdwck0rQ5d0yB4Y/wf0ZjXmKO8zs84qNu6s9TFcIkEwmxDxCOlHxG9qJsIQfSDZ dH/Pn12YiQr45lPBg/rRXW00Tvf630HlyvSKQCCYuqoS/lI7/jZ4nFqoq4TJrJonh61C OwC6yZpresOXnFBynMbDhRc9HaJSgRPvRFPzcQqViQCZNVDUXplU3GWWDXfx0ngUS5RM XxCw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=J0iPNra+g/vlKC5Ju1gxzbCRQbimekiMl2u6Xd5oCTM=; b=gQMxqZ3oVh3g6z53pJSmifZrsKl+PWMAO9U9eHBPLSkEewZHV9WoAvZR3q5bUC+s/B ubLKSYJmj7sHq2JiNlsM8UT0Norg2ktQuQuWeCkafypoXg7pcy5ENO6xYrN5TdzqNpYR /phB2crOwkxUfilmW679sgQyrCHlNI4zmGnEtbi6TpYYsXRbIgiFQx4Iiw9ED3DltBYJ UjQ7r8XMUZoqihHlOyFrdvEn3jFO5AIZuMGX1ytBn1nfKxSFt/frhcCBZSGbm/8xDR2J aqtdIRGk0kB+K47Z5PWAFvOjsUuVqwASqC1kzB4UPm3nOjSSrttpNgk2J0fRvtxf8fIq Z57Q== X-Gm-Message-State: ALyK8tIRI/4XGUnDCWzOHIJd58owIR04X3EHcgvJOeExevMTsvNaRjlnQ+O0PoPQX2iyzvRjkjN0RU8yMa7ywA== X-Received: by 10.25.2.195 with SMTP id 186mr12325010lfc.36.1466694287598; Thu, 23 Jun 2016 08:04:47 -0700 (PDT) MIME-Version: 1.0 Received: by 10.114.5.37 with HTTP; Thu, 23 Jun 2016 08:04:46 -0700 (PDT) In-Reply-To: <20160622225117.GX12670@dastard> References: <CAC=x_0jDYb17Vh97Led7XXDiUMcUTJbpJ2Dw45gn=D0_w0K5VQ@mail.gmail.com> <20160622225117.GX12670@dastard> From: Danny Shavit <danny@zadarastorage.com> Date: Thu, 23 Jun 2016 18:04:46 +0300 Message-ID: <CAC=x_0hdvm7SSP8EOAdUwLa-k3a3p7p7CRj8tyCnEx=As7A6jw@mail.gmail.com> Subject: Re: xfs metadata overhead To: Dave Chinner <david@fromorbit.com> X-ASG-Orig-Subj: Re: xfs metadata overhead Cc: xfs@oss.sgi.com Content-Type: multipart/alternative; boundary=001a113ca60601c33b0535f3605e X-Barracuda-Connect: mail-lf0-f50.google.com[209.85.215.50] X-Barracuda-Start-Time: 1466694289 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3203 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30692 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --001a113ca60601c33b0535f3605e Content-Type: text/plain; charset=UTF-8 I see. We will try this direction. BTW: I thought that good estimate would be "volume_size - allocated_size - free_space". But it produced quite a difference compared to metadata dump size. Is there a specific reason? Thanks, Danny On Thu, Jun 23, 2016 at 1:51 AM, Dave Chinner <david@fromorbit.com> wrote: > On Wed, Jun 22, 2016 at 06:58:16PM +0300, Danny Shavit wrote: > > Hi, > > > > We are looking for a method to estimate the size of metadata overhead > for a > > given file system. > > We would like to use this value as indicator for the amount of cache > memory > > a system for faster operation. > > Are there any counters that are maintained in the on-disk data > > structures like free space for examples? > > No. > > Right now, you'll need to take a metadump of the filesystem to > measure it. The size of the dump file will be a close indication of > the amount of metadata in the filesystem as it only contains > the filesystem metadata. > > In future, querying the rmap will enable us to calculate it on the > fly, (i.e. not requiring the filesystem to be snapshotted/taken off > line to do a metadump). > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com > -- Regards, Danny --001a113ca60601c33b0535f3605e Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr"><div>I see. We will try this direction.</div><div>BTW: I t= hought that good estimate would be "volume_size - allocated_size - fre= e_space". But it produced quite a difference compared to metadata dump= size.</div><div>Is there a specific reason?</div><div><br></div><div>Thank= s,</div><div>Danny</div></div><div class=3D"gmail_extra"><br><div class=3D"= gmail_quote">On Thu, Jun 23, 2016 at 1:51 AM, Dave Chinner <span dir=3D"ltr= "><<a href=3D"mailto:david@fromorbit.com" target=3D"_blank">david@fromor= bit.com</a>></span> wrote:<br><blockquote class=3D"gmail_quote" style=3D= "margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class= =3D"">On Wed, Jun 22, 2016 at 06:58:16PM +0300, Danny Shavit wrote:<br> > Hi,<br> ><br> > We are looking for a method to estimate the size of metadata overhead = for a<br> > given file system.<br> > We would like to use this value as indicator for the amount of cache m= emory<br> > a system for faster operation.<br> > Are there any counters that are maintained in the on-disk data<br> > structures like free space for examples?<br> <br> </span>No.<br> <br> Right now, you'll need to take a metadump of the filesystem to<br> measure it. The size of the dump file will be a close indication of<br> the amount of metadata in the filesystem as it only contains<br> the filesystem metadata.<br> <br> In future, querying the rmap will enable us to calculate it on the<br> fly, (i.e. not requiring the filesystem to be snapshotted/taken off<br> line to do a metadump).<br> <br> Cheers,<br> <br> Dave.<br> <span class=3D"HOEnZb"><font color=3D"#888888">--<br> Dave Chinner<br> <a href=3D"mailto:david@fromorbit.com">david@fromorbit.com</a><br> </font></span></blockquote></div><br><br clear=3D"all"><div><br></div>-- <b= r><div class=3D"gmail_signature" data-smartmail=3D"gmail_signature"><div di= r=3D"ltr"><div>Regards,<br></div>Danny<br></div></div> </div> --001a113ca60601c33b0535f3605e-- From billodo@redhat.com Thu Jun 23 12:07:16 2016 Return-Path: <billodo@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9484C7CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 12:07:16 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 6759C8F8033 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 10:07:13 -0700 (PDT) X-ASG-Debug-ID: 1466701631-04cb6c063f1163c0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id S7DXQ5NHI5gcMIS2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 10:07:12 -0700 (PDT) X-Barracuda-Envelope-From: billodo@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A60DB3F745 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 17:07:11 +0000 (UTC) Received: from localhost.localdomain.com (vpn-49-102.rdu2.redhat.com [10.10.49.102]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5NH7Blk024982 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 13:07:11 -0400 From: "Bill O'Donnell" <billodo@redhat.com> To: xfs@oss.sgi.com Subject: [PATCH] xfs_repair: resolve Coverity OVERFLOW_BEFORE_WIDEN Date: Thu, 23 Jun 2016 12:07:10 -0500 X-ASG-Orig-Subj: [PATCH] xfs_repair: resolve Coverity OVERFLOW_BEFORE_WIDEN Message-Id: <1466701630-6380-1-git-send-email-billodo@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 23 Jun 2016 17:07:11 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466701632 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 874 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Coverity complains that when multiplying two 32 bit values that eventually will be stored in a 64 bit value that it's possible the math could overflow unless one of the values being multiplied is type cast to the proper size. Signed-off-by: Bill O'Donnell <billodo@redhat.com> --- repair/sb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/repair/sb.c b/repair/sb.c index 3965953..8d4843c 100644 --- a/repair/sb.c +++ b/repair/sb.c @@ -230,7 +230,7 @@ find_secondary_sb(xfs_sb_t *rsb) do_warn(_("\nattempting to find secondary superblock...\n")); if (verify_sb_blocksize(rsb) == 0) { - skip = rsb->sb_agblocks * rsb->sb_blocksize; + skip = (__uint64_t)rsb->sb_agblocks * rsb->sb_blocksize; if (skip >= XFS_AG_MIN_BYTES && skip <= XFS_AG_MAX_BYTES) retval = __find_secondary_sb(rsb, skip, skip); } -- 2.7.4 From bfoster@redhat.com Thu Jun 23 12:20:16 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 4FC407CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 12:20:16 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0FC628F8033 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 10:20:16 -0700 (PDT) X-ASG-Debug-ID: 1466702390-04bdf074b5218b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id dQCbYPYCjgz2zkQB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 10:19:50 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5B7ADC0799BB; Thu, 23 Jun 2016 17:19:50 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-2.bos.redhat.com [10.18.41.2]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5NHJnWt016988; Thu, 23 Jun 2016 13:19:50 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 755071201DB; Thu, 23 Jun 2016 13:19:48 -0400 (EDT) Date: Thu, 23 Jun 2016 13:19:48 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 015/119] xfs: refactor btree owner change into a separate visit-blocks function Message-ID: <20160623171947.GA40109@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 015/119] xfs: refactor btree owner change into a separate visit-blocks function References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612636805.12839.15108503251791000478.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612636805.12839.15108503251791000478.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 23 Jun 2016 17:19:50 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466702390 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6859 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:28PM -0700, Darrick J. Wong wrote: > Refactor the btree_change_owner function into a more generic apparatus > which visits all blocks in a btree. We'll use this in a subsequent > patch for counting btree blocks for AG reservations. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- Reviewed-by: Brian Foster <bfoster@redhat.com> > fs/xfs/libxfs/xfs_btree.c | 141 +++++++++++++++++++++++++++++---------------- > fs/xfs/libxfs/xfs_btree.h | 5 ++ > 2 files changed, 96 insertions(+), 50 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 5f5cf23..eac876a 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -4289,6 +4289,81 @@ xfs_btree_get_rec( > return 0; > } > > +/* Visit a block in a btree. */ > +STATIC int > +xfs_btree_visit_block( > + struct xfs_btree_cur *cur, > + int level, > + xfs_btree_visit_blocks_fn fn, > + void *data) > +{ > + struct xfs_btree_block *block; > + struct xfs_buf *bp; > + union xfs_btree_ptr rptr; > + int error; > + > + /* do right sibling readahead */ > + xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); > + block = xfs_btree_get_block(cur, level, &bp); > + > + /* process the block */ > + error = fn(cur, level, data); > + if (error) > + return error; > + > + /* now read rh sibling block for next iteration */ > + xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); > + if (xfs_btree_ptr_is_null(cur, &rptr)) > + return -ENOENT; > + > + return xfs_btree_lookup_get_block(cur, level, &rptr, &block); > +} > + > + > +/* Visit every block in a btree. */ > +int > +xfs_btree_visit_blocks( > + struct xfs_btree_cur *cur, > + xfs_btree_visit_blocks_fn fn, > + void *data) > +{ > + union xfs_btree_ptr lptr; > + int level; > + struct xfs_btree_block *block = NULL; > + int error = 0; > + > + cur->bc_ops->init_ptr_from_cur(cur, &lptr); > + > + /* for each level */ > + for (level = cur->bc_nlevels - 1; level >= 0; level--) { > + /* grab the left hand block */ > + error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); > + if (error) > + return error; > + > + /* readahead the left most block for the next level down */ > + if (level > 0) { > + union xfs_btree_ptr *ptr; > + > + ptr = xfs_btree_ptr_addr(cur, 1, block); > + xfs_btree_readahead_ptr(cur, ptr, 1); > + > + /* save for the next iteration of the loop */ > + lptr = *ptr; > + } > + > + /* for each buffer in the level */ > + do { > + error = xfs_btree_visit_block(cur, level, fn, data); > + } while (!error); > + > + if (error != -ENOENT) > + return error; > + } > + > + return 0; > +} > + > /* > * Change the owner of a btree. > * > @@ -4313,26 +4388,27 @@ xfs_btree_get_rec( > * just queue the modified buffer as delayed write buffer so the transaction > * recovery completion writes the changes to disk. > */ > +struct xfs_btree_block_change_owner_info { > + __uint64_t new_owner; > + struct list_head *buffer_list; > +}; > + > static int > xfs_btree_block_change_owner( > struct xfs_btree_cur *cur, > int level, > - __uint64_t new_owner, > - struct list_head *buffer_list) > + void *data) > { > + struct xfs_btree_block_change_owner_info *bbcoi = data; > struct xfs_btree_block *block; > struct xfs_buf *bp; > - union xfs_btree_ptr rptr; > - > - /* do right sibling readahead */ > - xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); > > /* modify the owner */ > block = xfs_btree_get_block(cur, level, &bp); > if (cur->bc_flags & XFS_BTREE_LONG_PTRS) > - block->bb_u.l.bb_owner = cpu_to_be64(new_owner); > + block->bb_u.l.bb_owner = cpu_to_be64(bbcoi->new_owner); > else > - block->bb_u.s.bb_owner = cpu_to_be32(new_owner); > + block->bb_u.s.bb_owner = cpu_to_be32(bbcoi->new_owner); > > /* > * If the block is a root block hosted in an inode, we might not have a > @@ -4346,19 +4422,14 @@ xfs_btree_block_change_owner( > xfs_trans_ordered_buf(cur->bc_tp, bp); > xfs_btree_log_block(cur, bp, XFS_BB_OWNER); > } else { > - xfs_buf_delwri_queue(bp, buffer_list); > + xfs_buf_delwri_queue(bp, bbcoi->buffer_list); > } > } else { > ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE); > ASSERT(level == cur->bc_nlevels - 1); > } > > - /* now read rh sibling block for next iteration */ > - xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB); > - if (xfs_btree_ptr_is_null(cur, &rptr)) > - return -ENOENT; > - > - return xfs_btree_lookup_get_block(cur, level, &rptr, &block); > + return 0; > } > > int > @@ -4367,43 +4438,13 @@ xfs_btree_change_owner( > __uint64_t new_owner, > struct list_head *buffer_list) > { > - union xfs_btree_ptr lptr; > - int level; > - struct xfs_btree_block *block = NULL; > - int error = 0; > + struct xfs_btree_block_change_owner_info bbcoi; > > - cur->bc_ops->init_ptr_from_cur(cur, &lptr); > + bbcoi.new_owner = new_owner; > + bbcoi.buffer_list = buffer_list; > > - /* for each level */ > - for (level = cur->bc_nlevels - 1; level >= 0; level--) { > - /* grab the left hand block */ > - error = xfs_btree_lookup_get_block(cur, level, &lptr, &block); > - if (error) > - return error; > - > - /* readahead the left most block for the next level down */ > - if (level > 0) { > - union xfs_btree_ptr *ptr; > - > - ptr = xfs_btree_ptr_addr(cur, 1, block); > - xfs_btree_readahead_ptr(cur, ptr, 1); > - > - /* save for the next iteration of the loop */ > - lptr = *ptr; > - } > - > - /* for each buffer in the level */ > - do { > - error = xfs_btree_block_change_owner(cur, level, > - new_owner, > - buffer_list); > - } while (!error); > - > - if (error != -ENOENT) > - return error; > - } > - > - return 0; > + return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner, > + &bbcoi); > } > > /** > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index 898fee5..0ec3055 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -506,4 +506,9 @@ int xfs_btree_query_range(struct xfs_btree_cur *cur, > union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, > xfs_btree_query_range_fn fn, void *priv); > > +typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level, > + void *data); > +int xfs_btree_visit_blocks(struct xfs_btree_cur *cur, > + xfs_btree_visit_blocks_fn fn, void *data); > + > #endif /* __XFS_BTREE_H__ */ > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From sandeen@sandeen.net Thu Jun 23 12:35:21 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9F1AC7CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 12:35:21 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 70EA7304048 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 10:35:18 -0700 (PDT) X-ASG-Debug-ID: 1466703314-04cb6c063f1171d0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id jrQnCCG0bYUWbz9l for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 10:35:14 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 6499D15B3B for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 12:35:14 -0500 (CDT) Subject: Re: [PATCH] xfs_repair: resolve Coverity OVERFLOW_BEFORE_WIDEN To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] xfs_repair: resolve Coverity OVERFLOW_BEFORE_WIDEN References: <1466701630-6380-1-git-send-email-billodo@redhat.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <f1844664-4eea-9fdc-f617-39a602977201@sandeen.net> Date: Thu, 23 Jun 2016 12:35:14 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1466701630-6380-1-git-send-email-billodo@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1466703314 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1142 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30695 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/23/16 12:07 PM, Bill O'Donnell wrote: > Coverity complains that when multiplying two 32 bit values that > eventually will be stored in a 64 bit value that it's possible > the math could overflow unless one of the values being multiplied > is type cast to the proper size. > > Signed-off-by: Bill O'Donnell <billodo@redhat.com> Makes sense. Given that this is repair, and either value could be larger than expected, we need the skip value to be accurate. Reviewed-by: Eric Sandeen <sandeen@redhat.com> > --- > repair/sb.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/repair/sb.c b/repair/sb.c > index 3965953..8d4843c 100644 > --- a/repair/sb.c > +++ b/repair/sb.c > @@ -230,7 +230,7 @@ find_secondary_sb(xfs_sb_t *rsb) > do_warn(_("\nattempting to find secondary superblock...\n")); > > if (verify_sb_blocksize(rsb) == 0) { > - skip = rsb->sb_agblocks * rsb->sb_blocksize; > + skip = (__uint64_t)rsb->sb_agblocks * rsb->sb_blocksize; > if (skip >= XFS_AG_MIN_BYTES && skip <= XFS_AG_MAX_BYTES) > retval = __find_secondary_sb(rsb, skip, skip); > } > From sandeen@sandeen.net Thu Jun 23 13:12:26 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 7E4DF7CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 13:12:26 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 514818F8033 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 11:12:22 -0700 (PDT) X-ASG-Debug-ID: 1466705540-04cbb027381377c0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id AjZoEWlO7ZsAJF1o for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 11:12:20 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 6690915B3B for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 13:12:20 -0500 (CDT) Subject: Re: xfs metadata overhead To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: xfs metadata overhead References: <CAC=x_0jDYb17Vh97Led7XXDiUMcUTJbpJ2Dw45gn=D0_w0K5VQ@mail.gmail.com> <20160622225117.GX12670@dastard> <CAC=x_0hdvm7SSP8EOAdUwLa-k3a3p7p7CRj8tyCnEx=As7A6jw@mail.gmail.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <71fbc905-ef05-126a-5c7f-c68c9018763c@sandeen.net> Date: Thu, 23 Jun 2016 13:12:20 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <CAC=x_0hdvm7SSP8EOAdUwLa-k3a3p7p7CRj8tyCnEx=As7A6jw@mail.gmail.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1466705540 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1725 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30696 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/23/16 10:04 AM, Danny Shavit wrote: > I see. We will try this direction. > BTW: I thought that good estimate would be "volume_size - > allocated_size - free_space". But it produced quite a difference > compared to metadata dump size. > Is there a specific reason? How do you determine allocated_size, with du? How different? Can you show an example? -Eric > Thanks, > Danny > > On Thu, Jun 23, 2016 at 1:51 AM, Dave Chinner <david@fromorbit.com <mailto:david@fromorbit.com>> wrote: > > On Wed, Jun 22, 2016 at 06:58:16PM +0300, Danny Shavit wrote: > > Hi, > > > > We are looking for a method to estimate the size of metadata overhead for a > > given file system. > > We would like to use this value as indicator for the amount of cache memory > > a system for faster operation. > > Are there any counters that are maintained in the on-disk data > > structures like free space for examples? > > No. > > Right now, you'll need to take a metadump of the filesystem to > measure it. The size of the dump file will be a close indication of > the amount of metadata in the filesystem as it only contains > the filesystem metadata. > > In future, querying the rmap will enable us to calculate it on the > fly, (i.e. not requiring the filesystem to be snapshotted/taken off > line to do a metadump). > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com <mailto:david@fromorbit.com> > > > > > -- > Regards, > Danny > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs > From david@fromorbit.com Thu Jun 23 18:25:02 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 641A27CA1 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:25:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id E0892AC003 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 16:24:58 -0700 (PDT) X-ASG-Debug-ID: 1466724295-04bdf074b52e280001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id WacvkWjcMwBec3TK for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 16:24:55 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2BAFgCxbmxXEJgMLHldgz6BU4J2g3mecQEBAQEBAQaMPYoQhhIEAgKBMU0BAQEBAQEHAQEBAQEBAQE+QIRNAQEEOhwjEAgDDgoJJQ8FJQMHGhOIL8dCAQEBAQYCASQehUKFFYdsgi8FmH+OJ48tj36CXByBXioyigABAQE Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 24 Jun 2016 08:54:47 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGDzK-0007JT-VU; Fri, 24 Jun 2016 09:24:47 +1000 Date: Fri, 24 Jun 2016 09:24:46 +1000 From: Dave Chinner <david@fromorbit.com> To: Christoph Hellwig <hch@lst.de> Cc: xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160623232446.GA12670@dastard> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466609236-23801-1-git-send-email-hch@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466724295 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1311 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30706 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 22, 2016 at 05:27:08PM +0200, Christoph Hellwig wrote: > The last patch is what started the series: XFS currently uses the > direct I/O locking strategy for DAX because DAX was overloaded onto > the direct I/O path. For XFS this means that we only take a shared > inode lock instead of the normal exclusive one for writes IFF they > are properly aligned. While this is fine for O_DIRECT which requires > explicit opt-in from the application it's not fine for DAX where we'll > suddenly lose expected and required synchronization of the file system > happens to use DAX undeneath. Except we did that *intentionally* - by definition there is no cache to bypass with DAX and so all IO is "direct". That, combined with the fact that all Linux filesystems except XFS break the POSIX exclusive writer rule you are quoting to begin with, it seemed pointless to enforce it for DAX.... So, before taking any patches to change that behaviour in XFS, a wider discussion about the policy needs to be had. I don't think we should care about POSIX here - if you have an application that needs this serialisation, turn off DAX. That's why I made it a per-inode inheritable flag and why the mount option will go away over time. Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 23 19:40:31 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6FDEF7CA0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 19:40:31 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id B7DDFAC005 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 17:40:27 -0700 (PDT) X-ASG-Debug-ID: 1466728824-04cb6c063e123960001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id jpo717iup26hhwxu for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 17:40:24 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AXFwBXgGxXEJgMLHldgz6BU4J2g3mecQEBAQEBB4w9hgaECoYSAgIBAQKBMU0BAQEBAQEHAQEBAQEBAQE+QIRNAQEEOhwjEAgDGAklDwUlAwcaE4gvx1EBAQEBBgIBJB6FQoUVgTmGM4IvBZh/jieBXY1Qj36CaYFtKjKKAAEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 24 Jun 2016 10:10:24 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGFAU-0007Qm-Qp; Fri, 24 Jun 2016 10:40:22 +1000 Date: Fri, 24 Jun 2016 10:40:22 +1000 From: Dave Chinner <david@fromorbit.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH 008/145] libxfs: add more list operations Message-ID: <20160624004022.GB12670@dastard> X-ASG-Orig-Subj: Re: [PATCH 008/145] libxfs: add more list operations References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> <146612709549.16048.6522744362673808871.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612709549.16048.6522744362673808871.stgit@birch.djwong.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466728824 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 588 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30707 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 16, 2016 at 06:31:35PM -0700, Darrick J. Wong wrote: > Add some list operations that the deferred rmap code requires. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> This has all come from the linux kernel, right? Can you tell me which files it has come from so I can add it to the commit message? Maybe it would be better to keep the list sorting code in it's own file (e.g. libxfs/list_sort.c) just to keep a bit of separation between the xfs code and code that is copied in from outside? Cheers, Dave. -- Dave Chinner david@fromorbit.com From darrick.wong@oracle.com Thu Jun 23 19:46:57 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E420E7CA0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 19:46:56 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 77F6DAC003 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 17:46:56 -0700 (PDT) X-ASG-Debug-ID: 1466729207-04bdf074b630ab0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id qLBl8N4HCthLuuA5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 17:46:48 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5O0kg55018741 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 24 Jun 2016 00:46:43 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5O0kgH2002520 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Jun 2016 00:46:42 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5O0kfOq027936; Fri, 24 Jun 2016 00:46:41 GMT Received: from localhost (/173.240.251.56) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 23 Jun 2016 17:46:41 -0700 Date: Thu, 23 Jun 2016 17:46:38 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Dave Chinner <david@fromorbit.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH 008/145] libxfs: add more list operations Message-ID: <20160624004638.GA18415@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 008/145] libxfs: add more list operations References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> <146612709549.16048.6522744362673808871.stgit@birch.djwong.org> <20160624004022.GB12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160624004022.GB12670@dastard> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466729208 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1100 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30708 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 24, 2016 at 10:40:22AM +1000, Dave Chinner wrote: > On Thu, Jun 16, 2016 at 06:31:35PM -0700, Darrick J. Wong wrote: > > Add some list operations that the deferred rmap code requires. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > This has all come from the linux kernel, right? Yes. > Can you tell me > which files it has come from so I can add it to the commit message? lib/list_sort.c for all the list_sort stuff, include/linux/list.h for the rest of the list_* stuff, include/linux/kernel.h for container_of. > Maybe it would be better to keep the list sorting code in it's own > file (e.g. libxfs/list_sort.c) just to keep a bit of separation > between the xfs code and code that is copied in from outside? I'd wondered if it made more sense to do that, but (sort of arbitrarily decided not to add more files). --D > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From dan.j.williams@intel.com Thu Jun 23 20:14:54 2016 Return-Path: <dan.j.williams@intel.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8B84B7CA0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 20:14:54 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 4B1CB304039 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:14:54 -0700 (PDT) X-ASG-Debug-ID: 1466730888-04cbb02738146ba0001-NocioJ Received: from mail-oi0-f50.google.com (mail-oi0-f50.google.com [209.85.218.50]) by cuda.sgi.com with ESMTP id jemKORhGBXTGC51t (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:14:48 -0700 (PDT) X-Barracuda-Envelope-From: dan.j.williams@intel.com X-Barracuda-Effective-Source-IP: mail-oi0-f50.google.com[209.85.218.50] X-Barracuda-Apparent-Source-IP: 209.85.218.50 Received: by mail-oi0-f50.google.com with SMTP id r2so95902884oih.2 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:14:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=27uAdUarQkLHWAp5DpGQyGPV4FiRtuJj0kt2eFeL8Pc=; b=GZFnFJ078iYHoZFw77scvTrY3Y6I9p+LKHULs8lZOgfJhMiQf8iPsUmXkcW5YbZ+dG ME7c2ECwv+GaO5x3S70G3eQsEgaEn6TQNvsIlg9ebs+R9nWzB5aaZUJGwm+OJXcS341O fktUbU9wUbv6UwJR8Vcpr5PUaDRDnR14dLfF+Tw8Ti0ghtd7+mjuQnoQYR9+G+cybLU1 lAoQ/odM0rif+v14V+05qFUwFtOb0WXZhjaaTDTLrREi+bHgWBcmGWMvyZ89d7Cr6Fv6 OytyVB/Y9+shgaU0sZ+c2hQdEjcG2kMoSeFCa0rut1e1id97bZgzhFTXiZhKuyduwz95 hWLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=27uAdUarQkLHWAp5DpGQyGPV4FiRtuJj0kt2eFeL8Pc=; b=TiRVs5K9m9YonKPiRDsbOYt1KAkwYc87KI/2H35plaHe7OUjWSiZR8YT1KkU+1OfSS z4jxdysDt6bmokrB2iYGkGpZEgsPCCDlBMdFmUvo4uIfoaoA1IFmtB/BR2Miv4EbDARV TTzLE3LmM4kKd6jIoBBLc2ZfxWuuu8w+QlcdtQ0TyZW7O97qDtETp8RLX//C5RyznUtr MMiT1cboE/O5akosT3PiHtfc3J2YQmEDXn8lc8BCkZxxac5kmzxgblJMay4IV/uhuEsr RYF5AEfSbJWq3RW5GJSZJuLG8Mms77hSlgpmQMChP0Tb7qCuO3Xd+qdbwo7W6kTXElM7 2cJw== X-Gm-Message-State: ALyK8tLwr7uGjvFWEb7xbXAXU+SG3W+aEPx0D2WLw5UwhvBf5Tfhle3ZcLsigeU7Usm4AdlXbbsuveNeQrwcQa7N X-Received: by 10.157.16.93 with SMTP id o29mr1068228oto.155.1466730887948; Thu, 23 Jun 2016 18:14:47 -0700 (PDT) MIME-Version: 1.0 Received: by 10.157.62.131 with HTTP; Thu, 23 Jun 2016 18:14:47 -0700 (PDT) In-Reply-To: <20160623232446.GA12670@dastard> References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> From: Dan Williams <dan.j.williams@intel.com> Date: Thu, 23 Jun 2016 18:14:47 -0700 Message-ID: <CAPcyv4iWVyJ3vb+_dtehGRxT9WXwAxNXoDMNeNtxO+=njHNAhg@mail.gmail.com> Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking To: Dave Chinner <david@fromorbit.com> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Cc: Christoph Hellwig <hch@lst.de>, linux-fsdevel <linux-fsdevel@vger.kernel.org>, linux-nvdimm <linux-nvdimm@ml01.01.org>, XFS Developers <xfs@oss.sgi.com> Content-Type: text/plain; charset=UTF-8 X-Barracuda-Connect: mail-oi0-f50.google.com[209.85.218.50] X-Barracuda-Start-Time: 1466730888 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1553 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30708 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On Thu, Jun 23, 2016 at 4:24 PM, Dave Chinner <david@fromorbit.com> wrote: > On Wed, Jun 22, 2016 at 05:27:08PM +0200, Christoph Hellwig wrote: >> The last patch is what started the series: XFS currently uses the >> direct I/O locking strategy for DAX because DAX was overloaded onto >> the direct I/O path. For XFS this means that we only take a shared >> inode lock instead of the normal exclusive one for writes IFF they >> are properly aligned. While this is fine for O_DIRECT which requires >> explicit opt-in from the application it's not fine for DAX where we'll >> suddenly lose expected and required synchronization of the file system >> happens to use DAX undeneath. > > Except we did that *intentionally* - by definition there is no > cache to bypass with DAX and so all IO is "direct". That, combined > with the fact that all Linux filesystems except XFS break the POSIX > exclusive writer rule you are quoting to begin with, it seemed > pointless to enforce it for DAX.... If we're going to be strict about POSIX fsync() semantics we should be strict about this exclusive write semantic. In other words why is it ok to loosen one and not the other, if application compatibility is the concern? > > So, before taking any patches to change that behaviour in XFS, a > wider discussion about the policy needs to be had. I don't think > we should care about POSIX here - if you have an application that > needs this serialisation, turn off DAX. s/needs this serialisation/needs the kernel to flush cpu cache/ From darrick.wong@oracle.com Thu Jun 23 20:41:08 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A02F67CA0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 20:41:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 70002304051 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:41:08 -0700 (PDT) X-ASG-Debug-ID: 1466732466-04cb6c063e125310001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id J9wNLmdvwCJxazib (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:41:06 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5O1f0uo027392 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Jun 2016 01:41:00 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5O1exhb025095 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Jun 2016 01:41:00 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5O1euCu023204; Fri, 24 Jun 2016 01:40:57 GMT Received: from localhost (/173.240.251.56) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Thu, 23 Jun 2016 18:40:55 -0700 Date: Thu, 23 Jun 2016 18:40:53 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Vishal Verma <vishal.l.verma@intel.com> Cc: linux-nvdimm@ml01.01.org, xfs@oss.sgi.com, Dave Chinner <david@fromorbit.com>, Jan Kara <jack@suse.cz> Subject: Re: [RFC PATCH 0/2] Initial support for badblock checking in xfs Message-ID: <20160624014053.GB18415@birch.djwong.org> X-ASG-Orig-Subj: Re: [RFC PATCH 0/2] Initial support for badblock checking in xfs References: <1466125419-17736-1-git-send-email-vishal.l.verma@intel.com> <20160620184812.GA21878@omniknight.lm.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160620184812.GA21878@omniknight.lm.intel.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466732466 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4627 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30708 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 20, 2016 at 12:48:27PM -0600, Vishal Verma wrote: > On 06/16, Vishal Verma wrote: > > These are early/RFC patches to add badblock support in xfs. > > > > Patch 1 should be relatively straightforward - it adds a notifier chain > > to badblocks that filesystems can register with. > > > > Patch 2 is the beginnings of xfs support. So far, I have the notifier > > registration and building the initial badblock list happening in > > xfs_mountfs. The next steps (and I may need some help with this as I'm > > no (x)fs developer :)) are to add this badblocks info to the reverse > > mapping tree, and then to check for it before accessing the media. > > > > Right now, this just prints the sector numbers/counts/{added, removed} > > to the kernel log, for both the initial list, and subsequent notifier > > hits. > > > > While I've tested this with a fake pmem device using libnvdimm's > > nfit_test framework, it should also work using badblock injection with > > any block device: > > > > # mkfs.xfs -f /dev/<device> > > # echo 122 1 > /sys/block/<device>/badblocks > > # echo 124 1 > /sys/block/<device>/badblocks > > # mount -t xfs /dev/<device> /mnt > > ... in log: > > [ +8.803776] XFS (pmem7): Mounting V4 Filesystem > > [ +0.009633] XFS (pmem7): Ending clean mount > > [ +0.001655] XFS (pmem7): got badblocks: sector 122, count 1 > > [ +0.002018] XFS (pmem7): got badblocks: sector 124, count 1 > > > > # echo 132 5 | > /sys/block/<device>/badblocks > > [Jun16 18:56] XFS (pmem7): xfs badblock added sector 132 (count 5) > > > > This is all based on Darrik's rmap work at: > > https://github.com/djwong/linux/tree/rmap-reflink-devel > > > > Since this is based on a v4.5-rc kernel, it lacks pmem support for > > clearing badblocks on zeroing/writing, so those parts can't easily > > be tested yet. The clearing work is in 4.7-rs kernels, and once we > > rebase to that, that should also be available. > > Just fyi, These patches should also cleanly apply to Darrick's for-next > rebase: > https://github.com/djwong/linux/tree/djwong-devel > > With this, I can now test badblock clearing also: > > $ cat /sys/block/pmem7/badblocks > 122 1 > 124 1 > 126 1 > 128 1 > > $ sudo dd if=/dev/zero of=/dev/pmem7 bs=512 count=8 seek=120 > oflag=direct > 8+0 records in > 8+0 records out > 4096 bytes (4.1 kB) copied, 0.0206735 s, 198 kB/s > > [ +9.510106] nd_pmem namespace7.0: pmem_clear_poison: 78 clear 1 sector > [ +0.001827] XFS (pmem7): xfs badblock cleared sector 120 (count 1) > > [ +0.002772] nd_pmem namespace7.0: pmem_clear_poison: 7a clear 1 sector > [ +0.002527] XFS (pmem7): xfs badblock cleared sector 122 (count 1) > > [ +0.003004] nd_pmem namespace7.0: pmem_clear_poison: 7c clear 1 sector > [ +0.002215] XFS (pmem7): xfs badblock cleared sector 124 (count 1) > > [ +0.003063] nd_pmem namespace7.0: pmem_clear_poison: 7e clear 1 sector > [ +0.002307] XFS (pmem7): xfs badblock cleared sector 126 (count 1) I guess the next step looks something like this? static int xfs_whine_about_corruption( struct getfsmapx *fmv, void *priv) { struct xfs_mount *mp = priv; if (fmv->fmv_owner < 0) { xfs_err(mp, "fs metadata corrupt, bye bye!"); /* XXX: maybe shut down now? */ return 0; } xfs_err(mp, "inode %llu is corrupt at offset %llu length %u", fmv->fmv_owner, fmv->fmv_offset, fmv->fmv_length); return 0; } int xfs_whine_about_badblocks( struct xfs_mount *mp, sector_t low, sector_t high) { struct getfsmapx fmv[2]; struct getfsmapx *l, *h; int error; memset(l, 0, sizeof(*l)); memset(h, 0xFF, sizeof(*h)); l = fmv; h = fmv + 1; l->fmv_block = low; h->fmv_block = high; l->fmv_count = 2; return xfs_getfsmap(mp, fmv, xfs_whine_about_corruption, mp); } static int xfs_notifier_call(...) { ...all the stuff that's already there... xfs_whine_about_badblocks(mp, bb_data->sector, bb_data->sector + bb_data->count - 1); } (Yeah, you need rmap for this to do anything useful.) --D > > > > > > > > Vishal Verma (2): > > block, badblocks: add a notifier for badblocks > > xfs: initial/partial support for badblocks > > > > block/badblocks.c | 79 +++++++++++++++++++++++++++++++++-- > > fs/xfs/xfs_linux.h | 1 + > > fs/xfs/xfs_mount.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ > > fs/xfs/xfs_mount.h | 1 + > > include/linux/badblocks.h | 19 +++++++++ > > 5 files changed, 201 insertions(+), 3 deletions(-) > > > > -- > > 2.5.5 > > From david@fromorbit.com Thu Jun 23 20:50:26 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 126D27CA0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 20:50:26 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id D86798F8033 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:50:22 -0700 (PDT) X-ASG-Debug-ID: 1466733019-04cbb02736148920001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id rIKKADGAEi01XPYH for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 18:50:20 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AYFwDrkGxXEJgMLHldgz6BU4J2g3mecQEBAQEBB4w9hgaECoYSAgIBAQKBM00BAQEBAQEHAQEBAQEBAQE+QIRMAQEBAwE6HCMQCAMYCSUPBSUDBxoTiCgHxz0BAQEBBgEBAQEjHoVChRWBOYYzgi8FmH+OJ4FzjTqGU4krgmmBbSoyigABAQE Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail06.adl6.internode.on.net with ESMTP; 24 Jun 2016 11:20:19 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGGGA-0007X1-7i; Fri, 24 Jun 2016 11:50:18 +1000 Date: Fri, 24 Jun 2016 11:50:18 +1000 From: Dave Chinner <david@fromorbit.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH 008/145] libxfs: add more list operations Message-ID: <20160624015018.GC12670@dastard> X-ASG-Orig-Subj: Re: [PATCH 008/145] libxfs: add more list operations References: <146612704434.16048.12932915166928562654.stgit@birch.djwong.org> <146612709549.16048.6522744362673808871.stgit@birch.djwong.org> <20160624004022.GB12670@dastard> <20160624004638.GA18415@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160624004638.GA18415@birch.djwong.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466733019 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1353 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30709 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 23, 2016 at 05:46:38PM -0700, Darrick J. Wong wrote: > On Fri, Jun 24, 2016 at 10:40:22AM +1000, Dave Chinner wrote: > > On Thu, Jun 16, 2016 at 06:31:35PM -0700, Darrick J. Wong wrote: > > > Add some list operations that the deferred rmap code requires. > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > > This has all come from the linux kernel, right? > > Yes. > > > Can you tell me > > which files it has come from so I can add it to the commit message? > > lib/list_sort.c for all the list_sort stuff, > include/linux/list.h for the rest of the list_* stuff, > include/linux/kernel.h for container_of. I thought we already had container_of. Ah, only inside __KERNEL__ code fragments.... > > Maybe it would be better to keep the list sorting code in it's own > > file (e.g. libxfs/list_sort.c) just to keep a bit of separation > > between the xfs code and code that is copied in from outside? > > I'd wondered if it made more sense to do that, but (sort of arbitrarily > decided not to add more files). keeping it in a spearate file makes it easier to update in future (e.g. forklift replacement of radix tree code). maybe we don't need to do this here, but I don't mind adding new files for stuff like this... Cheers, Dave. -- Dave Chinner david@fromorbit.com From Sales.7@plasticbag.com Thu Jun 23 23:55:34 2016 Return-Path: <Sales.7@plasticbag.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: **** X-Spam-Status: No, score=4.2 required=5.0 tests=DEAR_SOMETHING,HTML_MESSAGE, MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0D1667CA0 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 23:55:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id D693B304039 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 21:55:30 -0700 (PDT) X-ASG-Debug-ID: 1466744125-04cb6c063c12a7b0001-NocioJ Received: from bromine.com ([39.69.182.88]) by cuda.sgi.com with SMTP id Xz3cPyS2BQAH7j6E for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 21:55:25 -0700 (PDT) X-Barracuda-Envelope-From: Sales.7@plasticbag.com X-Barracuda-Effective-Source-IP: UNKNOWN[39.69.182.88] X-Barracuda-Apparent-Source-IP: 39.69.182.88 Received: from PC201602130941[127.0.0.1] by PC201602130941[127.0.0.1] (SMTPD32); Fri, 24 Jun 2016 12:55:22 +0800 From: "sander.suen@bestplasticbag.com" <sander.suen@bestplasticbag.com> Subject: =?UTF-8?B?UmXvvJpSZTpIRFBF?= bags on roll To: xfs@oss.sgi.com X-ASG-Orig-Subj: =?UTF-8?B?UmXvvJpSZTpIRFBF?= bags on roll MIME-Version: 1.0 Sender: Sales.7@plasticbag.com Reply-To: sander.suen@bestplasticbag.com Date: Fri, 24 Jun 2016 12:55:22 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline X-Barracuda-Connect: UNKNOWN[39.69.182.88] X-Barracuda-Start-Time: 1466744125 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 19302 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.94 X-Barracuda-Spam-Status: No, SCORE=0.94 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_SA038b, BSF_SC5_MJ1963, HTML_MESSAGE, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30712 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.20 BSF_SC0_SA038b Custom Rule SA038b 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160624045530.C49B91296087@cuda.sgi.com> PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVU Ri04IiBodHRwLWVxdWl2PWNvbnRlbnQtdHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCA5LjAwLjgxMTIuMTY2ODQiPjwvSEVBRD4NCjxCT0RZPg0KPERJViANCnN0eWxl PSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAw cHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1B UkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBB RERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IExFVFRFUi1TUEFDSU5HOiBub3Jt YWw7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8yMXB4IOWui+S9kzsgV0hJVEUtU1BB Q0U6IG5vcm1hbDsgQ09MT1I6IHJnYigwLDAsMTI4KTsgQ0xFQVI6IGJvdGg7IEJPUkRFUi1UT1A6 IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFdPUkQtU1BBQ0lORzogMHB4OyBQQURESU5HLVRPUDog MHB4OyAtd2Via2l0LXRleHQtc3Ryb2tlLXdpZHRoOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJPUkRF Ui1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgTUFS R0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFE RElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBG T05ULUZBTUlMWTogVmVyZGFuYTsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsg UEFERElORy1UT1A6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JE RVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBMSU5FLUhFSUdIVDogMjFweDsgTUFS R0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFE RElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBG T05ULUZBTUlMWTogJiMzOTt0aW1lcyBuZXcgcm9tYW4mIzM5OzsgRk9OVC1TSVpFOiAxNnB4OyBC T1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij5EZWFy IA0KU2lyPC9TUEFOPjwvU1BBTj48L0RJVj4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTog MHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRF WFQtVFJBTlNGT1JNOiBub25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgT1VUTElO RS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsg T1VUTElORS1XSURUSDogMHB4OyBMRVRURVItU1BBQ0lORzogbm9ybWFsOyBQQURESU5HLVJJR0hU OiAwcHg7IEZPTlQ6IDE0cHgvMjFweCDlrovkvZM7IFdISVRFLVNQQUNFOiBub3JtYWw7IENPTE9S OiByZ2IoMCwwLDEyOCk7IENMRUFSOiBib3RoOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdI VDogMHB4OyBXT1JELVNQQUNJTkc6IDBweDsgUEFERElORy1UT1A6IDBweDsgLXdlYmtpdC10ZXh0 LXN0cm9rZS13aWR0aDogMHB4Ij48QlI+PC9ESVY+DQo8RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RU T006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAx OyBURVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9V VExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAw cHg7IE9VVExJTkUtV0lEVEg6IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1hbDsgUEFERElORy1S SUdIVDogMHB4OyBGT05UOiAxNHB4LzIxcHgg5a6L5L2TOyBXSElURS1TUEFDRTogbm9ybWFsOyBD T0xPUjogcmdiKDAsMCwxMjgpOyBDTEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVIt UklHSFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkctVE9QOiAwcHg7IC13ZWJraXQt dGV4dC1zdHJva2Utd2lkdGg6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4 OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBMSU5FLUhFSUdIVDogMjFw eDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVy dDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDog MHB4OyBGT05ULUZBTUlMWTogJiMzOTt0aW1lcyBuZXcgcm9tYW4mIzM5OzsgQ09MT1I6IHJnYigy NTUsMCwwKTsgRk9OVC1TSVpFOiAxNnB4OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDog MHB4OyBQQURESU5HLVRPUDogMHB4Ij5BcyANCnRoZSBxdWxhaXR5ICwgaXQgaXMgYW4gQWN0ICwg SXQgaXMgSGFiaXQgIVdlIGFsc28ga25vdyB5b3UgYnV5IHRoZSBTdHJpcCB0LXNoaXJ0IA0KYmFn IGluIENoaW5hLiBXZSBhbHNvIGNhbiBwcm92aWRlIGJlc3QgcHJpY2Ugd2l0aCBxdWFsaXR5IGZv ciB5b3U8L1NQQU4+PC9ESVY+DQo8UCANCnN0eWxlPSJXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JN OiBub25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5v cm1hbDsgRk9OVDogMTRweC8yMXB4IOWui+S9kzsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsgQ09MT1I6 IHJnYigwLDAsMTI4KTsgQ0xFQVI6IGJvdGg7IFdPUkQtU1BBQ0lORzogMHB4OyAtd2Via2l0LXRl eHQtc3Ryb2tlLXdpZHRoOiAwcHgiPjwvUD4NCjxQIA0Kc3R5bGU9IldJRE9XUzogMTsgVEVYVC1U UkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBMRVRURVItU1BB Q0lORzogbm9ybWFsOyBGT05UOiAxNHB4LzIxcHgg5a6L5L2TOyBXSElURS1TUEFDRTogbm9ybWFs OyBDT0xPUjogcmdiKDAsMCwxMjgpOyBDTEVBUjogYm90aDsgV09SRC1TUEFDSU5HOiAwcHg7IC13 ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRP TTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBw eDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxF RlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFN SUxZOiBWZXJkYW5hOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5H LVRPUDogMHB4Ij48U1BBTiANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZU OiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IExJTkUtSEVJR0hUOiAyMXB4OyBNQVJHSU46IDBw eDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxF RlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFN SUxZOiAmIzM5O3RpbWVzIG5ldyByb21hbiYjMzk7OyBGT05ULVNJWkU6IDE2cHg7IEJPUkRFUi1U T1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPjwvU1BBTj48L1NQ QU4+Jm5ic3A7PC9QPg0KPFAgDQpzdHlsZT0iV0lET1dTOiAxOyBURVhULVRSQU5TRk9STTogbm9u ZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7 IEZPTlQ6IDE0cHgvMjFweCDlrovkvZM7IFdISVRFLVNQQUNFOiBub3JtYWw7IENPTE9SOiByZ2Io MCwwLDEyOCk7IENMRUFSOiBib3RoOyBXT1JELVNQQUNJTkc6IDBweDsgLXdlYmtpdC10ZXh0LXN0 cm9rZS13aWR0aDogMHB4Ij48L1A+DQo8RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsg Qk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRS QU5TRk9STTogbm9uZTsgQkFDS0dST1VORC1DT0xPUjogcmdiKDI1NSwyNTUsMjU1KTsgVEVYVC1J TkRFTlQ6IDIwcHg7IE1BUkdJTjogMHB4IDBjbSAwcHQ7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9V VExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBw eDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1hbDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4 LzE5cHgg5a6L5L2TOyBXSElURS1TUEFDRTogbm9ybWFsOyBDT0xPUjogcmdiKDAsMCwxMjgpOyBD TEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgV09SRC1TUEFD SU5HOiAwcHg7IFBBRERJTkctVE9QOiAwcHg7IC13ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBw eCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQ QURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VU TElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4 OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtU0laRTogMTZweDsgQk9SREVSLVRPUDogMHB4OyBC T1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVS LUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBNQVJH SU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURE SU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZP TlQtRkFNSUxZOiAmIzM5O1RpbWVzIE5ldyBSb21hbiYjMzk7OyBCT1JERVItVE9QOiAwcHg7IEJP UkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij5XZSANCmFyZSB0aGUgcHJvZmVzc2lv bmFsIG1hbnVmYWN0dXJlciBvZiBwbGFzdGljIGJhZ3MgaW4gQ2hpbmEuIE91ciBwcm9kdWN0cyBy YW5nZSANCmluY2x1ZGUgYWxsIGtpbmRzIG9mIHBsYXN0aWMgc2hvcHBpbmcgYmFnczxTUEFOIA0K c3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RU T006IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6 IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1S SUdIVDogMHB4OyBDT0xPUjogcmdiKDI1NSwwLDApOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1S SUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij4oVC1zaGlydCANCmJhZ3MpICwgZ2FyYmFnZSBi YWdzLCBmcmVlemVyIGJhZ3MgLCBmbGF0IGJhZ3Mgb24gcm9sbCwgbmFwcHkgYmFnczwvU1BBTj48 U1BBTiANCmNsYXNzPUFwcGxlLWNvbnZlcnRlZC1zcGFjZT4mbmJzcDs8L1NQQU4+ZXRjLiB3aGlj aCBhcmUgbWFkZSBvZiBIRFBFIG9yIExEUEUgDQptYXRlcmlhbHMuIFdlJiMzOTtkIGxpa2UgdG8g cXVvdGUgZm9yIHlvdSBhbmQgZXN0YWJsaXNoIGNvb3BlcmF0aW9uIHdpdGggeW91IGlmIHlvdSAN CmFyZSBpbnRlcmVzdGVkIGluIG91ciBwcm9kdWN0cy48L1NQQU4+PC9TUEFOPjwvRElWPg0KPERJ ViANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkct Qk9UVE9NOiAwcHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IEJBQ0tHUk9VTkQt Q09MT1I6IHJnYigyNTUsMjU1LDI1NSk7IFRFWFQtSU5ERU5UOiAyMHB4OyBNQVJHSU46IDBweCAw Y20gMHB0OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJ TkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7 IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8xOXB4IOWui+S9kzsgV0hJVEUtU1BBQ0U6 IG5vcm1hbDsgQ09MT1I6IHJnYigwLDAsMTI4KTsgQ0xFQVI6IGJvdGg7IEJPUkRFUi1UT1A6IDBw eDsgQk9SREVSLVJJR0hUOiAwcHg7IFdPUkQtU1BBQ0lORzogMHB4OyBQQURESU5HLVRPUDogMHB4 OyAtd2Via2l0LXRleHQtc3Ryb2tlLXdpZHRoOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1C T1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgTUFSR0lO OiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElO Ry1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05U LUZBTUlMWTogJiMzOTtUaW1lcyBOZXcgUm9tYW4mIzM5OzsgQ09MT1I6IHJnYigyNTUsMCwwKTsg Rk9OVC1TSVpFOiAxNnB4OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURE SU5HLVRPUDogMHB4Ij5CZXN0IA0KYm90dG9tIHByaWNlIGZvciB5b3UgLjwvU1BBTj48L0RJVj4N CjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURE SU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBub25lOyBCQUNLR1JP VU5ELUNPTE9SOiByZ2IoMjU1LDI1NSwyNTUpOyBURVhULUlOREVOVDogMjBweDsgTUFSR0lOOiAw cHggMGNtIDBwdDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQ QURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBMRVRURVItU1BBQ0lORzogbm9y bWFsOyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0cHgvMTlweCDlrovkvZM7IFdISVRFLVNQ QUNFOiBub3JtYWw7IENPTE9SOiByZ2IoMCwwLDEyOCk7IENMRUFSOiBib3RoOyBCT1JERVItVE9Q OiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBXT1JELVNQQUNJTkc6IDBweDsgUEFERElORy1UT1A6 IDBweDsgLXdlYmtpdC10ZXh0LXN0cm9rZS13aWR0aDogMHB4Ij48U1BBTiANCnN0eWxlPSJCT1JE RVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IE1B UkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBB RERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsg Rk9OVC1GQU1JTFk6ICYjMzk7VGltZXMgTmV3IFJvbWFuJiMzOTs7IEZPTlQtU0laRTogMTZweDsg Qk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+PEJS PjwvU1BBTj48L0RJVj4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVIt TEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JN OiBub25lOyBCQUNLR1JPVU5ELUNPTE9SOiByZ2IoMjU1LDI1NSwyNTUpOyBURVhULUlOREVOVDog MjBweDsgTUFSR0lOOiAwcHggMGNtIDBwdDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1D T0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBMRVRU RVItU1BBQ0lORzogbm9ybWFsOyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0cHgvMTlweCDl rovkvZM7IFdISVRFLVNQQUNFOiBub3JtYWw7IENPTE9SOiByZ2IoMCwwLDEyOCk7IENMRUFSOiBi b3RoOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBXT1JELVNQQUNJTkc6IDBw eDsgUEFERElORy1UT1A6IDBweDsgLXdlYmtpdC10ZXh0LXN0cm9rZS13aWR0aDogMHB4Ij48U1BB TiANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkct Qk9UVE9NOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNP TE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJ TkctUklHSFQ6IDBweDsgRk9OVC1GQU1JTFk6ICYjMzk7VGltZXMgTmV3IFJvbWFuJiMzOTs7IEZP TlQtU0laRTogMTZweDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElO Ry1UT1A6IDBweCI+UGxlYXNlIA0Ka2lubGR5IGdpdmUgdXMgb24gY2hvaWNlIC4mbmJzcDs8L1NQ QU4+PC9ESVY+DQo8RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6 IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRSQU5TRk9STTogbm9u ZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9V VExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBw eDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1hbDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4 LzIxcHgg5a6L5L2TOyBXSElURS1TUEFDRTogbm9ybWFsOyBDT0xPUjogcmdiKDAsMCwxMjgpOyBD TEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgV09SRC1TUEFD SU5HOiAwcHg7IFBBRERJTkctVE9QOiAwcHg7IC13ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBw eCI+PEJSIA0KY2xhc3M9d2Via2l0LWJsb2NrLXBsYWNlaG9sZGVyPjwvRElWPg0KPERJViANCnN0 eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9N OiAwcHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IEJBQ0tHUk9VTkQtQ09MT1I6 IHJnYigyNTUsMjU1LDI1NSk7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4IDBjbSAwcHQ7 IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZU OiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1hbDsgUEFERElO Ry1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzE5cHgg5a6L5L2TOyBXSElURS1TUEFDRTogbm9ybWFs OyBDT0xPUjogcmdiKDAsMCwxMjgpOyBDTEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JE RVItUklHSFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkctVE9QOiAwcHg7IC13ZWJr aXQtdGV4dC1zdHJva2Utd2lkdGg6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTog MHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsg T1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6 IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtU0laRTog MTZweDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBw eCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQ QURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VU TElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4 OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFNSUxZOiAmIzM5O1RpbWVzIE5ldyBSb21hbiYj Mzk7OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4 Ij5Bd2FpdCANCnlvdXIgcmVwbHk8L1NQQU4+PC9TUEFOPjwvRElWPg0KPERJViANCnN0eWxlPSJC T1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7 IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJ TjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJ TkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7 IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8yMXB4IOWui+S9kzsgV0hJVEUtU1BBQ0U6 IG5vcm1hbDsgQ09MT1I6IHJnYigwLDAsMTI4KTsgQ0xFQVI6IGJvdGg7IEJPUkRFUi1UT1A6IDBw eDsgQk9SREVSLVJJR0hUOiAwcHg7IFdPUkQtU1BBQ0lORzogMHB4OyBQQURESU5HLVRPUDogMHB4 OyAtd2Via2l0LXRleHQtc3Ryb2tlLXdpZHRoOiAwcHgiPjxCUiANCmNsYXNzPXdlYmtpdC1ibG9j ay1wbGFjZWhvbGRlcj48L0RJVj4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBC T1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQtVFJB TlNGT1JNOiBub25lOyBCQUNLR1JPVU5ELUNPTE9SOiByZ2IoMjU1LDI1NSwyNTUpOyBURVhULUlO REVOVDogMHB4OyBNQVJHSU46IDBweCAwY20gMHB0OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRM SU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7 IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8x OXB4IOWui+S9kzsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsgQ09MT1I6IHJnYigwLDAsMTI4KTsgQ0xF QVI6IGJvdGg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFdPUkQtU1BBQ0lO RzogMHB4OyBQQURESU5HLVRPUDogMHB4OyAtd2Via2l0LXRleHQtc3Ryb2tlLXdpZHRoOiAwcHgi PjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFE RElORy1CT1RUT006IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJ TkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsg UEFERElORy1SSUdIVDogMHB4OyBGT05ULVNJWkU6IDE2cHg7IEJPUkRFUi1UT1A6IDBweDsgQk9S REVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1C T1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgTUFSR0lO OiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElO Ry1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05U LUZBTUlMWTogJiMzOTtUaW1lcyBOZXcgUm9tYW4mIzM5OzsgQk9SREVSLVRPUDogMHB4OyBCT1JE RVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+VGhhbmtzIA0KYW5kIEJlc3QgcmVnYXJk czwvU1BBTj48L1NQQU4+PC9ESVY+DQo8RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsg Qk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRS QU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZ TEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJ TkUtV0lEVEg6IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1hbDsgUEFERElORy1SSUdIVDogMHB4 OyBGT05UOiAxNHB4LzIxcHgg5a6L5L2TOyBXSElURS1TUEFDRTogbm9ybWFsOyBDT0xPUjogcmdi KDAsMCwxMjgpOyBDTEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBw eDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkctVE9QOiAwcHg7IC13ZWJraXQtdGV4dC1zdHJv a2Utd2lkdGg6IDBweCI+PEJSIA0KY2xhc3M9d2Via2l0LWJsb2NrLXBsYWNlaG9sZGVyPjwvRElW Pg0KPERJViANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBB RERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IEJBQ0tH Uk9VTkQtQ09MT1I6IHJnYigyNTUsMjU1LDI1NSk7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjog MHB4IDBjbSAwcHQ7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsg UEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5v cm1hbDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzE5cHgg5a6L5L2TOyBXSElURS1T UEFDRTogbm9ybWFsOyBDT0xPUjogcmdiKDAsMCwxMjgpOyBDTEVBUjogYm90aDsgQk9SREVSLVRP UDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkctVE9Q OiAwcHg7IC13ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9S REVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBN QVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQ QURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7 IEZPTlQtRkFNSUxZOiAmIzM5O1RpbWVzIE5ldyBSb21hbiYjMzk7OyBGT05ULVNJWkU6IDE2cHg7 IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPlNh bmRlcjwvU1BBTj48L0RJVj4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JE RVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNG T1JNOiBub25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTog bm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1X SURUSDogMHB4OyBMRVRURVItU1BBQ0lORzogbm9ybWFsOyBQQURESU5HLVJJR0hUOiAwcHg7IEZP TlQ6IDE0cHgvMjFweCDlrovkvZM7IFdISVRFLVNQQUNFOiBub3JtYWw7IENPTE9SOiByZ2IoMCww LDEyOCk7IENMRUFSOiBib3RoOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBX T1JELVNQQUNJTkc6IDBweDsgUEFERElORy1UT1A6IDBweDsgLXdlYmtpdC10ZXh0LXN0cm9rZS13 aWR0aDogMHB4Ij48QlIgDQpjbGFzcz13ZWJraXQtYmxvY2stcGxhY2Vob2xkZXI+PC9ESVY+DQo8 RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElO Ry1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRF TlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6 IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgTEVUVEVSLVNQ QUNJTkc6IG5vcm1hbDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzIxcHgg5a6L5L2T OyBXSElURS1TUEFDRTogbm9ybWFsOyBDT0xPUjogcmdiKDAsMCwxMjgpOyBDTEVBUjogYm90aDsg Qk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBB RERJTkctVE9QOiAwcHg7IC13ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBweCI+PEJSIA0KY2xh c3M9d2Via2l0LWJsb2NrLXBsYWNlaG9sZGVyPjwvRElWPg0KPEhSIA0Kc3R5bGU9IldJRE9XUzog MTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IExFVFRFUi1TUEFDSU5H OiBub3JtYWw7IEZPTlQ6IDE0cHgvMjFweCDlrovkvZM7IFdISVRFLVNQQUNFOiBub3JtYWw7IENP TE9SOiByZ2IoMCwwLDEyOCk7IFdPUkQtU1BBQ0lORzogMHB4OyAtd2Via2l0LXRleHQtc3Ryb2tl LXdpZHRoOiAwcHgiPg0KDQo8UCANCnN0eWxlPSJXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBu b25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1h bDsgRk9OVDogMTRweC8yMXB4IOWui+S9kzsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsgQ09MT1I6IHJn YigwLDAsMTI4KTsgQ0xFQVI6IGJvdGg7IFdPUkQtU1BBQ0lORzogMHB4OyAtd2Via2l0LXRleHQt c3Ryb2tlLXdpZHRoOiAwcHgiPjwvUD4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4 OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQt VFJBTlNGT1JNOiBub25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1T VFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VU TElORS1XSURUSDogMHB4OyBMRVRURVItU1BBQ0lORzogbm9ybWFsOyBQQURESU5HLVJJR0hUOiAw cHg7IEZPTlQ6IDE0cHgvMjFweCDlrovkvZM7IFdISVRFLVNQQUNFOiBub3JtYWw7IENPTE9SOiBy Z2IoMCwwLDEyOCk7IENMRUFSOiBib3RoOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDog MHB4OyBXT1JELVNQQUNJTkc6IDBweDsgUEFERElORy1UT1A6IDBweDsgLXdlYmtpdC10ZXh0LXN0 cm9rZS13aWR0aDogMHB4Ij48U1BBTiANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRF Ui1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNU WUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRM SU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVC1GQU1JTFk6ICYjMzk7dGlt ZXMgbmV3IHJvbWFuJiMzOTs7IENPTE9SOiByZ2IoMCwzMiw5Nik7IEZPTlQtU0laRTogMTZweDsg Qk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+V2Vp ZmFuZyANCkxlZGEgUGFja2FnaW5nIGNvLixsdGQ8L1NQQU4+PC9ESVY+DQo8RElWIA0Kc3R5bGU9 IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBw eDsgV0lET1dTOiAxOyBURVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFS R0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFE RElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1h bDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzIxcHgg5a6L5L2TOyBXSElURS1TUEFD RTogbm9ybWFsOyBDT0xPUjogcmdiKDAsMCwxMjgpOyBDTEVBUjogYm90aDsgQk9SREVSLVRPUDog MHB4OyBCT1JERVItUklHSFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkctVE9QOiAw cHg7IC13ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBweCI+PEJSIA0KY2xhc3M9d2Via2l0LWJs b2NrLXBsYWNlaG9sZGVyPjwvRElWPg0KPERJViANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7 IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzogMTsgVEVYVC1U UkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNU WUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRM SU5FLVdJRFRIOiAwcHg7IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7IFBBRERJTkctUklHSFQ6IDBw eDsgRk9OVDogMTRweC8yMXB4IOWui+S9kzsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsgQ09MT1I6IHJn YigwLDAsMTI4KTsgQ0xFQVI6IGJvdGg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAw cHg7IFdPUkQtU1BBQ0lORzogMHB4OyBQQURESU5HLVRPUDogMHB4OyAtd2Via2l0LXRleHQtc3Ry b2tlLXdpZHRoOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVS LUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZ TEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJ TkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05ULUZBTUlMWTogJiMzOTt0aW1l cyBuZXcgcm9tYW4mIzM5OzsgQ09MT1I6IHJnYigwLDMyLDk2KTsgRk9OVC1TSVpFOiAxNnB4OyBC T1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij5QSE9O RTowMDg2LTEzMjgwMTA2NzA4PC9TUEFOPjwvRElWPg0KPERJViANCnN0eWxlPSJCT1JERVItQk9U VE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzog MTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBP VVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDog MHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7IFBBRERJTkct UklHSFQ6IDBweDsgRk9OVDogMTRweC8yMXB4IOWui+S9kzsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsg Q09MT1I6IHJnYigwLDAsMTI4KTsgQ0xFQVI6IGJvdGg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVS LVJJR0hUOiAwcHg7IFdPUkQtU1BBQ0lORzogMHB4OyBQQURESU5HLVRPUDogMHB4OyAtd2Via2l0 LXRleHQtc3Ryb2tlLXdpZHRoOiAwcHgiPjxCUiANCmNsYXNzPXdlYmtpdC1ibG9jay1wbGFjZWhv bGRlcj48L0RJVj4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVG VDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBu b25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsg T1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDog MHB4OyBMRVRURVItU1BBQ0lORzogbm9ybWFsOyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0 cHgvMjFweCDlrovkvZM7IFdISVRFLVNQQUNFOiBub3JtYWw7IENPTE9SOiByZ2IoMCwwLDEyOCk7 IENMRUFSOiBib3RoOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBXT1JELVNQ QUNJTkc6IDBweDsgUEFERElORy1UT1A6IDBweDsgLXdlYmtpdC10ZXh0LXN0cm9rZS13aWR0aDog MHB4Ij48U1BBTiANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7 IFBBRERJTkctQk9UVE9NOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBP VVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAw cHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVC1GQU1JTFk6ICYjMzk7dGltZXMgbmV3IHJvbWFu JiMzOTs7IENPTE9SOiByZ2IoMCwzMiw5Nik7IEZPTlQtU0laRTogMTZweDsgQk9SREVSLVRPUDog MHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+PEEgDQpocmVmPSJza3lw ZTpzYW5kZXJzdWVuIj5TS1lQRTpzYW5kZXJzdWVuPC9BPjwvU1BBTj48L0RJVj4NCjxESVYgDQpz dHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRP TTogMHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBub25lOyBURVhULUlOREVOVDogMHB4 OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0 OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBMRVRURVItU1BBQ0lORzog bm9ybWFsOyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0cHgvMjFweCDlrovkvZM7IFdISVRF LVNQQUNFOiBub3JtYWw7IENPTE9SOiByZ2IoMCwwLDEyOCk7IENMRUFSOiBib3RoOyBCT1JERVIt VE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBXT1JELVNQQUNJTkc6IDBweDsgUEFERElORy1U T1A6IDBweDsgLXdlYmtpdC10ZXh0LXN0cm9rZS13aWR0aDogMHB4Ij48QlIgDQpjbGFzcz13ZWJr aXQtYmxvY2stcGxhY2Vob2xkZXI+PC9ESVY+DQo8RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006 IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBU RVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJ TkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7 IE9VVExJTkUtV0lEVEg6IDBweDsgTEVUVEVSLVNQQUNJTkc6IG5vcm1hbDsgUEFERElORy1SSUdI VDogMHB4OyBGT05UOiAxNHB4LzIxcHgg5a6L5L2TOyBXSElURS1TUEFDRTogbm9ybWFsOyBDT0xP UjogcmdiKDAsMCwxMjgpOyBDTEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklH SFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkctVE9QOiAwcHg7IC13ZWJraXQtdGV4 dC1zdHJva2Utd2lkdGg6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBC T1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsgT1VUTElO RS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsg T1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFNSUxZOiAmIzM5 O3RpbWVzIG5ldyByb21hbiYjMzk7OyBDT0xPUjogcmdiKDAsMzIsOTYpOyBGT05ULVNJWkU6IDE2 cHg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgi Pk1TTjpzYW5kZXIuc3VlbkA8QSANCmhyZWY9Imh0dHA6Ly9ob3RtYWlsLmNvbS8iPmhvdG1haWwu Y29tPC9BPjwvU1BBTj48U1BBTiANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1M RUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNUWUxF OiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5F LVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVC1GQU1JTFk6IOWui+S9kzsgRk9O VC1TSVpFOiAxNnB4OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5H LVRPUDogMHB4Ij48L1NQQU4+PC9ESVY+DQo8UD48QlIgY2xhc3M9QXBwbGUtaW50ZXJjaGFuZ2Ut bmV3bGluZT4mbmJzcDs8L1A+PC9CT0RZPjwvSFRNTD4NCg0K From houtao1@huawei.com Fri Jun 24 00:45:43 2016 Return-Path: <houtao1@huawei.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 99A327CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:45:43 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id F3B5EAC006 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 22:45:39 -0700 (PDT) X-ASG-Debug-ID: 1466747134-04bdf074b53c4a0001-NocioJ Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [58.251.152.64]) by cuda.sgi.com with ESMTP id jkH8lZgn3kkeNfLs (version=TLSv1 cipher=RC4-SHA bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 22:45:36 -0700 (PDT) X-Barracuda-Envelope-From: houtao1@huawei.com X-Barracuda-Effective-Source-IP: szxga01-in.huawei.com[58.251.152.64] X-Barracuda-Apparent-Source-IP: 58.251.152.64 Received: from 172.24.1.60 (EHLO szxeml426-hub.china.huawei.com) ([172.24.1.60]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DMR44898; Fri, 24 Jun 2016 13:45:32 +0800 (CST) Received: from huawei.com (10.175.124.28) by szxeml426-hub.china.huawei.com (10.82.67.181) with Microsoft SMTP Server id 14.3.235.1; Fri, 24 Jun 2016 13:45:23 +0800 From: Hou Tao <houtao1@huawei.com> To: <xfs@oss.sgi.com> CC: <fangwei1@huawei.com>, <miaoxie@huawei.com> Subject: [PATCH] xfs: simplify the calculation of tpp at xfs_bmdr_to_bmbt Date: Fri, 24 Jun 2016 13:39:20 +0800 X-ASG-Orig-Subj: [PATCH] xfs: simplify the calculation of tpp at xfs_bmdr_to_bmbt Message-ID: <1466746760-155962-1-git-send-email-houtao1@huawei.com> X-Mailer: git-send-email 2.5.5 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.175.124.28] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020202.576CC8FD.005A,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: e73e35560a214329a83deff3932eacca X-Barracuda-Connect: szxga01-in.huawei.com[58.251.152.64] X-Barracuda-Start-Time: 1466747136 X-Barracuda-Encrypted: RC4-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2328 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30713 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- remove the usage of rblocklen at xfs_bmdr_to_bmbt, and use be16_to_cpu(dblock->bb_numrecs) instead. It also reduces an extra calculation. Signed-off-by: Hou Tao <houtao1@huawei.com> --- fs/xfs/libxfs/xfs_bmap_btree.c | 5 ++--- fs/xfs/libxfs/xfs_bmap_btree.h | 2 +- fs/xfs/libxfs/xfs_inode_fork.c | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap_btree.c b/fs/xfs/libxfs/xfs_bmap_btree.c index 6282f6e..452cad9 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.c +++ b/fs/xfs/libxfs/xfs_bmap_btree.c @@ -59,8 +59,7 @@ xfs_bmdr_to_bmbt( struct xfs_inode *ip, xfs_bmdr_block_t *dblock, int dblocklen, - struct xfs_btree_block *rblock, - int rblocklen) + struct xfs_btree_block *rblock) { struct xfs_mount *mp = ip->i_mount; int dmxr; @@ -85,8 +84,8 @@ xfs_bmdr_to_bmbt( fkp = XFS_BMDR_KEY_ADDR(dblock, 1); tkp = XFS_BMBT_KEY_ADDR(mp, rblock, 1); fpp = XFS_BMDR_PTR_ADDR(dblock, 1, dmxr); - tpp = XFS_BMAP_BROOT_PTR_ADDR(mp, rblock, 1, rblocklen); dmxr = be16_to_cpu(dblock->bb_numrecs); + tpp = XFS_BMBT_PTR_ADDR(mp, rblock, 1, dmxr); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr); } diff --git a/fs/xfs/libxfs/xfs_bmap_btree.h b/fs/xfs/libxfs/xfs_bmap_btree.h index 819a8a4..b1d30f7 100644 --- a/fs/xfs/libxfs/xfs_bmap_btree.h +++ b/fs/xfs/libxfs/xfs_bmap_btree.h @@ -105,7 +105,7 @@ struct xfs_trans; * Prototypes for xfs_bmap.c to call. */ extern void xfs_bmdr_to_bmbt(struct xfs_inode *, xfs_bmdr_block_t *, int, - struct xfs_btree_block *, int); + struct xfs_btree_block *); extern void xfs_bmbt_get_all(xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s); extern xfs_filblks_t xfs_bmbt_get_blockcount(xfs_bmbt_rec_host_t *r); extern xfs_fsblock_t xfs_bmbt_get_startblock(xfs_bmbt_rec_host_t *r); diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index bbcc8c7..23967aa 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -433,7 +433,7 @@ xfs_iformat_btree( * to the in-memory structure. */ xfs_bmdr_to_bmbt(ip, dfp, XFS_DFORK_SIZE(dip, ip->i_mount, whichfork), - ifp->if_broot, size); + ifp->if_broot); ifp->if_flags &= ~XFS_IFEXTENTS; ifp->if_flags |= XFS_IFBROOT; -- 2.5.5 From david@fromorbit.com Fri Jun 24 01:38:11 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4ECCD7CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 01:38:11 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id D5208AC005 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 23:38:10 -0700 (PDT) X-ASG-Debug-ID: 1466750287-04bdf074b53dc30001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id qNsviBxCydMvH7Sy for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 23:38:07 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2BnFAAy1GxXEJgMLHldgz6BU4J2g3mebgaMPYNhgiWECoYSBAICgTFNAQEBAQEBBwEBAQEBAQEBPkCETQEBBCcTHCMQCAMYCSUPBSUDBxoTiC/HEgEBAQcCASQehUKFFYdsgi8BBJkAjimBXY1QSI82glwcgV4qMooAAQEB Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 24 Jun 2016 16:08:06 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGKkf-0007zo-KY; Fri, 24 Jun 2016 16:38:05 +1000 Date: Fri, 24 Jun 2016 16:38:05 +1000 From: Dave Chinner <david@fromorbit.com> To: Hou Tao <houtao1@huawei.com> Cc: xfs@oss.sgi.com, miaoxie@huawei.com, fangwei1@huawei.com Subject: Re: [PATCH] xfs: simplify the calculation of tpp at xfs_bmdr_to_bmbt Message-ID: <20160624063805.GD12670@dastard> X-ASG-Orig-Subj: Re: [PATCH] xfs: simplify the calculation of tpp at xfs_bmdr_to_bmbt References: <1466746760-155962-1-git-send-email-houtao1@huawei.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1466746760-155962-1-git-send-email-houtao1@huawei.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466750287 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 605 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30714 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 24, 2016 at 01:39:20PM +0800, Hou Tao wrote: > remove the usage of rblocklen at xfs_bmdr_to_bmbt, and > use be16_to_cpu(dblock->bb_numrecs) instead. It also > reduces an extra calculation. What problem does this fix, why does it need to be made and how did you test it? We have to be really careful about changing code that interacts with the on-disk format, as any bugs we introduced will result in filesystem corruption. Hence you need to explain to the reviewers why the change needs to be made to the reviewers... Cheers, Dave. -- Dave Chinner david@fromorbit.com From grace16@offer.com Fri Jun 24 01:42:23 2016 Return-Path: <grace16@offer.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.2 required=5.0 tests=HTML_MESSAGE,MIME_HTML_ONLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0D1A37CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 01:42:23 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id C1DF9304039 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 23:42:19 -0700 (PDT) X-ASG-Debug-ID: 1466750537-04cb6c063e12d1c0001-NocioJ Received: from offer.com ([219.133.162.97]) by cuda.sgi.com with SMTP id f4XLAFmuklQdBnO4 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 23:42:17 -0700 (PDT) X-Barracuda-Envelope-From: grace16@offer.com X-Barracuda-Effective-Source-IP: UNKNOWN[219.133.162.97] X-Barracuda-Apparent-Source-IP: 219.133.162.97 Received: from DESKTOP-9S5QUR1[127.0.0.1] by DESKTOP-9S5QUR1[127.0.0.1] (SMTPD32); Fri, 24 Jun 2016 13:58:35 +0800 From: "liguoyan2@163.com" <liguoyan2@163.com> Subject: re:bluetooth keyfinfer, ibeacon, personal alarm To: xfs@oss.sgi.com X-ASG-Orig-Subj: re:bluetooth keyfinfer, ibeacon, personal alarm MIME-Version: 1.0 Sender: grace16@offer.com Reply-To: liguoyan2@163.com Date: Fri, 24 Jun 2016 13:58:35 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline X-Barracuda-Connect: UNKNOWN[219.133.162.97] X-Barracuda-Start-Time: 1466750537 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3360 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.74 X-Barracuda-Spam-Status: No, SCORE=0.74 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, HTML_MESSAGE, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30713 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160624064219.A0BB7129608C@cuda.sgi.com> PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVU Ri04IiBodHRwLWVxdWl2PWNvbnRlbnQtdHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCAxMS4wMC4xMDU4Ni4wIj48L0hFQUQ+DQo8Qk9EWT4NCjxESVYgDQpzdHlsZT0i V0hJVEUtU1BBQ0U6IG5vcm1hbDsgV09SRC1TUEFDSU5HOiAwcHg7IFRFWFQtVFJBTlNGT1JNOiBu b25lOyBDT0xPUjogcmdiKDAsMCwwKTsgRk9OVDogMTRweC8yMHB4IFZlcmRhbmE7IFdJRE9XUzog MTsgTEVUVEVSLVNQQUNJTkc6IG5vcm1hbDsgVEVYVC1JTkRFTlQ6IDBweDsgLXdlYmtpdC10ZXh0 LXN0cm9rZS13aWR0aDogMHB4Ij4NCjxESVYgDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICYjMzk7bHVj aWRhIEdyYW5kZSYjMzk7LCBWZXJkYW5hLCAmIzM5O01pY3Jvc29mdCBZYUhlaSYjMzk7OyBMSU5F LUhFSUdIVDogMjNweCI+PEI+Jm5ic3A7aGkgDQpEZWFyICw8L0I+PC9ESVY+DQo8RElWIA0Kc3R5 bGU9IkZPTlQtRkFNSUxZOiAmIzM5O2x1Y2lkYSBHcmFuZGUmIzM5OywgVmVyZGFuYSwgJiMzOTtN aWNyb3NvZnQgWWFIZWkmIzM5OzsgTElORS1IRUlHSFQ6IDIzcHgiPjxTVFJPTkc+PC9TVFJPTkc+ Jm5ic3A7PC9ESVY+DQo8RElWIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAmIzM5O2x1Y2lkYSBHcmFu ZGUmIzM5OywgVmVyZGFuYSwgJiMzOTtNaWNyb3NvZnQgWWFIZWkmIzM5OzsgTElORS1IRUlHSFQ6 IDIzcHgiPjxCPk91ciANCk1BTlVGQUNUVVJFUiBmb2N1cyBvbiBCbHVldG9vdGggNC4wIChMb3cg RW5lcmd5KSwgcHJvZHVjZTo8L0I+PC9ESVY+DQo8RElWIA0Kc3R5bGU9IkZPTlQtRkFNSUxZOiAm IzM5O2x1Y2lkYSBHcmFuZGUmIzM5OywgVmVyZGFuYSwgJiMzOTtNaWNyb3NvZnQgWWFIZWkmIzM5 OzsgTElORS1IRUlHSFQ6IDIzcHgiPjxCPjEsIA0KQmVhY29uL2lCZWFjb246PC9CPiZuYnNwO2Zv ciBuYXZpZ2F0aW9uIFdJVEhPVVQgR1BTLCBjYW4gd29yayBwcm9wZXJseSBJTkRPT1IgDQphbmQg T1VURE9PUi48L0RJVj4NCjxESVYgDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICYjMzk7bHVjaWRhIEdy YW5kZSYjMzk7LCBWZXJkYW5hLCAmIzM5O01pY3Jvc29mdCBZYUhlaSYjMzk7OyBMSU5FLUhFSUdI VDogMjNweCI+PEI+MiwgDQpBbnRpLWxvc3QgQWxhcm06PC9CPiZuYnNwO2tlZXAgdmFsdWFibGUg dGhpbmdzIGluIHNhZmUgcmFuZ2UsIHByb3RlY3QgdGhlbSBmcm9tIA0KYmVpbmcgbG9zdDwvRElW Pg0KPERJViANCnN0eWxlPSJGT05ULUZBTUlMWTogJiMzOTtsdWNpZGEgR3JhbmRlJiMzOTssIFZl cmRhbmEsICYjMzk7TWljcm9zb2Z0IFlhSGVpJiMzOTs7IExJTkUtSEVJR0hUOiAyM3B4Ij5TdXBw b3J0IA0KbGFuZ3VhZ2UgOiBFbmdsaXNoLCBDaGluZXNlLER1dGNoLGZyZW5jaCxBcmFiaWMsIEtv cmVhbiwgSmFwYW5lc2UgLi4uIGFuZCBzbyANCm9uPC9ESVY+DQo8RElWIA0Kc3R5bGU9IkZPTlQt RkFNSUxZOiAmIzM5O2x1Y2lkYSBHcmFuZGUmIzM5OywgVmVyZGFuYSwgJiMzOTtNaWNyb3NvZnQg WWFIZWkmIzM5OzsgTElORS1IRUlHSFQ6IDIzcHgiPjxCIA0Kc3R5bGU9IkxJTkUtSEVJR0hUOiAy M3B4Ij4zLCBQZXJzb25hbCBBbGFybTo8U1BBTiANCmNsYXNzPUFwcGxlLWNvbnZlcnRlZC1zcGFj ZT4mbmJzcDs8L1NQQU4+PC9CPjxTUEFOIA0Kc3R5bGU9IkxJTkUtSEVJR0hUOiAyM3B4Ij5zdWl0 YWJsZSBmb3IgSG9tZXMgZm9yIHRoZSBlbGRlcmx5LCBjaGlsZHJlbiwgcGVvcGxlIA0Kb24gZmll bGQgdHJpcDwvU1BBTj48L0RJVj4NCjxESVYgDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICYjMzk7bHVj aWRhIEdyYW5kZSYjMzk7LCBWZXJkYW5hLCAmIzM5O01pY3Jvc29mdCBZYUhlaSYjMzk7OyBMSU5F LUhFSUdIVDogMjNweCI+PFNQQU4gDQpzdHlsZT0iTElORS1IRUlHSFQ6IDIzcHgiPjwvU1BBTj4m bmJzcDs8L0RJVj4NCjxESVYgDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICYjMzk7bHVjaWRhIEdyYW5k ZSYjMzk7LCBWZXJkYW5hLCAmIzM5O01pY3Jvc29mdCBZYUhlaSYjMzk7OyBMSU5FLUhFSUdIVDog MjNweCI+PFNQQU4gDQpzdHlsZT0iTElORS1IRUlHSFQ6IDIzcHgiPndlbGNvbWUgdG8gcGxhY2Ug YW4gb3JkZXIgITwvU1BBTj48L0RJVj4NCjxESVYgDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICYjMzk7 bHVjaWRhIEdyYW5kZSYjMzk7LCBWZXJkYW5hLCAmIzM5O01pY3Jvc29mdCBZYUhlaSYjMzk7OyBM SU5FLUhFSUdIVDogMjNweCI+PFNQQU4gDQpzdHlsZT0iTElORS1IRUlHSFQ6IDIzcHgiPjwvU1BB Tj4mbmJzcDs8L0RJVj4NCjxESVYgDQpzdHlsZT0iRk9OVC1GQU1JTFk6ICYjMzk7bHVjaWRhIEdy YW5kZSYjMzk7LCBWZXJkYW5hLCAmIzM5O01pY3Jvc29mdCBZYUhlaSYjMzk7OyBMSU5FLUhFSUdI VDogMjNweCI+PFNQQU4gDQpzdHlsZT0iTElORS1IRUlHSFQ6IDIzcHgiPlRoYW5rcyBhbmQgQmVz dCByZWdhcmRzPEJSPmdyYWNlIGxpIGZyb20gDQo8U1RST05HPigmbmJzcDtzaGVuemhlbiBqb3l3 YXkgdGVjaG5vbG9neSBjby4sbHRkKTwvU1RST05HPjwvU1BBTj48L0RJVj4NCjxESVYgDQpzdHls ZT0iRk9OVC1GQU1JTFk6ICYjMzk7bHVjaWRhIEdyYW5kZSYjMzk7LCBWZXJkYW5hLCAmIzM5O01p Y3Jvc29mdCBZYUhlaSYjMzk7OyBMSU5FLUhFSUdIVDogMjNweCI+PFNQQU4gDQpzdHlsZT0iTElO RS1IRUlHSFQ6IDIzcHgiPjxTVFJPTkc+PC9TVFJPTkc+PC9TUEFOPiZuYnNwOzwvRElWPg0KPERJ ViANCnN0eWxlPSJGT05ULUZBTUlMWTogJiMzOTtsdWNpZGEgR3JhbmRlJiMzOTssIFZlcmRhbmEs ICYjMzk7TWljcm9zb2Z0IFlhSGVpJiMzOTs7IExJTkUtSEVJR0hUOiAyM3B4Ij48U1BBTiANCnN0 eWxlPSJMSU5FLUhFSUdIVDogMjNweCI+DQo8UCBjbGFzcz1Nc29Ob3JtYWwgc3R5bGU9Ik1BUkdJ TjogMHB0Ij48U1BBTiANCnN0eWxlPSJGT05ULVNJWkU6IDEwLjVwdDsgRk9OVC1GQU1JTFk6IFZl cmRhbmE7IG1zby1zcGFjZXJ1bjogJiMzOTt5ZXMmIzM5OzsgbXNvLWZvbnQta2VybmluZzogMS4w MDAwcHQiPnNreXBlOiANCmdyYWNlX2Jlc3RvbmVyPC9TUEFOPjwvUD4NCjxQIGNsYXNzPU1zb05v cm1hbCBzdHlsZT0iTUFSR0lOOiAwcHQiPjxTUEFOIA0Kc3R5bGU9IkZPTlQtU0laRTogMTAuNXB0 OyBGT05ULUZBTUlMWTogVmVyZGFuYTsgbXNvLXNwYWNlcnVuOiAmIzM5O3llcyYjMzk7OyBtc28t Zm9udC1rZXJuaW5nOiAxLjAwMDBwdCI+d2VjaGF0L21vYmlsZS93aGF0c2FwcDowMDg2LTEzNTEw NzI2NzE2PC9TUEFOPjwvUD48L1NQQU4+PC9ESVY+PC9ESVY+PC9CT0RZPjwvSFRNTD4NCg0K From houtao1@huawei.com Fri Jun 24 01:44:02 2016 Return-Path: <houtao1@huawei.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C39927CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 01:44:02 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 46066AC006 for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 23:44:02 -0700 (PDT) X-ASG-Debug-ID: 1466750634-04cbb0273815b250001-NocioJ Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [58.251.152.64]) by cuda.sgi.com with ESMTP id 2ynGe7xmQjgwihwd (version=TLSv1 cipher=RC4-SHA bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 23 Jun 2016 23:43:58 -0700 (PDT) X-Barracuda-Envelope-From: houtao1@huawei.com X-Barracuda-Effective-Source-IP: szxga01-in.huawei.com[58.251.152.64] X-Barracuda-Apparent-Source-IP: 58.251.152.64 Received: from 172.24.1.36 (EHLO szxeml428-hub.china.huawei.com) ([172.24.1.36]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DMR51499; Fri, 24 Jun 2016 14:43:46 +0800 (CST) Received: from [127.0.0.1] (10.177.31.14) by szxeml428-hub.china.huawei.com (10.82.67.183) with Microsoft SMTP Server id 14.3.235.1; Fri, 24 Jun 2016 14:43:44 +0800 Subject: Re: [PATCH] xfs: remove the magic numbers in xfs_btree_block-related len macros To: Carlos Maiolino <cmaiolino@redhat.com> X-ASG-Orig-Subj: Re: [PATCH] xfs: remove the magic numbers in xfs_btree_block-related len macros References: <1466651420-126472-1-git-send-email-houtao1@huawei.com> <20160623102137.GH27894@redhat.com> CC: <xfs@oss.sgi.com> From: Hou Tao <houtao1@huawei.com> Message-ID: <576CD699.6040404@huawei.com> Date: Fri, 24 Jun 2016 14:43:37 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.1.0 MIME-Version: 1.0 In-Reply-To: <20160623102137.GH27894@redhat.com> Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.177.31.14] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090201.576CD6A3.00AB,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 81f8c73db655933db9205b8dc5ccb6c2 X-Barracuda-Connect: szxga01-in.huawei.com[58.251.152.64] X-Barracuda-Start-Time: 1466750637 X-Barracuda-Encrypted: RC4-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4570 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30713 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 2016/6/23 18:21, Carlos Maiolino wrote: > On Thu, Jun 23, 2016 at 11:10:20AM +0800, Hou Tao wrote: >> replace the magic numbers by offsetof(...) and sizeof(...), and add two >> extra checks on xfs_check_ondisk_structs() >> >> Signed-off-by: Hou Tao <houtao1@huawei.com> >> --- >> fs/xfs/libxfs/xfs_format.h | 66 ++++++++++++++++++++++++++++------------------ >> fs/xfs/xfs_ondisk.h | 2 ++ >> 2 files changed, 43 insertions(+), 25 deletions(-) >> > > Particularly I liked the idea of defining the short and long block structures > outside of xfs_btree_block and removing magic numbers is a good thing too. > > you can consider it > I had tried to do more than just move two structs out of struct xfs_btree_block, but the modification would be huge, so i just keep it simple. > Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> > Thanks for your review. >> diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h >> index dc97eb21..d3069be 100644 >> --- a/fs/xfs/libxfs/xfs_format.h >> +++ b/fs/xfs/libxfs/xfs_format.h >> @@ -1435,41 +1435,57 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t; >> * with the crc feature bit, and all accesses to them must be conditional on >> * that flag. >> */ >> +/* short form block */ >> +struct xfs_btree_sblock_part { >> + __be32 bb_leftsib; >> + __be32 bb_rightsib; >> + >> + __be64 bb_blkno; >> + __be64 bb_lsn; >> + uuid_t bb_uuid; >> + __be32 bb_owner; >> + __le32 bb_crc; >> +}; >> + >> +/* long form block */ >> +struct xfs_btree_lblock_part { >> + __be64 bb_leftsib; >> + __be64 bb_rightsib; >> + >> + __be64 bb_blkno; >> + __be64 bb_lsn; >> + uuid_t bb_uuid; >> + __be64 bb_owner; >> + __le32 bb_crc; >> + __be32 bb_pad; /* padding for alignment */ >> +}; >> + >> struct xfs_btree_block { >> __be32 bb_magic; /* magic number for block type */ >> __be16 bb_level; /* 0 is a leaf */ >> __be16 bb_numrecs; /* current # of data records */ >> union { >> - struct { >> - __be32 bb_leftsib; >> - __be32 bb_rightsib; >> - >> - __be64 bb_blkno; >> - __be64 bb_lsn; >> - uuid_t bb_uuid; >> - __be32 bb_owner; >> - __le32 bb_crc; >> - } s; /* short form pointers */ >> - struct { >> - __be64 bb_leftsib; >> - __be64 bb_rightsib; >> - >> - __be64 bb_blkno; >> - __be64 bb_lsn; >> - uuid_t bb_uuid; >> - __be64 bb_owner; >> - __le32 bb_crc; >> - __be32 bb_pad; /* padding for alignment */ >> - } l; /* long form pointers */ >> + struct xfs_btree_sblock_part s; >> + struct xfs_btree_lblock_part l; >> } bb_u; /* rest */ >> }; >> >> -#define XFS_BTREE_SBLOCK_LEN 16 /* size of a short form block */ >> -#define XFS_BTREE_LBLOCK_LEN 24 /* size of a long form block */ >> +/* size of a short form block */ >> +#define XFS_BTREE_SBLOCK_LEN \ >> + (offsetof(struct xfs_btree_block, bb_u) + \ >> + offsetof(struct xfs_btree_sblock_part, bb_blkno)) >> +/* size of a long form block */ >> +#define XFS_BTREE_LBLOCK_LEN \ >> + (offsetof(struct xfs_btree_block, bb_u) + \ >> + offsetof(struct xfs_btree_lblock_part, bb_blkno)) >> >> /* sizes of CRC enabled btree blocks */ >> -#define XFS_BTREE_SBLOCK_CRC_LEN (XFS_BTREE_SBLOCK_LEN + 40) >> -#define XFS_BTREE_LBLOCK_CRC_LEN (XFS_BTREE_LBLOCK_LEN + 48) >> +#define XFS_BTREE_SBLOCK_CRC_LEN \ >> + (offsetof(struct xfs_btree_block, bb_u) + \ >> + sizeof(struct xfs_btree_sblock_part)) >> +#define XFS_BTREE_LBLOCK_CRC_LEN \ >> + (offsetof(struct xfs_btree_block, bb_u) + \ >> + sizeof(struct xfs_btree_lblock_part)) >> >> #define XFS_BTREE_SBLOCK_CRC_OFF \ >> offsetof(struct xfs_btree_block, bb_u.s.bb_crc) >> diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h >> index 184c44e..6f06c48 100644 >> --- a/fs/xfs/xfs_ondisk.h >> +++ b/fs/xfs/xfs_ondisk.h >> @@ -34,6 +34,8 @@ xfs_check_ondisk_structs(void) >> XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_key, 8); >> XFS_CHECK_STRUCT_SIZE(struct xfs_bmbt_rec, 16); >> XFS_CHECK_STRUCT_SIZE(struct xfs_bmdr_block, 4); >> + XFS_CHECK_STRUCT_SIZE(struct xfs_btree_sblock_part, 48); >> + XFS_CHECK_STRUCT_SIZE(struct xfs_btree_lblock_part, 64); >> XFS_CHECK_STRUCT_SIZE(struct xfs_btree_block, 72); >> XFS_CHECK_STRUCT_SIZE(struct xfs_dinode, 176); >> XFS_CHECK_STRUCT_SIZE(struct xfs_disk_dquot, 104); >> -- >> 2.5.5 >> >> _______________________________________________ >> xfs mailing list >> xfs@oss.sgi.com >> http://oss.sgi.com/mailman/listinfo/xfs > From houtao1@huawei.com Fri Jun 24 02:05:33 2016 Return-Path: <houtao1@huawei.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id CBA137CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:05:33 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 8EEB78F8037 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:05:30 -0700 (PDT) X-ASG-Debug-ID: 1466751924-04cb6c063e12dbe0001-NocioJ Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [58.251.152.64]) by cuda.sgi.com with ESMTP id AjesLioXLYfwrz3S (version=TLSv1 cipher=RC4-SHA bits=128 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:05:27 -0700 (PDT) X-Barracuda-Envelope-From: houtao1@huawei.com X-Barracuda-Effective-Source-IP: szxga01-in.huawei.com[58.251.152.64] X-Barracuda-Apparent-Source-IP: 58.251.152.64 Received: from 172.24.1.136 (EHLO szxeml426-hub.china.huawei.com) ([172.24.1.136]) by szxrg01-dlp.huawei.com (MOS 4.3.7-GA FastPath queued) with ESMTP id DMR54011; Fri, 24 Jun 2016 15:02:06 +0800 (CST) Received: from [127.0.0.1] (10.177.31.14) by szxeml426-hub.china.huawei.com (10.82.67.181) with Microsoft SMTP Server id 14.3.235.1; Fri, 24 Jun 2016 15:01:57 +0800 Subject: Re: [PATCH] xfs: simplify the calculation of tpp at xfs_bmdr_to_bmbt To: Dave Chinner <david@fromorbit.com> X-ASG-Orig-Subj: Re: [PATCH] xfs: simplify the calculation of tpp at xfs_bmdr_to_bmbt References: <1466746760-155962-1-git-send-email-houtao1@huawei.com> <20160624063805.GD12670@dastard> CC: <xfs@oss.sgi.com>, <miaoxie@huawei.com>, <fangwei1@huawei.com> From: Hou Tao <houtao1@huawei.com> Message-ID: <576CDAE4.2040202@huawei.com> Date: Fri, 24 Jun 2016 15:01:56 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.1.0 MIME-Version: 1.0 In-Reply-To: <20160624063805.GD12670@dastard> Content-Type: text/plain; charset="windows-1252" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.177.31.14] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090205.576CDAF1.0035,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 27fdaecfc117a6d6af846cf7c8682f4f X-Barracuda-Connect: szxga01-in.huawei.com[58.251.152.64] X-Barracuda-Start-Time: 1466751926 X-Barracuda-Encrypted: RC4-SHA X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 930 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30714 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 2016/6/24 14:38, Dave Chinner wrote: > On Fri, Jun 24, 2016 at 01:39:20PM +0800, Hou Tao wrote: >> remove the usage of rblocklen at xfs_bmdr_to_bmbt, and >> use be16_to_cpu(dblock->bb_numrecs) instead. It also >> reduces an extra calculation. > > What problem does this fix, why does it need to be made and > how did you test it? It fixes nothing, just for simplification of code understanding. And now I realize keeping the original code untouched is better, because using rblocklen to calculate the offset of xfs_bmbt_ptr_t is common among the btree code, so keeping it consistent. > We have to be really careful about changing code that interacts with > the on-disk format, as any bugs we introduced will result in > filesystem corruption. Hence you need to explain to the reviewers > why the change needs to be made to the reviewers... I will take care, Thanks. > > Cheers, > > Dave. > From david@fromorbit.com Fri Jun 24 02:14:02 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 9BF737CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:14:02 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 52D348F8035 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:14:02 -0700 (PDT) X-ASG-Debug-ID: 1466752438-04cbb0273515be60001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id 2rNk6zCBf7G2I5O6 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:13:58 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AnFQBl3GxXEJgMLHldgz6BU4J2g3mebgaMPYoQhhICAgEBAoExTQEBAQEBAQcBAQEBAQEBAT5AhE0BAQQ6HCMQCAMYCSUPBSUDBxoTiC/HDAEBAQEGAgEkHoVChRWELINAgi8FmQCOKY8tj36CXByBXioyiD2BQwEBAQ Received: from ppp121-44-12-152.lns20.syd4.internode.on.net (HELO dastard) ([121.44.12.152]) by ipmail07.adl2.internode.on.net with ESMTP; 24 Jun 2016 16:43:19 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGLIk-00083w-HP; Fri, 24 Jun 2016 17:13:18 +1000 Date: Fri, 24 Jun 2016 17:13:18 +1000 From: Dave Chinner <david@fromorbit.com> To: Dan Williams <dan.j.williams@intel.com> Cc: Christoph Hellwig <hch@lst.de>, linux-fsdevel <linux-fsdevel@vger.kernel.org>, linux-nvdimm <linux-nvdimm@ml01.01.org>, XFS Developers <xfs@oss.sgi.com> Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160624071318.GE12670@dastard> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <CAPcyv4iWVyJ3vb+_dtehGRxT9WXwAxNXoDMNeNtxO+=njHNAhg@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <CAPcyv4iWVyJ3vb+_dtehGRxT9WXwAxNXoDMNeNtxO+=njHNAhg@mail.gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1466752438 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3523 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30714 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 23, 2016 at 06:14:47PM -0700, Dan Williams wrote: > On Thu, Jun 23, 2016 at 4:24 PM, Dave Chinner <david@fromorbit.com> wrote: > > On Wed, Jun 22, 2016 at 05:27:08PM +0200, Christoph Hellwig wrote: > >> The last patch is what started the series: XFS currently uses the > >> direct I/O locking strategy for DAX because DAX was overloaded onto > >> the direct I/O path. For XFS this means that we only take a shared > >> inode lock instead of the normal exclusive one for writes IFF they > >> are properly aligned. While this is fine for O_DIRECT which requires > >> explicit opt-in from the application it's not fine for DAX where we'll > >> suddenly lose expected and required synchronization of the file system > >> happens to use DAX undeneath. > > > > Except we did that *intentionally* - by definition there is no > > cache to bypass with DAX and so all IO is "direct". That, combined > > with the fact that all Linux filesystems except XFS break the POSIX > > exclusive writer rule you are quoting to begin with, it seemed > > pointless to enforce it for DAX.... > > If we're going to be strict about POSIX fsync() semantics we should be > strict about this exclusive write semantic. In other words why is it > ok to loosen one and not the other, if application compatibility is > the concern? This is a POSIX compliant fsync() implementation: int fsync(int fd) { return 0; } That's not what we require from Linux filesystems and storage subsystems. Our data integrity requirements are not actually defined by POSIX - we go way beyond what POSIX actually requires us to implement. If all we cared about is POSIX, then the above is how we'd implement fsync() simply because it's fast. Everyone implements fsync differently, so portable applications can't actually rely on the POSIX standard fsync() implementation to keep their data safe... IOWs, we don't give a shit about what POSIX says about fsync because, in practice, it's useless. Instead, we implement something that *works* and provides users with real data integrity guarantees. If you like the POSIX specs for data integrity, go use sync_file_range() - it doesn't guarantee data integrity, just like posix compliant fsync(). And yes, applications that use sync_file_range() are known to lose data when systems crash... The POSIX exclusive write requirement is a different case. No linux filesystem except XFS has ever met that requirement (in 20 something years), yet I don't see applications falling over with corrupt data from non-exclusive writes all the time, nor do I see application developers shouting at us to provide it. i.e. reality tells us this isn't a POSIX behaviour that applications rely on because everyone implements it differently. So, like fsync(), if everyone implements it differently, applications don't rely on posix smeantics to serialise access to overlapping ranges of a file. And if that's the case, then why even bother exclusive write locking in the filesystem when there is no need for serialisation of page cache contents? We don't do it because POSIX says so, because we already ignore what POSIX says about this topic for technical reasons. So why should we make DAX conform to POSIX exclusive writer behaviour when DAX is being specifically aimed at high performance, highly concurrent applications where exclusive writer behaviour will cause major performance issues? Cheers, Dave. -- Dave Chinner david@fromorbit.com From hch@lst.de Fri Jun 24 02:26:17 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EC45A7CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:26:17 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id B154D8F8033 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:26:17 -0700 (PDT) X-ASG-Debug-ID: 1466753173-04cb6c063c12e2d0001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id 8GBfFaW2Kb3CeZ41 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:26:15 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id E85F068C3E; Fri, 24 Jun 2016 09:26:12 +0200 (CEST) Date: Fri, 24 Jun 2016 09:26:12 +0200 From: Christoph Hellwig <hch@lst.de> To: Dave Chinner <david@fromorbit.com> Cc: Christoph Hellwig <hch@lst.de>, xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160624072612.GA22205@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160623232446.GA12670@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1466753174 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1390 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30714 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 24, 2016 at 09:24:46AM +1000, Dave Chinner wrote: > Except we did that *intentionally* - by definition there is no > cache to bypass with DAX and so all IO is "direct". That, combined > with the fact that all Linux filesystems except XFS break the POSIX > exclusive writer rule you are quoting to begin with, it seemed > pointless to enforce it for DAX.... No file system breaks the exclusive writer rule - most filesystem don't make writers atomic vs readers. More importantly every other filesystem (well there only are ext2 and ext4..) exludes DAX writers against other DAX writers. > So, before taking any patches to change that behaviour in XFS, a > wider discussion about the policy needs to be had. I don't think > we should care about POSIX here - if you have an application that > needs this serialisation, turn off DAX. That's why I made it a > per-inode inheritable flag and why the mount option will go away > over time. Sorry, but this is simply broken - allowing apps to opt-in behavior (e.g. like we're using O_DIRECT) is always fine. Requriring filesystem-specific tuning that has affect outside the app to get existing documented behavior is not how to design APIs. Maybe we'll need to opt-in to use DAX for mmap, but giving the same existing behavior for read and write and avoiding a copy to the pagecache is an obvious win. From hch@lst.de Fri Jun 24 02:31:13 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id E89CA7CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:31:12 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id A871A8F8037 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:31:12 -0700 (PDT) X-ASG-Debug-ID: 1466753470-04cb6c063e12e460001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id 401sIY8mWBQaN2bQ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:31:10 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 92B7468C3E; Fri, 24 Jun 2016 09:31:09 +0200 (CEST) Date: Fri, 24 Jun 2016 09:31:09 +0200 From: Christoph Hellwig <hch@lst.de> To: Dave Chinner <david@fromorbit.com> Cc: Dan Williams <dan.j.williams@intel.com>, Christoph Hellwig <hch@lst.de>, linux-fsdevel <linux-fsdevel@vger.kernel.org>, linux-nvdimm <linux-nvdimm@ml01.01.org>, XFS Developers <xfs@oss.sgi.com> Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160624073109.GB22205@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <CAPcyv4iWVyJ3vb+_dtehGRxT9WXwAxNXoDMNeNtxO+=njHNAhg@mail.gmail.com> <20160624071318.GE12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160624071318.GE12670@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1466753470 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2720 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30714 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 24, 2016 at 05:13:18PM +1000, Dave Chinner wrote: > This is a POSIX compliant fsync() implementation: > > int fsync(int fd) > { > return 0; > } Depends on what you mean with "Posix". Modern Posix which includex XPG has the _POSIX_SYNCHRONIZED_IO option, which Linux implements. For that Posix says about fsync: [SIO] [Option Start] If _POSIX_SYNCHRONIZED_IO is defined, the fsync() function shall force all currently queued I/O operations associated with the file indicated by file descriptor fildes to the synchronized I/O completion state. All I/O operations shall be completed as defined for synchronized I/O file integrity completion. [Option End] Whereas synchronized I/O file integrity completion is defined as: 3.378 Synchronized I/O Data Integrity Completion For read, when the operation has been completed or diagnosed if unsuccessful. The read is complete only when an image of the data has been successfully transferred to the requesting process. If there were any pending write requests affecting the data to be read at the time that the synchronized read operation was requested, these write requests are successfully transferred prior to reading the data. For write, when the operation has been completed or diagnosed if unsuccessful. The write is complete only when the data specified in the write request is successfully transferred and all file system information required to retrieve the data is successfully transferred. File attributes that are not necessary for data retrieval (access time, modification time, status change time) need not be successfully transferred prior to returning to the calling process. 3.379 Synchronized I/O File Integrity Completion Identical to a synchronized I/O data integrity completion with the addition that all file attributes relative to the I/O operation (including access time, modification time, status change time) are successfully transferred prior to returning to the calling process. So in this case Posix very much requires data to be on a stable medium. > The POSIX exclusive write requirement is a different case. No linux > filesystem except XFS has ever met that requirement (in 20 something > years), yet I don't see applications falling over with corrupt data > from non-exclusive writes all the time, nor do I see application > developers shouting at us to provide it. i.e. reality tells us this > isn't a POSIX behaviour that applications rely on because everyone > implements it differently. Every file system exludes writes from other writes. From BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 24 02:52:57 2016 Return-Path: <BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 167827CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:52:57 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 7FF7EAC002 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:52:53 -0700 (PDT) X-ASG-Debug-ID: 1466754771-04cb6c063f12eb30001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id IFMT1bNgbRYhrpiH (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:52:51 -0700 (PDT) X-Barracuda-Envelope-From: BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [91.114.64.3] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bGLv0-0002rC-Ez for xfs@oss.sgi.com; Fri, 24 Jun 2016 07:52:50 +0000 From: Christoph Hellwig <hch@lst.de> To: xfs@oss.sgi.com Subject: get rid of unaligned embedded structs in on-disk structures Date: Fri, 24 Jun 2016 09:52:44 +0200 X-ASG-Orig-Subj: get rid of unaligned embedded structs in on-disk structures Message-Id: <1466754767-10657-1-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 X-SRS-Rewrite: SMTP reverse-path rewritten from <hch@infradead.org> by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466754771 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 276 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30715 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Recent build bot reports show that besides ARM old ABI at least openrisc and cris also have problems with our unaligned structures in the on-disk format. This series gets rid of our structs that just wrap u8 arrays used for get_unaligned_be* and the __arch_pack magic. From BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 24 02:52:58 2016 Return-Path: <BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 760287CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:52:58 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 48FC48F8035 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:52:58 -0700 (PDT) X-ASG-Debug-ID: 1466754775-04cbb0273715ccd0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id KfMMb1Nda6snmyPL (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:52:55 -0700 (PDT) X-Barracuda-Envelope-From: BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [91.114.64.3] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bGLv4-0002rI-Af for xfs@oss.sgi.com; Fri, 24 Jun 2016 07:52:54 +0000 From: Christoph Hellwig <hch@lst.de> To: xfs@oss.sgi.com Subject: [PATCH 1/3] xfs: kill xfs_dir2_sf_off_t Date: Fri, 24 Jun 2016 09:52:45 +0200 X-ASG-Orig-Subj: [PATCH 1/3] xfs: kill xfs_dir2_sf_off_t Message-Id: <1466754767-10657-2-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466754767-10657-1-git-send-email-hch@lst.de> References: <1466754767-10657-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from <hch@infradead.org> by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466754775 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4376 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30715 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Just use an array of two unsigned chars directly to avoid problems with architectures that pad the size of structures. Signed-off-by: Christoph Hellwig <hch@lst.de> --- fs/xfs/libxfs/xfs_da_format.h | 14 ++++---------- fs/xfs/libxfs/xfs_dir2_sf.c | 13 ++++++------- fs/xfs/xfs_ondisk.h | 1 - 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index 8d4d8bc..a5f4d6e 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -192,12 +192,6 @@ typedef __uint16_t xfs_dir2_data_off_t; typedef uint xfs_dir2_data_aoff_t; /* argument form */ /* - * Normalized offset (in a data block) of the entry, really xfs_dir2_data_off_t. - * Only need 16 bits, this is the byte offset into the single block form. - */ -typedef struct { __uint8_t i[2]; } __arch_pack xfs_dir2_sf_off_t; - -/* * Offset in data space of a data entry. */ typedef __uint32_t xfs_dir2_dataptr_t; @@ -251,7 +245,7 @@ typedef struct xfs_dir2_sf_hdr { typedef struct xfs_dir2_sf_entry { __u8 namelen; /* actual name length */ - xfs_dir2_sf_off_t offset; /* saved offset */ + __u8 offset[2]; /* saved offset */ __u8 name[]; /* name, variable size */ /* * A single byte containing the file type field follows the inode @@ -260,7 +254,7 @@ typedef struct xfs_dir2_sf_entry { * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a * variable offset after the name. */ -} __arch_pack xfs_dir2_sf_entry_t; +} xfs_dir2_sf_entry_t; static inline int xfs_dir2_sf_hdr_size(int i8count) { @@ -272,13 +266,13 @@ static inline int xfs_dir2_sf_hdr_size(int i8count) static inline xfs_dir2_data_aoff_t xfs_dir2_sf_get_offset(xfs_dir2_sf_entry_t *sfep) { - return get_unaligned_be16(&sfep->offset.i); + return get_unaligned_be16(sfep->offset); } static inline void xfs_dir2_sf_put_offset(xfs_dir2_sf_entry_t *sfep, xfs_dir2_data_aoff_t off) { - put_unaligned_be16(off, &sfep->offset.i); + put_unaligned_be16(off, sfep->offset); } static inline struct xfs_dir2_sf_entry * diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c index e5bb9cc..f8ccfd5a 100644 --- a/fs/xfs/libxfs/xfs_dir2_sf.c +++ b/fs/xfs/libxfs/xfs_dir2_sf.c @@ -126,11 +126,10 @@ xfs_dir2_block_sfsize( /* * Calculate the new size, see if we should give up yet. */ - size = xfs_dir2_sf_hdr_size(i8count) + /* header */ - count + /* namelen */ - count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */ - namelen + /* name */ - (i8count ? /* inumber */ + size = xfs_dir2_sf_hdr_size(i8count) + /* header */ + count * 3 * sizeof(u8) + /* namelen + offset */ + namelen + /* name */ + (i8count ? /* inumber */ (uint)sizeof(xfs_dir2_ino8_t) * count : (uint)sizeof(xfs_dir2_ino4_t) * count); if (size > XFS_IFORK_DSIZE(dp)) @@ -1048,7 +1047,7 @@ xfs_dir2_sf_toino4( i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; - sfep->offset = oldsfep->offset; + memcpy(sfep->offset, oldsfep->offset, sizeof(sfep->offset)); memcpy(sfep->name, oldsfep->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, dp->d_ops->sf_get_ino(oldsfp, oldsfep)); @@ -1124,7 +1123,7 @@ xfs_dir2_sf_toino8( i++, sfep = dp->d_ops->sf_nextentry(sfp, sfep), oldsfep = dp->d_ops->sf_nextentry(oldsfp, oldsfep)) { sfep->namelen = oldsfep->namelen; - sfep->offset = oldsfep->offset; + memcpy(sfep->offset, oldsfep->offset, sizeof(sfep->offset)); memcpy(sfep->name, oldsfep->name, sfep->namelen); dp->d_ops->sf_put_ino(sfp, sfep, dp->d_ops->sf_get_ino(oldsfp, oldsfep)); diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 0272301..3cbc1f8 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -116,7 +116,6 @@ xfs_check_ondisk_structs(void) XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, offset, 1); XFS_CHECK_OFFSET(xfs_dir2_sf_entry_t, name, 3); XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_hdr_t, 10); - XFS_CHECK_STRUCT_SIZE(xfs_dir2_sf_off_t, 2); /* log structures */ XFS_CHECK_STRUCT_SIZE(struct xfs_dq_logformat, 24); -- 2.1.4 From BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 24 02:53:01 2016 Return-Path: <BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id CEB957CA7 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:53:01 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 409A4AC003 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:53:01 -0700 (PDT) X-ASG-Debug-ID: 1466754778-04bdf074b53edf0001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id y3mb1HQRXaaTPPIp (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:52:58 -0700 (PDT) X-Barracuda-Envelope-From: BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [91.114.64.3] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bGLv7-0002rM-J6 for xfs@oss.sgi.com; Fri, 24 Jun 2016 07:52:58 +0000 From: Christoph Hellwig <hch@lst.de> To: xfs@oss.sgi.com Subject: [PATCH 2/3] xfs: kill xfs_dir2_inou_t Date: Fri, 24 Jun 2016 09:52:46 +0200 X-ASG-Orig-Subj: [PATCH 2/3] xfs: kill xfs_dir2_inou_t Message-Id: <1466754767-10657-3-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466754767-10657-1-git-send-email-hch@lst.de> References: <1466754767-10657-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from <hch@infradead.org> by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466754778 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8181 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30715 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 And use an array of unsigned char values directly to avoid problems with architectures that pad the size of structures. This also gets rid of the xfs_dir2_ino4_t and xfs_dir2_ino8_t types, and introduces new constants for the size of 4 and 8 bytes as well as the size difference between the two. Signed-off-by: Christoph Hellwig <hch@lst.de> --- fs/xfs/libxfs/xfs_da_format.c | 31 +++++++++++++------------------ fs/xfs/libxfs/xfs_da_format.h | 27 +++++++-------------------- fs/xfs/libxfs/xfs_dir2_sf.c | 25 ++++++------------------- fs/xfs/xfs_ondisk.h | 3 --- 4 files changed, 26 insertions(+), 60 deletions(-) diff --git a/fs/xfs/libxfs/xfs_da_format.c b/fs/xfs/libxfs/xfs_da_format.c index 9d624a6..f1e8d4d 100644 --- a/fs/xfs/libxfs/xfs_da_format.c +++ b/fs/xfs/libxfs/xfs_da_format.c @@ -40,8 +40,7 @@ xfs_dir2_sf_entsize( int count = sizeof(struct xfs_dir2_sf_entry); /* namelen + offset */ count += len; /* name */ - count += hdr->i8count ? sizeof(xfs_dir2_ino8_t) : - sizeof(xfs_dir2_ino4_t); /* ino # */ + count += hdr->i8count ? XFS_INO64_SIZE : XFS_INO32_SIZE; /* ino # */ return count; } @@ -125,33 +124,33 @@ xfs_dir3_sfe_put_ftype( static xfs_ino_t xfs_dir2_sf_get_ino( struct xfs_dir2_sf_hdr *hdr, - xfs_dir2_inou_t *from) + __uint8_t *from) { if (hdr->i8count) - return get_unaligned_be64(&from->i8.i) & 0x00ffffffffffffffULL; + return get_unaligned_be64(from) & 0x00ffffffffffffffULL; else - return get_unaligned_be32(&from->i4.i); + return get_unaligned_be32(from); } static void xfs_dir2_sf_put_ino( struct xfs_dir2_sf_hdr *hdr, - xfs_dir2_inou_t *to, + __uint8_t *to, xfs_ino_t ino) { ASSERT((ino & 0xff00000000000000ULL) == 0); if (hdr->i8count) - put_unaligned_be64(ino, &to->i8.i); + put_unaligned_be64(ino, to); else - put_unaligned_be32(ino, &to->i4.i); + put_unaligned_be32(ino, to); } static xfs_ino_t xfs_dir2_sf_get_parent_ino( struct xfs_dir2_sf_hdr *hdr) { - return xfs_dir2_sf_get_ino(hdr, &hdr->parent); + return xfs_dir2_sf_get_ino(hdr, hdr->parent); } static void @@ -159,7 +158,7 @@ xfs_dir2_sf_put_parent_ino( struct xfs_dir2_sf_hdr *hdr, xfs_ino_t ino) { - xfs_dir2_sf_put_ino(hdr, &hdr->parent, ino); + xfs_dir2_sf_put_ino(hdr, hdr->parent, ino); } /* @@ -173,8 +172,7 @@ xfs_dir2_sfe_get_ino( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep) { - return xfs_dir2_sf_get_ino(hdr, - (xfs_dir2_inou_t *)&sfep->name[sfep->namelen]); + return xfs_dir2_sf_get_ino(hdr, &sfep->name[sfep->namelen]); } static void @@ -183,8 +181,7 @@ xfs_dir2_sfe_put_ino( struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino) { - xfs_dir2_sf_put_ino(hdr, - (xfs_dir2_inou_t *)&sfep->name[sfep->namelen], ino); + xfs_dir2_sf_put_ino(hdr, &sfep->name[sfep->namelen], ino); } static xfs_ino_t @@ -192,8 +189,7 @@ xfs_dir3_sfe_get_ino( struct xfs_dir2_sf_hdr *hdr, struct xfs_dir2_sf_entry *sfep) { - return xfs_dir2_sf_get_ino(hdr, - (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1]); + return xfs_dir2_sf_get_ino(hdr, &sfep->name[sfep->namelen + 1]); } static void @@ -202,8 +198,7 @@ xfs_dir3_sfe_put_ino( struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino) { - xfs_dir2_sf_put_ino(hdr, - (xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino); + xfs_dir2_sf_put_ino(hdr, &sfep->name[sfep->namelen + 1], ino); } diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index a5f4d6e..f877bb1 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -208,22 +208,10 @@ typedef xfs_off_t xfs_dir2_off_t; */ typedef __uint32_t xfs_dir2_db_t; -/* - * Inode number stored as 8 8-bit values. - */ -typedef struct { __uint8_t i[8]; } xfs_dir2_ino8_t; - -/* - * Inode number stored as 4 8-bit values. - * Works a lot of the time, when all the inode numbers in a directory - * fit in 32 bits. - */ -typedef struct { __uint8_t i[4]; } xfs_dir2_ino4_t; +#define XFS_INO32_SIZE 4 +#define XFS_INO64_SIZE 8 +#define XFS_INO64_DIFF (XFS_INO64_SIZE - XFS_INO32_SIZE) -typedef union { - xfs_dir2_ino8_t i8; - xfs_dir2_ino4_t i4; -} xfs_dir2_inou_t; #define XFS_DIR2_MAX_SHORT_INUM ((xfs_ino_t)0xffffffffULL) /* @@ -240,7 +228,7 @@ typedef union { typedef struct xfs_dir2_sf_hdr { __uint8_t count; /* count of entries */ __uint8_t i8count; /* count of 8-byte inode #s */ - xfs_dir2_inou_t parent; /* parent dir inode number */ + __uint8_t parent[8]; /* parent dir inode number */ } __arch_pack xfs_dir2_sf_hdr_t; typedef struct xfs_dir2_sf_entry { @@ -251,16 +239,15 @@ typedef struct xfs_dir2_sf_entry { * A single byte containing the file type field follows the inode * number for version 3 directory entries. * - * A xfs_dir2_ino8_t or xfs_dir2_ino4_t follows here, at a - * variable offset after the name. + * A 64-bit or 32-bit inode number follows here, at a variable offset + * after the name. */ } xfs_dir2_sf_entry_t; static inline int xfs_dir2_sf_hdr_size(int i8count) { return sizeof(struct xfs_dir2_sf_hdr) - - (i8count == 0) * - (sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t)); + (i8count == 0) * XFS_INO64_DIFF; } static inline xfs_dir2_data_aoff_t diff --git a/fs/xfs/libxfs/xfs_dir2_sf.c b/fs/xfs/libxfs/xfs_dir2_sf.c index f8ccfd5a..c6809ff 100644 --- a/fs/xfs/libxfs/xfs_dir2_sf.c +++ b/fs/xfs/libxfs/xfs_dir2_sf.c @@ -130,8 +130,8 @@ xfs_dir2_block_sfsize( count * 3 * sizeof(u8) + /* namelen + offset */ namelen + /* name */ (i8count ? /* inumber */ - (uint)sizeof(xfs_dir2_ino8_t) * count : - (uint)sizeof(xfs_dir2_ino4_t) * count); + count * XFS_INO64_SIZE : + count * XFS_INO32_SIZE); if (size > XFS_IFORK_DSIZE(dp)) return size; /* size value is a failure */ } @@ -318,10 +318,7 @@ xfs_dir2_sf_addname( /* * Yes, adjust the inode size. old count + (parent + new) */ - incr_isize += - (sfp->count + 2) * - ((uint)sizeof(xfs_dir2_ino8_t) - - (uint)sizeof(xfs_dir2_ino4_t)); + incr_isize += (sfp->count + 2) * XFS_INO64_DIFF; objchange = 1; } @@ -896,11 +893,7 @@ xfs_dir2_sf_replace( int error; /* error return value */ int newsize; /* new inode size */ - newsize = - dp->i_df.if_bytes + - (sfp->count + 1) * - ((uint)sizeof(xfs_dir2_ino8_t) - - (uint)sizeof(xfs_dir2_ino4_t)); + newsize = dp->i_df.if_bytes + (sfp->count + 1) * XFS_INO64_DIFF; /* * Won't fit as shortform, convert to block then do replace. */ @@ -1021,10 +1014,7 @@ xfs_dir2_sf_toino4( /* * Compute the new inode size. */ - newsize = - oldsize - - (oldsfp->count + 1) * - ((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)); + newsize = oldsize - (oldsfp->count + 1) * XFS_INO64_DIFF; xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK); xfs_idata_realloc(dp, newsize, XFS_DATA_FORK); /* @@ -1097,10 +1087,7 @@ xfs_dir2_sf_toino8( /* * Compute the new inode size (nb: entry count + 1 for parent) */ - newsize = - oldsize + - (oldsfp->count + 1) * - ((uint)sizeof(xfs_dir2_ino8_t) - (uint)sizeof(xfs_dir2_ino4_t)); + newsize = oldsize + (oldsfp->count + 1) * XFS_INO64_DIFF; xfs_idata_realloc(dp, -oldsize, XFS_DATA_FORK); xfs_idata_realloc(dp, newsize, XFS_DATA_FORK); /* diff --git a/fs/xfs/xfs_ondisk.h b/fs/xfs/xfs_ondisk.h index 3cbc1f8..673a50b 100644 --- a/fs/xfs/xfs_ondisk.h +++ b/fs/xfs/xfs_ondisk.h @@ -104,9 +104,6 @@ xfs_check_ondisk_structs(void) XFS_CHECK_OFFSET(xfs_dir2_data_unused_t, length, 2); XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_hdr_t, 16); XFS_CHECK_STRUCT_SIZE(xfs_dir2_free_t, 16); - XFS_CHECK_STRUCT_SIZE(xfs_dir2_ino4_t, 4); - XFS_CHECK_STRUCT_SIZE(xfs_dir2_ino8_t, 8); - XFS_CHECK_STRUCT_SIZE(xfs_dir2_inou_t, 8); XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_entry_t, 8); XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_hdr_t, 16); XFS_CHECK_STRUCT_SIZE(xfs_dir2_leaf_t, 16); -- 2.1.4 From BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org Fri Jun 24 02:53:06 2016 Return-Path: <BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id A6BBC7CA4 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 02:53:06 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 6852B304039 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:53:03 -0700 (PDT) X-ASG-Debug-ID: 1466754781-04bdf074b73ee00001-NocioJ Received: from bombadil.infradead.org ([198.137.202.9]) by cuda.sgi.com with ESMTP id nWpddx8eUtYg1PVR (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 00:53:01 -0700 (PDT) X-Barracuda-Envelope-From: BATV+93f716a33c6b40cffcc2+4688+infradead.org+hch@bombadil.srs.infradead.org X-Barracuda-Effective-Source-IP: UNKNOWN[198.137.202.9] X-Barracuda-Apparent-Source-IP: 198.137.202.9 Received: from [91.114.64.3] (helo=localhost) by bombadil.infradead.org with esmtpsa (Exim 4.85_2 #1 (Red Hat Linux)) id 1bGLvA-0002rZ-GQ for xfs@oss.sgi.com; Fri, 24 Jun 2016 07:53:01 +0000 From: Christoph Hellwig <hch@lst.de> To: xfs@oss.sgi.com Subject: [PATCH 3/3] xfs: remove __arch_pack Date: Fri, 24 Jun 2016 09:52:47 +0200 X-ASG-Orig-Subj: [PATCH 3/3] xfs: remove __arch_pack Message-Id: <1466754767-10657-4-git-send-email-hch@lst.de> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1466754767-10657-1-git-send-email-hch@lst.de> References: <1466754767-10657-1-git-send-email-hch@lst.de> X-SRS-Rewrite: SMTP reverse-path rewritten from <hch@infradead.org> by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Barracuda-Connect: UNKNOWN[198.137.202.9] X-Barracuda-Start-Time: 1466754781 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1582 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30715 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Instead we always declare struct xfs_dir2_sf_hdr as packed. That's the expected layout, and while most major architectures do the packing by default the new structure size and offset checker showed that not only the ARM old ABI got this wrong, but various minor embedded architectures did as well. Signed-off-by: Christoph Hellwig <hch@lst.de> --- fs/xfs/libxfs/xfs_da_format.h | 2 +- fs/xfs/xfs_linux.h | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h index f877bb1..685f23b 100644 --- a/fs/xfs/libxfs/xfs_da_format.h +++ b/fs/xfs/libxfs/xfs_da_format.h @@ -229,7 +229,7 @@ typedef struct xfs_dir2_sf_hdr { __uint8_t count; /* count of entries */ __uint8_t i8count; /* count of 8-byte inode #s */ __uint8_t parent[8]; /* parent dir inode number */ -} __arch_pack xfs_dir2_sf_hdr_t; +} __packed xfs_dir2_sf_hdr_t; typedef struct xfs_dir2_sf_entry { __u8 namelen; /* actual name length */ diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h index a8192dc..b8d64d5 100644 --- a/fs/xfs/xfs_linux.h +++ b/fs/xfs/xfs_linux.h @@ -328,13 +328,6 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y) return x; } -/* ARM old ABI has some weird alignment/padding */ -#if defined(__arm__) && !defined(__ARM_EABI__) -#define __arch_pack __attribute__((packed)) -#else -#define __arch_pack -#endif - #define ASSERT_ALWAYS(expr) \ (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) -- 2.1.4 From dan.carpenter@oracle.com Fri Jun 24 07:22:55 2016 Return-Path: <dan.carpenter@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E49EA7CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 07:22:54 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4D24AAC003 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 05:22:51 -0700 (PDT) X-ASG-Debug-ID: 1466770968-04cbb0273616d520001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id YYizKLz3t1qQFZel (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 05:22:49 -0700 (PDT) X-Barracuda-Envelope-From: dan.carpenter@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5OCMjZY008517 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Jun 2016 12:22:45 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5OCMjrY026931 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Jun 2016 12:22:45 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5OCMiT4012567; Fri, 24 Jun 2016 12:22:44 GMT Received: from mwanda (/154.0.139.178) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 24 Jun 2016 05:22:43 -0700 Date: Fri, 24 Jun 2016 15:22:34 +0300 From: Dan Carpenter <dan.carpenter@oracle.com> To: Dave Chinner <david@fromorbit.com> Cc: xfs@oss.sgi.com, kernel-janitors@vger.kernel.org Subject: [patch] xfs: don't allow negative error tags Message-ID: <20160624122234.GA23169@mwanda> X-ASG-Orig-Subj: [patch] xfs: don't allow negative error tags MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.6.0 (2016-04-01) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1466770969 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1232 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30719 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines Errors go from zero which means no error to XFS_ERRTAG_MAX (22). My static checker complains that xfs_errortag_add() puts an upper bound on this but not a lower bound. Let's fix it by making it unsigned. Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index 4ed3042..2e4f67f 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h @@ -128,7 +128,7 @@ extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ (rf)))) -extern int xfs_errortag_add(int error_tag, struct xfs_mount *mp); +extern int xfs_errortag_add(unsigned int error_tag, struct xfs_mount *mp); extern int xfs_errortag_clearall(struct xfs_mount *mp, int loud); #else #define XFS_TEST_ERROR(expr, mp, tag, rf) (expr) diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 355619a..ed7ee4e 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c @@ -55,7 +55,7 @@ xfs_error_test(int error_tag, int *fsidp, char *expression, } int -xfs_errortag_add(int error_tag, xfs_mount_t *mp) +xfs_errortag_add(unsigned int error_tag, xfs_mount_t *mp) { int i; int len; From sandeen@sandeen.net Fri Jun 24 08:17:33 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id AD98F7CA1 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 08:17:33 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 80CD6304048 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:17:29 -0700 (PDT) X-ASG-Debug-ID: 1466774245-04cbb0273716fee0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id MKGZhmh2UJH9cDgv for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:17:25 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 31FDE541; Fri, 24 Jun 2016 08:17:25 -0500 (CDT) Subject: Re: xfs metadata overhead To: Danny Shavit <danny@zadarastorage.com>, xfs-oss <xfs@oss.sgi.com> X-ASG-Orig-Subj: Re: xfs metadata overhead References: <CAC=x_0jDYb17Vh97Led7XXDiUMcUTJbpJ2Dw45gn=D0_w0K5VQ@mail.gmail.com> <20160622225117.GX12670@dastard> <CAC=x_0hdvm7SSP8EOAdUwLa-k3a3p7p7CRj8tyCnEx=As7A6jw@mail.gmail.com> <71fbc905-ef05-126a-5c7f-c68c9018763c@sandeen.net> <CAC=x_0hnGQHAenv985+FusWxK_63AatB_XK_mqbAmyt=OxqYrg@mail.gmail.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <b920a8ec-6410-1daa-809c-04b48db24c0a@sandeen.net> Date: Fri, 24 Jun 2016 08:17:23 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <CAC=x_0hnGQHAenv985+FusWxK_63AatB_XK_mqbAmyt=OxqYrg@mail.gmail.com> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1466774245 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3493 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30720 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On 6/24/16 5:34 AM, Danny Shavit wrote: >> How do you determine allocated_size, with du? > yes via du >> How different? Can you show an example? > meta data file size= 5.6 GB (*6,089,374,208*) > > *df:* > Filesystem 1K-blocks Used Available Use% Mounted on > /dev/dm-39 2725683200 955900860 1769782340 36% /export/v1 = 978,842,480,640 bytes > > *du:* du -s /export/v1/ > 952825644 /export/v1/ = 975,693,459,456 bytes > 978,842,480,640 -975,693,459,456 = > > Metadata size according to calculation=*3,149,021,184* bytes Oh, right. I should have thought of this; "du" counts some metadata as well, i.e. a directory full of zero-length files still consumes space which is reported by du. so your 975,693,459,456 bytes is file data as well as some metadata. -Eric > > Thanks, > Danny > > On Thu, Jun 23, 2016 at 9:12 PM, Eric Sandeen <sandeen@sandeen.net <mailto:sandeen@sandeen.net>> wrote: > > On 6/23/16 10:04 AM, Danny Shavit wrote: > > I see. We will try this direction. > > BTW: I thought that good estimate would be "volume_size - > > allocated_size - free_space". But it produced quite a difference > > compared to metadata dump size. > > Is there a specific reason? > > How do you determine allocated_size, with du? > > How different? Can you show an example? > > -Eric > > > Thanks, > > Danny > > > > On Thu, Jun 23, 2016 at 1:51 AM, Dave Chinner <david@fromorbit.com <mailto:david@fromorbit.com> <mailto:david@fromorbit.com <mailto:david@fromorbit.com>>> wrote: > > > > On Wed, Jun 22, 2016 at 06:58:16PM +0300, Danny Shavit wrote: > > > Hi, > > > > > > We are looking for a method to estimate the size of metadata overhead for a > > > given file system. > > > We would like to use this value as indicator for the amount of cache memory > > > a system for faster operation. > > > Are there any counters that are maintained in the on-disk data > > > structures like free space for examples? > > > > No. > > > > Right now, you'll need to take a metadump of the filesystem to > > measure it. The size of the dump file will be a close indication of > > the amount of metadata in the filesystem as it only contains > > the filesystem metadata. > > > > In future, querying the rmap will enable us to calculate it on the > > fly, (i.e. not requiring the filesystem to be snapshotted/taken off > > line to do a metadump). > > > > Cheers, > > > > Dave. > > -- > > Dave Chinner > > david@fromorbit.com <mailto:david@fromorbit.com> <mailto:david@fromorbit.com <mailto:david@fromorbit.com>> > > > > > > > > > > -- > > Regards, > > Danny > > > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com <mailto:xfs@oss.sgi.com> > > http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com <mailto:xfs@oss.sgi.com> > http://oss.sgi.com/mailman/listinfo/xfs > > > > > -- > Regards, > Danny From danny@zadarastorage.com Fri Jun 24 08:21:45 2016 Return-Path: <danny@zadarastorage.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 816A17CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 08:21:45 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 53050304048 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:21:45 -0700 (PDT) X-ASG-Debug-ID: 1466774500-04cb6c063c139a10001-NocioJ Received: from mail-lf0-f52.google.com (mail-lf0-f52.google.com [209.85.215.52]) by cuda.sgi.com with ESMTP id beA4jT08ENNU3uKR (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:21:41 -0700 (PDT) X-Barracuda-Envelope-From: danny@zadarastorage.com X-Barracuda-Effective-Source-IP: mail-lf0-f52.google.com[209.85.215.52] X-Barracuda-Apparent-Source-IP: 209.85.215.52 Received: by mail-lf0-f52.google.com with SMTP id h129so116172601lfh.1 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:21:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zadarastorage-com.20150623.gappssmtp.com; s=20150623; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=udOnRoJe4YMttQUznIDIBwH3HGnRk9zna3Em5WC8jUk=; b=u2fxi/yBmSfnUFlkJ9SB8ocPINHRd0yRbENGxvUjgyvKMaV4qjirnKdAecE7YQTIZq Osx46imqS0LrjG5rbb958hiaEKpKzX137fhbq0xsHd8eG+hNW+FcGRNLoMFc+qNixVeS xqj6prfIiekok0aEPpIoThr7x8e+4LaCd0vJD7xzNEe/hTgL0ph6DO88qojHX49z4ymC bvkd/w4EYGWLMrqxr0HPJLfxYEJTe8qvemwvC/G8a83LmkHPPjaYMv3oz+QQcWHN8pT+ /T+6zg/sGj28Bx+jHe9YN223tz8TZrb0IyygZ3Sd2bg+OCppw1T5dXkcE6gq7ALTs4HN Yyrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=udOnRoJe4YMttQUznIDIBwH3HGnRk9zna3Em5WC8jUk=; b=DBvDFsYpDR4vtZVFE9amD4ija3YA1BS5fCzHyHUHoPoTPdJUrwRor61p1hNG3epKfo L8c01ta+riMmgUELzoZ9jjzZwSG6yBnWoGzN5AI9Dz9REeAViW2KmruLY46GGV3nG7Mc OZ39g03O3aJPld4dVUlZiK2ARhYPXoiCHKaW9jckBXhdMEUxU0gocCu+X8dYgjr3Jhsx +T0PH2ELLYceqZXYpPCgNy+65Se9DPNkoBSXGdecF1hjouR67d1QtCvssGE+FdZih0J7 nDbND3H2OgSqpm4SFZdMJkfop60KBGuNpDPYzPPkNVJHwQg32tOALwCsG7JyIe6Ap4ds NmKQ== X-Gm-Message-State: ALyK8tL/Gpsu57fpMfJMROXU3j1/GdoyQRjsLfTYRNZqOKbDt2cXJazRGHOhQMEDYSCWAAR5J1TS7Vu+vI27FQ== X-Received: by 10.25.89.5 with SMTP id n5mr1384948lfb.89.1466774500116; Fri, 24 Jun 2016 06:21:40 -0700 (PDT) MIME-Version: 1.0 Received: by 10.114.5.37 with HTTP; Fri, 24 Jun 2016 06:21:39 -0700 (PDT) In-Reply-To: <b920a8ec-6410-1daa-809c-04b48db24c0a@sandeen.net> References: <CAC=x_0jDYb17Vh97Led7XXDiUMcUTJbpJ2Dw45gn=D0_w0K5VQ@mail.gmail.com> <20160622225117.GX12670@dastard> <CAC=x_0hdvm7SSP8EOAdUwLa-k3a3p7p7CRj8tyCnEx=As7A6jw@mail.gmail.com> <71fbc905-ef05-126a-5c7f-c68c9018763c@sandeen.net> <CAC=x_0hnGQHAenv985+FusWxK_63AatB_XK_mqbAmyt=OxqYrg@mail.gmail.com> <b920a8ec-6410-1daa-809c-04b48db24c0a@sandeen.net> From: Danny Shavit <danny@zadarastorage.com> Date: Fri, 24 Jun 2016 16:21:39 +0300 Message-ID: <CAC=x_0g_iktOKOKiRF5Ku7N-PSbCXOR+Amhm577YjNYQaRPjeA@mail.gmail.com> Subject: Re: xfs metadata overhead To: Eric Sandeen <sandeen@sandeen.net> X-ASG-Orig-Subj: Re: xfs metadata overhead Cc: xfs-oss <xfs@oss.sgi.com> Content-Type: multipart/alternative; boundary=001a114172ec0b9d7c0536060db0 X-Barracuda-Connect: mail-lf0-f52.google.com[209.85.215.52] X-Barracuda-Start-Time: 1466774501 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10200 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30720 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --001a114172ec0b9d7c0536060db0 Content-Type: text/plain; charset=UTF-8 I see. So using bulk_stat ioctl in similar way to xfs_fsr and summing allocated size will result with more accurate number? Thanks, Danny On Fri, Jun 24, 2016 at 4:17 PM, Eric Sandeen <sandeen@sandeen.net> wrote: > On 6/24/16 5:34 AM, Danny Shavit wrote: > >> How do you determine allocated_size, with du? > > yes via du > >> How different? Can you show an example? > > meta data file size= 5.6 GB (*6,089,374,208*) > > > > *df:* > > Filesystem 1K-blocks Used Available Use% > Mounted on > > /dev/dm-39 2725683200 955900860 1769782340 36% > /export/v1 = 978,842,480,640 bytes > > > > *du:* du -s /export/v1/ > > 952825644 /export/v1/ = 975,693,459,456 bytes > > 978,842,480,640 -975,693,459,456 = > > > > Metadata size according to calculation=*3,149,021,184* bytes > > Oh, right. I should have thought of this; "du" counts some metadata as > well, i.e. a directory full of zero-length files still consumes space > which is reported by du. > > so your 975,693,459,456 bytes is file data as well as some metadata. > > -Eric > > > > > Thanks, > > Danny > > > > On Thu, Jun 23, 2016 at 9:12 PM, Eric Sandeen <sandeen@sandeen.net > <mailto:sandeen@sandeen.net>> wrote: > > > > On 6/23/16 10:04 AM, Danny Shavit wrote: > > > I see. We will try this direction. > > > BTW: I thought that good estimate would be "volume_size - > > > allocated_size - free_space". But it produced quite a difference > > > compared to metadata dump size. > > > Is there a specific reason? > > > > How do you determine allocated_size, with du? > > > > How different? Can you show an example? > > > > -Eric > > > > > Thanks, > > > Danny > > > > > > On Thu, Jun 23, 2016 at 1:51 AM, Dave Chinner <david@fromorbit.com > <mailto:david@fromorbit.com> <mailto:david@fromorbit.com <mailto: > david@fromorbit.com>>> wrote: > > > > > > On Wed, Jun 22, 2016 at 06:58:16PM +0300, Danny Shavit wrote: > > > > Hi, > > > > > > > > We are looking for a method to estimate the size of metadata > overhead for a > > > > given file system. > > > > We would like to use this value as indicator for the amount > of cache memory > > > > a system for faster operation. > > > > Are there any counters that are maintained in the on-disk > data > > > > structures like free space for examples? > > > > > > No. > > > > > > Right now, you'll need to take a metadump of the filesystem to > > > measure it. The size of the dump file will be a close > indication of > > > the amount of metadata in the filesystem as it only contains > > > the filesystem metadata. > > > > > > In future, querying the rmap will enable us to calculate it on > the > > > fly, (i.e. not requiring the filesystem to be > snapshotted/taken off > > > line to do a metadump). > > > > > > Cheers, > > > > > > Dave. > > > -- > > > Dave Chinner > > > david@fromorbit.com <mailto:david@fromorbit.com> <mailto: > david@fromorbit.com <mailto:david@fromorbit.com>> > > > > > > > > > > > > > > > -- > > > Regards, > > > Danny > > > > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com <mailto:xfs@oss.sgi.com> > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com <mailto:xfs@oss.sgi.com> > > http://oss.sgi.com/mailman/listinfo/xfs > > > > > > > > > > -- > > Regards, > > Danny > -- Regards, Danny --001a114172ec0b9d7c0536060db0 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable <div dir=3D"ltr">I see.<div>So using bulk_stat ioctl in similar way to xfs_= fsr and summing allocated size will result with =C2=A0more accurate number?= </div><div><br></div><div>Thanks,</div><div>Danny</div></div><div class=3D"= gmail_extra"><br><div class=3D"gmail_quote">On Fri, Jun 24, 2016 at 4:17 PM= , Eric Sandeen <span dir=3D"ltr"><<a href=3D"mailto:sandeen@sandeen.net"= target=3D"_blank">sandeen@sandeen.net</a>></span> wrote:<br><blockquote= class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc soli= d;padding-left:1ex"><span class=3D"">On 6/24/16 5:34 AM, Danny Shavit wrote= :<br> >> How do you determine allocated_size, with du?<br> > yes via du<br> >> How different?=C2=A0 Can you show an example?<br> </span>> meta data file size=3D 5.6 GB (*6,089,374,208*)<br> ><br> > *df:*<br> <span class=3D"">> Filesystem=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A01K-blocks=C2=A0 =C2=A0 =C2=A0 =C2=A0Used=C2=A0 A= vailable Use% Mounted on<br> > /dev/dm-39=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 <a href=3D"tel:2725683200" value=3D"+12725683200">2725683200</a>=C2=A0 = 955900860 1769782340=C2=A0 36% /export/v1=C2=A0 =C2=A0 =C2=A0=3D 978,842,48= 0,640 bytes<br> ><br> </span>> *du:*=C2=A0 du -s /export/v1/<br> <span class=3D"">> 952825644=C2=A0 =C2=A0 =C2=A0 =C2=A0/export/v1/=C2=A0= =C2=A0 =C2=A0=3D 975,693,459,456 bytes<br> > 978,842,480,640 -975,693,459,456=C2=A0 =3D<br> ><br> </span>> Metadata size according to calculation=3D*3,149,021,184* bytes<= br> <br> Oh, right.=C2=A0 I should have thought of this; "du" counts some = metadata as<br> well, i.e. a directory full of zero-length files still consumes space<br> which is reported by du.<br> <br> so your 975,693,459,456 bytes is file data as well as some metadata.<br> <br> -Eric<br> <br> ><br> > Thanks,<br> > Danny<br> <span class=3D"">><br> > On Thu, Jun 23, 2016 at 9:12 PM, Eric Sandeen <<a href=3D"mailto:sa= ndeen@sandeen.net">sandeen@sandeen.net</a> <mailto:<a href=3D"mailto:san= deen@sandeen.net">sandeen@sandeen.net</a>>> wrote:<br> ><br> >=C2=A0 =C2=A0 =C2=A0On 6/23/16 10:04 AM, Danny Shavit wrote:<br> >=C2=A0 =C2=A0 =C2=A0> I see. We will try this direction.<br> >=C2=A0 =C2=A0 =C2=A0> BTW: I thought that good estimate would be &qu= ot;volume_size -<br> >=C2=A0 =C2=A0 =C2=A0> allocated_size - free_space". But it prod= uced quite a difference<br> >=C2=A0 =C2=A0 =C2=A0> compared to metadata dump size.<br> >=C2=A0 =C2=A0 =C2=A0> Is there a specific reason?<br> ><br> >=C2=A0 =C2=A0 =C2=A0How do you determine allocated_size, with du?<br> ><br> >=C2=A0 =C2=A0 =C2=A0How different?=C2=A0 Can you show an example?<br> ><br> >=C2=A0 =C2=A0 =C2=A0-Eric<br> ><br> >=C2=A0 =C2=A0 =C2=A0> Thanks,<br> >=C2=A0 =C2=A0 =C2=A0> Danny<br> >=C2=A0 =C2=A0 =C2=A0><br> </span><span class=3D"">>=C2=A0 =C2=A0 =C2=A0> On Thu, Jun 23, 2016 a= t 1:51 AM, Dave Chinner <<a href=3D"mailto:david@fromorbit.com">david@fr= omorbit.com</a> <mailto:<a href=3D"mailto:david@fromorbit.com">david@fro= morbit.com</a>> <mailto:<a href=3D"mailto:david@fromorbit.com">david@= fromorbit.com</a> <mailto:<a href=3D"mailto:david@fromorbit.com">david@f= romorbit.com</a>>>> wrote:<br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0On Wed, Jun 22, 2016 at 06:= 58:16PM +0300, Danny Shavit wrote:<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0> Hi,<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0> We are looking for a m= ethod to estimate the size of metadata overhead for a<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0> given file system.<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0> We would like to use t= his value as indicator for the amount of cache memory<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0> a system for faster op= eration.<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0> Are there any counters= that are maintained in the on-disk data<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0> structures like free s= pace for examples?<br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0No.<br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0Right now, you'll need = to take a metadump of the filesystem to<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0measure it. The size of the= dump file will be a close indication of<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0the amount of metadata in t= he filesystem as it only contains<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0the filesystem metadata.<br= > >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0In future, querying the rma= p will enable us to calculate it on the<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0fly, (i.e. not requiring th= e filesystem to be snapshotted/taken off<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0line to do a metadump).<br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0Cheers,<br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0Dave.<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0--<br> >=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0Dave Chinner<br> </span>>=C2=A0 =C2=A0 =C2=A0>=C2=A0 =C2=A0 =C2=A0<a href=3D"mailto:da= vid@fromorbit.com">david@fromorbit.com</a> <mailto:<a href=3D"mailto:dav= id@fromorbit.com">david@fromorbit.com</a>> <mailto:<a href=3D"mailto:= david@fromorbit.com">david@fromorbit.com</a> <mailto:<a href=3D"mailto:d= avid@fromorbit.com">david@fromorbit.com</a>>><br> <span class=3D"">>=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0> --<br> >=C2=A0 =C2=A0 =C2=A0> Regards,<br> >=C2=A0 =C2=A0 =C2=A0> Danny<br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0><br> >=C2=A0 =C2=A0 =C2=A0> ______________________________________________= _<br> >=C2=A0 =C2=A0 =C2=A0> xfs mailing list<br> </span>>=C2=A0 =C2=A0 =C2=A0> <a href=3D"mailto:xfs@oss.sgi.com">xfs@= oss.sgi.com</a> <mailto:<a href=3D"mailto:xfs@oss.sgi.com">xfs@oss.sgi.c= om</a>><br> <span class=3D"">>=C2=A0 =C2=A0 =C2=A0> <a href=3D"http://oss.sgi.com= /mailman/listinfo/xfs" rel=3D"noreferrer" target=3D"_blank">http://oss.sgi.= com/mailman/listinfo/xfs</a><br> >=C2=A0 =C2=A0 =C2=A0><br> ><br> >=C2=A0 =C2=A0 =C2=A0_______________________________________________<br> >=C2=A0 =C2=A0 =C2=A0xfs mailing list<br> </span>>=C2=A0 =C2=A0 =C2=A0<a href=3D"mailto:xfs@oss.sgi.com">xfs@oss.s= gi.com</a> <mailto:<a href=3D"mailto:xfs@oss.sgi.com">xfs@oss.sgi.com</a= >><br> <div class=3D"HOEnZb"><div class=3D"h5">>=C2=A0 =C2=A0 =C2=A0<a href=3D"= http://oss.sgi.com/mailman/listinfo/xfs" rel=3D"noreferrer" target=3D"_blan= k">http://oss.sgi.com/mailman/listinfo/xfs</a><br> ><br> ><br> ><br> ><br> > --<br> > Regards,<br> > Danny<br> </div></div></blockquote></div><br><br clear=3D"all"><div><br></div>-- <br>= <div class=3D"gmail_signature" data-smartmail=3D"gmail_signature"><div dir= =3D"ltr"><div>Regards,<br></div>Danny<br></div></div> </div> --001a114172ec0b9d7c0536060db0-- From dan.carpenter@oracle.com Fri Jun 24 08:28:08 2016 Return-Path: <dan.carpenter@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B5EA27CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 08:28:08 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 1E555AC005 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:28:04 -0700 (PDT) X-ASG-Debug-ID: 1466774882-04cb6c063f139cc0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id 8gvTRTkguPpFLzJD (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:28:03 -0700 (PDT) X-Barracuda-Envelope-From: dan.carpenter@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5ODRtLP028937 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Jun 2016 13:27:56 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5ODRtFX018087 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 24 Jun 2016 13:27:55 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5ODRs1b020506; Fri, 24 Jun 2016 13:27:54 GMT Received: from mwanda (/154.0.139.178) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Fri, 24 Jun 2016 06:27:53 -0700 Date: Fri, 24 Jun 2016 16:27:49 +0300 From: Dan Carpenter <dan.carpenter@oracle.com> To: Jeff Liu <jeff.liu@easystack.cn> Cc: Dave Chinner <david@fromorbit.com>, kernel-janitors@vger.kernel.org, xfs@oss.sgi.com Subject: Re: [patch] xfs: don't allow negative error tags Message-ID: <20160624132749.GP32247@mwanda> X-ASG-Orig-Subj: Re: [patch] xfs: don't allow negative error tags References: <20160624122234.GA23169@mwanda> <576D31B9.8010908@easystack.cn> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <576D31B9.8010908@easystack.cn> User-Agent: Mutt/1.5.21 (2010-09-15) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1466774882 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 568 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30720 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 24, 2016 at 09:12:25PM +0800, Jeff Liu wrote: > Hi Dan, > > xfs_errortag_add() is called by xfs_file_ioctl(), which accept the 1st > argument as signed, i.e, > > typedef struct xfs_error_injection { > __s32 fd; > __s32 errtag; > } xfs_error_injection_t; > > Should we make it happy as well? Also, the typedef can be converted to > to struct xfs_error_injection by removing the depreciated > xfs_error_injection_t > syntax if so. That has been the user interface for a while so I didn't want to change it. regards, dan carpenter From damien.gombault@recia.fr Fri Jun 24 08:52:02 2016 Return-Path: <damien.gombault@recia.fr> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id DA7397CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 08:52:02 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4526FAC006 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:52:02 -0700 (PDT) X-ASG-Debug-ID: 1466776318-04cb6c063d13a7e0001-NocioJ Received: from mx.recia.fr (mx.recia.fr [95.128.41.47]) by cuda.sgi.com with ESMTP id KkxvRfmxDAccTXLE (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 06:51:59 -0700 (PDT) X-Barracuda-Envelope-From: damien.gombault@recia.fr X-Barracuda-Effective-Source-IP: mx.recia.fr[95.128.41.47] X-Barracuda-Apparent-Source-IP: 95.128.41.47 Received: from e6530-damien.recia.fr (unknown [37.58.188.254]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: F12A086p) by mx.recia.fr (Postfix) with ESMTPSA id E9E76226278; Fri, 24 Jun 2016 15:51:57 +0200 (CEST) Subject: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed To: Dave Chinner <david@fromorbit.com> X-ASG-Orig-Subj: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed References: <a08ae222-7654-4a6f-d9ba-f70017784f74@recia.fr> <20160622220959.GV12670@dastard> <20160622222328.GW12670@dastard> <20160623014217.GZ12670@dastard> Cc: xfs@oss.sgi.com From: Damien Gombault <damien.gombault@recia.fr> Organization: GIP Recia Message-ID: <eacabe85-cdff-7fbc-8bb6-c8eb51fc0dac@recia.fr> Date: Fri, 24 Jun 2016 15:51:57 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160623014217.GZ12670@dastard> Content-Type: multipart/mixed; boundary="------------02BA962CC061415C1E234270" X-Barracuda-Connect: mx.recia.fr[95.128.41.47] X-Barracuda-Start-Time: 1466776319 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3318 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30721 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header This is a multi-part message in MIME format. --------------02BA962CC061415C1E234270 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Hi. Thank you for the patch. The patch fixes simple cases (like my reproducer) but it does not fix restoration of more complex directory structures : I have tested the patch on my real data, it fixes some but not all warnings (a user renamed/moved a lots of files and directory between the 2 dumps). Here is another testcase which fails (with the patch) : mkdir dira mkdir dira/dirc touch dira/dirc/filea mkdir dirb . ├── dira │ └── dirc │ └── filea └── dirb Make a level 0 dump. mv dirb dira/dirB mv dira/dirc/ dira/dirB/dirC touch dira/dirB/dirC/fileb . └── dira └── dirB └── dirC ├── filea └── fileb Make a level 1 dump. Restore level 0 then level 1 dump, you will get : xfsrestore: directory post-processing xfsrestore: WARNING: unable to set secure extended attribute for dira/dirB: No such file or directory (2) xfsrestore: restoring non-directory files xfsrestore: WARNING: open of dira/dirB/dirC/fileb failed: No such file or directory: discarding ino 524386 xfsrestore: WARNING: unable to set secure extended attribute for dira/dirB/dirC/fileb: No such file or directory (2) xfsrestore: WARNING: path_to_handle of dira/dirB/dirC failed:No such file or directory xfsrestore: could not set access and modification times of dira/dirB/dirC: No such file or directory xfsrestore: chown (uid=0, gid=0) dira/dirB/dirC failed: No such file or directory xfsrestore: chmod dira/dirB/dirC failed: No such file or directory xfsrestore: WARNING: attempt to set extended attributes (xflags 0x80000000, extsize = 0x0, projid = 0x0) of dira/dirB/dirC failed: Bad file descriptor xfsrestore: WARNING: path_to_handle of dira/dirB failed:No such file or directory xfsrestore: could not set access and modification times of dira/dirB: No such file or directory xfsrestore: chown (uid=0, gid=0) dira/dirB failed: No such file or directory xfsrestore: chmod dira/dirB failed: No such file or directory xfsrestore: WARNING: attempt to set extended attributes (xflags 0x80000000, extsize = 0x0, projid = 0x0) of dira/dirB failed: Bad file descriptor xfsrestore: WARNING: unable to rmdir /mnt/test//orphanage: Directory not empty Directory dirB is placed in orphanage folder and fileb is not restored : . ├── dira ├── orphanage │ └── 1069152.734839917 │ └── dirC │ └── filea └── xfsrestorehousekeepingdir ├── dirattr ├── dirextattr ├── namreg ├── state └── tree -- Damien Gombault Le 23/06/2016 à 03:42, Dave Chinner a écrit : > On Thu, Jun 23, 2016 at 08:23:28AM +1000, Dave Chinner wrote: >> On Thu, Jun 23, 2016 at 08:09:59AM +1000, Dave Chinner wrote: >>> But it seems that dirb hasn't been created before the file in it >>> is being restored. THis can happen because the inventory is not >>> correct, whichmay in fact be a problem with dump rather than >>> restore... >>> >>> I'll have a bit of a play around here, see if I can reproduce it. >> Yes, i can reproduce it, so I'll have a deeper look. > Can you try this patch? > > -Dave --------------02BA962CC061415C1E234270 Content-Type: text/x-vcard; charset=utf-8; name="damien_gombault.vcf" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="damien_gombault.vcf" begin:vcard fn:Damien Gombault n:Gombault;Damien org;quoted-printable:GIP Recia =E2=88=92 Centre de ressources r=C3=A9gional du num=C3=A9rique adr;quoted-printable;dom:Parc d'Activit=C3=A9s les Aulnaies;;151, Rue de la Juine;Olivet;;45160 email;internet:damien.gombault@recia.fr title;quoted-printable:Responsable des syst=C3=A8mes informatiques tel;work:02 38 42 14 71 tel;cell:06 42 62 78 19 url:http://recia.fr version:2.1 end:vcard --------------02BA962CC061415C1E234270-- From sandeen@sandeen.net Fri Jun 24 09:55:44 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id CFEE77CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 09:55:44 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id A32BB8F8037 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 07:55:43 -0700 (PDT) X-ASG-Debug-ID: 1466780137-04cbb02735177f10001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id WmEwPgbf27Cmoq7i for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 07:55:37 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id CDCED541 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 09:55:37 -0500 (CDT) Subject: Re: [PATCH 3/3] xfs: remove __arch_pack To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH 3/3] xfs: remove __arch_pack References: <1466754767-10657-1-git-send-email-hch@lst.de> <1466754767-10657-4-git-send-email-hch@lst.de> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <478743f8-774f-d363-2e3e-40cd0963d8a1@sandeen.net> Date: Fri, 24 Jun 2016 09:55:37 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <1466754767-10657-4-git-send-email-hch@lst.de> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1466780137 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2374 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-BRTS-Evidence: digitalvampire.org X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30722 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/24/16 2:52 AM, Christoph Hellwig wrote: > Instead we always declare struct xfs_dir2_sf_hdr as packed. That's > the expected layout, and while most major architectures do the packing > by default the new structure size and offset checker showed that not > only the ARM old ABI got this wrong, but various minor embedded > architectures did as well. > > Signed-off-by: Christoph Hellwig <hch@lst.de> > --- > fs/xfs/libxfs/xfs_da_format.h | 2 +- > fs/xfs/xfs_linux.h | 7 ------- > 2 files changed, 1 insertion(+), 8 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_da_format.h b/fs/xfs/libxfs/xfs_da_format.h > index f877bb1..685f23b 100644 > --- a/fs/xfs/libxfs/xfs_da_format.h > +++ b/fs/xfs/libxfs/xfs_da_format.h > @@ -229,7 +229,7 @@ typedef struct xfs_dir2_sf_hdr { > __uint8_t count; /* count of entries */ > __uint8_t i8count; /* count of 8-byte inode #s */ > __uint8_t parent[8]; /* parent dir inode number */ > -} __arch_pack xfs_dir2_sf_hdr_t; > +} __packed xfs_dir2_sf_hdr_t; The reason I did this in the first place was a vague notion that unconditional packing was harmful. http://digitalvampire.org/blog/index.php/2006/07/31/why-you-shouldnt-use-__attribute__packed/ "However, it's actively harmful to add the attribute to a structure that's already going to be laid out with no padding." ... "gcc gets scared about unaligned accesses and generates six times as much code (96 bytes vs. 16 bytes)! sparc64 goes similarly crazy, bloating from 12 bytes to 52 bytes" I don't know if that's (still) correct or not, but that was the reason for the selective __pack application way back when. Might be worth investigating? -Eric > typedef struct xfs_dir2_sf_entry { > __u8 namelen; /* actual name length */ > diff --git a/fs/xfs/xfs_linux.h b/fs/xfs/xfs_linux.h > index a8192dc..b8d64d5 100644 > --- a/fs/xfs/xfs_linux.h > +++ b/fs/xfs/xfs_linux.h > @@ -328,13 +328,6 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y) > return x; > } > > -/* ARM old ABI has some weird alignment/padding */ > -#if defined(__arm__) && !defined(__ARM_EABI__) > -#define __arch_pack __attribute__((packed)) > -#else > -#define __arch_pack > -#endif > - > #define ASSERT_ALWAYS(expr) \ > (unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) > > From Brady.Chang@emc.com Fri Jun 24 13:10:59 2016 Return-Path: <Brady.Chang@emc.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 645337CA2 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 13:10:59 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id C4849AC002 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 11:10:55 -0700 (PDT) X-ASG-Debug-ID: 1466791852-04cbb02736184330001-NocioJ Received: from mailuogwdur.emc.com (mailuogwdur.emc.com [128.221.224.79]) by cuda.sgi.com with ESMTP id O2eXU5GBrtFWT7a3 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 11:10:53 -0700 (PDT) X-Barracuda-Envelope-From: Brady.Chang@emc.com X-Barracuda-Effective-Source-IP: mailuogwdur.emc.com[128.221.224.79] X-Barracuda-Apparent-Source-IP: 128.221.224.79 Received: from maildlpprd53.lss.emc.com (maildlpprd53.lss.emc.com [10.106.48.157]) by mailuogwprd51.lss.emc.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.0) with ESMTP id u5OIAqxD001814 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 14:10:52 -0400 X-DKIM: OpenDKIM Filter v2.4.3 mailuogwprd51.lss.emc.com u5OIAqxD001814 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=emc.com; s=jan2013; t=1466791852; bh=V1YKsiZ//vsELRqOBoXR3oGRpRc=; h=From:To:Subject:Date:Message-ID:Content-Type:MIME-Version; b=QdaIF8JmCQe7pzyLjs2oePgPVB1eZMq0g3/jIhVp/2wqICy4U9GiEZamB8LtXBj2u WrkllxMFpSWb5gjMPqnG9UNzkmzm6KxU9nR3sZMbdnv5ouNgrRSJgl7PVpSW7GMUnZ QQP18ZzdRLV9R84JXfhx5s9J1JrwOSIpm+MwXhwI= X-DKIM: OpenDKIM Filter v2.4.3 mailuogwprd51.lss.emc.com u5OIAqxD001814 Received: from mailusrhubprd54.lss.emc.com (mailusrhubprd54.lss.emc.com [10.106.48.19]) by maildlpprd53.lss.emc.com (RSA Interceptor) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 14:10:29 -0400 Received: from MXHUB201.corp.emc.com (MXHUB201.corp.emc.com [10.253.68.27]) by mailusrhubprd54.lss.emc.com (Sentrion-MTA-4.3.1/Sentrion-MTA-4.3.0) with ESMTP id u5OIAef9005505 (version=TLSv1.2 cipher=AES128-SHA256 bits=128 verify=FAIL) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 14:10:40 -0400 Received: from MX103CL01.corp.emc.com ([169.254.5.160]) by MXHUB201.corp.emc.com ([10.253.68.27]) with mapi id 14.03.0266.001; Fri, 24 Jun 2016 14:10:39 -0400 From: "Chang, Brady" <Brady.Chang@emc.com> To: "xfs@oss.sgi.com" <xfs@oss.sgi.com> Subject: xfs_irecover question Thread-Topic: xfs_irecover question X-ASG-Orig-Subj: xfs_irecover question Thread-Index: AQHRzkO2lZ7msQqsUkqzWKg+CBiOvQ== Date: Fri, 24 Jun 2016 18:10:38 +0000 Message-ID: <D392E1CC.3E982%brady.chang@emc.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: user-agent: Microsoft-MacOutlook/14.6.4.160422 x-originating-ip: [10.97.69.140] Content-Type: multipart/alternative; boundary="_000_D392E1CC3E982bradychangemccom_" MIME-Version: 1.0 X-Sentrion-Hostname: mailusrhubprd54.lss.emc.com X-RSA-Classifications: public X-Barracuda-Connect: mailuogwdur.emc.com[128.221.224.79] X-Barracuda-Start-Time: 1466791852 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1083 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30727 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message --_000_D392E1CC3E982bradychangemccom_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi, Is there a way to find fullpath to the file generated by xfs_irecover ? For example: [root@sdw2 recover]# ls -l 532946 -rw------- 1 root root 33461216 Jun 23 21:07 532946 [root@sdw2 recover]# file 532946 532946: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs) Thanks -Brady --_000_D392E1CC3E982bradychangemccom_ Content-Type: text/html; charset="us-ascii" Content-ID: <EC42135312078B499F250DD64A3FFB0F@mail.corp.emc.com> Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dus-ascii"= > </head> <body style=3D"word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-lin= e-break: after-white-space; color: rgb(0, 0, 0); font-size: 14px; font-fami= ly: Calibri, sans-serif; "> <div>Hi,</div> <div>Is there a way to find fullpath to the  file generated by  x= fs_irecover ?</div> <div> <div><br> </div> <div>For example:</div> <div>[root@sdw2 recover]# ls -l 532946</div> <div>-rw------- 1 root root 33461216 Jun 23 21:07 532946</div> <div>[root@sdw2 recover]# file 532946</div> <div>532946: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs)</div> </div> <div><br> </div> <div>Thanks</div> <div>-Brady</div> <div><br> </div> <br> </body> </html> --_000_D392E1CC3E982bradychangemccom_-- From sandeen@redhat.com Fri Jun 24 16:25:02 2016 Return-Path: <sandeen@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 7F8F47CA2 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 16:25:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id F2B1AAC002 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 14:25:01 -0700 (PDT) X-ASG-Debug-ID: 1466803500-04bdf074b56e010001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id xtXEfRsKZEBWrxsA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 14:25:01 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 91827C049D58 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 21:25:00 +0000 (UTC) Received: from [IPv6:::1] (ovpn03.gateway.prod.ext.phx2.redhat.com [10.5.9.3]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5OLOwxd014658 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 24 Jun 2016 17:25:00 -0400 To: xfs-oss <xfs@oss.sgi.com> From: Eric Sandeen <sandeen@redhat.com> Subject: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Cc: Eryu Guan <eguan@redhat.com> X-ASG-Orig-Subj: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Message-ID: <13dd3974-956d-c3af-86ed-f6ce5cc1b996@redhat.com> Date: Fri, 24 Jun 2016 16:24:58 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Fri, 24 Jun 2016 21:25:00 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466803500 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2961 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 kernel commit 5ef828c4 xfs: avoid false quotacheck after unclean shutdown made xfs_sb_from_disk() also call xfs_sb_quota_from_disk by default. However, when this was merged to libxfs, existing separate calls to libxfs_sb_quota_from_disk remained, and calling it twice in a row on a V4 superblock leads to issues, because: if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { ... sbp->sb_pquotino = sbp->sb_gquotino; sbp->sb_gquotino = NULLFSINO; and after the second call, we have set both pquotino and gquotino to NULLFSINO. Fix this by making it safe to call twice, and also remove the extra calls to libxfs_sb_quota_from_disk. This is only spotted when running xfstests with "-m crc=0" because the sb_from_disk change came about after V5 became default, and the above behavior only exists on a V4 superblock. Reported-by: Eryu Guan <eguan@redhat.com> Signed-off-by: Eric Sandeen <sandeen@redhat.com> --- diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c index 45db6ae..44f3e3e 100644 --- a/libxfs/xfs_sb.c +++ b/libxfs/xfs_sb.c @@ -316,13 +316,16 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); - if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { + if (sbp->sb_qflags & XFS_PQUOTA_ACCT && + sbp->sb_gquotino != NULLFSINO) { /* * In older version of superblock, on-disk superblock only * has sb_gquotino, and in-core superblock has both sb_gquotino * and sb_pquotino. But, only one of them is supported at any * point of time. So, if PQUOTA is set in disk superblock, - * copy over sb_gquotino to sb_pquotino. + * copy over sb_gquotino to sb_pquotino. The NULLFSINO test + * above is to make sure we don't do this twice and wipe them + * both out! */ sbp->sb_pquotino = sbp->sb_gquotino; sbp->sb_gquotino = NULLFSINO; diff --git a/repair/sb.c b/repair/sb.c index 3965953..8087242 100644 --- a/repair/sb.c +++ b/repair/sb.c @@ -155,7 +155,6 @@ __find_secondary_sb( for (i = 0; !done && i < bsize; i += BBSIZE) { c_bufsb = (char *)sb + i; libxfs_sb_from_disk(&bufsb, (xfs_dsb_t *)c_bufsb); - libxfs_sb_quota_from_disk(&bufsb); if (verify_sb(c_bufsb, &bufsb, 0) != XR_OK) continue; @@ -568,7 +567,6 @@ get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno) do_error("%s\n", strerror(error)); } libxfs_sb_from_disk(sbp, buf); - libxfs_sb_quota_from_disk(sbp); rval = verify_sb((char *)buf, sbp, agno == 0); free(buf); diff --git a/repair/scan.c b/repair/scan.c index 964ff06..366ce16 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1622,7 +1622,6 @@ scan_ag( goto out_free_sb; } libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbbuf)); - libxfs_sb_quota_from_disk(sb); agfbuf = libxfs_readbuf(mp->m_dev, XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), From sandeen@sandeen.net Fri Jun 24 17:37:14 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6E72E7CA2 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 17:37:14 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 31C388F8037 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 15:37:14 -0700 (PDT) X-ASG-Debug-ID: 1466807831-04cb6c063e152720001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id qDxmj5BBsyEFQngQ for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 15:37:12 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 8D439541 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 17:37:11 -0500 (CDT) Subject: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) References: <20160304112354.GX11419@eguan.usersys.redhat.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <727b405b-7df2-641a-d4d0-24333e003374@sandeen.net> Date: Fri, 24 Jun 2016 17:37:10 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160304112354.GX11419@eguan.usersys.redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1466807831 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1563 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30734 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 3/4/16 5:23 AM, Eryu Guan wrote: > Hi, > > I noticed some xfstests failures while testing v4 XFS with latest > v4.5.0-rc1 xfsprogs on v4.5-rc6 kernel, and all these failures are gone > if I use v3.2.4 xfsprogs, or if test on v5 XFS. > > So either xfstests needs update or xfsprogs breaks something for non-crc > XFS. But I'm not sure which is which, so I post them out for broader > review. > > (All tests are checked with 'MKFS_OPTIONS="-m crc=0" ./check <sometest>') Eryu, sorry you didn't get a reply on this in March. We should have listened! ;) The patches I sent in the pat day or two should fix some of these ... > == 1. xfs/032 fsck failure (xfs_db check) on ppc64 host == but not this one. Do you still see this? > == 2. xfs/033 fsck failure == > > xfs_repair detects more nlinks error. And this happens after commit > "c2c5096 libxfs: update to 3.16 kernel code" this should be fixed by [PATCH] xfs_repair: set rsumino version to 2 > == 3. xfs/108 xfs/196 xfs/261 xfs/244 fsck failure. == this should be fixed by [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice although I'm not sure about the ppc-specific failure. > These tests fail in a similiar way, and they are all quota related. > Note that xfs/244 only fails on ppc64, others fail on all arches. > == 4. xfs/186 xfs/187 attr test failure == > > xfs/186 is missing almost all the attr values. [PATCH] xfs/186: fix test for crc=0, ftype=1 > xfs/187 reports test needs update. Not sure on this one yet. -Eric From david@fromorbit.com Fri Jun 24 17:51:51 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 86A347CA2 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 17:51:51 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 579E38F8037 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 15:51:51 -0700 (PDT) X-ASG-Debug-ID: 1466808708-04cb6c063e152f10001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id tPPaDse7teuoWInR for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 15:51:48 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AiFAA9uG1XEHvHLHlcgz6BU4J2g3meWQEBAQEBAQaMPooQhhIEAgKBLk0BAQEBAQEHAQEBAQEBAQE+QIRNAQEEOhwjEAgDGAkMGQ8FJQMHGhOIL8cRAQEBBwIBJB6FQoUVhH+CbYIvBZkAjiqPLY9+hFYqMokwAQEB Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail06.adl6.internode.on.net with ESMTP; 25 Jun 2016 08:21:46 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGZww-0001SH-0w; Sat, 25 Jun 2016 08:51:46 +1000 Date: Sat, 25 Jun 2016 08:51:45 +1000 From: Dave Chinner <david@fromorbit.com> To: Danny Shavit <danny@zadarastorage.com> Cc: Eric Sandeen <sandeen@sandeen.net>, xfs-oss <xfs@oss.sgi.com> Subject: Re: xfs metadata overhead Message-ID: <20160624225145.GF12670@dastard> X-ASG-Orig-Subj: Re: xfs metadata overhead References: <CAC=x_0jDYb17Vh97Led7XXDiUMcUTJbpJ2Dw45gn=D0_w0K5VQ@mail.gmail.com> <20160622225117.GX12670@dastard> <CAC=x_0hdvm7SSP8EOAdUwLa-k3a3p7p7CRj8tyCnEx=As7A6jw@mail.gmail.com> <71fbc905-ef05-126a-5c7f-c68c9018763c@sandeen.net> <CAC=x_0hnGQHAenv985+FusWxK_63AatB_XK_mqbAmyt=OxqYrg@mail.gmail.com> <b920a8ec-6410-1daa-809c-04b48db24c0a@sandeen.net> <CAC=x_0g_iktOKOKiRF5Ku7N-PSbCXOR+Amhm577YjNYQaRPjeA@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <CAC=x_0g_iktOKOKiRF5Ku7N-PSbCXOR+Amhm577YjNYQaRPjeA@mail.gmail.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466808708 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 729 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30735 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 24, 2016 at 04:21:39PM +0300, Danny Shavit wrote: > I see. > So using bulk_stat ioctl in similar way to xfs_fsr and summing allocated > size will result with more accurate number? No. du includes *directory blocks* in it's sum. bulkstat only counts inodes, which is not counted by du and is part of the metadata you have already accounted for. Even then, bulkstat doesn't give an accurate account o space used by inodes because they can be sparsely allocated from within inode chunks. Just snapshot the volume, run metadump on the snapshot - it's the fastest, most reliable way to work out how much metadata is in a filesystem right now... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Fri Jun 24 18:00:53 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6E17F7CA2 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 18:00:53 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id DE44BAC003 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 16:00:49 -0700 (PDT) X-ASG-Debug-ID: 1466809246-04cbb02736197010001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id Wa3vAto4VzIZHpbU for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 16:00:47 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AkFACSum1XEHvHLHlcgz6BU4J2g3meWQEBAQEBAQaMPooQhhIEAgKBLk0BAQEBAQEHAQEBAQEBAQE+QIRMAQEBAwE6HCMFCwgDDgoJJQ8FJQMHGhMeiAoHxxEBAQgCJR6FQoUVihsFmQCOKoFziAGFOY9+glwcgV4qMokwAQEB Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail06.adl6.internode.on.net with ESMTP; 25 Jun 2016 08:30:45 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGa5d-0001Tk-Dm; Sat, 25 Jun 2016 09:00:45 +1000 Date: Sat, 25 Jun 2016 09:00:45 +1000 From: Dave Chinner <david@fromorbit.com> To: Christoph Hellwig <hch@lst.de> Cc: xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160624230045.GG12670@dastard> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <20160624072612.GA22205@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160624072612.GA22205@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466809246 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2172 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30735 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 24, 2016 at 09:26:12AM +0200, Christoph Hellwig wrote: > On Fri, Jun 24, 2016 at 09:24:46AM +1000, Dave Chinner wrote: > > Except we did that *intentionally* - by definition there is no > > cache to bypass with DAX and so all IO is "direct". That, combined > > with the fact that all Linux filesystems except XFS break the POSIX > > exclusive writer rule you are quoting to begin with, it seemed > > pointless to enforce it for DAX.... > > No file system breaks the exclusive writer rule - most filesystem > don't make writers atomic vs readers. > > More importantly every other filesystem (well there only are ext2 > and ext4..) exludes DAX writers against other DAX writers. > > > So, before taking any patches to change that behaviour in XFS, a > > wider discussion about the policy needs to be had. I don't think > > we should care about POSIX here - if you have an application that > > needs this serialisation, turn off DAX. That's why I made it a > > per-inode inheritable flag and why the mount option will go away > > over time. > > Sorry, but this is simply broken - allowing apps to opt-in behavior > (e.g. like we're using O_DIRECT) is always fine. Requriring > filesystem-specific tuning that has affect outside the app to get > existing documented behavior is not how to design APIs. Using DAX is an *admin decision*, not an application decision. Indeed, it's a mount option right now, and that's most definitely not something the application can turn on or off! Inode flags allow the admin to decide that two apps working on the same filesystem can use (or not use) DAX independently, rather than needing to put them on different filesystems. > Maybe we'll need to opt-in to use DAX for mmap, but giving the same > existing behavior for read and write and avoiding a copy to the pagecache > is an obvious win. You can't use DAX just for mmap. It's an inode scope behaviour - once it's turned on, all accesses to that inode - regardless of user interface - must use DAX. It's all or nothing, not a per file descript/mmap context option. Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Fri Jun 24 18:03:54 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 85DE67CA2 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 18:03:54 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id E5C81AC002 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 16:03:50 -0700 (PDT) X-ASG-Debug-ID: 1466809427-04cb6c063f153790001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id y4LkFc9fnZSWC0u5 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 16:03:47 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AlFAC/u21XEHvHLHlcgz6BU4J2g3meWQEBAQEBAQaMPooQhhIEAgKBLk0BAQEBAQEHAQEBAQEBAQE+QIRNAQEEIw8BIyMQCAECGAICBRoHAgIPBSUDBxoTiC+ZR50dkC8BAQgCJR5jhF+FFYdBgj0dBZkAjiqPLY9+glwcF4FHKjKJMAEBAQ Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail06.adl6.internode.on.net with ESMTP; 25 Jun 2016 08:33:46 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bGa8Y-0001UD-7z; Sat, 25 Jun 2016 09:03:46 +1000 Date: Sat, 25 Jun 2016 09:03:46 +1000 From: Dave Chinner <david@fromorbit.com> To: Damien Gombault <damien.gombault@recia.fr> Cc: xfs@oss.sgi.com Subject: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed Message-ID: <20160624230346.GH12670@dastard> X-ASG-Orig-Subj: Re: Bug (?) : cumulative xfsrestore does not restore files and folders in a directory which was renamed References: <a08ae222-7654-4a6f-d9ba-f70017784f74@recia.fr> <20160622220959.GV12670@dastard> <20160622222328.GW12670@dastard> <20160623014217.GZ12670@dastard> <eacabe85-cdff-7fbc-8bb6-c8eb51fc0dac@recia.fr> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <eacabe85-cdff-7fbc-8bb6-c8eb51fc0dac@recia.fr> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1466809427 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1120 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30735 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Fri, Jun 24, 2016 at 03:51:57PM +0200, Damien Gombault wrote: > Hi. > > Thank you for the patch. > > The patch fixes simple cases (like my reproducer) but it does not fix > restoration of more complex directory structures : I have tested the > patch on my > real data, it fixes some but not all warnings (a user renamed/moved > a lots of > files and directory between the 2 dumps). > > Here is another testcase which fails (with the patch) : > > mkdir dira > mkdir dira/dirc > touch dira/dirc/filea > mkdir dirb > > . > ├── dira > │ └── dirc > │ └── filea > └── dirb > > Make a level 0 dump. > > mv dirb dira/dirB > mv dira/dirc/ dira/dirB/dirC > touch dira/dirB/dirC/fileb > > . > └── dira > └── dirB > └── dirC > ├── filea > └── fileb Well, yes. I specifically said in the patch description that it doesn't fix those nested dependency cases and that much deeper surgery is needed to handle those cases. Cheers, Dave. -- Dave Chinner david@fromorbit.com From eguan@redhat.com Fri Jun 24 23:44:17 2016 Return-Path: <eguan@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1CE607CA0 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 23:44:17 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id AB03CAC002 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 21:44:13 -0700 (PDT) X-ASG-Debug-ID: 1466829852-04bdf074b583230001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id OAQJE9kuWnir69a4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 21:44:12 -0700 (PDT) X-Barracuda-Envelope-From: eguan@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E165A90906; Sat, 25 Jun 2016 04:44:11 +0000 (UTC) Received: from localhost (dhcp-12-144.nay.redhat.com [10.66.12.144]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5P4iAVb024037; Sat, 25 Jun 2016 00:44:11 -0400 Date: Sat, 25 Jun 2016 12:44:10 +0800 From: Eryu Guan <eguan@redhat.com> To: Eric Sandeen <sandeen@sandeen.net> Cc: xfs@oss.sgi.com Subject: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) Message-ID: <20160625044410.GD23649@eguan.usersys.redhat.com> X-ASG-Orig-Subj: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) References: <20160304112354.GX11419@eguan.usersys.redhat.com> <727b405b-7df2-641a-d4d0-24333e003374@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <727b405b-7df2-641a-d4d0-24333e003374@sandeen.net> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Sat, 25 Jun 2016 04:44:12 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466829852 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2246 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jun 24, 2016 at 05:37:10PM -0500, Eric Sandeen wrote: > On 3/4/16 5:23 AM, Eryu Guan wrote: > > Hi, > > > > I noticed some xfstests failures while testing v4 XFS with latest > > v4.5.0-rc1 xfsprogs on v4.5-rc6 kernel, and all these failures are gone > > if I use v3.2.4 xfsprogs, or if test on v5 XFS. > > > > So either xfstests needs update or xfsprogs breaks something for non-crc > > XFS. But I'm not sure which is which, so I post them out for broader > > review. > > > > (All tests are checked with 'MKFS_OPTIONS="-m crc=0" ./check <sometest>') > > Eryu, sorry you didn't get a reply on this in March. We should have > listened! ;) The patches I sent in the pat day or two should Thanks for looking at them! :) > fix some of these ... > > > == 1. xfs/032 fsck failure (xfs_db check) on ppc64 host == > > but not this one. Do you still see this? My recent test with 4.7-rc4 kernel and latest xfsprogs (June 22nd) shows xfs/032 passed on ppc64 host. But I'll retest to be sure. > > > == 2. xfs/033 fsck failure == > > > > xfs_repair detects more nlinks error. And this happens after commit > > "c2c5096 libxfs: update to 3.16 kernel code" > > this should be fixed by > [PATCH] xfs_repair: set rsumino version to 2 > > > == 3. xfs/108 xfs/196 xfs/261 xfs/244 fsck failure. == > > this should be fixed by > [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice > > although I'm not sure about the ppc-specific failure. My recent test on RHEL7 shows xfs/244 is not ppc-specific. I'll retest with latest kernel and xfsprogs on ppc64 and report back. > > > These tests fail in a similiar way, and they are all quota related. > > Note that xfs/244 only fails on ppc64, others fail on all arches. > > > == 4. xfs/186 xfs/187 attr test failure == > > > > xfs/186 is missing almost all the attr values. > > [PATCH] xfs/186: fix test for crc=0, ftype=1 Thanks! I've queued it in fstests next pull request. Thanks, Eryu > > > xfs/187 reports test needs update. > > Not sure on this one yet. > > -Eric > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From sandeen@sandeen.net Sat Jun 25 00:21:34 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 2DC487CA0 for <xfs@oss.sgi.com>; Sat, 25 Jun 2016 00:21:34 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9CB43AC002 for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 22:21:30 -0700 (PDT) X-ASG-Debug-ID: 1466832087-04cb6c063c161520001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id Q35e6w6F8XHax2qs for <xfs@oss.sgi.com>; Fri, 24 Jun 2016 22:21:27 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.158] (EricSannsiPhone.sandeen.net [10.0.0.158]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 2CE06541; Sat, 25 Jun 2016 00:21:27 -0500 (CDT) Content-Type: text/plain; charset=us-ascii Mime-Version: 1.0 (1.0) Subject: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) From: Eric Sandeen <sandeen@sandeen.net> X-ASG-Orig-Subj: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) X-Mailer: iPhone Mail (13F69) In-Reply-To: <20160625044410.GD23649@eguan.usersys.redhat.com> Date: Sat, 25 Jun 2016 00:21:26 -0500 Cc: xfs@oss.sgi.com Content-Transfer-Encoding: 7bit Message-Id: <DFDE1D5E-8FC3-424F-B9B2-3701EA5A339A@sandeen.net> References: <20160304112354.GX11419@eguan.usersys.redhat.com> <727b405b-7df2-641a-d4d0-24333e003374@sandeen.net> <20160625044410.GD23649@eguan.usersys.redhat.com> To: Eryu Guan <eguan@redhat.com> X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1466832087 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1211 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30743 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header > On Jun 24, 2016, at 11:44 PM, Eryu Guan <eguan@redhat.com> wrote: > >> On Fri, Jun 24, 2016 at 05:37:10PM -0500, Eric Sandeen wrote: >>> On 3/4/16 5:23 AM, Eryu Guan wrote: >>> Hi, >>> >>> I noticed some xfstests failures while testing v4 XFS with latest >>> v4.5.0-rc1 xfsprogs on v4.5-rc6 kernel, and all these failures are gone >>> if I use v3.2.4 xfsprogs, or if test on v5 XFS. >>> >>> So either xfstests needs update or xfsprogs breaks something for non-crc >>> XFS. But I'm not sure which is which, so I post them out for broader >>> review. >>> >>> (All tests are checked with 'MKFS_OPTIONS="-m crc=0" ./check <sometest>') >> >> Eryu, sorry you didn't get a reply on this in March. We should have >> listened! ;) The patches I sent in the pat day or two should > > Thanks for looking at them! :) > >> fix some of these ... >> >>> == 1. xfs/032 fsck failure (xfs_db check) on ppc64 host == >> >> but not this one. Do you still see this? > > My recent test with 4.7-rc4 kernel and latest xfsprogs (June 22nd) shows > xfs/032 passed on ppc64 host. But I'll retest to be sure. I wasn't thinking. Brian's recent sparse inode patches fix this one. Eric From eguan@redhat.com Sat Jun 25 04:09:16 2016 Return-Path: <eguan@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 0EDF97CA0 for <xfs@oss.sgi.com>; Sat, 25 Jun 2016 04:09:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id D322F304039 for <xfs@oss.sgi.com>; Sat, 25 Jun 2016 02:09:12 -0700 (PDT) X-ASG-Debug-ID: 1466845750-04cbb027351b5620001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id WhyYrHlzy0UQVoyt (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Sat, 25 Jun 2016 02:09:11 -0700 (PDT) X-Barracuda-Envelope-From: eguan@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8269364094; Sat, 25 Jun 2016 09:09:10 +0000 (UTC) Received: from localhost (dhcp-12-144.nay.redhat.com [10.66.12.144]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5P999MB004501; Sat, 25 Jun 2016 05:09:09 -0400 Date: Sat, 25 Jun 2016 17:09:08 +0800 From: Eryu Guan <eguan@redhat.com> To: Eric Sandeen <sandeen@sandeen.net> Cc: xfs@oss.sgi.com Subject: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) Message-ID: <20160625090908.GE23649@eguan.usersys.redhat.com> X-ASG-Orig-Subj: Re: Some xfstests failures on non-crc xfs with latest xfsprogs (v4.5.0-rc1) References: <20160304112354.GX11419@eguan.usersys.redhat.com> <727b405b-7df2-641a-d4d0-24333e003374@sandeen.net> <20160625044410.GD23649@eguan.usersys.redhat.com> <DFDE1D5E-8FC3-424F-B9B2-3701EA5A339A@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <DFDE1D5E-8FC3-424F-B9B2-3701EA5A339A@sandeen.net> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Sat, 25 Jun 2016 09:09:10 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1466845751 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1495 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Sat, Jun 25, 2016 at 12:21:26AM -0500, Eric Sandeen wrote: > > > On Jun 24, 2016, at 11:44 PM, Eryu Guan <eguan@redhat.com> wrote: > > > >> On Fri, Jun 24, 2016 at 05:37:10PM -0500, Eric Sandeen wrote: > >>> On 3/4/16 5:23 AM, Eryu Guan wrote: > >>> Hi, > >>> > >>> I noticed some xfstests failures while testing v4 XFS with latest > >>> v4.5.0-rc1 xfsprogs on v4.5-rc6 kernel, and all these failures are gone > >>> if I use v3.2.4 xfsprogs, or if test on v5 XFS. > >>> > >>> So either xfstests needs update or xfsprogs breaks something for non-crc > >>> XFS. But I'm not sure which is which, so I post them out for broader > >>> review. > >>> > >>> (All tests are checked with 'MKFS_OPTIONS="-m crc=0" ./check <sometest>') > >> > >> Eryu, sorry you didn't get a reply on this in March. We should have > >> listened! ;) The patches I sent in the pat day or two should > > > > Thanks for looking at them! :) > > > >> fix some of these ... > >> > >>> == 1. xfs/032 fsck failure (xfs_db check) on ppc64 host == > >> > >> but not this one. Do you still see this? > > > > My recent test with 4.7-rc4 kernel and latest xfsprogs (June 22nd) shows > > xfs/032 passed on ppc64 host. But I'll retest to be sure. > > I wasn't thinking. Brian's recent sparse inode patches fix this one. Confirmed xfsprogs v4.7-rc1 passed the test. And xfs/244 is not ppc-specific, x86_64 fails it either. I think your patch could fix it as well. Thanks, Eryu From s.priebe@profihost.ag Sun Jun 26 00:44:31 2016 Return-Path: <s.priebe@profihost.ag> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 27D737CA0 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 00:44:31 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id B49DFAC003 for <xfs@oss.sgi.com>; Sat, 25 Jun 2016 22:44:27 -0700 (PDT) X-ASG-Debug-ID: 1466919862-04bdf074b4d0150001-NocioJ Received: from cloud1-vm154.de-nserver.de (cloud1-vm154.de-nserver.de [178.250.10.56]) by cuda.sgi.com with ESMTP id M0QmxeV8Z8a2d02v (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Sat, 25 Jun 2016 22:44:24 -0700 (PDT) X-Barracuda-Envelope-From: s.priebe@profihost.ag X-Barracuda-Effective-Source-IP: cloud1-vm154.de-nserver.de[178.250.10.56] X-Barracuda-Apparent-Source-IP: 178.250.10.56 Received: (qmail 6276 invoked from network); 26 Jun 2016 07:44:22 +0200 X-Fcrdns: No Received: from phoffice.de-nserver.de (HELO [10.242.2.3]) (185.39.223.5) (smtp-auth username s.priebe@profihost.ag, mechanism plain) by cloud1-vm154.de-nserver.de (qpsmtpd/0.92) with (ECDHE-RSA-AES256-SHA encrypted) ESMTPSA; Sun, 26 Jun 2016 07:44:22 +0200 Subject: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage To: Dave Chinner <david@fromorbit.com> X-ASG-Orig-Subj: Re: xfs trace in 4.4.2 / also in 4.3.3 WARNING fs/xfs/xfs_aops.c:1232 xfs_vm_releasepage References: <20160324122417.GB4068@bfoster.bfoster> <57332508.307@profihost.ag> <20160511133417.GA42410@bfoster.bfoster> <57333BA4.4040402@profihost.ag> <20160511155951.GF42410@bfoster.bfoster> <5738576B.4010208@profihost.ag> <20160515115017.GA6433@laptop.bfoster> <57386E84.3090606@profihost.ag> <20160516010602.GA24980@bfoster.bfoster> <57420A47.2000700@profihost.ag> <20160522213850.GE26977@dastard> <5751C4B8.2080301@profihost.ag> Cc: Brian Foster <bfoster@redhat.com>, "xfs-masters@oss.sgi.com" <xfs-masters@oss.sgi.com>, "xfs@oss.sgi.com" <xfs@oss.sgi.com> From: Stefan Priebe <s.priebe@profihost.ag> Message-ID: <576F6BE7.80605@profihost.ag> Date: Sun, 26 Jun 2016 07:45:11 +0200 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.7.2 MIME-Version: 1.0 In-Reply-To: <5751C4B8.2080301@profihost.ag> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-User-Auth: Auth by s.priebe@profihost.ag through 185.39.223.5 X-Barracuda-Connect: cloud1-vm154.de-nserver.de[178.250.10.56] X-Barracuda-Start-Time: 1466919863 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9812 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30767 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header Hi Dave, today i got this XFS trace while running 4.4.13. I'm not sure if it is related. [282732.262739] ------------[ cut here ]------------ [282732.264093] kernel BUG at fs/xfs/xfs_aops.c:1054! [282732.265459] invalid opcode: 0000 [#1] SMP [282732.266753] Modules linked in: netconsole xt_multiport iptable_filter ip_tables x_tables bonding coretemp 8021q garp fuse sb_edac edac_core xhci_pci i40e(O) xhci_hcd i2c_i801 vxlan shpchp ip6_udp_tunnel udp_tunnel ipmi_si ipmi_msghandler button btrfs xor raid6_pq dm_mod raid1 md_mod usbhid usb_storage ohci_hcd sg sd_mod ehci_pci ehci_hcd usbcore usb_common ahci libahci igb i2c_algo_bit mpt3sas i2c_core raid_class ptp pps_core scsi_transport_sas [282732.280494] CPU: 2 PID: 108 Comm: kswapd0 Tainted: G O 4.4.13+36-ph #1 [282732.282707] Hardware name: Supermicro Super Server/X10SRH-CF, BIOS 2.0 12/17/2015 [282732.284873] task: ffff880c4d9ba500 ti: ffff880c4da28000 task.ti: ffff880c4da28000 [282732.287038] RIP: 0010:[<ffffffff943267f1>] [<ffffffff943267f1>] xfs_vm_writepage+0x561/0x5c0 [282732.289554] RSP: 0018:ffff880c4da2b8e8 EFLAGS: 00010246 [282732.291095] RAX: 001fffff80020009 RBX: ffffea000186de80 RCX: 000000000000000c [282732.293161] RDX: 0000000000001800 RSI: ffff880c4da2b9b8 RDI: ffffea000186de80 [282732.295255] RBP: ffff880c4da2b9a8 R08: 0000000000000003 R09: 7fffffffffffffff [282732.297340] R10: ffff880c7ffdc6c0 R11: 0000000000000000 R12: ffffea000186de80 [282732.299405] R13: ffff88001ea855d0 R14: ffff880c4da2bad8 R15: ffffea000186dea0 [282732.301472] FS: 0000000000000000(0000) GS:ffff880c7fc40000(0000) knlGS:0000000000000000 [282732.303811] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [282732.305480] CR2: ffffffffff600400 CR3: 0000000014c0a000 CR4: 00000000001406e0 [282732.307545] Stack: [282732.308142] ffff8806c1e980e0 ffff880c442dc800 ffff880100000001 0000000100042000 [282732.310482] ffffea00016db240 ffff880c4da2b968 0000000001800000 ffff880c4da2b9b8 [282732.312822] 0000000000001000 0000000000297000 0000000000000000 0000000000000246 [282732.315161] Call Trace: [282732.315890] [<ffffffff9415c72e>] ? clear_page_dirty_for_io+0xee/0x1b0 [282732.317782] [<ffffffff94163974>] pageout.isra.43+0x164/0x280 [282732.319449] [<ffffffff94165f4a>] shrink_page_list+0x5ba/0x760 [282732.321143] [<ffffffff941667ce>] shrink_inactive_list+0x1ee/0x500 [282732.322934] [<ffffffff941674e1>] shrink_lruvec+0x621/0x7d0 [282732.324554] [<ffffffff9416776c>] shrink_zone+0xdc/0x2c0 [282732.326096] [<ffffffff941688b9>] kswapd+0x4f9/0x970 [282732.327541] [<ffffffff941683c0>] ? mem_cgroup_shrink_node_zone+0x1a0/0x1a0 [282732.329561] [<ffffffff940a0dc9>] kthread+0xc9/0xe0 [282732.330979] [<ffffffff940a0d00>] ? kthread_stop+0x100/0x100 [282732.332623] [<ffffffff946b470f>] ret_from_fork+0x3f/0x70 [282732.334191] [<ffffffff940a0d00>] ? kthread_stop+0x100/0x100 [282732.404901] Code: f8 f5 74 a3 4c 89 e7 89 85 50 ff ff ff e8 38 e8 ff ff f0 41 80 24 24 f7 4c 89 e7 e8 3a bf e2 ff 8b 85 50 ff ff ff e9 39 fd ff ff <0f> 0b 80 3d 04 fc 9c 00 00 0f 85 6d ff ff ff be d6 03 00 00 48 [282732.556398] RIP [<ffffffff943267f1>] xfs_vm_writepage+0x561/0x5c0 [282732.630207] RSP <ffff880c4da2b8e8> [282732.703062] ---[ end trace 9ea1afce9e126cdc ]--- [282732.842462] ------------[ cut here ]------------ [282732.914729] WARNING: CPU: 2 PID: 108 at kernel/exit.c:661 do_exit+0x50/0xab0() [282732.989039] Modules linked in: netconsole xt_multiport iptable_filter ip_tables x_tables bonding coretemp 8021q garp fuse sb_edac edac_core xhci_pci i40e(O) xhci_hcd i2c_i801 vxlan shpchp ip6_udp_tunnel udp_tunnel ipmi_si ipmi_msghandler button btrfs xor raid6_pq dm_mod raid1 md_mod usbhid usb_storage ohci_hcd sg sd_mod ehci_pci ehci_hcd usbcore usb_common ahci libahci igb i2c_algo_bit mpt3sas i2c_core raid_class ptp pps_core scsi_transport_sas [282733.306619] CPU: 2 PID: 108 Comm: kswapd0 Tainted: G D O 4.4.13+36-ph #1 [282733.386805] Hardware name: Supermicro Super Server/X10SRH-CF, BIOS 2.0 12/17/2015 [282733.467585] 0000000000000000 ffff880c4da2b5d8 ffffffff943c60ff 0000000000000000 [282733.547861] ffffffff94a330a8 ffff880c4da2b618 ffffffff940837a7 ffff880c4da2b838 [282733.626144] 000000000000000b ffff880c4da2b838 0000000000000246 ffff880c4d9ba500 [282733.702723] Call Trace: [282733.776298] [<ffffffff943c60ff>] dump_stack+0x63/0x84 [282733.849877] [<ffffffff940837a7>] warn_slowpath_common+0x97/0xe0 [282733.922917] [<ffffffff9408380a>] warn_slowpath_null+0x1a/0x20 [282733.994640] [<ffffffff94085a90>] do_exit+0x50/0xab0 [282734.064858] [<ffffffff94008a02>] oops_end+0xa2/0xe0 [282734.133974] [<ffffffff94008b88>] die+0x58/0x80 [282734.202270] [<ffffffff94005ba9>] do_trap+0x69/0x150 [282734.269913] [<ffffffff940a1bc2>] ? __atomic_notifier_call_chain+0x12/0x20 [282734.337974] [<ffffffff94005d5d>] do_error_trap+0xcd/0xf0 [282734.406008] [<ffffffff943267f1>] ? xfs_vm_writepage+0x561/0x5c0 [282734.474472] [<ffffffff9439c334>] ? generic_make_request+0x104/0x190 [282734.542216] [<ffffffff94006000>] do_invalid_op+0x20/0x30 [282734.609276] [<ffffffff946b5e8e>] invalid_op+0x1e/0x30 [282734.675516] [<ffffffff943267f1>] ? xfs_vm_writepage+0x561/0x5c0 [282734.741307] [<ffffffff94326528>] ? xfs_vm_writepage+0x298/0x5c0 [282734.805722] [<ffffffff9415c72e>] ? clear_page_dirty_for_io+0xee/0x1b0 [282734.870589] [<ffffffff94163974>] pageout.isra.43+0x164/0x280 [282734.934901] [<ffffffff94165f4a>] shrink_page_list+0x5ba/0x760 [282734.998565] [<ffffffff941667ce>] shrink_inactive_list+0x1ee/0x500 [282735.061845] [<ffffffff941674e1>] shrink_lruvec+0x621/0x7d0 [282735.124441] [<ffffffff9416776c>] shrink_zone+0xdc/0x2c0 [282735.186752] [<ffffffff941688b9>] kswapd+0x4f9/0x970 [282735.249021] [<ffffffff941683c0>] ? mem_cgroup_shrink_node_zone+0x1a0/0x1a0 [282735.312215] [<ffffffff940a0dc9>] kthread+0xc9/0xe0 [282735.375420] [<ffffffff940a0d00>] ? kthread_stop+0x100/0x100 [282735.439012] [<ffffffff946b470f>] ret_from_fork+0x3f/0x70 [282735.502368] [<ffffffff940a0d00>] ? kthread_stop+0x100/0x100 [282735.565534] ---[ end trace 9ea1afce9e126cdd ]--- Stefan Am 03.06.2016 um 19:56 schrieb Stefan Priebe - Profihost AG: > Hi, > > should i remove the complete if conditions incl. the return 0 or should > id convert it to if without WARN_ONCE? like below? > > if (WARN_ON_ONCE(delalloc)) > return 0; > if (WARN_ON_ONCE(unwritten)) > return 0; > > => > > if (delalloc) > return 0; > if (unwritten) > return 0; > > > > Am 22.05.2016 um 23:38 schrieb Dave Chinner: >> On Sun, May 22, 2016 at 09:36:39PM +0200, Stefan Priebe - Profihost AG wrote: >>> Am 16.05.2016 um 03:06 schrieb Brian Foster: >>>>> sd_mod ehci_pci ehci_hcd usbcore usb_common igb ahci i2c_algo_bit libahci >>>>> i2c_core ptp mpt3sas pps_core raid_class scsi_transport_sas >>>>> [Sun May 15 07:00:44 2016] CPU: 2 PID: 108 Comm: kswapd0 Tainted: G O >>>>> 4.4.10+25-ph #1 >>>> >>>> How close is this to an upstream kernel? Upstream XFS? Have you tried to >>>> reproduce this on an upstream kernel? >>> >>> It's a vanilla 4.4.10 + a new adaptec driver and some sched and wq >>> patches from 4.5 and 4.6 but i can try to replace the kernel on one >>> machine with a 100% vanilla one if this helps. >> >> Please do. >> >>>>> [295086.353473] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>>> 0x52000 size 0x13d1c8 >>>>> [295086.353476] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>>> 0x53000 size 0x13d1c8 >>>>> [295086.353478] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>>> 0x54000 size 0x13d1c8 >>>> ... >>>>> [295086.567508] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>>> 0xab000 size 0x13d1c8 >>>>> [295086.567510] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>>> 0xac000 size 0x13d1c8 >>>>> [295086.567515] XFS (md127p3): ino 0x600204f delalloc 1 unwritten 0 pgoff >>>>> 0xad000 size 0x13d1c8 >>>>> >>>>> The file to the inode number is: >>>>> /var/lib/apt/lists/security.debian.org_dists_wheezy_updates_main_i18n_Translation-en >>>>> >>>> >>>> xfs_bmap -v might be interesting here as well. >>> >>> # xfs_bmap -v >>> /var/lib/apt/lists/security.debian.org_dists_wheezy_updates_main_i18n_Translation-en >>> /var/lib/apt/lists/security.debian.org_dists_wheezy_updates_main_i18n_Translation-en: >>> EXT: FILE-OFFSET BLOCK-RANGE AG AG-OFFSET TOTAL >>> 0: [0..2567]: 41268928..41271495 3 (374464..377031) 2568 >> >> So the last file offset with a block is 0x140e00. This means the >> file is fully allocated. However, the pages inside the file range >> are still marked delayed allocation. That implies that we've failed >> to write the pages over a delayed allocation region after we've >> allocated the space. >> >> That, in turn, tends to indicate a problem in page writeback - the >> first page to be written has triggered delayed allocation of the >> entire range, but then the subsequent pages have not been written >> (for some as yet unknown reason). When a page is written, we map it >> to the current block via xfs_map_at_offset(), and that clears both >> the buffer delay and unwritten flags. >> >> This clearly isn't happening which means either the VFS doesn't >> think the inode is dirty anymore, writeback is never asking for >> these pages to be written, or XFs is screwing something up in >> ->writepage. The XFS writepage code changed significantly in 4.6, so >> it might be worth seeing if a 4.6 kernel reproduces this same >> problem.... >> >> Cheers, >> >> Dave. >> From regressions@leemhuis.info Sun Jun 26 07:16:27 2016 Return-Path: <regressions@leemhuis.info> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id B36E67CA0 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 07:16:27 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 802A48F8037 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 05:16:27 -0700 (PDT) X-ASG-Debug-ID: 1466943380-04cbb02736212810001-NocioJ Received: from basicbox7.server-home.net (basicbox7.server-home.net [195.137.212.29]) by cuda.sgi.com with ESMTP id iQKBWGS7ebYpSNm1 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 05:16:21 -0700 (PDT) X-Barracuda-Envelope-From: regressions@leemhuis.info X-Barracuda-Effective-Source-IP: basicbox7.server-home.net[195.137.212.29] X-Barracuda-Apparent-Source-IP: 195.137.212.29 Received: from ankhmorpork.fritz.box (ip4d15e046.dynamic.kabel-deutschland.de [77.21.224.70]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by basicbox7.server-home.net (Postfix) with ESMTPSA id B7B7E5EE7E6; Sun, 26 Jun 2016 14:16:19 +0200 (CEST) Subject: Re: Internal error xfs_trans_cancel To: Daniel Wagner <wagi@monom.org>, Dave Chinner <david@fromorbit.com> X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <ab487269-a423-e3dc-6f59-3dda004960c3@monom.org> <20160601071047.GJ12670@dastard> <e80cee4f-1789-5418-ffa8-7551138bda0a@monom.org> <0644b434-6cea-4188-9702-469c26d191b8@monom.org> <20160602002653.GL12670@dastard> <af997005-e144-5509-885c-a688562ea3ec@monom.org> <20160602063539.GM12670@dastard> <a933729c-afa8-3cc1-6fe4-5f49b9629326@monom.org> Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>, xfs@oss.sgi.com, Josh Poimboeuf <jpoimboe@redhat.com> From: Thorsten Leemhuis <regressions@leemhuis.info> Message-ID: <a738e82e-ffa5-53e0-ba58-a85a1254baf3@leemhuis.info> Date: Sun, 26 Jun 2016 14:16:19 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <a933729c-afa8-3cc1-6fe4-5f49b9629326@monom.org> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: basicbox7.server-home.net[195.137.212.29] X-Barracuda-Start-Time: 1466943381 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 928 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=ADVANCE_FEE_1, BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30774 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 ADVANCE_FEE_1 Appears to be advance fee fraud (Nigerian 419) On 02.06.2016 15:29, Daniel Wagner wrote: >> Hmmm, Ok. I've been running the lockperf test and kernel builds all >> day on a filesystem that is identical in shape and size to yours >> (i.e. xfs_info output is the same) but I haven't reproduced it yet. > I don't know if that is important: I run the lockperf test and after > they have finished I do a kernel build. > >> Is it possible to get a metadump image of your filesystem to see if >> I can reproduce it on that? > Sure, see private mail. Dave, Daniel, what's the latest status on this issue? It made it to my list of know 4.7 regressions after Christoph suggested it should be listed. But this thread looks stalled, as afaics nothing happened for three weeks apart from Josh (added to CC) mentioning he also saw it. Or is this discussed elsewhere? Or fixed already? Sincerely, your regression tracker for Linux 4.7 (http://bit.ly/28JRmJo) Thorsten From wagi@monom.org Sun Jun 26 10:13:42 2016 Return-Path: <wagi@monom.org> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D9D607CA0 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 10:13:42 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9B7598F8033 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 08:13:39 -0700 (PDT) X-ASG-Debug-ID: 1466954016-04cbb0273621b220001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id hDS6khOZOxQpOBBH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 08:13:37 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id 2C60F194074F; Sun, 26 Jun 2016 17:13:35 +0200 (CEST) Received: from handman.bmw-carit.intra (ppp-88-217-121-67.dynamic.mnet-online.de [88.217.121.67]) by hotel311.server4you.de (Postfix) with ESMTPSA id 8B5AF19406B1; Sun, 26 Jun 2016 17:13:34 +0200 (CEST) Subject: Re: Internal error xfs_trans_cancel To: Thorsten Leemhuis <regressions@leemhuis.info>, Dave Chinner <david@fromorbit.com> X-ASG-Orig-Subj: Re: Internal error xfs_trans_cancel References: <ab487269-a423-e3dc-6f59-3dda004960c3@monom.org> <20160601071047.GJ12670@dastard> <e80cee4f-1789-5418-ffa8-7551138bda0a@monom.org> <0644b434-6cea-4188-9702-469c26d191b8@monom.org> <20160602002653.GL12670@dastard> <af997005-e144-5509-885c-a688562ea3ec@monom.org> <20160602063539.GM12670@dastard> <a933729c-afa8-3cc1-6fe4-5f49b9629326@monom.org> <a738e82e-ffa5-53e0-ba58-a85a1254baf3@leemhuis.info> Cc: linux-fsdevel@vger.kernel.org, "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>, xfs@oss.sgi.com, Josh Poimboeuf <jpoimboe@redhat.com> From: Daniel Wagner <wagi@monom.org> X-Enigmail-Draft-Status: N1110 Message-ID: <af4706ea-0129-1692-e354-0bd08fabd255@monom.org> Date: Sun, 26 Jun 2016 17:13:33 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.0 MIME-Version: 1.0 In-Reply-To: <a738e82e-ffa5-53e0-ba58-a85a1254baf3@leemhuis.info> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1466954017 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1277 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=ADVANCE_FEE_1, BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30777 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 ADVANCE_FEE_1 Appears to be advance fee fraud (Nigerian 419) On 06/26/2016 02:16 PM, Thorsten Leemhuis wrote: > On 02.06.2016 15:29, Daniel Wagner wrote: >>> Hmmm, Ok. I've been running the lockperf test and kernel builds all >>> day on a filesystem that is identical in shape and size to yours >>> (i.e. xfs_info output is the same) but I haven't reproduced it yet. >> I don't know if that is important: I run the lockperf test and after >> they have finished I do a kernel build. >> >>> Is it possible to get a metadump image of your filesystem to see if >>> I can reproduce it on that? >> Sure, see private mail. > > Dave, Daniel, what's the latest status on this issue? I had no time to do some more testing in last couple of weeks. Tomorrow I'll try to reproduce it again, though last time I tried it couldn't trigger it. > It made it to my > list of know 4.7 regressions after Christoph suggested it should be > listed. But this thread looks stalled, as afaics nothing happened for > three weeks apart from Josh (added to CC) mentioning he also saw it. Or > is this discussed elsewhere? Or fixed already? The discussion wandered over to the thread called 'crash in xfs in current' and there are some instruction by Al what to do test Message-ID: <20160622014253.GS12670@dastard> cheers, daniel From jaonary@free.fr Sun Jun 26 17:54:26 2016 Return-Path: <jaonary@free.fr> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: ** X-Spam-Status: No, score=2.6 required=5.0 tests=EMPTY_MESSAGE,FREEMAIL_FROM, HTML_MESSAGE,MIME_HTML_MOSTLY autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 2C3447CA0 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 17:54:26 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id ABAF0AC003 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 15:54:25 -0700 (PDT) X-ASG-Debug-ID: 1466981655-04bdf074b5fce80001-NocioJ Received: from server.vieiragroup.com ([192.163.228.28]) by cuda.sgi.com with ESMTP id zWGszxinog6o8ExX (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 15:54:16 -0700 (PDT) X-Barracuda-Envelope-From: jaonary@free.fr X-Barracuda-Effective-Source-IP: UNKNOWN[192.163.228.28] X-Barracuda-Apparent-Source-IP: 192.163.228.28 Received: from [94.16.139.40] (port=44010 helo=ghphs.com) by server.vieiragroup.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.87) (envelope-from <jaonary@free.fr>) id 1bHIwG-0003ZR-Vi; Sun, 26 Jun 2016 22:54:05 +0000 From: Cyril Brulebois <jaonary@free.fr> To: "Miles Fidelman" <mfidelman@meetinghouse.net>, "793495" <793495@bugs.debian.org>, "xfs" <xfs@oss.sgi.com>, "751731" <751731@bugs.debian.org> Subject: Date: Mon, 27 Jun 2016 01:54:01 +0300 Message-ID: <0000d114e3c2$6e494448$3dd15fac$@free.fr> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="----=_NextPart_000_0001_0BA29374.4DD8F346" X-Mailer: Microsoft Outlook 15.0 Thread-Index: AdHPMrwXKZoN806e5jTEJEioMBPorA== Content-Language: en-us X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server.vieiragroup.com X-AntiAbuse: Original Domain - oss.sgi.com X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - free.fr X-Get-Message-Sender-Via: server.vieiragroup.com: authenticated_id: anthony@vieirafamily.com X-Authenticated-Sender: server.vieiragroup.com: anthony@vieirafamily.com X-Source: X-Source-Args: X-Source-Dir: X-Barracuda-Connect: UNKNOWN[192.163.228.28] X-Barracuda-Start-Time: 1466981656 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1700 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.02 X-Barracuda-Spam-Status: No, SCORE=2.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, EMPTY_MESSAGE, HTML_MESSAGE, MIME_HTML_MOSTLY, MISSING_SUBJECT, MISSING_SUBJECT_2, RDNS_NONE, THREAD_INDEX X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30785 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 MIME_HTML_MOSTLY BODY: Multipart message mostly text/html MIME 0.00 HTML_MESSAGE BODY: HTML included in message 0.61 EMPTY_MESSAGE Message appears to have no textual parts and no Subject: text 0.01 MISSING_SUBJECT Missing Subject: header 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 1.28 MISSING_SUBJECT_2 Missing Subject: header This is a multipart message in MIME format. ------=_NextPart_000_0001_0BA29374.4DD8F346 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit ------=_NextPart_000_0001_0BA29374.4DD8F346 Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable <html xmlns:v=3D"urn:schemas-microsoft-com:vml" xmlns:o=3D"urn:schemas= -microsoft-com:office:office" xmlns:w=3D"urn:schemas-microsoft-com:off= ice:word" xmlns:m=3D"http://schemas.microsoft.com/office/2004/12/omml"= xmlns=3D"http://www.w3.org/TR/REC-html40"><head><META HTTP-EQUIV=3D"C= ontent-Type" CONTENT=3D"text/html; charset=3Dus-ascii"><meta name=3DGe= nerator content=3D"Microsoft Word 15 (filtered medium)"><style><!-- /* Font Definitions */ @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {margin:0cm; margin-bottom:.0001pt; font-size:11.0pt; font-family:"Calibri",sans-serif; mso-fareast-language:EN-US;} a:link, span.MsoHyperlink {mso-style-priority:99; color:#0563C1; text-decoration:underline;} a:visited, span.MsoHyperlinkFollowed {mso-style-priority:99; color:#954F72; text-decoration:underline;} span.EmailStyle17 {mso-style-type:personal-compose; font-family:"Calibri",sans-serif; color:windowtext;} =2EMsoChpDefault {mso-style-type:export-only; font-family:"Calibri",sans-serif; mso-fareast-language:EN-US;} @page WordSection1 {size:612.0pt 792.0pt; margin:2.0cm 42.5pt 2.0cm 3.0cm;} div.WordSection1 {page:WordSection1;} --></style><!--[if gte mso 9]><xml> <o:shapedefaults v:ext=3D"edit" spidmax=3D"1026" /> </xml><![endif]--><!--[if gte mso 9]><xml> <o:shapelayout v:ext=3D"edit"> <o:idmap v:ext=3D"edit" data=3D"1" /> </o:shapelayout></xml><![endif]--></head><body lang=3DEN link=3D"#0563= C1" vlink=3D"#954F72"><div class=3DWordSection1></div></body></html> ------=_NextPart_000_0001_0BA29374.4DD8F346-- From irpost@statoil.com Sun Jun 26 20:14:11 2016 Return-Path: <irpost@statoil.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: * X-Spam-Status: No, score=1.0 required=5.0 tests=FREEMAIL_REPLYTO,T_FRT_CONTACT autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 13F4A7CA1 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 20:14:11 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id C7FAD304032 for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 18:14:07 -0700 (PDT) X-ASG-Debug-ID: 1466990044-04bdf074b41031a0001-NocioJ Received: from lynx.ablenet.jp (lynx.ablenet.jp [58.191.153.40]) by cuda.sgi.com with SMTP id 2Y5GHssSsNTSdrnl for <xfs@oss.sgi.com>; Sun, 26 Jun 2016 18:14:05 -0700 (PDT) X-Barracuda-Envelope-From: irpost@statoil.com X-Barracuda-Effective-Source-IP: lynx.ablenet.jp[58.191.153.40] X-Barracuda-Apparent-Source-IP: 58.191.153.40 Received: (qmail 40485 invoked by uid 98); 27 Jun 2016 10:14:04 +0900 Received: from 83.51.160.135 by lynx.ablenet.jp (envelope-from <irpost@statoil.com>, uid 89) with qmail-scanner-1.25st; 27 Jun 2016 10:14:04 -0900 Received: from unknown (HELO computer2016.telefonica.net) (tarot@boku-sui.net@83.51.160.135) by lynx.ablenet.jp with SMTP; 27 Jun 2016 10:14:03 +0900 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body Subject: =?utf-8?q?Herzlichen_Gl=C3=BCckwunsch!!!?= To: "Frautschi Hanspeter f.hanspeter@bluewin.ch" <irpost@statoil.com> X-ASG-Orig-Subj: =?utf-8?q?Herzlichen_Gl=C3=BCckwunsch!!!?= From: "Anne Girola" <irpost@statoil.com> Date: Mon, 27 Jun 2016 03:13:36 +0200 Reply-To: ggseguros@qq.com X-Antivirus: avast! (VPS 160626-1, 26/06/2016), Outbound message X-Antivirus-Status: Clean X-Qmail-Scanner-Message-ID: <146699004492340483@lynx.ablenet.jp> X-Barracuda-Connect: lynx.ablenet.jp[58.191.153.40] X-Barracuda-Start-Time: 1466990044 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 0 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.30 X-Barracuda-Spam-Status: No, SCORE=2.30 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA609_MID, BSF_SC0_SA_TO_FROM_ADDR_MATCH, MISSING_MID, PLING_PLING X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30787 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.46 PLING_PLING Subject has lots of exclamation marks 0.50 BSF_SC0_SA_TO_FROM_ADDR_MATCH Sender Address Matches Recipient Address 1.20 BSF_SC0_SA609_MID Custom Rule SA609_MID Message-Id: <20160627011407.7ECB5A420A8@cuda.sgi.com> Aufmerksamkeit LDN Gewinner, Ticket-Nummer:05163 Ihre e-Mail-Adresse wurde Gewinner des =E2=82=AC757,500,00 nominiert. Bitte= kontaktieren Sie uns Anspr=C3=BCche E-mail ggservicio@qq.com Herzliche Gr=C3=BC=C3=9Fe Anne Girolamo ADMIN-LDN --- This email has been checked for viruses by Avast antivirus software. https://www.avast.com/antivirus From cmaiolino@redhat.com Mon Jun 27 04:46:25 2016 Return-Path: <cmaiolino@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D1A2B7CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 04:46:25 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id A19D8304048 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 02:46:25 -0700 (PDT) X-ASG-Debug-ID: 1467020783-04cb6c063e1d2b70001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id Y3yZcAxICk6bmw1W (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 02:46:24 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 8F6BC71096; Mon, 27 Jun 2016 09:46:23 +0000 (UTC) Received: from redhat.com (vpn-63-153.rdu2.redhat.com [10.10.63.153]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5R9kJnO025957 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Jun 2016 05:46:22 -0400 Date: Mon, 27 Jun 2016 11:46:19 +0200 From: Carlos Maiolino <cmaiolino@redhat.com> To: "Chang, Brady" <Brady.Chang@emc.com> Cc: "xfs@oss.sgi.com" <xfs@oss.sgi.com> Subject: Re: xfs_irecover question Message-ID: <20160627094619.GB29774@redhat.com> X-ASG-Orig-Subj: Re: xfs_irecover question Mail-Followup-To: "Chang, Brady" <Brady.Chang@emc.com>, "xfs@oss.sgi.com" <xfs@oss.sgi.com> References: <D392E1CC.3E982%brady.chang@emc.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <D392E1CC.3E982%brady.chang@emc.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 27 Jun 2016 09:46:23 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467020784 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1181 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jun 24, 2016 at 06:10:38PM +0000, Chang, Brady wrote: > Hi, > > Is there a way to find fullpath to the file generated by xfs_irecover > ? I'm not a user of xfs_irecover, but, giving how inodes are deleted, I doubt you will be able to recover the fullpath in some way. While we don't delete inodes from the lists and make them usable for future files, this is not the same for directory entries. The directory entry is removed from the directory, and there is nothing that can link the inode to its directory entry (or entries) after the file is deleted. Somebody with more expertise on it might give a final POV, but I doubt you would be able to recover the directory entries pointing to the inode, once the file is deleted. > > For example: > [root@sdw2 recover]# ls -l 532946 > -rw------- 1 root root 33461216 Jun 23 21:07 532946 > [root@sdw2 recover]# file 532946 > 532946: SGI XFS filesystem data (blksz 4096, inosz 256, v2 dirs) > > Thanks > > -Brady > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From cmaiolino@redhat.com Mon Jun 27 04:49:02 2016 Return-Path: <cmaiolino@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id F30A47CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 04:49:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id C1F17304039 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 02:49:01 -0700 (PDT) X-ASG-Debug-ID: 1467020940-04cbb0273725b920001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id UERgCTaW6KXr1FPz (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 02:49:00 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 19CA07F080 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 09:49:00 +0000 (UTC) Received: from redhat.com (vpn-63-153.rdu2.redhat.com [10.10.63.153]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5R9mua7003259 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Mon, 27 Jun 2016 05:48:58 -0400 Date: Mon, 27 Jun 2016 11:48:55 +0200 From: Carlos Maiolino <cmaiolino@redhat.com> To: Eric Sandeen <sandeen@redhat.com> Cc: xfs-oss <xfs@oss.sgi.com>, Eryu Guan <eguan@redhat.com> Subject: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Message-ID: <20160627094855.GC29774@redhat.com> X-ASG-Orig-Subj: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Mail-Followup-To: Eric Sandeen <sandeen@redhat.com>, xfs-oss <xfs@oss.sgi.com>, Eryu Guan <eguan@redhat.com> References: <13dd3974-956d-c3af-86ed-f6ce5cc1b996@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <13dd3974-956d-c3af-86ed-f6ce5cc1b996@redhat.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 27 Jun 2016 09:49:00 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467020940 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3523 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jun 24, 2016 at 04:24:58PM -0500, Eric Sandeen wrote: > kernel commit 5ef828c4 > xfs: avoid false quotacheck after unclean shutdown > > made xfs_sb_from_disk() also call xfs_sb_quota_from_disk > by default. > > However, when this was merged to libxfs, existing separate > calls to libxfs_sb_quota_from_disk remained, and calling it > twice in a row on a V4 superblock leads to issues, because: > > > if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { > ... > sbp->sb_pquotino = sbp->sb_gquotino; > sbp->sb_gquotino = NULLFSINO; > > and after the second call, we have set both pquotino and gquotino > to NULLFSINO. > > Fix this by making it safe to call twice, and also remove the extra > calls to libxfs_sb_quota_from_disk. > > This is only spotted when running xfstests with "-m crc=0" because > the sb_from_disk change came about after V5 became default, and > the above behavior only exists on a V4 superblock. > > Reported-by: Eryu Guan <eguan@redhat.com> > Signed-off-by: Eric Sandeen <sandeen@redhat.com> > --- > > > diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c > index 45db6ae..44f3e3e 100644 > --- a/libxfs/xfs_sb.c > +++ b/libxfs/xfs_sb.c > @@ -316,13 +316,16 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) > XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; > sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); > > - if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { > + if (sbp->sb_qflags & XFS_PQUOTA_ACCT && > + sbp->sb_gquotino != NULLFSINO) { Although I agree with this check, shouldn't we report some sort of error when it happens? Once, it's not supposed to happen, and, might be a sign of corruption? Cheers > /* > * In older version of superblock, on-disk superblock only > * has sb_gquotino, and in-core superblock has both sb_gquotino > * and sb_pquotino. But, only one of them is supported at any > * point of time. So, if PQUOTA is set in disk superblock, > - * copy over sb_gquotino to sb_pquotino. > + * copy over sb_gquotino to sb_pquotino. The NULLFSINO test > + * above is to make sure we don't do this twice and wipe them > + * both out! > */ > sbp->sb_pquotino = sbp->sb_gquotino; > sbp->sb_gquotino = NULLFSINO; > diff --git a/repair/sb.c b/repair/sb.c > index 3965953..8087242 100644 > --- a/repair/sb.c > +++ b/repair/sb.c > @@ -155,7 +155,6 @@ __find_secondary_sb( > for (i = 0; !done && i < bsize; i += BBSIZE) { > c_bufsb = (char *)sb + i; > libxfs_sb_from_disk(&bufsb, (xfs_dsb_t *)c_bufsb); > - libxfs_sb_quota_from_disk(&bufsb); > > if (verify_sb(c_bufsb, &bufsb, 0) != XR_OK) > continue; > @@ -568,7 +567,6 @@ get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno) > do_error("%s\n", strerror(error)); > } > libxfs_sb_from_disk(sbp, buf); > - libxfs_sb_quota_from_disk(sbp); > > rval = verify_sb((char *)buf, sbp, agno == 0); > free(buf); > diff --git a/repair/scan.c b/repair/scan.c > index 964ff06..366ce16 100644 > --- a/repair/scan.c > +++ b/repair/scan.c > @@ -1622,7 +1622,6 @@ scan_ag( > goto out_free_sb; > } > libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbbuf)); > - libxfs_sb_quota_from_disk(sb); > > agfbuf = libxfs_readbuf(mp->m_dev, > XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From sinnsonys@yandex.com Mon Jun 27 05:52:32 2016 Return-Path: <sinnsonys@yandex.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=FREEMAIL_FROM, T_FILL_THIS_FORM_SHORT autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AAA587CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 05:52:32 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7C3E08F8035 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 03:52:29 -0700 (PDT) X-ASG-Debug-ID: 1467024747-04cbb02738260620001-NocioJ Received: from 681818.com ([192.210.174.196]) by cuda.sgi.com with ESMTP id DspsxjE13rc9SaB5 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 03:52:27 -0700 (PDT) X-Barracuda-Envelope-From: sinnsonys@yandex.com X-Barracuda-Effective-Source-IP: UNKNOWN[192.210.174.196] X-Barracuda-Apparent-Source-IP: 192.210.174.196 To: xfs@oss.sgi.com Subject: interested in becoming our distributor? Message-ID: <2a051d90387ccf089142a7336ba520f7@cleardisplays.com> X-ASG-Orig-Subj: interested in becoming our distributor? Date: Mon, 27 Jun 2016 12:52:35 +0200 From: "Roy Parker" <sinnsonys@yandex.com> Reply-To: hankobibi@aliyun.com MIME-Version: 1.0 X-Mailer-LID: 3 X-Mailer-RecptId: 4686092 X-Mailer-SID: 1550 X-Mailer-Sent-By: 1 Content-Type: text/plain; format=flowed; charset="UTF-8" Content-Transfer-Encoding: 8bit X-Barracuda-Connect: UNKNOWN[192.210.174.196] X-Barracuda-Start-Time: 1467024747 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 830 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=ADVANCE_FEE_1, BSF_SC5_MJ1963, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30797 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 ADVANCE_FEE_1 Appears to be advance fee fraud (Nigerian 419) 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Hi, Did you receive my last email? We are a 27 year old USA based company. We manufacture slip-resistant floor treatments We need distributors worldwide. One 30 minute treatment will make all types of floors slip resistant and safe for a minimum of 4 years. Can be used indoors or outdoors. No change in appearance Use on: ceramic, porcelain quarry tiles, marble, granite, concrete etc Typical applications: hotels hospitals, restaurant kitchen floors, , office buildings, etc. Some of our current customers: Kroger, McDonald's, Holiday Inn Miami Children's Hospital Contact us for details and to check if there is a distributorship available in your country. 5,000 USD required to start distributorship Please include your name, country and email address. Thanks, Roy Parker From bfoster@redhat.com Mon Jun 27 08:15:04 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 564127CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 08:15:04 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 93307AC002 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 06:15:00 -0700 (PDT) X-ASG-Debug-ID: 1467033296-04cbb027362720f0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id sB85e4Kv4jHCppFp (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 06:14:57 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4D5F77F09C; Mon, 27 Jun 2016 13:14:56 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-2.bos.redhat.com [10.18.41.2]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5RDEtSL015825; Mon, 27 Jun 2016 09:14:55 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 9FC261201DB; Mon, 27 Jun 2016 09:14:54 -0400 (EDT) Date: Mon, 27 Jun 2016 09:14:54 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 016/119] xfs: move deferred operations into a separate file Message-ID: <20160627131452.GA23076@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 016/119] xfs: move deferred operations into a separate file References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612637438.12839.12318902006860455847.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612637438.12839.12318902006860455847.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Mon, 27 Jun 2016 13:14:56 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467033297 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 27230 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:34PM -0700, Darrick J. Wong wrote: > All the code around struct xfs_bmap_free basically implements a > deferred operation framework through which we can roll transactions > (to unlock buffers and avoid violating lock order rules) while > managing all the necessary log redo items. Previously we only used > this code to free extents after some sort of mapping operation, but > with the advent of rmap and reflink, we suddenly need to do more than > that. > > With that in mind, xfs_bmap_free really becomes a deferred ops control > structure. Rename the structure and move the deferred ops into their > own file to avoid further bloating of the bmap code. > > v2: actually sort the work items by AG to avoid deadlocks > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- So if I'm following this correctly, we 1.) abstract the bmap freeing infrastructure into a generic mechanism and 2.) enhance it a bit to provide things like partial intent completion, etc. If so and for future reference, this would probably be easier to review if the abstraction and enhancement were done separately. It's probably not worth that at this point, however... > fs/xfs/Makefile | 2 > fs/xfs/libxfs/xfs_defer.c | 471 +++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/libxfs/xfs_defer.h | 96 +++++++++ > fs/xfs/xfs_defer_item.c | 36 +++ > fs/xfs/xfs_super.c | 2 > 5 files changed, 607 insertions(+) > create mode 100644 fs/xfs/libxfs/xfs_defer.c > create mode 100644 fs/xfs/libxfs/xfs_defer.h > create mode 100644 fs/xfs/xfs_defer_item.c > > > diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile > index 3542d94..ad46a2d 100644 > --- a/fs/xfs/Makefile > +++ b/fs/xfs/Makefile > @@ -39,6 +39,7 @@ xfs-y += $(addprefix libxfs/, \ > xfs_btree.o \ > xfs_da_btree.o \ > xfs_da_format.o \ > + xfs_defer.o \ > xfs_dir2.o \ > xfs_dir2_block.o \ > xfs_dir2_data.o \ > @@ -66,6 +67,7 @@ xfs-y += xfs_aops.o \ > xfs_attr_list.o \ > xfs_bmap_util.o \ > xfs_buf.o \ > + xfs_defer_item.o \ > xfs_dir2_readdir.o \ > xfs_discard.o \ > xfs_error.o \ > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c > new file mode 100644 > index 0000000..ad14e33e > --- /dev/null > +++ b/fs/xfs/libxfs/xfs_defer.c > @@ -0,0 +1,471 @@ > +/* > + * Copyright (C) 2016 Oracle. All Rights Reserved. > + * > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it would be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software Foundation, > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > + */ > +#include "xfs.h" > +#include "xfs_fs.h" > +#include "xfs_shared.h" > +#include "xfs_format.h" > +#include "xfs_log_format.h" > +#include "xfs_trans_resv.h" > +#include "xfs_bit.h" > +#include "xfs_sb.h" > +#include "xfs_mount.h" > +#include "xfs_defer.h" > +#include "xfs_trans.h" > +#include "xfs_trace.h" > + > +/* > + * Deferred Operations in XFS > + * > + * Due to the way locking rules work in XFS, certain transactions (block > + * mapping and unmapping, typically) have permanent reservations so that > + * we can roll the transaction to adhere to AG locking order rules and > + * to unlock buffers between metadata updates. Prior to rmap/reflink, > + * the mapping code had a mechanism to perform these deferrals for > + * extents that were going to be freed; this code makes that facility > + * more generic. > + * > + * When adding the reverse mapping and reflink features, it became > + * necessary to perform complex remapping multi-transactions to comply > + * with AG locking order rules, and to be able to spread a single > + * refcount update operation (an operation on an n-block extent can > + * update as many as n records!) among multiple transactions. XFS can > + * roll a transaction to facilitate this, but using this facility > + * requires us to log "intent" items in case log recovery needs to > + * redo the operation, and to log "done" items to indicate that redo > + * is not necessary. > + * > + * The xfs_defer_ops structure tracks incoming deferred work (which is > + * work that has not yet had an intent logged) in xfs_defer_intake. Do you mean xfs_defer_pending rather than xfs_defer_intake? > + * There is one xfs_defer_intake for each type of deferrable > + * operation. Each new deferral is placed in the op's intake list, > + * where it waits for the caller to finish the deferred operations. > + * > + * Finishing a set of deferred operations is an involved process. To > + * start, we define "rolling a deferred-op transaction" as follows: > + * > + * > For each xfs_defer_intake, > + * - Sort the items on the intake list in AG order. > + * - Create a log intent item for that type. > + * - Attach to it the items on the intake list. > + * - Stash the intent+items for later in an xfs_defer_pending. Does this mean "the pending list?" Thanks for the big comment and example below. It looks that perhaps terminology is a bit out of sync with the latest code (I'm guessing design and data structures evolved a bit since this was written). > + * - Attach the xfs_defer_pending to the xfs_defer_ops work list. > + * > Roll the transaction. > + * > + * NOTE: To avoid exceeding the transaction reservation, we limit the > + * number of items that we attach to a given xfs_defer_pending. > + * > + * The actual finishing process looks like this: > + * > + * > For each xfs_defer_pending in the xfs_defer_ops work list, > + * - Roll the deferred-op transaction as above. > + * - Create a log done item for that type, and attach it to the > + * intent item. > + * - For each work item attached to the intent item, > + * * Perform the described action. > + * * Attach the work item to the log done item. > + * * If the result of doing the work was -EAGAIN, log a fresh > + * intent item and attach all remaining work items to it. Put > + * the xfs_defer_pending item back on the work list, and repeat > + * the loop. This allows us to make partial progress even if > + * the transaction is too full to finish the job. > + * > + * The key here is that we must log an intent item for all pending > + * work items every time we roll the transaction, and that we must log > + * a done item as soon as the work is completed. With this mechanism > + * we can perform complex remapping operations, chaining intent items > + * as needed. > + * > + * This is an example of remapping the extent (E, E+B) into file X at > + * offset A and dealing with the extent (C, C+B) already being mapped > + * there: > + * +-------------------------------------------------+ > + * | Unmap file X startblock C offset A length B | t0 > + * | Intent to reduce refcount for extent (C, B) | > + * | Intent to remove rmap (X, C, A, B) | > + * | Intent to free extent (D, 1) (bmbt block) | > + * | Intent to map (X, A, B) at startblock E | > + * +-------------------------------------------------+ > + * | Map file X startblock E offset A length B | t1 > + * | Done mapping (X, E, A, B) | > + * | Intent to increase refcount for extent (E, B) | > + * | Intent to add rmap (X, E, A, B) | > + * +-------------------------------------------------+ > + * | Reduce refcount for extent (C, B) | t2 > + * | Done reducing refcount for extent (C, B) | > + * | Increase refcount for extent (E, B) | > + * | Done increasing refcount for extent (E, B) | > + * | Intent to free extent (C, B) | > + * | Intent to free extent (F, 1) (refcountbt block) | > + * | Intent to remove rmap (F, 1, REFC) | > + * +-------------------------------------------------+ > + * | Remove rmap (X, C, A, B) | t3 > + * | Done removing rmap (X, C, A, B) | > + * | Add rmap (X, E, A, B) | > + * | Done adding rmap (X, E, A, B) | > + * | Remove rmap (F, 1, REFC) | > + * | Done removing rmap (F, 1, REFC) | > + * +-------------------------------------------------+ > + * | Free extent (C, B) | t4 > + * | Done freeing extent (C, B) | > + * | Free extent (D, 1) | > + * | Done freeing extent (D, 1) | > + * | Free extent (F, 1) | > + * | Done freeing extent (F, 1) | > + * +-------------------------------------------------+ > + * > + * If we should crash before t2 commits, log recovery replays > + * the following intent items: > + * > + * - Intent to reduce refcount for extent (C, B) > + * - Intent to remove rmap (X, C, A, B) > + * - Intent to free extent (D, 1) (bmbt block) > + * - Intent to increase refcount for extent (E, B) > + * - Intent to add rmap (X, E, A, B) > + * > + * In the process of recovering, it should also generate and take care > + * of these intent items: > + * > + * - Intent to free extent (C, B) > + * - Intent to free extent (F, 1) (refcountbt block) > + * - Intent to remove rmap (F, 1, REFC) > + */ > + > +static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; > + > +/* > + * For each pending item in the intake list, log its intent item and the > + * associated extents, then add the entire intake list to the end of > + * the pending list. > + */ > +STATIC void I don't think we're using 'STATIC' any longer. Better to use 'static' so we can eventually kill off the former. > +xfs_defer_intake_work( > + struct xfs_trans *tp, > + struct xfs_defer_ops *dop) > +{ > + struct list_head *li; > + struct xfs_defer_pending *dfp; > + > + list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { > + dfp->dfp_intent = dfp->dfp_type->create_intent(tp, > + dfp->dfp_count); > + list_sort(tp->t_mountp, &dfp->dfp_work, > + dfp->dfp_type->diff_items); > + list_for_each(li, &dfp->dfp_work) > + dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); > + } > + > + list_splice_tail_init(&dop->dop_intake, &dop->dop_pending); > +} > + > +/* Abort all the intents that were committed. */ > +STATIC void > +xfs_defer_trans_abort( > + struct xfs_trans *tp, > + struct xfs_defer_ops *dop, > + int error) > +{ > + struct xfs_defer_pending *dfp; > + > + /* > + * If the transaction was committed, drop the intent reference > + * since we're bailing out of here. The other reference is > + * dropped when the intent hits the AIL. If the transaction > + * was not committed, the intent is freed by the intent item > + * unlock handler on abort. > + */ > + if (!dop->dop_committed) > + return; > + > + /* Abort intent items. */ > + list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { > + if (dfp->dfp_committed) > + dfp->dfp_type->abort_intent(dfp->dfp_intent); > + } > + > + /* Shut down FS. */ > + xfs_force_shutdown(tp->t_mountp, (error == -EFSCORRUPTED) ? > + SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR); > +} > + > +/* Roll a transaction so we can do some deferred op processing. */ > +STATIC int > +xfs_defer_trans_roll( > + struct xfs_trans **tp, > + struct xfs_defer_ops *dop, > + struct xfs_inode *ip) > +{ > + int i; > + int error; > + > + /* Log all the joined inodes except the one we passed in. */ > + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { > + if (dop->dop_inodes[i] == ip) > + continue; > + xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); > + } > + > + /* Roll the transaction. */ > + error = xfs_trans_roll(tp, ip); > + if (error) { > + xfs_defer_trans_abort(*tp, dop, error); > + return error; > + } > + dop->dop_committed = true; > + > + /* Log all the joined inodes except the one we passed in. */ Rejoin? > + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { > + if (dop->dop_inodes[i] == ip) > + continue; > + xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); > + } > + > + return error; > +} > + > +/* Do we have any work items to finish? */ > +bool > +xfs_defer_has_unfinished_work( > + struct xfs_defer_ops *dop) > +{ > + return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake); > +} > + > +/* > + * Add this inode to the deferred op. Each joined inode is relogged > + * each time we roll the transaction, in addition to any inode passed > + * to xfs_defer_finish(). > + */ > +int > +xfs_defer_join( > + struct xfs_defer_ops *dop, > + struct xfs_inode *ip) > +{ > + int i; > + > + for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) { > + if (dop->dop_inodes[i] == ip) > + return 0; > + else if (dop->dop_inodes[i] == NULL) { > + dop->dop_inodes[i] = ip; > + return 0; > + } > + } > + > + return -EFSCORRUPTED; > +} > + > +/* > + * Finish all the pending work. This involves logging intent items for > + * any work items that wandered in since the last transaction roll (if > + * one has even happened), rolling the transaction, and finishing the > + * work items in the first item on the logged-and-pending list. > + * > + * If an inode is provided, relog it to the new transaction. > + */ > +int > +xfs_defer_finish( > + struct xfs_trans **tp, > + struct xfs_defer_ops *dop, > + struct xfs_inode *ip) > +{ > + struct xfs_defer_pending *dfp; > + struct list_head *li; > + struct list_head *n; > + void *done_item = NULL; > + void *state; > + int error = 0; > + void (*cleanup_fn)(struct xfs_trans *, void *, int); > + > + ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); > + > + /* Until we run out of pending work to finish... */ > + while (xfs_defer_has_unfinished_work(dop)) { > + /* Log intents for work items sitting in the intake. */ > + xfs_defer_intake_work(*tp, dop); > + > + /* Roll the transaction. */ > + error = xfs_defer_trans_roll(tp, dop, ip); > + if (error) > + goto out; > + > + /* Mark all pending intents as committed. */ > + list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { > + if (dfp->dfp_committed) > + break; > + dfp->dfp_committed = true; > + } > + > + /* Log an intent-done item for the first pending item. */ > + dfp = list_first_entry(&dop->dop_pending, > + struct xfs_defer_pending, dfp_list); > + done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, > + dfp->dfp_count); > + cleanup_fn = dfp->dfp_type->finish_cleanup; > + > + /* Finish the work items. */ > + state = NULL; > + list_for_each_safe(li, n, &dfp->dfp_work) { > + list_del(li); > + dfp->dfp_count--; > + error = dfp->dfp_type->finish_item(*tp, dop, li, > + done_item, &state); > + if (error == -EAGAIN) { > + /* > + * If the caller needs to try again, put the > + * item back on the pending list and jump out > + * for further processing. A little confused by the terminology here. Perhaps better to say "back on the work list" rather than "pending list?" Also, what is the meaning/purpose of -EAGAIN here? This isn't used by the extent free bits so I'm missing some context. For example, is there an issue with carrying a done_item with an unexpected list count? Is it expected that xfs_defer_finish() will not return until -EAGAIN is "cleared" (does relogging below and rolling somehow address this)? > + */ > + list_add(li, &dfp->dfp_work); > + dfp->dfp_count++; > + break; > + } else if (error) { > + /* > + * Clean up after ourselves and jump out. > + * xfs_defer_cancel will take care of freeing > + * all these lists and stuff. > + */ > + if (cleanup_fn) > + cleanup_fn(*tp, state, error); > + xfs_defer_trans_abort(*tp, dop, error); > + goto out; > + } > + } > + if (error == -EAGAIN) { > + /* > + * Log a new intent, relog all the remaining work > + * item to the new intent, attach the new intent to > + * the dfp, and leave the dfp at the head of the list > + * for further processing. > + */ Similar to the above, could you elaborate on the mechanics of this with respect to the log? E.g., the comment kind of just repeats what the code does as opposed to explain why it's here. Is the point here to log a new intent in the same transaction as the done item to ensure that we (atomically) indicate that certain operations need to be replayed if this transaction hits the log and then we crash? Brian > + dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, > + dfp->dfp_count); > + list_for_each(li, &dfp->dfp_work) > + dfp->dfp_type->log_item(*tp, dfp->dfp_intent, > + li); > + } else { > + /* Done with the dfp, free it. */ > + list_del(&dfp->dfp_list); > + kmem_free(dfp); > + } > + > + if (cleanup_fn) > + cleanup_fn(*tp, state, error); > + } > + > +out: > + return error; > +} > + > +/* > + * Free up any items left in the list. > + */ > +void > +xfs_defer_cancel( > + struct xfs_defer_ops *dop) > +{ > + struct xfs_defer_pending *dfp; > + struct xfs_defer_pending *pli; > + struct list_head *pwi; > + struct list_head *n; > + > + /* > + * Free the pending items. Caller should already have arranged > + * for the intent items to be released. > + */ > + list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { > + list_del(&dfp->dfp_list); > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > + list_del(pwi); > + dfp->dfp_count--; > + dfp->dfp_type->cancel_item(pwi); > + } > + ASSERT(dfp->dfp_count == 0); > + kmem_free(dfp); > + } > + list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { > + list_del(&dfp->dfp_list); > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > + list_del(pwi); > + dfp->dfp_count--; > + dfp->dfp_type->cancel_item(pwi); > + } > + ASSERT(dfp->dfp_count == 0); > + kmem_free(dfp); > + } > +} > + > +/* Add an item for later deferred processing. */ > +void > +xfs_defer_add( > + struct xfs_defer_ops *dop, > + enum xfs_defer_ops_type type, > + struct list_head *li) > +{ > + struct xfs_defer_pending *dfp = NULL; > + > + /* > + * Add the item to a pending item at the end of the intake list. > + * If the last pending item has the same type, reuse it. Else, > + * create a new pending item at the end of the intake list. > + */ > + if (!list_empty(&dop->dop_intake)) { > + dfp = list_last_entry(&dop->dop_intake, > + struct xfs_defer_pending, dfp_list); > + if (dfp->dfp_type->type != type || > + (dfp->dfp_type->max_items && > + dfp->dfp_count >= dfp->dfp_type->max_items)) > + dfp = NULL; > + } > + if (!dfp) { > + dfp = kmem_alloc(sizeof(struct xfs_defer_pending), > + KM_SLEEP | KM_NOFS); > + dfp->dfp_type = defer_op_types[type]; > + dfp->dfp_committed = false; > + dfp->dfp_intent = NULL; > + dfp->dfp_count = 0; > + INIT_LIST_HEAD(&dfp->dfp_work); > + list_add_tail(&dfp->dfp_list, &dop->dop_intake); > + } > + > + list_add_tail(li, &dfp->dfp_work); > + dfp->dfp_count++; > +} > + > +/* Initialize a deferred operation list. */ > +void > +xfs_defer_init_op_type( > + const struct xfs_defer_op_type *type) > +{ > + defer_op_types[type->type] = type; > +} > + > +/* Initialize a deferred operation. */ > +void > +xfs_defer_init( > + struct xfs_defer_ops *dop, > + xfs_fsblock_t *fbp) > +{ > + dop->dop_committed = false; > + dop->dop_low = false; > + memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); > + *fbp = NULLFSBLOCK; > + INIT_LIST_HEAD(&dop->dop_intake); > + INIT_LIST_HEAD(&dop->dop_pending); > +} > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > new file mode 100644 > index 0000000..85c7a3a > --- /dev/null > +++ b/fs/xfs/libxfs/xfs_defer.h > @@ -0,0 +1,96 @@ > +/* > + * Copyright (C) 2016 Oracle. All Rights Reserved. > + * > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it would be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software Foundation, > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > + */ > +#ifndef __XFS_DEFER_H__ > +#define __XFS_DEFER_H__ > + > +struct xfs_defer_op_type; > + > +/* > + * Save a log intent item and a list of extents, so that we can replay > + * whatever action had to happen to the extent list and file the log done > + * item. > + */ > +struct xfs_defer_pending { > + const struct xfs_defer_op_type *dfp_type; /* function pointers */ > + struct list_head dfp_list; /* pending items */ > + bool dfp_committed; /* committed trans? */ > + void *dfp_intent; /* log intent item */ > + struct list_head dfp_work; /* work items */ > + unsigned int dfp_count; /* # extent items */ > +}; > + > +/* > + * Header for deferred operation list. > + * > + * dop_low is used by the allocator to activate the lowspace algorithm - > + * when free space is running low the extent allocator may choose to > + * allocate an extent from an AG without leaving sufficient space for > + * a btree split when inserting the new extent. In this case the allocator > + * will enable the lowspace algorithm which is supposed to allow further > + * allocations (such as btree splits and newroots) to allocate from > + * sequential AGs. In order to avoid locking AGs out of order the lowspace > + * algorithm will start searching for free space from AG 0. If the correct > + * transaction reservations have been made then this algorithm will eventually > + * find all the space it needs. > + */ > +enum xfs_defer_ops_type { > + XFS_DEFER_OPS_TYPE_MAX, > +}; > + > +#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ > + > +struct xfs_defer_ops { > + bool dop_committed; /* did any trans commit? */ > + bool dop_low; /* alloc in low mode */ > + struct list_head dop_intake; /* unlogged pending work */ > + struct list_head dop_pending; /* logged pending work */ > + > + /* relog these inodes with each roll */ > + struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; > +}; > + > +void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, > + struct list_head *h); > +int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop, > + struct xfs_inode *ip); > +void xfs_defer_cancel(struct xfs_defer_ops *dop); > +void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); > +bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); > +int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip); > + > +/* Description of a deferred type. */ > +struct xfs_defer_op_type { > + enum xfs_defer_ops_type type; > + unsigned int max_items; > + void (*abort_intent)(void *); > + void *(*create_done)(struct xfs_trans *, void *, unsigned int); > + int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, > + struct list_head *, void *, void **); > + void (*finish_cleanup)(struct xfs_trans *, void *, int); > + void (*cancel_item)(struct list_head *); > + int (*diff_items)(void *, struct list_head *, struct list_head *); > + void *(*create_intent)(struct xfs_trans *, uint); > + void (*log_item)(struct xfs_trans *, void *, struct list_head *); > +}; > + > +void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); > +void xfs_defer_init_types(void); > + > +#endif /* __XFS_DEFER_H__ */ > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > new file mode 100644 > index 0000000..849088d > --- /dev/null > +++ b/fs/xfs/xfs_defer_item.c > @@ -0,0 +1,36 @@ > +/* > + * Copyright (C) 2016 Oracle. All Rights Reserved. > + * > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it would be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software Foundation, > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > + */ > +#include "xfs.h" > +#include "xfs_fs.h" > +#include "xfs_shared.h" > +#include "xfs_format.h" > +#include "xfs_log_format.h" > +#include "xfs_trans_resv.h" > +#include "xfs_bit.h" > +#include "xfs_sb.h" > +#include "xfs_mount.h" > +#include "xfs_defer.h" > +#include "xfs_trans.h" > + > +/* Initialize the deferred operation types. */ > +void > +xfs_defer_init_types(void) > +{ > +} > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c > index 09722a7..bf63f6d 100644 > --- a/fs/xfs/xfs_super.c > +++ b/fs/xfs/xfs_super.c > @@ -46,6 +46,7 @@ > #include "xfs_quota.h" > #include "xfs_sysfs.h" > #include "xfs_ondisk.h" > +#include "xfs_defer.h" > > #include <linux/namei.h> > #include <linux/init.h> > @@ -1850,6 +1851,7 @@ init_xfs_fs(void) > printk(KERN_INFO XFS_VERSION_STRING " with " > XFS_BUILD_OPTIONS " enabled\n"); > > + xfs_defer_init_types(); > xfs_dir_startup(); > > error = xfs_init_zones(); > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Mon Jun 27 08:15:09 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 4EA087CA4 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 08:15:09 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id D37CE304032 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 06:15:05 -0700 (PDT) X-ASG-Debug-ID: 1467033303-04cb6c063f1e0860001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id DVMBPm4MSIqpbFpV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 06:15:03 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1A0D47F6A5; Mon, 27 Jun 2016 13:15:03 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-2.bos.redhat.com [10.18.41.2]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5RDF29g015967; Mon, 27 Jun 2016 09:15:02 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 8E0081201DB; Mon, 27 Jun 2016 09:15:01 -0400 (EDT) Date: Mon, 27 Jun 2016 09:15:01 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 017/119] xfs: add tracepoints for the deferred ops mechanism Message-ID: <20160627131500.GB23076@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 017/119] xfs: add tracepoints for the deferred ops mechanism References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612638080.12839.2097094526348177968.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612638080.12839.2097094526348177968.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Mon, 27 Jun 2016 13:15:03 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467033303 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12157 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:40PM -0700, Darrick J. Wong wrote: > Add tracepoints for the internals of the deferred ops mechanism > and tracepoint classes for clients of the dops, to make debugging > easier. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- Reviewed-by: Brian Foster <bfoster@redhat.com> > fs/xfs/libxfs/xfs_defer.c | 19 ++++ > fs/xfs/xfs_defer_item.c | 1 > fs/xfs/xfs_trace.c | 1 > fs/xfs/xfs_trace.h | 198 +++++++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 219 insertions(+) > > > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c > index ad14e33e..b4e7faa 100644 > --- a/fs/xfs/libxfs/xfs_defer.c > +++ b/fs/xfs/libxfs/xfs_defer.c > @@ -163,6 +163,7 @@ xfs_defer_intake_work( > struct xfs_defer_pending *dfp; > > list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { > + trace_xfs_defer_intake_work(tp->t_mountp, dfp); > dfp->dfp_intent = dfp->dfp_type->create_intent(tp, > dfp->dfp_count); > list_sort(tp->t_mountp, &dfp->dfp_work, > @@ -183,6 +184,7 @@ xfs_defer_trans_abort( > { > struct xfs_defer_pending *dfp; > > + trace_xfs_defer_trans_abort(tp->t_mountp, dop); > /* > * If the transaction was committed, drop the intent reference > * since we're bailing out of here. The other reference is > @@ -195,6 +197,7 @@ xfs_defer_trans_abort( > > /* Abort intent items. */ > list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { > + trace_xfs_defer_pending_abort(tp->t_mountp, dfp); > if (dfp->dfp_committed) > dfp->dfp_type->abort_intent(dfp->dfp_intent); > } > @@ -221,9 +224,12 @@ xfs_defer_trans_roll( > xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); > } > > + trace_xfs_defer_trans_roll((*tp)->t_mountp, dop); > + > /* Roll the transaction. */ > error = xfs_trans_roll(tp, ip); > if (error) { > + trace_xfs_defer_trans_roll_error((*tp)->t_mountp, dop, error); > xfs_defer_trans_abort(*tp, dop, error); > return error; > } > @@ -295,6 +301,8 @@ xfs_defer_finish( > > ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); > > + trace_xfs_defer_finish((*tp)->t_mountp, dop); > + > /* Until we run out of pending work to finish... */ > while (xfs_defer_has_unfinished_work(dop)) { > /* Log intents for work items sitting in the intake. */ > @@ -309,12 +317,14 @@ xfs_defer_finish( > list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { > if (dfp->dfp_committed) > break; > + trace_xfs_defer_pending_commit((*tp)->t_mountp, dfp); > dfp->dfp_committed = true; > } > > /* Log an intent-done item for the first pending item. */ > dfp = list_first_entry(&dop->dop_pending, > struct xfs_defer_pending, dfp_list); > + trace_xfs_defer_pending_finish((*tp)->t_mountp, dfp); > done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, > dfp->dfp_count); > cleanup_fn = dfp->dfp_type->finish_cleanup; > @@ -370,6 +380,10 @@ xfs_defer_finish( > } > > out: > + if (error) > + trace_xfs_defer_finish_error((*tp)->t_mountp, dop, error); > + else > + trace_xfs_defer_finish_done((*tp)->t_mountp, dop); > return error; > } > > @@ -385,11 +399,14 @@ xfs_defer_cancel( > struct list_head *pwi; > struct list_head *n; > > + trace_xfs_defer_cancel(NULL, dop); > + > /* > * Free the pending items. Caller should already have arranged > * for the intent items to be released. > */ > list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { > + trace_xfs_defer_intake_cancel(NULL, dfp); > list_del(&dfp->dfp_list); > list_for_each_safe(pwi, n, &dfp->dfp_work) { > list_del(pwi); > @@ -400,6 +417,7 @@ xfs_defer_cancel( > kmem_free(dfp); > } > list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { > + trace_xfs_defer_pending_cancel(NULL, dfp); > list_del(&dfp->dfp_list); > list_for_each_safe(pwi, n, &dfp->dfp_work) { > list_del(pwi); > @@ -468,4 +486,5 @@ xfs_defer_init( > *fbp = NULLFSBLOCK; > INIT_LIST_HEAD(&dop->dop_intake); > INIT_LIST_HEAD(&dop->dop_pending); > + trace_xfs_defer_init(NULL, dop); > } > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > index 849088d..4c2ba28 100644 > --- a/fs/xfs/xfs_defer_item.c > +++ b/fs/xfs/xfs_defer_item.c > @@ -28,6 +28,7 @@ > #include "xfs_mount.h" > #include "xfs_defer.h" > #include "xfs_trans.h" > +#include "xfs_trace.h" > > /* Initialize the deferred operation types. */ > void > diff --git a/fs/xfs/xfs_trace.c b/fs/xfs/xfs_trace.c > index 13a0298..3971527 100644 > --- a/fs/xfs/xfs_trace.c > +++ b/fs/xfs/xfs_trace.c > @@ -22,6 +22,7 @@ > #include "xfs_log_format.h" > #include "xfs_trans_resv.h" > #include "xfs_mount.h" > +#include "xfs_defer.h" > #include "xfs_da_format.h" > #include "xfs_inode.h" > #include "xfs_btree.h" > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > index f0ac9c9..5923014 100644 > --- a/fs/xfs/xfs_trace.h > +++ b/fs/xfs/xfs_trace.h > @@ -2220,6 +2220,204 @@ DEFINE_EVENT(xfs_btree_cur_class, name, \ > DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); > > +/* deferred ops */ > +struct xfs_defer_pending; > +struct xfs_defer_intake; > +struct xfs_defer_ops; > + > +DECLARE_EVENT_CLASS(xfs_defer_class, > + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop), > + TP_ARGS(mp, dop), > + TP_STRUCT__entry( > + __field(dev_t, dev) > + __field(void *, dop) > + __field(bool, committed) > + __field(bool, low) > + ), > + TP_fast_assign( > + __entry->dev = mp ? mp->m_super->s_dev : 0; > + __entry->dop = dop; > + __entry->committed = dop->dop_committed; > + __entry->low = dop->dop_low; > + ), > + TP_printk("dev %d:%d ops %p committed %d low %d\n", > + MAJOR(__entry->dev), MINOR(__entry->dev), > + __entry->dop, > + __entry->committed, > + __entry->low) > +) > +#define DEFINE_DEFER_EVENT(name) \ > +DEFINE_EVENT(xfs_defer_class, name, \ > + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop), \ > + TP_ARGS(mp, dop)) > + > +DECLARE_EVENT_CLASS(xfs_defer_error_class, > + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), > + TP_ARGS(mp, dop, error), > + TP_STRUCT__entry( > + __field(dev_t, dev) > + __field(void *, dop) > + __field(bool, committed) > + __field(bool, low) > + __field(int, error) > + ), > + TP_fast_assign( > + __entry->dev = mp ? mp->m_super->s_dev : 0; > + __entry->dop = dop; > + __entry->committed = dop->dop_committed; > + __entry->low = dop->dop_low; > + __entry->error = error; > + ), > + TP_printk("dev %d:%d ops %p committed %d low %d err %d\n", > + MAJOR(__entry->dev), MINOR(__entry->dev), > + __entry->dop, > + __entry->committed, > + __entry->low, > + __entry->error) > +) > +#define DEFINE_DEFER_ERROR_EVENT(name) \ > +DEFINE_EVENT(xfs_defer_error_class, name, \ > + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_ops *dop, int error), \ > + TP_ARGS(mp, dop, error)) > + > +DECLARE_EVENT_CLASS(xfs_defer_pending_class, > + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp), > + TP_ARGS(mp, dfp), > + TP_STRUCT__entry( > + __field(dev_t, dev) > + __field(int, type) > + __field(void *, intent) > + __field(bool, committed) > + __field(int, nr) > + ), > + TP_fast_assign( > + __entry->dev = mp ? mp->m_super->s_dev : 0; > + __entry->type = dfp->dfp_type->type; > + __entry->intent = dfp->dfp_intent; > + __entry->committed = dfp->dfp_committed; > + __entry->nr = dfp->dfp_count; > + ), > + TP_printk("dev %d:%d optype %d intent %p committed %d nr %d\n", > + MAJOR(__entry->dev), MINOR(__entry->dev), > + __entry->type, > + __entry->intent, > + __entry->committed, > + __entry->nr) > +) > +#define DEFINE_DEFER_PENDING_EVENT(name) \ > +DEFINE_EVENT(xfs_defer_pending_class, name, \ > + TP_PROTO(struct xfs_mount *mp, struct xfs_defer_pending *dfp), \ > + TP_ARGS(mp, dfp)) > + > +DECLARE_EVENT_CLASS(xfs_phys_extent_deferred_class, > + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, > + int type, xfs_agblock_t agbno, xfs_extlen_t len), > + TP_ARGS(mp, agno, type, agbno, len), > + TP_STRUCT__entry( > + __field(dev_t, dev) > + __field(xfs_agnumber_t, agno) > + __field(int, type) > + __field(xfs_agblock_t, agbno) > + __field(xfs_extlen_t, len) > + ), > + TP_fast_assign( > + __entry->dev = mp->m_super->s_dev; > + __entry->agno = agno; > + __entry->type = type; > + __entry->agbno = agbno; > + __entry->len = len; > + ), > + TP_printk("dev %d:%d op %d agno %u agbno %u len %u", > + MAJOR(__entry->dev), MINOR(__entry->dev), > + __entry->type, > + __entry->agno, > + __entry->agbno, > + __entry->len) > +); > +#define DEFINE_PHYS_EXTENT_DEFERRED_EVENT(name) \ > +DEFINE_EVENT(xfs_phys_extent_deferred_class, name, \ > + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ > + int type, \ > + xfs_agblock_t bno, \ > + xfs_extlen_t len), \ > + TP_ARGS(mp, agno, type, bno, len)) > + > +DECLARE_EVENT_CLASS(xfs_map_extent_deferred_class, > + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, > + int op, > + xfs_agblock_t agbno, > + xfs_ino_t ino, > + int whichfork, > + xfs_fileoff_t offset, > + xfs_filblks_t len, > + xfs_exntst_t state), > + TP_ARGS(mp, agno, op, agbno, ino, whichfork, offset, len, state), > + TP_STRUCT__entry( > + __field(dev_t, dev) > + __field(xfs_agnumber_t, agno) > + __field(xfs_ino_t, ino) > + __field(xfs_agblock_t, agbno) > + __field(int, whichfork) > + __field(xfs_fileoff_t, l_loff) > + __field(xfs_filblks_t, l_len) > + __field(xfs_exntst_t, l_state) > + __field(int, op) > + ), > + TP_fast_assign( > + __entry->dev = mp->m_super->s_dev; > + __entry->agno = agno; > + __entry->ino = ino; > + __entry->agbno = agbno; > + __entry->whichfork = whichfork; > + __entry->l_loff = offset; > + __entry->l_len = len; > + __entry->l_state = state; > + __entry->op = op; > + ), > + TP_printk("dev %d:%d op %d agno %u agbno %u owner %lld %s offset %llu len %llu state %d", > + MAJOR(__entry->dev), MINOR(__entry->dev), > + __entry->op, > + __entry->agno, > + __entry->agbno, > + __entry->ino, > + __entry->whichfork == XFS_ATTR_FORK ? "attr" : "data", > + __entry->l_loff, > + __entry->l_len, > + __entry->l_state) > +); > +#define DEFINE_MAP_EXTENT_DEFERRED_EVENT(name) \ > +DEFINE_EVENT(xfs_map_extent_deferred_class, name, \ > + TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \ > + int op, \ > + xfs_agblock_t agbno, \ > + xfs_ino_t ino, \ > + int whichfork, \ > + xfs_fileoff_t offset, \ > + xfs_filblks_t len, \ > + xfs_exntst_t state), \ > + TP_ARGS(mp, agno, op, agbno, ino, whichfork, offset, len, state)) > + > +DEFINE_DEFER_EVENT(xfs_defer_init); > +DEFINE_DEFER_EVENT(xfs_defer_cancel); > +DEFINE_DEFER_EVENT(xfs_defer_trans_roll); > +DEFINE_DEFER_EVENT(xfs_defer_trans_abort); > +DEFINE_DEFER_EVENT(xfs_defer_finish); > +DEFINE_DEFER_EVENT(xfs_defer_finish_done); > + > +DEFINE_DEFER_ERROR_EVENT(xfs_defer_trans_roll_error); > +DEFINE_DEFER_ERROR_EVENT(xfs_defer_finish_error); > +DEFINE_DEFER_ERROR_EVENT(xfs_defer_op_finish_error); > + > +DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_work); > +DEFINE_DEFER_PENDING_EVENT(xfs_defer_intake_cancel); > +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_commit); > +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_cancel); > +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_finish); > +DEFINE_DEFER_PENDING_EVENT(xfs_defer_pending_abort); > + > +DEFINE_PHYS_EXTENT_DEFERRED_EVENT(xfs_defer_phys_extent); > +DEFINE_MAP_EXTENT_DEFERRED_EVENT(xfs_defer_map_extent); > + > #endif /* _TRACE_XFS_H */ > > #undef TRACE_INCLUDE_PATH > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Mon Jun 27 08:15:12 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 66CDE7CB2 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 08:15:12 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3A34B304032 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 06:15:12 -0700 (PDT) X-ASG-Debug-ID: 1467033310-04cbb02736272140001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id HcvTZH7pRKfpljUq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 06:15:10 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id F02A7C04B318; Mon, 27 Jun 2016 13:15:09 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-2.bos.redhat.com [10.18.41.2]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5RDF9Zi021539; Mon, 27 Jun 2016 09:15:09 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id A0A141201DB; Mon, 27 Jun 2016 09:15:08 -0400 (EDT) Date: Mon, 27 Jun 2016 09:15:08 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free Message-ID: <20160627131508.GC23076@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612638717.12839.11007379793448761871.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612638717.12839.11007379793448761871.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 27 Jun 2016 13:15:10 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467033310 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4539 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:19:47PM -0700, Darrick J. Wong wrote: > Connect the xfs_defer mechanism with the pieces that we'll need to > handle deferred extent freeing. We'll wire up the existing code to > our new deferred mechanism later. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- Could we merge this with the xfs_trans_*efi/efd* bits? We'd need to preserve some calls for recovery, but it looks like other parts are only used by the deferred ops infrastructure at this point. Brian > fs/xfs/libxfs/xfs_defer.h | 1 > fs/xfs/xfs_defer_item.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 109 insertions(+) > > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > index 85c7a3a..743fc32 100644 > --- a/fs/xfs/libxfs/xfs_defer.h > +++ b/fs/xfs/libxfs/xfs_defer.h > @@ -51,6 +51,7 @@ struct xfs_defer_pending { > * find all the space it needs. > */ > enum xfs_defer_ops_type { > + XFS_DEFER_OPS_TYPE_FREE, > XFS_DEFER_OPS_TYPE_MAX, > }; > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > index 4c2ba28..127a54e 100644 > --- a/fs/xfs/xfs_defer_item.c > +++ b/fs/xfs/xfs_defer_item.c > @@ -29,9 +29,117 @@ > #include "xfs_defer.h" > #include "xfs_trans.h" > #include "xfs_trace.h" > +#include "xfs_bmap.h" > +#include "xfs_extfree_item.h" > + > +/* Extent Freeing */ > + > +/* Sort bmap items by AG. */ > +static int > +xfs_bmap_free_diff_items( > + void *priv, > + struct list_head *a, > + struct list_head *b) > +{ > + struct xfs_mount *mp = priv; > + struct xfs_bmap_free_item *ra; > + struct xfs_bmap_free_item *rb; > + > + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); > + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); > + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - > + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); > +} > + > +/* Get an EFI. */ > +STATIC void * > +xfs_bmap_free_create_intent( > + struct xfs_trans *tp, > + unsigned int count) > +{ > + return xfs_trans_get_efi(tp, count); > +} > + > +/* Log a free extent to the intent item. */ > +STATIC void > +xfs_bmap_free_log_item( > + struct xfs_trans *tp, > + void *intent, > + struct list_head *item) > +{ > + struct xfs_bmap_free_item *free; > + > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > + xfs_trans_log_efi_extent(tp, intent, free->xbfi_startblock, > + free->xbfi_blockcount); > +} > + > +/* Get an EFD so we can process all the free extents. */ > +STATIC void * > +xfs_bmap_free_create_done( > + struct xfs_trans *tp, > + void *intent, > + unsigned int count) > +{ > + return xfs_trans_get_efd(tp, intent, count); > +} > + > +/* Process a free extent. */ > +STATIC int > +xfs_bmap_free_finish_item( > + struct xfs_trans *tp, > + struct xfs_defer_ops *dop, > + struct list_head *item, > + void *done_item, > + void **state) > +{ > + struct xfs_bmap_free_item *free; > + int error; > + > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > + error = xfs_trans_free_extent(tp, done_item, > + free->xbfi_startblock, > + free->xbfi_blockcount); > + kmem_free(free); > + return error; > +} > + > +/* Abort all pending EFIs. */ > +STATIC void > +xfs_bmap_free_abort_intent( > + void *intent) > +{ > + xfs_efi_release(intent); > +} > + > +/* Cancel a free extent. */ > +STATIC void > +xfs_bmap_free_cancel_item( > + struct list_head *item) > +{ > + struct xfs_bmap_free_item *free; > + > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > + kmem_free(free); > +} > + > +const struct xfs_defer_op_type xfs_extent_free_defer_type = { > + .type = XFS_DEFER_OPS_TYPE_FREE, > + .max_items = XFS_EFI_MAX_FAST_EXTENTS, > + .diff_items = xfs_bmap_free_diff_items, > + .create_intent = xfs_bmap_free_create_intent, > + .abort_intent = xfs_bmap_free_abort_intent, > + .log_item = xfs_bmap_free_log_item, > + .create_done = xfs_bmap_free_create_done, > + .finish_item = xfs_bmap_free_finish_item, > + .cancel_item = xfs_bmap_free_cancel_item, > +}; > + > +/* Deferred Item Initialization */ > > /* Initialize the deferred operation types. */ > void > xfs_defer_init_types(void) > { > + xfs_defer_init_op_type(&xfs_extent_free_defer_type); > } > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From sandeen@sandeen.net Mon Jun 27 10:34:46 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 9641D7CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 10:34:46 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 5A4C8304048 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 08:34:43 -0700 (PDT) X-ASG-Debug-ID: 1467041679-04cbb0273827dd10001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id nnjyXHEF92vCZxfU for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 08:34:40 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id BCE132A9D for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 10:34:39 -0500 (CDT) Subject: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice References: <13dd3974-956d-c3af-86ed-f6ce5cc1b996@redhat.com> <20160627094855.GC29774@redhat.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <5c408cf1-e9fa-8bee-106e-93e553fc98a7@sandeen.net> Date: Mon, 27 Jun 2016 10:34:39 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160627094855.GC29774@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1467041680 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2006 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30801 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/27/16 4:48 AM, Carlos Maiolino wrote: > On Fri, Jun 24, 2016 at 04:24:58PM -0500, Eric Sandeen wrote: >> kernel commit 5ef828c4 >> xfs: avoid false quotacheck after unclean shutdown >> >> made xfs_sb_from_disk() also call xfs_sb_quota_from_disk >> by default. >> >> However, when this was merged to libxfs, existing separate >> calls to libxfs_sb_quota_from_disk remained, and calling it >> twice in a row on a V4 superblock leads to issues, because: >> >> >> if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { >> ... >> sbp->sb_pquotino = sbp->sb_gquotino; >> sbp->sb_gquotino = NULLFSINO; >> >> and after the second call, we have set both pquotino and gquotino >> to NULLFSINO. >> >> Fix this by making it safe to call twice, and also remove the extra >> calls to libxfs_sb_quota_from_disk. >> >> This is only spotted when running xfstests with "-m crc=0" because >> the sb_from_disk change came about after V5 became default, and >> the above behavior only exists on a V4 superblock. >> >> Reported-by: Eryu Guan <eguan@redhat.com> >> Signed-off-by: Eric Sandeen <sandeen@redhat.com> >> --- >> >> >> diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c >> index 45db6ae..44f3e3e 100644 >> --- a/libxfs/xfs_sb.c >> +++ b/libxfs/xfs_sb.c >> @@ -316,13 +316,16 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) >> XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; >> sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); >> >> - if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { >> + if (sbp->sb_qflags & XFS_PQUOTA_ACCT && >> + sbp->sb_gquotino != NULLFSINO) { > > Although I agree with this check, shouldn't we report some sort of error when it > happens? Once, it's not supposed to happen, and, might be a sign of corruption? I dunno, it would also happen if it gets called twice, which is intentionally made harmless by this change. We don't warn on free(NULL) for example... I don't think it needs a warning. -Eric From darrick.wong@oracle.com Mon Jun 27 14:14:25 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1742E7CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 14:14:25 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6877FAC001 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 12:14:21 -0700 (PDT) X-ASG-Debug-ID: 1467054852-04cbb02736294eb0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id rAWGuZNMT07dwzBs (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 12:14:12 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5RJE6mI027476 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 19:14:06 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5RJE5ef011563 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 19:14:05 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5RJE3mj008690; Mon, 27 Jun 2016 19:14:04 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 27 Jun 2016 12:14:02 -0700 Date: Mon, 27 Jun 2016 12:14:01 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 016/119] xfs: move deferred operations into a separate file Message-ID: <20160627191401.GA4921@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 016/119] xfs: move deferred operations into a separate file References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612637438.12839.12318902006860455847.stgit@birch.djwong.org> <20160627131452.GA23076@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160627131452.GA23076@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467054852 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 32645 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30808 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 27, 2016 at 09:14:54AM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:19:34PM -0700, Darrick J. Wong wrote: > > All the code around struct xfs_bmap_free basically implements a > > deferred operation framework through which we can roll transactions > > (to unlock buffers and avoid violating lock order rules) while > > managing all the necessary log redo items. Previously we only used > > this code to free extents after some sort of mapping operation, but > > with the advent of rmap and reflink, we suddenly need to do more than > > that. > > > > With that in mind, xfs_bmap_free really becomes a deferred ops control > > structure. Rename the structure and move the deferred ops into their > > own file to avoid further bloating of the bmap code. > > > > v2: actually sort the work items by AG to avoid deadlocks > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > So if I'm following this correctly, we 1.) abstract the bmap freeing > infrastructure into a generic mechanism and 2.) enhance it a bit to > provide things like partial intent completion, etc. [Back from vacation] Yup. The partial intent completion code is for use by the refcount adjust function because in the worst case an adjustment of N blocks could require N record updates. > If so and for future > reference, this would probably be easier to review if the abstraction > and enhancement were done separately. It's probably not worth that at > this point, however... It wouldn't be difficult to separate them; the partial intent completion are the two code blocks below that handle the -EAGAIN case. (On the other hand it's so little code that I figured I might as well just do the whole file all at once.) > > fs/xfs/Makefile | 2 > > fs/xfs/libxfs/xfs_defer.c | 471 +++++++++++++++++++++++++++++++++++++++++++++ > > fs/xfs/libxfs/xfs_defer.h | 96 +++++++++ > > fs/xfs/xfs_defer_item.c | 36 +++ > > fs/xfs/xfs_super.c | 2 > > 5 files changed, 607 insertions(+) > > create mode 100644 fs/xfs/libxfs/xfs_defer.c > > create mode 100644 fs/xfs/libxfs/xfs_defer.h > > create mode 100644 fs/xfs/xfs_defer_item.c > > > > > > diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile > > index 3542d94..ad46a2d 100644 > > --- a/fs/xfs/Makefile > > +++ b/fs/xfs/Makefile > > @@ -39,6 +39,7 @@ xfs-y += $(addprefix libxfs/, \ > > xfs_btree.o \ > > xfs_da_btree.o \ > > xfs_da_format.o \ > > + xfs_defer.o \ > > xfs_dir2.o \ > > xfs_dir2_block.o \ > > xfs_dir2_data.o \ > > @@ -66,6 +67,7 @@ xfs-y += xfs_aops.o \ > > xfs_attr_list.o \ > > xfs_bmap_util.o \ > > xfs_buf.o \ > > + xfs_defer_item.o \ > > xfs_dir2_readdir.o \ > > xfs_discard.o \ > > xfs_error.o \ > > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c > > new file mode 100644 > > index 0000000..ad14e33e > > --- /dev/null > > +++ b/fs/xfs/libxfs/xfs_defer.c > > @@ -0,0 +1,471 @@ > > +/* > > + * Copyright (C) 2016 Oracle. All Rights Reserved. > > + * > > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License > > + * as published by the Free Software Foundation; either version 2 > > + * of the License, or (at your option) any later version. > > + * > > + * This program is distributed in the hope that it would be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public License > > + * along with this program; if not, write the Free Software Foundation, > > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > + */ > > +#include "xfs.h" > > +#include "xfs_fs.h" > > +#include "xfs_shared.h" > > +#include "xfs_format.h" > > +#include "xfs_log_format.h" > > +#include "xfs_trans_resv.h" > > +#include "xfs_bit.h" > > +#include "xfs_sb.h" > > +#include "xfs_mount.h" > > +#include "xfs_defer.h" > > +#include "xfs_trans.h" > > +#include "xfs_trace.h" > > + > > +/* > > + * Deferred Operations in XFS > > + * > > + * Due to the way locking rules work in XFS, certain transactions (block > > + * mapping and unmapping, typically) have permanent reservations so that > > + * we can roll the transaction to adhere to AG locking order rules and > > + * to unlock buffers between metadata updates. Prior to rmap/reflink, > > + * the mapping code had a mechanism to perform these deferrals for > > + * extents that were going to be freed; this code makes that facility > > + * more generic. > > + * > > + * When adding the reverse mapping and reflink features, it became > > + * necessary to perform complex remapping multi-transactions to comply > > + * with AG locking order rules, and to be able to spread a single > > + * refcount update operation (an operation on an n-block extent can > > + * update as many as n records!) among multiple transactions. XFS can > > + * roll a transaction to facilitate this, but using this facility > > + * requires us to log "intent" items in case log recovery needs to > > + * redo the operation, and to log "done" items to indicate that redo > > + * is not necessary. > > + * > > + * The xfs_defer_ops structure tracks incoming deferred work (which is > > + * work that has not yet had an intent logged) in xfs_defer_intake. > > Do you mean xfs_defer_pending rather than xfs_defer_intake? Ugh, I forgot to update the documentation. Unlogged work originally got its own xfs_defer_intake item, but I then realized that it was basically a subset of xfs_defer_pending. Then I reorganized the data structures so that we create one x_d_p, attach items to it, and later log the redo item and move it from the intake list to the pending list. So.... doc changes will be inline in the message. Just replace the whole paragraph with: "* Deferred work is tracked in xfs_defer_pending items. Each pending * item tracks one type of deferred work. Incoming work items (which * have not yet had an intent logged) are attached to a pending item * on the dop_intake list, where they wait for the caller to finish * the deferred operations." > > + * There is one xfs_defer_intake for each type of deferrable > > + * operation. Each new deferral is placed in the op's intake list, > > + * where it waits for the caller to finish the deferred operations. > > + * > > + * Finishing a set of deferred operations is an involved process. To > > + * start, we define "rolling a deferred-op transaction" as follows: > > + * > > + * > For each xfs_defer_intake, "For each xfs_defer_pending on the dop_intake list," > > + * - Sort the items on the intake list in AG order. "Sort the work items in AG order. XFS locking order rules require us to lock buffers in AG order." > > + * - Create a log intent item for that type. > > + * - Attach to it the items on the intake list. "Attach it to the pending item." > > + * - Stash the intent+items for later in an xfs_defer_pending. > > Does this mean "the pending list?" No, the intent and work items are already attached to the x_d_p item. This should read: "Move the xfs_defer_pending item from the dop_intake list to the dop_pending list." > Thanks for the big comment and example below. It looks that perhaps > terminology is a bit out of sync with the latest code (I'm guessing > design and data structures evolved a bit since this was written). Yes. > > + * - Attach the xfs_defer_pending to the xfs_defer_ops work list. This line becomes redundant with above. > > + * > Roll the transaction. > > + * > > + * NOTE: To avoid exceeding the transaction reservation, we limit the > > + * number of items that we attach to a given xfs_defer_pending. > > + * > > + * The actual finishing process looks like this: > > + * > > + * > For each xfs_defer_pending in the xfs_defer_ops work list, "For each xfs_defer_pending in the dop_pending list," > > + * - Roll the deferred-op transaction as above. > > + * - Create a log done item for that type, and attach it to the > > + * intent item. > > + * - For each work item attached to the intent item, > > + * * Perform the described action. > > + * * Attach the work item to the log done item. > > + * * If the result of doing the work was -EAGAIN, log a fresh > > + * intent item and attach all remaining work items to it. Put > > + * the xfs_defer_pending item back on the work list, and repeat > > + * the loop. This allows us to make partial progress even if > > + * the transaction is too full to finish the job. > > + * > > + * The key here is that we must log an intent item for all pending > > + * work items every time we roll the transaction, and that we must log > > + * a done item as soon as the work is completed. With this mechanism > > + * we can perform complex remapping operations, chaining intent items > > + * as needed. > > + * > > + * This is an example of remapping the extent (E, E+B) into file X at > > + * offset A and dealing with the extent (C, C+B) already being mapped > > + * there: > > + * +-------------------------------------------------+ > > + * | Unmap file X startblock C offset A length B | t0 > > + * | Intent to reduce refcount for extent (C, B) | > > + * | Intent to remove rmap (X, C, A, B) | > > + * | Intent to free extent (D, 1) (bmbt block) | > > + * | Intent to map (X, A, B) at startblock E | > > + * +-------------------------------------------------+ > > + * | Map file X startblock E offset A length B | t1 > > + * | Done mapping (X, E, A, B) | > > + * | Intent to increase refcount for extent (E, B) | > > + * | Intent to add rmap (X, E, A, B) | > > + * +-------------------------------------------------+ > > + * | Reduce refcount for extent (C, B) | t2 > > + * | Done reducing refcount for extent (C, B) | > > + * | Increase refcount for extent (E, B) | > > + * | Done increasing refcount for extent (E, B) | > > + * | Intent to free extent (C, B) | > > + * | Intent to free extent (F, 1) (refcountbt block) | > > + * | Intent to remove rmap (F, 1, REFC) | > > + * +-------------------------------------------------+ > > + * | Remove rmap (X, C, A, B) | t3 > > + * | Done removing rmap (X, C, A, B) | > > + * | Add rmap (X, E, A, B) | > > + * | Done adding rmap (X, E, A, B) | > > + * | Remove rmap (F, 1, REFC) | > > + * | Done removing rmap (F, 1, REFC) | > > + * +-------------------------------------------------+ > > + * | Free extent (C, B) | t4 > > + * | Done freeing extent (C, B) | > > + * | Free extent (D, 1) | > > + * | Done freeing extent (D, 1) | > > + * | Free extent (F, 1) | > > + * | Done freeing extent (F, 1) | > > + * +-------------------------------------------------+ > > + * > > + * If we should crash before t2 commits, log recovery replays > > + * the following intent items: > > + * > > + * - Intent to reduce refcount for extent (C, B) > > + * - Intent to remove rmap (X, C, A, B) > > + * - Intent to free extent (D, 1) (bmbt block) > > + * - Intent to increase refcount for extent (E, B) > > + * - Intent to add rmap (X, E, A, B) > > + * > > + * In the process of recovering, it should also generate and take care > > + * of these intent items: > > + * > > + * - Intent to free extent (C, B) > > + * - Intent to free extent (F, 1) (refcountbt block) > > + * - Intent to remove rmap (F, 1, REFC) > > + */ > > + > > +static const struct xfs_defer_op_type *defer_op_types[XFS_DEFER_OPS_TYPE_MAX]; > > + > > +/* > > + * For each pending item in the intake list, log its intent item and the > > + * associated extents, then add the entire intake list to the end of > > + * the pending list. > > + */ > > +STATIC void > > I don't think we're using 'STATIC' any longer. Better to use 'static' so > we can eventually kill off the former. <shrug> For debugging I've found it useful to have all these internal functions show up in stack traces, etc. On the other hand, I've noticed that all the new patches have eschewed STATIC for static. Will queue this for the next time I do full-patchbomb edits. > > +xfs_defer_intake_work( > > + struct xfs_trans *tp, > > + struct xfs_defer_ops *dop) > > +{ > > + struct list_head *li; > > + struct xfs_defer_pending *dfp; > > + > > + list_for_each_entry(dfp, &dop->dop_intake, dfp_list) { > > + dfp->dfp_intent = dfp->dfp_type->create_intent(tp, > > + dfp->dfp_count); > > + list_sort(tp->t_mountp, &dfp->dfp_work, > > + dfp->dfp_type->diff_items); > > + list_for_each(li, &dfp->dfp_work) > > + dfp->dfp_type->log_item(tp, dfp->dfp_intent, li); > > + } > > + > > + list_splice_tail_init(&dop->dop_intake, &dop->dop_pending); > > +} > > + > > +/* Abort all the intents that were committed. */ > > +STATIC void > > +xfs_defer_trans_abort( > > + struct xfs_trans *tp, > > + struct xfs_defer_ops *dop, > > + int error) > > +{ > > + struct xfs_defer_pending *dfp; > > + > > + /* > > + * If the transaction was committed, drop the intent reference > > + * since we're bailing out of here. The other reference is > > + * dropped when the intent hits the AIL. If the transaction > > + * was not committed, the intent is freed by the intent item > > + * unlock handler on abort. > > + */ > > + if (!dop->dop_committed) > > + return; > > + > > + /* Abort intent items. */ > > + list_for_each_entry(dfp, &dop->dop_pending, dfp_list) { > > + if (dfp->dfp_committed) > > + dfp->dfp_type->abort_intent(dfp->dfp_intent); > > + } > > + > > + /* Shut down FS. */ > > + xfs_force_shutdown(tp->t_mountp, (error == -EFSCORRUPTED) ? > > + SHUTDOWN_CORRUPT_INCORE : SHUTDOWN_META_IO_ERROR); > > +} > > + > > +/* Roll a transaction so we can do some deferred op processing. */ > > +STATIC int > > +xfs_defer_trans_roll( > > + struct xfs_trans **tp, > > + struct xfs_defer_ops *dop, > > + struct xfs_inode *ip) > > +{ > > + int i; > > + int error; > > + > > + /* Log all the joined inodes except the one we passed in. */ > > + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { > > + if (dop->dop_inodes[i] == ip) > > + continue; > > + xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); > > + } > > + > > + /* Roll the transaction. */ > > + error = xfs_trans_roll(tp, ip); > > + if (error) { > > + xfs_defer_trans_abort(*tp, dop, error); > > + return error; > > + } > > + dop->dop_committed = true; > > + > > + /* Log all the joined inodes except the one we passed in. */ > > Rejoin? Er, yes. :) > > + for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++) { > > + if (dop->dop_inodes[i] == ip) > > + continue; > > + xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); > > + } > > + > > + return error; > > +} > > + > > +/* Do we have any work items to finish? */ > > +bool > > +xfs_defer_has_unfinished_work( > > + struct xfs_defer_ops *dop) > > +{ > > + return !list_empty(&dop->dop_pending) || !list_empty(&dop->dop_intake); > > +} > > + > > +/* > > + * Add this inode to the deferred op. Each joined inode is relogged > > + * each time we roll the transaction, in addition to any inode passed > > + * to xfs_defer_finish(). > > + */ > > +int > > +xfs_defer_join( > > + struct xfs_defer_ops *dop, > > + struct xfs_inode *ip) > > +{ > > + int i; > > + > > + for (i = 0; i < XFS_DEFER_OPS_NR_INODES; i++) { > > + if (dop->dop_inodes[i] == ip) > > + return 0; > > + else if (dop->dop_inodes[i] == NULL) { > > + dop->dop_inodes[i] = ip; > > + return 0; > > + } > > + } > > + > > + return -EFSCORRUPTED; > > +} > > + > > +/* > > + * Finish all the pending work. This involves logging intent items for > > + * any work items that wandered in since the last transaction roll (if > > + * one has even happened), rolling the transaction, and finishing the > > + * work items in the first item on the logged-and-pending list. > > + * > > + * If an inode is provided, relog it to the new transaction. > > + */ > > +int > > +xfs_defer_finish( > > + struct xfs_trans **tp, > > + struct xfs_defer_ops *dop, > > + struct xfs_inode *ip) > > +{ > > + struct xfs_defer_pending *dfp; > > + struct list_head *li; > > + struct list_head *n; > > + void *done_item = NULL; > > + void *state; > > + int error = 0; > > + void (*cleanup_fn)(struct xfs_trans *, void *, int); > > + > > + ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); > > + > > + /* Until we run out of pending work to finish... */ > > + while (xfs_defer_has_unfinished_work(dop)) { > > + /* Log intents for work items sitting in the intake. */ > > + xfs_defer_intake_work(*tp, dop); > > + > > + /* Roll the transaction. */ > > + error = xfs_defer_trans_roll(tp, dop, ip); > > + if (error) > > + goto out; > > + > > + /* Mark all pending intents as committed. */ > > + list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { > > + if (dfp->dfp_committed) > > + break; > > + dfp->dfp_committed = true; > > + } > > + > > + /* Log an intent-done item for the first pending item. */ > > + dfp = list_first_entry(&dop->dop_pending, > > + struct xfs_defer_pending, dfp_list); > > + done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, > > + dfp->dfp_count); > > + cleanup_fn = dfp->dfp_type->finish_cleanup; > > + > > + /* Finish the work items. */ > > + state = NULL; > > + list_for_each_safe(li, n, &dfp->dfp_work) { > > + list_del(li); > > + dfp->dfp_count--; > > + error = dfp->dfp_type->finish_item(*tp, dop, li, > > + done_item, &state); > > + if (error == -EAGAIN) { > > + /* > > + * If the caller needs to try again, put the > > + * item back on the pending list and jump out > > + * for further processing. > > A little confused by the terminology here. Perhaps better to say "back > on the work list" rather than "pending list?" Yes. > Also, what is the meaning/purpose of -EAGAIN here? This isn't used by > the extent free bits so I'm missing some context. Generally, the ->finish_item() uses -EAGAIN to signal that it couldn't finish the work item and that it's necessary to log a new redo item and try again. Practically, the only user of this mechanism is the refcountbt adjust function. It might be the case that we want to adjust N blocks, but some pathological user has creatively used reflink to create many refcount records. In that case we could blow out the transaction reservation logging all the updates. To avoid that, the refcount code tries to guess (conservatively) when it might be getting close and returns a short *adjusted. See the call sites of xfs_refcount_still_have_space(). Next, xfs_trans_log_finish_refcount_update() will notice the short adjust returned and fixes up the CUD item to have a reduced cud_nextents and to reflect where the operation stopped. Then, xfs_refcount_update_finish_item() notices the short return, updates the work item list, and returns -EAGAIN. Finally, xfs_defer_finish() sees the -EAGAIN and requeues the work item so that we resume refcount adjusting after the transaction rolls. > For example, is there > an issue with carrying a done_item with an unexpected list count? AFAICT, nothing in log recovery ever checks that the list counts of the intent and done items actually match, let alone the extents logged with them. It only seems to care if there's an efd such that efd->efd_efi_id == efi->efi_id, in which case it won't replay the efi. I don't know if that was a deliberate part of the log design, but the lack of checking helps us here. > Is it > expected that xfs_defer_finish() will not return until -EAGAIN is > "cleared" (does relogging below and rolling somehow address this)? Yes, relogging and rolling gives us a fresh transaction with which to continue updating. > > + */ > > + list_add(li, &dfp->dfp_work); > > + dfp->dfp_count++; > > + break; > > + } else if (error) { > > + /* > > + * Clean up after ourselves and jump out. > > + * xfs_defer_cancel will take care of freeing > > + * all these lists and stuff. > > + */ > > + if (cleanup_fn) > > + cleanup_fn(*tp, state, error); > > + xfs_defer_trans_abort(*tp, dop, error); > > + goto out; > > + } > > + } > > + if (error == -EAGAIN) { > > + /* > > + * Log a new intent, relog all the remaining work > > + * item to the new intent, attach the new intent to > > + * the dfp, and leave the dfp at the head of the list > > + * for further processing. > > + */ > > Similar to the above, could you elaborate on the mechanics of this with > respect to the log? E.g., the comment kind of just repeats what the > code does as opposed to explain why it's here. Is the point here to log > a new intent in the same transaction as the done item to ensure that we > (atomically) indicate that certain operations need to be replayed if > this transaction hits the log and then we crash? Yes. "This effectively replaces the old intent item with a new one listing only the work items that were not completed when ->finish_item() returned -EAGAIN. After the subsequent transaction roll, we'll resume where we left off with a fresh transaction." Thank you for the review! --D > Brian > > > + dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, > > + dfp->dfp_count); > > + list_for_each(li, &dfp->dfp_work) > > + dfp->dfp_type->log_item(*tp, dfp->dfp_intent, > > + li); > > + } else { > > + /* Done with the dfp, free it. */ > > + list_del(&dfp->dfp_list); > > + kmem_free(dfp); > > + } > > + > > + if (cleanup_fn) > > + cleanup_fn(*tp, state, error); > > + } > > + > > +out: > > + return error; > > +} > > + > > +/* > > + * Free up any items left in the list. > > + */ > > +void > > +xfs_defer_cancel( > > + struct xfs_defer_ops *dop) > > +{ > > + struct xfs_defer_pending *dfp; > > + struct xfs_defer_pending *pli; > > + struct list_head *pwi; > > + struct list_head *n; > > + > > + /* > > + * Free the pending items. Caller should already have arranged > > + * for the intent items to be released. > > + */ > > + list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { > > + list_del(&dfp->dfp_list); > > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > > + list_del(pwi); > > + dfp->dfp_count--; > > + dfp->dfp_type->cancel_item(pwi); > > + } > > + ASSERT(dfp->dfp_count == 0); > > + kmem_free(dfp); > > + } > > + list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { > > + list_del(&dfp->dfp_list); > > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > > + list_del(pwi); > > + dfp->dfp_count--; > > + dfp->dfp_type->cancel_item(pwi); > > + } > > + ASSERT(dfp->dfp_count == 0); > > + kmem_free(dfp); > > + } > > +} > > + > > +/* Add an item for later deferred processing. */ > > +void > > +xfs_defer_add( > > + struct xfs_defer_ops *dop, > > + enum xfs_defer_ops_type type, > > + struct list_head *li) > > +{ > > + struct xfs_defer_pending *dfp = NULL; > > + > > + /* > > + * Add the item to a pending item at the end of the intake list. > > + * If the last pending item has the same type, reuse it. Else, > > + * create a new pending item at the end of the intake list. > > + */ > > + if (!list_empty(&dop->dop_intake)) { > > + dfp = list_last_entry(&dop->dop_intake, > > + struct xfs_defer_pending, dfp_list); > > + if (dfp->dfp_type->type != type || > > + (dfp->dfp_type->max_items && > > + dfp->dfp_count >= dfp->dfp_type->max_items)) > > + dfp = NULL; > > + } > > + if (!dfp) { > > + dfp = kmem_alloc(sizeof(struct xfs_defer_pending), > > + KM_SLEEP | KM_NOFS); > > + dfp->dfp_type = defer_op_types[type]; > > + dfp->dfp_committed = false; > > + dfp->dfp_intent = NULL; > > + dfp->dfp_count = 0; > > + INIT_LIST_HEAD(&dfp->dfp_work); > > + list_add_tail(&dfp->dfp_list, &dop->dop_intake); > > + } > > + > > + list_add_tail(li, &dfp->dfp_work); > > + dfp->dfp_count++; > > +} > > + > > +/* Initialize a deferred operation list. */ > > +void > > +xfs_defer_init_op_type( > > + const struct xfs_defer_op_type *type) > > +{ > > + defer_op_types[type->type] = type; > > +} > > + > > +/* Initialize a deferred operation. */ > > +void > > +xfs_defer_init( > > + struct xfs_defer_ops *dop, > > + xfs_fsblock_t *fbp) > > +{ > > + dop->dop_committed = false; > > + dop->dop_low = false; > > + memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); > > + *fbp = NULLFSBLOCK; > > + INIT_LIST_HEAD(&dop->dop_intake); > > + INIT_LIST_HEAD(&dop->dop_pending); > > +} > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > > new file mode 100644 > > index 0000000..85c7a3a > > --- /dev/null > > +++ b/fs/xfs/libxfs/xfs_defer.h > > @@ -0,0 +1,96 @@ > > +/* > > + * Copyright (C) 2016 Oracle. All Rights Reserved. > > + * > > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License > > + * as published by the Free Software Foundation; either version 2 > > + * of the License, or (at your option) any later version. > > + * > > + * This program is distributed in the hope that it would be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public License > > + * along with this program; if not, write the Free Software Foundation, > > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > + */ > > +#ifndef __XFS_DEFER_H__ > > +#define __XFS_DEFER_H__ > > + > > +struct xfs_defer_op_type; > > + > > +/* > > + * Save a log intent item and a list of extents, so that we can replay > > + * whatever action had to happen to the extent list and file the log done > > + * item. > > + */ > > +struct xfs_defer_pending { > > + const struct xfs_defer_op_type *dfp_type; /* function pointers */ > > + struct list_head dfp_list; /* pending items */ > > + bool dfp_committed; /* committed trans? */ > > + void *dfp_intent; /* log intent item */ > > + struct list_head dfp_work; /* work items */ > > + unsigned int dfp_count; /* # extent items */ > > +}; > > + > > +/* > > + * Header for deferred operation list. > > + * > > + * dop_low is used by the allocator to activate the lowspace algorithm - > > + * when free space is running low the extent allocator may choose to > > + * allocate an extent from an AG without leaving sufficient space for > > + * a btree split when inserting the new extent. In this case the allocator > > + * will enable the lowspace algorithm which is supposed to allow further > > + * allocations (such as btree splits and newroots) to allocate from > > + * sequential AGs. In order to avoid locking AGs out of order the lowspace > > + * algorithm will start searching for free space from AG 0. If the correct > > + * transaction reservations have been made then this algorithm will eventually > > + * find all the space it needs. > > + */ > > +enum xfs_defer_ops_type { > > + XFS_DEFER_OPS_TYPE_MAX, > > +}; > > + > > +#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ > > + > > +struct xfs_defer_ops { > > + bool dop_committed; /* did any trans commit? */ > > + bool dop_low; /* alloc in low mode */ > > + struct list_head dop_intake; /* unlogged pending work */ > > + struct list_head dop_pending; /* logged pending work */ > > + > > + /* relog these inodes with each roll */ > > + struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; > > +}; > > + > > +void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, > > + struct list_head *h); > > +int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop, > > + struct xfs_inode *ip); > > +void xfs_defer_cancel(struct xfs_defer_ops *dop); > > +void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); > > +bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); > > +int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip); > > + > > +/* Description of a deferred type. */ > > +struct xfs_defer_op_type { > > + enum xfs_defer_ops_type type; > > + unsigned int max_items; > > + void (*abort_intent)(void *); > > + void *(*create_done)(struct xfs_trans *, void *, unsigned int); > > + int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, > > + struct list_head *, void *, void **); > > + void (*finish_cleanup)(struct xfs_trans *, void *, int); > > + void (*cancel_item)(struct list_head *); > > + int (*diff_items)(void *, struct list_head *, struct list_head *); > > + void *(*create_intent)(struct xfs_trans *, uint); > > + void (*log_item)(struct xfs_trans *, void *, struct list_head *); > > +}; > > + > > +void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); > > +void xfs_defer_init_types(void); > > + > > +#endif /* __XFS_DEFER_H__ */ > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > > new file mode 100644 > > index 0000000..849088d > > --- /dev/null > > +++ b/fs/xfs/xfs_defer_item.c > > @@ -0,0 +1,36 @@ > > +/* > > + * Copyright (C) 2016 Oracle. All Rights Reserved. > > + * > > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > > + * > > + * This program is free software; you can redistribute it and/or > > + * modify it under the terms of the GNU General Public License > > + * as published by the Free Software Foundation; either version 2 > > + * of the License, or (at your option) any later version. > > + * > > + * This program is distributed in the hope that it would be useful, > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > + * GNU General Public License for more details. > > + * > > + * You should have received a copy of the GNU General Public License > > + * along with this program; if not, write the Free Software Foundation, > > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > + */ > > +#include "xfs.h" > > +#include "xfs_fs.h" > > +#include "xfs_shared.h" > > +#include "xfs_format.h" > > +#include "xfs_log_format.h" > > +#include "xfs_trans_resv.h" > > +#include "xfs_bit.h" > > +#include "xfs_sb.h" > > +#include "xfs_mount.h" > > +#include "xfs_defer.h" > > +#include "xfs_trans.h" > > + > > +/* Initialize the deferred operation types. */ > > +void > > +xfs_defer_init_types(void) > > +{ > > +} > > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c > > index 09722a7..bf63f6d 100644 > > --- a/fs/xfs/xfs_super.c > > +++ b/fs/xfs/xfs_super.c > > @@ -46,6 +46,7 @@ > > #include "xfs_quota.h" > > #include "xfs_sysfs.h" > > #include "xfs_ondisk.h" > > +#include "xfs_defer.h" > > > > #include <linux/namei.h> > > #include <linux/init.h> > > @@ -1850,6 +1851,7 @@ init_xfs_fs(void) > > printk(KERN_INFO XFS_VERSION_STRING " with " > > XFS_BUILD_OPTIONS " enabled\n"); > > > > + xfs_defer_init_types(); > > xfs_dir_startup(); > > > > error = xfs_init_zones(); > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Mon Jun 27 16:08:01 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 330A47CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 16:08:01 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 067748F8037 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 14:07:57 -0700 (PDT) X-ASG-Debug-ID: 1467061673-04cb6c063f2029a0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id ap2d2gpcQV56eEg0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 14:07:53 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5RL7om2003256 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 21:07:50 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5RL7obU006162 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 21:07:50 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5RL7mF4021454; Mon, 27 Jun 2016 21:07:49 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 27 Jun 2016 14:07:48 -0700 Date: Mon, 27 Jun 2016 14:07:46 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 014/119] xfs: introduce interval queries on btrees Message-ID: <20160627210746.GB4921@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 014/119] xfs: introduce interval queries on btrees References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612636170.12839.675596870201079078.stgit@birch.djwong.org> <20160622151800.GC5423@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622151800.GC5423@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467061673 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15261 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30812 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Wed, Jun 22, 2016 at 11:18:00AM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:19:21PM -0700, Darrick J. Wong wrote: > > Create a function to enable querying of btree records mapping to a > > range of keys. This will be used in subsequent patches to allow > > querying the reverse mapping btree to find the extents mapped to a > > range of physical blocks, though the generic code can be used for > > any range query. > > > > v2: add some shortcuts so that we can jump out of processing once > > we know there won't be any more records to find. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > fs/xfs/libxfs/xfs_btree.c | 249 +++++++++++++++++++++++++++++++++++++++++++++ > > fs/xfs/libxfs/xfs_btree.h | 22 +++- > > fs/xfs/xfs_trace.h | 1 > > 3 files changed, 267 insertions(+), 5 deletions(-) > > > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > index afcafd6..5f5cf23 100644 > > --- a/fs/xfs/libxfs/xfs_btree.c > > +++ b/fs/xfs/libxfs/xfs_btree.c > > @@ -4509,3 +4509,252 @@ xfs_btree_calc_size( > > } > > return rval; > > } > > + > > +/* Query a regular btree for all records overlapping a given interval. */ > > Can you elaborate on the search algorithm used? (More for reference > against the overlapped query, as that one is more complex). Ok. Both query_range functions aim to return all records intersecting the given range. For non-overlapped btrees, we start with a LE lookup of the low key and return each record we find a the record with a key greater than the high key. For overlapped btrees, we follow the procedure in the "Interval trees" section of _Introduction to Algorithms_, which is 14.3 in the 2nd and 3rd editions. The query algorithm is roughly as follows: For any leaf btree node, generate the low and high keys for the record. If there's a range overlap with the query's low and high keys, pass the record to the iterator function. For any internal btree node, compare the low and high keys for each pointer against the query's low and high keys. If there's an overlap, follow the pointer downwards in the tree. (I could render the figures in the book as ASCII art if anyone wants.) > > > +STATIC int > > +xfs_btree_simple_query_range( > > + struct xfs_btree_cur *cur, > > + union xfs_btree_irec *low_rec, > > + union xfs_btree_irec *high_rec, > > + xfs_btree_query_range_fn fn, > > + void *priv) > > +{ > > + union xfs_btree_rec *recp; > > + union xfs_btree_rec rec; > > + union xfs_btree_key low_key; > > + union xfs_btree_key high_key; > > + union xfs_btree_key rec_key; > > + __int64_t diff; > > + int stat; > > + bool firstrec = true; > > + int error; > > + > > + ASSERT(cur->bc_ops->init_high_key_from_rec); > > + > > + /* Find the keys of both ends of the interval. */ > > + cur->bc_rec = *high_rec; > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > > + > > + cur->bc_rec = *low_rec; > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > > + > > + /* Find the leftmost record. */ > > + stat = 0; > > + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat); > > + if (error) > > + goto out; > > + > > + while (stat) { > > + /* Find the record. */ > > + error = xfs_btree_get_rec(cur, &recp, &stat); > > + if (error || !stat) > > + break; > > + > > + /* Can we tell if this record is too low? */ > > + if (firstrec) { > > + cur->bc_rec = *low_rec; > > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > > + diff = cur->bc_ops->key_diff(cur, &rec_key); > > + if (diff < 0) > > + goto advloop; > > + } > > + firstrec = false; > > This could move up into the if block. Ok. > > + > > + /* Have we gone past the end? */ > > + cur->bc_rec = *high_rec; > > + cur->bc_ops->init_key_from_rec(&rec_key, recp); > > I'd move this up to immediately after the xfs_btree_get_rec() call and > eliminate the duplicate in the 'if (firstrec)' block above. Ok. That key ought to be named rec_hkey too. > > + diff = cur->bc_ops->key_diff(cur, &rec_key); > > + if (diff > 0) > > + break; > > + > > + /* Callback */ > > + error = fn(cur, recp, priv); > > + if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) > > + break; > > + > > +advloop: > > + /* Move on to the next record. */ > > + error = xfs_btree_increment(cur, 0, &stat); > > + if (error) > > + break; > > + } > > + > > +out: > > + return error; > > +} > > + > > +/* > > + * Query an overlapped interval btree for all records overlapping a given > > + * interval. > > + */ > > Same comment here, can you elaborate on the search algorithm? Also, I > think an example or generic description of the rules around what records > this query returns (e.g., low_rec/high_rec vs. record low/high keys) > would be useful, particularly since I, at least, don't have much context > on the rmap+reflink scenarios quite yet. Let's say you have a bunch of (overlapped) rmap records: 1: +- file A startblock B offset C length D -----------+ 2: +- file E startblock F offset G length H --------------+ 3: +- file I startblock F offset J length K --+ 4: +- file L... --+ Now say we want to map block (B+D) into file A at offset (C+D). Ideally, we'd simply increment the length of record 1. But how do we find that record that ends at (B+D-1)? A LE lookup of (B+D-1) would return record 3 because the keys are ordered first by startblock. An interval query would return records 1 and 2 because they both overlap (B+D-1), and from that we can pick out record 1 as the appropriate left neighbor. In the non-overlapped case you can do a LE lookup and decrement the cursor because a record's interval must end before the next record. > > +STATIC int > > +xfs_btree_overlapped_query_range( > > + struct xfs_btree_cur *cur, > > + union xfs_btree_irec *low_rec, > > + union xfs_btree_irec *high_rec, > > + xfs_btree_query_range_fn fn, > > + void *priv) > > +{ > > + union xfs_btree_ptr ptr; > > + union xfs_btree_ptr *pp; > > + union xfs_btree_key rec_key; > > + union xfs_btree_key low_key; > > + union xfs_btree_key high_key; > > + union xfs_btree_key *lkp; > > + union xfs_btree_key *hkp; > > + union xfs_btree_rec rec; > > + union xfs_btree_rec *recp; > > + struct xfs_btree_block *block; > > + __int64_t ldiff; > > + __int64_t hdiff; > > + int level; > > + struct xfs_buf *bp; > > + int i; > > + int error; > > + > > + /* Find the keys of both ends of the interval. */ > > + cur->bc_rec = *high_rec; > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > > + > > + cur->bc_rec = *low_rec; > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > > + > > + /* Load the root of the btree. */ > > + level = cur->bc_nlevels - 1; > > + cur->bc_ops->init_ptr_from_cur(cur, &ptr); > > + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); > > + if (error) > > + return error; > > + xfs_btree_get_block(cur, level, &bp); > > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > > +#ifdef DEBUG > > + error = xfs_btree_check_block(cur, block, level, bp); > > + if (error) > > + goto out; > > +#endif > > + cur->bc_ptrs[level] = 1; > > + > > + while (level < cur->bc_nlevels) { > > + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); > > + > > + if (level == 0) { > > + /* End of leaf, pop back towards the root. */ > > + if (cur->bc_ptrs[level] > > > + be16_to_cpu(block->bb_numrecs)) { > > +leaf_pop_up: > > + if (level < cur->bc_nlevels - 1) > > + cur->bc_ptrs[level + 1]++; > > + level++; > > + continue; > > + } > > + > > + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); > > + > > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, > > + &rec_key); > > + > > + cur->bc_ops->init_key_from_rec(&rec_key, recp); > > + hdiff = cur->bc_ops->diff_two_keys(cur, &rec_key, > > + &high_key); > > + > > This looked a little funny to me because I expected diff_two_keys() to > basically be param1 - param2. Looking ahead at the rmapbt code, it is in > fact the other way around. I'm not sure we have precedent for either > way, tbh. I still have to stare at this some more, but I wonder if a > "does record overlap" helper (with comments) would help clean this up a > bit. You're correct this is exactly the opposite of the compare functions in the C library and the rest of the kernel. I'll fix that up. > > + /* If the record matches, callback */ > > + if (ldiff >= 0 && hdiff >= 0) { Ok, I'll make it a little clearer what we're testing here: /* * If (record's high key >= query's low key) and * (query's high key >= record's low key), then * this record overlaps the query range, so callback. */ > > + error = fn(cur, recp, priv); > > + if (error < 0 || > > + error == XFS_BTREE_QUERY_RANGE_ABORT) > > + break; > > + } else if (hdiff < 0) { > > + /* Record is larger than high key; pop. */ > > + goto leaf_pop_up; > > + } > > + cur->bc_ptrs[level]++; > > + continue; > > + } > > + > > + /* End of node, pop back towards the root. */ > > + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { > > +node_pop_up: > > + if (level < cur->bc_nlevels - 1) > > + cur->bc_ptrs[level + 1]++; > > + level++; > > + continue; > > Looks like same code as leaf_pop_up. I wonder if we can bury this at the > end of the loop with a common label. Yep. > > + } > > + > > + lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); > > + hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); > > + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); > > + > > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, hkp); > > + hdiff = cur->bc_ops->diff_two_keys(cur, lkp, &high_key); > > + > > + /* If the key matches, drill another level deeper. */ > > + if (ldiff >= 0 && hdiff >= 0) { > > + level--; > > + error = xfs_btree_lookup_get_block(cur, level, pp, > > + &block); > > + if (error) > > + goto out; > > + xfs_btree_get_block(cur, level, &bp); > > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > > +#ifdef DEBUG > > + error = xfs_btree_check_block(cur, block, level, bp); > > + if (error) > > + goto out; > > +#endif > > + cur->bc_ptrs[level] = 1; > > + continue; > > + } else if (hdiff < 0) { > > + /* The low key is larger than the upper range; pop. */ > > + goto node_pop_up; > > + } > > + cur->bc_ptrs[level]++; > > + } > > + > > +out: > > + /* > > + * If we don't end this function with the cursor pointing at a record > > + * block, a subsequent non-error cursor deletion will not release > > + * node-level buffers, causing a buffer leak. This is quite possible > > + * with a zero-results range query, so release the buffers if we > > + * failed to return any results. > > + */ > > + if (cur->bc_bufs[0] == NULL) { > > + for (i = 0; i < cur->bc_nlevels; i++) { > > + if (cur->bc_bufs[i]) { > > + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); > > + cur->bc_bufs[i] = NULL; > > + cur->bc_ptrs[i] = 0; > > + cur->bc_ra[i] = 0; > > + } > > + } > > + } > > + > > + return error; > > +} > > + > > +/* > > + * Query a btree for all records overlapping a given interval of keys. The > > + * supplied function will be called with each record found; return one of the > > + * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error > > + * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a > > + * negative error code. > > + */ > > +int > > +xfs_btree_query_range( > > + struct xfs_btree_cur *cur, > > + union xfs_btree_irec *low_rec, > > + union xfs_btree_irec *high_rec, > > + xfs_btree_query_range_fn fn, > > + void *priv) > > +{ > > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > > + return xfs_btree_simple_query_range(cur, low_rec, > > + high_rec, fn, priv); > > + return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, > > + fn, priv); > > +} > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > index a5ec6c7..898fee5 100644 > > --- a/fs/xfs/libxfs/xfs_btree.h > > +++ b/fs/xfs/libxfs/xfs_btree.h > > @@ -206,6 +206,12 @@ struct xfs_btree_ops { > > #define LASTREC_DELREC 2 > > > > > > +union xfs_btree_irec { > > + xfs_alloc_rec_incore_t a; > > + xfs_bmbt_irec_t b; > > + xfs_inobt_rec_incore_t i; > > +}; > > + > > We might as well kill off the typedef usage here. Ok. Thx for the review! --D > > Brian > > > /* > > * Btree cursor structure. > > * This collects all information needed by the btree code in one place. > > @@ -216,11 +222,7 @@ typedef struct xfs_btree_cur > > struct xfs_mount *bc_mp; /* file system mount struct */ > > const struct xfs_btree_ops *bc_ops; > > uint bc_flags; /* btree features - below */ > > - union { > > - xfs_alloc_rec_incore_t a; > > - xfs_bmbt_irec_t b; > > - xfs_inobt_rec_incore_t i; > > - } bc_rec; /* current insert/search record value */ > > + union xfs_btree_irec bc_rec; /* current insert/search record value */ > > struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ > > int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ > > __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ > > @@ -494,4 +496,14 @@ xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > > uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, > > unsigned long len); > > > > +/* return codes */ > > +#define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */ > > +#define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */ > > +typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur, > > + union xfs_btree_rec *rec, void *priv); > > + > > +int xfs_btree_query_range(struct xfs_btree_cur *cur, > > + union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, > > + xfs_btree_query_range_fn fn, void *priv); > > + > > #endif /* __XFS_BTREE_H__ */ > > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > > index ffea28c..f0ac9c9 100644 > > --- a/fs/xfs/xfs_trace.h > > +++ b/fs/xfs/xfs_trace.h > > @@ -2218,6 +2218,7 @@ DEFINE_EVENT(xfs_btree_cur_class, name, \ > > TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > > TP_ARGS(cur, level, bp)) > > DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > > +DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); > > > > #endif /* _TRACE_XFS_H */ > > > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Mon Jun 27 16:41:58 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 6764E7CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 16:41:58 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id E5A93AC005 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 14:41:54 -0700 (PDT) X-ASG-Debug-ID: 1467063712-04bdf074b61502b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id A1EHOdPosIoDjEQ6 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 14:41:52 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5RLfn0x002957 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 21:41:50 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5RLfncB017191 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 21:41:49 GMT Received: from abhmp0015.oracle.com (abhmp0015.oracle.com [141.146.116.21]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5RLfmkU004773; Mon, 27 Jun 2016 21:41:49 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 27 Jun 2016 14:41:48 -0700 Date: Mon, 27 Jun 2016 14:41:45 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free Message-ID: <20160627214145.GC4921@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612638717.12839.11007379793448761871.stgit@birch.djwong.org> <20160627131508.GC23076@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160627131508.GC23076@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467063712 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5080 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30813 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 27, 2016 at 09:15:08AM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:19:47PM -0700, Darrick J. Wong wrote: > > Connect the xfs_defer mechanism with the pieces that we'll need to > > handle deferred extent freeing. We'll wire up the existing code to > > our new deferred mechanism later. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > Could we merge this with the xfs_trans_*efi/efd* bits? We'd need to > preserve some calls for recovery, but it looks like other parts are only > used by the deferred ops infrastructure at this point. Yes, we could replace xfs_bmap_free_create_{intent,done} with xfs_trans_get_ef[id] and lose the silly functions. I'll go take care of all of them. --D > > Brian > > > fs/xfs/libxfs/xfs_defer.h | 1 > > fs/xfs/xfs_defer_item.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 109 insertions(+) > > > > > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > > index 85c7a3a..743fc32 100644 > > --- a/fs/xfs/libxfs/xfs_defer.h > > +++ b/fs/xfs/libxfs/xfs_defer.h > > @@ -51,6 +51,7 @@ struct xfs_defer_pending { > > * find all the space it needs. > > */ > > enum xfs_defer_ops_type { > > + XFS_DEFER_OPS_TYPE_FREE, > > XFS_DEFER_OPS_TYPE_MAX, > > }; > > > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > > index 4c2ba28..127a54e 100644 > > --- a/fs/xfs/xfs_defer_item.c > > +++ b/fs/xfs/xfs_defer_item.c > > @@ -29,9 +29,117 @@ > > #include "xfs_defer.h" > > #include "xfs_trans.h" > > #include "xfs_trace.h" > > +#include "xfs_bmap.h" > > +#include "xfs_extfree_item.h" > > + > > +/* Extent Freeing */ > > + > > +/* Sort bmap items by AG. */ > > +static int > > +xfs_bmap_free_diff_items( > > + void *priv, > > + struct list_head *a, > > + struct list_head *b) > > +{ > > + struct xfs_mount *mp = priv; > > + struct xfs_bmap_free_item *ra; > > + struct xfs_bmap_free_item *rb; > > + > > + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); > > + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); > > + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - > > + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); > > +} > > + > > +/* Get an EFI. */ > > +STATIC void * > > +xfs_bmap_free_create_intent( > > + struct xfs_trans *tp, > > + unsigned int count) > > +{ > > + return xfs_trans_get_efi(tp, count); > > +} > > + > > +/* Log a free extent to the intent item. */ > > +STATIC void > > +xfs_bmap_free_log_item( > > + struct xfs_trans *tp, > > + void *intent, > > + struct list_head *item) > > +{ > > + struct xfs_bmap_free_item *free; > > + > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > + xfs_trans_log_efi_extent(tp, intent, free->xbfi_startblock, > > + free->xbfi_blockcount); > > +} > > + > > +/* Get an EFD so we can process all the free extents. */ > > +STATIC void * > > +xfs_bmap_free_create_done( > > + struct xfs_trans *tp, > > + void *intent, > > + unsigned int count) > > +{ > > + return xfs_trans_get_efd(tp, intent, count); > > +} > > + > > +/* Process a free extent. */ > > +STATIC int > > +xfs_bmap_free_finish_item( > > + struct xfs_trans *tp, > > + struct xfs_defer_ops *dop, > > + struct list_head *item, > > + void *done_item, > > + void **state) > > +{ > > + struct xfs_bmap_free_item *free; > > + int error; > > + > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > + error = xfs_trans_free_extent(tp, done_item, > > + free->xbfi_startblock, > > + free->xbfi_blockcount); > > + kmem_free(free); > > + return error; > > +} > > + > > +/* Abort all pending EFIs. */ > > +STATIC void > > +xfs_bmap_free_abort_intent( > > + void *intent) > > +{ > > + xfs_efi_release(intent); > > +} > > + > > +/* Cancel a free extent. */ > > +STATIC void > > +xfs_bmap_free_cancel_item( > > + struct list_head *item) > > +{ > > + struct xfs_bmap_free_item *free; > > + > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > + kmem_free(free); > > +} > > + > > +const struct xfs_defer_op_type xfs_extent_free_defer_type = { > > + .type = XFS_DEFER_OPS_TYPE_FREE, > > + .max_items = XFS_EFI_MAX_FAST_EXTENTS, > > + .diff_items = xfs_bmap_free_diff_items, > > + .create_intent = xfs_bmap_free_create_intent, > > + .abort_intent = xfs_bmap_free_abort_intent, > > + .log_item = xfs_bmap_free_log_item, > > + .create_done = xfs_bmap_free_create_done, > > + .finish_item = xfs_bmap_free_finish_item, > > + .cancel_item = xfs_bmap_free_cancel_item, > > +}; > > + > > +/* Deferred Item Initialization */ > > > > /* Initialize the deferred operation types. */ > > void > > xfs_defer_init_types(void) > > { > > + xfs_defer_init_op_type(&xfs_extent_free_defer_type); > > } > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Mon Jun 27 17:00:12 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id C31027CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 17:00:12 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 92567304032 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 15:00:12 -0700 (PDT) X-ASG-Debug-ID: 1467064809-04cbb0273729f790001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id FxMX2aeeE05YpN1M (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 15:00:09 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5RM077Z021037 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 22:00:07 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5RM07tl030282 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 22:00:07 GMT Received: from abhmp0001.oracle.com (abhmp0001.oracle.com [141.146.116.7]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5RM05Ea016429; Mon, 27 Jun 2016 22:00:06 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 27 Jun 2016 15:00:04 -0700 Date: Mon, 27 Jun 2016 15:00:03 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free Message-ID: <20160627220003.GA4917@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612638717.12839.11007379793448761871.stgit@birch.djwong.org> <20160627131508.GC23076@bfoster.bfoster> <20160627214145.GC4921@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20160627214145.GC4921@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467064809 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6114 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30814 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 27, 2016 at 02:41:45PM -0700, Darrick J. Wong wrote: > On Mon, Jun 27, 2016 at 09:15:08AM -0400, Brian Foster wrote: > > On Thu, Jun 16, 2016 at 06:19:47PM -0700, Darrick J. Wong wrote: > > > Connect the xfs_defer mechanism with the pieces that we'll need to > > > handle deferred extent freeing. We'll wire up the existing code to > > > our new deferred mechanism later. > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > --- > > > > Could we merge this with the xfs_trans_*efi/efd* bits? We'd need to > > preserve some calls for recovery, but it looks like other parts are only > > used by the deferred ops infrastructure at this point. > > Yes, we could replace xfs_bmap_free_create_{intent,done} with > xfs_trans_get_ef[id] and lose the silly functions. I'll go take > care of all of them. Hah, gcc complains about the mismatch in pointer types for the second argument. fs/xfs/xfs_defer_item.c:504:17: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] .create_done = xfs_trans_get_bud, ^ fs/xfs/xfs_defer_item.c:504:17: note: (near initialization for ‘xfs_bmap_update_defer_type.create_done’) I guess one could put in an ugly cast to coerce the types at a cost of uglifying the code. <shrug> Opinions? --D > > --D > > > > > Brian > > > > > fs/xfs/libxfs/xfs_defer.h | 1 > > > fs/xfs/xfs_defer_item.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ > > > 2 files changed, 109 insertions(+) > > > > > > > > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > > > index 85c7a3a..743fc32 100644 > > > --- a/fs/xfs/libxfs/xfs_defer.h > > > +++ b/fs/xfs/libxfs/xfs_defer.h > > > @@ -51,6 +51,7 @@ struct xfs_defer_pending { > > > * find all the space it needs. > > > */ > > > enum xfs_defer_ops_type { > > > + XFS_DEFER_OPS_TYPE_FREE, > > > XFS_DEFER_OPS_TYPE_MAX, > > > }; > > > > > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > > > index 4c2ba28..127a54e 100644 > > > --- a/fs/xfs/xfs_defer_item.c > > > +++ b/fs/xfs/xfs_defer_item.c > > > @@ -29,9 +29,117 @@ > > > #include "xfs_defer.h" > > > #include "xfs_trans.h" > > > #include "xfs_trace.h" > > > +#include "xfs_bmap.h" > > > +#include "xfs_extfree_item.h" > > > + > > > +/* Extent Freeing */ > > > + > > > +/* Sort bmap items by AG. */ > > > +static int > > > +xfs_bmap_free_diff_items( > > > + void *priv, > > > + struct list_head *a, > > > + struct list_head *b) > > > +{ > > > + struct xfs_mount *mp = priv; > > > + struct xfs_bmap_free_item *ra; > > > + struct xfs_bmap_free_item *rb; > > > + > > > + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); > > > + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); > > > + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - > > > + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); > > > +} > > > + > > > +/* Get an EFI. */ > > > +STATIC void * > > > +xfs_bmap_free_create_intent( > > > + struct xfs_trans *tp, > > > + unsigned int count) > > > +{ > > > + return xfs_trans_get_efi(tp, count); > > > +} > > > + > > > +/* Log a free extent to the intent item. */ > > > +STATIC void > > > +xfs_bmap_free_log_item( > > > + struct xfs_trans *tp, > > > + void *intent, > > > + struct list_head *item) > > > +{ > > > + struct xfs_bmap_free_item *free; > > > + > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > + xfs_trans_log_efi_extent(tp, intent, free->xbfi_startblock, > > > + free->xbfi_blockcount); > > > +} > > > + > > > +/* Get an EFD so we can process all the free extents. */ > > > +STATIC void * > > > +xfs_bmap_free_create_done( > > > + struct xfs_trans *tp, > > > + void *intent, > > > + unsigned int count) > > > +{ > > > + return xfs_trans_get_efd(tp, intent, count); > > > +} > > > + > > > +/* Process a free extent. */ > > > +STATIC int > > > +xfs_bmap_free_finish_item( > > > + struct xfs_trans *tp, > > > + struct xfs_defer_ops *dop, > > > + struct list_head *item, > > > + void *done_item, > > > + void **state) > > > +{ > > > + struct xfs_bmap_free_item *free; > > > + int error; > > > + > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > + error = xfs_trans_free_extent(tp, done_item, > > > + free->xbfi_startblock, > > > + free->xbfi_blockcount); > > > + kmem_free(free); > > > + return error; > > > +} > > > + > > > +/* Abort all pending EFIs. */ > > > +STATIC void > > > +xfs_bmap_free_abort_intent( > > > + void *intent) > > > +{ > > > + xfs_efi_release(intent); > > > +} > > > + > > > +/* Cancel a free extent. */ > > > +STATIC void > > > +xfs_bmap_free_cancel_item( > > > + struct list_head *item) > > > +{ > > > + struct xfs_bmap_free_item *free; > > > + > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > + kmem_free(free); > > > +} > > > + > > > +const struct xfs_defer_op_type xfs_extent_free_defer_type = { > > > + .type = XFS_DEFER_OPS_TYPE_FREE, > > > + .max_items = XFS_EFI_MAX_FAST_EXTENTS, > > > + .diff_items = xfs_bmap_free_diff_items, > > > + .create_intent = xfs_bmap_free_create_intent, > > > + .abort_intent = xfs_bmap_free_abort_intent, > > > + .log_item = xfs_bmap_free_log_item, > > > + .create_done = xfs_bmap_free_create_done, > > > + .finish_item = xfs_bmap_free_finish_item, > > > + .cancel_item = xfs_bmap_free_cancel_item, > > > +}; > > > + > > > +/* Deferred Item Initialization */ > > > > > > /* Initialize the deferred operation types. */ > > > void > > > xfs_defer_init_types(void) > > > { > > > + xfs_defer_init_op_type(&xfs_extent_free_defer_type); > > > } > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Mon Jun 27 17:30:37 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 431EB7CA0 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 17:30:37 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 06BB98F8035 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 15:30:33 -0700 (PDT) X-ASG-Debug-ID: 1467066630-04cbb027352a0bf0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id G13ZJqeBCXpm4Ldl (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 15:30:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5RMUQcg018767 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 22:30:27 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5RMUQVk014001 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 27 Jun 2016 22:30:26 GMT Received: from abhmp0013.oracle.com (abhmp0013.oracle.com [141.146.116.19]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5RMUP7N025624; Mon, 27 Jun 2016 22:30:25 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 27 Jun 2016 15:30:24 -0700 Date: Mon, 27 Jun 2016 15:30:23 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion Message-ID: <20160627223023.GD4921@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612634887.12839.6210102273046676244.stgit@birch.djwong.org> <20160621130043.GA62352@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160621130043.GA62352@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467066630 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10311 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30815 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Tue, Jun 21, 2016 at 09:00:45AM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:19:08PM -0700, Darrick J. Wong wrote: > > When a btree block has to be split, we pass the new block's ptr from > > xfs_btree_split() back to xfs_btree_insert() via a pointer parameter; > > however, we pass the block's key through the cursor's record. It is a > > little weird to "initialize" a record from a key since the non-key > > attributes will have garbage values. > > > > When we go to add support for interval queries, we have to be able to > > pass the lowest and highest keys accessible via a pointer. There's no > > clean way to pass this back through the cursor's record field. > > Therefore, pass the key directly back to xfs_btree_insert() the same > > way that we pass the btree_ptr. > > > > As a bonus, we no longer need init_rec_from_key and can drop it from the > > codebase. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > fs/xfs/libxfs/xfs_alloc_btree.c | 12 ---------- > > fs/xfs/libxfs/xfs_bmap_btree.c | 12 ---------- > > fs/xfs/libxfs/xfs_btree.c | 44 +++++++++++++++++++------------------- > > fs/xfs/libxfs/xfs_btree.h | 2 -- > > fs/xfs/libxfs/xfs_ialloc_btree.c | 10 --------- > > 5 files changed, 22 insertions(+), 58 deletions(-) > > > > > ... > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > index 046fbcf..a096539 100644 > > --- a/fs/xfs/libxfs/xfs_btree.c > > +++ b/fs/xfs/libxfs/xfs_btree.c > ... > > @@ -2929,16 +2927,16 @@ xfs_btree_insrec( > > struct xfs_btree_cur *cur, /* btree cursor */ > > int level, /* level to insert record at */ > > union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ > > - union xfs_btree_rec *recp, /* i/o: record data inserted */ > > + union xfs_btree_key *key, /* i/o: block key for ptrp */ > > struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ > > int *stat) /* success/failure */ > > { > > struct xfs_btree_block *block; /* btree block */ > > struct xfs_buf *bp; /* buffer for block */ > > - union xfs_btree_key key; /* btree key */ > > union xfs_btree_ptr nptr; /* new block ptr */ > > struct xfs_btree_cur *ncur; /* new btree cursor */ > > - union xfs_btree_rec nrec; /* new record count */ > > + union xfs_btree_key nkey; /* new block key */ > > + union xfs_btree_rec rec; /* record to insert */ > > int optr; /* old key/record index */ > > int ptr; /* key/record index */ > > int numrecs;/* number of records */ > > @@ -2947,8 +2945,14 @@ xfs_btree_insrec( > > int i; > > #endif > > > > + /* Make a key out of the record data to be inserted, and save it. */ > > + if (level == 0) { > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > + cur->bc_ops->init_key_from_rec(key, &rec); > > + } > > The level == 0 check looks a bit hacky to me. IOW, I think it's cleaner > that the key is initialized once in the caller rather than check for a > particular iteration down in xfs_btree_insrec(). That said, > xfs_btree_insrec() still needs rec initialized in the level == 0 case. > > I wonder if we could create an inline xfs_btree_init_key_from_cur() > helper to combine the above calls, invoke it once in xfs_btree_insert(), > then push down the ->init_rec_from_cur() calls to the contexts further > down in this function where rec is actually required. There are only two > and one of them is DEBUG code. Thoughts? How about I make btree_insert set both &key and &rec at the start and pass them both into btree_insrec? That would eliminate the hacky check above and fix the dummy tracing hook too, in case it ever does anything. > > > + > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > - XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp); > > + XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, &rec); > > > > So these look like unimplemented dummy tracing hooks. It sounds like > previously rec could have a junk value after a btree split, but now it > looks like rec is junk for every non-zero level. Kind of annoying, I > wonder if we can just kill these.. :/ <shrug> I have no opinion either way. :) --D > > Brian > > > ncur = NULL; > > > > @@ -2973,9 +2977,6 @@ xfs_btree_insrec( > > return 0; > > } > > > > - /* Make a key out of the record data to be inserted, and save it. */ > > - cur->bc_ops->init_key_from_rec(&key, recp); > > - > > optr = ptr; > > > > XFS_BTREE_STATS_INC(cur, insrec); > > @@ -2992,10 +2993,10 @@ xfs_btree_insrec( > > /* Check that the new entry is being inserted in the right place. */ > > if (ptr <= numrecs) { > > if (level == 0) { > > - ASSERT(cur->bc_ops->recs_inorder(cur, recp, > > + ASSERT(cur->bc_ops->recs_inorder(cur, &rec, > > xfs_btree_rec_addr(cur, ptr, block))); > > } else { > > - ASSERT(cur->bc_ops->keys_inorder(cur, &key, > > + ASSERT(cur->bc_ops->keys_inorder(cur, key, > > xfs_btree_key_addr(cur, ptr, block))); > > } > > } > > @@ -3008,7 +3009,7 @@ xfs_btree_insrec( > > xfs_btree_set_ptr_null(cur, &nptr); > > if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) { > > error = xfs_btree_make_block_unfull(cur, level, numrecs, > > - &optr, &ptr, &nptr, &ncur, &nrec, stat); > > + &optr, &ptr, &nptr, &ncur, &nkey, stat); > > if (error || *stat == 0) > > goto error0; > > } > > @@ -3058,7 +3059,7 @@ xfs_btree_insrec( > > #endif > > > > /* Now put the new data in, bump numrecs and log it. */ > > - xfs_btree_copy_keys(cur, kp, &key, 1); > > + xfs_btree_copy_keys(cur, kp, key, 1); > > xfs_btree_copy_ptrs(cur, pp, ptrp, 1); > > numrecs++; > > xfs_btree_set_numrecs(block, numrecs); > > @@ -3079,7 +3080,7 @@ xfs_btree_insrec( > > xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1); > > > > /* Now put the new data in, bump numrecs and log it. */ > > - xfs_btree_copy_recs(cur, rp, recp, 1); > > + xfs_btree_copy_recs(cur, rp, &rec, 1); > > xfs_btree_set_numrecs(block, ++numrecs); > > xfs_btree_log_recs(cur, bp, ptr, numrecs); > > #ifdef DEBUG > > @@ -3095,7 +3096,7 @@ xfs_btree_insrec( > > > > /* If we inserted at the start of a block, update the parents' keys. */ > > if (optr == 1) { > > - error = xfs_btree_updkey(cur, &key, level + 1); > > + error = xfs_btree_updkey(cur, key, level + 1); > > if (error) > > goto error0; > > } > > @@ -3105,7 +3106,7 @@ xfs_btree_insrec( > > * we are at the far right edge of the tree, update it. > > */ > > if (xfs_btree_is_lastrec(cur, block, level)) { > > - cur->bc_ops->update_lastrec(cur, block, recp, > > + cur->bc_ops->update_lastrec(cur, block, &rec, > > ptr, LASTREC_INSREC); > > } > > > > @@ -3115,7 +3116,7 @@ xfs_btree_insrec( > > */ > > *ptrp = nptr; > > if (!xfs_btree_ptr_is_null(cur, &nptr)) { > > - *recp = nrec; > > + *key = nkey; > > *curp = ncur; > > } > > > > @@ -3146,14 +3147,13 @@ xfs_btree_insert( > > union xfs_btree_ptr nptr; /* new block number (split result) */ > > struct xfs_btree_cur *ncur; /* new cursor (split result) */ > > struct xfs_btree_cur *pcur; /* previous level's cursor */ > > - union xfs_btree_rec rec; /* record to insert */ > > + union xfs_btree_key key; /* key of block to insert */ > > > > level = 0; > > ncur = NULL; > > pcur = cur; > > > > xfs_btree_set_ptr_null(cur, &nptr); > > - cur->bc_ops->init_rec_from_cur(cur, &rec); > > > > /* > > * Loop going up the tree, starting at the leaf level. > > @@ -3165,7 +3165,7 @@ xfs_btree_insert( > > * Insert nrec/nptr into this level of the tree. > > * Note if we fail, nptr will be null. > > */ > > - error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i); > > + error = xfs_btree_insrec(pcur, level, &nptr, &key, &ncur, &i); > > if (error) { > > if (pcur != cur) > > xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > index b955e5d..b99c018 100644 > > --- a/fs/xfs/libxfs/xfs_btree.h > > +++ b/fs/xfs/libxfs/xfs_btree.h > > @@ -158,8 +158,6 @@ struct xfs_btree_ops { > > /* init values of btree structures */ > > void (*init_key_from_rec)(union xfs_btree_key *key, > > union xfs_btree_rec *rec); > > - void (*init_rec_from_key)(union xfs_btree_key *key, > > - union xfs_btree_rec *rec); > > void (*init_rec_from_cur)(struct xfs_btree_cur *cur, > > union xfs_btree_rec *rec); > > void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, > > diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c > > index 89c21d7..88da2ad 100644 > > --- a/fs/xfs/libxfs/xfs_ialloc_btree.c > > +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c > > @@ -146,14 +146,6 @@ xfs_inobt_init_key_from_rec( > > } > > > > STATIC void > > -xfs_inobt_init_rec_from_key( > > - union xfs_btree_key *key, > > - union xfs_btree_rec *rec) > > -{ > > - rec->inobt.ir_startino = key->inobt.ir_startino; > > -} > > - > > -STATIC void > > xfs_inobt_init_rec_from_cur( > > struct xfs_btree_cur *cur, > > union xfs_btree_rec *rec) > > @@ -314,7 +306,6 @@ static const struct xfs_btree_ops xfs_inobt_ops = { > > .get_minrecs = xfs_inobt_get_minrecs, > > .get_maxrecs = xfs_inobt_get_maxrecs, > > .init_key_from_rec = xfs_inobt_init_key_from_rec, > > - .init_rec_from_key = xfs_inobt_init_rec_from_key, > > .init_rec_from_cur = xfs_inobt_init_rec_from_cur, > > .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, > > .key_diff = xfs_inobt_key_diff, > > @@ -336,7 +327,6 @@ static const struct xfs_btree_ops xfs_finobt_ops = { > > .get_minrecs = xfs_inobt_get_minrecs, > > .get_maxrecs = xfs_inobt_get_maxrecs, > > .init_key_from_rec = xfs_inobt_init_key_from_rec, > > - .init_rec_from_key = xfs_inobt_init_rec_from_key, > > .init_rec_from_cur = xfs_inobt_init_rec_from_cur, > > .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, > > .key_diff = xfs_inobt_key_diff, > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From david@fromorbit.com Mon Jun 27 19:26:59 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 55E187CA1 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 19:26:59 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id C24D8AC001 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 17:26:55 -0700 (PDT) X-ASG-Debug-ID: 1467073611-04cb6c063d209ff0001-NocioJ Received: from ipmail07.adl2.internode.on.net (ipmail07.adl2.internode.on.net [150.101.137.131]) by cuda.sgi.com with ESMTP id jm6hl6UYHCLkfyDS for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 17:26:51 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Apparent-Source-IP: 150.101.137.131 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2BaDwA4w3FXEHvHLHlbgz6BU4Zvnl0BAQEBAQEGjEOKEIYSBAICgTFNAQEBAQEBBwEBAQEBAQEBPkCETQEBBDocIxAIAw4KCSUPBSUDBxoTiC/AfgELJR6FQoUVihsFmQKOL48uj3+CXByBXioyiTABAQE Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail07.adl2.internode.on.net with ESMTP; 28 Jun 2016 09:56:49 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bHgrZ-0007gU-BM; Tue, 28 Jun 2016 10:26:49 +1000 Date: Tue, 28 Jun 2016 10:26:49 +1000 From: Dave Chinner <david@fromorbit.com> To: Christoph Hellwig <hch@lst.de> Cc: xfs@oss.sgi.com, rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V5 Message-ID: <20160628002649.GI12670@dastard> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V5 References: <1464792297-13185-1-git-send-email-hch@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1464792297-13185-1-git-send-email-hch@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail07.adl2.internode.on.net[150.101.137.131] X-Barracuda-Start-Time: 1467073611 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 10355 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30817 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 01, 2016 at 04:44:43PM +0200, Christoph Hellwig wrote: > This series add a new file system I/O path that uses the iomap structure > introduced for the pNFS support and support multi-page buffered writes. > > This was first started by Dave Chinner a long time ago, then I did beat > it into shape for production runs in a very constrained ARM NAS > enviroment for Tuxera almost as long ago, and now half a dozen rewrites > later it's back. > > The basic idea is to avoid the per-block get_blocks overhead > and make use of extents in the buffered write path by iterating over > them instead. Christoph, it look slike there's an ENOSPC+ENOMEM behavioural regression here. generic/224 on my 1p/1GB RAM VM using a 1k lock size filesystem has significantly different behaviour once ENOSPC is hit withi this patchset. It ends up with an endless stream of errors like this: [ 687.530641] XFS (sdc): page discard on page ffffea0000197700, inode 0xb52c, offset 400338944. [ 687.539828] XFS (sdc): page discard on page ffffea0000197740, inode 0xb52c, offset 400343040. [ 687.549035] XFS (sdc): page discard on page ffffea0000197780, inode 0xb52c, offset 400347136. [ 687.558222] XFS (sdc): page discard on page ffffea00001977c0, inode 0xb52c, offset 400351232. [ 687.567391] XFS (sdc): page discard on page ffffea0000846000, inode 0xb52c, offset 400355328. [ 687.576602] XFS (sdc): page discard on page ffffea0000846040, inode 0xb52c, offset 400359424. [ 687.585794] XFS (sdc): page discard on page ffffea0000846080, inode 0xb52c, offset 400363520. [ 687.595005] XFS (sdc): page discard on page ffffea00008460c0, inode 0xb52c, offset 400367616. Yeah, it's been going for ten minutes already, and it's reporting this for every page on inode 0xb52c. df reports: Filesystem 1K-blocks Used Available Use% Mounted on /dev/sdc 1038336 1038334 2 100% /mnt/scratch So it's looking very much like the iomap write is allowing pages through the write side rather than giving ENOSPC. i.e. the initial alloc fails, it triggers a flush, which triggers a page discard, which then allows the next write to proceed because it's free up blocks. The trace looks like this dd-12284 [000] 983.936583: xfs_file_buffered_write: dev 8:32 ino 0xb52c size 0xa00000 offset 0x1f37a000 count 0x1000 ioflags dd-12284 [000] 983.936584: xfs_ilock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff8150bb47s dd-12284 [000] 983.936585: xfs_iomap_prealloc_size: dev 8:32 ino 0xb52c prealloc blocks 64 shift 6 m_writeio_blocks 64 dd-12284 [000] 983.936585: xfs_delalloc_enospc: dev 8:32 ino 0xb52c isize 0x1f37a000 disize 0xa00000 offset 0x1f37a000 count 4096 dd-12284 [000] 983.936586: xfs_delalloc_enospc: dev 8:32 ino 0xb52c isize 0x1f37a000 disize 0xa00000 offset 0x1f37a000 count 4096 dd-12284 [000] 983.936586: xfs_iunlock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff8150bc61s kworker/u2:0-6 [000] 983.946649: xfs_writepage: dev 8:32 ino 0xb52c pgoff 0x1f379000 size 0x1f37a000 offset 0 length 0 delalloc 1 unwritten 0 kworker/u2:0-6 [000] 983.946650: xfs_ilock: dev 8:32 ino 0xb52c flags ILOCK_SHARED caller 0xffffffff814f4b49s kworker/u2:0-6 [000] 983.946651: xfs_iunlock: dev 8:32 ino 0xb52c flags ILOCK_SHARED caller 0xffffffff814f4bf5s kworker/u2:0-6 [000] 983.948093: xfs_ilock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff814f555fs kworker/u2:0-6 [000] 983.948095: xfs_bunmap: dev 8:32 ino 0xb52c size 0xa00000 bno 0x7cde4 len 0x1flags caller 0xffffffff814f9123s kworker/u2:0-6 [000] 983.948096: xfs_bmap_pre_update: dev 8:32 ino 0xb52c state idx 0 offset 511460 block 4503599627239431 count 4 flag 0 caller 0xffffffff814c6ea3s kworker/u2:0-6 [000] 983.948097: xfs_bmap_post_update: dev 8:32 ino 0xb52c state idx 0 offset 511461 block 4503599627239431 count 3 flag 0 caller 0xffffffff814c6f1es kworker/u2:0-6 [000] 983.948097: xfs_bunmap: dev 8:32 ino 0xb52c size 0xa00000 bno 0x7cde5 len 0x1flags caller 0xffffffff814f9123s kworker/u2:0-6 [000] 983.948098: xfs_bmap_pre_update: dev 8:32 ino 0xb52c state idx 0 offset 511461 block 4503599627239431 count 3 flag 0 caller 0xffffffff814c6ea3s kworker/u2:0-6 [000] 983.948098: xfs_bmap_post_update: dev 8:32 ino 0xb52c state idx 0 offset 511462 block 4503599627239431 count 2 flag 0 caller 0xffffffff814c6f1es kworker/u2:0-6 [000] 983.948099: xfs_bunmap: dev 8:32 ino 0xb52c size 0xa00000 bno 0x7cde6 len 0x1flags caller 0xffffffff814f9123s kworker/u2:0-6 [000] 983.948099: xfs_bmap_pre_update: dev 8:32 ino 0xb52c state idx 0 offset 511462 block 4503599627239431 count 2 flag 0 caller 0xffffffff814c6ea3s kworker/u2:0-6 [000] 983.948100: xfs_bmap_post_update: dev 8:32 ino 0xb52c state idx 0 offset 511463 block 4503599627239431 count 1 flag 0 caller 0xffffffff814c6f1es kworker/u2:0-6 [000] 983.948100: xfs_bunmap: dev 8:32 ino 0xb52c size 0xa00000 bno 0x7cde7 len 0x1flags caller 0xffffffff814f9123s kworker/u2:0-6 [000] 983.948101: xfs_iext_remove: dev 8:32 ino 0xb52c state idx 0 offset 511463 block 4503599627239431 count 1 flag 0 caller 0xffffffff814c6d2as kworker/u2:0-6 [000] 983.948101: xfs_iunlock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff814f55e8s kworker/u2:0-6 [000] 983.948102: xfs_invalidatepage: dev 8:32 ino 0xb52c pgoff 0x1f379000 size 0x1f37a000 offset 0 length 1000 delalloc 1 unwritten 0 kworker/u2:0-6 [000] 983.948102: xfs_releasepage: dev 8:32 ino 0xb52c pgoff 0x1f379000 size 0x1f37a000 offset 0 length 0 delalloc 0 unwritten 0 [snip eof block scan locking] dd-12284 [000] 983.948239: xfs_file_buffered_write: dev 8:32 ino 0xb52c size 0xa00000 offset 0x1f37a000 count 0x1000 ioflags dd-12284 [000] 983.948239: xfs_ilock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff8150bb47s dd-12284 [000] 983.948240: xfs_iomap_prealloc_size: dev 8:32 ino 0xb52c prealloc blocks 64 shift 0 m_writeio_blocks 64 dd-12284 [000] 983.948242: xfs_delalloc_enospc: dev 8:32 ino 0xb52c isize 0x1f37a000 disize 0xa00000 offset 0x1f37a000 count 4096 dd-12284 [000] 983.948243: xfs_iext_insert: dev 8:32 ino 0xb52c state idx 0 offset 511464 block 4503599627239431 count 4 flag 0 caller 0xffffffff814c265as dd-12284 [000] 983.948243: xfs_iunlock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff8150bc61s dd-12284 [000] 983.948244: xfs_iomap_alloc: dev 8:32 ino 0xb52c size 0xa00000 offset 0x1f37a000 count 4096 type invalid startoff 0x7cde8 startblock -1 blockcount 0x4 dd-12284 [000] 983.948250: xfs_iunlock: dev 8:32 ino 0xb52c flags IOLOCK_EXCL caller 0xffffffff81502378s dd-12284 [000] 983.948254: xfs_ilock: dev 8:32 ino 0xb52c flags IOLOCK_EXCL caller 0xffffffff81502352s dd-12284 [000] 983.948256: xfs_update_time: dev 8:32 ino 0xb52c dd-12284 [000] 983.948257: xfs_log_reserve: dev 8:32 t_ocnt 0 t_cnt 0 t_curr_res 2860 t_unit_res 2860 t_flags XLOG_TIC_INITED reserveq empty writeq empty grant_reserve_cycle 1 grant_reserve_bytes 956212 grant_write_cycle 1 grant_write_bytes 956212 curr_cycle 1 curr_block 1863 tail_cycle 1 tail_block 1861 dd-12284 [000] 983.948257: xfs_log_reserve_exit: dev 8:32 t_ocnt 0 t_cnt 0 t_curr_res 2860 t_unit_res 2860 t_flags XLOG_TIC_INITED reserveq empty writeq empty grant_reserve_cycle 1 grant_reserve_bytes 959072 grant_write_cycle 1 grant_write_bytes 959072 curr_cycle 1 curr_block 1863 tail_cycle 1 tail_block 1861 dd-12284 [000] 983.948258: xfs_ilock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff8150c4dfs dd-12284 [000] 983.948260: xfs_log_done_nonperm: dev 8:32 t_ocnt 0 t_cnt 0 t_curr_res 2860 t_unit_res 2860 t_flags XLOG_TIC_INITED reserveq empty writeq empty grant_reserve_cycle 1 grant_reserve_bytes 959072 grant_write_cycle 1 grant_write_bytes 959072 curr_cycle 1 curr_block 1863 tail_cycle 1 tail_block 1861 dd-12284 [000] 983.948260: xfs_log_ungrant_enter: dev 8:32 t_ocnt 0 t_cnt 0 t_curr_res 2860 t_unit_res 2860 t_flags XLOG_TIC_INITED reserveq empty writeq empty grant_reserve_cycle 1 grant_reserve_bytes 959072 grant_write_cycle 1 grant_write_bytes 959072 curr_cycle 1 curr_block 1863 tail_cycle 1 tail_block 1861 dd-12284 [000] 983.948260: xfs_log_ungrant_sub: dev 8:32 t_ocnt 0 t_cnt 0 t_curr_res 2860 t_unit_res 2860 t_flags XLOG_TIC_INITED reserveq empty writeq empty grant_reserve_cycle 1 grant_reserve_bytes 959072 grant_write_cycle 1 grant_write_bytes 959072 curr_cycle 1 curr_block 1863 tail_cycle 1 tail_block 1861 dd-12284 [000] 983.948261: xfs_log_ungrant_exit: dev 8:32 t_ocnt 0 t_cnt 0 t_curr_res 2860 t_unit_res 2860 t_flags XLOG_TIC_INITED reserveq empty writeq empty grant_reserve_cycle 1 grant_reserve_bytes 956212 grant_write_cycle 1 grant_write_bytes 956212 curr_cycle 1 curr_block 1863 tail_cycle 1 tail_block 1861 dd-12284 [000] 983.948261: xfs_iunlock: dev 8:32 ino 0xb52c flags ILOCK_EXCL caller 0xffffffff81526d6cs Ad so the cycle goes. The next page at offset 0x1f37b000 fails allocation, triggers a flush, which results in the write at 0x1f37a000 failing and freeing it's delalloc blocks, which then allows the retry of the write at 0x1f37b000 to succeed.... I can see that mapping errors (i.e. the AS_ENOSPC error) ar enot propagated into the write() path, but that's the same as the old code. What I don't quite understand is how delalloc has blown through the XFS_ALLOC_SET_ASIDE() limits which are supposed to trigger ENOSPC on the write() side much earlier than just one or two blocks free.... Something doesn't quite add up here, and I haven't been able to put my finger on it yet. Cheers, Dave. -- Dave Chinner david@fromorbit.com From darrick.wong@oracle.com Mon Jun 27 22:26:42 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id EC5097CA1 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 22:26:42 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id AD7F5304032 for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 20:26:39 -0700 (PDT) X-ASG-Debug-ID: 1467084389-04bdf074b4161200001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id Qc48mX4VXrm4PzPH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Mon, 27 Jun 2016 20:26:30 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5S3QPFd005883 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 03:26:26 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5S3QPeW022575 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 03:26:25 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5S3QNwZ024036; Tue, 28 Jun 2016 03:26:24 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Mon, 27 Jun 2016 20:26:22 -0700 Date: Mon, 27 Jun 2016 20:26:21 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys Message-ID: <20160628032621.GB4917@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612635526.12839.13865365567940815077.stgit@birch.djwong.org> <20160622151706.GB5423@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160622151706.GB5423@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467084390 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 33261 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30821 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Wed, Jun 22, 2016 at 11:17:06AM -0400, Brian Foster wrote: > On Thu, Jun 16, 2016 at 06:19:15PM -0700, Darrick J. Wong wrote: > > On a filesystem with both reflink and reverse mapping enabled, it's > > possible to have multiple rmap records referring to the same blocks on > > disk. When overlapping intervals are possible, querying a classic > > btree to find all records intersecting a given interval is inefficient > > because we cannot use the left side of the search interval to filter > > out non-matching records the same way that we can use the existing > > btree key to filter out records coming after the right side of the > > search interval. This will become important once we want to use the > > rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl. > > > > (For the non-overlapping case, we can perform such queries trivially > > by starting at the left side of the interval and walking the tree > > until we pass the right side.) > > > > Therefore, extend the btree code to come closer to supporting > > intervals as a first-class record attribute. This involves widening > > the btree node's key space to store both the lowest key reachable via > > the node pointer (as the btree does now) and the highest key reachable > > via the same pointer and teaching the btree modifying functions to > > keep the highest-key records up to date. > > > > This behavior can be turned on via a new btree ops flag so that btrees > > that cannot store overlapping intervals don't pay the overhead costs > > in terms of extra code and disk format changes. > > > > v2: When we're deleting a record in a btree that supports overlapped > > interval records and the deletion results in two btree blocks being > > joined, we defer updating the high/low keys until after all possible > > joining (at higher levels in the tree) have finished. At this point, > > the btree pointers at all levels have been updated to remove the empty > > blocks and we can update the low and high keys. > > > > When we're doing this, we must be careful to update the keys of all > > node pointers up to the root instead of stopping at the first set of > > keys that don't need updating. This is because it's possible for a > > single deletion to cause joining of multiple levels of tree, and so > > we need to update everything going back to the root. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > --- > > I think I get the gist of this and it mostly looks Ok to me. A few > questions and minor comments... Ok. > > fs/xfs/libxfs/xfs_btree.c | 379 +++++++++++++++++++++++++++++++++++++++++---- > > fs/xfs/libxfs/xfs_btree.h | 16 ++ > > fs/xfs/xfs_trace.h | 36 ++++ > > 3 files changed, 395 insertions(+), 36 deletions(-) > > > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > index a096539..afcafd6 100644 > > --- a/fs/xfs/libxfs/xfs_btree.c > > +++ b/fs/xfs/libxfs/xfs_btree.c > > @@ -52,6 +52,11 @@ static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { > > xfs_magics[!!((cur)->bc_flags & XFS_BTREE_CRC_BLOCKS)][cur->bc_btnum] > > > > > > +struct xfs_btree_double_key { > > + union xfs_btree_key low; > > + union xfs_btree_key high; > > +}; > > + > > STATIC int /* error (0 or EFSCORRUPTED) */ > > xfs_btree_check_lblock( > > struct xfs_btree_cur *cur, /* btree cursor */ > > @@ -428,6 +433,30 @@ xfs_btree_dup_cursor( > > * into a btree block (xfs_btree_*_offset) or return a pointer to the given > > * record, key or pointer (xfs_btree_*_addr). Note that all addressing > > * inside the btree block is done using indices starting at one, not zero! > > + * > > + * If XFS_BTREE_OVERLAPPING is set, then this btree supports keys containing > > + * overlapping intervals. In such a tree, records are still sorted lowest to > > + * highest and indexed by the smallest key value that refers to the record. > > + * However, nodes are different: each pointer has two associated keys -- one > > + * indexing the lowest key available in the block(s) below (the same behavior > > + * as the key in a regular btree) and another indexing the highest key > > + * available in the block(s) below. Because records are /not/ sorted by the > > + * highest key, all leaf block updates require us to compute the highest key > > + * that matches any record in the leaf and to recursively update the high keys > > + * in the nodes going further up in the tree, if necessary. Nodes look like > > + * this: > > + * > > + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ > > + * Non-Leaf: | header | lo1 | hi1 | lo2 | hi2 | ... | ptr 1 | ptr 2 | ... | > > + * +--------+-----+-----+-----+-----+-----+-------+-------+-----+ > > + * > > + * To perform an interval query on an overlapped tree, perform the usual > > + * depth-first search and use the low and high keys to decide if we can skip > > + * that particular node. If a leaf node is reached, return the records that > > + * intersect the interval. Note that an interval query may return numerous > > + * entries. For a non-overlapped tree, simply search for the record associated > > + * with the lowest key and iterate forward until a non-matching record is > > + * found. > > */ > > > > /* > > @@ -445,6 +474,17 @@ static inline size_t xfs_btree_block_len(struct xfs_btree_cur *cur) > > return XFS_BTREE_SBLOCK_LEN; > > } > > > > +/* Return size of btree block keys for this btree instance. */ > > +static inline size_t xfs_btree_key_len(struct xfs_btree_cur *cur) > > +{ > > + size_t len; > > + > > + len = cur->bc_ops->key_len; > > + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) > > + len *= 2; > > + return len; > > +} > > + > > /* > > * Return size of btree block pointers for this btree instance. > > */ > > @@ -475,7 +515,19 @@ xfs_btree_key_offset( > > int n) > > { > > return xfs_btree_block_len(cur) + > > - (n - 1) * cur->bc_ops->key_len; > > + (n - 1) * xfs_btree_key_len(cur); > > +} > > + > > +/* > > + * Calculate offset of the n-th high key in a btree block. > > + */ > > +STATIC size_t > > +xfs_btree_high_key_offset( > > + struct xfs_btree_cur *cur, > > + int n) > > +{ > > + return xfs_btree_block_len(cur) + > > + (n - 1) * xfs_btree_key_len(cur) + cur->bc_ops->key_len; > > } > > > > /* > > @@ -488,7 +540,7 @@ xfs_btree_ptr_offset( > > int level) > > { > > return xfs_btree_block_len(cur) + > > - cur->bc_ops->get_maxrecs(cur, level) * cur->bc_ops->key_len + > > + cur->bc_ops->get_maxrecs(cur, level) * xfs_btree_key_len(cur) + > > (n - 1) * xfs_btree_ptr_len(cur); > > } > > > > @@ -519,6 +571,19 @@ xfs_btree_key_addr( > > } > > > > /* > > + * Return a pointer to the n-th high key in the btree block. > > + */ > > +STATIC union xfs_btree_key * > > +xfs_btree_high_key_addr( > > + struct xfs_btree_cur *cur, > > + int n, > > + struct xfs_btree_block *block) > > +{ > > + return (union xfs_btree_key *) > > + ((char *)block + xfs_btree_high_key_offset(cur, n)); > > +} > > + > > +/* > > * Return a pointer to the n-th block pointer in the btree block. > > */ > > STATIC union xfs_btree_ptr * > > @@ -1217,7 +1282,7 @@ xfs_btree_copy_keys( > > int numkeys) > > { > > ASSERT(numkeys >= 0); > > - memcpy(dst_key, src_key, numkeys * cur->bc_ops->key_len); > > + memcpy(dst_key, src_key, numkeys * xfs_btree_key_len(cur)); > > } > > > > /* > > @@ -1263,8 +1328,8 @@ xfs_btree_shift_keys( > > ASSERT(numkeys >= 0); > > ASSERT(dir == 1 || dir == -1); > > > > - dst_key = (char *)key + (dir * cur->bc_ops->key_len); > > - memmove(dst_key, key, numkeys * cur->bc_ops->key_len); > > + dst_key = (char *)key + (dir * xfs_btree_key_len(cur)); > > + memmove(dst_key, key, numkeys * xfs_btree_key_len(cur)); > > } > > > > /* > > @@ -1879,6 +1944,180 @@ error0: > > return error; > > } > > > > +/* Determine the low and high keys of a leaf block */ > > +STATIC void > > +xfs_btree_find_leaf_keys( > > + struct xfs_btree_cur *cur, > > + struct xfs_btree_block *block, > > + union xfs_btree_key *low, > > + union xfs_btree_key *high) > > +{ > > + int n; > > + union xfs_btree_rec *rec; > > + union xfs_btree_key max_hkey; > > + union xfs_btree_key hkey; > > + > > + rec = xfs_btree_rec_addr(cur, 1, block); > > + cur->bc_ops->init_key_from_rec(low, rec); > > + > > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > > + return; > > + > > + cur->bc_ops->init_high_key_from_rec(&max_hkey, rec); > > + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { > > + rec = xfs_btree_rec_addr(cur, n, block); > > + cur->bc_ops->init_high_key_from_rec(&hkey, rec); > > + if (cur->bc_ops->diff_two_keys(cur, &max_hkey, &hkey) > 0) > > + max_hkey = hkey; > > + } > > + > > + *high = max_hkey; > > +} > > + > > +/* Determine the low and high keys of a node block */ > > +STATIC void > > +xfs_btree_find_node_keys( > > + struct xfs_btree_cur *cur, > > + struct xfs_btree_block *block, > > + union xfs_btree_key *low, > > + union xfs_btree_key *high) > > +{ > > + int n; > > + union xfs_btree_key *hkey; > > + union xfs_btree_key *max_hkey; > > + > > + *low = *xfs_btree_key_addr(cur, 1, block); > > + > > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > > + return; > > + > > + max_hkey = xfs_btree_high_key_addr(cur, 1, block); > > + for (n = 2; n <= xfs_btree_get_numrecs(block); n++) { > > + hkey = xfs_btree_high_key_addr(cur, n, block); > > + if (cur->bc_ops->diff_two_keys(cur, max_hkey, hkey) > 0) > > + max_hkey = hkey; > > + } > > + > > + *high = *max_hkey; > > +} > > + > > +/* > > + * Update parental low & high keys from some block all the way back to the > > + * root of the btree. > > + */ > > +STATIC int > > +__xfs_btree_updkeys( > > + struct xfs_btree_cur *cur, > > + int level, > > + struct xfs_btree_block *block, > > + struct xfs_buf *bp0, > > + bool force_all) > > +{ > > + union xfs_btree_key lkey; /* keys from current level */ > > + union xfs_btree_key hkey; > > + union xfs_btree_key *nlkey; /* keys from the next level up */ > > + union xfs_btree_key *nhkey; > > + struct xfs_buf *bp; > > + int ptr = -1; > > ptr doesn't appear to require initialization. Ok. > > > + > > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > > + return 0; > > + > > + if (level + 1 >= cur->bc_nlevels) > > + return 0; > > This could use a comment to indicate we're checking for a parent level > to update. Ok. > > > + > > + trace_xfs_btree_updkeys(cur, level, bp0); > > + > > + if (level == 0) > > + xfs_btree_find_leaf_keys(cur, block, &lkey, &hkey); > > + else > > + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); > > + for (level++; level < cur->bc_nlevels; level++) { > > + block = xfs_btree_get_block(cur, level, &bp); > > + trace_xfs_btree_updkeys(cur, level, bp); > > + ptr = cur->bc_ptrs[level]; > > + nlkey = xfs_btree_key_addr(cur, ptr, block); > > + nhkey = xfs_btree_high_key_addr(cur, ptr, block); > > + if (!(cur->bc_ops->diff_two_keys(cur, nlkey, &lkey) != 0 || > > + cur->bc_ops->diff_two_keys(cur, nhkey, &hkey) != 0) && > > + !force_all) > > + break; > > + memcpy(nlkey, &lkey, cur->bc_ops->key_len); > > + memcpy(nhkey, &hkey, cur->bc_ops->key_len); > > + xfs_btree_log_keys(cur, bp, ptr, ptr); > > + if (level + 1 >= cur->bc_nlevels) > > + break; > > + xfs_btree_find_node_keys(cur, block, &lkey, &hkey); > > + } > > + > > + return 0; > > +} > > + > > +/* > > + * Update all the keys from a sibling block at some level in the cursor back > > + * to the root, stopping when we find a key pair that doesn't need updating. > > + */ > > +STATIC int > > +xfs_btree_sibling_updkeys( > > + struct xfs_btree_cur *cur, > > + int level, > > + int ptr, > > + struct xfs_btree_block *block, > > + struct xfs_buf *bp0) > > +{ > > + struct xfs_btree_cur *ncur; > > + int stat; > > + int error; > > + > > + error = xfs_btree_dup_cursor(cur, &ncur); > > + if (error) > > + return error; > > + > > + if (level + 1 >= ncur->bc_nlevels) > > + error = -EDOM; > > + else if (ptr == XFS_BB_RIGHTSIB) > > + error = xfs_btree_increment(ncur, level + 1, &stat); > > + else if (ptr == XFS_BB_LEFTSIB) > > + error = xfs_btree_decrement(ncur, level + 1, &stat); > > + else > > + error = -EBADE; > > So we inc/dec the cursor at the next level up the tree, then update the > keys up that path with the __xfs_btree_updkeys() call below. The inc/dec > calls explicitly say that they don't alter the cursor below the level, > so it looks like we'd end up with a weird cursor path here. > > Digging around further, it looks like we pass the sibling bp/block > pointers from the caller and thus __xfs_btree_updkeys() should do the > correct thing, but this is not very clear. If I'm on the right track, > I'd suggest to add a big fat comment here. :) Yep. /* * The caller passed us the sibling block in bp0/block, but the * (duplicate) cursor points to original block and not the sibling. * Therefore we must adjust the cursor at the next level higher * to point to the sibling block we were handed. Only then can * we go up the tree updating keys. */ > > + if (error || !stat) > > + return error; > > Looks like a potential cursor leak on error. Oops! > > + > > + error = __xfs_btree_updkeys(ncur, level, block, bp0, false); > > + xfs_btree_del_cursor(ncur, XFS_BTREE_NOERROR); > > + return error; > > +} > > + > > +/* > > + * Update all the keys from some level in cursor back to the root, stopping > > + * when we find a key pair that don't need updating. > > + */ > > +STATIC int > > +xfs_btree_updkeys( > > + struct xfs_btree_cur *cur, > > + int level) > > +{ > > + struct xfs_buf *bp; > > + struct xfs_btree_block *block; > > + > > + block = xfs_btree_get_block(cur, level, &bp); > > + return __xfs_btree_updkeys(cur, level, block, bp, false); > > +} > > + > > +/* Update all the keys from some level in cursor back to the root. */ > > +STATIC int > > +xfs_btree_updkeys_force( > > + struct xfs_btree_cur *cur, > > + int level) > > +{ > > + struct xfs_buf *bp; > > + struct xfs_btree_block *block; > > + > > + block = xfs_btree_get_block(cur, level, &bp); > > + return __xfs_btree_updkeys(cur, level, block, bp, true); > > +} > > + > > /* > > * Update keys at all levels from here to the root along the cursor's path. > > */ > > @@ -1893,6 +2132,9 @@ xfs_btree_updkey( > > union xfs_btree_key *kp; > > int ptr; > > > > + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) > > + return 0; > > + > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > XFS_BTREE_TRACE_ARGIK(cur, level, keyp); > > > > @@ -1970,7 +2212,8 @@ xfs_btree_update( > > ptr, LASTREC_UPDATE); > > } > > > > - /* Updating first rec in leaf. Pass new key value up to our parent. */ > > + /* Pass new key value up to our parent. */ > > + xfs_btree_updkeys(cur, 0); > > if (ptr == 1) { > > union xfs_btree_key key; > > > > @@ -2149,7 +2392,9 @@ xfs_btree_lshift( > > rkp = &key; > > } > > > > - /* Update the parent key values of right. */ > > + /* Update the parent key values of left and right. */ > > + xfs_btree_sibling_updkeys(cur, level, XFS_BB_LEFTSIB, left, lbp); > > + xfs_btree_updkeys(cur, level); > > error = xfs_btree_updkey(cur, rkp, level + 1); > > if (error) > > goto error0; > > @@ -2321,6 +2566,9 @@ xfs_btree_rshift( > > if (error) > > goto error1; > > > > + /* Update left and right parent pointers */ > > + xfs_btree_updkeys(cur, level); > > + xfs_btree_updkeys(tcur, level); > > In this case, we grab the last record of the block, increment from there > and update using the cursor. This is much more straightforward, imo. > Could we use this approach in the left shift case as well? Yes, I think so. I might have started refactoring btree_sibling_updkeys out of existence and got distracted, since there isn't anything that uses the RIGHTSIB ptr value. > > error = xfs_btree_updkey(tcur, rkp, level + 1); > > if (error) > > goto error1; > > @@ -2356,7 +2604,7 @@ __xfs_btree_split( > > struct xfs_btree_cur *cur, > > int level, > > union xfs_btree_ptr *ptrp, > > - union xfs_btree_key *key, > > + struct xfs_btree_double_key *key, > > struct xfs_btree_cur **curp, > > int *stat) /* success/failure */ > > { > > @@ -2452,9 +2700,6 @@ __xfs_btree_split( > > > > xfs_btree_log_keys(cur, rbp, 1, rrecs); > > xfs_btree_log_ptrs(cur, rbp, 1, rrecs); > > - > > - /* Grab the keys to the entries moved to the right block */ > > - xfs_btree_copy_keys(cur, key, rkp, 1); > > } else { > > /* It's a leaf. Move records. */ > > union xfs_btree_rec *lrp; /* left record pointer */ > > @@ -2465,12 +2710,8 @@ __xfs_btree_split( > > > > xfs_btree_copy_recs(cur, rrp, lrp, rrecs); > > xfs_btree_log_recs(cur, rbp, 1, rrecs); > > - > > - cur->bc_ops->init_key_from_rec(key, > > - xfs_btree_rec_addr(cur, 1, right)); > > } > > > > - > > /* > > * Find the left block number by looking in the buffer. > > * Adjust numrecs, sibling pointers. > > @@ -2484,6 +2725,12 @@ __xfs_btree_split( > > xfs_btree_set_numrecs(left, lrecs); > > xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs); > > > > + /* Find the low & high keys for the new block. */ > > + if (level > 0) > > + xfs_btree_find_node_keys(cur, right, &key->low, &key->high); > > + else > > + xfs_btree_find_leaf_keys(cur, right, &key->low, &key->high); > > + > > Why not push these into the above if/else where the previous key > copy/init calls were removed from? We don't set bb_numrecs on the right block until the line above the new hunk, and the btree_find_*_keys functions require numrecs to be set. The removed key copy/init calls only looked at keys[1]. That said, it's trivial to move the set_numrecs calls above the if statement. > > xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS); > > xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); > > > > @@ -2499,6 +2746,10 @@ __xfs_btree_split( > > xfs_btree_set_sibling(cur, rrblock, &rptr, XFS_BB_LEFTSIB); > > xfs_btree_log_block(cur, rrbp, XFS_BB_LEFTSIB); > > } > > + > > + /* Update the left block's keys... */ > > + xfs_btree_updkeys(cur, level); > > + > > /* > > * If the cursor is really in the right block, move it there. > > * If it's just pointing past the last entry in left, then we'll > > @@ -2537,7 +2788,7 @@ struct xfs_btree_split_args { > > struct xfs_btree_cur *cur; > > int level; > > union xfs_btree_ptr *ptrp; > > - union xfs_btree_key *key; > > + struct xfs_btree_double_key *key; > > struct xfs_btree_cur **curp; > > int *stat; /* success/failure */ > > int result; > > @@ -2586,7 +2837,7 @@ xfs_btree_split( > > struct xfs_btree_cur *cur, > > int level, > > union xfs_btree_ptr *ptrp, > > - union xfs_btree_key *key, > > + struct xfs_btree_double_key *key, > > struct xfs_btree_cur **curp, > > int *stat) /* success/failure */ > > { > > @@ -2806,27 +3057,27 @@ xfs_btree_new_root( > > bp = lbp; > > nptr = 2; > > } > > + > > /* Fill in the new block's btree header and log it. */ > > xfs_btree_init_block_cur(cur, nbp, cur->bc_nlevels, 2); > > xfs_btree_log_block(cur, nbp, XFS_BB_ALL_BITS); > > ASSERT(!xfs_btree_ptr_is_null(cur, &lptr) && > > !xfs_btree_ptr_is_null(cur, &rptr)); > > - > > ? Don't know why I did that. I like having one blank line before a chunk of code, but there's no reason to remove that one. > > /* Fill in the key data in the new root. */ > > if (xfs_btree_get_level(left) > 0) { > > - xfs_btree_copy_keys(cur, > > + xfs_btree_find_node_keys(cur, left, > > xfs_btree_key_addr(cur, 1, new), > > - xfs_btree_key_addr(cur, 1, left), 1); > > - xfs_btree_copy_keys(cur, > > + xfs_btree_high_key_addr(cur, 1, new)); > > + xfs_btree_find_node_keys(cur, right, > > xfs_btree_key_addr(cur, 2, new), > > - xfs_btree_key_addr(cur, 1, right), 1); > > + xfs_btree_high_key_addr(cur, 2, new)); > > } else { > > - cur->bc_ops->init_key_from_rec( > > - xfs_btree_key_addr(cur, 1, new), > > - xfs_btree_rec_addr(cur, 1, left)); > > - cur->bc_ops->init_key_from_rec( > > - xfs_btree_key_addr(cur, 2, new), > > - xfs_btree_rec_addr(cur, 1, right)); > > + xfs_btree_find_leaf_keys(cur, left, > > + xfs_btree_key_addr(cur, 1, new), > > + xfs_btree_high_key_addr(cur, 1, new)); > > + xfs_btree_find_leaf_keys(cur, right, > > + xfs_btree_key_addr(cur, 2, new), > > + xfs_btree_high_key_addr(cur, 2, new)); > > } > > xfs_btree_log_keys(cur, nbp, 1, 2); > > > > @@ -2837,6 +3088,7 @@ xfs_btree_new_root( > > xfs_btree_ptr_addr(cur, 2, new), &rptr, 1); > > xfs_btree_log_ptrs(cur, nbp, 1, 2); > > > > + > > Extra line. Removed. > > /* Fix up the cursor. */ > > xfs_btree_setbuf(cur, cur->bc_nlevels, nbp); > > cur->bc_ptrs[cur->bc_nlevels] = nptr; > > @@ -2862,7 +3114,7 @@ xfs_btree_make_block_unfull( > > int *index, /* new tree index */ > > union xfs_btree_ptr *nptr, /* new btree ptr */ > > struct xfs_btree_cur **ncur, /* new btree cursor */ > > - union xfs_btree_key *key, /* key of new block */ > > + struct xfs_btree_double_key *key, /* key of new block */ > > int *stat) > > { > > int error = 0; > > @@ -2918,6 +3170,22 @@ xfs_btree_make_block_unfull( > > return 0; > > } > > > > +/* Copy a double key into a btree block. */ > > +static void > > +xfs_btree_copy_double_keys( > > + struct xfs_btree_cur *cur, > > + int ptr, > > + struct xfs_btree_block *block, > > + struct xfs_btree_double_key *key) > > +{ > > + memcpy(xfs_btree_key_addr(cur, ptr, block), &key->low, > > + cur->bc_ops->key_len); > > + > > + if (cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING) > > + memcpy(xfs_btree_high_key_addr(cur, ptr, block), &key->high, > > + cur->bc_ops->key_len); > > +} > > + > > /* > > * Insert one record/level. Return information to the caller > > * allowing the next level up to proceed if necessary. > > @@ -2927,7 +3195,7 @@ xfs_btree_insrec( > > struct xfs_btree_cur *cur, /* btree cursor */ > > int level, /* level to insert record at */ > > union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ > > - union xfs_btree_key *key, /* i/o: block key for ptrp */ > > + struct xfs_btree_double_key *key, /* i/o: block key for ptrp */ > > struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ > > int *stat) /* success/failure */ > > { > > @@ -2935,7 +3203,7 @@ xfs_btree_insrec( > > struct xfs_buf *bp; /* buffer for block */ > > union xfs_btree_ptr nptr; /* new block ptr */ > > struct xfs_btree_cur *ncur; /* new btree cursor */ > > - union xfs_btree_key nkey; /* new block key */ > > + struct xfs_btree_double_key nkey; /* new block key */ > > union xfs_btree_rec rec; /* record to insert */ > > int optr; /* old key/record index */ > > int ptr; /* key/record index */ > > @@ -2944,11 +3212,12 @@ xfs_btree_insrec( > > #ifdef DEBUG > > int i; > > #endif > > + xfs_daddr_t old_bn; > > > > /* Make a key out of the record data to be inserted, and save it. */ > > if (level == 0) { > > cur->bc_ops->init_rec_from_cur(cur, &rec); > > - cur->bc_ops->init_key_from_rec(key, &rec); > > + cur->bc_ops->init_key_from_rec(&key->low, &rec); > > } > > > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > @@ -2983,6 +3252,7 @@ xfs_btree_insrec( > > > > /* Get pointers to the btree buffer and block. */ > > block = xfs_btree_get_block(cur, level, &bp); > > + old_bn = bp ? bp->b_bn : XFS_BUF_DADDR_NULL; > > numrecs = xfs_btree_get_numrecs(block); > > > > #ifdef DEBUG > > @@ -2996,7 +3266,7 @@ xfs_btree_insrec( > > ASSERT(cur->bc_ops->recs_inorder(cur, &rec, > > xfs_btree_rec_addr(cur, ptr, block))); > > } else { > > - ASSERT(cur->bc_ops->keys_inorder(cur, key, > > + ASSERT(cur->bc_ops->keys_inorder(cur, &key->low, > > xfs_btree_key_addr(cur, ptr, block))); > > } > > } > > @@ -3059,7 +3329,7 @@ xfs_btree_insrec( > > #endif > > > > /* Now put the new data in, bump numrecs and log it. */ > > - xfs_btree_copy_keys(cur, kp, key, 1); > > + xfs_btree_copy_double_keys(cur, ptr, block, key); > > xfs_btree_copy_ptrs(cur, pp, ptrp, 1); > > numrecs++; > > xfs_btree_set_numrecs(block, numrecs); > > @@ -3095,8 +3365,24 @@ xfs_btree_insrec( > > xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); > > > > /* If we inserted at the start of a block, update the parents' keys. */ > > This comment is associated with the codeblock that has been pushed > further down, no? Correct. I think that got mismerged somewhere along the way. > > + if (ncur && bp->b_bn != old_bn) { > > + /* > > + * We just inserted into a new tree block, which means that > > + * the key for the block is in nkey, not the tree. > > + */ > > + if (level == 0) > > + xfs_btree_find_leaf_keys(cur, block, &nkey.low, > > + &nkey.high); > > + else > > + xfs_btree_find_node_keys(cur, block, &nkey.low, > > + &nkey.high); > > + } else { > > + /* Updating the left block, do it the standard way. */ > > + xfs_btree_updkeys(cur, level); > > + } > > + > > Not quite sure I follow the purpose of this hunk. Is this for the case > where a btree split occurs, nkey is filled in for the new/right block > and then (after nkey is filled in) the new record ends up being added to > the new block? If so, what about the case where ncur is not created? > (It looks like that's possible from the code, but I could easily be > missing some context as to why that's not the case.) Yes, the first part of the if-else hunk is to fill out nkey when we've split a btree block. Now that I look at it again, I think that whole weird conditional could be replaced with the same xfs_btree_ptr_is_null() check later on. I think it can also be combined with it. Commentage for now: /* * If we just inserted a new tree block, we have to find the low * and high keys for the new block and arrange to pass them back * separately. If we're just updating a block we can use the * regular tree update mechanism. */ > In any event, I think we could elaborate a bit in the comment on why > this is necessary. I'd also move it above the top-level if/else. > > > if (optr == 1) { > > - error = xfs_btree_updkey(cur, key, level + 1); > > + error = xfs_btree_updkey(cur, &key->low, level + 1); > > if (error) > > goto error0; > > } > > @@ -3147,7 +3433,7 @@ xfs_btree_insert( > > union xfs_btree_ptr nptr; /* new block number (split result) */ > > struct xfs_btree_cur *ncur; /* new cursor (split result) */ > > struct xfs_btree_cur *pcur; /* previous level's cursor */ > > - union xfs_btree_key key; /* key of block to insert */ > > + struct xfs_btree_double_key key; /* key of block to insert */ > > Probably should fix up the function param alignment here and the couple > other or so places we make this change. I changed the name to xfs_btree_bigkey, which avoids the alignment problems. --D > > Brian > > > > > level = 0; > > ncur = NULL; > > @@ -3552,6 +3838,7 @@ xfs_btree_delrec( > > * If we deleted the leftmost entry in the block, update the > > * key values above us in the tree. > > */ > > + xfs_btree_updkeys(cur, level); > > if (ptr == 1) { > > error = xfs_btree_updkey(cur, keyp, level + 1); > > if (error) > > @@ -3882,6 +4169,16 @@ xfs_btree_delrec( > > if (level > 0) > > cur->bc_ptrs[level]--; > > > > + /* > > + * We combined blocks, so we have to update the parent keys if the > > + * btree supports overlapped intervals. However, bc_ptrs[level + 1] > > + * points to the old block so that the caller knows which record to > > + * delete. Therefore, the caller must be savvy enough to call updkeys > > + * for us if we return stat == 2. The other exit points from this > > + * function don't require deletions further up the tree, so they can > > + * call updkeys directly. > > + */ > > + > > XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); > > /* Return value means the next level up has something to do. */ > > *stat = 2; > > @@ -3907,6 +4204,7 @@ xfs_btree_delete( > > int error; /* error return value */ > > int level; > > int i; > > + bool joined = false; > > > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > > > @@ -3920,8 +4218,17 @@ xfs_btree_delete( > > error = xfs_btree_delrec(cur, level, &i); > > if (error) > > goto error0; > > + if (i == 2) > > + joined = true; > > } > > > > + /* > > + * If we combined blocks as part of deleting the record, delrec won't > > + * have updated the parent keys so we have to do that here. > > + */ > > + if (joined) > > + xfs_btree_updkeys_force(cur, 0); > > + > > if (i == 0) { > > for (level = 1; level < cur->bc_nlevels; level++) { > > if (cur->bc_ptrs[level] == 0) { > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > index b99c018..a5ec6c7 100644 > > --- a/fs/xfs/libxfs/xfs_btree.h > > +++ b/fs/xfs/libxfs/xfs_btree.h > > @@ -126,6 +126,9 @@ struct xfs_btree_ops { > > size_t key_len; > > size_t rec_len; > > > > + /* flags */ > > + uint flags; > > + > > /* cursor operations */ > > struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); > > void (*update_cursor)(struct xfs_btree_cur *src, > > @@ -162,11 +165,21 @@ struct xfs_btree_ops { > > union xfs_btree_rec *rec); > > void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, > > union xfs_btree_ptr *ptr); > > + void (*init_high_key_from_rec)(union xfs_btree_key *key, > > + union xfs_btree_rec *rec); > > > > /* difference between key value and cursor value */ > > __int64_t (*key_diff)(struct xfs_btree_cur *cur, > > union xfs_btree_key *key); > > > > + /* > > + * Difference between key2 and key1 -- positive if key2 > key1, > > + * negative if key2 < key1, and zero if equal. > > + */ > > + __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur, > > + union xfs_btree_key *key1, > > + union xfs_btree_key *key2); > > + > > const struct xfs_buf_ops *buf_ops; > > > > #if defined(DEBUG) || defined(XFS_WARN) > > @@ -182,6 +195,9 @@ struct xfs_btree_ops { > > #endif > > }; > > > > +/* btree ops flags */ > > +#define XFS_BTREE_OPS_OVERLAPPING (1<<0) /* overlapping intervals */ > > + > > /* > > * Reasons for the update_lastrec method to be called. > > */ > > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > > index 68f27f7..ffea28c 100644 > > --- a/fs/xfs/xfs_trace.h > > +++ b/fs/xfs/xfs_trace.h > > @@ -38,6 +38,7 @@ struct xlog_recover_item; > > struct xfs_buf_log_format; > > struct xfs_inode_log_format; > > struct xfs_bmbt_irec; > > +struct xfs_btree_cur; > > > > DECLARE_EVENT_CLASS(xfs_attr_list_class, > > TP_PROTO(struct xfs_attr_list_context *ctx), > > @@ -2183,6 +2184,41 @@ DEFINE_DISCARD_EVENT(xfs_discard_toosmall); > > DEFINE_DISCARD_EVENT(xfs_discard_exclude); > > DEFINE_DISCARD_EVENT(xfs_discard_busy); > > > > +/* btree cursor events */ > > +DECLARE_EVENT_CLASS(xfs_btree_cur_class, > > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), > > + TP_ARGS(cur, level, bp), > > + TP_STRUCT__entry( > > + __field(dev_t, dev) > > + __field(xfs_btnum_t, btnum) > > + __field(int, level) > > + __field(int, nlevels) > > + __field(int, ptr) > > + __field(xfs_daddr_t, daddr) > > + ), > > + TP_fast_assign( > > + __entry->dev = cur->bc_mp->m_super->s_dev; > > + __entry->btnum = cur->bc_btnum; > > + __entry->level = level; > > + __entry->nlevels = cur->bc_nlevels; > > + __entry->ptr = cur->bc_ptrs[level]; > > + __entry->daddr = bp->b_bn; > > + ), > > + TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx", > > + MAJOR(__entry->dev), MINOR(__entry->dev), > > + __entry->btnum, > > + __entry->level, > > + __entry->nlevels, > > + __entry->ptr, > > + (unsigned long long)__entry->daddr) > > +) > > + > > +#define DEFINE_BTREE_CUR_EVENT(name) \ > > +DEFINE_EVENT(xfs_btree_cur_class, name, \ > > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > > + TP_ARGS(cur, level, bp)) > > +DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > > + > > #endif /* _TRACE_XFS_H */ > > > > #undef TRACE_INCLUDE_PATH > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From cmaiolino@redhat.com Tue Jun 28 03:57:40 2016 Return-Path: <cmaiolino@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id A418C7CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 03:57:40 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0D878AC001 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 01:57:36 -0700 (PDT) X-ASG-Debug-ID: 1467104250-04cb6c063c2252f0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 6hcOHg9m5lEtZvGU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 01:57:31 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6204A7F6A2; Tue, 28 Jun 2016 08:57:30 +0000 (UTC) Received: from redhat.com (unused [10.10.51.63] (may be forged)) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5S8vQX1012015 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Tue, 28 Jun 2016 04:57:29 -0400 Date: Tue, 28 Jun 2016 10:57:26 +0200 From: Carlos Maiolino <cmaiolino@redhat.com> To: Eric Sandeen <sandeen@sandeen.net> Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Message-ID: <20160628085726.GA4397@redhat.com> X-ASG-Orig-Subj: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Mail-Followup-To: Eric Sandeen <sandeen@sandeen.net>, xfs@oss.sgi.com References: <13dd3974-956d-c3af-86ed-f6ce5cc1b996@redhat.com> <20160627094855.GC29774@redhat.com> <5c408cf1-e9fa-8bee-106e-93e553fc98a7@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <5c408cf1-e9fa-8bee-106e-93e553fc98a7@sandeen.net> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 28 Jun 2016 08:57:30 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467104251 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2496 X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at sgi.com On Mon, Jun 27, 2016 at 10:34:39AM -0500, Eric Sandeen wrote: > > > On 6/27/16 4:48 AM, Carlos Maiolino wrote: > > On Fri, Jun 24, 2016 at 04:24:58PM -0500, Eric Sandeen wrote: > >> kernel commit 5ef828c4 > >> xfs: avoid false quotacheck after unclean shutdown > >> > >> made xfs_sb_from_disk() also call xfs_sb_quota_from_disk > >> by default. > >> > >> However, when this was merged to libxfs, existing separate > >> calls to libxfs_sb_quota_from_disk remained, and calling it > >> twice in a row on a V4 superblock leads to issues, because: > >> > >> > >> if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { > >> ... > >> sbp->sb_pquotino = sbp->sb_gquotino; > >> sbp->sb_gquotino = NULLFSINO; > >> > >> and after the second call, we have set both pquotino and gquotino > >> to NULLFSINO. > >> > >> Fix this by making it safe to call twice, and also remove the extra > >> calls to libxfs_sb_quota_from_disk. > >> > >> This is only spotted when running xfstests with "-m crc=0" because > >> the sb_from_disk change came about after V5 became default, and > >> the above behavior only exists on a V4 superblock. > >> > >> Reported-by: Eryu Guan <eguan@redhat.com> > >> Signed-off-by: Eric Sandeen <sandeen@redhat.com> > >> --- > >> > >> > >> diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c > >> index 45db6ae..44f3e3e 100644 > >> --- a/libxfs/xfs_sb.c > >> +++ b/libxfs/xfs_sb.c > >> @@ -316,13 +316,16 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) > >> XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; > >> sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); > >> > >> - if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { > >> + if (sbp->sb_qflags & XFS_PQUOTA_ACCT && > >> + sbp->sb_gquotino != NULLFSINO) { > > > > Although I agree with this check, shouldn't we report some sort of error when it > > happens? Once, it's not supposed to happen, and, might be a sign of corruption? > > I dunno, it would also happen if it gets called twice, which is intentionally > made harmless by this change. We don't warn on free(NULL) for example... > Well, I don't 100% agree with not having a warning here, but it doesn't make the patch less valuable. Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> > I don't think it needs a warning. > > -Eric > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From bfoster@redhat.com Tue Jun 28 07:31:54 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A97AD7CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 07:31:54 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5CFA28F8035 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:31:51 -0700 (PDT) X-ASG-Debug-ID: 1467117109-04bdf074b4185910001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id xlx2F7dyRIrDE6M5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:31:49 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2A4007F6A2; Tue, 28 Jun 2016 12:31:49 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5SCVmqt032337; Tue, 28 Jun 2016 08:31:48 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 2FF721200E8; Tue, 28 Jun 2016 08:31:48 -0400 (EDT) Date: Tue, 28 Jun 2016 08:31:48 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion Message-ID: <20160628123146.GA4212@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 012/119] xfs: during btree split, save new block key & ptr for future insertion References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612634887.12839.6210102273046676244.stgit@birch.djwong.org> <20160621130043.GA62352@bfoster.bfoster> <20160627223023.GD4921@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160627223023.GD4921@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 28 Jun 2016 12:31:49 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467117109 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11057 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 27, 2016 at 03:30:23PM -0700, Darrick J. Wong wrote: > On Tue, Jun 21, 2016 at 09:00:45AM -0400, Brian Foster wrote: > > On Thu, Jun 16, 2016 at 06:19:08PM -0700, Darrick J. Wong wrote: > > > When a btree block has to be split, we pass the new block's ptr from > > > xfs_btree_split() back to xfs_btree_insert() via a pointer parameter; > > > however, we pass the block's key through the cursor's record. It is a > > > little weird to "initialize" a record from a key since the non-key > > > attributes will have garbage values. > > > > > > When we go to add support for interval queries, we have to be able to > > > pass the lowest and highest keys accessible via a pointer. There's no > > > clean way to pass this back through the cursor's record field. > > > Therefore, pass the key directly back to xfs_btree_insert() the same > > > way that we pass the btree_ptr. > > > > > > As a bonus, we no longer need init_rec_from_key and can drop it from the > > > codebase. > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > --- > > > fs/xfs/libxfs/xfs_alloc_btree.c | 12 ---------- > > > fs/xfs/libxfs/xfs_bmap_btree.c | 12 ---------- > > > fs/xfs/libxfs/xfs_btree.c | 44 +++++++++++++++++++------------------- > > > fs/xfs/libxfs/xfs_btree.h | 2 -- > > > fs/xfs/libxfs/xfs_ialloc_btree.c | 10 --------- > > > 5 files changed, 22 insertions(+), 58 deletions(-) > > > > > > > > ... > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > > index 046fbcf..a096539 100644 > > > --- a/fs/xfs/libxfs/xfs_btree.c > > > +++ b/fs/xfs/libxfs/xfs_btree.c > > ... > > > @@ -2929,16 +2927,16 @@ xfs_btree_insrec( > > > struct xfs_btree_cur *cur, /* btree cursor */ > > > int level, /* level to insert record at */ > > > union xfs_btree_ptr *ptrp, /* i/o: block number inserted */ > > > - union xfs_btree_rec *recp, /* i/o: record data inserted */ > > > + union xfs_btree_key *key, /* i/o: block key for ptrp */ > > > struct xfs_btree_cur **curp, /* output: new cursor replacing cur */ > > > int *stat) /* success/failure */ > > > { > > > struct xfs_btree_block *block; /* btree block */ > > > struct xfs_buf *bp; /* buffer for block */ > > > - union xfs_btree_key key; /* btree key */ > > > union xfs_btree_ptr nptr; /* new block ptr */ > > > struct xfs_btree_cur *ncur; /* new btree cursor */ > > > - union xfs_btree_rec nrec; /* new record count */ > > > + union xfs_btree_key nkey; /* new block key */ > > > + union xfs_btree_rec rec; /* record to insert */ > > > int optr; /* old key/record index */ > > > int ptr; /* key/record index */ > > > int numrecs;/* number of records */ > > > @@ -2947,8 +2945,14 @@ xfs_btree_insrec( > > > int i; > > > #endif > > > > > > + /* Make a key out of the record data to be inserted, and save it. */ > > > + if (level == 0) { > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > + cur->bc_ops->init_key_from_rec(key, &rec); > > > + } > > > > The level == 0 check looks a bit hacky to me. IOW, I think it's cleaner > > that the key is initialized once in the caller rather than check for a > > particular iteration down in xfs_btree_insrec(). That said, > > xfs_btree_insrec() still needs rec initialized in the level == 0 case. > > > > I wonder if we could create an inline xfs_btree_init_key_from_cur() > > helper to combine the above calls, invoke it once in xfs_btree_insert(), > > then push down the ->init_rec_from_cur() calls to the contexts further > > down in this function where rec is actually required. There are only two > > and one of them is DEBUG code. Thoughts? > > How about I make btree_insert set both &key and &rec at the start and > pass them both into btree_insrec? That would eliminate the hacky check > above and fix the dummy tracing hook too, in case it ever does anything. > That seems fine to me. Brian > > > > > + > > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > > - XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, recp); > > > + XFS_BTREE_TRACE_ARGIPR(cur, level, *ptrp, &rec); > > > > > > > So these look like unimplemented dummy tracing hooks. It sounds like > > previously rec could have a junk value after a btree split, but now it > > looks like rec is junk for every non-zero level. Kind of annoying, I > > wonder if we can just kill these.. :/ > > <shrug> I have no opinion either way. :) > > --D > > > > Brian > > > > > ncur = NULL; > > > > > > @@ -2973,9 +2977,6 @@ xfs_btree_insrec( > > > return 0; > > > } > > > > > > - /* Make a key out of the record data to be inserted, and save it. */ > > > - cur->bc_ops->init_key_from_rec(&key, recp); > > > - > > > optr = ptr; > > > > > > XFS_BTREE_STATS_INC(cur, insrec); > > > @@ -2992,10 +2993,10 @@ xfs_btree_insrec( > > > /* Check that the new entry is being inserted in the right place. */ > > > if (ptr <= numrecs) { > > > if (level == 0) { > > > - ASSERT(cur->bc_ops->recs_inorder(cur, recp, > > > + ASSERT(cur->bc_ops->recs_inorder(cur, &rec, > > > xfs_btree_rec_addr(cur, ptr, block))); > > > } else { > > > - ASSERT(cur->bc_ops->keys_inorder(cur, &key, > > > + ASSERT(cur->bc_ops->keys_inorder(cur, key, > > > xfs_btree_key_addr(cur, ptr, block))); > > > } > > > } > > > @@ -3008,7 +3009,7 @@ xfs_btree_insrec( > > > xfs_btree_set_ptr_null(cur, &nptr); > > > if (numrecs == cur->bc_ops->get_maxrecs(cur, level)) { > > > error = xfs_btree_make_block_unfull(cur, level, numrecs, > > > - &optr, &ptr, &nptr, &ncur, &nrec, stat); > > > + &optr, &ptr, &nptr, &ncur, &nkey, stat); > > > if (error || *stat == 0) > > > goto error0; > > > } > > > @@ -3058,7 +3059,7 @@ xfs_btree_insrec( > > > #endif > > > > > > /* Now put the new data in, bump numrecs and log it. */ > > > - xfs_btree_copy_keys(cur, kp, &key, 1); > > > + xfs_btree_copy_keys(cur, kp, key, 1); > > > xfs_btree_copy_ptrs(cur, pp, ptrp, 1); > > > numrecs++; > > > xfs_btree_set_numrecs(block, numrecs); > > > @@ -3079,7 +3080,7 @@ xfs_btree_insrec( > > > xfs_btree_shift_recs(cur, rp, 1, numrecs - ptr + 1); > > > > > > /* Now put the new data in, bump numrecs and log it. */ > > > - xfs_btree_copy_recs(cur, rp, recp, 1); > > > + xfs_btree_copy_recs(cur, rp, &rec, 1); > > > xfs_btree_set_numrecs(block, ++numrecs); > > > xfs_btree_log_recs(cur, bp, ptr, numrecs); > > > #ifdef DEBUG > > > @@ -3095,7 +3096,7 @@ xfs_btree_insrec( > > > > > > /* If we inserted at the start of a block, update the parents' keys. */ > > > if (optr == 1) { > > > - error = xfs_btree_updkey(cur, &key, level + 1); > > > + error = xfs_btree_updkey(cur, key, level + 1); > > > if (error) > > > goto error0; > > > } > > > @@ -3105,7 +3106,7 @@ xfs_btree_insrec( > > > * we are at the far right edge of the tree, update it. > > > */ > > > if (xfs_btree_is_lastrec(cur, block, level)) { > > > - cur->bc_ops->update_lastrec(cur, block, recp, > > > + cur->bc_ops->update_lastrec(cur, block, &rec, > > > ptr, LASTREC_INSREC); > > > } > > > > > > @@ -3115,7 +3116,7 @@ xfs_btree_insrec( > > > */ > > > *ptrp = nptr; > > > if (!xfs_btree_ptr_is_null(cur, &nptr)) { > > > - *recp = nrec; > > > + *key = nkey; > > > *curp = ncur; > > > } > > > > > > @@ -3146,14 +3147,13 @@ xfs_btree_insert( > > > union xfs_btree_ptr nptr; /* new block number (split result) */ > > > struct xfs_btree_cur *ncur; /* new cursor (split result) */ > > > struct xfs_btree_cur *pcur; /* previous level's cursor */ > > > - union xfs_btree_rec rec; /* record to insert */ > > > + union xfs_btree_key key; /* key of block to insert */ > > > > > > level = 0; > > > ncur = NULL; > > > pcur = cur; > > > > > > xfs_btree_set_ptr_null(cur, &nptr); > > > - cur->bc_ops->init_rec_from_cur(cur, &rec); > > > > > > /* > > > * Loop going up the tree, starting at the leaf level. > > > @@ -3165,7 +3165,7 @@ xfs_btree_insert( > > > * Insert nrec/nptr into this level of the tree. > > > * Note if we fail, nptr will be null. > > > */ > > > - error = xfs_btree_insrec(pcur, level, &nptr, &rec, &ncur, &i); > > > + error = xfs_btree_insrec(pcur, level, &nptr, &key, &ncur, &i); > > > if (error) { > > > if (pcur != cur) > > > xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); > > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > > index b955e5d..b99c018 100644 > > > --- a/fs/xfs/libxfs/xfs_btree.h > > > +++ b/fs/xfs/libxfs/xfs_btree.h > > > @@ -158,8 +158,6 @@ struct xfs_btree_ops { > > > /* init values of btree structures */ > > > void (*init_key_from_rec)(union xfs_btree_key *key, > > > union xfs_btree_rec *rec); > > > - void (*init_rec_from_key)(union xfs_btree_key *key, > > > - union xfs_btree_rec *rec); > > > void (*init_rec_from_cur)(struct xfs_btree_cur *cur, > > > union xfs_btree_rec *rec); > > > void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, > > > diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c > > > index 89c21d7..88da2ad 100644 > > > --- a/fs/xfs/libxfs/xfs_ialloc_btree.c > > > +++ b/fs/xfs/libxfs/xfs_ialloc_btree.c > > > @@ -146,14 +146,6 @@ xfs_inobt_init_key_from_rec( > > > } > > > > > > STATIC void > > > -xfs_inobt_init_rec_from_key( > > > - union xfs_btree_key *key, > > > - union xfs_btree_rec *rec) > > > -{ > > > - rec->inobt.ir_startino = key->inobt.ir_startino; > > > -} > > > - > > > -STATIC void > > > xfs_inobt_init_rec_from_cur( > > > struct xfs_btree_cur *cur, > > > union xfs_btree_rec *rec) > > > @@ -314,7 +306,6 @@ static const struct xfs_btree_ops xfs_inobt_ops = { > > > .get_minrecs = xfs_inobt_get_minrecs, > > > .get_maxrecs = xfs_inobt_get_maxrecs, > > > .init_key_from_rec = xfs_inobt_init_key_from_rec, > > > - .init_rec_from_key = xfs_inobt_init_rec_from_key, > > > .init_rec_from_cur = xfs_inobt_init_rec_from_cur, > > > .init_ptr_from_cur = xfs_inobt_init_ptr_from_cur, > > > .key_diff = xfs_inobt_key_diff, > > > @@ -336,7 +327,6 @@ static const struct xfs_btree_ops xfs_finobt_ops = { > > > .get_minrecs = xfs_inobt_get_minrecs, > > > .get_maxrecs = xfs_inobt_get_maxrecs, > > > .init_key_from_rec = xfs_inobt_init_key_from_rec, > > > - .init_rec_from_key = xfs_inobt_init_rec_from_key, > > > .init_rec_from_cur = xfs_inobt_init_rec_from_cur, > > > .init_ptr_from_cur = xfs_finobt_init_ptr_from_cur, > > > .key_diff = xfs_inobt_key_diff, > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Tue Jun 28 07:32:10 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id EA5497CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 07:32:10 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id BC08B304032 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:07 -0700 (PDT) X-ASG-Debug-ID: 1467117125-04cbb027352ed460001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id MnuLw020ICNQB2hq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:05 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1BC9D63146; Tue, 28 Jun 2016 12:32:05 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5SCW4NU003031; Tue, 28 Jun 2016 08:32:04 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 1D6DB1200E8; Tue, 28 Jun 2016 08:32:04 -0400 (EDT) Date: Tue, 28 Jun 2016 08:32:04 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys Message-ID: <20160628123203.GB4212@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612635526.12839.13865365567940815077.stgit@birch.djwong.org> <20160622151706.GB5423@bfoster.bfoster> <20160628032621.GB4917@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160628032621.GB4917@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 28 Jun 2016 12:32:05 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467117125 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 15853 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 27, 2016 at 08:26:21PM -0700, Darrick J. Wong wrote: > On Wed, Jun 22, 2016 at 11:17:06AM -0400, Brian Foster wrote: > > On Thu, Jun 16, 2016 at 06:19:15PM -0700, Darrick J. Wong wrote: > > > On a filesystem with both reflink and reverse mapping enabled, it's > > > possible to have multiple rmap records referring to the same blocks on > > > disk. When overlapping intervals are possible, querying a classic > > > btree to find all records intersecting a given interval is inefficient > > > because we cannot use the left side of the search interval to filter > > > out non-matching records the same way that we can use the existing > > > btree key to filter out records coming after the right side of the > > > search interval. This will become important once we want to use the > > > rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl. > > > > > > (For the non-overlapping case, we can perform such queries trivially > > > by starting at the left side of the interval and walking the tree > > > until we pass the right side.) > > > > > > Therefore, extend the btree code to come closer to supporting > > > intervals as a first-class record attribute. This involves widening > > > the btree node's key space to store both the lowest key reachable via > > > the node pointer (as the btree does now) and the highest key reachable > > > via the same pointer and teaching the btree modifying functions to > > > keep the highest-key records up to date. > > > > > > This behavior can be turned on via a new btree ops flag so that btrees > > > that cannot store overlapping intervals don't pay the overhead costs > > > in terms of extra code and disk format changes. > > > > > > v2: When we're deleting a record in a btree that supports overlapped > > > interval records and the deletion results in two btree blocks being > > > joined, we defer updating the high/low keys until after all possible > > > joining (at higher levels in the tree) have finished. At this point, > > > the btree pointers at all levels have been updated to remove the empty > > > blocks and we can update the low and high keys. > > > > > > When we're doing this, we must be careful to update the keys of all > > > node pointers up to the root instead of stopping at the first set of > > > keys that don't need updating. This is because it's possible for a > > > single deletion to cause joining of multiple levels of tree, and so > > > we need to update everything going back to the root. > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > --- > > > > I think I get the gist of this and it mostly looks Ok to me. A few > > questions and minor comments... > > Ok. > > > > fs/xfs/libxfs/xfs_btree.c | 379 +++++++++++++++++++++++++++++++++++++++++---- > > > fs/xfs/libxfs/xfs_btree.h | 16 ++ > > > fs/xfs/xfs_trace.h | 36 ++++ > > > 3 files changed, 395 insertions(+), 36 deletions(-) > > > > > > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > > index a096539..afcafd6 100644 > > > --- a/fs/xfs/libxfs/xfs_btree.c > > > +++ b/fs/xfs/libxfs/xfs_btree.c ... > > > @@ -2149,7 +2392,9 @@ xfs_btree_lshift( > > > rkp = &key; > > > } > > > > > > - /* Update the parent key values of right. */ > > > + /* Update the parent key values of left and right. */ > > > + xfs_btree_sibling_updkeys(cur, level, XFS_BB_LEFTSIB, left, lbp); > > > + xfs_btree_updkeys(cur, level); > > > error = xfs_btree_updkey(cur, rkp, level + 1); > > > if (error) > > > goto error0; > > > @@ -2321,6 +2566,9 @@ xfs_btree_rshift( > > > if (error) > > > goto error1; > > > > > > + /* Update left and right parent pointers */ > > > + xfs_btree_updkeys(cur, level); > > > + xfs_btree_updkeys(tcur, level); > > > > In this case, we grab the last record of the block, increment from there > > and update using the cursor. This is much more straightforward, imo. > > Could we use this approach in the left shift case as well? > > Yes, I think so. I might have started refactoring btree_sibling_updkeys > out of existence and got distracted, since there isn't anything that uses > the RIGHTSIB ptr value. > Ok, I think that would be much cleaner. > > > error = xfs_btree_updkey(tcur, rkp, level + 1); > > > if (error) > > > goto error1; > > > @@ -2356,7 +2604,7 @@ __xfs_btree_split( > > > struct xfs_btree_cur *cur, > > > int level, > > > union xfs_btree_ptr *ptrp, > > > - union xfs_btree_key *key, > > > + struct xfs_btree_double_key *key, > > > struct xfs_btree_cur **curp, > > > int *stat) /* success/failure */ > > > { > > > @@ -2452,9 +2700,6 @@ __xfs_btree_split( > > > > > > xfs_btree_log_keys(cur, rbp, 1, rrecs); > > > xfs_btree_log_ptrs(cur, rbp, 1, rrecs); > > > - > > > - /* Grab the keys to the entries moved to the right block */ > > > - xfs_btree_copy_keys(cur, key, rkp, 1); > > > } else { > > > /* It's a leaf. Move records. */ > > > union xfs_btree_rec *lrp; /* left record pointer */ > > > @@ -2465,12 +2710,8 @@ __xfs_btree_split( > > > > > > xfs_btree_copy_recs(cur, rrp, lrp, rrecs); > > > xfs_btree_log_recs(cur, rbp, 1, rrecs); > > > - > > > - cur->bc_ops->init_key_from_rec(key, > > > - xfs_btree_rec_addr(cur, 1, right)); > > > } > > > > > > - > > > /* > > > * Find the left block number by looking in the buffer. > > > * Adjust numrecs, sibling pointers. > > > @@ -2484,6 +2725,12 @@ __xfs_btree_split( > > > xfs_btree_set_numrecs(left, lrecs); > > > xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs); > > > > > > + /* Find the low & high keys for the new block. */ > > > + if (level > 0) > > > + xfs_btree_find_node_keys(cur, right, &key->low, &key->high); > > > + else > > > + xfs_btree_find_leaf_keys(cur, right, &key->low, &key->high); > > > + > > > > Why not push these into the above if/else where the previous key > > copy/init calls were removed from? > > We don't set bb_numrecs on the right block until the line above the new > hunk, and the btree_find_*_keys functions require numrecs to be set. > > The removed key copy/init calls only looked at keys[1]. > > That said, it's trivial to move the set_numrecs calls above the if statement. > Ok, thanks. No need to shuffle it around. I'd suggest a one-liner comment though so somebody doesn't blindly refactor this down the road. It also sounds like the find keys functions could use ASSERT() checks for a sane bb_numrecs. > > > xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS); > > > xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); > > > ... > > > @@ -3095,8 +3365,24 @@ xfs_btree_insrec( > > > xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); > > > > > > /* If we inserted at the start of a block, update the parents' keys. */ > > > > This comment is associated with the codeblock that has been pushed > > further down, no? > > Correct. I think that got mismerged somewhere along the way. > > > > + if (ncur && bp->b_bn != old_bn) { > > > + /* > > > + * We just inserted into a new tree block, which means that > > > + * the key for the block is in nkey, not the tree. > > > + */ > > > + if (level == 0) > > > + xfs_btree_find_leaf_keys(cur, block, &nkey.low, > > > + &nkey.high); > > > + else > > > + xfs_btree_find_node_keys(cur, block, &nkey.low, > > > + &nkey.high); > > > + } else { > > > + /* Updating the left block, do it the standard way. */ > > > + xfs_btree_updkeys(cur, level); > > > + } > > > + > > > > Not quite sure I follow the purpose of this hunk. Is this for the case > > where a btree split occurs, nkey is filled in for the new/right block > > and then (after nkey is filled in) the new record ends up being added to > > the new block? If so, what about the case where ncur is not created? > > (It looks like that's possible from the code, but I could easily be > > missing some context as to why that's not the case.) > > Yes, the first part of the if-else hunk is to fill out nkey when we've > split a btree block. Now that I look at it again, I think that whole > weird conditional could be replaced with the same xfs_btree_ptr_is_null() > check later on. I think it can also be combined with it. > Ok. > Commentage for now: > > /* > * If we just inserted a new tree block, we have to find the low > * and high keys for the new block and arrange to pass them back > * separately. If we're just updating a block we can use the > * regular tree update mechanism. > */ > Couldn't you just point out that nkey may not be coherent with the new block if the new record was inserted therein..? > > In any event, I think we could elaborate a bit in the comment on why > > this is necessary. I'd also move it above the top-level if/else. > > > > > if (optr == 1) { > > > - error = xfs_btree_updkey(cur, key, level + 1); > > > + error = xfs_btree_updkey(cur, &key->low, level + 1); > > > if (error) > > > goto error0; > > > } > > > @@ -3147,7 +3433,7 @@ xfs_btree_insert( > > > union xfs_btree_ptr nptr; /* new block number (split result) */ > > > struct xfs_btree_cur *ncur; /* new cursor (split result) */ > > > struct xfs_btree_cur *pcur; /* previous level's cursor */ > > > - union xfs_btree_key key; /* key of block to insert */ > > > + struct xfs_btree_double_key key; /* key of block to insert */ > > > > Probably should fix up the function param alignment here and the couple > > other or so places we make this change. > > I changed the name to xfs_btree_bigkey, which avoids the alignment problems. > Sounds good. Brian > --D > > > > > Brian > > > > > > > > level = 0; > > > ncur = NULL; > > > @@ -3552,6 +3838,7 @@ xfs_btree_delrec( > > > * If we deleted the leftmost entry in the block, update the > > > * key values above us in the tree. > > > */ > > > + xfs_btree_updkeys(cur, level); > > > if (ptr == 1) { > > > error = xfs_btree_updkey(cur, keyp, level + 1); > > > if (error) > > > @@ -3882,6 +4169,16 @@ xfs_btree_delrec( > > > if (level > 0) > > > cur->bc_ptrs[level]--; > > > > > > + /* > > > + * We combined blocks, so we have to update the parent keys if the > > > + * btree supports overlapped intervals. However, bc_ptrs[level + 1] > > > + * points to the old block so that the caller knows which record to > > > + * delete. Therefore, the caller must be savvy enough to call updkeys > > > + * for us if we return stat == 2. The other exit points from this > > > + * function don't require deletions further up the tree, so they can > > > + * call updkeys directly. > > > + */ > > > + > > > XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); > > > /* Return value means the next level up has something to do. */ > > > *stat = 2; > > > @@ -3907,6 +4204,7 @@ xfs_btree_delete( > > > int error; /* error return value */ > > > int level; > > > int i; > > > + bool joined = false; > > > > > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > > > > > @@ -3920,8 +4218,17 @@ xfs_btree_delete( > > > error = xfs_btree_delrec(cur, level, &i); > > > if (error) > > > goto error0; > > > + if (i == 2) > > > + joined = true; > > > } > > > > > > + /* > > > + * If we combined blocks as part of deleting the record, delrec won't > > > + * have updated the parent keys so we have to do that here. > > > + */ > > > + if (joined) > > > + xfs_btree_updkeys_force(cur, 0); > > > + > > > if (i == 0) { > > > for (level = 1; level < cur->bc_nlevels; level++) { > > > if (cur->bc_ptrs[level] == 0) { > > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > > index b99c018..a5ec6c7 100644 > > > --- a/fs/xfs/libxfs/xfs_btree.h > > > +++ b/fs/xfs/libxfs/xfs_btree.h > > > @@ -126,6 +126,9 @@ struct xfs_btree_ops { > > > size_t key_len; > > > size_t rec_len; > > > > > > + /* flags */ > > > + uint flags; > > > + > > > /* cursor operations */ > > > struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); > > > void (*update_cursor)(struct xfs_btree_cur *src, > > > @@ -162,11 +165,21 @@ struct xfs_btree_ops { > > > union xfs_btree_rec *rec); > > > void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, > > > union xfs_btree_ptr *ptr); > > > + void (*init_high_key_from_rec)(union xfs_btree_key *key, > > > + union xfs_btree_rec *rec); > > > > > > /* difference between key value and cursor value */ > > > __int64_t (*key_diff)(struct xfs_btree_cur *cur, > > > union xfs_btree_key *key); > > > > > > + /* > > > + * Difference between key2 and key1 -- positive if key2 > key1, > > > + * negative if key2 < key1, and zero if equal. > > > + */ > > > + __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur, > > > + union xfs_btree_key *key1, > > > + union xfs_btree_key *key2); > > > + > > > const struct xfs_buf_ops *buf_ops; > > > > > > #if defined(DEBUG) || defined(XFS_WARN) > > > @@ -182,6 +195,9 @@ struct xfs_btree_ops { > > > #endif > > > }; > > > > > > +/* btree ops flags */ > > > +#define XFS_BTREE_OPS_OVERLAPPING (1<<0) /* overlapping intervals */ > > > + > > > /* > > > * Reasons for the update_lastrec method to be called. > > > */ > > > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > > > index 68f27f7..ffea28c 100644 > > > --- a/fs/xfs/xfs_trace.h > > > +++ b/fs/xfs/xfs_trace.h > > > @@ -38,6 +38,7 @@ struct xlog_recover_item; > > > struct xfs_buf_log_format; > > > struct xfs_inode_log_format; > > > struct xfs_bmbt_irec; > > > +struct xfs_btree_cur; > > > > > > DECLARE_EVENT_CLASS(xfs_attr_list_class, > > > TP_PROTO(struct xfs_attr_list_context *ctx), > > > @@ -2183,6 +2184,41 @@ DEFINE_DISCARD_EVENT(xfs_discard_toosmall); > > > DEFINE_DISCARD_EVENT(xfs_discard_exclude); > > > DEFINE_DISCARD_EVENT(xfs_discard_busy); > > > > > > +/* btree cursor events */ > > > +DECLARE_EVENT_CLASS(xfs_btree_cur_class, > > > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), > > > + TP_ARGS(cur, level, bp), > > > + TP_STRUCT__entry( > > > + __field(dev_t, dev) > > > + __field(xfs_btnum_t, btnum) > > > + __field(int, level) > > > + __field(int, nlevels) > > > + __field(int, ptr) > > > + __field(xfs_daddr_t, daddr) > > > + ), > > > + TP_fast_assign( > > > + __entry->dev = cur->bc_mp->m_super->s_dev; > > > + __entry->btnum = cur->bc_btnum; > > > + __entry->level = level; > > > + __entry->nlevels = cur->bc_nlevels; > > > + __entry->ptr = cur->bc_ptrs[level]; > > > + __entry->daddr = bp->b_bn; > > > + ), > > > + TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx", > > > + MAJOR(__entry->dev), MINOR(__entry->dev), > > > + __entry->btnum, > > > + __entry->level, > > > + __entry->nlevels, > > > + __entry->ptr, > > > + (unsigned long long)__entry->daddr) > > > +) > > > + > > > +#define DEFINE_BTREE_CUR_EVENT(name) \ > > > +DEFINE_EVENT(xfs_btree_cur_class, name, \ > > > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > > > + TP_ARGS(cur, level, bp)) > > > +DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > > > + > > > #endif /* _TRACE_XFS_H */ > > > > > > #undef TRACE_INCLUDE_PATH > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Tue Jun 28 07:32:23 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 2024A7CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 07:32:23 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id E639B8F8033 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:22 -0700 (PDT) X-ASG-Debug-ID: 1467117140-04cbb027352ed510001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id qXoFgFSQHdXReP6m (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:20 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3F29964389; Tue, 28 Jun 2016 12:32:20 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5SCWJKj000325; Tue, 28 Jun 2016 08:32:19 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 3827C1200E8; Tue, 28 Jun 2016 08:32:19 -0400 (EDT) Date: Tue, 28 Jun 2016 08:32:19 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 014/119] xfs: introduce interval queries on btrees Message-ID: <20160628123218.GC4212@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 014/119] xfs: introduce interval queries on btrees References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612636170.12839.675596870201079078.stgit@birch.djwong.org> <20160622151800.GC5423@bfoster.bfoster> <20160627210746.GB4921@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160627210746.GB4921@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Tue, 28 Jun 2016 12:32:20 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467117140 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 16772 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 27, 2016 at 02:07:46PM -0700, Darrick J. Wong wrote: > On Wed, Jun 22, 2016 at 11:18:00AM -0400, Brian Foster wrote: > > On Thu, Jun 16, 2016 at 06:19:21PM -0700, Darrick J. Wong wrote: > > > Create a function to enable querying of btree records mapping to a > > > range of keys. This will be used in subsequent patches to allow > > > querying the reverse mapping btree to find the extents mapped to a > > > range of physical blocks, though the generic code can be used for > > > any range query. > > > > > > v2: add some shortcuts so that we can jump out of processing once > > > we know there won't be any more records to find. > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > --- > > > fs/xfs/libxfs/xfs_btree.c | 249 +++++++++++++++++++++++++++++++++++++++++++++ > > > fs/xfs/libxfs/xfs_btree.h | 22 +++- > > > fs/xfs/xfs_trace.h | 1 > > > 3 files changed, 267 insertions(+), 5 deletions(-) > > > > > > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > > index afcafd6..5f5cf23 100644 > > > --- a/fs/xfs/libxfs/xfs_btree.c > > > +++ b/fs/xfs/libxfs/xfs_btree.c > > > @@ -4509,3 +4509,252 @@ xfs_btree_calc_size( > > > } > > > return rval; > > > } > > > + > > > +/* Query a regular btree for all records overlapping a given interval. */ > > > > Can you elaborate on the search algorithm used? (More for reference > > against the overlapped query, as that one is more complex). > > Ok. Both query_range functions aim to return all records intersecting the > given range. > > For non-overlapped btrees, we start with a LE lookup of the low key and > return each record we find a the record with a key greater than the > high key. > > For overlapped btrees, we follow the procedure in the "Interval trees" > section of _Introduction to Algorithms_, which is 14.3 in the 2nd and > 3rd editions. The query algorithm is roughly as follows: > > For any leaf btree node, generate the low and high keys for the record. > If there's a range overlap with the query's low and high keys, pass the > record to the iterator function. > > For any internal btree node, compare the low and high keys for each pointer > against the query's low and high keys. If there's an overlap, follow the > pointer downwards in the tree. > > (I could render the figures in the book as ASCII art if anyone wants.) > Thanks. I meant more to update the comments above each function. :) No need to go as far as ASCII art I don't think (the external reference might be good though). I was really just looking for something that says "this function is supposed to do <whatever>" so somebody reading through it has a starting point of reference. > > > > > +STATIC int > > > +xfs_btree_simple_query_range( > > > + struct xfs_btree_cur *cur, > > > + union xfs_btree_irec *low_rec, > > > + union xfs_btree_irec *high_rec, > > > + xfs_btree_query_range_fn fn, > > > + void *priv) > > > +{ > > > + union xfs_btree_rec *recp; > > > + union xfs_btree_rec rec; > > > + union xfs_btree_key low_key; > > > + union xfs_btree_key high_key; > > > + union xfs_btree_key rec_key; > > > + __int64_t diff; > > > + int stat; > > > + bool firstrec = true; > > > + int error; > > > + > > > + ASSERT(cur->bc_ops->init_high_key_from_rec); > > > + > > > + /* Find the keys of both ends of the interval. */ > > > + cur->bc_rec = *high_rec; > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > > > + > > > + cur->bc_rec = *low_rec; > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > > > + > > > + /* Find the leftmost record. */ > > > + stat = 0; > > > + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat); > > > + if (error) > > > + goto out; > > > + > > > + while (stat) { > > > + /* Find the record. */ > > > + error = xfs_btree_get_rec(cur, &recp, &stat); > > > + if (error || !stat) > > > + break; > > > + > > > + /* Can we tell if this record is too low? */ > > > + if (firstrec) { > > > + cur->bc_rec = *low_rec; > > > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > > > + diff = cur->bc_ops->key_diff(cur, &rec_key); > > > + if (diff < 0) > > > + goto advloop; > > > + } > > > + firstrec = false; > > > > This could move up into the if block. > > Ok. > > > > + > > > + /* Have we gone past the end? */ > > > + cur->bc_rec = *high_rec; > > > + cur->bc_ops->init_key_from_rec(&rec_key, recp); > > > > I'd move this up to immediately after the xfs_btree_get_rec() call and > > eliminate the duplicate in the 'if (firstrec)' block above. > > Ok. That key ought to be named rec_hkey too. > > > > + diff = cur->bc_ops->key_diff(cur, &rec_key); > > > + if (diff > 0) > > > + break; > > > + > > > + /* Callback */ > > > + error = fn(cur, recp, priv); > > > + if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) > > > + break; > > > + > > > +advloop: > > > + /* Move on to the next record. */ > > > + error = xfs_btree_increment(cur, 0, &stat); > > > + if (error) > > > + break; > > > + } > > > + > > > +out: > > > + return error; > > > +} > > > + > > > +/* > > > + * Query an overlapped interval btree for all records overlapping a given > > > + * interval. > > > + */ > > > > Same comment here, can you elaborate on the search algorithm? Also, I > > think an example or generic description of the rules around what records > > this query returns (e.g., low_rec/high_rec vs. record low/high keys) > > would be useful, particularly since I, at least, don't have much context > > on the rmap+reflink scenarios quite yet. > > Let's say you have a bunch of (overlapped) rmap records: > > 1: +- file A startblock B offset C length D -----------+ > 2: +- file E startblock F offset G length H --------------+ > 3: +- file I startblock F offset J length K --+ > 4: +- file L... --+ > > Now say we want to map block (B+D) into file A at offset (C+D). Ideally, we'd > simply increment the length of record 1. But how do we find that record that > ends at (B+D-1)? A LE lookup of (B+D-1) would return record 3 because the > keys are ordered first by startblock. An interval query would return records > 1 and 2 because they both overlap (B+D-1), and from that we can pick out > record 1 as the appropriate left neighbor. > Great, thanks.. can you include this content in the comment above the function as well? Brian > In the non-overlapped case you can do a LE lookup and decrement the cursor > because a record's interval must end before the next record. > > > > +STATIC int > > > +xfs_btree_overlapped_query_range( > > > + struct xfs_btree_cur *cur, > > > + union xfs_btree_irec *low_rec, > > > + union xfs_btree_irec *high_rec, > > > + xfs_btree_query_range_fn fn, > > > + void *priv) > > > +{ > > > + union xfs_btree_ptr ptr; > > > + union xfs_btree_ptr *pp; > > > + union xfs_btree_key rec_key; > > > + union xfs_btree_key low_key; > > > + union xfs_btree_key high_key; > > > + union xfs_btree_key *lkp; > > > + union xfs_btree_key *hkp; > > > + union xfs_btree_rec rec; > > > + union xfs_btree_rec *recp; > > > + struct xfs_btree_block *block; > > > + __int64_t ldiff; > > > + __int64_t hdiff; > > > + int level; > > > + struct xfs_buf *bp; > > > + int i; > > > + int error; > > > + > > > + /* Find the keys of both ends of the interval. */ > > > + cur->bc_rec = *high_rec; > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > > > + > > > + cur->bc_rec = *low_rec; > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > > > + > > > + /* Load the root of the btree. */ > > > + level = cur->bc_nlevels - 1; > > > + cur->bc_ops->init_ptr_from_cur(cur, &ptr); > > > + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); > > > + if (error) > > > + return error; > > > + xfs_btree_get_block(cur, level, &bp); > > > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > > > +#ifdef DEBUG > > > + error = xfs_btree_check_block(cur, block, level, bp); > > > + if (error) > > > + goto out; > > > +#endif > > > + cur->bc_ptrs[level] = 1; > > > + > > > + while (level < cur->bc_nlevels) { > > > + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); > > > + > > > + if (level == 0) { > > > + /* End of leaf, pop back towards the root. */ > > > + if (cur->bc_ptrs[level] > > > > + be16_to_cpu(block->bb_numrecs)) { > > > +leaf_pop_up: > > > + if (level < cur->bc_nlevels - 1) > > > + cur->bc_ptrs[level + 1]++; > > > + level++; > > > + continue; > > > + } > > > + > > > + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); > > > + > > > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > > > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, > > > + &rec_key); > > > + > > > + cur->bc_ops->init_key_from_rec(&rec_key, recp); > > > + hdiff = cur->bc_ops->diff_two_keys(cur, &rec_key, > > > + &high_key); > > > + > > > > This looked a little funny to me because I expected diff_two_keys() to > > basically be param1 - param2. Looking ahead at the rmapbt code, it is in > > fact the other way around. I'm not sure we have precedent for either > > way, tbh. I still have to stare at this some more, but I wonder if a > > "does record overlap" helper (with comments) would help clean this up a > > bit. > > You're correct this is exactly the opposite of the compare functions in > the C library and the rest of the kernel. I'll fix that up. > > > > + /* If the record matches, callback */ > > > + if (ldiff >= 0 && hdiff >= 0) { > > Ok, I'll make it a little clearer what we're testing here: > > /* > * If (record's high key >= query's low key) and > * (query's high key >= record's low key), then > * this record overlaps the query range, so callback. > */ > > > > > + error = fn(cur, recp, priv); > > > + if (error < 0 || > > > + error == XFS_BTREE_QUERY_RANGE_ABORT) > > > + break; > > > + } else if (hdiff < 0) { > > > + /* Record is larger than high key; pop. */ > > > + goto leaf_pop_up; > > > + } > > > + cur->bc_ptrs[level]++; > > > + continue; > > > + } > > > + > > > + /* End of node, pop back towards the root. */ > > > + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { > > > +node_pop_up: > > > + if (level < cur->bc_nlevels - 1) > > > + cur->bc_ptrs[level + 1]++; > > > + level++; > > > + continue; > > > > Looks like same code as leaf_pop_up. I wonder if we can bury this at the > > end of the loop with a common label. > > Yep. > > > > + } > > > + > > > + lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); > > > + hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); > > > + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); > > > + > > > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, hkp); > > > + hdiff = cur->bc_ops->diff_two_keys(cur, lkp, &high_key); > > > + > > > + /* If the key matches, drill another level deeper. */ > > > + if (ldiff >= 0 && hdiff >= 0) { > > > + level--; > > > + error = xfs_btree_lookup_get_block(cur, level, pp, > > > + &block); > > > + if (error) > > > + goto out; > > > + xfs_btree_get_block(cur, level, &bp); > > > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > > > +#ifdef DEBUG > > > + error = xfs_btree_check_block(cur, block, level, bp); > > > + if (error) > > > + goto out; > > > +#endif > > > + cur->bc_ptrs[level] = 1; > > > + continue; > > > + } else if (hdiff < 0) { > > > + /* The low key is larger than the upper range; pop. */ > > > + goto node_pop_up; > > > + } > > > + cur->bc_ptrs[level]++; > > > + } > > > + > > > +out: > > > + /* > > > + * If we don't end this function with the cursor pointing at a record > > > + * block, a subsequent non-error cursor deletion will not release > > > + * node-level buffers, causing a buffer leak. This is quite possible > > > + * with a zero-results range query, so release the buffers if we > > > + * failed to return any results. > > > + */ > > > + if (cur->bc_bufs[0] == NULL) { > > > + for (i = 0; i < cur->bc_nlevels; i++) { > > > + if (cur->bc_bufs[i]) { > > > + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); > > > + cur->bc_bufs[i] = NULL; > > > + cur->bc_ptrs[i] = 0; > > > + cur->bc_ra[i] = 0; > > > + } > > > + } > > > + } > > > + > > > + return error; > > > +} > > > + > > > +/* > > > + * Query a btree for all records overlapping a given interval of keys. The > > > + * supplied function will be called with each record found; return one of the > > > + * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error > > > + * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a > > > + * negative error code. > > > + */ > > > +int > > > +xfs_btree_query_range( > > > + struct xfs_btree_cur *cur, > > > + union xfs_btree_irec *low_rec, > > > + union xfs_btree_irec *high_rec, > > > + xfs_btree_query_range_fn fn, > > > + void *priv) > > > +{ > > > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > > > + return xfs_btree_simple_query_range(cur, low_rec, > > > + high_rec, fn, priv); > > > + return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, > > > + fn, priv); > > > +} > > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > > index a5ec6c7..898fee5 100644 > > > --- a/fs/xfs/libxfs/xfs_btree.h > > > +++ b/fs/xfs/libxfs/xfs_btree.h > > > @@ -206,6 +206,12 @@ struct xfs_btree_ops { > > > #define LASTREC_DELREC 2 > > > > > > > > > +union xfs_btree_irec { > > > + xfs_alloc_rec_incore_t a; > > > + xfs_bmbt_irec_t b; > > > + xfs_inobt_rec_incore_t i; > > > +}; > > > + > > > > We might as well kill off the typedef usage here. > > Ok. Thx for the review! > > --D > > > > > Brian > > > > > /* > > > * Btree cursor structure. > > > * This collects all information needed by the btree code in one place. > > > @@ -216,11 +222,7 @@ typedef struct xfs_btree_cur > > > struct xfs_mount *bc_mp; /* file system mount struct */ > > > const struct xfs_btree_ops *bc_ops; > > > uint bc_flags; /* btree features - below */ > > > - union { > > > - xfs_alloc_rec_incore_t a; > > > - xfs_bmbt_irec_t b; > > > - xfs_inobt_rec_incore_t i; > > > - } bc_rec; /* current insert/search record value */ > > > + union xfs_btree_irec bc_rec; /* current insert/search record value */ > > > struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ > > > int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ > > > __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ > > > @@ -494,4 +496,14 @@ xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > > > uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, > > > unsigned long len); > > > > > > +/* return codes */ > > > +#define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */ > > > +#define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */ > > > +typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur, > > > + union xfs_btree_rec *rec, void *priv); > > > + > > > +int xfs_btree_query_range(struct xfs_btree_cur *cur, > > > + union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, > > > + xfs_btree_query_range_fn fn, void *priv); > > > + > > > #endif /* __XFS_BTREE_H__ */ > > > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > > > index ffea28c..f0ac9c9 100644 > > > --- a/fs/xfs/xfs_trace.h > > > +++ b/fs/xfs/xfs_trace.h > > > @@ -2218,6 +2218,7 @@ DEFINE_EVENT(xfs_btree_cur_class, name, \ > > > TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > > > TP_ARGS(cur, level, bp)) > > > DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > > > +DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); > > > > > > #endif /* _TRACE_XFS_H */ > > > > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Tue Jun 28 07:32:40 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8AF0F7CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 07:32:40 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 12C80AC002 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:37 -0700 (PDT) X-ASG-Debug-ID: 1467117154-04cbb027362ed580001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id B2XZGmtyEuaB0VoA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:34 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D428E7F6B1; Tue, 28 Jun 2016 12:32:33 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5SCWXKt016398; Tue, 28 Jun 2016 08:32:33 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id EDC8F1200E8; Tue, 28 Jun 2016 08:32:32 -0400 (EDT) Date: Tue, 28 Jun 2016 08:32:32 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 016/119] xfs: move deferred operations into a separate file Message-ID: <20160628123232.GD4212@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 016/119] xfs: move deferred operations into a separate file References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612637438.12839.12318902006860455847.stgit@birch.djwong.org> <20160627131452.GA23076@bfoster.bfoster> <20160627191401.GA4921@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160627191401.GA4921@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Tue, 28 Jun 2016 12:32:33 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467117154 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 21834 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 27, 2016 at 12:14:01PM -0700, Darrick J. Wong wrote: > On Mon, Jun 27, 2016 at 09:14:54AM -0400, Brian Foster wrote: > > On Thu, Jun 16, 2016 at 06:19:34PM -0700, Darrick J. Wong wrote: > > > All the code around struct xfs_bmap_free basically implements a > > > deferred operation framework through which we can roll transactions > > > (to unlock buffers and avoid violating lock order rules) while > > > managing all the necessary log redo items. Previously we only used > > > this code to free extents after some sort of mapping operation, but > > > with the advent of rmap and reflink, we suddenly need to do more than > > > that. > > > > > > With that in mind, xfs_bmap_free really becomes a deferred ops control > > > structure. Rename the structure and move the deferred ops into their > > > own file to avoid further bloating of the bmap code. > > > > > > v2: actually sort the work items by AG to avoid deadlocks > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > --- > > > > So if I'm following this correctly, we 1.) abstract the bmap freeing > > infrastructure into a generic mechanism and 2.) enhance it a bit to > > provide things like partial intent completion, etc. > > [Back from vacation] > > Yup. The partial intent completion code is for use by the refcount adjust > function because in the worst case an adjustment of N blocks could require > N record updates. > Ok, technically those bits could be punted off to the reflink series. > > If so and for future > > reference, this would probably be easier to review if the abstraction > > and enhancement were done separately. It's probably not worth that at > > this point, however... > > It wouldn't be difficult to separate them; the partial intent completion > are the two code blocks below that handle the -EAGAIN case. > That's kind of what I figured, since otherwise most of the rest of the code maps to the xfs_bmap_*() stuff. > (On the other hand it's so little code that I figured I might as well > just do the whole file all at once.) > It's more a matter of simplifying review when a change is explicitly refactoring vs. having to read through and identify where the enhancements actually are. It leaves a cleaner git history and tends to simplify backporting as well, fwiw. That said, I don't mind leaving this one as is at this point. > > > fs/xfs/Makefile | 2 > > > fs/xfs/libxfs/xfs_defer.c | 471 +++++++++++++++++++++++++++++++++++++++++++++ > > > fs/xfs/libxfs/xfs_defer.h | 96 +++++++++ > > > fs/xfs/xfs_defer_item.c | 36 +++ > > > fs/xfs/xfs_super.c | 2 > > > 5 files changed, 607 insertions(+) > > > create mode 100644 fs/xfs/libxfs/xfs_defer.c > > > create mode 100644 fs/xfs/libxfs/xfs_defer.h > > > create mode 100644 fs/xfs/xfs_defer_item.c > > > > > > > > > diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile > > > index 3542d94..ad46a2d 100644 > > > --- a/fs/xfs/Makefile > > > +++ b/fs/xfs/Makefile > > > @@ -39,6 +39,7 @@ xfs-y += $(addprefix libxfs/, \ > > > xfs_btree.o \ > > > xfs_da_btree.o \ > > > xfs_da_format.o \ > > > + xfs_defer.o \ > > > xfs_dir2.o \ > > > xfs_dir2_block.o \ > > > xfs_dir2_data.o \ > > > @@ -66,6 +67,7 @@ xfs-y += xfs_aops.o \ > > > xfs_attr_list.o \ > > > xfs_bmap_util.o \ > > > xfs_buf.o \ > > > + xfs_defer_item.o \ > > > xfs_dir2_readdir.o \ > > > xfs_discard.o \ > > > xfs_error.o \ > > > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c > > > new file mode 100644 > > > index 0000000..ad14e33e > > > --- /dev/null > > > +++ b/fs/xfs/libxfs/xfs_defer.c ... > > > +int > > > +xfs_defer_finish( > > > + struct xfs_trans **tp, > > > + struct xfs_defer_ops *dop, > > > + struct xfs_inode *ip) > > > +{ > > > + struct xfs_defer_pending *dfp; > > > + struct list_head *li; > > > + struct list_head *n; > > > + void *done_item = NULL; > > > + void *state; > > > + int error = 0; > > > + void (*cleanup_fn)(struct xfs_trans *, void *, int); > > > + > > > + ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); > > > + > > > + /* Until we run out of pending work to finish... */ > > > + while (xfs_defer_has_unfinished_work(dop)) { > > > + /* Log intents for work items sitting in the intake. */ > > > + xfs_defer_intake_work(*tp, dop); > > > + > > > + /* Roll the transaction. */ > > > + error = xfs_defer_trans_roll(tp, dop, ip); > > > + if (error) > > > + goto out; > > > + > > > + /* Mark all pending intents as committed. */ > > > + list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { > > > + if (dfp->dfp_committed) > > > + break; > > > + dfp->dfp_committed = true; > > > + } > > > + > > > + /* Log an intent-done item for the first pending item. */ > > > + dfp = list_first_entry(&dop->dop_pending, > > > + struct xfs_defer_pending, dfp_list); > > > + done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, > > > + dfp->dfp_count); > > > + cleanup_fn = dfp->dfp_type->finish_cleanup; > > > + > > > + /* Finish the work items. */ > > > + state = NULL; > > > + list_for_each_safe(li, n, &dfp->dfp_work) { > > > + list_del(li); > > > + dfp->dfp_count--; > > > + error = dfp->dfp_type->finish_item(*tp, dop, li, > > > + done_item, &state); > > > + if (error == -EAGAIN) { > > > + /* > > > + * If the caller needs to try again, put the > > > + * item back on the pending list and jump out > > > + * for further processing. > > > > A little confused by the terminology here. Perhaps better to say "back > > on the work list" rather than "pending list?" > > Yes. > > > Also, what is the meaning/purpose of -EAGAIN here? This isn't used by > > the extent free bits so I'm missing some context. > > Generally, the ->finish_item() uses -EAGAIN to signal that it couldn't finish > the work item and that it's necessary to log a new redo item and try again. > Ah, Ok. So it is explicitly part of the dfops interface/infrastructure. I think that is worth documenting above with a comment (i.e., "certain callers might require many transactions, use -EAGAIN to indicate ... blah blah"). > Practically, the only user of this mechanism is the refcountbt adjust function. > It might be the case that we want to adjust N blocks, but some pathological > user has creatively used reflink to create many refcount records. In that > case we could blow out the transaction reservation logging all the updates. > > To avoid that, the refcount code tries to guess (conservatively) when it > might be getting close and returns a short *adjusted. See the call sites of > xfs_refcount_still_have_space(). Next, xfs_trans_log_finish_refcount_update() > will notice the short adjust returned and fixes up the CUD item to have a > reduced cud_nextents and to reflect where the operation stopped. Then, > xfs_refcount_update_finish_item() notices the short return, updates the work > item list, and returns -EAGAIN. Finally, xfs_defer_finish() sees the -EAGAIN > and requeues the work item so that we resume refcount adjusting after the > transaction rolls. > Hmm, this makes me think that maybe it is better to split this up into two patches for now after all. I'm expecting this is going to be merged along with the rmap bits before the refcount stuff and I'm not a huge fan of putting in infrastructure code without users, moreso without fully understanding how/why said code is going to be used (and I'm not really looking to jump ahead into the refcount stuff yet). > > For example, is there > > an issue with carrying a done_item with an unexpected list count? > > AFAICT, nothing in log recovery ever checks that the list counts of the > intent and done items actually match, let alone the extents logged with > them. It only seems to care if there's an efd such that efd->efd_efi_id == > efi->efi_id, in which case it won't replay the efi. > Yeah, I didn't notice any issues with respect to EFI/EFD handling, though I didn't look too hard because it doesn't use this -EAGAIN mechanism. If it did, I think you might hit the odd ASSERT() check here or there (see xfs_efd_item_format()), but that's probably not catastrophic. I think it also affects the size of the transaction written to the log, fwiw. I ask more because it's unexpected to have a structure with a list count that doesn't match the actual number of items and I don't see it called out anywhere. This might be another good reason to punt this part off to the reflink series... > I don't know if that was a deliberate part of the log design, but the > lack of checking helps us here. > > > Is it > > expected that xfs_defer_finish() will not return until -EAGAIN is > > "cleared" (does relogging below and rolling somehow address this)? > > Yes, relogging and rolling gives us a fresh transaction with which to > continue updating. > > > > + */ > > > + list_add(li, &dfp->dfp_work); > > > + dfp->dfp_count++; > > > + break; > > > + } else if (error) { > > > + /* > > > + * Clean up after ourselves and jump out. > > > + * xfs_defer_cancel will take care of freeing > > > + * all these lists and stuff. > > > + */ > > > + if (cleanup_fn) > > > + cleanup_fn(*tp, state, error); > > > + xfs_defer_trans_abort(*tp, dop, error); > > > + goto out; > > > + } > > > + } > > > + if (error == -EAGAIN) { > > > + /* > > > + * Log a new intent, relog all the remaining work > > > + * item to the new intent, attach the new intent to > > > + * the dfp, and leave the dfp at the head of the list > > > + * for further processing. > > > + */ > > > > Similar to the above, could you elaborate on the mechanics of this with > > respect to the log? E.g., the comment kind of just repeats what the > > code does as opposed to explain why it's here. Is the point here to log > > a new intent in the same transaction as the done item to ensure that we > > (atomically) indicate that certain operations need to be replayed if > > this transaction hits the log and then we crash? > > Yes. > > "This effectively replaces the old intent item with a new one listing only > the work items that were not completed when ->finish_item() returned -EAGAIN. > After the subsequent transaction roll, we'll resume where we left off with a > fresh transaction." > I'd point out the relevance of doing so in the same transaction, otherwise sounds good. Brian > Thank you for the review! > > --D > > > Brian > > > > > + dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, > > > + dfp->dfp_count); > > > + list_for_each(li, &dfp->dfp_work) > > > + dfp->dfp_type->log_item(*tp, dfp->dfp_intent, > > > + li); > > > + } else { > > > + /* Done with the dfp, free it. */ > > > + list_del(&dfp->dfp_list); > > > + kmem_free(dfp); > > > + } > > > + > > > + if (cleanup_fn) > > > + cleanup_fn(*tp, state, error); > > > + } > > > + > > > +out: > > > + return error; > > > +} > > > + > > > +/* > > > + * Free up any items left in the list. > > > + */ > > > +void > > > +xfs_defer_cancel( > > > + struct xfs_defer_ops *dop) > > > +{ > > > + struct xfs_defer_pending *dfp; > > > + struct xfs_defer_pending *pli; > > > + struct list_head *pwi; > > > + struct list_head *n; > > > + > > > + /* > > > + * Free the pending items. Caller should already have arranged > > > + * for the intent items to be released. > > > + */ > > > + list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { > > > + list_del(&dfp->dfp_list); > > > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > > > + list_del(pwi); > > > + dfp->dfp_count--; > > > + dfp->dfp_type->cancel_item(pwi); > > > + } > > > + ASSERT(dfp->dfp_count == 0); > > > + kmem_free(dfp); > > > + } > > > + list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { > > > + list_del(&dfp->dfp_list); > > > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > > > + list_del(pwi); > > > + dfp->dfp_count--; > > > + dfp->dfp_type->cancel_item(pwi); > > > + } > > > + ASSERT(dfp->dfp_count == 0); > > > + kmem_free(dfp); > > > + } > > > +} > > > + > > > +/* Add an item for later deferred processing. */ > > > +void > > > +xfs_defer_add( > > > + struct xfs_defer_ops *dop, > > > + enum xfs_defer_ops_type type, > > > + struct list_head *li) > > > +{ > > > + struct xfs_defer_pending *dfp = NULL; > > > + > > > + /* > > > + * Add the item to a pending item at the end of the intake list. > > > + * If the last pending item has the same type, reuse it. Else, > > > + * create a new pending item at the end of the intake list. > > > + */ > > > + if (!list_empty(&dop->dop_intake)) { > > > + dfp = list_last_entry(&dop->dop_intake, > > > + struct xfs_defer_pending, dfp_list); > > > + if (dfp->dfp_type->type != type || > > > + (dfp->dfp_type->max_items && > > > + dfp->dfp_count >= dfp->dfp_type->max_items)) > > > + dfp = NULL; > > > + } > > > + if (!dfp) { > > > + dfp = kmem_alloc(sizeof(struct xfs_defer_pending), > > > + KM_SLEEP | KM_NOFS); > > > + dfp->dfp_type = defer_op_types[type]; > > > + dfp->dfp_committed = false; > > > + dfp->dfp_intent = NULL; > > > + dfp->dfp_count = 0; > > > + INIT_LIST_HEAD(&dfp->dfp_work); > > > + list_add_tail(&dfp->dfp_list, &dop->dop_intake); > > > + } > > > + > > > + list_add_tail(li, &dfp->dfp_work); > > > + dfp->dfp_count++; > > > +} > > > + > > > +/* Initialize a deferred operation list. */ > > > +void > > > +xfs_defer_init_op_type( > > > + const struct xfs_defer_op_type *type) > > > +{ > > > + defer_op_types[type->type] = type; > > > +} > > > + > > > +/* Initialize a deferred operation. */ > > > +void > > > +xfs_defer_init( > > > + struct xfs_defer_ops *dop, > > > + xfs_fsblock_t *fbp) > > > +{ > > > + dop->dop_committed = false; > > > + dop->dop_low = false; > > > + memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); > > > + *fbp = NULLFSBLOCK; > > > + INIT_LIST_HEAD(&dop->dop_intake); > > > + INIT_LIST_HEAD(&dop->dop_pending); > > > +} > > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > > > new file mode 100644 > > > index 0000000..85c7a3a > > > --- /dev/null > > > +++ b/fs/xfs/libxfs/xfs_defer.h > > > @@ -0,0 +1,96 @@ > > > +/* > > > + * Copyright (C) 2016 Oracle. All Rights Reserved. > > > + * > > > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > > > + * > > > + * This program is free software; you can redistribute it and/or > > > + * modify it under the terms of the GNU General Public License > > > + * as published by the Free Software Foundation; either version 2 > > > + * of the License, or (at your option) any later version. > > > + * > > > + * This program is distributed in the hope that it would be useful, > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > + * GNU General Public License for more details. > > > + * > > > + * You should have received a copy of the GNU General Public License > > > + * along with this program; if not, write the Free Software Foundation, > > > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > > + */ > > > +#ifndef __XFS_DEFER_H__ > > > +#define __XFS_DEFER_H__ > > > + > > > +struct xfs_defer_op_type; > > > + > > > +/* > > > + * Save a log intent item and a list of extents, so that we can replay > > > + * whatever action had to happen to the extent list and file the log done > > > + * item. > > > + */ > > > +struct xfs_defer_pending { > > > + const struct xfs_defer_op_type *dfp_type; /* function pointers */ > > > + struct list_head dfp_list; /* pending items */ > > > + bool dfp_committed; /* committed trans? */ > > > + void *dfp_intent; /* log intent item */ > > > + struct list_head dfp_work; /* work items */ > > > + unsigned int dfp_count; /* # extent items */ > > > +}; > > > + > > > +/* > > > + * Header for deferred operation list. > > > + * > > > + * dop_low is used by the allocator to activate the lowspace algorithm - > > > + * when free space is running low the extent allocator may choose to > > > + * allocate an extent from an AG without leaving sufficient space for > > > + * a btree split when inserting the new extent. In this case the allocator > > > + * will enable the lowspace algorithm which is supposed to allow further > > > + * allocations (such as btree splits and newroots) to allocate from > > > + * sequential AGs. In order to avoid locking AGs out of order the lowspace > > > + * algorithm will start searching for free space from AG 0. If the correct > > > + * transaction reservations have been made then this algorithm will eventually > > > + * find all the space it needs. > > > + */ > > > +enum xfs_defer_ops_type { > > > + XFS_DEFER_OPS_TYPE_MAX, > > > +}; > > > + > > > +#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ > > > + > > > +struct xfs_defer_ops { > > > + bool dop_committed; /* did any trans commit? */ > > > + bool dop_low; /* alloc in low mode */ > > > + struct list_head dop_intake; /* unlogged pending work */ > > > + struct list_head dop_pending; /* logged pending work */ > > > + > > > + /* relog these inodes with each roll */ > > > + struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; > > > +}; > > > + > > > +void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, > > > + struct list_head *h); > > > +int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop, > > > + struct xfs_inode *ip); > > > +void xfs_defer_cancel(struct xfs_defer_ops *dop); > > > +void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); > > > +bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); > > > +int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip); > > > + > > > +/* Description of a deferred type. */ > > > +struct xfs_defer_op_type { > > > + enum xfs_defer_ops_type type; > > > + unsigned int max_items; > > > + void (*abort_intent)(void *); > > > + void *(*create_done)(struct xfs_trans *, void *, unsigned int); > > > + int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, > > > + struct list_head *, void *, void **); > > > + void (*finish_cleanup)(struct xfs_trans *, void *, int); > > > + void (*cancel_item)(struct list_head *); > > > + int (*diff_items)(void *, struct list_head *, struct list_head *); > > > + void *(*create_intent)(struct xfs_trans *, uint); > > > + void (*log_item)(struct xfs_trans *, void *, struct list_head *); > > > +}; > > > + > > > +void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); > > > +void xfs_defer_init_types(void); > > > + > > > +#endif /* __XFS_DEFER_H__ */ > > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > > > new file mode 100644 > > > index 0000000..849088d > > > --- /dev/null > > > +++ b/fs/xfs/xfs_defer_item.c > > > @@ -0,0 +1,36 @@ > > > +/* > > > + * Copyright (C) 2016 Oracle. All Rights Reserved. > > > + * > > > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > > > + * > > > + * This program is free software; you can redistribute it and/or > > > + * modify it under the terms of the GNU General Public License > > > + * as published by the Free Software Foundation; either version 2 > > > + * of the License, or (at your option) any later version. > > > + * > > > + * This program is distributed in the hope that it would be useful, > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > + * GNU General Public License for more details. > > > + * > > > + * You should have received a copy of the GNU General Public License > > > + * along with this program; if not, write the Free Software Foundation, > > > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > > + */ > > > +#include "xfs.h" > > > +#include "xfs_fs.h" > > > +#include "xfs_shared.h" > > > +#include "xfs_format.h" > > > +#include "xfs_log_format.h" > > > +#include "xfs_trans_resv.h" > > > +#include "xfs_bit.h" > > > +#include "xfs_sb.h" > > > +#include "xfs_mount.h" > > > +#include "xfs_defer.h" > > > +#include "xfs_trans.h" > > > + > > > +/* Initialize the deferred operation types. */ > > > +void > > > +xfs_defer_init_types(void) > > > +{ > > > +} > > > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c > > > index 09722a7..bf63f6d 100644 > > > --- a/fs/xfs/xfs_super.c > > > +++ b/fs/xfs/xfs_super.c > > > @@ -46,6 +46,7 @@ > > > #include "xfs_quota.h" > > > #include "xfs_sysfs.h" > > > #include "xfs_ondisk.h" > > > +#include "xfs_defer.h" > > > > > > #include <linux/namei.h> > > > #include <linux/init.h> > > > @@ -1850,6 +1851,7 @@ init_xfs_fs(void) > > > printk(KERN_INFO XFS_VERSION_STRING " with " > > > XFS_BUILD_OPTIONS " enabled\n"); > > > > > > + xfs_defer_init_types(); > > > xfs_dir_startup(); > > > > > > error = xfs_init_zones(); > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Tue Jun 28 07:32:42 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 521C17CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 07:32:42 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 24A058F8035 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:42 -0700 (PDT) X-ASG-Debug-ID: 1467117160-04cb6c063d22e230001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id qebSWrxlPHHNm2N7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 05:32:40 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4FD50C0799AD; Tue, 28 Jun 2016 12:32:40 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5SCWd41000912; Tue, 28 Jun 2016 08:32:40 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 8456B1200E8; Tue, 28 Jun 2016 08:32:39 -0400 (EDT) Date: Tue, 28 Jun 2016 08:32:39 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free Message-ID: <20160628123238.GE4212@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612638717.12839.11007379793448761871.stgit@birch.djwong.org> <20160627131508.GC23076@bfoster.bfoster> <20160627214145.GC4921@birch.djwong.org> <20160627220003.GA4917@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20160627220003.GA4917@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Tue, 28 Jun 2016 12:32:40 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467117160 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7487 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Mon, Jun 27, 2016 at 03:00:03PM -0700, Darrick J. Wong wrote: > On Mon, Jun 27, 2016 at 02:41:45PM -0700, Darrick J. Wong wrote: > > On Mon, Jun 27, 2016 at 09:15:08AM -0400, Brian Foster wrote: > > > On Thu, Jun 16, 2016 at 06:19:47PM -0700, Darrick J. Wong wrote: > > > > Connect the xfs_defer mechanism with the pieces that we'll need to > > > > handle deferred extent freeing. We'll wire up the existing code to > > > > our new deferred mechanism later. > > > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > > --- > > > > > > Could we merge this with the xfs_trans_*efi/efd* bits? We'd need to > > > preserve some calls for recovery, but it looks like other parts are only > > > used by the deferred ops infrastructure at this point. > > > > Yes, we could replace xfs_bmap_free_create_{intent,done} with > > xfs_trans_get_ef[id] and lose the silly functions. I'll go take > > care of all of them. > > Hah, gcc complains about the mismatch in pointer types for the second > argument. > > fs/xfs/xfs_defer_item.c:504:17: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] > .create_done = xfs_trans_get_bud, > ^ > fs/xfs/xfs_defer_item.c:504:17: note: (near initialization for ‘xfs_bmap_update_defer_type.create_done’) > > I guess one could put in an ugly cast to coerce the types at a cost of > uglifying the code. <shrug> Opinions? > Not sure what you mean here... I should be more clear. What I was thinking is to nuke xfs_defer_item.c, define the 'const struct xfs_defer_op_type xfs_extent_free_defer_type' right in xfs_trans_extfree.c (perhaps rename the file) and wire up the functions appropriately. Just change the function signatures if you need to. For something like xfs_trans_get_efd(), maybe refactor the guts into a static helper that both the defer callback and xfs_trans_get_efd() can use, since we need the latter for log recovery. Will something like that work? To put it simply, it looks like we have at least a few places where defer item has a callback that calls yet another interface, but is the only caller of the latter (e.g., xfs_bmap_free_create_intent()->xfs_trans_get_efi()). Brian > --D > > > > > --D > > > > > > > > Brian > > > > > > > fs/xfs/libxfs/xfs_defer.h | 1 > > > > fs/xfs/xfs_defer_item.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ > > > > 2 files changed, 109 insertions(+) > > > > > > > > > > > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > > > > index 85c7a3a..743fc32 100644 > > > > --- a/fs/xfs/libxfs/xfs_defer.h > > > > +++ b/fs/xfs/libxfs/xfs_defer.h > > > > @@ -51,6 +51,7 @@ struct xfs_defer_pending { > > > > * find all the space it needs. > > > > */ > > > > enum xfs_defer_ops_type { > > > > + XFS_DEFER_OPS_TYPE_FREE, > > > > XFS_DEFER_OPS_TYPE_MAX, > > > > }; > > > > > > > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > > > > index 4c2ba28..127a54e 100644 > > > > --- a/fs/xfs/xfs_defer_item.c > > > > +++ b/fs/xfs/xfs_defer_item.c > > > > @@ -29,9 +29,117 @@ > > > > #include "xfs_defer.h" > > > > #include "xfs_trans.h" > > > > #include "xfs_trace.h" > > > > +#include "xfs_bmap.h" > > > > +#include "xfs_extfree_item.h" > > > > + > > > > +/* Extent Freeing */ > > > > + > > > > +/* Sort bmap items by AG. */ > > > > +static int > > > > +xfs_bmap_free_diff_items( > > > > + void *priv, > > > > + struct list_head *a, > > > > + struct list_head *b) > > > > +{ > > > > + struct xfs_mount *mp = priv; > > > > + struct xfs_bmap_free_item *ra; > > > > + struct xfs_bmap_free_item *rb; > > > > + > > > > + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); > > > > + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); > > > > + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - > > > > + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); > > > > +} > > > > + > > > > +/* Get an EFI. */ > > > > +STATIC void * > > > > +xfs_bmap_free_create_intent( > > > > + struct xfs_trans *tp, > > > > + unsigned int count) > > > > +{ > > > > + return xfs_trans_get_efi(tp, count); > > > > +} > > > > + > > > > +/* Log a free extent to the intent item. */ > > > > +STATIC void > > > > +xfs_bmap_free_log_item( > > > > + struct xfs_trans *tp, > > > > + void *intent, > > > > + struct list_head *item) > > > > +{ > > > > + struct xfs_bmap_free_item *free; > > > > + > > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > > + xfs_trans_log_efi_extent(tp, intent, free->xbfi_startblock, > > > > + free->xbfi_blockcount); > > > > +} > > > > + > > > > +/* Get an EFD so we can process all the free extents. */ > > > > +STATIC void * > > > > +xfs_bmap_free_create_done( > > > > + struct xfs_trans *tp, > > > > + void *intent, > > > > + unsigned int count) > > > > +{ > > > > + return xfs_trans_get_efd(tp, intent, count); > > > > +} > > > > + > > > > +/* Process a free extent. */ > > > > +STATIC int > > > > +xfs_bmap_free_finish_item( > > > > + struct xfs_trans *tp, > > > > + struct xfs_defer_ops *dop, > > > > + struct list_head *item, > > > > + void *done_item, > > > > + void **state) > > > > +{ > > > > + struct xfs_bmap_free_item *free; > > > > + int error; > > > > + > > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > > + error = xfs_trans_free_extent(tp, done_item, > > > > + free->xbfi_startblock, > > > > + free->xbfi_blockcount); > > > > + kmem_free(free); > > > > + return error; > > > > +} > > > > + > > > > +/* Abort all pending EFIs. */ > > > > +STATIC void > > > > +xfs_bmap_free_abort_intent( > > > > + void *intent) > > > > +{ > > > > + xfs_efi_release(intent); > > > > +} > > > > + > > > > +/* Cancel a free extent. */ > > > > +STATIC void > > > > +xfs_bmap_free_cancel_item( > > > > + struct list_head *item) > > > > +{ > > > > + struct xfs_bmap_free_item *free; > > > > + > > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > > + kmem_free(free); > > > > +} > > > > + > > > > +const struct xfs_defer_op_type xfs_extent_free_defer_type = { > > > > + .type = XFS_DEFER_OPS_TYPE_FREE, > > > > + .max_items = XFS_EFI_MAX_FAST_EXTENTS, > > > > + .diff_items = xfs_bmap_free_diff_items, > > > > + .create_intent = xfs_bmap_free_create_intent, > > > > + .abort_intent = xfs_bmap_free_abort_intent, > > > > + .log_item = xfs_bmap_free_log_item, > > > > + .create_done = xfs_bmap_free_create_done, > > > > + .finish_item = xfs_bmap_free_finish_item, > > > > + .cancel_item = xfs_bmap_free_cancel_item, > > > > +}; > > > > + > > > > +/* Deferred Item Initialization */ > > > > > > > > /* Initialize the deferred operation types. */ > > > > void > > > > xfs_defer_init_types(void) > > > > { > > > > + xfs_defer_init_op_type(&xfs_extent_free_defer_type); > > > > } > > > > > > > > _______________________________________________ > > > > xfs mailing list > > > > xfs@oss.sgi.com > > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From hch@lst.de Tue Jun 28 08:11:08 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 348927CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:11:08 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id E73A2304032 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:11:04 -0700 (PDT) X-ASG-Debug-ID: 1467119460-04bdf074b4188010001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id 26jRHzfNwsjJ0bu0 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:11:02 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 10DBA68D89; Tue, 28 Jun 2016 15:11:00 +0200 (CEST) Date: Tue, 28 Jun 2016 15:10:59 +0200 From: Christoph Hellwig <hch@lst.de> To: Dave Chinner <david@fromorbit.com> Cc: Christoph Hellwig <hch@lst.de>, xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160628131059.GA30475@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <20160624072612.GA22205@lst.de> <20160624230045.GG12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160624230045.GG12670@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1467119461 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1960 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30830 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Sat, Jun 25, 2016 at 09:00:45AM +1000, Dave Chinner wrote: > > > > Sorry, but this is simply broken - allowing apps to opt-in behavior > > (e.g. like we're using O_DIRECT) is always fine. Requriring > > filesystem-specific tuning that has affect outside the app to get > > existing documented behavior is not how to design APIs. > > Using DAX is an *admin decision*, not an application decision. Of course - that's exactly my point. > Indeed, it's a mount option right now, and that's most definitely not > something the application can turn on or off! Inode flags allow the > admin to decide that two apps working on the same filesystem can use > (or not use) DAX independently, rather than needing to put them on > different filesystems. Right. And an existing application can get DAX turned on under its back, and will now suddently get different synchronization behavior. That is if it's writes happen to be aligned to the fs block size. > > Maybe we'll need to opt-in to use DAX for mmap, but giving the same > > existing behavior for read and write and avoiding a copy to the pagecache > > is an obvious win. > > You can't use DAX just for mmap. It's an inode scope behaviour - > once it's turned on, all accesses to that inode - regardless of user > interface - must use DAX. It's all or nothing, not a per file > descript/mmap context option. Right now it is. But when discussing mmap behavior one option was to require an opt-in to get DAX-specific mmap semantics. For plain read/write we have no such option and thus absolutely need to behave as all normal reads and writes behave. If you think the exclusive lock for writes hurts we have two options: a) implement range locks (although they might be more expensive for typical loads) b) add a new O_* or RWF_* option to not require the synchronization for apps that don't want it. Neither of those cases really is DAX-specific. From boaz@plexistor.com Tue Jun 28 08:27:12 2016 Return-Path: <boaz@plexistor.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 980D17CA4 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:27:12 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 65BEA304032 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:27:12 -0700 (PDT) X-ASG-Debug-ID: 1467120426-04cb6c063f230c80001-NocioJ Received: from mail-wm0-f43.google.com (mail-wm0-f43.google.com [74.125.82.43]) by cuda.sgi.com with ESMTP id pyCiPv7nv0LrU3L8 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:27:07 -0700 (PDT) X-Barracuda-Envelope-From: boaz@plexistor.com X-Barracuda-Effective-Source-IP: mail-wm0-f43.google.com[74.125.82.43] X-Barracuda-Apparent-Source-IP: 74.125.82.43 Received: by mail-wm0-f43.google.com with SMTP id a66so27864657wme.0 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:27:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=plexistor-com.20150623.gappssmtp.com; s=20150623; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-transfer-encoding; bh=FQ2N2UdRcGMtHqiac6zr2Fu4X6oSbftcBCBzJqh301k=; b=yKgO1sPRYup3cvQ85BAALDKM4YAdNNOcnNTlY1peXbli4Mk/D/y42Wk7UFUTK7/Hud drWQ2rddfnWozEaqOIZgxJEE6ayHqP/ZK4a3/Zt7sJhFx8xAtsH1ePDMwhIbIJMuKJ7B ByOGsn3BCgk3KE6SgpfT2DCw1DtsqDltAYHiZIXWIrliSVgBtuJl/7zi4PYChRtaajXp zpCpTZR3qAoHlmpLI6wPDkudncDkNOWetT92kflCxykh9vIoSAmMpXqpe54SN0cCylxB hhrmC1Gwk+zCV44pI6mzxIwhBdUBcLSrfayyBMW6JxsHZYsIHUZC/RGBlwYIKVCHlBGg VOlw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-transfer-encoding; bh=FQ2N2UdRcGMtHqiac6zr2Fu4X6oSbftcBCBzJqh301k=; b=jJ4fKC/h0Ll0KRgdZbL6s2UXeBp64kzh5Z0Bzo6Rp94h8TOSyKxt8klrfodr1OnCTC SJu8zXfxLF764GoojQaFYrPN6ehl8oAq9iGg5/strmOSl3WOUhGYe5SNKAsX+bIKXyEY OpB7szGa9vBHDe5cAIQZ2PoB6awbuii+abqdbKVT5UXBgQPG7qkkL3AKSAW+ZFc6H3td JsAXejpQWFlg0s3IqTEqlCYp0oc9GYlwLFbC6QRI5zS5bQMC1wWqFqgocuvDvAbflGjG FW2YW0O2HmIK6Or29Z2ZpnGSSWqBsNz74xbcLJSMrj2f3i/2dkTZGHuDEVof0bdwTF/I 1uZQ== X-Gm-Message-State: ALyK8tJ+gy5Hc8e9CXJKimuytw6WaH6ci17qNANhgUrzt3ZafDtxyiCoNxtkhIXacKhPNg== X-Received: by 10.194.25.135 with SMTP id c7mr3059259wjg.63.1467120426316; Tue, 28 Jun 2016 06:27:06 -0700 (PDT) Received: from [10.0.0.5] ([207.232.55.62]) by smtp.googlemail.com with ESMTPSA id c142sm9117369wme.18.2016.06.28.06.27.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jun 2016 06:27:05 -0700 (PDT) Message-ID: <57727B27.7060104@plexistor.com> Date: Tue, 28 Jun 2016 16:27:03 +0300 From: Boaz Harrosh <boaz@plexistor.com> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Christoph Hellwig <hch@lst.de>, Dave Chinner <david@fromorbit.com> CC: xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <20160624072612.GA22205@lst.de> <20160624230045.GG12670@dastard> <20160628131059.GA30475@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking In-Reply-To: <20160628131059.GA30475@lst.de> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f43.google.com[74.125.82.43] X-Barracuda-Start-Time: 1467120427 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 451 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30830 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/28/2016 04:10 PM, Christoph Hellwig wrote: > On Sat, Jun 25, 2016 at 09:00:45AM +1000, Dave Chinner wrote: <> > > Right. And an existing application can get DAX turned on under its > back, and will now suddently get different synchronization behavior. > That is if it's writes happen to be aligned to the fs block size. > Is there an actual application that does that? or is this purely theoretical right now? Thanks Boaz From hch@lst.de Tue Jun 28 08:28:44 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 009B87CA4 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:28:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 6EA33AC003 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:28:43 -0700 (PDT) X-ASG-Debug-ID: 1467120520-04cb6c063d230d90001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id VxFRGjeYP9gZsFV4 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:28:41 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id AC35868D8B; Tue, 28 Jun 2016 15:28:39 +0200 (CEST) Date: Tue, 28 Jun 2016 15:28:39 +0200 From: Christoph Hellwig <hch@lst.de> To: Dave Chinner <david@fromorbit.com> Cc: Christoph Hellwig <hch@lst.de>, xfs@oss.sgi.com, rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V5 Message-ID: <20160628132839.GA30892@lst.de> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V5 References: <1464792297-13185-1-git-send-email-hch@lst.de> <20160628002649.GI12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160628002649.GI12670@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1467120521 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 526 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30830 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 28, 2016 at 10:26:49AM +1000, Dave Chinner wrote: > Christoph, it look slike there's an ENOSPC+ENOMEM behavioural regression here. > generic/224 on my 1p/1GB RAM VM using a 1k lock size filesystem has > significantly different behaviour once ENOSPC is hit withi this patchset. Works fine on my 1k test setup with 4 CPUs and 2GB RAM. 1 CPU and 1GB RAM runs into the OOM killer, although I haven't checked if that was the case with the old code as well. I'll look into this more later today or tomorrow. From hch@lst.de Tue Jun 28 08:38:17 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 673367CA4 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:38:17 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2E9568F8033 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:38:14 -0700 (PDT) X-ASG-Debug-ID: 1467121091-04cb6c063e2315d0001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id tAA41R66bOjxqnN8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:38:12 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 1917168C3F; Tue, 28 Jun 2016 15:38:11 +0200 (CEST) Date: Tue, 28 Jun 2016 15:38:11 +0200 From: Christoph Hellwig <hch@lst.de> To: Dave Chinner <david@fromorbit.com> Cc: Christoph Hellwig <hch@lst.de>, xfs@oss.sgi.com, rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V5 Message-ID: <20160628133811.GA31283@lst.de> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V5 References: <1464792297-13185-1-git-send-email-hch@lst.de> <20160628002649.GI12670@dastard> <20160628132839.GA30892@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160628132839.GA30892@lst.de> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1467121092 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 566 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30830 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 28, 2016 at 03:28:39PM +0200, Christoph Hellwig wrote: > > generic/224 on my 1p/1GB RAM VM using a 1k lock size filesystem has > > significantly different behaviour once ENOSPC is hit withi this patchset. > > Works fine on my 1k test setup with 4 CPUs and 2GB RAM. 1 CPU and 1GB > RAM runs into the OOM killer, although I haven't checked if that was > the case with the old code as well. I'll look into this more later > today or tomorrow. It was doing fine before my changes - I'm going to investigate what caused the change in behavior. From hch@lst.de Tue Jun 28 08:39:32 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EE5887CA4 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:39:32 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id ADFFD8F8033 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:39:32 -0700 (PDT) X-ASG-Debug-ID: 1467121169-04bdf074b7189b10001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id fq8EJO6hcXy41eMp (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:39:30 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id A997D68C3F; Tue, 28 Jun 2016 15:39:28 +0200 (CEST) Date: Tue, 28 Jun 2016 15:39:28 +0200 From: Christoph Hellwig <hch@lst.de> To: Boaz Harrosh <boaz@plexistor.com> Cc: Christoph Hellwig <hch@lst.de>, Dave Chinner <david@fromorbit.com>, xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160628133928.GB31283@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <20160624072612.GA22205@lst.de> <20160624230045.GG12670@dastard> <20160628131059.GA30475@lst.de> <57727B27.7060104@plexistor.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <57727B27.7060104@plexistor.com> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1467121169 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 795 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30831 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 28, 2016 at 04:27:03PM +0300, Boaz Harrosh wrote: > > Right. And an existing application can get DAX turned on under its > > back, and will now suddently get different synchronization behavior. > > That is if it's writes happen to be aligned to the fs block size. > > > > Is there an actual application that does that? or is this purely > theoretical right now? Lots of them. The typical case is multithreaded (or preforked like old apache) daemons that use O_APPEND to write to a common log file. Then again those log records will usually not be 4k aligned, so they'd still accidentally get the exclusive locking even without this patch. But beware the case where a log record actually matches the alignment.. > > > Thanks > Boaz ---end quoted text--- From boaz@plexistor.com Tue Jun 28 08:56:37 2016 Return-Path: <boaz@plexistor.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 8A8ED7CA4 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:56:37 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 0C651AC003 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:56:36 -0700 (PDT) X-ASG-Debug-ID: 1467122193-04bdf074b718b740001-NocioJ Received: from mail-wm0-f43.google.com (mail-wm0-f43.google.com [74.125.82.43]) by cuda.sgi.com with ESMTP id 1F3vvhW58WC3AjCA (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:56:34 -0700 (PDT) X-Barracuda-Envelope-From: boaz@plexistor.com X-Barracuda-Effective-Source-IP: mail-wm0-f43.google.com[74.125.82.43] X-Barracuda-Apparent-Source-IP: 74.125.82.43 Received: by mail-wm0-f43.google.com with SMTP id v199so141049471wmv.0 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 06:56:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=plexistor-com.20150623.gappssmtp.com; s=20150623; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-transfer-encoding; bh=BziU09rUwOPmvG/puVw8AGNvl/d0bNxPKp+hfzBB8mk=; b=FCZqDex8wFv7RMyIGd0iRnU2XtEnX9jUEj/eqss2hhph/E1aFJGobC+3MF6VvUuVOY 1SKo2ViMZ3J772UaFb8oKsI6UROTuEKgcJlW3jy/C5l+B12OdQfYszTG5ZKtZuCFw8lW Yo0am7fY9L9GbMSNaL0y4JfifFqFUk+tGxnYr+81BoWuY+NnM3eRBIJG0u7/IWmHI966 AYB/+n09mti9z+FwFf3bk+XG3BX1D9MiBJ/DIfAvn+VvfVp7KLFtvgC1UYF1DDRS7krn T+YrYk01rgpItbcvax/5Kh3nd59sRb/5KmYT3E0j4UftcB2o4MpOR8QHciL2pfk8FQz4 lSoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-transfer-encoding; bh=BziU09rUwOPmvG/puVw8AGNvl/d0bNxPKp+hfzBB8mk=; b=PH66sTYmHZR/5dxb4y/f8/PuCLtzLcrqkLyJg53S8ABB0LLNFGc5slIn3Nu/PFTLVq BChpWiYrOpbIRgey2vPK+J86aYZTfG6kS1zulXKm71+0QHm/5l2gg9uIU6AapnU7xsFc jaPIJ1EYkUBxKlm6BaMPYKWk0EnMYM7mh54sn/4l/FesDNB3P5u6X+qz7RzvvO0FLJ36 kDy4lIg4BZgepzXHyiYXvBsinuQD01uFrvPXGrZ2a/mSiFNXjIxCAy4zpvEs21e0rPM8 JRLH22AwSgehr6p8dvxuawpyudZw8+wb2bdd/enx02s/Jw2Zi5ass4/eu6kmyrs3QK+t NWQg== X-Gm-Message-State: ALyK8tK44M5vquK/3khb30G56b6C5OKO1uNqPsT4fjjpALY9GVuMJUS9+9nXn1164/XyIQ== X-Received: by 10.194.105.41 with SMTP id gj9mr3611864wjb.22.1467122192790; Tue, 28 Jun 2016 06:56:32 -0700 (PDT) Received: from [10.0.0.5] ([207.232.55.62]) by smtp.googlemail.com with ESMTPSA id c74sm445597wme.1.2016.06.28.06.56.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 28 Jun 2016 06:56:32 -0700 (PDT) Message-ID: <5772820E.2080403@plexistor.com> Date: Tue, 28 Jun 2016 16:56:30 +0300 From: Boaz Harrosh <boaz@plexistor.com> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Christoph Hellwig <hch@lst.de> CC: Dave Chinner <david@fromorbit.com>, xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <20160624072612.GA22205@lst.de> <20160624230045.GG12670@dastard> <20160628131059.GA30475@lst.de> <57727B27.7060104@plexistor.com> <20160628133928.GB31283@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking In-Reply-To: <20160628133928.GB31283@lst.de> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f43.google.com[74.125.82.43] X-Barracuda-Start-Time: 1467122194 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1838 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30831 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/28/2016 04:39 PM, Christoph Hellwig wrote: > On Tue, Jun 28, 2016 at 04:27:03PM +0300, Boaz Harrosh wrote: >>> Right. And an existing application can get DAX turned on under its >>> back, and will now suddently get different synchronization behavior. >>> That is if it's writes happen to be aligned to the fs block size. >>> >> >> Is there an actual application that does that? or is this purely >> theoretical right now? > > Lots of them. The typical case is multithreaded (or preforked like old > apache) daemons that use O_APPEND to write to a common log file. Then > again those log records will usually not be 4k aligned, so they'd still > accidentally get the exclusive locking even without this patch. But > beware the case where a log record actually matches the alignment.. > But O_APPEND is exclusion problem of i_size update not of the actual memcpy done in parallel or not. Actually with O_APPEND each write request should write a different region of the file, there are no overlapping writes. And no issue of which version of the write came last and got its data written. If it is the issue of isize update vs O_APPEND is a different issue don't you think? One way that we solved it is to update isize = isize + len; atomically before starting the IO, then on the error case sub the unwritten bytes. And still allow concurrent writers. I agree that isize updates needs to be atomic, but why does the memcpy? And BTW in NFS O_APPEND concurrent readers to a writer may see ZEROs in the interim. I still don't see how an application can use the fact that two writers will not give them mixed records. And surly it does not work on a shared FS. So I was really wondering if you know of any such app Thanks Boaz >> >> >> Thanks >> Boaz > ---end quoted text--- > From hch@lst.de Tue Jun 28 10:39:32 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id DF75A7CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 10:39:32 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 9FC938F8039 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:39:32 -0700 (PDT) X-ASG-Debug-ID: 1467128366-04bdf074b61929b0001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id rDXx8QPA9xEzhrNK (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:39:27 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 8E22C68C3E; Tue, 28 Jun 2016 17:39:25 +0200 (CEST) Date: Tue, 28 Jun 2016 17:39:25 +0200 From: Christoph Hellwig <hch@lst.de> To: Boaz Harrosh <boaz@plexistor.com> Cc: Christoph Hellwig <hch@lst.de>, Dave Chinner <david@fromorbit.com>, xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking Message-ID: <20160628153925.GA2643@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <20160624072612.GA22205@lst.de> <20160624230045.GG12670@dastard> <20160628131059.GA30475@lst.de> <57727B27.7060104@plexistor.com> <20160628133928.GB31283@lst.de> <5772820E.2080403@plexistor.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <5772820E.2080403@plexistor.com> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1467128366 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1135 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30834 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 28, 2016 at 04:56:30PM +0300, Boaz Harrosh wrote: > Actually with O_APPEND each write request should write a different region > of the file, there are no overlapping writes. And no issue of which version of the > write came last and got its data written. You have one fd for multiple threads or processes (it doesn't matter if you're using O_APPEND or not), and all of them write to it. i_size is only updated once the write finishes, so having multiple concurrent writes will mean multiple records go into the same regions. Now to be fair in current XFS writes beyond i_size will always take the lock exclusively, so for this case we will not get concurrent writes and thus data corruption anyway. But if you have a cycling log that gets overwritten (say a database journal) we're back to square one. > I still don't see how an application can use the fact that two writers > will not give them mixed records. And surly it does not work on a shared > FS. So I was really wondering if you know of any such app If it doesn't work for two threads using the same fd on a shared fs the fs is broken. From sandeen@sandeen.net Tue Jun 28 10:40:36 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5401A7CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 10:40:36 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 269F08F8040 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:40:35 -0700 (PDT) X-ASG-Debug-ID: 1467128432-04cbb027382fdb70001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id 5jGLkNHAf9GyZ2o5 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 08:40:32 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 679E62A9D for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 10:40:32 -0500 (CDT) Subject: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice References: <13dd3974-956d-c3af-86ed-f6ce5cc1b996@redhat.com> <20160627094855.GC29774@redhat.com> <5c408cf1-e9fa-8bee-106e-93e553fc98a7@sandeen.net> <20160628085726.GA4397@redhat.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <c72e1f9a-0f83-aa2b-48f1-bc6deccc6315@sandeen.net> Date: Tue, 28 Jun 2016 10:40:31 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160628085726.GA4397@redhat.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1467128432 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4180 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30833 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/28/16 3:57 AM, Carlos Maiolino wrote: > On Mon, Jun 27, 2016 at 10:34:39AM -0500, Eric Sandeen wrote: >> >> >> On 6/27/16 4:48 AM, Carlos Maiolino wrote: >>> On Fri, Jun 24, 2016 at 04:24:58PM -0500, Eric Sandeen wrote: >>>> kernel commit 5ef828c4 >>>> xfs: avoid false quotacheck after unclean shutdown >>>> >>>> made xfs_sb_from_disk() also call xfs_sb_quota_from_disk >>>> by default. >>>> >>>> However, when this was merged to libxfs, existing separate >>>> calls to libxfs_sb_quota_from_disk remained, and calling it >>>> twice in a row on a V4 superblock leads to issues, because: >>>> >>>> >>>> if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { >>>> ... >>>> sbp->sb_pquotino = sbp->sb_gquotino; >>>> sbp->sb_gquotino = NULLFSINO; >>>> >>>> and after the second call, we have set both pquotino and gquotino >>>> to NULLFSINO. >>>> >>>> Fix this by making it safe to call twice, and also remove the extra >>>> calls to libxfs_sb_quota_from_disk. >>>> >>>> This is only spotted when running xfstests with "-m crc=0" because >>>> the sb_from_disk change came about after V5 became default, and >>>> the above behavior only exists on a V4 superblock. >>>> >>>> Reported-by: Eryu Guan <eguan@redhat.com> >>>> Signed-off-by: Eric Sandeen <sandeen@redhat.com> >>>> --- >>>> >>>> >>>> diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c >>>> index 45db6ae..44f3e3e 100644 >>>> --- a/libxfs/xfs_sb.c >>>> +++ b/libxfs/xfs_sb.c >>>> @@ -316,13 +316,16 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) >>>> XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; >>>> sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); >>>> >>>> - if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { >>>> + if (sbp->sb_qflags & XFS_PQUOTA_ACCT && >>>> + sbp->sb_gquotino != NULLFSINO) { >>> >>> Although I agree with this check, shouldn't we report some sort of error when it >>> happens? Once, it's not supposed to happen, and, might be a sign of corruption? >> >> I dunno, it would also happen if it gets called twice, which is intentionally >> made harmless by this change. We don't warn on free(NULL) for example... >> > > Well, I don't 100% agree with not having a warning here, but it doesn't make the > patch less valuable. Thanks Carlos - Maybe I don't understand what you want to warn about. If we get here with: if (sbp->sb_qflags & XFS_PQUOTA_ACCT && sbp->sb_gquotino != NULLFSINO) { that means we have an on-disk super without the pquotino field, the XFS_PQUOTA_ACCT flag is set, and so the gquotino field was used for the project quota; this is valid, and there is nothing to warn about in this case. If we get here with: if (sbp->sb_qflags & XFS_PQUOTA_ACCT && sbp->sb_gquotino == NULLFSINO) { that means we have an on-disk super without the pquotino field, the XFS_PQUOTA_ACCT flag is set, and the gquotino was not set to a valid value. This could happen either from a bad on-disk value, or it could mean that we called the function twice in a row. Without maintaining more state, we can't know which, and warning the user about a programming error wouldn't be helpful. Actually, repair already handles this case elsewhere: quota_sb_check(xfs_mount_t *mp) { /* * if the sb says we have quotas and we lost both, * signal a superblock downgrade. that will cause * the quota flags to get zeroed. (if we only lost * one quota inode, do nothing and complain later.) * * if the sb says we have quotas but we didn't start out * with any quota inodes, signal a superblock downgrade. In the case where quota flags are on but all quota inodes are zero, it silently clears the quota flags. Whether or not that should be silent I'm not sure, but I think that is separate from this patch. Thanks, -Eric > Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> > >> I don't think it needs a warning. >> >> -Eric >> >> >> _______________________________________________ >> xfs mailing list >> xfs@oss.sgi.com >> http://oss.sgi.com/mailman/listinfo/xfs > From darrick.wong@oracle.com Tue Jun 28 11:30:04 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0EE647CA4 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 11:30:04 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id A904D8F8039 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 09:30:00 -0700 (PDT) X-ASG-Debug-ID: 1467131395-04bdf074b71970c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id vAeias3JX7PCLeaY (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 09:29:56 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5SGTsGL001470 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 16:29:54 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5SGTrM7017861 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 16:29:54 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5SGTrJI000428; Tue, 28 Jun 2016 16:29:53 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 09:29:52 -0700 Date: Tue, 28 Jun 2016 09:29:51 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 014/119] xfs: introduce interval queries on btrees Message-ID: <20160628162951.GA16181@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 014/119] xfs: introduce interval queries on btrees References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612636170.12839.675596870201079078.stgit@birch.djwong.org> <20160622151800.GC5423@bfoster.bfoster> <20160627210746.GB4921@birch.djwong.org> <20160628123218.GC4212@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160628123218.GC4212@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467131396 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17962 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30836 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Tue, Jun 28, 2016 at 08:32:19AM -0400, Brian Foster wrote: > On Mon, Jun 27, 2016 at 02:07:46PM -0700, Darrick J. Wong wrote: > > On Wed, Jun 22, 2016 at 11:18:00AM -0400, Brian Foster wrote: > > > On Thu, Jun 16, 2016 at 06:19:21PM -0700, Darrick J. Wong wrote: > > > > Create a function to enable querying of btree records mapping to a > > > > range of keys. This will be used in subsequent patches to allow > > > > querying the reverse mapping btree to find the extents mapped to a > > > > range of physical blocks, though the generic code can be used for > > > > any range query. > > > > > > > > v2: add some shortcuts so that we can jump out of processing once > > > > we know there won't be any more records to find. > > > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > > --- > > > > fs/xfs/libxfs/xfs_btree.c | 249 +++++++++++++++++++++++++++++++++++++++++++++ > > > > fs/xfs/libxfs/xfs_btree.h | 22 +++- > > > > fs/xfs/xfs_trace.h | 1 > > > > 3 files changed, 267 insertions(+), 5 deletions(-) > > > > > > > > > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > > > index afcafd6..5f5cf23 100644 > > > > --- a/fs/xfs/libxfs/xfs_btree.c > > > > +++ b/fs/xfs/libxfs/xfs_btree.c > > > > @@ -4509,3 +4509,252 @@ xfs_btree_calc_size( > > > > } > > > > return rval; > > > > } > > > > + > > > > +/* Query a regular btree for all records overlapping a given interval. */ > > > > > > Can you elaborate on the search algorithm used? (More for reference > > > against the overlapped query, as that one is more complex). > > > > Ok. Both query_range functions aim to return all records intersecting the > > given range. > > > > For non-overlapped btrees, we start with a LE lookup of the low key and > > return each record we find a the record with a key greater than the > > high key. > > > > For overlapped btrees, we follow the procedure in the "Interval trees" > > section of _Introduction to Algorithms_, which is 14.3 in the 2nd and > > 3rd editions. The query algorithm is roughly as follows: > > > > For any leaf btree node, generate the low and high keys for the record. > > If there's a range overlap with the query's low and high keys, pass the > > record to the iterator function. > > > > For any internal btree node, compare the low and high keys for each pointer > > against the query's low and high keys. If there's an overlap, follow the > > pointer downwards in the tree. > > > > (I could render the figures in the book as ASCII art if anyone wants.) > > > > Thanks. I meant more to update the comments above each function. :) No > need to go as far as ASCII art I don't think (the external reference > might be good though). I was really just looking for something that says > "this function is supposed to do <whatever>" so somebody reading through > it has a starting point of reference. Ok, I pasted a (somewhat reworded) version of the above in the comments. > > > > > > > +STATIC int > > > > +xfs_btree_simple_query_range( > > > > + struct xfs_btree_cur *cur, > > > > + union xfs_btree_irec *low_rec, > > > > + union xfs_btree_irec *high_rec, > > > > + xfs_btree_query_range_fn fn, > > > > + void *priv) > > > > +{ > > > > + union xfs_btree_rec *recp; > > > > + union xfs_btree_rec rec; > > > > + union xfs_btree_key low_key; > > > > + union xfs_btree_key high_key; > > > > + union xfs_btree_key rec_key; > > > > + __int64_t diff; > > > > + int stat; > > > > + bool firstrec = true; > > > > + int error; > > > > + > > > > + ASSERT(cur->bc_ops->init_high_key_from_rec); > > > > + > > > > + /* Find the keys of both ends of the interval. */ > > > > + cur->bc_rec = *high_rec; > > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > > > > + > > > > + cur->bc_rec = *low_rec; > > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > > > > + > > > > + /* Find the leftmost record. */ > > > > + stat = 0; > > > > + error = xfs_btree_lookup(cur, XFS_LOOKUP_LE, &stat); > > > > + if (error) > > > > + goto out; > > > > + > > > > + while (stat) { > > > > + /* Find the record. */ > > > > + error = xfs_btree_get_rec(cur, &recp, &stat); > > > > + if (error || !stat) > > > > + break; > > > > + > > > > + /* Can we tell if this record is too low? */ > > > > + if (firstrec) { > > > > + cur->bc_rec = *low_rec; > > > > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > > > > + diff = cur->bc_ops->key_diff(cur, &rec_key); > > > > + if (diff < 0) > > > > + goto advloop; > > > > + } > > > > + firstrec = false; > > > > > > This could move up into the if block. > > > > Ok. > > > > > > + > > > > + /* Have we gone past the end? */ > > > > + cur->bc_rec = *high_rec; > > > > + cur->bc_ops->init_key_from_rec(&rec_key, recp); > > > > > > I'd move this up to immediately after the xfs_btree_get_rec() call and > > > eliminate the duplicate in the 'if (firstrec)' block above. > > > > Ok. That key ought to be named rec_hkey too. > > > > > > + diff = cur->bc_ops->key_diff(cur, &rec_key); > > > > + if (diff > 0) > > > > + break; > > > > + > > > > + /* Callback */ > > > > + error = fn(cur, recp, priv); > > > > + if (error < 0 || error == XFS_BTREE_QUERY_RANGE_ABORT) > > > > + break; > > > > + > > > > +advloop: > > > > + /* Move on to the next record. */ > > > > + error = xfs_btree_increment(cur, 0, &stat); > > > > + if (error) > > > > + break; > > > > + } > > > > + > > > > +out: > > > > + return error; > > > > +} > > > > + > > > > +/* > > > > + * Query an overlapped interval btree for all records overlapping a given > > > > + * interval. > > > > + */ > > > > > > Same comment here, can you elaborate on the search algorithm? Also, I > > > think an example or generic description of the rules around what records > > > this query returns (e.g., low_rec/high_rec vs. record low/high keys) > > > would be useful, particularly since I, at least, don't have much context > > > on the rmap+reflink scenarios quite yet. > > > > Let's say you have a bunch of (overlapped) rmap records: > > > > 1: +- file A startblock B offset C length D -----------+ > > 2: +- file E startblock F offset G length H --------------+ > > 3: +- file I startblock F offset J length K --+ > > 4: +- file L... --+ > > > > Now say we want to map block (B+D) into file A at offset (C+D). Ideally, we'd > > simply increment the length of record 1. But how do we find that record that > > ends at (B+D-1)? A LE lookup of (B+D-1) would return record 3 because the > > keys are ordered first by startblock. An interval query would return records > > 1 and 2 because they both overlap (B+D-1), and from that we can pick out > > record 1 as the appropriate left neighbor. > > > > Great, thanks.. can you include this content in the comment above the > function as well? Added this to the comments as well, since it documents the only justification for any of this overlapped interval btree stuff. :) --D > > Brian > > > In the non-overlapped case you can do a LE lookup and decrement the cursor > > because a record's interval must end before the next record. > > > > > > +STATIC int > > > > +xfs_btree_overlapped_query_range( > > > > + struct xfs_btree_cur *cur, > > > > + union xfs_btree_irec *low_rec, > > > > + union xfs_btree_irec *high_rec, > > > > + xfs_btree_query_range_fn fn, > > > > + void *priv) > > > > +{ > > > > + union xfs_btree_ptr ptr; > > > > + union xfs_btree_ptr *pp; > > > > + union xfs_btree_key rec_key; > > > > + union xfs_btree_key low_key; > > > > + union xfs_btree_key high_key; > > > > + union xfs_btree_key *lkp; > > > > + union xfs_btree_key *hkp; > > > > + union xfs_btree_rec rec; > > > > + union xfs_btree_rec *recp; > > > > + struct xfs_btree_block *block; > > > > + __int64_t ldiff; > > > > + __int64_t hdiff; > > > > + int level; > > > > + struct xfs_buf *bp; > > > > + int i; > > > > + int error; > > > > + > > > > + /* Find the keys of both ends of the interval. */ > > > > + cur->bc_rec = *high_rec; > > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > > + cur->bc_ops->init_key_from_rec(&high_key, &rec); > > > > + > > > > + cur->bc_rec = *low_rec; > > > > + cur->bc_ops->init_rec_from_cur(cur, &rec); > > > > + cur->bc_ops->init_key_from_rec(&low_key, &rec); > > > > + > > > > + /* Load the root of the btree. */ > > > > + level = cur->bc_nlevels - 1; > > > > + cur->bc_ops->init_ptr_from_cur(cur, &ptr); > > > > + error = xfs_btree_lookup_get_block(cur, level, &ptr, &block); > > > > + if (error) > > > > + return error; > > > > + xfs_btree_get_block(cur, level, &bp); > > > > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > > > > +#ifdef DEBUG > > > > + error = xfs_btree_check_block(cur, block, level, bp); > > > > + if (error) > > > > + goto out; > > > > +#endif > > > > + cur->bc_ptrs[level] = 1; > > > > + > > > > + while (level < cur->bc_nlevels) { > > > > + block = XFS_BUF_TO_BLOCK(cur->bc_bufs[level]); > > > > + > > > > + if (level == 0) { > > > > + /* End of leaf, pop back towards the root. */ > > > > + if (cur->bc_ptrs[level] > > > > > + be16_to_cpu(block->bb_numrecs)) { > > > > +leaf_pop_up: > > > > + if (level < cur->bc_nlevels - 1) > > > > + cur->bc_ptrs[level + 1]++; > > > > + level++; > > > > + continue; > > > > + } > > > > + > > > > + recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block); > > > > + > > > > + cur->bc_ops->init_high_key_from_rec(&rec_key, recp); > > > > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, > > > > + &rec_key); > > > > + > > > > + cur->bc_ops->init_key_from_rec(&rec_key, recp); > > > > + hdiff = cur->bc_ops->diff_two_keys(cur, &rec_key, > > > > + &high_key); > > > > + > > > > > > This looked a little funny to me because I expected diff_two_keys() to > > > basically be param1 - param2. Looking ahead at the rmapbt code, it is in > > > fact the other way around. I'm not sure we have precedent for either > > > way, tbh. I still have to stare at this some more, but I wonder if a > > > "does record overlap" helper (with comments) would help clean this up a > > > bit. > > > > You're correct this is exactly the opposite of the compare functions in > > the C library and the rest of the kernel. I'll fix that up. > > > > > > + /* If the record matches, callback */ > > > > + if (ldiff >= 0 && hdiff >= 0) { > > > > Ok, I'll make it a little clearer what we're testing here: > > > > /* > > * If (record's high key >= query's low key) and > > * (query's high key >= record's low key), then > > * this record overlaps the query range, so callback. > > */ > > > > > > > > + error = fn(cur, recp, priv); > > > > + if (error < 0 || > > > > + error == XFS_BTREE_QUERY_RANGE_ABORT) > > > > + break; > > > > + } else if (hdiff < 0) { > > > > + /* Record is larger than high key; pop. */ > > > > + goto leaf_pop_up; > > > > + } > > > > + cur->bc_ptrs[level]++; > > > > + continue; > > > > + } > > > > + > > > > + /* End of node, pop back towards the root. */ > > > > + if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) { > > > > +node_pop_up: > > > > + if (level < cur->bc_nlevels - 1) > > > > + cur->bc_ptrs[level + 1]++; > > > > + level++; > > > > + continue; > > > > > > Looks like same code as leaf_pop_up. I wonder if we can bury this at the > > > end of the loop with a common label. > > > > Yep. > > > > > > + } > > > > + > > > > + lkp = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block); > > > > + hkp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block); > > > > + pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block); > > > > + > > > > + ldiff = cur->bc_ops->diff_two_keys(cur, &low_key, hkp); > > > > + hdiff = cur->bc_ops->diff_two_keys(cur, lkp, &high_key); > > > > + > > > > + /* If the key matches, drill another level deeper. */ > > > > + if (ldiff >= 0 && hdiff >= 0) { > > > > + level--; > > > > + error = xfs_btree_lookup_get_block(cur, level, pp, > > > > + &block); > > > > + if (error) > > > > + goto out; > > > > + xfs_btree_get_block(cur, level, &bp); > > > > + trace_xfs_btree_overlapped_query_range(cur, level, bp); > > > > +#ifdef DEBUG > > > > + error = xfs_btree_check_block(cur, block, level, bp); > > > > + if (error) > > > > + goto out; > > > > +#endif > > > > + cur->bc_ptrs[level] = 1; > > > > + continue; > > > > + } else if (hdiff < 0) { > > > > + /* The low key is larger than the upper range; pop. */ > > > > + goto node_pop_up; > > > > + } > > > > + cur->bc_ptrs[level]++; > > > > + } > > > > + > > > > +out: > > > > + /* > > > > + * If we don't end this function with the cursor pointing at a record > > > > + * block, a subsequent non-error cursor deletion will not release > > > > + * node-level buffers, causing a buffer leak. This is quite possible > > > > + * with a zero-results range query, so release the buffers if we > > > > + * failed to return any results. > > > > + */ > > > > + if (cur->bc_bufs[0] == NULL) { > > > > + for (i = 0; i < cur->bc_nlevels; i++) { > > > > + if (cur->bc_bufs[i]) { > > > > + xfs_trans_brelse(cur->bc_tp, cur->bc_bufs[i]); > > > > + cur->bc_bufs[i] = NULL; > > > > + cur->bc_ptrs[i] = 0; > > > > + cur->bc_ra[i] = 0; > > > > + } > > > > + } > > > > + } > > > > + > > > > + return error; > > > > +} > > > > + > > > > +/* > > > > + * Query a btree for all records overlapping a given interval of keys. The > > > > + * supplied function will be called with each record found; return one of the > > > > + * XFS_BTREE_QUERY_RANGE_{CONTINUE,ABORT} values or the usual negative error > > > > + * code. This function returns XFS_BTREE_QUERY_RANGE_ABORT, zero, or a > > > > + * negative error code. > > > > + */ > > > > +int > > > > +xfs_btree_query_range( > > > > + struct xfs_btree_cur *cur, > > > > + union xfs_btree_irec *low_rec, > > > > + union xfs_btree_irec *high_rec, > > > > + xfs_btree_query_range_fn fn, > > > > + void *priv) > > > > +{ > > > > + if (!(cur->bc_ops->flags & XFS_BTREE_OPS_OVERLAPPING)) > > > > + return xfs_btree_simple_query_range(cur, low_rec, > > > > + high_rec, fn, priv); > > > > + return xfs_btree_overlapped_query_range(cur, low_rec, high_rec, > > > > + fn, priv); > > > > +} > > > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > > > index a5ec6c7..898fee5 100644 > > > > --- a/fs/xfs/libxfs/xfs_btree.h > > > > +++ b/fs/xfs/libxfs/xfs_btree.h > > > > @@ -206,6 +206,12 @@ struct xfs_btree_ops { > > > > #define LASTREC_DELREC 2 > > > > > > > > > > > > +union xfs_btree_irec { > > > > + xfs_alloc_rec_incore_t a; > > > > + xfs_bmbt_irec_t b; > > > > + xfs_inobt_rec_incore_t i; > > > > +}; > > > > + > > > > > > We might as well kill off the typedef usage here. > > > > Ok. Thx for the review! > > > > --D > > > > > > > > Brian > > > > > > > /* > > > > * Btree cursor structure. > > > > * This collects all information needed by the btree code in one place. > > > > @@ -216,11 +222,7 @@ typedef struct xfs_btree_cur > > > > struct xfs_mount *bc_mp; /* file system mount struct */ > > > > const struct xfs_btree_ops *bc_ops; > > > > uint bc_flags; /* btree features - below */ > > > > - union { > > > > - xfs_alloc_rec_incore_t a; > > > > - xfs_bmbt_irec_t b; > > > > - xfs_inobt_rec_incore_t i; > > > > - } bc_rec; /* current insert/search record value */ > > > > + union xfs_btree_irec bc_rec; /* current insert/search record value */ > > > > struct xfs_buf *bc_bufs[XFS_BTREE_MAXLEVELS]; /* buf ptr per level */ > > > > int bc_ptrs[XFS_BTREE_MAXLEVELS]; /* key/record # */ > > > > __uint8_t bc_ra[XFS_BTREE_MAXLEVELS]; /* readahead bits */ > > > > @@ -494,4 +496,14 @@ xfs_extlen_t xfs_btree_calc_size(struct xfs_mount *mp, uint *limits, > > > > uint xfs_btree_compute_maxlevels(struct xfs_mount *mp, uint *limits, > > > > unsigned long len); > > > > > > > > +/* return codes */ > > > > +#define XFS_BTREE_QUERY_RANGE_CONTINUE 0 /* keep iterating */ > > > > +#define XFS_BTREE_QUERY_RANGE_ABORT 1 /* stop iterating */ > > > > +typedef int (*xfs_btree_query_range_fn)(struct xfs_btree_cur *cur, > > > > + union xfs_btree_rec *rec, void *priv); > > > > + > > > > +int xfs_btree_query_range(struct xfs_btree_cur *cur, > > > > + union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec, > > > > + xfs_btree_query_range_fn fn, void *priv); > > > > + > > > > #endif /* __XFS_BTREE_H__ */ > > > > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > > > > index ffea28c..f0ac9c9 100644 > > > > --- a/fs/xfs/xfs_trace.h > > > > +++ b/fs/xfs/xfs_trace.h > > > > @@ -2218,6 +2218,7 @@ DEFINE_EVENT(xfs_btree_cur_class, name, \ > > > > TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > > > > TP_ARGS(cur, level, bp)) > > > > DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > > > > +DEFINE_BTREE_CUR_EVENT(xfs_btree_overlapped_query_range); > > > > > > > > #endif /* _TRACE_XFS_H */ > > > > > > > > > > > > _______________________________________________ > > > > xfs mailing list > > > > xfs@oss.sgi.com > > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Tue Jun 28 11:33:56 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id A31587CA4 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 11:33:56 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 5954B8F8039 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 09:33:56 -0700 (PDT) X-ASG-Debug-ID: 1467131633-04cbb02738302370001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id KyGdmVECabcXo0VJ (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 09:33:53 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5SGXp0c002560 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 16:33:52 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5SGXpmM017946 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 16:33:51 GMT Received: from abhmp0017.oracle.com (abhmp0017.oracle.com [141.146.116.23]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5SGXpKX002470; Tue, 28 Jun 2016 16:33:51 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 09:33:49 -0700 Date: Tue, 28 Jun 2016 09:33:48 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free Message-ID: <20160628163348.GB16181@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 018/119] xfs: enable the xfs_defer mechanism to process extents to free References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612638717.12839.11007379793448761871.stgit@birch.djwong.org> <20160627131508.GC23076@bfoster.bfoster> <20160627214145.GC4921@birch.djwong.org> <20160627220003.GA4917@birch.djwong.org> <20160628123238.GE4212@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20160628123238.GE4212@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467131633 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 8249 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30835 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Tue, Jun 28, 2016 at 08:32:39AM -0400, Brian Foster wrote: > On Mon, Jun 27, 2016 at 03:00:03PM -0700, Darrick J. Wong wrote: > > On Mon, Jun 27, 2016 at 02:41:45PM -0700, Darrick J. Wong wrote: > > > On Mon, Jun 27, 2016 at 09:15:08AM -0400, Brian Foster wrote: > > > > On Thu, Jun 16, 2016 at 06:19:47PM -0700, Darrick J. Wong wrote: > > > > > Connect the xfs_defer mechanism with the pieces that we'll need to > > > > > handle deferred extent freeing. We'll wire up the existing code to > > > > > our new deferred mechanism later. > > > > > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > > > --- > > > > > > > > Could we merge this with the xfs_trans_*efi/efd* bits? We'd need to > > > > preserve some calls for recovery, but it looks like other parts are only > > > > used by the deferred ops infrastructure at this point. > > > > > > Yes, we could replace xfs_bmap_free_create_{intent,done} with > > > xfs_trans_get_ef[id] and lose the silly functions. I'll go take > > > care of all of them. > > > > Hah, gcc complains about the mismatch in pointer types for the second > > argument. > > > > fs/xfs/xfs_defer_item.c:504:17: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types] > > .create_done = xfs_trans_get_bud, > > ^ > > fs/xfs/xfs_defer_item.c:504:17: note: (near initialization for ‘xfs_bmap_update_defer_type.create_done’) > > > > I guess one could put in an ugly cast to coerce the types at a cost of > > uglifying the code. <shrug> Opinions? > > > > Not sure what you mean here... I should be more clear. What I was > thinking is to nuke xfs_defer_item.c, define the 'const struct > xfs_defer_op_type xfs_extent_free_defer_type' right in > xfs_trans_extfree.c (perhaps rename the file) and wire up the functions > appropriately. Just change the function signatures if you need to. For > something like xfs_trans_get_efd(), maybe refactor the guts into a > static helper that both the defer callback and xfs_trans_get_efd() can > use, since we need the latter for log recovery. Will something like that > work? > > To put it simply, it looks like we have at least a few places where > defer item has a callback that calls yet another interface, but is the > only caller of the latter (e.g., > xfs_bmap_free_create_intent()->xfs_trans_get_efi()). *Oh*. Yes, certainly all the stuff in xfs_defer_item.c can be broken up by type and moved into xfs_trans_*.c. The libxfs version will retain libxfs/defer_item.c since the deferred op types there simply call the appropriate libxfs functions without any logging. --D > > Brian > > > --D > > > > > > > > --D > > > > > > > > > > > Brian > > > > > > > > > fs/xfs/libxfs/xfs_defer.h | 1 > > > > > fs/xfs/xfs_defer_item.c | 108 +++++++++++++++++++++++++++++++++++++++++++++ > > > > > 2 files changed, 109 insertions(+) > > > > > > > > > > > > > > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > > > > > index 85c7a3a..743fc32 100644 > > > > > --- a/fs/xfs/libxfs/xfs_defer.h > > > > > +++ b/fs/xfs/libxfs/xfs_defer.h > > > > > @@ -51,6 +51,7 @@ struct xfs_defer_pending { > > > > > * find all the space it needs. > > > > > */ > > > > > enum xfs_defer_ops_type { > > > > > + XFS_DEFER_OPS_TYPE_FREE, > > > > > XFS_DEFER_OPS_TYPE_MAX, > > > > > }; > > > > > > > > > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > > > > > index 4c2ba28..127a54e 100644 > > > > > --- a/fs/xfs/xfs_defer_item.c > > > > > +++ b/fs/xfs/xfs_defer_item.c > > > > > @@ -29,9 +29,117 @@ > > > > > #include "xfs_defer.h" > > > > > #include "xfs_trans.h" > > > > > #include "xfs_trace.h" > > > > > +#include "xfs_bmap.h" > > > > > +#include "xfs_extfree_item.h" > > > > > + > > > > > +/* Extent Freeing */ > > > > > + > > > > > +/* Sort bmap items by AG. */ > > > > > +static int > > > > > +xfs_bmap_free_diff_items( > > > > > + void *priv, > > > > > + struct list_head *a, > > > > > + struct list_head *b) > > > > > +{ > > > > > + struct xfs_mount *mp = priv; > > > > > + struct xfs_bmap_free_item *ra; > > > > > + struct xfs_bmap_free_item *rb; > > > > > + > > > > > + ra = container_of(a, struct xfs_bmap_free_item, xbfi_list); > > > > > + rb = container_of(b, struct xfs_bmap_free_item, xbfi_list); > > > > > + return XFS_FSB_TO_AGNO(mp, ra->xbfi_startblock) - > > > > > + XFS_FSB_TO_AGNO(mp, rb->xbfi_startblock); > > > > > +} > > > > > + > > > > > +/* Get an EFI. */ > > > > > +STATIC void * > > > > > +xfs_bmap_free_create_intent( > > > > > + struct xfs_trans *tp, > > > > > + unsigned int count) > > > > > +{ > > > > > + return xfs_trans_get_efi(tp, count); > > > > > +} > > > > > + > > > > > +/* Log a free extent to the intent item. */ > > > > > +STATIC void > > > > > +xfs_bmap_free_log_item( > > > > > + struct xfs_trans *tp, > > > > > + void *intent, > > > > > + struct list_head *item) > > > > > +{ > > > > > + struct xfs_bmap_free_item *free; > > > > > + > > > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > > > + xfs_trans_log_efi_extent(tp, intent, free->xbfi_startblock, > > > > > + free->xbfi_blockcount); > > > > > +} > > > > > + > > > > > +/* Get an EFD so we can process all the free extents. */ > > > > > +STATIC void * > > > > > +xfs_bmap_free_create_done( > > > > > + struct xfs_trans *tp, > > > > > + void *intent, > > > > > + unsigned int count) > > > > > +{ > > > > > + return xfs_trans_get_efd(tp, intent, count); > > > > > +} > > > > > + > > > > > +/* Process a free extent. */ > > > > > +STATIC int > > > > > +xfs_bmap_free_finish_item( > > > > > + struct xfs_trans *tp, > > > > > + struct xfs_defer_ops *dop, > > > > > + struct list_head *item, > > > > > + void *done_item, > > > > > + void **state) > > > > > +{ > > > > > + struct xfs_bmap_free_item *free; > > > > > + int error; > > > > > + > > > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > > > + error = xfs_trans_free_extent(tp, done_item, > > > > > + free->xbfi_startblock, > > > > > + free->xbfi_blockcount); > > > > > + kmem_free(free); > > > > > + return error; > > > > > +} > > > > > + > > > > > +/* Abort all pending EFIs. */ > > > > > +STATIC void > > > > > +xfs_bmap_free_abort_intent( > > > > > + void *intent) > > > > > +{ > > > > > + xfs_efi_release(intent); > > > > > +} > > > > > + > > > > > +/* Cancel a free extent. */ > > > > > +STATIC void > > > > > +xfs_bmap_free_cancel_item( > > > > > + struct list_head *item) > > > > > +{ > > > > > + struct xfs_bmap_free_item *free; > > > > > + > > > > > + free = container_of(item, struct xfs_bmap_free_item, xbfi_list); > > > > > + kmem_free(free); > > > > > +} > > > > > + > > > > > +const struct xfs_defer_op_type xfs_extent_free_defer_type = { > > > > > + .type = XFS_DEFER_OPS_TYPE_FREE, > > > > > + .max_items = XFS_EFI_MAX_FAST_EXTENTS, > > > > > + .diff_items = xfs_bmap_free_diff_items, > > > > > + .create_intent = xfs_bmap_free_create_intent, > > > > > + .abort_intent = xfs_bmap_free_abort_intent, > > > > > + .log_item = xfs_bmap_free_log_item, > > > > > + .create_done = xfs_bmap_free_create_done, > > > > > + .finish_item = xfs_bmap_free_finish_item, > > > > > + .cancel_item = xfs_bmap_free_cancel_item, > > > > > +}; > > > > > + > > > > > +/* Deferred Item Initialization */ > > > > > > > > > > /* Initialize the deferred operation types. */ > > > > > void > > > > > xfs_defer_init_types(void) > > > > > { > > > > > + xfs_defer_init_op_type(&xfs_extent_free_defer_type); > > > > > } > > > > > > > > > > _______________________________________________ > > > > > xfs mailing list > > > > > xfs@oss.sgi.com > > > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > > > _______________________________________________ > > > xfs mailing list > > > xfs@oss.sgi.com > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From elizabethnuru3@gmail.com Tue Jun 28 12:01:11 2016 Return-Path: <elizabethnuru3@gmail.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_MESSAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 5D1917CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 12:01:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id B7C15AC003 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 10:01:07 -0700 (PDT) X-ASG-Debug-ID: 1467133262-04cbb02736304ab0001-NocioJ Received: from nh603-vm7.bullet.mail.ssk.yahoo.co.jp (nh603-vm7.bullet.mail.ssk.yahoo.co.jp [182.22.90.48]) by cuda.sgi.com with SMTP id DbV8cVI1avPFX5FJ for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 10:01:03 -0700 (PDT) X-Barracuda-Envelope-From: elizabethnuru3@gmail.com X-Barracuda-Effective-Source-IP: nh603-vm7.bullet.mail.ssk.yahoo.co.jp[182.22.90.48] X-Barracuda-Apparent-Source-IP: 182.22.90.48 Received: from [182.22.66.106] by nh603.bullet.mail.ssk.yahoo.co.jp with NNFMP; 28 Jun 2016 17:01:02 -0000 Received: from [182.22.91.129] by t604.bullet.mail.ssk.yahoo.co.jp with NNFMP; 28 Jun 2016 17:01:02 -0000 Received: from [127.0.0.1] by omp602.mail.ssk.yahoo.co.jp with NNFMP; 28 Jun 2016 17:01:02 -0000 X-Yahoo-Newman-Property: ymail-3 X-Yahoo-Newman-Id: 284886.69547.bm@omp602.mail.ssk.yahoo.co.jp Received: (qmail 63343 invoked by uid 60001); 28 Jun 2016 17:01:01 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=yj20050223; d=yahoo.co.jp; h=Message-ID:X-YMail-OSG:Received:X-RocketYMMF:X-Mailer:X-YMail-JAS:Sender:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type; b=euZE7qCXRA73pcapUe0CIeuvlnh+yYxYL+7ESAPfNd8Lpp11dubD/0w8/oVNUHyk/QTMMed9AOxov+LQOFQduG9M6zXWvTKG8YsQ64p5p7aoJ+IwANQICelvyBm59gvE ; Message-ID: <679645.41844.qm@web101520.mail.kks.yahoo.co.jp> X-YMail-OSG: Pp0HlbIVM1l0.3tghe11w3isYcqYC9uBmOiTdqs.wGaikJHg53JgVHDTjDsYHhFxb1YJyDgbhGK3mM2xJzwtMTySN8HoBxIjvwc16Pum5jbvHPOE5mMLE1f4PWTYqgCfAknlZ9UyNzI9vubpQBzXcX26SsxTHjBpLtWP5O01BSBX3HEQ6qSrDtlXqR6mqtqg.PFlM6F8Vs2wy5lsYEb3iMwD_LeGCiAmWjwJqVCHKx3_h8hWC6yR_7IEA9vWUjqYJbENA7fZl1.EwDEHczGtDRukKBk3DDRlIMeu0M1Hls170uxBYJnOWKwxvS2qP7OfyJz.QUOCjnrRvgnufPlmU_V6.OytCBY_n4e.tr3Ez0D8T7Lc8KrvFLnT6ptrfyw5ep_J8IP0O7yF7N2bJV9g8mQIsqmerAXSnPZPT60k292b2wXB.7FcBog6qaa5ai1bQ9nsgd7yO6AirRfcmvBTGVwQW3ViZUT0Ub5kfMjg7DHCIuCZMnaBMGLFgc1kZ8JD2lbi1vVJpOz7S.6thmCRodo41Env1NqYafUiS9hH6Yb9LpnO Received: from [37.130.229.149] by web101520.mail.kks.yahoo.co.jp via HTTP; Wed, 29 Jun 2016 02:01:01 JST X-RocketYMMF: personal_aid10 X-Mailer: YahooMailWebService/0.8.111_69 X-YMail-JAS: 9Rdsa.AVM1m660tqPCbkd8u.vx9LhSloeIIHEgd2gPp8DPoLYL3BR.t4a5AJfXs_iQWag_6ibaZD8STFyL8vP7kw4KjJi4CmdXaXN2BMtVf3lXwa1gcW10Dt67us7DQjYaVt Sender: personal_aid10@yahoo.co.jp Date: Wed, 29 Jun 2016 02:01:01 +0900 (JST) From: Elizabet Hnuru <elizabethnuru3@gmail.com> Reply-To: Elizabet Hnuru <elizabethnuru3@gmail.com> Subject: Hi, I ask your help in the transfer and investment of funds, i want you in the capacity of the fund manager. Regards, Elisabeth. To: undisclosed recipients: ; X-ASG-Orig-Subj: Hi, I ask your help in the transfer and investment of funds, i want you in the capacity of the fund manager. Regards, Elisabeth. MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="1501132162-1717057604-1467133261=:41844" X-Barracuda-Connect: nh603-vm7.bullet.mail.ssk.yahoo.co.jp[182.22.90.48] X-Barracuda-Start-Time: 1467133263 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 134 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.00 X-Barracuda-Spam-Status: No, SCORE=2.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA643_EMP_2, DKIM_SIGNED, DKIM_VERIFIED, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30836 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 HTML_MESSAGE BODY: HTML included in message 2.00 BSF_SC0_SA643_EMP_2 Custom Rule SA643_EMP_2 --1501132162-1717057604-1467133261=:41844 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable =0A --1501132162-1717057604-1467133261=:41844 Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable <html><body><div style=3D"color:; background-color:; font-family:MS PGothic= , sans-serif;font-size:12pt"><div></div></div></body></html> --1501132162-1717057604-1467133261=:41844-- From darrick.wong@oracle.com Tue Jun 28 12:37:12 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 206527CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 12:37:12 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9CF90AC001 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 10:37:08 -0700 (PDT) X-ASG-Debug-ID: 1467135423-04bdf074b719d0c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id oxMteaGtgDuCCvdx (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 10:37:04 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5SHb0AB022346 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 17:37:00 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5SHaxlh018225 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 17:37:00 GMT Received: from abhmp0007.oracle.com (abhmp0007.oracle.com [141.146.116.13]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5SHaxRR032444; Tue, 28 Jun 2016 17:36:59 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 10:36:58 -0700 Date: Tue, 28 Jun 2016 10:36:57 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys Message-ID: <20160628173657.GC16181@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 013/119] xfs: support btrees with overlapping intervals for keys References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612635526.12839.13865365567940815077.stgit@birch.djwong.org> <20160622151706.GB5423@bfoster.bfoster> <20160628032621.GB4917@birch.djwong.org> <20160628123203.GB4212@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160628123203.GB4212@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467135424 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17813 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30837 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Tue, Jun 28, 2016 at 08:32:04AM -0400, Brian Foster wrote: > On Mon, Jun 27, 2016 at 08:26:21PM -0700, Darrick J. Wong wrote: > > On Wed, Jun 22, 2016 at 11:17:06AM -0400, Brian Foster wrote: > > > On Thu, Jun 16, 2016 at 06:19:15PM -0700, Darrick J. Wong wrote: > > > > On a filesystem with both reflink and reverse mapping enabled, it's > > > > possible to have multiple rmap records referring to the same blocks on > > > > disk. When overlapping intervals are possible, querying a classic > > > > btree to find all records intersecting a given interval is inefficient > > > > because we cannot use the left side of the search interval to filter > > > > out non-matching records the same way that we can use the existing > > > > btree key to filter out records coming after the right side of the > > > > search interval. This will become important once we want to use the > > > > rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl. > > > > > > > > (For the non-overlapping case, we can perform such queries trivially > > > > by starting at the left side of the interval and walking the tree > > > > until we pass the right side.) > > > > > > > > Therefore, extend the btree code to come closer to supporting > > > > intervals as a first-class record attribute. This involves widening > > > > the btree node's key space to store both the lowest key reachable via > > > > the node pointer (as the btree does now) and the highest key reachable > > > > via the same pointer and teaching the btree modifying functions to > > > > keep the highest-key records up to date. > > > > > > > > This behavior can be turned on via a new btree ops flag so that btrees > > > > that cannot store overlapping intervals don't pay the overhead costs > > > > in terms of extra code and disk format changes. > > > > > > > > v2: When we're deleting a record in a btree that supports overlapped > > > > interval records and the deletion results in two btree blocks being > > > > joined, we defer updating the high/low keys until after all possible > > > > joining (at higher levels in the tree) have finished. At this point, > > > > the btree pointers at all levels have been updated to remove the empty > > > > blocks and we can update the low and high keys. > > > > > > > > When we're doing this, we must be careful to update the keys of all > > > > node pointers up to the root instead of stopping at the first set of > > > > keys that don't need updating. This is because it's possible for a > > > > single deletion to cause joining of multiple levels of tree, and so > > > > we need to update everything going back to the root. > > > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > > --- > > > > > > I think I get the gist of this and it mostly looks Ok to me. A few > > > questions and minor comments... > > > > Ok. > > > > > > fs/xfs/libxfs/xfs_btree.c | 379 +++++++++++++++++++++++++++++++++++++++++---- > > > > fs/xfs/libxfs/xfs_btree.h | 16 ++ > > > > fs/xfs/xfs_trace.h | 36 ++++ > > > > 3 files changed, 395 insertions(+), 36 deletions(-) > > > > > > > > > > > > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > > > > index a096539..afcafd6 100644 > > > > --- a/fs/xfs/libxfs/xfs_btree.c > > > > +++ b/fs/xfs/libxfs/xfs_btree.c > ... > > > > @@ -2149,7 +2392,9 @@ xfs_btree_lshift( > > > > rkp = &key; > > > > } > > > > > > > > - /* Update the parent key values of right. */ > > > > + /* Update the parent key values of left and right. */ > > > > + xfs_btree_sibling_updkeys(cur, level, XFS_BB_LEFTSIB, left, lbp); > > > > + xfs_btree_updkeys(cur, level); > > > > error = xfs_btree_updkey(cur, rkp, level + 1); > > > > if (error) > > > > goto error0; > > > > @@ -2321,6 +2566,9 @@ xfs_btree_rshift( > > > > if (error) > > > > goto error1; > > > > > > > > + /* Update left and right parent pointers */ > > > > + xfs_btree_updkeys(cur, level); > > > > + xfs_btree_updkeys(tcur, level); > > > > > > In this case, we grab the last record of the block, increment from there > > > and update using the cursor. This is much more straightforward, imo. > > > Could we use this approach in the left shift case as well? > > > > Yes, I think so. I might have started refactoring btree_sibling_updkeys > > out of existence and got distracted, since there isn't anything that uses > > the RIGHTSIB ptr value. > > > > Ok, I think that would be much cleaner. Done. > > > > error = xfs_btree_updkey(tcur, rkp, level + 1); > > > > if (error) > > > > goto error1; > > > > @@ -2356,7 +2604,7 @@ __xfs_btree_split( > > > > struct xfs_btree_cur *cur, > > > > int level, > > > > union xfs_btree_ptr *ptrp, > > > > - union xfs_btree_key *key, > > > > + struct xfs_btree_double_key *key, > > > > struct xfs_btree_cur **curp, > > > > int *stat) /* success/failure */ > > > > { > > > > @@ -2452,9 +2700,6 @@ __xfs_btree_split( > > > > > > > > xfs_btree_log_keys(cur, rbp, 1, rrecs); > > > > xfs_btree_log_ptrs(cur, rbp, 1, rrecs); > > > > - > > > > - /* Grab the keys to the entries moved to the right block */ > > > > - xfs_btree_copy_keys(cur, key, rkp, 1); > > > > } else { > > > > /* It's a leaf. Move records. */ > > > > union xfs_btree_rec *lrp; /* left record pointer */ > > > > @@ -2465,12 +2710,8 @@ __xfs_btree_split( > > > > > > > > xfs_btree_copy_recs(cur, rrp, lrp, rrecs); > > > > xfs_btree_log_recs(cur, rbp, 1, rrecs); > > > > - > > > > - cur->bc_ops->init_key_from_rec(key, > > > > - xfs_btree_rec_addr(cur, 1, right)); > > > > } > > > > > > > > - > > > > /* > > > > * Find the left block number by looking in the buffer. > > > > * Adjust numrecs, sibling pointers. > > > > @@ -2484,6 +2725,12 @@ __xfs_btree_split( > > > > xfs_btree_set_numrecs(left, lrecs); > > > > xfs_btree_set_numrecs(right, xfs_btree_get_numrecs(right) + rrecs); > > > > > > > > + /* Find the low & high keys for the new block. */ > > > > + if (level > 0) > > > > + xfs_btree_find_node_keys(cur, right, &key->low, &key->high); > > > > + else > > > > + xfs_btree_find_leaf_keys(cur, right, &key->low, &key->high); > > > > + > > > > > > Why not push these into the above if/else where the previous key > > > copy/init calls were removed from? > > > > We don't set bb_numrecs on the right block until the line above the new > > hunk, and the btree_find_*_keys functions require numrecs to be set. > > > > The removed key copy/init calls only looked at keys[1]. > > > > That said, it's trivial to move the set_numrecs calls above the if statement. > > > > Ok, thanks. No need to shuffle it around. I'd suggest a one-liner > comment though so somebody doesn't blindly refactor this down the road. > It also sounds like the find keys functions could use ASSERT() checks > for a sane bb_numrecs. Hmm. I already moved it, oh well. It _does_ make the function less messy, so I'll leave it unless anyone yells. > > > > xfs_btree_log_block(cur, rbp, XFS_BB_ALL_BITS); > > > > xfs_btree_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); > > > > > ... > > > > @@ -3095,8 +3365,24 @@ xfs_btree_insrec( > > > > xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS); > > > > > > > > /* If we inserted at the start of a block, update the parents' keys. */ > > > > > > This comment is associated with the codeblock that has been pushed > > > further down, no? > > > > Correct. I think that got mismerged somewhere along the way. > > > > > > + if (ncur && bp->b_bn != old_bn) { > > > > + /* > > > > + * We just inserted into a new tree block, which means that > > > > + * the key for the block is in nkey, not the tree. > > > > + */ > > > > + if (level == 0) > > > > + xfs_btree_find_leaf_keys(cur, block, &nkey.low, > > > > + &nkey.high); > > > > + else > > > > + xfs_btree_find_node_keys(cur, block, &nkey.low, > > > > + &nkey.high); > > > > + } else { > > > > + /* Updating the left block, do it the standard way. */ > > > > + xfs_btree_updkeys(cur, level); > > > > + } > > > > + > > > > > > Not quite sure I follow the purpose of this hunk. Is this for the case > > > where a btree split occurs, nkey is filled in for the new/right block > > > and then (after nkey is filled in) the new record ends up being added to > > > the new block? If so, what about the case where ncur is not created? > > > (It looks like that's possible from the code, but I could easily be > > > missing some context as to why that's not the case.) > > > > Yes, the first part of the if-else hunk is to fill out nkey when we've > > split a btree block. Now that I look at it again, I think that whole > > weird conditional could be replaced with the same xfs_btree_ptr_is_null() > > check later on. I think it can also be combined with it. This is incorrect. The only time we want to perform the nkey recalculation is in the specific case where we split a btree block and the cursor ends up pointing into the new block for the insertion. We cannot gate the nkey recalc on whether or not &nptr is null, because if we insert into the left block after a split we'll recalculate nkey (the right block's keys) using the left block's data, which is incorrect. We probably want to do the key recalc ahead of calling ->update_lastrec because the callback could modify the cursor. So I'll just leave the code mostly as is, clarify the comments about what we're doing and why, and change the if statement to: if (bp && bp->b_bn != old_bn) Also for some reason I neglected to check the return code from xfs_btree_updkeys, so I will go fix that. At the moment it doesn't matter because updkeys never fails, but I might as well fix it now. > Ok. > > > Commentage for now: > > > > /* > > * If we just inserted a new tree block, we have to find the low > > * and high keys for the new block and arrange to pass them back > > * separately. If we're just updating a block we can use the > > * regular tree update mechanism. > > */ > > > > Couldn't you just point out that nkey may not be coherent with the new > block if the new record was inserted therein..? Yes, that would be less convoluted. Done. :) > > > In any event, I think we could elaborate a bit in the comment on why > > > this is necessary. I'd also move it above the top-level if/else. > > > > > > > if (optr == 1) { > > > > - error = xfs_btree_updkey(cur, key, level + 1); > > > > + error = xfs_btree_updkey(cur, &key->low, level + 1); > > > > if (error) > > > > goto error0; > > > > } > > > > @@ -3147,7 +3433,7 @@ xfs_btree_insert( > > > > union xfs_btree_ptr nptr; /* new block number (split result) */ > > > > struct xfs_btree_cur *ncur; /* new cursor (split result) */ > > > > struct xfs_btree_cur *pcur; /* previous level's cursor */ > > > > - union xfs_btree_key key; /* key of block to insert */ > > > > + struct xfs_btree_double_key key; /* key of block to insert */ > > > > > > Probably should fix up the function param alignment here and the couple > > > other or so places we make this change. > > > > I changed the name to xfs_btree_bigkey, which avoids the alignment problems. > > > > Sounds good. --D > > Brian > > > --D > > > > > > > > Brian > > > > > > > > > > > level = 0; > > > > ncur = NULL; > > > > @@ -3552,6 +3838,7 @@ xfs_btree_delrec( > > > > * If we deleted the leftmost entry in the block, update the > > > > * key values above us in the tree. > > > > */ > > > > + xfs_btree_updkeys(cur, level); > > > > if (ptr == 1) { > > > > error = xfs_btree_updkey(cur, keyp, level + 1); > > > > if (error) > > > > @@ -3882,6 +4169,16 @@ xfs_btree_delrec( > > > > if (level > 0) > > > > cur->bc_ptrs[level]--; > > > > > > > > + /* > > > > + * We combined blocks, so we have to update the parent keys if the > > > > + * btree supports overlapped intervals. However, bc_ptrs[level + 1] > > > > + * points to the old block so that the caller knows which record to > > > > + * delete. Therefore, the caller must be savvy enough to call updkeys > > > > + * for us if we return stat == 2. The other exit points from this > > > > + * function don't require deletions further up the tree, so they can > > > > + * call updkeys directly. > > > > + */ > > > > + > > > > XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); > > > > /* Return value means the next level up has something to do. */ > > > > *stat = 2; > > > > @@ -3907,6 +4204,7 @@ xfs_btree_delete( > > > > int error; /* error return value */ > > > > int level; > > > > int i; > > > > + bool joined = false; > > > > > > > > XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY); > > > > > > > > @@ -3920,8 +4218,17 @@ xfs_btree_delete( > > > > error = xfs_btree_delrec(cur, level, &i); > > > > if (error) > > > > goto error0; > > > > + if (i == 2) > > > > + joined = true; > > > > } > > > > > > > > + /* > > > > + * If we combined blocks as part of deleting the record, delrec won't > > > > + * have updated the parent keys so we have to do that here. > > > > + */ > > > > + if (joined) > > > > + xfs_btree_updkeys_force(cur, 0); > > > > + > > > > if (i == 0) { > > > > for (level = 1; level < cur->bc_nlevels; level++) { > > > > if (cur->bc_ptrs[level] == 0) { > > > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > > > > index b99c018..a5ec6c7 100644 > > > > --- a/fs/xfs/libxfs/xfs_btree.h > > > > +++ b/fs/xfs/libxfs/xfs_btree.h > > > > @@ -126,6 +126,9 @@ struct xfs_btree_ops { > > > > size_t key_len; > > > > size_t rec_len; > > > > > > > > + /* flags */ > > > > + uint flags; > > > > + > > > > /* cursor operations */ > > > > struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); > > > > void (*update_cursor)(struct xfs_btree_cur *src, > > > > @@ -162,11 +165,21 @@ struct xfs_btree_ops { > > > > union xfs_btree_rec *rec); > > > > void (*init_ptr_from_cur)(struct xfs_btree_cur *cur, > > > > union xfs_btree_ptr *ptr); > > > > + void (*init_high_key_from_rec)(union xfs_btree_key *key, > > > > + union xfs_btree_rec *rec); > > > > > > > > /* difference between key value and cursor value */ > > > > __int64_t (*key_diff)(struct xfs_btree_cur *cur, > > > > union xfs_btree_key *key); > > > > > > > > + /* > > > > + * Difference between key2 and key1 -- positive if key2 > key1, > > > > + * negative if key2 < key1, and zero if equal. > > > > + */ > > > > + __int64_t (*diff_two_keys)(struct xfs_btree_cur *cur, > > > > + union xfs_btree_key *key1, > > > > + union xfs_btree_key *key2); > > > > + > > > > const struct xfs_buf_ops *buf_ops; > > > > > > > > #if defined(DEBUG) || defined(XFS_WARN) > > > > @@ -182,6 +195,9 @@ struct xfs_btree_ops { > > > > #endif > > > > }; > > > > > > > > +/* btree ops flags */ > > > > +#define XFS_BTREE_OPS_OVERLAPPING (1<<0) /* overlapping intervals */ > > > > + > > > > /* > > > > * Reasons for the update_lastrec method to be called. > > > > */ > > > > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > > > > index 68f27f7..ffea28c 100644 > > > > --- a/fs/xfs/xfs_trace.h > > > > +++ b/fs/xfs/xfs_trace.h > > > > @@ -38,6 +38,7 @@ struct xlog_recover_item; > > > > struct xfs_buf_log_format; > > > > struct xfs_inode_log_format; > > > > struct xfs_bmbt_irec; > > > > +struct xfs_btree_cur; > > > > > > > > DECLARE_EVENT_CLASS(xfs_attr_list_class, > > > > TP_PROTO(struct xfs_attr_list_context *ctx), > > > > @@ -2183,6 +2184,41 @@ DEFINE_DISCARD_EVENT(xfs_discard_toosmall); > > > > DEFINE_DISCARD_EVENT(xfs_discard_exclude); > > > > DEFINE_DISCARD_EVENT(xfs_discard_busy); > > > > > > > > +/* btree cursor events */ > > > > +DECLARE_EVENT_CLASS(xfs_btree_cur_class, > > > > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), > > > > + TP_ARGS(cur, level, bp), > > > > + TP_STRUCT__entry( > > > > + __field(dev_t, dev) > > > > + __field(xfs_btnum_t, btnum) > > > > + __field(int, level) > > > > + __field(int, nlevels) > > > > + __field(int, ptr) > > > > + __field(xfs_daddr_t, daddr) > > > > + ), > > > > + TP_fast_assign( > > > > + __entry->dev = cur->bc_mp->m_super->s_dev; > > > > + __entry->btnum = cur->bc_btnum; > > > > + __entry->level = level; > > > > + __entry->nlevels = cur->bc_nlevels; > > > > + __entry->ptr = cur->bc_ptrs[level]; > > > > + __entry->daddr = bp->b_bn; > > > > + ), > > > > + TP_printk("dev %d:%d btnum %d level %d/%d ptr %d daddr 0x%llx", > > > > + MAJOR(__entry->dev), MINOR(__entry->dev), > > > > + __entry->btnum, > > > > + __entry->level, > > > > + __entry->nlevels, > > > > + __entry->ptr, > > > > + (unsigned long long)__entry->daddr) > > > > +) > > > > + > > > > +#define DEFINE_BTREE_CUR_EVENT(name) \ > > > > +DEFINE_EVENT(xfs_btree_cur_class, name, \ > > > > + TP_PROTO(struct xfs_btree_cur *cur, int level, struct xfs_buf *bp), \ > > > > + TP_ARGS(cur, level, bp)) > > > > +DEFINE_BTREE_CUR_EVENT(xfs_btree_updkeys); > > > > + > > > > #endif /* _TRACE_XFS_H */ > > > > > > > > #undef TRACE_INCLUDE_PATH > > > > > > > > _______________________________________________ > > > > xfs mailing list > > > > xfs@oss.sgi.com > > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Tue Jun 28 13:52:04 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 843F07CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 13:52:04 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 54E0D30404E for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 11:52:01 -0700 (PDT) X-ASG-Debug-ID: 1467139916-04cbb0273730ddd0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id BuqHzcly4NrqnbD7 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 11:51:57 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5SIptjB019599 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 18:51:55 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5SIpsWe001480 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 18:51:54 GMT Received: from abhmp0018.oracle.com (abhmp0018.oracle.com [141.146.116.24]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5SIpqmq011719; Tue, 28 Jun 2016 18:51:53 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 11:51:51 -0700 Date: Tue, 28 Jun 2016 11:51:50 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Brian Foster <bfoster@redhat.com> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 016/119] xfs: move deferred operations into a separate file Message-ID: <20160628185150.GD16181@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 016/119] xfs: move deferred operations into a separate file References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612637438.12839.12318902006860455847.stgit@birch.djwong.org> <20160627131452.GA23076@bfoster.bfoster> <20160627191401.GA4921@birch.djwong.org> <20160628123232.GD4212@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160628123232.GD4212@bfoster.bfoster> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467139917 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 23352 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30839 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Tue, Jun 28, 2016 at 08:32:32AM -0400, Brian Foster wrote: > On Mon, Jun 27, 2016 at 12:14:01PM -0700, Darrick J. Wong wrote: > > On Mon, Jun 27, 2016 at 09:14:54AM -0400, Brian Foster wrote: > > > On Thu, Jun 16, 2016 at 06:19:34PM -0700, Darrick J. Wong wrote: > > > > All the code around struct xfs_bmap_free basically implements a > > > > deferred operation framework through which we can roll transactions > > > > (to unlock buffers and avoid violating lock order rules) while > > > > managing all the necessary log redo items. Previously we only used > > > > this code to free extents after some sort of mapping operation, but > > > > with the advent of rmap and reflink, we suddenly need to do more than > > > > that. > > > > > > > > With that in mind, xfs_bmap_free really becomes a deferred ops control > > > > structure. Rename the structure and move the deferred ops into their > > > > own file to avoid further bloating of the bmap code. > > > > > > > > v2: actually sort the work items by AG to avoid deadlocks > > > > > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > > > --- > > > > > > So if I'm following this correctly, we 1.) abstract the bmap freeing > > > infrastructure into a generic mechanism and 2.) enhance it a bit to > > > provide things like partial intent completion, etc. > > > > [Back from vacation] > > > > Yup. The partial intent completion code is for use by the refcount adjust > > function because in the worst case an adjustment of N blocks could require > > N record updates. > > > > Ok, technically those bits could be punted off to the reflink series. > > > > If so and for future > > > reference, this would probably be easier to review if the abstraction > > > and enhancement were done separately. It's probably not worth that at > > > this point, however... > > > > It wouldn't be difficult to separate them; the partial intent completion > > are the two code blocks below that handle the -EAGAIN case. > > > > That's kind of what I figured, since otherwise most of the rest of the > code maps to the xfs_bmap_*() stuff. > > > (On the other hand it's so little code that I figured I might as well > > just do the whole file all at once.) > > > > It's more a matter of simplifying review when a change is explicitly > refactoring vs. having to read through and identify where the > enhancements actually are. It leaves a cleaner git history and tends to > simplify backporting as well, fwiw. Point taken, the new functionality could be a separate patch. Or rather, the two chunks of code and a gigantic comment explaining how it should be used will become a separate patch. > That said, I don't mind leaving this one as is at this point. > > > > > fs/xfs/Makefile | 2 > > > > fs/xfs/libxfs/xfs_defer.c | 471 +++++++++++++++++++++++++++++++++++++++++++++ > > > > fs/xfs/libxfs/xfs_defer.h | 96 +++++++++ > > > > fs/xfs/xfs_defer_item.c | 36 +++ > > > > fs/xfs/xfs_super.c | 2 > > > > 5 files changed, 607 insertions(+) > > > > create mode 100644 fs/xfs/libxfs/xfs_defer.c > > > > create mode 100644 fs/xfs/libxfs/xfs_defer.h > > > > create mode 100644 fs/xfs/xfs_defer_item.c > > > > > > > > > > > > diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile > > > > index 3542d94..ad46a2d 100644 > > > > --- a/fs/xfs/Makefile > > > > +++ b/fs/xfs/Makefile > > > > @@ -39,6 +39,7 @@ xfs-y += $(addprefix libxfs/, \ > > > > xfs_btree.o \ > > > > xfs_da_btree.o \ > > > > xfs_da_format.o \ > > > > + xfs_defer.o \ > > > > xfs_dir2.o \ > > > > xfs_dir2_block.o \ > > > > xfs_dir2_data.o \ > > > > @@ -66,6 +67,7 @@ xfs-y += xfs_aops.o \ > > > > xfs_attr_list.o \ > > > > xfs_bmap_util.o \ > > > > xfs_buf.o \ > > > > + xfs_defer_item.o \ > > > > xfs_dir2_readdir.o \ > > > > xfs_discard.o \ > > > > xfs_error.o \ > > > > diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c > > > > new file mode 100644 > > > > index 0000000..ad14e33e > > > > --- /dev/null > > > > +++ b/fs/xfs/libxfs/xfs_defer.c > ... > > > > +int > > > > +xfs_defer_finish( > > > > + struct xfs_trans **tp, > > > > + struct xfs_defer_ops *dop, > > > > + struct xfs_inode *ip) > > > > +{ > > > > + struct xfs_defer_pending *dfp; > > > > + struct list_head *li; > > > > + struct list_head *n; > > > > + void *done_item = NULL; > > > > + void *state; > > > > + int error = 0; > > > > + void (*cleanup_fn)(struct xfs_trans *, void *, int); > > > > + > > > > + ASSERT((*tp)->t_flags & XFS_TRANS_PERM_LOG_RES); > > > > + > > > > + /* Until we run out of pending work to finish... */ > > > > + while (xfs_defer_has_unfinished_work(dop)) { > > > > + /* Log intents for work items sitting in the intake. */ > > > > + xfs_defer_intake_work(*tp, dop); > > > > + > > > > + /* Roll the transaction. */ > > > > + error = xfs_defer_trans_roll(tp, dop, ip); > > > > + if (error) > > > > + goto out; > > > > + > > > > + /* Mark all pending intents as committed. */ > > > > + list_for_each_entry_reverse(dfp, &dop->dop_pending, dfp_list) { > > > > + if (dfp->dfp_committed) > > > > + break; > > > > + dfp->dfp_committed = true; > > > > + } > > > > + > > > > + /* Log an intent-done item for the first pending item. */ > > > > + dfp = list_first_entry(&dop->dop_pending, > > > > + struct xfs_defer_pending, dfp_list); > > > > + done_item = dfp->dfp_type->create_done(*tp, dfp->dfp_intent, > > > > + dfp->dfp_count); > > > > + cleanup_fn = dfp->dfp_type->finish_cleanup; > > > > + > > > > + /* Finish the work items. */ > > > > + state = NULL; > > > > + list_for_each_safe(li, n, &dfp->dfp_work) { > > > > + list_del(li); > > > > + dfp->dfp_count--; > > > > + error = dfp->dfp_type->finish_item(*tp, dop, li, > > > > + done_item, &state); > > > > + if (error == -EAGAIN) { > > > > + /* > > > > + * If the caller needs to try again, put the > > > > + * item back on the pending list and jump out > > > > + * for further processing. > > > > > > A little confused by the terminology here. Perhaps better to say "back > > > on the work list" rather than "pending list?" > > > > Yes. > > > > > Also, what is the meaning/purpose of -EAGAIN here? This isn't used by > > > the extent free bits so I'm missing some context. > > > > Generally, the ->finish_item() uses -EAGAIN to signal that it couldn't finish > > the work item and that it's necessary to log a new redo item and try again. > > > > Ah, Ok. So it is explicitly part of the dfops interface/infrastructure. > I think that is worth documenting above with a comment (i.e., "certain > callers might require many transactions, use -EAGAIN to indicate ... > blah blah"). > > > Practically, the only user of this mechanism is the refcountbt adjust function. > > It might be the case that we want to adjust N blocks, but some pathological > > user has creatively used reflink to create many refcount records. In that > > case we could blow out the transaction reservation logging all the updates. > > > > To avoid that, the refcount code tries to guess (conservatively) when it > > might be getting close and returns a short *adjusted. See the call sites of > > xfs_refcount_still_have_space(). Next, xfs_trans_log_finish_refcount_update() > > will notice the short adjust returned and fixes up the CUD item to have a > > reduced cud_nextents and to reflect where the operation stopped. Then, > > xfs_refcount_update_finish_item() notices the short return, updates the work > > item list, and returns -EAGAIN. Finally, xfs_defer_finish() sees the -EAGAIN > > and requeues the work item so that we resume refcount adjusting after the > > transaction rolls. > > > > Hmm, this makes me think that maybe it is better to split this up into > two patches for now after all. I'm expecting this is going to be merged > along with the rmap bits before the refcount stuff and I'm not a huge > fan of putting in infrastructure code without users, moreso without > fully understanding how/why said code is going to be used (and I'm not > really looking to jump ahead into the refcount stuff yet). <nod> > > > For example, is there > > > an issue with carrying a done_item with an unexpected list count? > > > > AFAICT, nothing in log recovery ever checks that the list counts of the > > intent and done items actually match, let alone the extents logged with > > them. It only seems to care if there's an efd such that efd->efd_efi_id == > > efi->efi_id, in which case it won't replay the efi. > > > > Yeah, I didn't notice any issues with respect to EFI/EFD handling, > though I didn't look too hard because it doesn't use this -EAGAIN > mechanism. If it did, I think you might hit the odd ASSERT() check here > or there (see xfs_efd_item_format()), but that's probably not > catastrophic. I think it also affects the size of the transaction > written to the log, fwiw. Yes, xfs_trans_log_finish_refcount_update fixes the list count in the CUD to avoid triggering the ASSERT in xfs_cud_item_format(). > I ask more because it's unexpected to have a structure with a list count > that doesn't match the actual number of items and I don't see it called > out anywhere. This might be another good reason to punt this part off to > the reflink series... > > > I don't know if that was a deliberate part of the log design, but the > > lack of checking helps us here. > > > > > Is it > > > expected that xfs_defer_finish() will not return until -EAGAIN is > > > "cleared" (does relogging below and rolling somehow address this)? > > > > Yes, relogging and rolling gives us a fresh transaction with which to > > continue updating. > > > > > > + */ > > > > + list_add(li, &dfp->dfp_work); > > > > + dfp->dfp_count++; > > > > + break; > > > > + } else if (error) { > > > > + /* > > > > + * Clean up after ourselves and jump out. > > > > + * xfs_defer_cancel will take care of freeing > > > > + * all these lists and stuff. > > > > + */ > > > > + if (cleanup_fn) > > > > + cleanup_fn(*tp, state, error); > > > > + xfs_defer_trans_abort(*tp, dop, error); > > > > + goto out; > > > > + } > > > > + } > > > > + if (error == -EAGAIN) { > > > > + /* > > > > + * Log a new intent, relog all the remaining work > > > > + * item to the new intent, attach the new intent to > > > > + * the dfp, and leave the dfp at the head of the list > > > > + * for further processing. > > > > + */ > > > > > > Similar to the above, could you elaborate on the mechanics of this with > > > respect to the log? E.g., the comment kind of just repeats what the > > > code does as opposed to explain why it's here. Is the point here to log > > > a new intent in the same transaction as the done item to ensure that we > > > (atomically) indicate that certain operations need to be replayed if > > > this transaction hits the log and then we crash? > > > > Yes. > > > > "This effectively replaces the old intent item with a new one listing only > > the work items that were not completed when ->finish_item() returned -EAGAIN. > > After the subsequent transaction roll, we'll resume where we left off with a > > fresh transaction." > > > > I'd point out the relevance of doing so in the same transaction, > otherwise sounds good. Ok. --D > > Brian > > > Thank you for the review! > > > > --D > > > > > Brian > > > > > > > + dfp->dfp_intent = dfp->dfp_type->create_intent(*tp, > > > > + dfp->dfp_count); > > > > + list_for_each(li, &dfp->dfp_work) > > > > + dfp->dfp_type->log_item(*tp, dfp->dfp_intent, > > > > + li); > > > > + } else { > > > > + /* Done with the dfp, free it. */ > > > > + list_del(&dfp->dfp_list); > > > > + kmem_free(dfp); > > > > + } > > > > + > > > > + if (cleanup_fn) > > > > + cleanup_fn(*tp, state, error); > > > > + } > > > > + > > > > +out: > > > > + return error; > > > > +} > > > > + > > > > +/* > > > > + * Free up any items left in the list. > > > > + */ > > > > +void > > > > +xfs_defer_cancel( > > > > + struct xfs_defer_ops *dop) > > > > +{ > > > > + struct xfs_defer_pending *dfp; > > > > + struct xfs_defer_pending *pli; > > > > + struct list_head *pwi; > > > > + struct list_head *n; > > > > + > > > > + /* > > > > + * Free the pending items. Caller should already have arranged > > > > + * for the intent items to be released. > > > > + */ > > > > + list_for_each_entry_safe(dfp, pli, &dop->dop_intake, dfp_list) { > > > > + list_del(&dfp->dfp_list); > > > > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > > > > + list_del(pwi); > > > > + dfp->dfp_count--; > > > > + dfp->dfp_type->cancel_item(pwi); > > > > + } > > > > + ASSERT(dfp->dfp_count == 0); > > > > + kmem_free(dfp); > > > > + } > > > > + list_for_each_entry_safe(dfp, pli, &dop->dop_pending, dfp_list) { > > > > + list_del(&dfp->dfp_list); > > > > + list_for_each_safe(pwi, n, &dfp->dfp_work) { > > > > + list_del(pwi); > > > > + dfp->dfp_count--; > > > > + dfp->dfp_type->cancel_item(pwi); > > > > + } > > > > + ASSERT(dfp->dfp_count == 0); > > > > + kmem_free(dfp); > > > > + } > > > > +} > > > > + > > > > +/* Add an item for later deferred processing. */ > > > > +void > > > > +xfs_defer_add( > > > > + struct xfs_defer_ops *dop, > > > > + enum xfs_defer_ops_type type, > > > > + struct list_head *li) > > > > +{ > > > > + struct xfs_defer_pending *dfp = NULL; > > > > + > > > > + /* > > > > + * Add the item to a pending item at the end of the intake list. > > > > + * If the last pending item has the same type, reuse it. Else, > > > > + * create a new pending item at the end of the intake list. > > > > + */ > > > > + if (!list_empty(&dop->dop_intake)) { > > > > + dfp = list_last_entry(&dop->dop_intake, > > > > + struct xfs_defer_pending, dfp_list); > > > > + if (dfp->dfp_type->type != type || > > > > + (dfp->dfp_type->max_items && > > > > + dfp->dfp_count >= dfp->dfp_type->max_items)) > > > > + dfp = NULL; > > > > + } > > > > + if (!dfp) { > > > > + dfp = kmem_alloc(sizeof(struct xfs_defer_pending), > > > > + KM_SLEEP | KM_NOFS); > > > > + dfp->dfp_type = defer_op_types[type]; > > > > + dfp->dfp_committed = false; > > > > + dfp->dfp_intent = NULL; > > > > + dfp->dfp_count = 0; > > > > + INIT_LIST_HEAD(&dfp->dfp_work); > > > > + list_add_tail(&dfp->dfp_list, &dop->dop_intake); > > > > + } > > > > + > > > > + list_add_tail(li, &dfp->dfp_work); > > > > + dfp->dfp_count++; > > > > +} > > > > + > > > > +/* Initialize a deferred operation list. */ > > > > +void > > > > +xfs_defer_init_op_type( > > > > + const struct xfs_defer_op_type *type) > > > > +{ > > > > + defer_op_types[type->type] = type; > > > > +} > > > > + > > > > +/* Initialize a deferred operation. */ > > > > +void > > > > +xfs_defer_init( > > > > + struct xfs_defer_ops *dop, > > > > + xfs_fsblock_t *fbp) > > > > +{ > > > > + dop->dop_committed = false; > > > > + dop->dop_low = false; > > > > + memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); > > > > + *fbp = NULLFSBLOCK; > > > > + INIT_LIST_HEAD(&dop->dop_intake); > > > > + INIT_LIST_HEAD(&dop->dop_pending); > > > > +} > > > > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > > > > new file mode 100644 > > > > index 0000000..85c7a3a > > > > --- /dev/null > > > > +++ b/fs/xfs/libxfs/xfs_defer.h > > > > @@ -0,0 +1,96 @@ > > > > +/* > > > > + * Copyright (C) 2016 Oracle. All Rights Reserved. > > > > + * > > > > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > > > > + * > > > > + * This program is free software; you can redistribute it and/or > > > > + * modify it under the terms of the GNU General Public License > > > > + * as published by the Free Software Foundation; either version 2 > > > > + * of the License, or (at your option) any later version. > > > > + * > > > > + * This program is distributed in the hope that it would be useful, > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > > + * GNU General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU General Public License > > > > + * along with this program; if not, write the Free Software Foundation, > > > > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > > > + */ > > > > +#ifndef __XFS_DEFER_H__ > > > > +#define __XFS_DEFER_H__ > > > > + > > > > +struct xfs_defer_op_type; > > > > + > > > > +/* > > > > + * Save a log intent item and a list of extents, so that we can replay > > > > + * whatever action had to happen to the extent list and file the log done > > > > + * item. > > > > + */ > > > > +struct xfs_defer_pending { > > > > + const struct xfs_defer_op_type *dfp_type; /* function pointers */ > > > > + struct list_head dfp_list; /* pending items */ > > > > + bool dfp_committed; /* committed trans? */ > > > > + void *dfp_intent; /* log intent item */ > > > > + struct list_head dfp_work; /* work items */ > > > > + unsigned int dfp_count; /* # extent items */ > > > > +}; > > > > + > > > > +/* > > > > + * Header for deferred operation list. > > > > + * > > > > + * dop_low is used by the allocator to activate the lowspace algorithm - > > > > + * when free space is running low the extent allocator may choose to > > > > + * allocate an extent from an AG without leaving sufficient space for > > > > + * a btree split when inserting the new extent. In this case the allocator > > > > + * will enable the lowspace algorithm which is supposed to allow further > > > > + * allocations (such as btree splits and newroots) to allocate from > > > > + * sequential AGs. In order to avoid locking AGs out of order the lowspace > > > > + * algorithm will start searching for free space from AG 0. If the correct > > > > + * transaction reservations have been made then this algorithm will eventually > > > > + * find all the space it needs. > > > > + */ > > > > +enum xfs_defer_ops_type { > > > > + XFS_DEFER_OPS_TYPE_MAX, > > > > +}; > > > > + > > > > +#define XFS_DEFER_OPS_NR_INODES 2 /* join up to two inodes */ > > > > + > > > > +struct xfs_defer_ops { > > > > + bool dop_committed; /* did any trans commit? */ > > > > + bool dop_low; /* alloc in low mode */ > > > > + struct list_head dop_intake; /* unlogged pending work */ > > > > + struct list_head dop_pending; /* logged pending work */ > > > > + > > > > + /* relog these inodes with each roll */ > > > > + struct xfs_inode *dop_inodes[XFS_DEFER_OPS_NR_INODES]; > > > > +}; > > > > + > > > > +void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, > > > > + struct list_head *h); > > > > +int xfs_defer_finish(struct xfs_trans **tp, struct xfs_defer_ops *dop, > > > > + struct xfs_inode *ip); > > > > +void xfs_defer_cancel(struct xfs_defer_ops *dop); > > > > +void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp); > > > > +bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop); > > > > +int xfs_defer_join(struct xfs_defer_ops *dop, struct xfs_inode *ip); > > > > + > > > > +/* Description of a deferred type. */ > > > > +struct xfs_defer_op_type { > > > > + enum xfs_defer_ops_type type; > > > > + unsigned int max_items; > > > > + void (*abort_intent)(void *); > > > > + void *(*create_done)(struct xfs_trans *, void *, unsigned int); > > > > + int (*finish_item)(struct xfs_trans *, struct xfs_defer_ops *, > > > > + struct list_head *, void *, void **); > > > > + void (*finish_cleanup)(struct xfs_trans *, void *, int); > > > > + void (*cancel_item)(struct list_head *); > > > > + int (*diff_items)(void *, struct list_head *, struct list_head *); > > > > + void *(*create_intent)(struct xfs_trans *, uint); > > > > + void (*log_item)(struct xfs_trans *, void *, struct list_head *); > > > > +}; > > > > + > > > > +void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); > > > > +void xfs_defer_init_types(void); > > > > + > > > > +#endif /* __XFS_DEFER_H__ */ > > > > diff --git a/fs/xfs/xfs_defer_item.c b/fs/xfs/xfs_defer_item.c > > > > new file mode 100644 > > > > index 0000000..849088d > > > > --- /dev/null > > > > +++ b/fs/xfs/xfs_defer_item.c > > > > @@ -0,0 +1,36 @@ > > > > +/* > > > > + * Copyright (C) 2016 Oracle. All Rights Reserved. > > > > + * > > > > + * Author: Darrick J. Wong <darrick.wong@oracle.com> > > > > + * > > > > + * This program is free software; you can redistribute it and/or > > > > + * modify it under the terms of the GNU General Public License > > > > + * as published by the Free Software Foundation; either version 2 > > > > + * of the License, or (at your option) any later version. > > > > + * > > > > + * This program is distributed in the hope that it would be useful, > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > > > > + * GNU General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU General Public License > > > > + * along with this program; if not, write the Free Software Foundation, > > > > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > > > > + */ > > > > +#include "xfs.h" > > > > +#include "xfs_fs.h" > > > > +#include "xfs_shared.h" > > > > +#include "xfs_format.h" > > > > +#include "xfs_log_format.h" > > > > +#include "xfs_trans_resv.h" > > > > +#include "xfs_bit.h" > > > > +#include "xfs_sb.h" > > > > +#include "xfs_mount.h" > > > > +#include "xfs_defer.h" > > > > +#include "xfs_trans.h" > > > > + > > > > +/* Initialize the deferred operation types. */ > > > > +void > > > > +xfs_defer_init_types(void) > > > > +{ > > > > +} > > > > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c > > > > index 09722a7..bf63f6d 100644 > > > > --- a/fs/xfs/xfs_super.c > > > > +++ b/fs/xfs/xfs_super.c > > > > @@ -46,6 +46,7 @@ > > > > #include "xfs_quota.h" > > > > #include "xfs_sysfs.h" > > > > #include "xfs_ondisk.h" > > > > +#include "xfs_defer.h" > > > > > > > > #include <linux/namei.h> > > > > #include <linux/init.h> > > > > @@ -1850,6 +1851,7 @@ init_xfs_fs(void) > > > > printk(KERN_INFO XFS_VERSION_STRING " with " > > > > XFS_BUILD_OPTIONS " enabled\n"); > > > > > > > > + xfs_defer_init_types(); > > > > xfs_dir_startup(); > > > > > > > > error = xfs_init_zones(); > > > > > > > > _______________________________________________ > > > > xfs mailing list > > > > xfs@oss.sgi.com > > > > http://oss.sgi.com/mailman/listinfo/xfs > > > > _______________________________________________ > > xfs mailing list > > xfs@oss.sgi.com > > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Tue Jun 28 14:13:49 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id EF9807CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 14:13:49 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id C2069304039 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 12:13:46 -0700 (PDT) X-ASG-Debug-ID: 1467141223-04cb6c063f247c10001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id EuO7w3W3cikfTaoH (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 12:13:43 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5SJDACR013697 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 19:13:10 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5SJD8Cp026735 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 19:13:08 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5SJD5S4022505; Tue, 28 Jun 2016 19:13:06 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 12:13:05 -0700 Date: Tue, 28 Jun 2016 12:13:02 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Bart Van Assche <bart.vanassche@gmail.com> Cc: "axboe@kernel.dk" <axboe@kernel.dk>, "linux-block@vger.kernel.org" <linux-block@vger.kernel.org>, "tytso@mit.edu" <tytso@mit.edu>, "martin.petersen@oracle.com" <martin.petersen@oracle.com>, "snitzer@redhat.com" <snitzer@redhat.com>, "linux-api@vger.kernel.org" <linux-api@vger.kernel.org>, "bfoster@redhat.com" <bfoster@redhat.com>, "xfs@oss.sgi.com" <xfs@oss.sgi.com>, "hch@infradead.org" <hch@infradead.org>, "dm-devel@redhat.com" <dm-devel@redhat.com>, "linux-fsdevel@vger.kernel.org" <linux-fsdevel@vger.kernel.org>, Christoph Hellwig <hch@lst.de> Subject: Re: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. Message-ID: <20160628191302.GE16181@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> <146612625412.12764.6647932282740152837.stgit@birch.djwong.org> <7589fc01-a000-a912-f9b5-cf099cc2d27a@acm.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <7589fc01-a000-a912-f9b5-cf099cc2d27a@acm.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467141223 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2941 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30839 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Mon, Jun 20, 2016 at 02:35:29PM +0200, Bart Van Assche wrote: > On 06/17/2016 03:18 AM, Darrick J. Wong wrote: > >Invalidate the page cache (as a regular O_DIRECT write would do) to avoid > >returning stale cache contents at a later time. > > > >v5: Refactor the 4.4 refactoring of the ioctl code into separate functions. > >Split the page invalidation and the new ioctl into separate patches. > > > >Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > >Reviewed-by: Christoph Hellwig <hch@lst.de> > >--- > > block/ioctl.c | 29 +++++++++++++++++++++++------ > > 1 file changed, 23 insertions(+), 6 deletions(-) > > > > > >diff --git a/block/ioctl.c b/block/ioctl.c > >index ed2397f..d001f52 100644 > >--- a/block/ioctl.c > >+++ b/block/ioctl.c > >@@ -225,7 +225,9 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, > > unsigned long arg) > > { > > uint64_t range[2]; > >- uint64_t start, len; > >+ struct address_space *mapping; > >+ uint64_t start, end, len; > >+ int ret; > > > > if (!(mode & FMODE_WRITE)) > > return -EBADF; > >@@ -235,18 +237,33 @@ static int blk_ioctl_zeroout(struct block_device *bdev, fmode_t mode, > > > > start = range[0]; > > len = range[1]; > >+ end = start + len - 1; > > > > if (start & 511) > > return -EINVAL; > > if (len & 511) > > return -EINVAL; > >- start >>= 9; > >- len >>= 9; > >- > >- if (start + len > (i_size_read(bdev->bd_inode) >> 9)) > >+ if (end >= (uint64_t)i_size_read(bdev->bd_inode)) > >+ return -EINVAL; > >+ if (end < start) > > return -EINVAL; > > > >- return blkdev_issue_zeroout(bdev, start, len, GFP_KERNEL, false); > >+ /* Invalidate the page cache, including dirty pages */ > >+ mapping = bdev->bd_inode->i_mapping; > >+ truncate_inode_pages_range(mapping, start, end); > >+ > >+ ret = blkdev_issue_zeroout(bdev, start >> 9, len >> 9, GFP_KERNEL, > >+ false); > >+ if (ret) > >+ return ret; > >+ > >+ /* > >+ * Invalidate again; if someone wandered in and dirtied a page, > >+ * the caller will be given -EBUSY. > >+ */ > >+ return invalidate_inode_pages2_range(mapping, > >+ start >> PAGE_SHIFT, > >+ end >> PAGE_SHIFT); > > } > > Hello Darrick, > > Maybe this has already been discussed, but anyway: in the POSIX spec > (http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html) I > found the following: "This volume of POSIX.1-2008 does not specify behavior > of concurrent writes to a file from multiple processes. Applications should > use some form of concurrency control." > > Do we really need the invalidate_inode_pages2_range() call? It's not strictly necessary. I like the idea of having the kernel bonking userspace when they don't coordinate and collide, but we could just jump out after the blkdev_*() calls and let userspace fend for themselves. :) --D > > Thanks, > > Bart. > From darrick.wong@oracle.com Tue Jun 28 14:20:02 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id BC9067CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 14:20:02 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 3BC61AC004 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 12:19:59 -0700 (PDT) X-ASG-Debug-ID: 1467141595-04cbb0273630f190001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id FfYlQyewwqybNqFb (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 12:19:56 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5SJJVS2021407 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 19:19:32 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5SJJVGh008387 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 28 Jun 2016 19:19:31 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5SJJU84020988; Tue, 28 Jun 2016 19:19:31 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 12:19:30 -0700 Date: Tue, 28 Jun 2016 12:19:29 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Christoph Hellwig <hch@infradead.org> Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 001/119] vfs: fix return type of ioctl_file_dedupe_range Message-ID: <20160628191929.GC4917@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 001/119] vfs: fix return type of ioctl_file_dedupe_range References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612627940.12839.15145788608361492501.stgit@birch.djwong.org> <20160617113223.GA19042@infradead.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160617113223.GA19042@infradead.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467141596 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 627 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30839 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Fri, Jun 17, 2016 at 04:32:23AM -0700, Christoph Hellwig wrote: > On Thu, Jun 16, 2016 at 06:17:59PM -0700, Darrick J. Wong wrote: > > All the VFS functions in the dedupe ioctl path return int status, so > > the ioctl handler ought to as well. > > > > Found by Coverity, CID 1350952. > > > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > > This should go out to Al as a separate patch. I sent it to him back in February, though he hasn't responded. --D > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From security@adminmail.cn Tue Jun 28 18:32:49 2016 Return-Path: <security@adminmail.cn> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=HTML_MESSAGE,T_REMOTE_IMAGE autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 309E17CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 18:32:49 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id D5E35304032 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 16:32:45 -0700 (PDT) X-ASG-Debug-ID: 1467156756-04bdf074b61b7270001-NocioJ Received: from relay2.e-rxplanet.biz (relay2.e-rxplanet.biz [188.40.98.83]) by cuda.sgi.com with ESMTP id imNAJ7gt82ufIUvp for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 16:32:36 -0700 (PDT) X-Barracuda-Envelope-From: security@adminmail.cn X-Barracuda-Effective-Source-IP: relay2.e-rxplanet.biz[188.40.98.83] X-Barracuda-Apparent-Source-IP: 188.40.98.83 Received: from mail.1jobtoday.com (mail.1jobtoday.com [95.211.216.142]) by relay2.e-rxplanet.biz (Postfix) with ESMTP id 1E9201980D67 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 01:36:38 +0200 (CEST) X-Virus-Scanned: amavisd-new at mail.1jobtoday.com Received: from [192.168.43.132] (unknown [197.210.173.64]) by mail.1jobtoday.com (Postfix) with ESMTPSA id DAC6E10047A7 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 00:42:41 +0200 (CEST) Content-Type: multipart/alternative; boundary="===============1953726805==" MIME-Version: 1.0 Subject: =?utf-8?b?6YKu566x5o+Q56S677ya55m75b2V5byC5bi45rS75Yqo?= To: xfs@oss.sgi.com X-ASG-Orig-Subj: =?utf-8?b?6YKu566x5o+Q56S677ya55m75b2V5byC5bi45rS75Yqo?= From: "Mail Admin"<security@adminmail.cn> Date: Wed, 29 Jun 2016 00:32:20 +0200 Message-Id: <20160628224241.DAC6E10047A7@mail.1jobtoday.com> X-Barracuda-Connect: relay2.e-rxplanet.biz[188.40.98.83] X-Barracuda-Start-Time: 1467156756 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 52 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.20 X-Barracuda-Spam-Status: No, SCORE=0.20 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MV0113c, BSF_SC0_SA038b, HTML_MESSAGE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30846 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MV0113c BSF_SC0_MV0113c 0.00 HTML_MESSAGE BODY: HTML included in message 0.20 BSF_SC0_SA038b Custom Rule SA038b You will not see this in a MIME-aware mail reader. --===============1953726805== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body = = =90AE=7BB1=63D0=793A=FF1A=767B=5F55=5F02=5E38=6D3B=52A8 = = = = =4F60=597D xfs@oss.sgi.com, = =770B=6765=FF0C=60A8=7684IP=5730=5740=6539=53D8=4E86=FF0C=522B=4EBA=6B63= =8BD5=56FE=4ECE=5176=4ED6=4F4D=7F6E=8BBF=95EE=60A8=7684=90AE=7BB1=3002=4F46= =662F=FF0C=6211=4EEC=505C=6B62=767B=5F55=5C1D=8BD5=FF0C=4EE5=786E=4FDD=60A8= =7684=90AE=7BB1=5B89=5168=FF0C=8BF7=53C2=89C1=4E0B=9762=7684=5C1D=8BD5=4F4D= =7F6E=7684=8BE6=7EC6=4FE1=606F=3002 =767B=5F55=8BE6=7EC6=4FE1=606F=FF1A= =56FD=5BB6/=5730=533A=FF1A=67EC=57D4=5BE8=FF08KH=FF09=FF0C=4E9A=6D32 IP= =5730=5740=FF1A119.82.253.0 =65E5=671F=FF1A=5468=4E09=FF0C2016=5E746=670829= =65E5=FF08GMT+7=FF09 =5982=679C=4F60=662F=8C01=767B=5F55=4E2A=4EBA=FF0C= =90A3=4E48=4F60=7684=5E10=6237=88AB=56FA=5B9A=5728=4E00=4E2A=FF0C=4F60=53EF= =4EE5=5FFD=7565=6B64=7535=5B50=90AE=4EF6=8B66=62A5=3002=5982=679C=4F60=4E0D= =786E=5B9A=662F=5426=662F=4F60=FF0C=90A3=4E48=6076=610F=7528=6237=53EF=80FD= =5DF2=7ECF=77E5=9053=4F60=7684=5BC6=7801=3002=4E3A=4E86=4FDD=8BC1=60A8=7684= =8D26=6237=5B89=5168=FF0C=6211=4EEC=5F3A=70C8=5EFA=8BAE=60A8=7ACB=5373=66F4= =6539=5BC6=7801=FF0C=5426=5219=4F60=7AD9=5728=6709=4F60=7684=5E10=6237=88AB= =52AB=6301=7684=98CE=9669=3002=60A8=53D1=9001=8FD9=5C01=7535=5B50=90AE=4EF6= =670D=52A1=516C=544A=901A=77E5=60A8=6709=5173=7684=7535=5B50=90AE=4EF6=5E10= =6237=7684=91CD=8981=53D8=66F4=3002 = = = = = =70B9=51FB=6B64=5904=66F4=6539=5BC6=7801 = = = = = =60A8=53EF=80FD=4F1A=88AB=8981=6C42=8F93=5165=8FD9=4E2A=9A8C=8BC1=7801: = = 73919 = =6211=4EEC=53D1=9001=8FD9=5C01=7535=5B50=90AE=4EF6=670D=52A1=516C=544A= =901A=77E5=60A8=6709=5173=7684=7535=5B50=90AE=4EF6=5E10=6237=7684=91CD=8981= =53D8=5316=3002 --===============1953726805== Content-Type: text/html; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Description: Mail message body <HTML><head><meta http-equiv=3D"Content-Type" content=3D"text/html; charset= =3Dutf-8"/></head><BODY>   </TD><TD> = <TABLE style=3D"BORDER-COLLAPSE: collapse" cellSpacing=3D0 cellPadding=3D0 = width=3D"100%"> <TBODY> <TR> <TD style=3D"LINE-HEIGHT: 16px" height=3D16 colSpan=3D3> </TD></TR> <TR> <TD style=3D"HEIGHT: 32px; LINE-HEIGHT: 0px" vAlign=3Dmiddle width=3D32 ali= gn=3Dleft><A style=3D"TEXT-DECORATION: none; COLOR: #3b5998" href=3D"http:/= /cantinhodeamizade.cv/sina" target=3D_blank><IMG style=3D"BORDER-TOP: 0px; = BORDER-RIGHT: 0px; BORDER-BOTTOM: 0px; BORDER-LEFT: 0px" src=3D"https://upl= oad.wikimedia.org/wikipedia/commons/thumb/3/3c/Mail-message-open-alert.svg/= 72px-Mail-message-open-alert.svg.png" width=3D32 height=3D32></A></TD> <TD style=3D"WIDTH: 15px; DISPLAY: block" width=3D15>   </TD> <TD width=3D"100%"><A style=3D"FONT-SIZE: 19px; TEXT-DECORATION: none; FONT= -FAMILY: Helvetica Neue,Helvetica,Lucida Grande,tahoma,verdana,arial,sans-s= erif; COLOR: #3b5998; LINE-HEIGHT: 32px" href=3D"http://cantinhodeamizade.c= v/sina" target=3D_blank>=E9=82=AE=E7=AE=B1=E6=8F=90=E7=A4=BA=EF=BC=9A=E7=99= =BB=E5=BD=95=E5=BC=82=E5=B8=B8=E6=B4=BB=E5=8A=A8</A></TD></TR> <TR style=3D"BORDER-BOTTOM: #e5e5e5 1px solid"> <TD style=3D"LINE-HEIGHT: 16px" height=3D16 colSpan=3D3> </TD></TR></T= BODY></TABLE></TD><TD style=3D"WIDTH: 15px; DISPLAY: block" width=3D"15">&n= bsp;  </TD></TR><TR><TD style=3D"WIDTH: 15px; DISPLAY: block" wid= th=3D"15">   </TD><TD> = <TABLE style=3D"BORDER-COLLAPSE: collapse" cellSpacing=3D0 cellPadding=3D0 = width=3D"100%"> <TBODY> <TR> <TD style=3D"LINE-HEIGHT: 28px" height=3D28> </TD></TR> <TR> <TD><SPAN style=3D"FONT-SIZE: 16px; FONT-FAMILY: Helvetica Neue,Helvetica,L= ucida Grande,tahoma,verdana,arial,sans-serif; COLOR: #141823; LINE-HEIGHT: = 21px">=E4=BD=A0=E5=A5=BD xfs@oss.sgi.com,</SPAN></TD></TR> <TR> <TD style=3D"LINE-HEIGHT: 14px" height=3D14> </TD></TR> <TR> <TD><SPAN style=3D"FONT-SIZE: 16px; FONT-FAMILY: Helvetica Neue,Helvetica,L= ucida Grande,tahoma,verdana,arial,sans-serif; COLOR: #141823; LINE-HEIGHT: = 21px">=E7=9C=8B=E6=9D=A5=EF=BC=8C=E6=82=A8=E7=9A=84IP=E5=9C=B0=E5=9D=80=E6= =94=B9=E5=8F=98=E4=BA=86=EF=BC=8C=E5=88=AB=E4=BA=BA=E6=AD=A3=E8=AF=95=E5=9B= =BE=E4=BB=8E=E5=85=B6=E4=BB=96=E4=BD=8D=E7=BD=AE=E8=AE=BF=E9=97=AE=E6=82=A8= =E7=9A=84=E9=82=AE=E7=AE=B1=E3=80=82=E4=BD=86=E6=98=AF=EF=BC=8C=E6=88=91=E4= =BB=AC=E5=81=9C=E6=AD=A2=E7=99=BB=E5=BD=95=E5=B0=9D=E8=AF=95=EF=BC=8C=E4=BB= =A5=E7=A1=AE=E4=BF=9D=E6=82=A8=E7=9A=84=E9=82=AE=E7=AE=B1=E5=AE=89=E5=85=A8= =EF=BC=8C=E8=AF=B7=E5=8F=82=E8=A7=81=E4=B8=8B=E9=9D=A2=E7=9A=84=E5=B0=9D=E8= =AF=95=E4=BD=8D=E7=BD=AE=E7=9A=84=E8=AF=A6=E7=BB=86=E4=BF=A1=E6=81=AF=E3=80= =82 = <P>=E7=99=BB=E5=BD=95=E8=AF=A6=E7=BB=86=E4=BF=A1=E6=81=AF=EF=BC=9A=E5=9B=BD= =E5=AE=B6/=E5=9C=B0=E5=8C=BA=EF=BC=9A=E6=9F=AC=E5=9F=94=E5=AF=A8=EF=BC=88KH= =EF=BC=89=EF=BC=8C=E4=BA=9A=E6=B4=B2 = <P>IP=E5=9C=B0=E5=9D=80=EF=BC=9A119.82.253.0 = <P>=E6=97=A5=E6=9C=9F=EF=BC=9A=E5=91=A8=E4=B8=89=EF=BC=8C2016=E5=B9=B46=E6= =9C=8829=E6=97=A5=EF=BC=88GMT+7=EF=BC=89 = <P>=E5=A6=82=E6=9E=9C=E4=BD=A0=E6=98=AF=E8=B0=81=E7=99=BB=E5=BD=95=E4=B8=AA= =E4=BA=BA=EF=BC=8C=E9=82=A3=E4=B9=88=E4=BD=A0=E7=9A=84=E5=B8=90=E6=88=B7=E8= =A2=AB=E5=9B=BA=E5=AE=9A=E5=9C=A8=E4=B8=80=E4=B8=AA=EF=BC=8C=E4=BD=A0=E5=8F= =AF=E4=BB=A5=E5=BF=BD=E7=95=A5=E6=AD=A4=E7=94=B5=E5=AD=90=E9=82=AE=E4=BB=B6= =E8=AD=A6=E6=8A=A5=E3=80=82=E5=A6=82=E6=9E=9C=E4=BD=A0=E4=B8=8D=E7=A1=AE=E5= =AE=9A=E6=98=AF=E5=90=A6=E6=98=AF=E4=BD=A0=EF=BC=8C=E9=82=A3=E4=B9=88=E6=81= =B6=E6=84=8F=E7=94=A8=E6=88=B7=E5=8F=AF=E8=83=BD=E5=B7=B2=E7=BB=8F=E7=9F=A5= =E9=81=93=E4=BD=A0=E7=9A=84=E5=AF=86=E7=A0=81=E3=80=82=E4=B8=BA=E4=BA=86=E4= =BF=9D=E8=AF=81=E6=82=A8=E7=9A=84=E8=B4=A6=E6=88=B7=E5=AE=89=E5=85=A8=EF=BC= =8C=E6=88=91=E4=BB=AC=E5=BC=BA=E7=83=88=E5=BB=BA=E8=AE=AE=E6=82=A8=E7=AB=8B= =E5=8D=B3=E6=9B=B4=E6=94=B9=E5=AF=86=E7=A0=81=EF=BC=8C=E5=90=A6=E5=88=99=E4= =BD=A0=E7=AB=99=E5=9C=A8=E6=9C=89=E4=BD=A0=E7=9A=84=E5=B8=90=E6=88=B7=E8=A2= =AB=E5=8A=AB=E6=8C=81=E7=9A=84=E9=A3=8E=E9=99=A9=E3=80=82=E6=82=A8=E5=8F=91= =E9=80=81=E8=BF=99=E5=B0=81=E7=94=B5=E5=AD=90=E9=82=AE=E4=BB=B6=E6=9C=8D=E5= =8A=A1=E5=85=AC=E5=91=8A=E9=80=9A=E7=9F=A5=E6=82=A8=E6=9C=89=E5=85=B3=E7=9A= =84=E7=94=B5=E5=AD=90=E9=82=AE=E4=BB=B6=E5=B8=90=E6=88=B7=E7=9A=84=E9=87=8D= =E8=A6=81=E5=8F=98=E6=9B=B4=E3=80=82</SPAN></P></TD></TR> <TR> <TD style=3D"LINE-HEIGHT: 14px" height=3D14> </TD></TR></TBODY></TABLE= ></TD><TD style=3D"WIDTH: 15px; DISPLAY: block" width=3D"15">  &n= bsp;</TD></TR><TR><TD style=3D"WIDTH: 15px; DISPLAY: block" width=3D"15">&n= bsp;  </TD><TD> = <TABLE style=3D"BORDER-COLLAPSE: collapse" cellSpacing=3D0 cellPadding=3D0 = width=3D"100%"> <TBODY> <TR> <TD style=3D"LINE-HEIGHT: 2px" height=3D2 colSpan=3D3> </TD></TR> <TR> <TD><A style=3D"TEXT-DECORATION: none; COLOR: #3b5998" href=3D"" target=3D_= blank> <TABLE style=3D"BORDER-COLLAPSE: collapse" cellSpacing=3D0 cellPadding=3D0 = width=3D"100%"> <TBODY> <TR> <TD style=3D"BORDER-TOP: #344c80 1px solid; BORDER-RIGHT: #344c80 1px solid= ; BACKGROUND: #4c649b; BORDER-COLLAPSE: collapse; BORDER-BOTTOM: #344c80 1p= x solid; PADDING-BOTTOM: 11px; TEXT-ALIGN: center; PADDING-TOP: 7px; PADDIN= G-LEFT: 16px; BORDER-LEFT: #344c80 1px solid; DISPLAY: block; PADDING-RIGHT= : 16px; border-radius: 2px"><A style=3D"TEXT-DECORATION: none; COLOR: #3b59= 98; DISPLAY: block" href=3D"http://cantinhodeamizade.cv/sina" target=3D_bla= nk> <CENTER><FONT size=3D3><SPAN style=3D"FONT-SIZE: 14px; FONT-FAMILY: Helveti= ca Neue,Helvetica,Lucida Grande,tahoma,verdana,arial,sans-serif; VERTICAL-A= LIGN: middle; WHITE-SPACE: nowrap; FONT-WEIGHT: bold; COLOR: #ffffff; LINE-= HEIGHT: 14px">=E7=82=B9=E5=87=BB=E6=AD=A4=E5=A4=84=E6=9B=B4=E6=94=B9=E5=AF= =86=E7=A0=81   </SPAN></FONT></CENTER></A></TD></TR></TBODY></TAB= LE></A></TD> <TD width=3D"100%"></TD></TR> <TR> <TD style=3D"LINE-HEIGHT: 32px" height=3D32 colSpan=3D3> </TD></TR></T= BODY></TABLE></TD><TD style=3D"WIDTH: 15px; DISPLAY: block" width=3D"15">&n= bsp;  </TD></TR><TR><TD style=3D"WIDTH: 15px; DISPLAY: block" wid= th=3D"15">   </TD><TD> = <TABLE style=3D"BORDER-COLLAPSE: collapse" cellSpacing=3D0 cellPadding=3D0 = width=3D"100%"> <TBODY> <TR> <TD><SPAN style=3D"FONT-SIZE: 16px; FONT-FAMILY: Helvetica Neue,Helvetica,L= ucida Grande,tahoma,verdana,arial,sans-serif; COLOR: #141823; LINE-HEIGHT: = 21px">=E6=82=A8=E5=8F=AF=E8=83=BD=E4=BC=9A=E8=A2=AB=E8=A6=81=E6=B1=82=E8=BE= =93=E5=85=A5=E8=BF=99=E4=B8=AA=E9=AA=8C=E8=AF=81=E7=A0=81:</SPAN></TD></TR> <TR> <TD style=3D"LINE-HEIGHT: 14px" height=3D14> </TD></TR> <TR> <TD><SPAN style=3D"FONT-SIZE: 16px; FONT-FAMILY: Helvetica Neue,Helvetica,L= ucida Grande,tahoma,verdana,arial,sans-serif; COLOR: #141823; LINE-HEIGHT: = 21px"> <CENTER> <TABLE style=3D"BORDER-COLLAPSE: collapse" cellSpacing=3D0 cellPadding=3D0> <TBODY> <TR> <TD style=3D"FONT-SIZE: 11px; BORDER-TOP: #ccc 1px solid; FONT-FAMILY: Luci= daGrande,tahoma,verdana,arial,sans-serif; BORDER-RIGHT: #ccc 1px solid; BOR= DER-BOTTOM: #ccc 1px solid; PADDING-BOTTOM: 10px; PADDING-TOP: 10px; PADDIN= G-LEFT: 10px; BORDER-LEFT: #ccc 1px solid; PADDING-RIGHT: 10px; BACKGROUND-= COLOR: #f2f2f2">73919</TD></TR></TBODY></TABLE></CENTER></SPAN></TD></TR> <TR> <TD style=3D"LINE-HEIGHT: 14px" height=3D14> </TD></TR> <TR> <TD><SPAN style=3D"FONT-SIZE: 14px; FONT-FAMILY: Helvetica Neue,Helvetica,L= ucida Grande,tahoma,verdana,arial,sans-serif; COLOR: #898f9c; LINE-HEIGHT: = 19px">=E6=88=91=E4=BB=AC=E5=8F=91=E9=80=81=E8=BF=99=E5=B0=81=E7=94=B5=E5=AD= =90=E9=82=AE=E4=BB=B6=E6=9C=8D=E5=8A=A1=E5=85=AC=E5=91=8A=E9=80=9A=E7=9F=A5= =E6=82=A8=E6=9C=89=E5=85=B3=E7=9A=84=E7=94=B5=E5=AD=90=E9=82=AE=E4=BB=B6=E5= =B8=90=E6=88=B7=E7=9A=84=E9=87=8D=E8=A6=81=E5=8F=98=E5=8C=96=E3=80=82</SPAN= ></TD></TR></TBODY></TABLE></BODY></HTML> --===============1953726805==-- From darrick.wong@oracle.com Tue Jun 28 22:37:01 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 3C7C87CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 22:37:01 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 0F1C1304048 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 20:36:58 -0700 (PDT) X-ASG-Debug-ID: 1467171412-04cbb02738332d20001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id NiMcxux8bwlD1DNV (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 20:36:53 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5T3ap5m032118 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 29 Jun 2016 03:36:51 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5T3aowr010153 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 29 Jun 2016 03:36:51 GMT Received: from abhmp0003.oracle.com (abhmp0003.oracle.com [141.146.116.9]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5T3aoX1001729; Wed, 29 Jun 2016 03:36:50 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 20:36:49 -0700 Date: Tue, 28 Jun 2016 20:36:48 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: david@fromorbit.com Cc: linux-btrfs@vger.kernel.org, fstests@vger.kernel.org, xfs@oss.sgi.com Subject: [PATCH 21/20] xfs/128: cycle_mount the scratch device, not the test device Message-ID: <20160629033648.GA7108@birch.djwong.org> X-ASG-Orig-Subj: [PATCH 21/20] xfs/128: cycle_mount the scratch device, not the test device References: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612796204.25024.18254357523133394284.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467171413 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1672 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30851 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines This test uses the scratch device, so cycle that, not the test dev. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> --- tests/xfs/128 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/xfs/128 b/tests/xfs/128 index 8758d7e..2e756d5 100755 --- a/tests/xfs/128 +++ b/tests/xfs/128 @@ -66,7 +66,7 @@ _pwrite_byte 0x61 0 $((blks * blksz)) $testdir/file1 >> $seqres.full _cp_reflink $testdir/file1 $testdir/file2 _cp_reflink $testdir/file2 $testdir/file3 _cp_reflink $testdir/file3 $testdir/file4 -_test_cycle_mount +_scratch_cycle_mount free_blocks1=$(stat -f $testdir -c '%f') md5sum $testdir/file1 | _filter_scratch @@ -82,7 +82,7 @@ c04=$(_md5_checksum $testdir/file4) echo "CoW the reflink copies" _pwrite_byte 0x62 $blksz $blksz $testdir/file2 >> $seqres.full _pwrite_byte 0x63 $(( blksz * (blks - 1) )) $blksz $testdir/file3 >> $seqres.full -_test_cycle_mount +_scratch_cycle_mount free_blocks2=$(stat -f $testdir -c '%f') md5sum $testdir/file1 | _filter_scratch @@ -97,11 +97,12 @@ c14=$(_md5_checksum $testdir/file4) echo "Defragment" lsattr -l $testdir/ | _filter_scratch | _filter_spaces +filefrag -v $testdir/file* >> $seqres.full $XFS_FSR_PROG -v -d $testdir/file1 >> $seqres.full $XFS_FSR_PROG -v -d $testdir/file2 >> $seqres.full # fsr probably breaks the link $XFS_FSR_PROG -v -d $testdir/file3 >> $seqres.full # fsr probably breaks the link $XFS_FSR_PROG -v -d $testdir/file4 >> $seqres.full # fsr probably ignores this file -_test_cycle_mount +_scratch_cycle_mount free_blocks3=$(stat -f $testdir -c '%f') md5sum $testdir/file1 | _filter_scratch From darrick.wong@oracle.com Tue Jun 28 23:21:22 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 4B19B7CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 23:21:22 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 0C65F8F8050 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 21:21:18 -0700 (PDT) X-ASG-Debug-ID: 1467174074-04bdf074b51c6670001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id QV5BMD3i26WFpQYI (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 21:21:15 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5T4LAmR021947 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jun 2016 04:21:10 GMT Received: from userv0122.oracle.com (userv0122.oracle.com [156.151.31.75]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5T4L9cZ012594 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jun 2016 04:21:09 GMT Received: from abhmp0014.oracle.com (abhmp0014.oracle.com [141.146.116.20]) by userv0122.oracle.com (8.14.4/8.14.4) with ESMTP id u5T4L8ji018900; Wed, 29 Jun 2016 04:21:08 GMT Received: from localhost (/24.21.211.40) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 21:21:07 -0700 Date: Tue, 28 Jun 2016 21:21:06 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Dave Chinner <david@fromorbit.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH 10/11] xfs: simplify inode reclaim tagging interfaces Message-ID: <20160629042106.GD4917@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 10/11] xfs: simplify inode reclaim tagging interfaces References: <1460525492-1170-1-git-send-email-david@fromorbit.com> <1460525492-1170-11-git-send-email-david@fromorbit.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1460525492-1170-11-git-send-email-david@fromorbit.com> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467174075 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9286 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30853 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Wed, Apr 13, 2016 at 03:31:31PM +1000, Dave Chinner wrote: > From: Dave Chinner <dchinner@redhat.com> > > Inode radix tree tagging for reclaim passes a lot of unnecessary > variables around. Over time the xfs-perag has grown a xfs_mount > backpointer, and an internal agno so we don't need to pass other > variables into the tagging functions to supply this information. > > Rework the functions to pass the minimal variable set required > and simplify the internal logic and flow. > > Signed-off-by: Dave Chinner <dchinner@redhat.com> > --- > fs/xfs/xfs_icache.c | 97 +++++++++++++++++++++++++++-------------------------- > 1 file changed, 49 insertions(+), 48 deletions(-) > > diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c > index a60db43..927e7b0 100644 > --- a/fs/xfs/xfs_icache.c > +++ b/fs/xfs/xfs_icache.c > @@ -37,8 +37,7 @@ > #include <linux/kthread.h> > #include <linux/freezer.h> > > -STATIC void __xfs_inode_clear_reclaim_tag(struct xfs_mount *mp, > - struct xfs_perag *pag, struct xfs_inode *ip); > +STATIC void xfs_inode_clear_reclaim_tag(struct xfs_perag *pag, xfs_ino_t ino); > > /* > * Allocate and initialise an xfs_inode. > @@ -271,7 +270,7 @@ xfs_iget_cache_hit( > */ > ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS; > ip->i_flags |= XFS_INEW; > - __xfs_inode_clear_reclaim_tag(mp, pag, ip); > + xfs_inode_clear_reclaim_tag(pag, ip->i_ino); > inode->i_state = I_NEW; > > ASSERT(!rwsem_is_locked(&ip->i_iolock.mr_lock)); > @@ -768,29 +767,44 @@ xfs_reclaim_worker( > } > > static void > -__xfs_inode_set_reclaim_tag( > +xfs_perag_set_reclaim_tag( > struct xfs_perag *pag, > - struct xfs_inode *ip) > + xfs_ino_t ino) > { > - radix_tree_tag_set(&pag->pag_ici_root, > - XFS_INO_TO_AGINO(ip->i_mount, ip->i_ino), > + struct xfs_mount *mp = pag->pag_mount; > + > + ASSERT(spin_is_locked(&pag->pag_ici_lock)); Hmm. On (only) ppc64, I see the following splat on umount: [ 1598.584616] XFS: Assertion failed: spin_is_locked(&pag->pag_ici_lock), file: /raid/home/djwong/cdev/work/linux-mcsum/fs/xfs/xfs_icache.c, line: 216 [ 1598.584799] ------------[ cut here ]------------ [ 1598.585262] WARNING: CPU: 0 PID: 9144 at /raid/home/djwong/cdev/work/linux-mcsum/fs/xfs/xfs_message.c:105 .asswarn+0x48/0x70 [xfs] [ 1598.585318] Modules linked in: xfs libcrc32c sg sch_fq_codel autofs4 hid_generic usbhid hid xhci_pci xhci_hcd sd_mod [ 1598.585518] CPU: 0 PID: 9144 Comm: umount Tainted: G W 4.7.0-rc5-pcsum #1 [ 1598.585566] task: c000000069621bd0 ti: c000000069668000 task.ti: c000000069668000 [ 1598.585608] NIP: d000000001942658 LR: d000000001942658 CTR: c0000000003e4e30 [ 1598.585651] REGS: c00000006966b300 TRAP: 0700 Tainted: G W (4.7.0-rc5-pcsum) [ 1598.585691] MSR: 800000000282b032 <SF,VEC,VSX,EE,FP,ME,IR,DR,RI> CR: 28242448 XER: 00000000 [ 1598.585854] CFAR: d000000001942374 SOFTE: 1 GPR00: d000000001942658 c00000006966b580 d0000000019ff908 ffffffffffffffea GPR04: 000000000000000a c00000006966b390 00000000000000d1 ffffffffffffffc0 GPR08: 0000000000000000 0000000000000021 00000000ffffffd1 d0000000019b01d0 GPR12: c0000000003e4e30 c00000000fff0000 0000000010110000 c00000007922eb80 GPR16: 0000000040000000 0000000020000000 0000000000000000 c00000007922ebe8 GPR20: 0000000000000004 c00000007922ebd0 c00000006966b9d0 0000000000000001 GPR24: 0000000000600081 c00000007922eb80 c000000069668000 c000000069668000 GPR28: c00000006966b710 d0000000019aef20 d0000000019aee90 00000000000000d8 [ 1598.586844] NIP [d000000001942658] .asswarn+0x48/0x70 [xfs] [ 1598.587242] LR [d000000001942658] .asswarn+0x48/0x70 [xfs] [ 1598.587281] Call Trace: [ 1598.587669] [c00000006966b580] [d000000001942658] .asswarn+0x48/0x70 [xfs] (unreliable) [ 1598.588098] [c00000006966b610] [d00000000192d308] .xfs_perag_clear_reclaim_tag+0x48/0x1a0 [xfs] [ 1598.588597] [c00000006966b6a0] [d00000000192d7a8] .xfs_reclaim_inode+0x2d8/0x600 [xfs] [ 1598.589027] [c00000006966b760] [d00000000192dc8c] .xfs_reclaim_inodes_ag+0x1bc/0x390 [xfs] [ 1598.589451] [c00000006966b960] [d00000000192ff28] .xfs_reclaim_inodes+0x38/0x50 [xfs] [ 1598.589875] [c00000006966b9f0] [d000000001944754] .xfs_unmountfs+0xb4/0x280 [xfs] [ 1598.590297] [c00000006966ba90] [d00000000194cd48] .xfs_fs_put_super+0x48/0xa0 [xfs] [ 1598.590382] [c00000006966bb10] [c0000000002527f8] .generic_shutdown_super+0xb8/0x180 [ 1598.590455] [c00000006966bb90] [c000000000252e18] .kill_block_super+0x38/0xa0 [ 1598.590521] [c00000006966bc20] [c000000000253104] .deactivate_locked_super+0xa4/0xf0 [ 1598.590594] [c00000006966bca0] [c00000000027c73c] .cleanup_mnt+0x5c/0xa0 [ 1598.590671] [c00000006966bd20] [c0000000000a44bc] .task_work_run+0xbc/0x100 [ 1598.590748] [c00000006966bdb0] [c000000000015598] .do_notify_resume+0xf8/0x100 [ 1598.590826] [c00000006966be30] [c0000000000094b0] .ret_from_except_lite+0x5c/0x60 [ 1598.590884] Instruction dump: [ 1598.590942] 7c7d1b78 7c9e2378 7cbf2b78 48000008 e8410028 3d220000 38600000 e889c190 [ 1598.591109] 7fa5eb78 7fc6f378 7fe7fb78 4bfffc5d <0fe00000> 38210090 e8010010 eba1ffe8 [ 1598.591281] ---[ end trace dea443eeb71bd63f ]--- Not sure if it's the rmap/reflink patchset that's to blame, or what. It's kinda late, so I'm going to set this aside for debugging tomorrow. (x64/i386/armhf seem fine for whatever reason) --D > + if (pag->pag_ici_reclaimable++) > + return; > + > + /* propagate the reclaim tag up into the perag radix tree */ > + spin_lock(&mp->m_perag_lock); > + radix_tree_tag_set(&mp->m_perag_tree, pag->pag_agno, > XFS_ICI_RECLAIM_TAG); > + spin_unlock(&mp->m_perag_lock); > > - if (!pag->pag_ici_reclaimable) { > - /* propagate the reclaim tag up into the perag radix tree */ > - spin_lock(&ip->i_mount->m_perag_lock); > - radix_tree_tag_set(&ip->i_mount->m_perag_tree, > - XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), > - XFS_ICI_RECLAIM_TAG); > - spin_unlock(&ip->i_mount->m_perag_lock); > + /* schedule periodic background inode reclaim */ > + xfs_reclaim_work_queue(mp); > > - /* schedule periodic background inode reclaim */ > - xfs_reclaim_work_queue(ip->i_mount); > + trace_xfs_perag_set_reclaim(mp, pag->pag_agno, -1, _RET_IP_); > +} > > - trace_xfs_perag_set_reclaim(ip->i_mount, pag->pag_agno, > - -1, _RET_IP_); > - } > - pag->pag_ici_reclaimable++; > +static void > +xfs_perag_clear_reclaim_tag( > + struct xfs_perag *pag) > +{ > + struct xfs_mount *mp = pag->pag_mount; > + > + ASSERT(spin_is_locked(&pag->pag_ici_lock)); > + if (--pag->pag_ici_reclaimable) > + return; > + > + /* clear the reclaim tag from the perag radix tree */ > + spin_lock(&mp->m_perag_lock); > + radix_tree_tag_clear(&mp->m_perag_tree, pag->pag_agno, > + XFS_ICI_RECLAIM_TAG); > + spin_unlock(&mp->m_perag_lock); > + trace_xfs_perag_clear_reclaim(mp, pag->pag_agno, -1, _RET_IP_); > } > > /* > @@ -800,48 +814,35 @@ __xfs_inode_set_reclaim_tag( > */ > void > xfs_inode_set_reclaim_tag( > - xfs_inode_t *ip) > + struct xfs_inode *ip) > { > - struct xfs_mount *mp = ip->i_mount; > - struct xfs_perag *pag; > + struct xfs_mount *mp = ip->i_mount; > + struct xfs_perag *pag; > > pag = xfs_perag_get(mp, XFS_INO_TO_AGNO(mp, ip->i_ino)); > spin_lock(&pag->pag_ici_lock); > spin_lock(&ip->i_flags_lock); > - __xfs_inode_set_reclaim_tag(pag, ip); > + > + radix_tree_tag_set(&pag->pag_ici_root, XFS_INO_TO_AGINO(mp, ip->i_ino), > + XFS_ICI_RECLAIM_TAG); > + xfs_perag_set_reclaim_tag(pag, ip->i_ino); > __xfs_iflags_set(ip, XFS_IRECLAIMABLE); > + > spin_unlock(&ip->i_flags_lock); > spin_unlock(&pag->pag_ici_lock); > xfs_perag_put(pag); > } > > -STATIC void > -__xfs_inode_clear_reclaim( > - xfs_perag_t *pag, > - xfs_inode_t *ip) > -{ > - pag->pag_ici_reclaimable--; > - if (!pag->pag_ici_reclaimable) { > - /* clear the reclaim tag from the perag radix tree */ > - spin_lock(&ip->i_mount->m_perag_lock); > - radix_tree_tag_clear(&ip->i_mount->m_perag_tree, > - XFS_INO_TO_AGNO(ip->i_mount, ip->i_ino), > - XFS_ICI_RECLAIM_TAG); > - spin_unlock(&ip->i_mount->m_perag_lock); > - trace_xfs_perag_clear_reclaim(ip->i_mount, pag->pag_agno, > - -1, _RET_IP_); > - } > -} > > STATIC void > -__xfs_inode_clear_reclaim_tag( > - xfs_mount_t *mp, > - xfs_perag_t *pag, > - xfs_inode_t *ip) > +xfs_inode_clear_reclaim_tag( > + struct xfs_perag *pag, > + xfs_ino_t ino) > { > radix_tree_tag_clear(&pag->pag_ici_root, > - XFS_INO_TO_AGINO(mp, ip->i_ino), XFS_ICI_RECLAIM_TAG); > - __xfs_inode_clear_reclaim(pag, ip); > + XFS_INO_TO_AGINO(pag->pag_mount, ino), > + XFS_ICI_RECLAIM_TAG); > + xfs_perag_clear_reclaim_tag(pag); > } > > /* > @@ -1032,7 +1033,7 @@ reclaim: > if (!radix_tree_delete(&pag->pag_ici_root, > XFS_INO_TO_AGINO(ip->i_mount, ino))) > ASSERT(0); > - __xfs_inode_clear_reclaim(pag, ip); > + xfs_perag_clear_reclaim_tag(pag); > spin_unlock(&pag->pag_ici_lock); > > /* > -- > 2.7.0 > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From martin.petersen@oracle.com Tue Jun 28 23:58:16 2016 Return-Path: <martin.petersen@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 87C487CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 23:58:16 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4B4898F8037 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 21:58:16 -0700 (PDT) X-ASG-Debug-ID: 1467176292-04cbb027363396c0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id F2PWmZf4EeYopHTt (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 21:58:13 -0700 (PDT) X-Barracuda-Envelope-From: martin.petersen@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5T4vdrW017247 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jun 2016 04:57:40 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by aserv0022.oracle.com (8.13.8/8.13.8) with ESMTP id u5T4vcp3002604 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jun 2016 04:57:39 GMT Received: from abhmp0012.oracle.com (abhmp0012.oracle.com [141.146.116.18]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5T4vVw8023572; Wed, 29 Jun 2016 04:57:36 GMT Received: from ca-mkp.ca.oracle.com (/10.159.214.123) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 21:57:30 -0700 To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: axboe@kernel.dk, hch@infradead.org, tytso@mit.edu, martin.petersen@oracle.com, snitzer@redhat.com, linux-api@vger.kernel.org, bfoster@redhat.com, xfs@oss.sgi.com, linux-block@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, Christoph Hellwig <hch@lst.de> Subject: Re: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. From: "Martin K. Petersen" <martin.petersen@oracle.com> X-ASG-Orig-Subj: Re: [PATCH 1/3] block: invalidate the page cache when issuing BLKZEROOUT. Organization: Oracle Corporation References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> <146612625412.12764.6647932282740152837.stgit@birch.djwong.org> Date: Wed, 29 Jun 2016 00:57:27 -0400 In-Reply-To: <146612625412.12764.6647932282740152837.stgit@birch.djwong.org> (Darrick J. Wong's message of "Thu, 16 Jun 2016 18:17:34 -0700") Message-ID: <yq1shvwsibs.fsf@sermon.lab.mkp.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Source-IP: aserv0022.oracle.com [141.146.126.234] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467176293 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 329 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_DOMAIN_MATCH, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30853 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient Domain >>>>> "Darrick" == Darrick J Wong <darrick.wong@oracle.com> writes: Darrick> Invalidate the page cache (as a regular O_DIRECT write would Darrick> do) to avoid returning stale cache contents at a later time. Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> -- Martin K. Petersen Oracle Linux Engineering From martin.petersen@oracle.com Tue Jun 28 23:58:46 2016 Return-Path: <martin.petersen@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 757807CA1 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 23:58:46 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 37609304048 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 21:58:43 -0700 (PDT) X-ASG-Debug-ID: 1467176320-04bdf074b61c91b0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 3bw9JHbaod2EAau8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 21:58:41 -0700 (PDT) X-Barracuda-Envelope-From: martin.petersen@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5T4wB5o032726 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jun 2016 04:58:12 GMT Received: from userv0121.oracle.com (userv0121.oracle.com [156.151.31.72]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5T4wBxZ023826 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jun 2016 04:58:11 GMT Received: from abhmp0010.oracle.com (abhmp0010.oracle.com [141.146.116.16]) by userv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5T4wAnG023762; Wed, 29 Jun 2016 04:58:10 GMT Received: from ca-mkp.ca.oracle.com (/10.159.214.123) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 28 Jun 2016 21:58:09 -0700 To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: axboe@kernel.dk, hch@infradead.org, tytso@mit.edu, martin.petersen@oracle.com, snitzer@redhat.com, linux-api@vger.kernel.org, bfoster@redhat.com, xfs@oss.sgi.com, linux-block@vger.kernel.org, dm-devel@redhat.com, linux-fsdevel@vger.kernel.org, Christoph Hellwig <hch@lst.de> Subject: Re: [PATCH 2/3] block: require write_same and discard requests align to logical block size From: "Martin K. Petersen" <martin.petersen@oracle.com> X-ASG-Orig-Subj: Re: [PATCH 2/3] block: require write_same and discard requests align to logical block size Organization: Oracle Corporation References: <146612624734.12764.4316680863289411106.stgit@birch.djwong.org> <146612626092.12764.773833541076937471.stgit@birch.djwong.org> Date: Wed, 29 Jun 2016 00:58:06 -0400 In-Reply-To: <146612626092.12764.773833541076937471.stgit@birch.djwong.org> (Darrick J. Wong's message of "Thu, 16 Jun 2016 18:17:41 -0700") Message-ID: <yq1oa6ksiap.fsf@sermon.lab.mkp.net> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467176320 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 544 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.01 X-Barracuda-Spam-Status: No, SCORE=0.01 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, BSF_SC0_SA_TO_FROM_DOMAIN_MATCH, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30853 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines 0.01 BSF_SC0_SA_TO_FROM_DOMAIN_MATCH Sender Domain Matches Recipient Domain >>>>> "Darrick" == Darrick J Wong <darrick.wong@oracle.com> writes: Darrick> Make sure that the offset and length arguments that we're using Darrick> to construct WRITE SAME and DISCARD requests are actually Darrick> aligned to the logical block size. Failure to do this causes Darrick> other errors in other parts of the block layer or the SCSI Darrick> layer because disks don't support partial logical block writes. Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> -- Martin K. Petersen Oracle Linux Engineering From david@fromorbit.com Wed Jun 29 00:08:29 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 52E587CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 00:08:29 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 137C5304048 for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 22:08:25 -0700 (PDT) X-ASG-Debug-ID: 1467176902-04bdf074b51c9d40001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id s45FHwRSZA3EsYwq for <xfs@oss.sgi.com>; Tue, 28 Jun 2016 22:08:22 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2DVLACQVnNXIHvHLHlbgz4iNH2CdoN5nk8CHAaBD4s2hgaCD4F7FwOFeASBNjoTAQEBAQEBAQYBAQEBAQFAQIUpOyQ0BSUDBy2IL6NjoDUOHoVCiiGBfQtAgkcFk06FNYYIiCmPLQKQASABgWoMAYI+KjKJPgEBAQ Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail05.adl6.internode.on.net with ESMTP; 29 Jun 2016 14:38:21 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bI7jY-0002Z5-B8 for xfs@oss.sgi.com; Wed, 29 Jun 2016 15:08:20 +1000 Date: Wed, 29 Jun 2016 15:08:20 +1000 From: Dave Chinner <david@fromorbit.com> To: xfs@oss.sgi.com Subject: [ANNOUNCE] xfsprogs: master branch updated to ee37542 Message-ID: <20160629050820.GO12670@dastard> X-ASG-Orig-Subj: [ANNOUNCE] xfsprogs: master branch updated to ee37542 MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="KR/qxknboQ7+Tpez" Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1467176902 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 871 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30853 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- --KR/qxknboQ7+Tpez Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hi Folks, The xfsprogs repository at: git://oss.sgi.com/xfs/cmds/xfsprogs git://git.kernel.org/pub/scm/fs/xfs/xfsprogs-dev.git has just been updated. The new head of the master branch is commit: ee37542 xfs_repair: don't call xfs_sb_quota_from_disk twice New Commits: Bill O'Donnell (1): [dd36660] xfs_repair: resolve Coverity OVERFLOW_BEFORE_WIDEN Dave Chinner (2): [8730711] libxfs: fix use after from in xfs_trans_roll [3fbf002] libxfs: fix double free in libxfs_alloc_file_space Eric Sandeen (1): [ee37542] xfs_repair: don't call xfs_sb_quota_from_disk twice Code Diffstat: libxfs/trans.c | 4 +++- libxfs/util.c | 4 ---- libxfs/xfs_sb.c | 7 +++++-- repair/sb.c | 4 +--- repair/scan.c | 1 - 5 files changed, 9 insertions(+), 11 deletions(-) --=20 Dave Chinner david@fromorbit.com --KR/qxknboQ7+Tpez Content-Type: application/pgp-signature; name="signature.asc" Content-Description: Digital signature -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAEBAgAGBQJXc1fDAAoJEK3oKUf0dfodzkwP/1aOJN26x7FsD8sfmYyYamxu wTTDSnj9EVAlF2oH+M502c2oHwADHCCdu6YZQS7+TJLGrqk1wPRp8fQlCJDy4IcS TSTV2B4z5trXQKjnzPZZTi6DK/IoOpK+cboc0gLtv50BJOj5tgBOupYoJ7WER2lw Ouj2C1jUU6XdLWtBSsAjZ3QjditLZh4yBc1vV76IvEHYTIwZdjWEu0kpIN5YN3Sd DrNid9T8nHVH8+KUZn4t39jsnt8SpPwG42w4pqaFZcxCIxm4sn23Be86dNdfuVVW /wX55rkHn+UVSQSEixGQkAFjCS56zrFyBraPyUJJlPfe2pkzCbeBFCdQBwoR+t99 0/XRhlGz9PrByHiJR3ZLIAZqLXr+4+RNHWYAX25qXPOmRprQDk9LGqK7Xx54ahfq o8vYsgLrvW5Qo/V/UCWUAsoYGrweGFc5xYAEobNC+bj5rXav3sZj+AXkfc0ZNKBX 8s8zmpHxR/me+ZG40WQAIbghgkTtUbZtqvrSad6x4lcilxkQWiTopEugsvIUoCqW m7DTUEdN/f9SIK5ETwPcseaaiTKmm1t/ruKapwo0FqsVRhQYbWuhJrrQUKZag41u pqqnO/rs6/29pI8GQ0vnxiQGNmojpZmmY7gRXjHxAQDlOwf0yATdD5VouJQoQjLb Wo6gMEezFL3e6WX4ll5p =0P80 -----END PGP SIGNATURE----- --KR/qxknboQ7+Tpez-- From cmaiolino@redhat.com Wed Jun 29 03:31:03 2016 Return-Path: <cmaiolino@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id D0A937CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 03:31:03 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 925EF8F8050 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 01:31:03 -0700 (PDT) X-ASG-Debug-ID: 1467189058-04cbb02737346350001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id xHuixOf8rHB1ytqf (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 01:30:59 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 02A0F7F6A5; Wed, 29 Jun 2016 08:30:58 +0000 (UTC) Received: from redhat.com (unused [10.10.50.36] (may be forged)) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5T8UqQX001363 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 29 Jun 2016 04:30:56 -0400 Date: Wed, 29 Jun 2016 10:30:51 +0200 From: Carlos Maiolino <cmaiolino@redhat.com> To: Eric Sandeen <sandeen@sandeen.net> Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Message-ID: <20160629083051.GC22634@redhat.com> X-ASG-Orig-Subj: Re: [PATCH] xfs_repair: don't call xfs_sb_quota_from_disk twice Mail-Followup-To: Eric Sandeen <sandeen@sandeen.net>, xfs@oss.sgi.com References: <13dd3974-956d-c3af-86ed-f6ce5cc1b996@redhat.com> <20160627094855.GC29774@redhat.com> <5c408cf1-e9fa-8bee-106e-93e553fc98a7@sandeen.net> <20160628085726.GA4397@redhat.com> <c72e1f9a-0f83-aa2b-48f1-bc6deccc6315@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <c72e1f9a-0f83-aa2b-48f1-bc6deccc6315@sandeen.net> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Wed, 29 Jun 2016 08:30:58 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467189058 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4475 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Tue, Jun 28, 2016 at 10:40:31AM -0500, Eric Sandeen wrote: > > > On 6/28/16 3:57 AM, Carlos Maiolino wrote: > > On Mon, Jun 27, 2016 at 10:34:39AM -0500, Eric Sandeen wrote: > >> > >> > >> On 6/27/16 4:48 AM, Carlos Maiolino wrote: > >>> On Fri, Jun 24, 2016 at 04:24:58PM -0500, Eric Sandeen wrote: > >>>> kernel commit 5ef828c4 > >>>> xfs: avoid false quotacheck after unclean shutdown > >>>> > >>>> made xfs_sb_from_disk() also call xfs_sb_quota_from_disk > >>>> by default. > >>>> > >>>> However, when this was merged to libxfs, existing separate > >>>> calls to libxfs_sb_quota_from_disk remained, and calling it > >>>> twice in a row on a V4 superblock leads to issues, because: > >>>> > >>>> > >>>> if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { > >>>> ... > >>>> sbp->sb_pquotino = sbp->sb_gquotino; > >>>> sbp->sb_gquotino = NULLFSINO; > >>>> > >>>> and after the second call, we have set both pquotino and gquotino > >>>> to NULLFSINO. > >>>> > >>>> Fix this by making it safe to call twice, and also remove the extra > >>>> calls to libxfs_sb_quota_from_disk. > >>>> > >>>> This is only spotted when running xfstests with "-m crc=0" because > >>>> the sb_from_disk change came about after V5 became default, and > >>>> the above behavior only exists on a V4 superblock. > >>>> > >>>> Reported-by: Eryu Guan <eguan@redhat.com> > >>>> Signed-off-by: Eric Sandeen <sandeen@redhat.com> > >>>> --- > >>>> > >>>> > >>>> diff --git a/libxfs/xfs_sb.c b/libxfs/xfs_sb.c > >>>> index 45db6ae..44f3e3e 100644 > >>>> --- a/libxfs/xfs_sb.c > >>>> +++ b/libxfs/xfs_sb.c > >>>> @@ -316,13 +316,16 @@ xfs_sb_quota_from_disk(struct xfs_sb *sbp) > >>>> XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD; > >>>> sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD); > >>>> > >>>> - if (sbp->sb_qflags & XFS_PQUOTA_ACCT) { > >>>> + if (sbp->sb_qflags & XFS_PQUOTA_ACCT && > >>>> + sbp->sb_gquotino != NULLFSINO) { > >>> > >>> Although I agree with this check, shouldn't we report some sort of error when it > >>> happens? Once, it's not supposed to happen, and, might be a sign of corruption? > >> > >> I dunno, it would also happen if it gets called twice, which is intentionally > >> made harmless by this change. We don't warn on free(NULL) for example... > >> > > > > Well, I don't 100% agree with not having a warning here, but it doesn't make the > > patch less valuable. > > Thanks Carlos - > > Maybe I don't understand what you want to warn about. > > If we get here with: > > if (sbp->sb_qflags & XFS_PQUOTA_ACCT && > sbp->sb_gquotino != NULLFSINO) { > > that means we have an on-disk super without the pquotino field, > the XFS_PQUOTA_ACCT flag is set, and so the gquotino field was > used for the project quota; this is valid, and there is > nothing to warn about in this case. > > If we get here with: > > if (sbp->sb_qflags & XFS_PQUOTA_ACCT && > sbp->sb_gquotino == NULLFSINO) { > > that means we have an on-disk super without the pquotino field, > the XFS_PQUOTA_ACCT flag is set, and the gquotino was not set > to a valid value. This could happen either from a bad on-disk > value, or it could mean that we called the function twice in a > row. Without maintaining more state, we can't know which, and > warning the user about a programming error wouldn't be helpful. > > Actually, repair already handles this case elsewhere: > > quota_sb_check(xfs_mount_t *mp) > { > /* > * if the sb says we have quotas and we lost both, > * signal a superblock downgrade. that will cause > * the quota flags to get zeroed. (if we only lost > * one quota inode, do nothing and complain later.) > * > * if the sb says we have quotas but we didn't start out > * with any quota inodes, signal a superblock downgrade. > > In the case where quota flags are on but all quota inodes are > zero, it silently clears the quota flags. Whether or not that > should be silent I'm not sure, but I think that is separate > from this patch. > > Thanks, > -Eric Thanks for the great and detailed explanation Eric, I think I was just being too careful about not having a warning there, without completely understand why a warning isn't not necessary there. :) > > > > Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com> -- Carlos From Helen.3@sunny.com Wed Jun 29 03:35:14 2016 Return-Path: <Helen.3@sunny.com> X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id CC5107CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 03:35:13 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 917EF304032 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 01:35:13 -0700 (PDT) X-ASG-Debug-ID: 1467189269-04cbb02738346510001-NocioJ Received: from sunny.com ([180.175.239.15]) by cuda.sgi.com with SMTP id SFsK0as5B7eBAwmQ for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 01:34:29 -0700 (PDT) X-Barracuda-Envelope-From: Helen.3@sunny.com X-Barracuda-Effective-Source-IP: UNKNOWN[180.175.239.15] X-Barracuda-Apparent-Source-IP: 180.175.239.15 Received: from PC-20150326YWGV[127.0.0.1] by PC-20150326YWGV[127.0.0.1] (SMTPD32); Wed, 29 Jun 2016 12:26:13 +0800 From: "kevinzhao@yihuaprinting.com" <kevinzhao@yihuaprinting.com> Subject: Re:badge emblems manufacturer - From Shanghai of China To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re:badge emblems manufacturer - From Shanghai of China Content-Type: multipart/mixed; charset=UTF-8; boundary="VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt" MIME-Version: 1.0 Sender: Helen.3@sunny.com Reply-To: kevinzhao@yihuaprinting.com Date: Wed, 29 Jun 2016 12:26:13 +0800 X-Mailer: Foxmail 6, 13, 102, 15 [cn] X-Barracuda-Connect: UNKNOWN[180.175.239.15] X-Barracuda-Start-Time: 1467189269 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17879 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 2.38 X-Barracuda-Spam-Status: No, SCORE=2.38 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC5_MJ1963, DATE_IN_PAST_03_06, DATE_IN_PAST_03_06_2, HTML_IMAGE_RATIO_02, HTML_MESSAGE, HTTP_ESCAPED_HOST, MIME_HTML_ONLY, MISSING_MID, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30856 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.14 MISSING_MID Missing Message-Id: header 0.01 DATE_IN_PAST_03_06 Date: is 3 to 6 hours before Received: date 0.00 HTTP_ESCAPED_HOST URI: Uses %-escapes inside a URL's hostname 0.00 MIME_HTML_ONLY BODY: Message only has text/html MIME parts 0.55 HTML_IMAGE_RATIO_02 BODY: HTML has a low ratio of text to image area 0.00 HTML_MESSAGE BODY: HTML included in message 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 1.08 DATE_IN_PAST_03_06_2 DATE_IN_PAST_03_06_2 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Message-Id: <20160629083513.09777106C2EC@cuda.sgi.com> This is a multi-part message in MIME format --VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: base64 Content-Disposition: inline PCFET0NUWVBFIEhUTUwgUFVCTElDICItLy9XM0MvL0RURCBIVE1MIDQuMCBUcmFuc2l0aW9uYWwv L0VOIj4NCjxIVE1MPjxIRUFEPg0KPE1FVEEgY29udGVudD0idGV4dC9odG1sOyBjaGFyc2V0PVVU Ri04IiBodHRwLWVxdWl2PWNvbnRlbnQtdHlwZT4NCjxNRVRBIG5hbWU9R0VORVJBVE9SIGNvbnRl bnQ9Ik1TSFRNTCA4LjAwLjc2MDEuMTkwNTgiPjwvSEVBRD4NCjxCT0RZPg0KPERJViANCnN0eWxl PSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAw cHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1B UkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBB RERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsg Rk9OVDogMTRweC8yM3B4IFRhaG9tYSwgQXJpYWw7IFdISVRFLVNQQUNFOiBub3JtYWw7IExFVFRF Ui1TUEFDSU5HOiBub3JtYWw7IENPTE9SOiByZ2IoMCwwLDApOyBDTEVBUjogYm90aDsgQk9SREVS LVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkct VE9QOiAwcHg7IC13ZWJraXQtdGV4dC1zdHJva2Utd2lkdGg6IDBweCI+PFNQQU4gDQpzdHlsZT0i Qk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4 OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0 OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAw cHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJpOyBDT0xPUjogcmdiKDMxLDczLDEyNSk7IEZPTlQtU0la RTogMThweDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6 IDBweCI+SGVsbG8sPC9TUEFOPjwvRElWPg0KPERJViANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAw cHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzogMTsgVEVY VC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5F LVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBP VVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8yM3B4IFRh aG9tYSwgQXJpYWw7IFdISVRFLVNQQUNFOiBub3JtYWw7IExFVFRFUi1TUEFDSU5HOiBub3JtYWw7 IENPTE9SOiByZ2IoMCwwLDApOyBDTEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVIt UklHSFQ6IDBweDsgV09SRC1TUEFDSU5HOiAwcHg7IFBBRERJTkctVE9QOiAwcHg7IC13ZWJraXQt dGV4dC1zdHJva2Utd2lkdGg6IDBweCI+DQo8RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBw eDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhU LVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUt U1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9V VExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzIzcHggVGFo b21hLCBBcmlhbDsgQ09MT1I6IHJnYigwLDAsMCk7IENMRUFSOiBib3RoOyBCT1JERVItVE9QOiAw cHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij4NCjxESVYgDQpzdHlsZT0i Qk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4 OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBub25lOyBURVhULUlOREVOVDogMHB4OyBNQVJH SU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURE SU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZP TlQ6IDE0cHgvMjNweCBUYWhvbWEsIEFyaWFsOyBDT0xPUjogcmdiKDAsMCwwKTsgQ0xFQVI6IGJv dGg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgi Pg0KPERJViANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBB RERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQt SU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNP TE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJ TkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8yM3B4IFRhaG9tYSwgQXJpYWw7IENPTE9SOiByZ2Io MCwwLDApOyBDTEVBUjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsg UEFERElORy1UT1A6IDBweCI+DQo8RElWIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9S REVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRSQU5T Rk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6 IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUt V0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzIzcHggVGFob21hLCBB cmlhbDsgQ09MT1I6IHJnYigwLDAsMCk7IENMRUFSOiBib3RoOyBCT1JERVItVE9QOiAwcHg7IEJP UkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij48U1BBTiANCnN0eWxlPSJCT1JERVIt Qk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IE1BUkdJ TjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJ TkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9O VC1GQU1JTFk6IGNhbGlicmk7IENPTE9SOiByZ2IoMzEsNzMsMTI1KTsgRk9OVC1TSVpFOiAxOHB4 OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij5H b29kIA0KZGF5ITwvU1BBTj48L0RJVj48L0RJVj4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRP TTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7 IFRFWFQtVFJBTlNGT1JNOiBub25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgT1VU TElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBw eDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0cHgvMjNw eCBUYWhvbWEsIEFyaWFsOyBDT0xPUjogcmdiKDAsMCwwKTsgQ0xFQVI6IGJvdGg7IEJPUkRFUi1U T1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPg0KPERJViANCnN0 eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9N OiAwcHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7 IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7 IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBw eDsgRk9OVDogMTRweC8yM3B4IFRhaG9tYSwgQXJpYWw7IENPTE9SOiByZ2IoMCwwLDApOyBDTEVB UjogYm90aDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6 IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4 OyBQQURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsg T1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDog MHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJpOyBDT0xPUjogcmdi KDMxLDczLDEyNSk7IEZPTlQtU0laRTogMThweDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklH SFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+TG9uZyANCnRpbWUgbm8gaGVhcmluZyB5b3VyIG5l d3MgaG93IGFyZSB5b3U/PC9TUEFOPjwvRElWPg0KPERJViANCnN0eWxlPSJCT1JERVItQk9UVE9N OiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzogMTsg VEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRM SU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4 OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8yM3B4 IFRhaG9tYSwgQXJpYWw7IENPTE9SOiByZ2IoMCwwLDApOyBDTEVBUjogYm90aDsgQk9SREVSLVRP UDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+PFNQQU4gDQpzdHls ZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTog MHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBub25lOyBURVhULUlOREVOVDogMHB4OyBN QVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQ QURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7 IEZPTlQ6IDE4cHgvMjNweCBjYWxpYnJpOyBDT0xPUjogcmdiKDMxLDczLDEyNSk7IEJPUkRFUi1U T1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPlBscyANCmtpbmRs eSBmaW5kIGF0dGFjaGVkIG9mIGhvdCBzYWxlIGl0ZW1zIGZvciB5b3Ugc2hhcmUhIE1heWJlIHRo ZXkgd291bGQgYmUgaGVscCANCnlvdSB0byBnZXQgbW9yZSBwcm9maXQgaW4geW91ciBtYXJrZXQu VGtzPC9TUEFOPjwvRElWPjwvRElWPjwvRElWPg0KPERJViANCnN0eWxlPSJCT1JERVItQk9UVE9N OiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzogMTsg VEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRM SU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4 OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8yM3B4 IFRhaG9tYSwgQXJpYWw7IENPTE9SOiByZ2IoMCwwLDApOyBDTEVBUjogYm90aDsgQk9SREVSLVRP UDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+DQo8RElWIA0Kc3R5 bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006 IDBweDsgV0lET1dTOiAxOyBURVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsg TUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsg UEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4 OyBGT05UOiAxNHB4LzIzcHggVGFob21hLCBBcmlhbDsgQ09MT1I6IHJnYigwLDAsMCk7IENMRUFS OiBib3RoOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDog MHB4Ij4NCjxESVYgDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4 OyBQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQtVFJBTlNGT1JNOiBub25lOyBU RVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElO RS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQ QURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0cHgvMjNweCBUYWhvbWEsIEFyaWFsOyBDT0xPUjog cmdiKDAsMCwwKTsgQ0xFQVI6IGJvdGg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAw cHg7IFBBRERJTkctVE9QOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsg Qk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRS QU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZ TEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJ TkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxOHB4LzIzcHggY2FsaWJy aTsgQ09MT1I6IHJnYigzMSw3MywxMjUpOyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDog MHB4OyBQQURESU5HLVRPUDogMHB4Ij5Mb29raW5nIA0KZm9yd2FyZCB0byBoZWFyaW5nIGZyb20g eW91IHNvb248L1NQQU4+PC9ESVY+PC9ESVY+PC9ESVY+PC9ESVY+PC9ESVY+DQo8RElWIA0Kc3R5 bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006 IDBweDsgV0lET1dTOiAxOyBURVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsg TUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsg UEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4 OyBGT05UOiAxNHB4LzIzcHggVGFob21hLCBBcmlhbDsgV0hJVEUtU1BBQ0U6IG5vcm1hbDsgTEVU VEVSLVNQQUNJTkc6IG5vcm1hbDsgQ09MT1I6IHJnYigwLDAsMCk7IENMRUFSOiBib3RoOyBCT1JE RVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBXT1JELVNQQUNJTkc6IDBweDsgUEFERElO Ry1UT1A6IDBweDsgLXdlYmtpdC10ZXh0LXN0cm9rZS13aWR0aDogMHB4Ij4NCjxQIA0Kc3R5bGU9 IlBBRERJTkctQk9UVE9NOiAwcHg7IExJTkUtSEVJR0hUOiAyM3B4OyBXSURPV1M6IDE7IFRFWFQt SU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBQQURESU5HLUxFRlQ6IDBweDsgUEFERElORy1SSUdI VDogMHB4OyBDTEVBUjogYm90aDsgUEFERElORy1UT1A6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9S REVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBM SU5FLUhFSUdIVDogMjNweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJ TkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsg UEFERElORy1SSUdIVDogMHB4OyBGT05ULUZBTUlMWTogY2FsaWJyaTsgRk9OVC1TSVpFOiAxOHB4 OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij48 QlI+PC9TUEFOPjwvUD4NCjxQIA0Kc3R5bGU9IlBBRERJTkctQk9UVE9NOiAwcHg7IExJTkUtSEVJ R0hUOiAyM3B4OyBXSURPV1M6IDE7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBQQURE SU5HLUxFRlQ6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBDTEVBUjogYm90aDsgUEFERElORy1U T1A6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDog MHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBMSU5FLUhFSUdIVDogMjNweDsgTUFSR0lOOiAwcHg7 IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZU OiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05ULUZBTUlM WTogY2FsaWJyaTsgRk9OVC1TSVpFOiAxOHB4OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdI VDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij5Ua3MmYW1wO0Jlc3QgDQpSZWdhcmRzPC9TUEFOPjxC Uj48L1A+DQo8UCANCnN0eWxlPSJQQURESU5HLUJPVFRPTTogMHB4OyBXSURPV1M6IDE7IFRFWFQt VFJBTlNGT1JNOiBub25lOyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgUEFERElORy1M RUZUOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVDogMTRweC8yM3B4IFRhaG9tYSwgQXJp YWwsIFNUSGVpdGksIFNpbVN1bjsgQ09MT1I6IHJnYigwLDAsMCk7IENMRUFSOiBib3RoOyBQQURE SU5HLVRPUDogMHB4Ij48U1BBTiANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1M RUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNUWUxF OiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5F LVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVC1GQU1JTFk6IGNhbGlicmk7IEZP TlQtU0laRTogMThweDsgQk9SREVSLVRPUDogMHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElO Ry1UT1A6IDBweCI+S2V2aW4gDQpaaGFvPC9TUEFOPjwvUD4NCjxQIA0Kc3R5bGU9IlBBRERJTkct Qk9UVE9NOiAwcHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5U OiAwcHg7IE1BUkdJTjogMHB4OyBQQURESU5HLUxFRlQ6IDBweDsgUEFERElORy1SSUdIVDogMHB4 OyBGT05UOiAxNHB4LzIzcHggVGFob21hLCBBcmlhbCwgU1RIZWl0aSwgU2ltU3VuOyBDT0xPUjog cmdiKDAsMCwwKTsgQ0xFQVI6IGJvdGg7IFBBRERJTkctVE9QOiAwcHgiPjxTUEFOIA0Kc3R5bGU9 IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBw eDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVy dDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDog MHB4OyBGT05ULUZBTUlMWTogY2FsaWJyaTsgRk9OVC1TSVpFOiAxOHB4OyBCT1JERVItVE9QOiAw cHg7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij5TYWxlcyANCk1hbmFnZXI8 L1NQQU4+PC9QPg0KPFAgDQpzdHlsZT0iUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBU RVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IFBBRERJ TkctTEVGVDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0cHgvMjNweCBUYWhvbWEs IEFyaWFsLCBTVEhlaXRpLCBTaW1TdW47IENPTE9SOiByZ2IoMCwwLDApOyBDTEVBUjogYm90aDsg UEFERElORy1UT1A6IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JE RVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1T VFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VU TElORS1XSURUSDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJp OyBGT05ULVNJWkU6IDE4cHg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBB RERJTkctVE9QOiAwcHgiPlRlbDombmJzcDswMjEtNjI5OTA2ODImbmJzcDsmbmJzcDs8U1BBTiAN CnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9U VE9NOiAwcHg7IExJTkUtSEVJR0hUOiAzMHB4OyBCQUNLR1JPVU5ELUNPTE9SOiByZ2IoMjU1LDI1 NSwyNTUpOyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjog aW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJ R0hUOiAwcHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJpOyBGT05ULVNJWkU6IDE4cHg7IEJPUkRFUi1U T1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPkZheDogDQowMjEt NjI2NjM2MTQmbmJzcDs8L1NQQU4+PC9TUEFOPjwvUD4NCjxQIA0Kc3R5bGU9IlBBRERJTkctQk9U VE9NOiAwcHg7IFdJRE9XUzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAw cHg7IE1BUkdJTjogMHB4OyBQQURESU5HLUxFRlQ6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBG T05UOiAxNHB4LzIzcHggVGFob21hLCBBcmlhbCwgU1RIZWl0aSwgU2ltU3VuOyBDT0xPUjogcmdi KDAsMCwwKTsgQ0xFQVI6IGJvdGg7IFBBRERJTkctVE9QOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJP UkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsg TUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsg UEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4 OyBGT05ULUZBTUlMWTogY2FsaWJyaTsgRk9OVC1TSVpFOiAxOHB4OyBCT1JERVItVE9QOiAwcHg7 IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4Ij5Nb2I6Kzg2MTM2MzE0OTg4NDYm bmJzcDsmbmJzcDs8U1BBTiANCnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZU OiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IExJTkUtSEVJR0hUOiAzMHB4OyBCQUNLR1JPVU5E LUNPTE9SOiByZ2IoMjU1LDI1NSwyNTUpOyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9u ZTsgT1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURU SDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJpOyBGT05ULVNJ WkU6IDE4cHg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9Q OiAwcHgiPldlY2hhdDpkZXZvbjUyMTwvU1BBTj48L1NQQU4+PC9QPg0KPFAgDQpzdHlsZT0iUEFE RElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRSQU5TRk9STTogbm9uZTsgVEVYVC1J TkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IFBBRERJTkctTEVGVDogMHB4OyBQQURESU5HLVJJR0hU OiAwcHg7IEZPTlQ6IDE0cHgvMjNweCBUYWhvbWEsIEFyaWFsLCBTVEhlaXRpLCBTaW1TdW47IENP TE9SOiByZ2IoMCwwLDApOyBDTEVBUjogYm90aDsgUEFERElORy1UT1A6IDBweCI+PFNQQU4gDQpz dHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQQURESU5HLUJPVFRP TTogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjog aW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJ R0hUOiAwcHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJpOyBGT05ULVNJWkU6IDE4cHg7IEJPUkRFUi1U T1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPjxTUEFOIA0Kc3R5 bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006 IDBweDsgTElORS1IRUlHSFQ6IDMwcHg7IEJBQ0tHUk9VTkQtQ09MT1I6IHJnYigyNTUsMjU1LDI1 NSk7IE1BUkdJTjogMHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZl cnQ7IFBBRERJTkctTEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6 IDBweDsgRk9OVC1GQU1JTFk6IGNhbGlicmk7IEZPTlQtU0laRTogMThweDsgQk9SREVSLVRPUDog MHB4OyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1UT1A6IDBweCI+RS1tYWlsOiZuYnNwOzwv U1BBTj48L1NQQU4+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVG VDogMHB4OyBQQURESU5HLUJPVFRPTTogMHB4OyBMSU5FLUhFSUdIVDogMzBweDsgQkFDS0dST1VO RC1DT0xPUjogcmdiKDI1NSwyNTUsMjU1KTsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5v bmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lE VEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05ULUZBTUlMWTogY2FsaWJyaTsgRk9OVC1T SVpFOiAxOHB4OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDogMHB4OyBURVhULURFQ09S QVRJT046IHVuZGVybGluZTsgUEFERElORy1UT1A6IDBweCI+a2V2aW56aGFvQHlpaHVhcHJpbnRp bmcuY29tPC9TUEFOPjwvUD4NCjxQIA0Kc3R5bGU9IlBBRERJTkctQk9UVE9NOiAwcHg7IFdJRE9X UzogMTsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4 OyBQQURESU5HLUxFRlQ6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzIzcHgg VGFob21hLCBBcmlhbCwgU1RIZWl0aSwgU2ltU3VuOyBDT0xPUjogcmdiKDAsMCwwKTsgQ0xFQVI6 IGJvdGg7IFBBRERJTkctVE9QOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBw eDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgTUFSR0lOOiAwcHg7IE9V VExJTkUtU1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAw cHg7IE9VVExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05ULUZBTUlMWTog Y2FsaWJyaTsgRk9OVC1TSVpFOiAxOHB4OyBCT1JERVItVE9QOiAwcHg7IEJPUkRFUi1SSUdIVDog MHB4OyBQQURESU5HLVRPUDogMHB4Ij5Ta3lwZTo8U1BBTiANCnN0eWxlPSJCT1JERVItQk9UVE9N OiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9UVE9NOiAwcHg7IExJTkUtSEVJR0hU OiAyNHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElORS1DT0xPUjog aW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQQURESU5HLVJJ R0hUOiAwcHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJpOyBGT05ULVNJWkU6IDE4cHg7IEJPUkRFUi1U T1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgiPnBldGVyemhhby5j b20uaGs8L1NQQU4+Jm5ic3A7IA0KV2hhdHNBcHA6Kzg2MTM2MzE0OTg4NDY8L1NQQU4+PC9QPg0K PFAgDQpzdHlsZT0iUEFERElORy1CT1RUT006IDBweDsgV0lET1dTOiAxOyBURVhULVRSQU5TRk9S TTogbm9uZTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IFBBRERJTkctTEVGVDogMHB4 OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQ6IDE0cHgvMjNweCBUYWhvbWEsIEFyaWFsLCBTVEhl aXRpLCBTaW1TdW47IENPTE9SOiByZ2IoMCwwLDApOyBDTEVBUjogYm90aDsgUEFERElORy1UT1A6 IDBweCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4 OyBQQURESU5HLUJPVFRPTTogMHB4OyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsg T1VUTElORS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDog MHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFNSUxZOiBjYWxpYnJpOyBGT05ULVNJWkU6 IDE4cHg7IEJPUkRFUi1UT1A6IDBweDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAw cHgiPlNoYW5naGFpIA0KWWlodWEgUHJpbnRpbmcgQ28uLEx0ZCAmbmJzcDsoRmFjdG9yeSk8L1NQ QU4+PEJSPjwvUD4NCjxQIA0Kc3R5bGU9IlBBRERJTkctQk9UVE9NOiAwcHg7IFdJRE9XUzogMTsg VEVYVC1UUkFOU0ZPUk06IG5vbmU7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBQQURE SU5HLUxFRlQ6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05UOiAxNHB4LzIzcHggVGFob21h LCBBcmlhbCwgU1RIZWl0aSwgU2ltU3VuOyBDT0xPUjogcmdiKDAsMCwwKTsgQ0xFQVI6IGJvdGg7 IFBBRERJTkctVE9QOiAwcHgiPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9S REVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgTUFSR0lOOiAwcHg7IE9VVExJTkUt U1RZTEU6IG5vbmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9V VExJTkUtV0lEVEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05ULUZBTUlMWTogJiMzOTt0 aW1lcyBuZXcgcm9tYW4mIzM5OzsgRk9OVC1TSVpFOiAxOHB4OyBCT1JERVItVE9QOiAwcHg7IEJP UkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4IiANCmNsYXNzPWNoYW5nZWQ+V2Vic2l0 ZTombmJzcDs8QSBocmVmPSJodHRwOi8vc2h5aWh1YS5lbi5hbGliYWJhLmNvbSUyYy8iIA0KdGFy Z2V0PV9ibGFuaz5odHRwOi8vc2h5aWh1YS5lbi5hbGliYWJhLmNvbTwvQT48L1NQQU4+PC9QPg0K PFAgDQpzdHlsZT0iUEFERElORy1CT1RUT006IDBweDsgTElORS1IRUlHSFQ6IDIzcHg7IFdJRE9X UzogMTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IFBBRERJTkctTEVGVDogMHB4OyBQ QURESU5HLVJJR0hUOiAwcHg7IENMRUFSOiBib3RoOyBQQURESU5HLVRPUDogMHB4Ij48U1BBTiAN CnN0eWxlPSJCT1JERVItQk9UVE9NOiAwcHg7IEJPUkRFUi1MRUZUOiAwcHg7IFBBRERJTkctQk9U VE9NOiAwcHg7IFRFWFQtVFJBTlNGT1JNOiBub25lOyBGT05ULVZBUklBTlQ6IG5vcm1hbDsgRk9O VC1TVFlMRTogbm9ybWFsOyBNQVJHSU46IDBweDsgT1VUTElORS1TVFlMRTogbm9uZTsgT1VUTElO RS1DT0xPUjogaW52ZXJ0OyBQQURESU5HLUxFRlQ6IDBweDsgT1VUTElORS1XSURUSDogMHB4OyBQ QURESU5HLVJJR0hUOiAwcHg7IEZPTlQtRkFNSUxZOiAmIzM5O3RpbWVzIG5ldyByb21hbiYjMzk7 OyBDT0xPUjogcmdiKDAsMCwwKTsgRk9OVC1TSVpFOiAxOHB4OyBCT1JERVItVE9QOiAwcHg7IEZP TlQtV0VJR0hUOiBub3JtYWw7IEJPUkRFUi1SSUdIVDogMHB4OyBQQURESU5HLVRPUDogMHB4IiAN CmNsYXNzPWNoYW5nZWQ+PEEgaHJlZj0iaHR0cDovL3d3dy5zaHlpaHVhLmNvbS5jbi8iIHRhcmdl dD1fYmxhbms+PC9BPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBweDsgQk9SREVSLUxF RlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgVEVYVC1UUkFOU0ZPUk06IG5vbmU7IEZPTlQt VkFSSUFOVDogbm9ybWFsOyBGT05ULVNUWUxFOiBub3JtYWw7IE1BUkdJTjogMHB4OyBPVVRMSU5F LVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkctTEVGVDogMHB4OyBP VVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVC1GQU1JTFk6IGNhbGli cmk7IENPTE9SOiByZ2IoMCwwLDApOyBGT05ULVNJWkU6IDE4cHg7IEJPUkRFUi1UT1A6IDBweDsg Rk9OVC1XRUlHSFQ6IG5vcm1hbDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJTkctVE9QOiAwcHgi PkFkZDpSb29tNTEwLEJ1aWxkaW5nOSxMYW5lMjYsSGVYdWFuJm5ic3A7Um9hZCxKaWFuZ1FpYW8s SmlhRGluZyANCkRpc3RyaWN0LFNoYW5naGFpJm5ic3A7Q2l0eS4mbmJzcDtDaGluYe+8iEppYW5n UWlhbyZuYnNwO1dBTiZuYnNwO0RBJm5ic3A7UExBWkEpIA0KWmlwOjIwMTgwMy48L1NQQU4+PC9T UEFOPjwvUD4NCjxQIA0Kc3R5bGU9IlBBRERJTkctQk9UVE9NOiAwcHg7IExJTkUtSEVJR0hUOiAy M3B4OyBXSURPV1M6IDE7IFRFWFQtSU5ERU5UOiAwcHg7IE1BUkdJTjogMHB4OyBQQURESU5HLUxF RlQ6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBDTEVBUjogYm90aDsgUEFERElORy1UT1A6IDBw eCI+PFNQQU4gDQpzdHlsZT0iQk9SREVSLUJPVFRPTTogMHB4OyBCT1JERVItTEVGVDogMHB4OyBQ QURESU5HLUJPVFRPTTogMHB4OyBURVhULVRSQU5TRk9STTogbm9uZTsgRk9OVC1WQVJJQU5UOiBu b3JtYWw7IEZPTlQtU1RZTEU6IG5vcm1hbDsgTUFSR0lOOiAwcHg7IE9VVExJTkUtU1RZTEU6IG5v bmU7IE9VVExJTkUtQ09MT1I6IGludmVydDsgUEFERElORy1MRUZUOiAwcHg7IE9VVExJTkUtV0lE VEg6IDBweDsgUEFERElORy1SSUdIVDogMHB4OyBGT05ULUZBTUlMWTogJiMzOTt0aW1lcyBuZXcg cm9tYW4mIzM5OzsgQ09MT1I6IHJnYigwLDAsMCk7IEZPTlQtU0laRTogMThweDsgQk9SREVSLVRP UDogMHB4OyBGT05ULVdFSUdIVDogbm9ybWFsOyBCT1JERVItUklHSFQ6IDBweDsgUEFERElORy1U T1A6IDBweCIgDQpjbGFzcz1jaGFuZ2VkPjxTUEFOIA0Kc3R5bGU9IkJPUkRFUi1CT1RUT006IDBw eDsgQk9SREVSLUxFRlQ6IDBweDsgUEFERElORy1CT1RUT006IDBweDsgVEVYVC1UUkFOU0ZPUk06 IG5vbmU7IEZPTlQtVkFSSUFOVDogbm9ybWFsOyBGT05ULVNUWUxFOiBub3JtYWw7IE1BUkdJTjog MHB4OyBPVVRMSU5FLVNUWUxFOiBub25lOyBPVVRMSU5FLUNPTE9SOiBpbnZlcnQ7IFBBRERJTkct TEVGVDogMHB4OyBPVVRMSU5FLVdJRFRIOiAwcHg7IFBBRERJTkctUklHSFQ6IDBweDsgRk9OVC1G QU1JTFk6IGNhbGlicmk7IENPTE9SOiByZ2IoMCwwLDApOyBGT05ULVNJWkU6IDE4cHg7IEJPUkRF Ui1UT1A6IDBweDsgRk9OVC1XRUlHSFQ6IG5vcm1hbDsgQk9SREVSLVJJR0hUOiAwcHg7IFBBRERJ TkctVE9QOiAwcHgiPjwvU1BBTj48L1NQQU4+Jm5ic3A7PElNRyANCnN0eWxlPSJXSURUSDogMjcx cHg7IEhFSUdIVDogMjY4cHgiIGJvcmRlcj0wIGhzcGFjZT0wIGFsdD0iIiBhbGlnbj1iYXNlbGlu ZSANCnNyYz0iY2lkOmltZzAuanBnIiB3aWR0aD0yNzIgaGVpZ2h0PTM2Mz4mbmJzcDs8SU1HIA0K c3R5bGU9IldJRFRIOiAyNjVweDsgSEVJR0hUOiAyNjhweCIgYm9yZGVyPTAgaHNwYWNlPTAgYWx0 PSIiIGFsaWduPWJhc2VsaW5lIA0Kc3JjPSJjaWQ6aW1nMS5qcGciIA0Kd2lkdGg9Mjk0IGhlaWdo dD0zNDQ+PC9QPg0KPFAgDQpzdHlsZT0iUEFERElORy1CT1RUT006IDBweDsgTElORS1IRUlHSFQ6 IDIzcHg7IFdJRE9XUzogMTsgVEVYVC1JTkRFTlQ6IDBweDsgTUFSR0lOOiAwcHg7IFBBRERJTkct TEVGVDogMHB4OyBQQURESU5HLVJJR0hUOiAwcHg7IENMRUFSOiBib3RoOyBQQURESU5HLVRPUDog MHB4Ij4mbmJzcDs8SU1HIA0Kc3R5bGU9IldJRFRIOiAyNzFweDsgSEVJR0hUOiAyNDNweCIgYm9y ZGVyPTAgaHNwYWNlPTAgYWx0PSIiIGFsaWduPWJhc2VsaW5lIA0Kc3JjPSJjaWQ6aW1nMi5qcGci IHdpZHRoPTIwOSANCmhlaWdodD0zODg+Jm5ic3A7PElNRyBzdHlsZT0iV0lEVEg6IDI2NnB4OyBI RUlHSFQ6IDI0M3B4IiBib3JkZXI9MCBoc3BhY2U9MCANCmFsdD0iIiBhbGlnbj1iYXNlbGluZSBz cmM9ImNpZDppbWczLmpwZyIgDQp3aWR0aD0zNzkgaGVpZ2h0PTQzMj4mbmJzcDs8L1A+DQo8UCAN CnN0eWxlPSJQQURESU5HLUJPVFRPTTogMHB4OyBMSU5FLUhFSUdIVDogMjNweDsgV0lET1dTOiAx OyBURVhULUlOREVOVDogMHB4OyBNQVJHSU46IDBweDsgUEFERElORy1MRUZUOiAwcHg7IFBBRERJ TkctUklHSFQ6IDBweDsgQ0xFQVI6IGJvdGg7IFBBRERJTkctVE9QOiAwcHgiPjxJTUcgDQpzdHls ZT0iV0lEVEg6IDM3MnB4OyBIRUlHSFQ6IDI1MXB4IiBib3JkZXI9MCBoc3BhY2U9MCBhbHQ9IiIg YWxpZ249YmFzZWxpbmUgDQpzcmM9ImNpZDppbWc0LmpwZyIgDQp3aWR0aD0zNDYgaGVpZ2h0PTI1 ND4mbmJzcDs8SU1HIHN0eWxlPSJXSURUSDogMzc4cHg7IEhFSUdIVDogMjU0cHgiIGJvcmRlcj0w IA0KaHNwYWNlPTAgYWx0PSIiIGFsaWduPWJhc2VsaW5lIA0Kc3JjPSJjaWQ6aW1nNS5qcGciIA0K d2lkdGg9MzExIGhlaWdodD04Mz48L1A+PC9ESVY+PC9CT0RZPjwvSFRNTD4NCg0K --VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt Content-Type: image/jpeg; name="A M G.jpg" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="A M G.jpg" Content-ID: <img0.jpg> Content-Description: Photo /9j/4AAQSkZJRgABAQEAYABgAAD/4R++RXhpZgAASUkqAN4CAABgAAAAAQAAAGAAAAABAAAAMjAx NTowNjozMCAxNDozMDozMQAAAAAAQEIPAAAAAABAQg8AAAAAAEBCDwAAAAAAQEIPAAAAAABAQg8A AAAAAEBCDwAAAAAAQEIPAAAAAABAQg8AAAAAAEBCDwAAAAAAQEIPAAAAAABAQg8AAAAAAEBCDwAA AAAAQEIPAAAAAABAQg8AAAAAAEBCDwAAAAAAQEIPAAAAAABAQg8AAAAAAEBCDwAAAAAAQEIPAAAA AABAQg8AAAAAAEBCDwAAAAAAQEIPAAAAAABAQg8AAAAAAEBCDwAAAAAAQEIPAAAAAABAQg8AAAAA AEBCDwAAAAAAQEIPAAAAAABAQg8AAAAAAEBCDwAAAAAAQEIPACQAmoIFAAEAAAC0AAAAnYIFAAEA AAC8AAAAIogDAAEAAAAAAAAAJ4gDAAEAAAAAAAAAAJACAAAAAAAAAAAAApEFAAEAAADEAAAAAZIF AAEAAADMAAAAApIFAAEAAADUAAAAA5IFAAEAAADcAAAABJIFAAEAAADkAAAABZIFAAEAAADsAAAA BpIFAAEAAAD0AAAAB5IDAAEAAAAAAAAACJIDAAEAAAAAAAAACZIDAAEAAAAAAAAACpIFAAEAAAD8 AAAAAaADAAEAAAAAAAAAAqADAAEAAAAAAAAAA6ADAAEAAAAAAAAADqIFAAEAAAAEAQAAD6IFAAEA AAAMAQAAEKIDAAEAAAAAAAAAFaIFAAEAAAAUAQAAF6IDAAEAAAAAAAAAAKMDAAEAAAAAAAAAAaMD AAEAAAAAAAAAAqQDAAEAAAAAAAAAA6QDAAEAAAAAAAAABKQFAAEAAAAcAQAABaQDAAEAAAAAAAAA BqQDAAEAAAAAAAAAB6QDAAEAAAAAAAAACKQDAAEAAAAAAAAACaQDAAEAAAAAAAAACqQDAAEAAAAA AAAADKQDAAEAAAAAAAAAAAAAACQBAAAMABIBAwABAAAAAQAAABoBBQABAAAACAAAABsBBQABAAAA EAAAACgBAwABAAAAAgAAADEBAgAEAAAAaVNlZTIBAgAUAAAAGAAAAD4BBQACAAAALAAAAD8BBQAG AAAAPAAAABECBQADAAAAbAAAABMCAwABAAAAAAAAABQCBQAGAAAAhAAAAGmHBAABAAAAJAEAAOQe AAAAAAAAAQAAAAAAAAABAAAACAAIAAgA/9j/4AAQSkZJRgABAQEBLAEsAAD/2wBDAAYEBQYFBAYG BQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhYaHSUfGhsjHBYWICwgIyYnKSopGR8tMC0oMCUoKSj/ 2wBDAQcHBwoIChMKChMoGhYaKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgo KCgoKCgoKCgoKCj/wAARCACgAKADASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQF BgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS 0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4 eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi 4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREA AgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl 8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImK kpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP0 9fb3+Pn6/9oADAMBAAIRAxEAPwDstJtvCej+B9E1LX/C13eJcRDzb6BFZAxYjDfvAQenbByAMmu2 8O+Fvh94i08Xmj6bZ3EOdrYLhkb0ZScg/Wr3wytobz4YaRbXcSTW81sySRuMhlLMCCK8+8NaJfeA /ipdwwzuuhJZy3s0j8hrVQcZ9XV8DPXGT0bFdeOxuLp4uUYzbi5NbvTU68sy3LsZl7coqFWEea7t aSS19H+fY6XxfpPw48KQK2q6Vb+c4zHbxbmkceoG7AHuSBWO3/CA2fh6LWNa8Mx6fBdc2Vuzl7i5 XGdwQHCr0wScc9sjPmsOpDxL41bVvEEck9s9wjSW6EfPlgI4FJwMdAckfKrHrUWuav8A8Jb40utT 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 IiQiHiQcHh8e/9sAQwEFBQUHBgcOCAgOHhQRFB4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e Hh4eHh4eHh4eHh4eHh4eHh4eHh4e/8AAEQgCWAJYAwERAAIRAQMRAf/EAB0AAQACAgMBAQAAAAAA AAAAAAABAgMGBAcIBQn/xABgEAABAgQDAwMMCQ8KBAYDAQEBAAIDBAURBiExBxJBE1FhCBQXIjdx gYSRtNHTFRYyQlaToaSxIzQ2RFJUYnJzdIKSsrPSJDM1Q1ODlKLB4SVjZHUJJkVG8PFVZaPDwv/E ABwBAQEBAAIDAQAAAAAAAAAAAAABAgMHBAUGCP/EAE4RAAIBAgMDBwkGBAQEBAUFAAABAgMRBAUh BhIxNUFRgaGy0QcTFiJTYXGCkRQyorHB8EJS0uEVIzNiNHKS8SZDRMIXJHODswg2Y9Pi/9oADAMB AAIRAxEAPwDVMOUWp4irMCj0eW65npje5KFyjWb260uObiAMmk5ld64rFUsJSdas7RXF8eLtzHTu Hw9TE1FSpK8n/wB+c3HsLbTPg18+l/WL1HpRlXtfwy8D2no9mPs+2PiOwttM+DXz6X9YnpRlXtfw y8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+ 2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4 NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6U ZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6 PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiO wttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPp f1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X 8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7 Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM +DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ie lGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvA ej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4 jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz 6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe 1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y +z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLb TPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9Y npRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DL wHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y +I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg1 8+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRl Xtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9 mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C 20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/ WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfw y8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+ 2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4 NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6U ZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiOwttM+DXz6X9YnpRlXtfwy8B6 PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPpf1ielGVe1/DLwHo9mPs+2PiO wttM+DXz6X9YnpRlXtfwy8B6PZj7Ptj4jsLbTPg18+l/WJ6UZV7X8MvAej2Y+z7Y+I7C20z4NfPp f1ielGVe1/DLwHo9mPs+2PiadiOi1PDtZj0esS3W09L7vKwuUa/d3mhwzaSDk4HIr2+FxVLF0lWo u8XwfDg7c56vEYephqjpVVaS/wC/Mbj1OfdloPjHm8Veo2o5Kq/L3ke02e5Rp9fdZ7FXUJ2cEAQB AEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBA EAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6 h1OfdloPjHm8VNqOSqvy95DZ7lGn191neO1aq7XaG6PPYdlaPP0lpLv5PKPfNQW/hML7P77R+iF0 jipYqF5Qs18NT9D7N4TZvG2pY2U4VPfJKDfudtOv6nUUvt22hMIiGcpUw3mdJZH9VwK9asxr34r6 HYc/J3kslZKa+bxRtmG+qLmGvbDxJhxjmH3UenRcx/dv1/WXk081f8cfoegx/kwVm8FX16Jr/wBy 8DubBuMcOYvkzM0GpwposA5WCbtiwvxmHMd/Q8F7OjiKdZXgzrfNMlx2VVNzF03G/B8U/g1oz765 j1QQBAEBx6lPSVMkYs9UZuDKSsFu9EjRnhjGDpJXJSpTqzUKau3zIxOpGnFym7JHSmNuqDkJZ75b CVNM84ZdeTd4cLvtZ7pw7+74V9nl+xlWot7Fy3V0LV/Xgu0+Tx21dKm3HDR3n0vh+/odTV/atj2r xHcviSZloZOUOStLtb0Xb23lJX1eG2cy3DpWpJvpev8AbsPm6+fY+vxnb4afkb5sb2fYhxjDh4ix XWq1Doz+2l4Bnooizg+6J3rthnnGbtRYWJ9BnucYXAt4fCU47/O7K0ezV9iPfZNleJxK8/ipy3eZ Xev9jvyamaHhTDwiTUxLUulyUMNDoj91jGjIC51J5tSecrryvX1dWq/iz7vBYKriJxw+Gg5SeiS1 Ok8b9UVChvfLYOpImAMhOz4LWHpbCFnEfjFveXpq2ba2pLrfgdpZP5Mak0p5jU3f9sdX1y4Lqv8A E6orm1HaBWXnrrFM9BYTcQ5MiXaOjtACfCSvXTxlefGT6tD77B7HZLhF6mHUn0y9b89Ow3HY3s/x RjuKyuVyvVqWoLHHdidexDFnHA2IYSTZgOr+Og4keTg8HPEevOT3fi9f7HzO1e0eXZKnhcJRhKtz +rG0fjpq+hc3F9D9KUun0nDdG63lQyTkZdpc58WMXboGZc57ySekkr6ClStaEEdLYzGVMTUlWry1 fHgl9FZI6rxvt/oFMfElcNSj61HbkZhzuSlgeg23n+AWPAr7DL9j8TXSniHuLo4v6c3X9D5LHbT4 eg3Cit59n7/dzqeu7adoNUiP3KxCpsJ2kKSgNaB+k7ed8q+rw+yuW0VrByfS3+isj5mvtJj6vCW6 vcv2+0+1soou0PaDOmbj4uxBJ0WC/djznX0W8Rw1ZCF7F3O7RvScl4Oc4nLMrjuQoxlUfBWWnvfh xZ5mU4XMMwlvzqyUPi9fgelaDSZajU5klLRZuM1usSamXx4rzzl7ySfo5l1zXryrzc5JL4JJfRH3 dGjGjDdi2/i7vtOeuE5QgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAg CAIAgCAIAgCAIAgCAIAgCAIAgCAIDx11Rndlr3i/m8JdvbL8lUvm7zOsdoeUanV3UOpz7stB8Y83 iptRyVV+XvIbPco0+vus9irqE7OOnttGx6VxBDj17C0CFK1sXfGlxZkKd578GxOZ2hPutbj1uMwC q+vDj+Z2FsnttUy6UcLjW5UeCfFw+HTHpXNzdD8yR4cSDHiwI8KJBjQnmHEhxGlr4bgbFrgdCDqF 6HVaWO8ac41IqcHdPVNapp869xlpk/PUqowKlTJuNJTsA3hR4Lt1zejpB4g5HikZyjLei7M48Vha OLpSo14qUHxT/ej6GtUeo9iO1eBjKGKLWuSlcQQmFzQ3KHOMGrmDg4e+Z4Rle30GCxqr+pP735nR O12x1TJ5faMPeVF/WL6H7uh9T149qL2B8MEB8fGWJaThOgR61WI5hy8LJrWi74rz7ljBxcfSTYAl eXgcDWx1ZUaKu32e9+48bF4ulhKTq1XZL92PIu0rH9bxxUzHqMTkJGE8ulZGG68OCOBP3b7e+PTY AZLtzKMmoZZTtT1k+Mud/DoXu+p1jmmb18xn62keZGnOdxXtz1iR2XsD2de3WuuqFUhH2Bpzxy4I ymouog3+5AsXdBA99cfLbS519gpeapP/ADJdi6fD6n0mz+Ufa6nnqi9RdrPTON8UUbBOGYtYqrxC l4IEODBhgb8Z9u1hsbxJt3gASbAErqXEV40YOc3/AHO2MnyjEZrio4XDR1f0S52+hL+y1PHm0THF dxzWHT9XjFkBjj1pIw3EwZZvCw987neczwsLAfL18RPET3pcOZdH76T9GZBs5g8koeboK8n96T4y 8F0L63eprBI42XAe+Owdh2z1+PMSkzrXtocgWvnnglvKk5tgtOtzq4jRvMSF5uCwn2iev3Vx8D47 bLaZZJhd2k/86f3fcueXVzdL9yZ62q1Qo+F8OxZ6diQKdS5CCL2bushsFg1rWjwANAzNgAvrMNhq lepGjRjdvRI/OWJxKipVq0ve2/3q32nkja1tOrGOp58AOiSVDhuvLyId7uxyfGt7p3G3uW8Lm7j2 xkmQ0ctgpv1qj4vo9y8eL7DrbNs7q46ThHSHR0/H9/30HeJOZN19Cj0djcdkuB5vHmKWU1jokGnw AIs/MsGcOHfJoOm+6xA5rE2Nl6XO82jluH3+MnpFe/p+C/se1yjLJY+vu/wriz2ZSKdI0imS1Mps tDlZOWhiHBhMFg1o4f78V0/WrTrTdSo7t8Wdn06caUFCCskcpcZsIAgCAIAgCAIAgCAIAgCAIAgC AIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIDx11Rndlr3i/m8 JdvbL8lUvm7zOsdoeUanV3UOpz7stB8Y83iptRyVV+XvIbPco0+vus9irqE7OCA6V6ovZoKxJxcX 0CU3qrLsvOwITc5uE0e6A4xGjwuaLZkNC9ZmGE84vOQ4rj7zsjYXar7FUWAxUv8AKk/Vb/hb/KL5 +h69J5oBaQHNzBFwvQs7v9xlkpqYkpuDOycd8vNS8QRYEVmTob2m4cETaaa5jjr0KdenKlVjeMlZ rpTPZGx3HEHHWEYc+/k4dSlyIM/BYcmRAPdAa7rhmPCLmxX0+ExKxFPe5+c/N+1GQzyTHOjxg9Yv pXiuD+vObm5wa0ucQGgXJJyC8o+cPHm2zHcXGuKnvlop9h5IuhSDMwHjR0Y9LuHM2w1Jv2/s7k6y 7DXkv8yWr93Qurn951fnuaPHV3GL9SPDxOv3Ouvfs9Mkc7DNGn8RYgkaHTWB03OxRDZfRg1c89DW guPQF4uNxdPB0JV6nCK/a6zy8HhZ4qtGlDiz29hGg07CeGJOiU8bkrJwrF7zm86ue485Nye+ulcb i6mMryr1Hq/3bqO18Lho4elGjTWiPI+2rHUXHOMIkzBiO9iJIug05mYBbftopB4vIB6Gho518bjc S69S64Lh4/vmP0vsfs7HJcClNf5s7OXu6I9X53NFvkvEPrTkUenTtXqspSqbB5acm4rYMBnO5x48 wGpPAAlbjFzkox4s8fG4ulg6E8RWdoxV3++noPcWzzCsjgzCUnQZGz+RbvR427Yx4pze898+QADg vqsPQjQpqCPy/nWbVs3xs8VV4vguhcyXw/PU83dUjj9+JsTuw/T4wNHpMYtO6cpiYFw555w3Nren eOdxbtbZbKFhKH2movXmvov78fodV7RZm8RV+zwfqx4+9/v96nUpNwvruc+ZM0lAjzc3ClJWC+PM R4jYUGEwXc97iA1o6SSFx1akacHObslq/gahTlUkoR4s9sbJsFy2BsHy9KZuRJyJ9Wno4/rYxAvb 8EWDR0DnJXTOcZnPMcVKq+HBLoX71Z2nlmAjgsOqa48/xNtXqz2AQBAEAQBAEAQBAEAQBAEAQBAE AQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAeOuqM7ste8X8 3hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOSqvy95DZ7lGn191nsVdQnZwQBAeUuqJwC3Cu IxWqZADKLVYhIY3JsvMZlzBzNdm5vecMgAvnswwqoz34rR9jO+dg9pHmWF+yV3erTX/VHmfxXB+6 z6Tqo8y9dxPvzt/qT4dVdtBnYknELKeyQPXwIu15LvqQ6HX3yDzBw4r2eVqXnW1wtr+h1x5TJYZZ bTVRf5jl6vuVvW6uHXY7T6pPFLsP4AdTpaLuTlYcZVtjYthWvFcP0bN/TC7E2Vy9YvGqcl6sNX8e bt16j837R454XCOMfvS06ufw6zyY855WC7ZOtEjGSM1DSPQ/UtYdkaZTY+M6xHlpePPB0vThGiNa eRafqjxc++cAO83pXXm12OnXqrCUk2o6yt08y6l+fuPu9msFGhTeIqaOWiv0c/78TaeqSxfCpWzN 8pTZuG+YrcQycN8J4daFrGI/RG50F4XXGZ1JUaTi9G9P31Hcfk/yqOZZpGrLWFL1n0X/AIV9deo8 mnIZCy+Zdj9DFSiFzvbqWsPU+Tix8c12ZlpRl3ylL65iNZvEfzsRu9rb3AI/DXvMmwVSo3VUW+bR fv4HT/lO2gjDcy2ErfxT1/6V+r6jtfa/jmUoOzSo1ekVCXmJmKespSJAiteGx3jW4uLtbd9uhfZZ Nlc8VjoUakWlxd1zLx4HR+Z4+OHwkqsHd8F8f3qeMTYCw0AXcJ1fx1IF7j5FblO8upRwc2o1yZxf Owd6WppMCTDhk6YcO2d+i0277+cL4jbHMnTpRwkHrLV/DmXW/wAj6vZjAb83iZ8Fovj+/wBD02uu T7gIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAg CAIAgCAIAgCAIAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yG z3KNPr7rPYq6hOzggCA+NjbDslivC8/QKgCIM3D3Q8DOE8ZseOlrgD4FxVqUasHCXOewyrMquWYu niqPGL+q50/c1oeIq3TJ2jVacpNSh8lOScZ0GO3hvDiOdpFiDzEL5ScHCTjLij9PYLGUsbh4Yii7 xmrrw+K4P3nqTqZsMmhbOYVSmIW5OVl/Xb7jMQrWhN727236ZX0OXUfN0U3xep0Tt/mv27NZUoO8 aXqr4/xP66dR0x1RuJPZ/aTMy0GLvSlJb1lCsci8G8U9/e7U/iBdz7KYH7NgFNr1p69XN49Z+fdp cX9oxjgnpHTr5/A6ycRzr6U9CkfRwpRJrEuJadQZO7Ys7HEPfAvybNXv7zWgnwLxMdi44PDzrz/h X1fMutnmYHCyxVeNKPOz6W0iqwsUYy5GiSxiSEq2HSqLLtFyYLDuQwMr3e4l3P2w5l4OV4f7FhN6 s/WleUn73q/otDz8wrvF4pU6P3VaMfgjmbWo0CUrUjhCQiMfI4Zk2yAcz3MSZPbzMS3AmIbH8RdB 7Q5jLH4+dV9P7+isuo/Y3kzyJZTkkJSXrVNX8Ob66y6zSyvScDsQ5VFpk7WqzJUens35uejNgQRw BcbXPQBcnoBW4Qc5KMeLPEx2MpYLDzxNV2jBNvq8eBse1+qSUziOHQaSOUouHIHsZIgAfVHMP1aL lkXPiA5jUNaV+hdlcrjl+Xx5nLV/Dm7Nfi2fhba3Oq2b5nUrTfFv9/BcF7kjnbVAKDT8PYChBrXU eU65qIaLXnpgB7wbZO3GlrQeZ1lz5LfE1KuOf8btH/ljovqevzd+Zp08Iv4Vd/F69mlmaDdfQHoz kU6UmZ+el5CShGNNTMVsGBD+6e4gNHlIXFVqwo03UnokrvqN06cqs1CPFnuvAmHZXCeEabh+Us5k pBDXvt/ORDm9/hcSfCulMfjJ43ETrz/ifZzLqR2vg8NHDUY0o837Z9teGeSEAQBAEAQBAEAQBAEA QBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAeOu qM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOSqvy95DZ7lGn191nsVdQnZwQBAE B0xtv2WxMVY2oFVp8IthzkZspV3MFiITQXCLprutey54mGF6zGYLz1WMlz8fh+9DsXZLa5ZVgMRh 6r1inKn/AMz0t9bS6mdiY+rstgzAdQq0NkNgkpbclYVu1MQ2ZCZYcN4tHeX0OWYJ43FQoR532c/Y dYZljfs9CeIm7vj8W/7niCPEfEiOiRYjokR5LnvcblzibknvnNd3RioRUY8EdQyk5ycnzmE6q3NI 33BUvHoezqvYthS8aJPVAmiUvk4ZcWb43piKABcWYN0OHG4XzmZVY4nHUsI2lGPry6vur66tH0OX 05UMHUxCXrS9VdfF/TgzBspkHUmpz+M6rIRWSOGpQzcNkeC5rYs076nLQ87H3Z3rjTdC9ftjm9PC 5fKMJJuWmj5uf68Os93sNs7WzbN6VFrS/wDdvqV31GkxosaPGiTEzFfFjxnuiRYjjcve43c49JJJ XQjbbu+c/cNKlClBU4KySsl7lwKFZvqcp2DsqgzVFw/iLHUvLR4s3KwfYykclCc9wm447aILA25O Hnnl21l9Tsll8MZjouppFcb9vh1nT/lez2WEy+ODo/enq7dC4duvUcLZRh53tqbVq7IzcCjUCA6q ThjQSwPELNkMbws4ufu5cQCu5s4xq+zeZw8k51Huqz6eL06Fzn5cyzCS8/56tG0Y+s+rxfMapWqj NVisTlWnjeanY75iMRpvOJJA6Bew6AF7rD0IYejCjDhFWPU4ivKvVlUlxbOIBmuZnCdy9SnhcVXG 0fEMeHeWo8L6nfQzEQEDv7rN49BLV8dthjvM4aOHjxnx+C8XbtPptmMJ5yu60uEfzf7fYeqF1ofe hAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQB AEAQBAEAQBAEAQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOSqvy95DZ 7lGn191nsVdQnZwQBAEAQHnHqr8VNmarI4Rlot4cmBNzgB/rXAiG095pLv02rsTYvLt2E8ZJcdF8 Od/XTqZ8NtZjt6UcNHm1f6dn5nQzyO8vuT5BIzUuQm6pU5WmyELlpubitgwWfdPcbDwc/RdcGIrw oUpVJ6Jas8ihRlWqKnBXbPdOCcPyuFsKU6gSecOTghhfaxiP1e89LnEnwrpTHYueMxE68+Mn/wBl 1I7YwuHjhqMaUeCR0T1XGKhHnqdg2Vi3ZL2nZ4A+/IIhMPeG84jpYV8zmta7VJfF/od0eTLJ7RqZ jUXH1Y/+5/kvqdBEr0524kWgwo0xHhwJaE6LHivbDhQ2C7nvcbNaBzkkBLPgZqVIUoOpUdopXb6E uJ7i2WYVhYNwNTqE3ddHhw+Umojf6yM7N56Rc2HQAvrMNR8zSUP3c/L20GbSzbMKmKfBvT3RWi7O PvOreq3xWJakSODpWJ9VnXCanADpBYe0afxni/8Ad9K+82Oy/frSxclpHRfF8fovzOvdp8b5ukqE XrLV/D9/keanHgV2Mj4ZIs0OJAa1znE2a1ouXG+QHOVG0ldhRcmkj21sawl7TMAyNKjMaJ6IDMzx HGM/Mjp3RZt+Zq6azrMPt+MlVX3eC+C8ePWdo5Vglg8NGnz8X8f3obkvVHsQgCAIAgCAIAgCAIAg CAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgP HXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdQ6nPuy0HxjzeKm1HJVX5e8hs9yjT6+6z2KuoTs4IA gCA+RjLEElhfDM9XagfqMrDLgwaxHnJrB0ucQB315WBwdTG4iNCnxk/2+o8bF4qGFoyrT4I8QV6q TlYqs3VahE5SbnIzo0Z3DeJ0HMBoBwAC7tw2HhhqUaNPhFWOpK9eeIqyqz4s+YczzLlvYzwPQfUr YDfvnHdUg2buuhUpjhqDk+N4c2t6N48QV1/tfmyk/sVN++X6L9X1H2+zWWbq+1VFq+Hid6Yprcjh zD09XKlE3JWSgmK/MXdbRov74mwA4khdf1akaUHOXBH3WAwVXH4mGGoq8puy/fQuL9x4WxHV52v1 6frdRdeano7o0S2YbfRo6GizR0AL5OpUdSbnLiz9SZbgKWX4WnhaX3YK3x6X1vU+fnzLHE847w6l rATqnV/btU4H8hknFlOa4ZRY+jonSGZgH7o/gr2uWYZzn52XBcPidWeUbaNUKX+GUH60tZ+5c0fi +L93xPR9cqclRaPN1apRxAk5SE6NGeeDWi5755hxK+joUZ16kaVNXbdkdI1asaUHOb0R4YxxiKbx ViqoYgnQWRZyLvNh3vyUMZMZ4GgC/E3PFd05dgY4HDQoR5vz52dV47FyxeIlVfP+R8UWOS8w8Q7m 6mHAT67iIYtqUA+xlLifyUO0jzI0PSGa/jbvMV8ftXm6oUfslJ+tLj7l/f8AI+p2cyzztT7RNaLh 8f7Hqddan3QQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEA QBAEAQBAEAQBAEAQBAEAQBAEAQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8 VNqOSqvy95DZ7lGn191nsVdQnZwQBAViPZDhuiRHtYxoLnOcbAAaklVJt2RG0ldnlHb9tFZjCssp dKiXolPiEw3g5TMW1jF/FAuG98niLdqbM5I8BS89WX+ZLm6F0fF8/wBDrnaHN/tlTzNJ+pHtZ1U8 3X1DZ86jsjYlsumscVBlSqUKJAw5Af8AVYmbTNuBzhsPNwc4aaDPT5jP8/jl8HSpO9R9nvf6I+ly TJZYuSq1VaC7T1zKwIErLQpaWgw4MCCwQ4cOG0NaxoFgABoAOC6rlKU5OUnds7DjFRSilZI8vdUt tFh4iqzcLUaY36VT4u9MxWHtZmYGVhzsZn0F1/uQV89mOK87LzUOC4/H+35neXk+2ZeCpf4hiY2q TXqp80en4y7F8WdMnn4L1Z2ZwN62PbOKjj+s2IiS1Elnjr2cAtfjyUPgXkcdGjM52B8vCYWWJlpp FcX+iPktqtqqGR0LR9atL7sej/dL3dHS+tr2PSpCSpNMl6dT5eHLScrCEOFCZk1jQMh/uvpoQUIq MVoj864jEVMTVlWqyvKTu2+dnmTqjNp8HE017V6BMcpRpWKHTMwx3azkVpyDeeG0530c4AjJoJ7L 2XyKWFX2qurTfBdC6fi+xHX+0Gbqt/8AL0X6q4vp/t++g6YOfMvsT5U3fZHs4qmPqxuQuUlaRLvA nZ4D3PHk4d8jEI8DQbngD6POs7pZbTtxm+C/V+78z3OU5TUx1S70guLPZFCpVPodHlaRSpVkrJSs MQ4MJmjQPpJ1JOZJJK6mr16leo6tR3k+J2PSpQowUIKyRzVxHIEAQBAEAQBAEAQBAEAQBAEAQBAE AQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQHjrqjO7LX vF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ2cEB8PFlaqdG ljGp+GKjWzuk7spEhNseYh7g79UFeZg8NSry3alVQ+N/0T7bHi4qvUoq8Kbl8Lf9/omeeNp+L9pu K2PpsbDFYpFMdk6TgSUYmL0RIm6C4dAAHOCuwsoy7KMC1U89Gc+ltafBX7XqfD5nmGaYxOmqThHo s9es0mk7O8dViMIclhWp2Pv5iDyDPLE3Qvc189y+gryrLq1/K56mhk2Nq6Rpvr0/M7d2fdT5BgRo c9jWchzW7YinyriIZ/KPyLu8AB0kL5DM9sJ1E4YNbv8AufHqXMfVZdsvCm1PEu76Fw/f7uduYgxB R8H02EyLT6g2WhQ92FCp9NixmMa0ZN+ptLWDmuQF8JiMRutzqXbfxZ97luVVMbJU6LirdMox+l2u w88bVNutTxBAi0bDkvHoshEBbGjRTaajN4tFsoYOd7Ek84zC9FiszlUW7TVl2/2O4dnPJ9h8HJYn GyVSS4JfdXvf83YvidYUPDlfrcRsKi0KpT1zugwZZ24O+626PCV66FKpPSEWz7vGZvgcEnLEVox+ LV/pxO4tnfU91CajQp7G8y2Ulgb+x8rE3or+h8QZNHQ256QvaYfKpS1quy6DrnPfKVShF0ssjd/z yWi+C5+v6M7wqrKjhjD8vJ4LwrJz0KXbuMk2zjZUMb0XaQTfW5F19LgsPhm1CpPcj7lf9TpnMcbi 60pV2vOTfG7s31s6F2pVnbXiRkWlTmFKnS6a8Fr5WnQHRRFHM+K0neHQLA8QV95lOHyPCtVVVUpd MtLfBP8AufGZnXzWunTVNxj7te00ClbMNoNTiCHLYRqcPpmGCA0eGIQvfVs/y6kryqp/DX8j0lPJ cdU4U316fmdrYB6nVwiw5vGtSY9gNzISLiA7ofFyNucNA/GXzGY7ZOScMHG3vf6Lx+h9DgdmIxal iXf3Lx/fxO/aTTpCk06DTqZJwZOUgN3YUGCwNa0dAC+Iq1Z1pudR3b52fV06cacVGCskcpcZsIAg CAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgC AIAgCAIAgCAIAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yGz 3KNPr7rPYq6hOzggCA1DG203AmCalBp2K8SSlImY8LloTZhrwIjLkXa61jmMxe4yvqEB9zC9fouK KHL1zD1Sl6lTZkEwZiA7eY6xLT4QQQRwIQGnV/bfsooVYm6RVMcUyBPycQwpiA3fiOZEGrO1abuB yIGYNxrkhbGz4xxfhzB9AFexNVIVLpxeyHy8djrbzvcggC4PgQljhYDx3gjH8Kbj4SrUnWGybmtm HQmOHJlwJbfeA1sfIpZGlKS4M+djba/s1wRWjRMT4qlKZUGwmxTLvhRHEMdex7VpGdiqTVm40ioS VWpUpVadMNmZKcgMmJeM3SJDe0Oa4X4EEFCGhUDblspr+JJXDlIxhLTdUmoxgQZdkCMC94vcXLAO BzJQtmbJtBxzhXAFGg1jF1WZS5GNMCWhxXwnvDoha5wbZgJ0a4+BCWKbPMfYR2g02ZqWD6wyqSkt H5CNEbBiQw2Juh1rPaCcnDMZIVo+HtC207NsAV4UPFmIvY6oOgNmBC6zjxfqbi4A3YwjVpyvfJBY 3WgVaQr1DkK3So/XEhPy8OZlou6W78N7Q5rrEAi4IyIuhDV9pu1TAmzZ8hDxjW/Y6JPh5lmNlosZ zwy28bQ2usO2GZtfhoUKlcvsx2oYI2kw59+Dq0Kj7HuY2aaYESE6Hvglps9oJB3XZjmKBqxuSECA IAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAI AgCAIAgCAIAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yGz3K NPr7rPYq6hOzggCA0bbZs0ou1LBUegVU9bzLCYtPnmMDokpHtk4D3zTo5vvhzGxAHh6gY52l9T/N 4uwE+FDlpmbYW2c4mHLRyAGzsAkWcHM5wLkN3s2FpvEp211F2xEzESW2p4yk4jzvctQpWZBu52vX jwdSTmy/4/FhRsHZHV3Ncep+myPe1KTJ+Mt/qoQ0T/w43E0TGzSMhOSh/wD5v9CrKzq/q92X29Pb pv0WWz/SihEDbcG9WCcPYRo2H+xvMzRpkjBk+WbU90ReTYGbwHJG17Xtc6qaFZ1H1OMz1x1SOE5s w93l6y+LuA+532xDbwX+RGD1H/4hbQdidMdxbiCXt8VGVREfP/8ADpJOzPEo4ezmX+HhKPiGdQf+ IGANusuc86BLk/Gx1pDmPZGwUgbDsDuJsPa/JG54fUGLKD4ninF9Qf1QfVWy8lLRIsWhxJtslAdD PuKdAJdFiNNst/6o8E6b7RwSTsiorsurE1sD6qKZo9WiOg0ps4+lzznmwdKRXB0COSeDbw3k623x xR9JX0H6HIYCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAg CAIAgCAIAgCAIAgCAIAgCAIAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4q bUclVfl7yGz3KNPr7rPYq6hOzggCAIDxN1auzzHeJ9sL6lh3CNaq0k6jwIPLyksYjA8Oi3bccRvD yominr3Z7BmpfAOHZedl4ktNQqXLMjQYgs6G8QmhzSOBBuEIzrnqxMP1rE2w+epWH6VN1SfdOysR kvLM33kNiguIHQEBo3UG4QxZhKRxhCxRhyp0UzMeUfLicg7nKgMiB27z2yv3wlys0Lq1dnOPcVbY xU8N4Rq9VkvYeBB64lYG+zfD4pIvzjeCJg9XbJKfMU/ZXhKQqMk6VnJaiycGPBisAfCe2CwOa4c4 IIKBni3Y7sq2kUnqhaHW53A9alaXArsSNEmYkABjIRc+zib6WIS+hT1z1RGzk7Udl89hiXmYMrUB EZNSEaMCYbY8M5B1s91wLmki9t69jaxGTytsrluqN2HTVSp1J2cTFXkZyKHxoBhdcwjEaN0RIb4L rgkAXvqAMgUui6HDrGyvbvt02jCvYvw8MOQ4zGQIkzNQxBgycBt+1hwi4xHntnEA6uObmjRfoB6e 2207EmHNgRwbszok/Up58nCo0oIDm78tL8nuPiucS3PcaQCM95zTzotAecNi/Uo4mr8jPzuMp+qY MjQYrYMpBgtY+LFbu3c4kOybmABfOxvwS9xwMe2bqUcWUJlOmMFTNRxmZgvhzrY5hwosCwG4QXP7 ZpG8NcrDnS44nqrqdY+MnbKaVIY9o83TK7TWdZReuHtcZljABDigtc6922Bub7zXHQhRBnYapAgC AIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCA IAgCAIAgCAIDx11Rndlr3i/m8JdvbL8lUvm7zOsdoeUanV3UOpz7stB8Y83iptRyVV+XvIbPco0+ vus9irqE7OCAIDUNrE1OymHpaJIzMeXiGca0ugxCxxbuPNrjhkMkB10yuV0tA9l6lc6fyl/pUM3M 8KrVwxADWKjpa3XL/SpcqZnbVa7feFVnySLWMw8gfKrcb1jMyr1gtzqc6LXy64f6VC3M8KqVa297 Iz5vw64f6VbkbsX9k6uW2FRnbAa8u65+VS+pN4t7JVZlr1OcIP8Az3H/AFVuVO5kbU6oST7ITlrf 27svlUuLktqVVuCZ+b+Pd6VbkuTEqNTDreyM23+/d6UuRMxtqFXDi41KdLeH1d3pVLckVOqtsRPT hPEGYd6ULco+pVUg2qU50WmHelBcxuqVXcCRUp0cMph3pQiZV9RrLNalPEj/AJ7h/qhbnFmKxVy4 kVSfb0CZf6UFzCKvW3G4q9QAtoZl3pQlyrqrXLf0zUL8P5S/0qXKmU9lq7/+YqP+Kf6ULvFPZivb 1jWKj/in+lBcj2ZroH9L1LmB67f6VTNyDWa7f+maj/in+lDW8V9mK/n/AMaqWX/VP9KF3iprNfsb VmpDxt/pRsm8Q2s1/wB9WakD+dv9KC5X2ZxDf+m6l/in+lEyXJNZxD/+ZqX+Lf6ULvEGtYh4Vqpf 4p/pVJvFXVqv2P8Axqpg9E2/0qFUiG1uv2t7OVO/52/0pcu8DWsQ6+zVTvzddv8ASpcu8gKziEtz rdUv+dv9KociHVnEIv8A8bqn+Lf6VLmbg1rEF/6bqg8bf6VRvEezWIb/ANN1S353E9KXLvosKxiH /wDN1TMffb/SlxvEezWIcv8AjdT6f5W/0pcbxU1rEN/6cqh702/0oN4qa5iK4/43VP8AFv8AShpN c5IrWIjrW6p/i3+lCb3uJdW8QA5VyqW/O3+lApIGt4iyJrVUHjcT0omauugr7OYiIyrlT/xb/Spc XXQT7N4iF7Vyp25+u3+lLmk4kOrmIrf03VP8XE9KXLoYnV3EQFvZyrAH/rIl/pS5HZGP2dxOQQK3 VdMiZyJf6U4hNFxXcRnL2dquWX14/wBKIaFX13Eg/wDXar/jInpS5dLFIlfxKBlXqpb88ielGLI4 tQquI5yV63OJa7AzB34NRitfkb6hyljXq9BmGIMSm1q9VRbK3XsTP5VWFZ8xHtgxNYD2eqwP55E9 Kzc04x6CDiHEwz9n6r/jInpVM7sSnthxLf7IKtn/ANbE9Kalsuge2LE1rez9W/xsT0qltHoKe2HE 5cP/ADDVx0dexPSpexUo9BZuI8TXscQ1b/GRPSlytRvwKnEeJ7Ee2Cr3/PYnpS4UY9BR2I8TjTEF Yz0/l0T0qoy0ugs3EeKCfsgq/wDjYnpWW7EsugHEeKNPZ+r/AONielTeFl0FHYkxQLXr9Xt0TsT0 raL6vQVGJcTnePthrAy06+ifxKltFcxAxJinX2wVj/HRPSoHu9B3LsPnp+fwnNRqjOzE3FbPPaHx 4piODeThm1yTlcnyqnj1bX0N8Q4wgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfG PN4qbUclVfl7yGz3KNPr7rPYq6hOzggCA0za+L4bluicb+w9RkZ1jDeG++00UMKxyGPaePbc6zvI 0chjha+R8KtzLWpmhkGxNu8qVXM0N4BI1Qze5drjpf5Fl6FsZQTkEiypFw+7SMloMu0huYIOV8+K y0wmBuuzcT0KpDRlQ7dIs4W6Stiz6Cd5rgSDn30F0VuCSCbnjmhSCdwcNdEIzDGigXvmVnUlzgPd vxCbAZ8yqHEs1tr5KlSKRBzG6jKYYhuN0aqkbIGYFzwQqKPNr5f7IRqxjPRx6EJdlCRkb8UGpZzb 9sPkQ0Y+KEuyQQeCFuQT0oLjPmQwyDrzoaQDQDcjNDTYJbfd48UI3biRcXHHpClyNkON9LKl1Rhc 4B1i4X43Kj04mb34GdgBaHCx7xUTuWLTWhIcM1otypIPOUBxpqblZOHys3MwJaHe2/GiBjT4SVid SFNXm0vjp+Zz4bC18VLcw8HN9EU5P6K7ErMys5DMWUmYEzDBsXwYgeAe+EhUjPWLuXE4XEYSW5iK coPoknF/R2ZmAF8tVs4Q8XytZCFQO14+FZsE2LC6WNcQbaKBGCXm5OaLxKzcvMGGbPEKK1+6emxy WYVITuotOx5dfCYnDKPnqcoqWq3otJr3NpXLusFo8TiUiai17FNQtCGjdcTwQ1xJfbTVVm0YoluZ VgoBnZZcgQ4WU4lTsY3e5vxRRN3KHIaraM3IJNrA5ILsrYuNiO9mo2VRZA46ZLPOL2JLQQCqyXZS xzvYBZuXeIvZuQV4jeDd4d5N3QqdyxyOQRIrKGxNudaRxkEOGVrK3RreKOFsiTZZuFI7t2CADB83 Yf8AqD/3cNaRxVeJ2EqcYQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqO Sqvy95DZ7lGn191nsVdQnZwQBAabte+xuX/PG/sPQj4HVsMWtkuKRxo5LQBkAsamzIBmNPKrcjRl YbWyOQWtS3MzL73fS5EZ2G2QCFMrSSUAuLDj4VUzIJ6dFohZsQ2zCXKjWNo9Fpc/harzkzIwHTUK TfEhx9z6o1zW3b22uRA+heBjqFOdGcpR1te59Vsnm2Mw2Z4ajSqNQc0nG+jUmk9P3qdFbOJOWqmN abIVCGY8tGiOD4ZcQHDcceHeXzGBhGpXjCS0Z35tdi62ByeviMPLdnFKzsulHdkzs3wfGglgpxgb 2TXw5hzXA9FyV9LLK8I1bdsdF0Nvs+hJSdbetzOKt12R8zZlh9+F8SYjpjozo0HclYkCIci5h5W1 xzixHgXDl2HeGrVIceH6nsNs8+hnmXYLFxjuyvUUl0Nbn6NPrN5NnX+659V7ZSu7HXtmUbCLiWt1 4jitXHAxElt889Cl0W/MUJ3jlYE56pct0Y90g9/il0zLVtWQBYX/APneS5bpIrqdO8jduJG9DGbj TwKkUugqRcWOSFv0htxkBdRtIKSIPbHIHwBLjiwQLZIS/MULSCLgj5FSp34Fiw26UMvoKFpANroi pgE2yzPlWWxvcxoe2OTlvYKFP8i0TLIzWCKNd03yJ5l6XO6UXRU2tb2udn+S7HV/8Slhd57ji3bm vpr8TDsRu6k1K5J+rMGv4JWcjk/NzPI8rMUsZh1b+GX5o394OZGWa99bWyOqH0s0jatTpV+Hos+6 DD65huYBFHurXtbvL1GbUoOg6ltek7E8m+YYqOawwim/NSUvV5r2ve3Tp1858rYk53K1MHS0Pjpq vDyJ3c+o+l8rStHDfGX6HZpFszqvojpYxTMVkGBEjPvuw2Fx8AKk5KMW2c1Gm6tSNNc7S+rsdRYP nouItocvGqgbHa8RSyFEG8xtmOIFjlYL5bBVni8anV1vfTmO/dp8BDZ/ZipTwPqNOCclpJ3kk3dd OvVobVgrB9SoeIJifizkHrVzXtbDgk9vc3G8LWFv9F7HA5dUw1ZzlL1ejpPiNqtssHnOW08NSpS8 5FpuUraWVnZ31v8AvU3hoyzPyr3FzrbXh/Yggk8FoFXDKxyHBC6EEZ2+ngo30i58fGJje1SomXcW xBAJBbqOf5Lrw8dvfZ57vQe/2UVKecYbzqTi5LR9PN22OstlHLnFjBCeWs5F5iDgRbIFfO5Rf7Rp 0XO6vKOqX+Cy84rvejbpvfwO4NDn3l9bLRn55vpqVPfy4IZvqPeqXNIob2uNERveKvutMpjB0XGx cEHO6AxnmVVwVe3Oy0gRYbuippPQq4A5qOzNX0IIyNmpwMC3a2OSjdyoqW8ygdiCM7O+RWxkaBUt wQb5rPAt7kAZWWri5Z++WtBN7aLD0IypsBmiB3TsI+xGa/P3/u4a5Ecc+J2AqYCAIDx11Rndlr3i /m8JdvbL8lUvm7zOsdoeUanV3UOpz7stB8Y83iptRyVV+XvIbPco0+vus9irqE7OCAIDTNr5thqX /PG/sPUYZ1cwaELjejOFy1M7SBmTmobuZmuAZkBYpui5kabHVUjMrHEBRlTMm9Yk5pwDZZsQgWHH ipclzIwg8VVqQs4i/SuRIFgTzhUHx8bk+0ytZ/aEb9krxcYv8ifwf5Hudm+WML/9SHeR582aTsrT 8b0yenY7YEvCiOL4hBIHaOHDNfJ4CcYYiMpcFf8AI/Ru2GFrYzJq9CjHelJKy6dUdpz+NqZXMZ0G jUWK+PAZOCNHj7pYHFrHBrRcXOZJOXAL3s8fTr4inSpu6vds6kwuyGMyvJ8ZjsdFRk4OMY3TavJX babWtrLntc7AjQobw9x7SJEYIbojMnkC5GfRvG3fXtXFS+J11CvOO6uKTbSeqvpf62V/gjojEGKs RUfGczTTiCddJSs4WXduk7gdnfLPK6+Xr4yvSruG+91PsO/8q2YynMsmp4r7LDzk4X0vbeafv01P r41mNodQjS9Sp8vPS1Pj5ysvKkmI1vvXRQ3O51zyC8jF1MbUtUppqL4W6Peek2cobJ4GNTCYicJV o/elP7ra4qDejUeGmrfSbVjLE8fDOFZWPNMbEqseG1gadOU3RvuNuAPyr2OLxksLQTlrJnxOzuzV LP8ANqtOi2qEW3dcd2/qpX53+R8GXp9cnMDPxJMV+otqb4DpuG1kXdhNaLkN3RkbtF+i68WNKtPD faJTe9a610+h9DiMwy7CZ8spo4SDoKUabvFOTfBve4qzdj7GzHFMXElJfDmw3r6ULWvLRYRGkZO6 DrdeXlmMeKg1L7yPR7dbMQyHFxnQ/wBKd7X5rcVfntzXPhzGJJ3FON20ClTkSUpkNzuWjQTaJGa3 3RB4AnIW768OWMnjMT5mm7R6UfQUdnMNs5kTzPHU1Ou7Wi9VFy4JrnaWrv8AAwVysT+CMWS0Az0z PUmZYHvhzD99zBezi12txa6zWr1MuxCipNxfMzmyvJ8Ltdk9SoqcaeJptpSgrJu11dcLPg/qdmAh wBBBBFwRxHOvoE01dc50604tp6fuz7SkeHykJ7A57d5pG802IuDmOlGrqxulV3JqVk7cz1T+KOk6 niXEsjiiNT4VXm5hkKa3Gsc4XiAO0Jtx0XyVXG4mnXcFNuztqforA7NZJjMqhi5YeEHKF21fTTja /NxR9vaLAxXTZCHW5muPYXxgx0rLksZBuCQAQe2ta2i8rMI4qlBVZT57WXMfM7F4jZ/H4iWW0cIm lFtTlq5WsnpbS97qzOVg+sYmxTR+soM0yTfAO7HqDmhznXHata37o2NyuXB4nE4ynuxdmuMjwdp8 myLZrHLEVIOop6wpJ2St95t66cN1dPOa5IYgr2HMZPkJmpRpuHDmeSjtiOJa8E2uL6ZFeDDFV8Li XCUm1ezPr8Xs9lOf5GsVQoRhKUN6LSs07cNLX6DtfElVgUSix6lHzbDHatBzc4+5HlX0mJrxw9KU 5a2OjcjyqtnGOp4Slo5c/QlxfUaPgmJU8YxZ+oVSqTsCBBc1kKDKxTCa0uBPDPKw8q9TgnVx7lOp Nq3MtDsrayGB2ShQwuCoQlOablKa3tFZcHprr9DHQ8VT9FxdHw7WJp03LNjmAyO8duz7kkjUZhTD 46ph8Q8PUd1e2pvN9ksJm2SwzfL6fm6jjvOC+6+lW6VqfV2y29qQyt/KWfQVz5z/AMMviv1PQ+S3 lr5JfocDYd/RNS/LsH+UrhyFXpzXvR7Xytu2Nw3/ACy/NHCxxiupzmI/a/Q5gy7RFEu6Iw2dEiEg EX4AHLwLizDMKlSt5mi7a26z2OyOyGAwmV/4tmUN57rnZ8FFarTnbWvWZsd0eqUnCsZraxMVCUe5 gjtms3NO8LOYddeC5Mww1Whh367lHS9/0PG2PzrL80zmm5YaNGqlJxcNE9NVJcOGqehi2IDefU/x Yf8AqsZDxn1fqeV5W/uYX4y/Q7NsACL3X0aR0rc+RiiRmpymnrSpxpAw2vc8w2g8oN09qb8F4uMp TqQ9Se7btPf7PY/DYPFJ16Cq71kr6buq1Vuc6e2fS0xOYqlpeVnYkjFcyJaNDALm2YSdefTwr5PL oSqYhRjLdeuq+B+hNtMVRwmT1K1ekqsU4+q+D9ZflxO3MS1luGsOddx3GamBuwoe9kYkSxzNtNCS vqcViPslC71fBfE6C2eyV7Q5oqFNbkNZSt/DH3X4u7SX15jXaBJ1bEGG41bnK3PQpqJvulmwYm5D hht7dqNbkFeBh6dbE0HWnNp82ui6j7DOcZl2R5rDLcPhYSpx3d9yW9J36JPVWT5jlbMcUR63AjyF QcHTks0Pa8D+cZexJ6QbeVcuVY6WIThP7yPC2+2UpZPUhisKrUpt6fyy0tZ9DV3bmscPEOI56qYu hYZo8wZaDyvJzEwz3biBdwB4ALgxOOnXxCw9F2XT+Z5+S7M4XLcllnWYw352vGD4L+W/S3x9xgxX OT+C6vIxpWempuRmWu5WBMxDEN2kXIJ01CzjKtXL6sXGTafM9TyNnMBg9rsHXp16UadWFrSglHin a6WnFdZvQMCpU0OY4OgTcDI21a5v+692t2pD3M6uarZfi/W0nTl2xfijQdkVMfLT1VmIrbPgv61F +cE730BekyWhuyqSfNp4naflOzWNfD4SlTekl5zqaSX5s7DtcadK9+kdRXK2zOnlSwuQ4JYJkG27 qspmo6cSjs1ps3vJmNzb5hYIVIHSFblvYW5tFGzRV1tSquAKG2YSzBU25/kWrGuYcEauRh2QWVGx CgBOirRSxtfMLNiFXNuiYILctVSogC2aEGg4o1cFDm7MKpFR3XsJ+xGb/P3/ALuGqjinxN/VMhAE B466ozuy17xfzeEu3tl+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq/L3kNnuUafX3WexV1CdnB AEBpe2D7Gpa/3639h6GZHVsI8LLilxONxMrCTwKIIzQz2vMqjdjLvAZhS1hcy56Hv6ILF2usL5KE aLNdlbUrJngZQRbJVaGXclp4nVbbNLgSXOBy0RalPj41d/5NrWZ+sI37JXBjP9Cp8H+R7jZvljC/ /Uh3kdEbJrdkKkXzHKO1/Ecvlctt9qh8f0P0Nt3dZBiWnzLvI7kxDh6SOJqFXJKTbDmYU6GRzCZY Ohua7MgcxtnzEr6GvhYqrTqwWqep0jlOf1/8OxeX16l4SheN9bSTWi+KvobQ6wtfJeytZnx/Qecc csbE2mVJjhdrqiQR0FwXxmMV8XJe8/T+zEnDZuhJc1L9GeiA0CE0ACwbYBfZR4aH5ik25Nv3nT23 90Q1alNsTDEB5H429n8ll83nr/zIfD9Tu7yTRh9kxLXHej9LO35s2DB1HmqvgqRc3E9Shy8eVMJ8 BjIe60C7C0Xbe2R6fKvOwmHlWw8bVHa3DTm48x8ttHm1DLM8rp4Km5xnvKT37tu0k361vpoczD2D ZbCrZ+Zp85NRosWWcwCJa1wLt0Gui5sNgIYTenTbba/7Hrs62wrbROhRxVOMYxknpfnsnxb0sdW7 MGPi4tgwIVRjSESLDe1sWCGlxNr2zBHD5F8/ll3iElLdvzo7k27nCllE6s6SqKMk2ne3RfRp852R W8AQqzFZGqdeqU1Eht3WFwhiw8DV7ytlUa7TnNt9R1HlnlBqZXBwweFpwT1f39dOP3jbZGWEpIy8 q2I6IIEJsIPdq4NAAJ6cl7OEdyKiubQ+Hxlf7TXnXcbObcrfF3/Uy8/MtHjWOgK73Q5j/uA/bC+L r/8AGP8A5v1P1FlC/wDDNN//AMX/ALWdkbafsQzJP8sh/Q9e/wA6/wCG61+R0/5K+XP/ALcvzifM 2Gf0TUh/z2H/ACFePkS/y5/H9D3Hlc0xeG/5Zd5Gl417oU/r9ej/AEXqsb/xkvidi7Kr/wAM0P8A 6b/Jm97aTE9q0o1m9u9dN37fiusvcZ239njbpOsPJWof4xWT47jt/wBSKbE7e1ydOV+u7H9RqmRf 6M/j+hryst/4nRi/Z/8AukaNtCLvb1UTD/nOWba33Qa3/VeozL/jJ26Ts7YlL0dw+/w3X9Ly/Q3/ AGvAjBsO+vLw79+xuvd5z/wy+K/I6n8mNv8AHZW/ll+ZxNhgvTahfTrhn0FceQaQn8Uex8rqvjMO v9svzNGw855x7KOmL8oagN6/3W/6V6bDO2Ljf+b9TszO4xWzlZUuHmtPhu8fodobVB/5JnL2vvwz /nC+kza32WXUdJ+Tl/8AiCj8Jd1mt7D779Ttb3MP/VeuyHjPq/U+y8rb9TC/GX5I7KDhmDmV9JY6 VMNQ+sJg/wDKd+yVx1fuM8rBf8TT+K/NHTeyb7OpP8nF/duXyGT/APFR6/yZ+jPKQ/8Aw9W+MO+j ZtuTonW9IaL8mXRSbcTZnpK9lnzdodGp8X5JIw87i3/ElD6Xl+vHqOTs9p81UMJy74OIZ6WYC+G6 DDbDLWG+mbb6Z+Fby6lKrhk1Ua5raeB4m2mY4fA51UjUwcJy0kpPfu1bjpJLR6dR9bDGDJLD9VdU JWcmo0Uw3MLX7u6QbG+QHMvKw2WwwtTzkZO56HP9t8TnmEWEr0oxjdPS99L9LfvX5nWGGHRHY2gt 68iSkSJMOZyrLbzSb84t0eFfO4W7xaV7O71O6M/jCGQTfm1UjGCe672aVnzNPt5jsmsYKbVxCFTr 1RmRCvyZc1gtfU5N6PkXv62VqvbzlRu3w8Dp3K9u3lSbweEpx3uNt/W3zPpPv0qSZTaXL0+G+JEE CGGNdEycQNL2XsKNJUqcaa1sfJ5ljpY/GVMXNJOcm3bpfRx5785x6NIskYlQLYjH9czkSZO773eA yPkKxh6Sp79ne8m9PeeTmuPljVhlJNebpxhrz7t9V9T6ByvdeQeoWupU2JyVLYqSQbXQFCOBKyVk FQIg6IauUcLpY1YroNUshdoo7nCoV2VIuNc1pGkLA8Vm+ppEEDQLQIIvkpcxYgZBRlJvxISwKm6J FIsUBPDgj1FipvzocblcqQ660jkR3RsI+xGb/wC4P/dw0OOfE7AQwEAQHjrqjO7LXvF/N4S7e2X5 KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ2cEAQGlbYjbDMsf+tb+w9Rm ZcDqphzz0XGyXMrSQbX10UMnIhuyt9K0nYpcXHBRyuLGRjiDzIXUykjKxF1LNksWvoSdFGrAuAN2 90TLYne0zWmZLF+V0iwa/jmdjuoNRpklSqhOTMzLuhMMGATD7YWuXnLK+a8TG1JeblCEW2/d/c+n 2Zw1GOOoYqvXhTjCSk96ST9V34cdeY6kwVh3E1DxRIVWZw5U3wZeJeIIcIF1iC3IEjPNehwmExFC tGcoOy9x3HtHtBk+a5ZWwlHFwUpLS70ve+uh3pJTYmYAiiDMQdRuxoZhuHgK+ppy3le1vifnzEUH h57m9GVv5Wmvqv8AuWjRAyE6I5rnBoJ3WNuT3hxK03bU46cN+ajdK+l3ovqdE4gw/iWoYxmqzBw9 UeQizfLsa6GA4t3r555HJfKV8LiKld1VTdr3P0LlG0GT4PJ6eBni6e9GG63fS9rdHC53dT5szcpD j8hMy29kYUeHuPaRzhfU0570b2t8ToDF4f7PWdPfjL3xd19f3Y1jadhV+JqRD60cwT0s4uhbxsHA 6tvw0C8HMcG8VT9T7yPrditpoZFjH55PzVRWlbmtwfbr7uBoWDKhjXC730tmHZuagvcXiA+E4brr WLmuA0y7y9Rg6mLwt4Km2vgzsTaTBbN7QwjjJYyMJJW3lKOq6Gnz/Ro7Lw5LVVzolVrbmMnI7Ghk rDdeHLw9Q38JxOp6LL3+Fp1NalXi+Zcx1FnWKwChHB5em6cOM396crfe90Vb1Vx6dTq3FmDK1Qq6 ajQ5eNGluV5WC6AN58E3vuuGuXPYhfO4vL62HqecpK6O49nts8tzfA/Zcxmo1LbslLRS96fDXnXF P3G2Uar4zxHLtk41LbSYTxux59wc11jk7k2n3x59AvZ0a+LxMd2UN1c7PhsyynZrIqjxFPEefktY 0k01fm32uMV0aN8NTeIMNkKAyDDu1kNoawE3IAyGfgXuFHdSj0HXNapKpOVSbu222+F2+OnMRHdy cF0Qse8NF92G27jbOwHEo9FfoJSi6k4wTSu7XfBX6ehe/U6TqNAxHM4oi1ZlAqHIvmuWDTDs7dDg efXJfJVMJiJVnVVN2vfgforAbRZJh8ohgZ4ynvKG63fS9mujpN12nCfrWHoElTqRUIsWLFbHcORt ybQHCzuZ1zpzL2+aKpXoqEIO714f3Ot9gZYTKMzqYnGYmnGMYuK9b7zbi7rT7tk9enmOHsplalRI E7KVGkz8ExXCLDicldpDWkEXvrzc64spp1cOpRqQav7v7nsPKLjMDnFSjXweJhPdvFre1W81Z8OH S+Y1XEFCxFUcUTVVg0CoCDFmOVa10Ptt2/f6F67EYXEVK8qm47XvwPtsl2gybAZPSwNTGU3KMd1t PS+tzs6r0+DiTDb5WYhR5Xlm5CLDs+E8Zgkcc/kX0daisXQ3GrX6ek6Ty3Mqmz+axxFKSnuv+F3U k+ZP3rhpozUsFGo4PfO0+rUqefBivbEgxpaFyzXEAg6cCLW4jivU4FzwG9CrFtPnWp9/tYsHtXGh isBXgpwTUozlutJu649Gt+Z81zBQsK1GtYujYhq8m+SlHTBjsgxhaI/PtRbgBkph8DVxGJdeorK9 9TyM52uwWUZLDKMBVVWpu7rlH7q5m78LvWyXDi7H29qcGeqVKZTKfTZuZiGI2I58OHdjQL8eJ6F5 WbRnVp+bpxbfE+b8nmJwmX42WNxdeEI2cbN6tu3NzL385wtlEpU6PDmpKoUqdgGPEa+HEMLtMgci eCxlFOph7wqQavrfmPY+UfG4HNZ0sTg8RCagmmr+tq1Zpc/VqfFxzhOqSOIX1ujwHx4MSLy9oTd5 0KJe5uOa+fhXh5hl9WlV89SV1x6+J9HshthgMXlqy3MZqMorc10Uo2tx4Xtpa/wb4n0sUTmI8S4W e2FQ40lCuwvY4F7477jJjbXDRrdeRiqmJxdCyhZfVv3Je49Ns9gsl2dzeLni1Ul61mrRjBW1c3dp t8EkV2XUrEFGnI/XdIcyBMBoc98VrSy1/e6nXoTKsPXw83vQ0fS0uzib8oOcZNnFGmqGJvOneyUW 07/7tErW99+B2MQL5c69/c6gWpwa7HdL0yLuSk1NRHw3NZDl4e8b248wXBiajjTdk38D2uUYWNfE x3qkacU025O2l+bpZ1dgei16iYnlahN0OfMCGHtfycLePbMLb2vnmV83gMNXw9ZVJU3b4dJ3dtdn mU5xlNXCUMXBSdmruy0kpdGmiOwMbUMYkw/1vCJhTDHCNAdEaRZwBu1w4XB8q95j8KsXS3eD4o6o 2Vz57PZk60lvQa3ZW6Lp3jzO1r+9X6dOvsMRcW4VnYsrDoszHhxXdtALHFriNHNcOPSvRYSWLwcm lTbT46Ha+0FHZzaahCtPFxg4cJJq9nzST/LijsSgwqvNRzVK01ktE3NyBKMcSILTYlzud5sO8Avf 4eNWcvO1lZ8y8TqPOauXYen9hy5ucb3lUa1k1eyiuaKu/wDmfG9jQ8d4PqctWYlUo8vEjwIr+VIh Zvgvvciw1HG4XpMwy6rCbq0tU39DtHY7bbBVsFHA5hNQnFbvraKUeb3Xto07X4q+tvt0Kt4yqsuy U9imSr/cvqEdrmho4ndOrrc3Febh8RjcRHze5bmcj5vN8j2Yyyo8T9pc1xVKLTb911wj8ebS7Nkq knNQ8Lx5ClxHmO2XLILnO7YkDUnnOa9hVpy+zuNJ62PjMBjaM83hicbFbjneSS0tfo4WWnV0mh7L 6XXZXEEWLMS8zLyzWObH5VpaHO6L6lelymhiIV95rTnO0vKDmuUYnLIwpTjOo2t3ds7LnbtwTR2d clfSK3MdIrhZlb8+RVNFTmbrNwVJNhxUBF8s0CRUnpVNKJQm+SjdjkRU3CcSWKlUqIOiXBHC6XRp cRkVWGQ7nUXEhGfBVoCx6LLO8QgjoKqZoghXiQga24KlJDQRcaBSxhrUxu0ORVNo7p2E/YjNfn7/ AN3DQ4p8Tf0MBAEB466ozuy17xfzeEu3tl+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq/L3kNn uUafX3WexV1CdnBAEBpW2P7GJb89b+w9RmZK51Rfhe9+ZcfOZehmY7jxWecaGRriD2qoMwe3wrJb lxE4WuquIuXY9tzfVaaZdC5eLCyJdIsTvkaC6WRGW3jlkoQneKX1IWB7yt+kAuI0ctbwIB7yjZqx G9c5WQNCx6Foy0Y3mxz11QFd4811bh6kb5GQPgS/OZaRBdlmLKMkkpGNx7bLSycC36Q51xfir7yW uQDwuiD95Bta1rqmSDqgKW6UBGVtFC2FlSEEDNAQTa1lbksiDpe2ahoa6pcidtChyNiquBtA8+Y6 UuTREXOZ4oGuYhtsrBCsk3bxQXLNJyuSoaRU68+eSPXiZXEkZEWQ0LkjK6AAi1s7obKOJuhnd0Gf Oo1c0lYo4Eq89ypaAm/EoLIqSssc5FsrrN2ChJztwS5UyrjfhqlzdkVJtldW5EyD0Km2yG6rLNEF wubqXIVNm65qXYKHM2C2iog99LFY0POpcl9BYHJbuER3ypcMm4U4Aj3ypmTZNs72uqiplXZlU0Do Vm5Ctuk+RW4udz7C/sSmvz9/7uGiOKTuzflTIQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6 h1OfdloPjHm8VNqOSqvy95DZ7lGn191nsVdQnZwQBAaVtk+xiW/PW/sPUZHwOpQbOvdcbMGRp43W bEMjXEanRXUGSGeByPOoyozC3Nkqi2Ld4WVuLF2C3AqXKWvbOxWrBlgctFDJIJ4hVIgvnorZAsHk 5WCWBBOXSpbUjkQbc6nAsdUQ57t0WK0isqTmqQgZhLgre2WpQy5Am9uayGih5zkhhu5W99DkiLFj w3VsJcCLgKmEVJ4lZZVYqDcaLSDsQhCSctEBG9fU2QFbAlALlARc97pQFbEm9kNKwJsbHRUfAqCO dDRkGl7KFHkQEaG9h4EBBPEICu8CTnwQpJJ8CCxXeytwQXYvz3Q0VvbNCkoUrewQFHEXUYG94Fxk IJtmDqhDG45qmrlHLaNxSKuNjkfAjNNXKg3WJFBICyugFbiytgQfkKqdgRwurvAkZDJR8QQee6J8 xSG3dmRxWylra5KCxDQQSSoyWJHSFIkIeLnIKpgk6JLiVlOGqkTD9x3NsLzwlNfn7/3cNbRiRvyp AgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yGz3KNPr7rPYq6h OzggCA0nbN9i8t+et/YeoyNXOpB7q11xmbFg7MhWxDkMJDQDZSxq5kY5o4rNhcyNfzIkxckPsFqw uXD8rA2U3SNklx3VtWROJYPO6lrsm9zEhxsqC1xu6m6C5G+RnxRocxG/ccEBbeNuCWBQk9CWBDiQ UBG8bKNXI0QXdtdUjRQnPihAe2Od0Q0IvY5KhNFbm5VEuJBJ1QsbFd4XzF1loxe5V5zuqgU3yXaZ ql0LusM87oQqdLlCsmw4XQg8qXBHA6oCe9ZCpGJ1rkFU0ABrkhS4coExfPNC3JLhkboRsqXC+iET K5XvdDdyC/mKC4uENEZf/CgByIy+VAQTdCoq4lClHGxUbBBzz5lm5LlHEqBEE+VEVFHGx+lVFSKP ve9kXE5Uit7G6MBzjqscAV6bCy0pXKLkA5KANzHfVIN7glgBYlGiknS7c1bhOwAsOK0bTROZIyWL EbJAzzUWhkkjIqkKcTl8q1c0VsckuZO59hv2JTX5+/8Adw1UYnxN9VMBAEB466ozuy17xfzeEu3t l+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq/L3kNnuUafX3WexV1CdnBAEBo+2j7F5b89Z+xEQ zN2R1IHA5k98LDMXLw88+HBVAysOg5lndBdosL5XKhUXa62RQGRhabqtC5YFtiL5qoE3JFsksWwa SMiroZa1LA56LNxcm50WiWuRcjInMoEhcnihSRe+qAX1uhGwHA5KoIrfNQO4LrcEM685W/bd4ICN 7PRLXIyvObolYhHlPhVZbkXtwREBAVBR1kBAA1zQFr5Z6oCp4aILi6Ad9RKwIvYdCoI3rmyBkOGS gKC97DMLRsXIOmSpS1zYngoQXBGSgIvYlC2IQ0ioadSckLYm5yyQpCAglAVccroVFLkqXKQ5OIK3 IupYFXO4LNgVe4XAVQRVxy4KpG1qULjfwJY2VJOpQXI3jfPJRojZXfPH6ESsLsneJCiRS2nBTnBX jkuUtyQSNVLAkd/yJZBki9wpcFrkaGyaAs26jSIN486yDGTqNc1yIvMDe1yiVgdy7CzfCU1+fv8A 3cNU458TfkMBAEB466ozuy17xfzeEu3tl+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq/L3kNnu UafX3WexV1CdnBAEBo22sXwrLfnzP2IijI0dSNFhmFDjMjTnogLC980BkGWeqFSLOcSOhQl2WbYG /Oo2CwyJJ4rS4Au0qM0mWvlcrNmVgOsM1UkzjauQHLQSsN7PJClgbDRZvqS5IcBZaI2Q1w0AQyAR fMKo0mHW04KFuVOmSpG0wTYXUZllN5BxGdrX1WiEICriQdUA4XGaAgnigK34oAeg+FADnqgGd0BU nwoAQbICpDkLcG4FroCm8R4VTSJBt0qlLB5ItZSxCBcFQJEOdnmENlSb95BwJDrjRDVyLG+qAEmy FKO76AjouhStzbgs2BU3uc1QQDkoWxQm5UuUo4Z3OquociDoojUSLKN6miHWslxYgjoBUbKVcDkt J6EFu2ClwSchYrKBAyzW9Sgi+it7AloNrGyXDLgC6JBE5Aq2NO1iwsD4EsZsQW/KoW2hUN1IHStE uMzkAhTuXYYLYSmvz9/7uGhxT4m+oYCAIDx11Rndlr3i/m8JdvbL8lUvm7zOsdoeUanV3UOpz7st B8Y83iptRyVV+XvIbPco0+vus9irqE7OCAIDRttZthaV/PmfsRESuZkdSsDnDeBupYyy4adAhC2g Idko3YFw4g5kIaTLDTnugZIOgOaliFxmM8uZUrJbrZDN7F9dOGqpW7hx7a4vZZsTgRmTkbBUFhe2 aAgHghhk8QNLIC1gBYK2JfpIt0pYr9wLm3tcJcKSsQHHoS5GQ4Z5I0RlSLJY0pEOO6hm4JAGqpSC 0cShAG242QEEHQ6ICC3JARoM0KxnzoQhw4oCB0oAT4FAVDsuCpbB2Y4ITgULchcq3NbwyH/0hRc8 AqCzbnW4UYuUfe9lDSZFuAQq1AFroasCTcZICLjgRkgIN9VGilXfT0KWBW//AMsrcpQnO4RsFScl mxqNyLEnRSxSCMr8VTLdyhyWVoaWhUki54WVeppMi97ZFN0pYAHI3WQQbDIq2Ddim722qWKStpAX F1bFJFuGqWBLbFZehC9ri+S0giRzqi4JudRbvIUcP9VARunKwsiVgXDe1Qw73O4tiIthWb/P3/u4 apmfE3tDAQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOSqvy95DZ7lGn 191nsVdQnZwQBAaLts+xWV/Pmfu4iqMy4HW9FppnoMR7Yu4GEA5XvdQ4nI+oMPZXMyL/AIqFTucW cwrHjAclUhC/u7/6obscc4SqDRutrEM5WuYJz+VSxLEjCdT3A1tWgdN4R9KpolmE6rDADapLEdLH KMhBwzWrf0lLWvwa5Uid+JZuH62Bczcqe+HKWLoS2h1tv9dJnwu9CBIt7EVoAi8of0z6EsHqR7D1 kgW6075iH0JYwyXUqsaAStxb+sNksVEClVYE73W3geUsLXJ9h6y89p1r4Yh9CWI1YyjD9esCDKZ/ 8w+hUzYHD9etm6TI1/nD6EKloUNBrpFiZT9c+hGkHFEewVdt9qfGH0KpIiRBoVdAtuS1/wAofQlj TSK+wdeJzbK/G/7KE3UQ6iV61jClj/e/7K2I0QKLWzkYUv4IyNGkgaLXLi0GXI4/VgoN1FjQ65/Y wfjghN0CjV0D63gn++CGbMn2HrPvpaEOe0UJYWZV1Iq4z61Z8aFSkexVW+9mfGhLBor7F1a/1u34 wKEaHsZVc/5M3P8A5gQhX2MqpA/kzfjWoUr7FVXjKt+NCXLdj2Lq3CVaf71qAgUqsv1k2tIP9qCr YiRk9hawTlKt+MarY1YkUSs3ykx8a1Rhl/YascZMX/KNULZGCJR6pfOUGX/MCFWhQ0upWI62A/vA hpuxRtMqX9gPjAlhcsKTUrn6i3wxApqUqaRVjcNhQQTpeKFQXZRKycnQpc96MoW5PsBWP7OXA/K/ 7Ki5b2v1i1i2W+M/2WbFKuw5Vb3/AJNb8c+hAVOHam0G7pe3S8oUg0CoWziQB+kiNEGgz1z9Ug+U qEsT7Xp02vFg599WxUQcMzrs+uIA8qbqNlThqdb9swCO8VbFJbh2b++oA8BUcRYyMwtNu0nJcHvF VIy2WbhCdJuZ2X/VKWLvIscITdvr6X/VKJFHtPnNevJf9Uqi5cYQmr269gD9EqNk3kGYSmwSOu4H Qd0qcRe49qM59+QLfila4C6RZuE5toI68gH9EqNkckVbhabF7zcD9UqXCkV9rE0LjrqXIPfVsaMg w5Hy+rQflUuZuWOHo4GcaD5CrcXOzdk8m+Rw7MQnua4mbc64/EYP9ERiTuzb1TIQBAeOuqM7ste8 X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOSqvy95DZ7lGn191nsVdQnZwQBAaBt1du4S lDe3/EGfu4iqMyWhpuCXb1NjOPGLb5AjRwpGwAg5BQ2lYXOgCGrlictT5UJdlmkWtn5ULctcHK6F KkHwFDI3c9BdBYnID/dDSKOFja6EZP6RQhUt0QhU9/5UF7GSCMhmUF7nMZ7jXRBYjezyJQFTznNA VJB0QFHOudLK2IypfnZDJF7nVDSILtwZapxDBcbcwPBBcs0hRhMkm5760kUjLnVAPeQymVOnHyoV sqbEarLMMxPJ4IEQTldQpN8v90IA43QplhuF7eFauDM21u+qzVzK3TVYKVe4DigOHHdmbFaQOK8Z 5q6CxXgMzZR2ANtVk2Lm98kBlY8c4QGQRB0ICHRAelDSRUvBGoWGasVc/LVUGB8S1+2RkbK74vqE RVxJbEa3mWrHIDFZzhAY4kZmlxZCoNjQ8rWUuUysjtuLOCoOUJgbupshmxXrj8IoWwMfO9ygsWbH bx4qWDRcRm3yCpNC7Yzb6ILDlRc6rLMF5aDEmozYUJhc9xsAoN6wqEpMSUQQ44IOo6VrUJ3OIYgA 4rJgh0QWzuhU7m8bPXb1GjEffLv2WrSDNjVIEAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1Oruo dTn3ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ2cEAQHXe355Zg6TLeNQYP/5xFYq7MydkaXgmITRQ Rftor/8ARWSscOtzYGRHX0WS3Lh7gL3Q1cryruhCkmI62aFLNiE5j6ECLmKbaIWxjdGc2xsM0MrQ gxj0IaTI5RxzuhlsnlHDK5QhBflqgMe+b6hAZ4EQhwGqA5piODc7oDEYtv8A6QFHxnAWzN0RGVbF cDmUIir4x4lAyhim2qGSOXdxRm+YjljfpQiZJiutmFRclkU3sSq1Yti/KEcUQbsQYx5wqUcubLJx tHMpEv1/M8k525Da0ue/7gWVC1OO9reVLIb94XsD0c6jDOTXpaBItgQWOcZks3o1zkL2sFCs+S+I bZFDK4kGIedCgPPGyIhdkY9CAyiO62q0jSLmZcAqbMESbdvHNRoHHfHcSiBAiEjVR8QULjznyqFI c88CUNECISdSgLh3/wBoAHnnQEPiEcUNJmIxQFgtyC885VKipdf6SoUjXJaIuJOoVOQxOQqK71su ZCkhw4pYjMjH2NhogRyGxMgNEKW37ZlAN++d0BdrhcIC4cOdTgYtYu11zkpcNmRuY4XQxc2XBcEd dPjkXc1u63LiURJHOxPTzHli1ou9o3225hqtcxIuxpcRmoWDdjE/K6oSN62di1EjfnLv2WrRlmyo QIAgPHXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdQ6nPuy0HxjzeKm1HJVX5e8hs9yjT6+6z2Kuo Ts4IAgOueqC3fabJl2Vqiw35vqcRVEaNQwdlQZc2ALi49GqsjjPttsMiSSsixaw7/QgJvnl9CFTJ JBbdCsoTfRCEFwFrZoCjog3wUKiC42CFZLXBDBOet0NWK3J45d5BYgkC4N/Chlo5dNhh796ypm5m mHjeLQchoOhQtzj7xuLHJCORcbu6SSgcjDEdlcZ8ytxcxCIS7QoGA+6XRG9DHEcWnVUJkNe7vqC5 kBuN6+SJ2JcgxCrcqZcPuMhmhbohzgBqqaDC57hDaCXE2AtqVDjufZnYjKdJex0Nw5V5vNOB99wZ 3hx6UD00K07k5OWNUmWg2O7Lw3f1jxq7vBGVK2p8iZmokxGiRoji973Xc7nWTN+cwF4VQK799Clw N+2pVA5TisgvDjLRtOxd8btclSowF5LkK+BRzs0JFjlCO8pYpZr7hQqRje4qGyN+2t0IOU8qFK8q TmhCHRPAhq9zGYmpLlllSKl+maWNaBsTPO9ggaMrCS2/OoE9SYrw0ahbORHHfF7ayFKOeb3KAjlD wQFoMXtwCdUBzHODR7pAVEXXVAW5bJZRA1+d7rRTM19yhGzIIgsoyXM0OJfnsoRm74Ia4yMd4z7a wHA5IjjkfcjtO8yMbB7D7ngQVowadiWmchG64gAmBEFwbaHmKlrmkz4DxnunTihtSN8wDDfDor99 jmh0cubcW3hutz+lUyzYEIEAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTa jkqr8veQ2e5Rp9fdZ7FXUJ2cEAQHXPVBge0uUJvlUYf7uIqlcjNUwo21Akubk7+UkrT00OJtH2D4 Vg0mAONkISbAXQ1YoTlfghDE59jkUIYI0cNP0W1QXOpsQ7fMH0vEU1RmmYjul38k+bhNDoO+NWgj M2OVxktqnJq6I5WZ9ih7TaNW4bHSWIsMwnxCWiDM1SDLxQRwLIrmlRwadmaTujaYUziONBEeUp5n YR0fJGHMg/FPddTdDREWdxJBzjUSpwhzvpkYD9lVRQs0fOmMURoLSZiKyWtqY0F0MDwuACWRNXwP lTO0WnMe6HAqkGditPbMkIDpgjv7gIHhIU0RN2Rildrj4BiQ4kLrVrRusdNQ7OixCbNhAAkhzs7X 5iqo3NShZXOfV9pHWUGFMVIQpGA95Y2IDvFzh7rtTwFxmMldw8Zz1LS+PqZNU2LUYNeZFlIT2w4k WHLFwa91y1hteziASBxsVHGxyK74HxantS5GJyUlCnI8S4DeWhthZ943d8gWbo3GlNnOoW0J1Rl3 RmcpHhQiIUdxhgNbHtdzWm/bAG+fFbUTElucT6bcWQYsvGmBU5ZsKC3ejEszhAmwJGZFyQBzk2Rx sZTvwPh1LaEYMNxlQ+NxD4zRBZ3s7u+RY0ZpK5zpPHEOPKPnmReUkXudyEzEh7m+0GxeW8Be46LL kUSPQ5BxQ50CDGgTBmmxnObC63ly8vc228BlbK4vci1xchLIidzFHxrKS0Rsu6sykeefEaxsCXIi sGfbb0ZvaXAv2rS7PIlTdTN8x9SHiHl5hsFkVnLOBsxzCXOsCTYDmAJ6ACdFd049/Wx9JlRbDlWR p2q0+VdEhiJCliS+YeHC7TybblgNxm6yXOZK6LsqI5DlYrgL86ljEpJGfDuJZCDCm6057DLydoUM u0iR333WDnsA5x6AtbupFJcSKNV2VKdiTE1HbDlIDTGm4xv2rL8Ock2AHFHG2hVqfMrON4c/OOfB hsbBYOTgwxchjBoO+iiZcmz5zsTv97L73eF0sQp7Z5kDKRjEdDP90sEypxRMgfWUUfo/7pYtzE7F M1e3WcQcRduvypY0DiaYc25hNaOJcMvLdTdMtpGv1jaxR6Q8Q3T0GamL5QZcbzr82S1uku2zacNY nNWpMCfixJUco4sdDgxhF5I2DgHEZB1jpwWGrHPzH2jNTczDiCl06PUosIDfhQXNL/1Sd4+AFFqc d29EfAnMWGVmhKVCRmKdM6iXnoL5eIRzgPA3h0i60olvbiV9trC63JsHfJSxpMk40gQYjGRYJIcA bszsOfVZaNI+/JVKWnYIiwYrXNPNwPTzLBo5JN0BVxyuoDBFjhl9AqD41RrsGA7cbd7+DQM0sU1K rbSqZITTpSPOs5Rp7dsFjou5+Nu5BbUGN7Q+hT8WwJ+VExKVCWiwr2cW5Fp5iCLjwqONuIUrn2aJ M1mtxTDo0pHnyw2fEYzdgsP4UR3a+S5WGcu6b1SMMTb6dHjmpQ5qYhg9rAYHQmuAuQX6X8ItzKE4 OxqM1WYTXNYwF73uDWNHviTYW791tRNt2NBZthwm+qx6dEmTKxYEV0Fzo9msL2mxF++q6bRlTRsc tiuDMQRElxCiwiL7zIoc3yrJd4yMxPBdkRCvzcqL+RAmWbX2b7XAw9fu04DeOS7Em+/tWM729mhp Mj2fc528yED0BwQy5Ms7EW5YvhNb332Qq6Q3EYIs2HDdlf8AnAhos/FDWAufALRz3CWBEPF8B7i1 kCI+2oaLlLCxy4GKYIN3y7mX0D3Bp+VRrnM2O3dnM0JnDEOcEMsbGiO3Rz8LrMeJxVNGbAxkXf3v qThqDvZlbMHHgNESDHgzsMbl97tjkL8xQGpzTJWXeTEDDMjMQzm2GL5F3T0IaNrwrFfGkIj3zPLn lfdX07RuXRZCs+uhAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl 7yGz3KNPr7rPYq6hOzggCA666oE2wbKf9wZ+7iLcFqGa1hxhFGk22t9RaVJPU4nE+kL3zWQDfPmQ FT380LcxPcd0jpQhxo8UNab3QHRfVH7TXUCQdhqjTW7VpuHeNEhu7aVhHiCNHuF7cwz5kgt6XuMt nlV4bDBaAARzLzLozq2Vc9rh213Anj/81U3uYqJhN3X3HaOGYc3I/IjsHJmwU7FOJqcwskMS1yUa fewajGZl3muUsjDcmzs3DM7j7E8jAo1UxFWau2PFZEMrOzj40OGBm0lrj7rjc+5A6V402j2OHg0t 6R2dWYzaJRoWGpB7Xx2DlJuKGhjWgC+ZyFhYm55lxXvoWo1e51fhyehV6tTWIZx0aBhyiWc1xyD4 hyD+YxHe9Gov0OI8qMdyOvE8OpJtmq4uxNNYkrjnhhgwsoctAhm+40Xs0fLrqbnUrcVY8a12b3hG kNw5S+uJhgfPxQLtI9xlk0Dn1vZePUqXZ59GCSPkYmq8SXdyUAl9RmLF4YReGHe5A5nOHkCzBNu4 qT3VofbfV24PwxL0GWiwpirzDeUmXWJhS5eBexORNg0XGgHG+XOeDJubMuGpeY609kZ+I8PfnCbe 2/8AhEdPC+i8erPmR5dOmlG7Pk1yoxajUIVOkntDokUQzEJ7UknMk/ctGZ7y1TjpqcbZ9Gs1l01N waRSXRDKS7GwYJA7d7RkHW5ybmxyzucgua9jx4xbZyqjO+x8hDZGiG4h7kO3uYbedo4m5NjxJLuZ cTlvM8jcsjHhqZgyseJUJkBz4DdyEwEEbx4a6NGZPORwF1yI4p3RuLYs3Jy1oriycmA5kWGDbdGp Y7jYZbx4nteDgo2ZijY8PSIu2bcw3te7h2z3E3LndOveFulS7N3sKpOx6jUmUKmkOe8kRou9ZrQB dxJ5gLkngAVuPSccnvM+RFh1LFVbk6JhqDMilSUQwoL2wzZz3WL4r/wn7t89Gho4FctrK7OJtydk bnjCUdT6aMOUSpuhtl3GJOzBbZkeYyAYS2+6xmYvb3RPMuHfuzzVTsjrKpTmJ5MvbE5Z8Rr91zIE YRXNIuPetIOmoJ4c4WrnHw0PlRKzie7iJWpm2XuD/AoLHBi1nFgvuytV01sf4EJoYHVvFrRnK1c2 Gpc4fQxBdHJplQxJPS8cxHVGWiQnMsyLEexrwbi++5oF7jTU52yC1oi3Rr22uRxXhmrSlIrs3MQY 0xJMmnywnOW3A5zmtD3AAXs29gSOlbhrqcUnfgdeSMQmdhQ2XG/EaNL27ZcjTsVHqLD0TkMNysBp DTCqbmZCwzgQ+ZeLNHkRfqnV23yfjy2IaXHlo8SFFbCeREY8tLc+BC5KKumeNPidb1bFeIKqyEyo VyfnGwBaG2ZmHRRD/F3id3wLk4GUdh9TfLVrGmLahQH4mn5SDL0mNOQWBweHxGvhta0717AmIfIs T0VzyaSTdmfTqcWtUWamG1YRJjkohZFmGtO/DcOEVpzGmoyXjts8lxtwMuH8XTsnMCNLx7gnS+Tv SuSMVY4G3c7XwtjSTqcNrIruRjnVrjk7vFcconItT701VZdkJzuVaLcLrINLxbi+VkJV0abm2y8G 12gZvidDW6nv6LUYuRG7HUOIcX1quPfApsMyEi7J0Tf7Zw/CI4dAXPGKitTDkz5EpLNETreVhddz ORdf3MP8J596OYZudwBUc1zFhFyMuKnS+H6HGdPy8OdrU4DDlocUAw5aH7+MGXte/at3s7gk2suN JzOZpQR3Xs9qkzV6LIQpqemJrkoENj2RIriG/UmG+Ztz+VScd0kZXPVclIy8lhhsjJwmQZeHKuYy G0WAG6Vwwk2af3jyRXY7nU2OC67utItrjQ7hsuaPEVDyY+C8QWRGizL7gNxe44W8K8xxR4tzn02u zVOk3MkmGWmL9rMMjOadRcFt9082nFcbgbTPQOy/A+JcWbGJjHsvHnKpNwJyJCdTJKHChxXQmWu5 peCHnO+7x4XOS8e6k7HkqdkafExpTZIiHEkMSl2lmRZZ1u/ZmvQjgzdy0vjOlxo7Ib4eI4AeQOUj PlWMbfndu2CbjKrdB9OvYmw7R5tss2rYgqETdBicm6WY1vG1y3thnrkq4nLGFziS2PqA53bDEdr5 ARZb0LO6y+bXScuHtCpFt2FBxIc+MSVP+izYOKSMrdoNNLh9Trh0BG/KkjvhVRZjnPr03HmG479y PExCyxtZvWj/AA2uo4tamrfA7BwzM4HrsSDDlsU12HEed0crR4bg09LmE+VRy0sZleKvZHpPDknL UjCkrKS8QxoMGECHhu4XZ3JtwUirHiSlvO5klSd7rhwcG73l6B0rRk+RiCtiXL4EAMdHDt5zznuO 6Okc6hqKNPixSXlznEkm5PFTiaaN52cACjzJHvpon/IxaIzZ0IEAQHjrqjO7LXvF/N4S7e2X5Kpf N3mdY7Q8o1OruodTn3ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ2cEAQHXXVAWODpQf8A7Bn7qKtw 4kZr1IG7TpUc0Jo+RJcTjb1OeCM7FYBWI62Q8KFszC51rEILHHivLbm47yBnXm2TaBJ4Hw46cu2P Uo92SEuT/OP+6P4DdT5FLbzsjNzxXVJ6cqU/M1GfmnTEzMxDFiRnHN7ic+93uAXlqKirIwziRLXA tYc6y0FcgEZdqD0FVItjLC3DfPd4dCu7cw0zbsC4diT0zCno8F0SGXhstDt/ORAbeQfKVxzlZWPM oUd7VnpGk0+U2f4ZMxFhGLW5wWawDeeCfei2XNc846M/GvfQ8ipPSyOpsVTk7Xak7CUhNB0WO7lK 3N731Jljfkg7+zZa7j75wto3PlpwUdTwZ1GarjWrywZAw/Rd9tGkj9SuSHTMXR0Z/Pc3AHAeFc2s tWcDlc2fZjhpshT24jqkOz4tzJQ4nNxikc3BvORzBcVWdtEc9Cjd7zPsYjqMKn0x9Vmsibw5WASb vdxJ6AM3HvDiF48Ibz0PKn6iNUosN8lJ+26qsEWNEiFsjBeP56L76IRoWty8rRzrybbuh4MpXOfh SlRK1PRqrUnF0HlHOiuiZmI69yM+F8z31xznbQ5qFPnZ9HGNdEEugQ4hbYdsR7xvP3zw7646cb6s 3LU+cIESi02FHmGBs/PsJhQCbuhQr6kcLm5J42K8rgcDPuYfk2UuRNUnQXTMQ9o1+RcSNOi4+RcM nfQ3BWPjzM1NVSfdMPdcntmH3rG/d24AaALUY2RmbNhw3Ghy8RswIYayAPqe825a7g7dOTnk+5Gg N3H3NjoxFX4m3YWk5iqzgmZknk4dtxu8SGgaDptc99xJKGLamy4kq8Omywk4LgI726/2bOfvngiV 2ZmzgPlpinUllNl4TnVesNby7Wi7oMs43bC6HRDZzvwQ0cSuWKOOTasjtGjUpmzzC0Kmy134hqTd +M9rSet2nLIDjwA5wTwXDUnvM8yhT3FqfZpEpJ4Ww82p1GXHXjyetpeJm6K61gSOYA38JvwWErnL JmmxpUzUeLOzYDokZxe9wGV+NuAGi5eBwysYXU+UJyZfmzS7MmCLTpWxHJgIND49Up0s2GTuHvgq XMStY1TEErAa+ExkfknPc3dhm/1S5ANrZAjXP6U3jEDqnbNiGdxTjSLVKs5peILYFmCzWsYS1thw 73SVzxdkccVqafQpRxxZS5ce5izUMMIzBG+LrV7o5UtT0ZRnWkpnM2bXLAcADLtK4JankRVkdXdU d9e0skn+biXt3wt0ODPHnxOoGv7Yka9K5WTU7t6jez9qtRgPBAmMOT0PW18mHXwFYqK0es56L11O y8RzVLnJmJBmjMtq0rMxZGbiNhElwhu7SMXaHeYQCNbtJ0K4Wkjy5OxoWJMLQobTP06J1tEOb3Qm l0vE6XM1Z4NOKjbOPeTPkS09Hk5pkKZgulYjj2g39+HEHOx+h57ZHoVTuZd1wN6oFQiVaSmoT56V losvDJgRJh7QDEIybmcx31d25E2dYRmRag6LUqxOcpED3NeC/wByRznQDmWnK2hxO7ZngSz4kBsS K8U2ntaC2JEu172nTcaRdo743jrZo7ZYcrnLGHSfboc3JSUeUbK0qJ1oYgaX7249xJtvAm4be/uu 2NuJWLHMtDrDaKalAxNWJWrloqMCciy0djH7zIfJvMPcabC7QG2ByuM+K8yEEkcMp3Z6F2MQAMLQ 5sbwfGO6Te2Ql2ELxqvGxumezJTt6XDH3UL6QvGgjcn6x44rzT1tMM1+oxRp+C5csdWKh5ecWQaI 15H1QTosOjczXmtnjJHHqkzLRYMNkKXbBc0Xe4G+/wAVDVnwPZnUrPijqR6yIER7Ixn5iG1zDZzC 4w27w5iN668SOlRnPJcD6kPDkmGEOdEdbncTeySepyI4s5IUKUhWmpfeuNCLqJspqVcnaZDa6PJY Om6lAb/OxoTQWw9bbxAJF7ZX5lUxz8TUIuMaGYhYMGxSb2AGZvxBAal3wN+Yk194p7Z6e9otgWat na8A8P0FbG1Rf8yLsr8k8gjAUy/m/k7v9WJvWHmPefXkaqC1rvaS9uYABaePeasTnoR0rc53/gzC rpONJQ20CM9sxAa8xpcgMhOOZDibaX6Vm9zxZSb0udvmVhsglo9yAQOhaMWPiYgqDZGSZChOtFIs y2o+6d30Bo8xEL3G7r8FDSOO/oU4FOwdm9/YKLf75P7LVpEZs6ECAIDx11Rndlr3i/m8JdvbL8lU vm7zOsdoeUanV3UOpz7stB8Y83iptRyVV+XvIbPco0+vus9irqE7OCAIDrvb8L4PktP6RZ+7iLUe JJcD4VPZuSUBun1Nv0KyOKxme62QWUUo8k3N1GVMwRHWvmckFzXsY4ip2HKLM1arTHIykuzeebXL uZredxOQCj6EZbPEW0XFtTxpiWPWqn2jSdyXl2uu2BDByYOfpPE5ryqdPdRi5rTr2sRx1C3YpBF+ BWQNTYHNCXPuYTob6zPWfvw5WDZ0d7Qcx9wPwjw8J4LMp2Rz0Kbmz01s5w7I4epJxTWhClmQYf8A JYbyA2CznztmeHhK8STPNnNRW6jrvaLjqdqlTLacHvn5vtJNls4EJw930OcPc30FzwC3ThrqeBVq LmNHnZn2v0+JRpWba6ai5z0ZuYPHkweYEZ95eRa7PFk3c+3srwecRT0atVaG6HSJFwdFyIMaJ7yE 3pJ1PAJUnuI5KVJy1Z2BWJyHGixZyaJgU+WYHRXsGUNjTZrGjn960cTfpXhWcuB5vnIxRoUKJ7aa xMViqPdJ0WSYC5jT7hjT2sNl9XH5Sb6Cy8qENxHjTqbxm3J3GOJIbhDZKycFohQIMMEQ5eENGsHy 31LiSsylZCCu7s2etz0tR6e2UlQ3koQ3ILW6RHDMkHmBvnxz5lwJbzuc0p2Whq9HhQ992IKqzlpW E/egsJIEzFzsR+CPotzryVFJHC5HPoUnFn5uJXKs+1zlv9FrAdAGQGmizKfQWK1ORW52JVJsQWsc YYPJiE3UknJvfOpPBccEabsRBloz5hsjLta+I9wMZ7cgSBpfg1ov5L8VzXOPizZpCmNmJ6BJy7iR A/nXjLMgadNsugKJmrJG9RpqVw9RhE3RvNG7BYPfOt9AGv8AunFnDN2NfwnyNYrMxVqw7fkJBvXM yCbGM69mQ29LnEN6Bc8FyR6EcLep25s2kodNkY+0PFbWmcmnuNPl3DNztN8DW2dhzAX5lmpL+FHJ Rhb15HAnMWxzVo9RdAgTMdx3t+Yhue0HhYDmGQXGkjn85qfIrWNZ6qvESqQ4c9GY20KzYkHcHEC2 Q8nBbSSDuzW6niGqxmsEs+LKWHbsDnRb+EtyUckXdufGj1nEIvaemOgCEf4U3ka3UcR9YxG9ptPT l7cITv4FHInm0cWJO4gjAtix6lEHOILs/wDIpcebREnEqUGahR48nOzMMRWveyLLxCd0HMNAaM+i 4S483Gx19tekZOBiJsxTW1CHJTTN9kOebaKx292wvYbzbnJ1gdbjLPng9DxnTsz5uztnLYupkIje LZtjmDm7a5C03obSO96RDDKfPcza40fNR6Fwvgc1tDq/qimXm6U4Z9rEA6dFyUOc8aZ0+fdnPvZL lMneHUZAP20y8NwuH0udh+AwiT/osVL7jOalxO66rTJfskYjbDY3cizEKPbpiQGOP/zmC8d8DypO 6RwK1QLMfyTbtcLOZewKikcdjQaphOcG/BlGiagRHDlZWPYHvg6eEWKNhXObL7OqcJeDDi1Kot3G 25NkZpa1x1sS29tNVUzSsVn9n0pLy3XVFfEm6qIzHQvZB/KQWi1i7dAGYsNb6I3fiEr8Dn0zZ5Ch xDUK3Mvq9SPbOiRx2jDr2rNPLdRvoOWMLERqVDNRgwhZsQvuHht7Wz/0ssxOOcug6E2psiRNpWKX OaHAVmcuWkH+vevP5keG5NHofY1LPZgiiuiw3NbM9sCR7ock1v8AovDqP1meVRva568ob9+jSZOp gs8tguGBqXE8i4kZumahj3QMYeG7lyLics1dnnCHh6YqFNjWc2E2HHfyd8zEcGXsPkHhXM52NKi2 fIqlAjyFHE3Gex0UPDIkIG+7cZZrPnUWdBxVz0xsLxNTqT1K83TZh72zNWr8WUlw247dsNkUm/AA M8N1xwi99sy43aO1YLw6Va8jNzAT5FGVI1XFLIj3BzQSLFCnWmI5+p0aXgzMpU4siwTUWDMQ2TBY +NDfDGW6wFzxfosD31uKM2TZ8eqY5luvN2RoM9MS8OExkPcqMaVFw2x7Tccb8SS4k3vleyu4+JtP d0MEHG0WI/t5EywcdJivzYz5soSjTRpTZ9CUxTKRozYJaI8XVz5erx3QmDiHb7WuBAzva2Sm62N4 2rDtZw9UC4SnLz0ZuW9Cm4roEPL3Zc4Xd0ADvrgqu0TljFy4Hs6gxGzNFkpgbtosvDfkLDNoOiQd 0jwJK0mjlxjZjje2Rz8C5CHWFZnDNTb4u8S0mzegBVmoo+Y8g6LNytoxm+dtFURHYezb+gow5pl3 7LVRLibOhkIAgPHXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdQ6nPuy0HxjzeKm1HJVX5e8hs9yj T6+6z2KuoTs4IAgOvNvhHtRkgTa9ShgfFxFqHEzLgfDgXbCY0/cj6FZHGncs5wtosWZTDFcQMtEB 8+oTTYMJ8R72MYG7znONg0AXJJ4BRvoJvI8ebb9ocTHWIesadFdDoUlEIgb929cOBziu5gfejgNc yvIpUt1bzOOo7HXLoBJAabuvplqudHFGRiEF1i4A2Byulma3hyZvcWz5xqpYbyOVSqZNVGoQpOVh b8WJpl7kcSegDisy0WpyU4Oeh6L2UYJk5WUZPzrmMpknd4MQ7ojRAM4jidGj0DnXh1JXZ7JNU42N X2pY2diGYFQ3T7ASkUspcq8kdexwD9WcLZsbqPANTlqnT6TwZ1d525j4sWlyuG8Lez1aixI+I6sX daSziW8hDPuozxx5mjiTzBc1rysjx58T4eCMLzmLK6yQlLw4MM78zMON2wmXzcTzrbaprUsYObO7 qozkqfK4Vw3BbDgwhuQ987ob91FefuiLm/vQLrxG3J3Z5Te7GyOvKy6PiSpy+F6FEManQIpJjX3R MRBk6O7mY1oIaPetBdq4rkit08aUrqxxa40T0xK4bw7DDqfJkMD8/wCURdHTD+IB96ODQOJK03zk SZudKwvApVJdU5qYdCpMiwte8Os6cmDqxn4LRqeGnFcTe9ocyZrEvIRsT1Z/KRBKyUBpfMRX6S8E Z2txceYak2W4xsZfDQ5ktIxsW1yHAlJfrSkSILIUM2+psDsy4jWI45uPPpkArJ2JGFnc5mK4kKWj CmSZaGQW2c45BlhmfAuNK5ypmKnQXUmVZN8kROTDSyTYW3fCY7Ixeh7r9qeC2okdpGxSFEjUuTgt ENpqM2L2Iygs5z9PkUEVum1Uuny1Hpro0Z+62G0viRH69JPSfQhJtGh4jqcxWZ/6kx4AO7DhjMht 8h31yRj0njyaZ2bs3w1JmK6HXnsgUeihs3VCHXMeYI7SXGly0XFhxLucLUpWWhmEN53fMbPiOqT1 ZqrZ2blXSpdDBlpcm3IwPei3AnPPiuA55Su9DhxmTRc5ku8OYHGxLbeXpQhxY0vVbZOh27y1c3vH GMvVwf6shGaUiOtqqRnuA3y7UlSxbkPlqo0Ete1x5t0hZaNJnHmW1GG27gemxQl0fPnZmcbBe0Tb oDgBYloPfN9Bx1uqkZc7HQ2NZSOJ6PF3Y74fXDg2NEud7O9yTrl9I0XPE4neWo2WwYrsbU6JDhtc YUffAtnYZ36Ta6srbrOSnHU76gyT5Sn1aFEuX+z8N4cR7tplsj/ouG+iOaot06o2/wAIPhyFxEL+ 3DLaD3Oq5qFtTwpu501GY8RyS4X6Fy21Cizu3qMmOO26SeWP3esZtpeB2ucF9s//AJwUrNbtjmpx a1PRlWEpExSHQZcw44kJMTD96/KEwzuuA4WaLE8SF4suk5tbGaLAa4ZgLBDjRZCA8AOgsPgQGP2L lt4HkhojehtMzQpCWhjtWW581m7Le5xqgwNgua0CyrZbnXWJWuYHFhIO8RcGxz/2urE45HnWuSsw cSz0q1j4sV88+G1jc3PO+QANcyvPTW7c4d1tnqLAsdhwrhentitMxS4T4c8xhB5N/BpAOXHjZeFP i2eVGLSPU9BAbSJRrXBw5JliNCLDNcMDMuJ5NxdDcyo1CGcnNmI7f87guW5yvmOlBc9ZM3A2EGAW At2xAJ75WJSPZUoHAmqc+bFVpobcvhnkd86Ws4G+gXGp6nNOmpRZ21scfT6R1PtSw/VpylwZ2PXB MQhGhRYr2s5IXdB3G5PuC3eJ3Wgkm+QPJCetz1tWm1JWNpgY5kmyzQyNDeGtAAayJkB+itHHax8m e2iwmX5OQdNW4Bjm38oTQjTPiVDaTMON4WD5eJZvuhMEPHfG5l5SrewUfefNdjqrRT9SwK1g0B64 IJv+hoqpm40785xqjWqtUobocbDUGXvzxyT+wsuZpUz5krRxNzY9kJeLAlYrSyLyG89+4dd0boF+ nhzFPO2I6TNqw1h+hUh7o1Em8Rk74PWs/Jw3ggcRFY4fKwLjrTUos5qClB6ns/Z9NQ5nBtLdDiNe WSzIbhfNpAtYjgVij91Hh17qbPtTWctEH4DvoK5jhOpXZgX5lTlWpgI7bJSxGrlXCxSxpROwtmwt QYv5y79lqpia1NnQyEAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTajkqr8 veQ2e5Rp9fdZ7FXUJ2cEAQGgbcm7+Gqa24F6pD1/JxFuHEzLga/cCzRpZHxOHnDgTrpZRs2cWYvb myUuiWOktus/izEE77Q8H0Sbm3RGti1CMHBjS13bMhBzi0WIF3WOlhz25KMItuUjLg2dd07YBjiN Ec6fj4boDDqJ2tMLm3GY3YQeV5DqwTMKi7cT7sHYFR2Axq1tSlOUGbmUyixpgk8e2e5g8Kx5/oRp UUuLPqSuyTZPKQP5TNY9rEQe9aJeUhu+RxUeInzIvm4I50HB+y2VO7LbL52ceBk6frkZ9/0WNA+V R1Zi0VwME/QKMJmFHpWBIdJhNAZEhU0vBii9+2dEc4nwWC4pOT4s5ac0j62L5apYkpkrQ6dJx5Ck PG/Pl5DHNht0h2+40zHujbKwWVGzuSdXeVjryewlPx6/1zHkY80+VDWU+Bbk5SXYCT249288bN3Q Sb3ysuVWWp47uc+Fs+m5ypNqdZl6hVJgEOLC0QoNho3MklvRYZK76QcTfabCqkJsWXg4fptJgRIe 4GykBkNgDTcXAzObjrmuOfrnPCaSsfBr9AqBkhLxZuahtmy7rh8rCEaMIfCG0bzWtLze7nE2DRro pGyepxydz5dNwRMS/KCDKTctKRQAYDYjYkV7OZ8WzdeIaAM+K25q5iKNuhU9j4cGShYckqTKtOcS Qlm8o3Kxc5xdvPy1BPeWXqcidiNoFPj1brClN3mU2Th25OQYHGJEv70uNmttd2+4HNxycQAsxVtS NnxaLhmNT4PITlNM/KOcXmULy1jnZ2dEc0tc8i97XA6Fu4ublLMkolPmIvsRApkzDF2y8pDDIEVu 6GtAGoLSLnUkHW6w10nIzRIOFI8e5iw4sac5Zxjvita2XIBytnvPvqPcgcbrWiRly6DbaTh2RbMs m5yC6ZqIdvddRI51AG6Ay261oAy1KXJA+5BkXPjiK9mTcxlrle6GmcKu4ar9fZEbLNlZKlyzgYk1 NzAhQ3Pt4S63MGlE0jiacjBh3D9Ew5Pwqj13Grc9BIcxsOEZeVa4cS513xPAGhb330E3EcmamXzl QdMOkpeXDopiFkvC3WbxNybXOd+KzJ3Kkkfek5OMyMHRn8pEc1p397eG6Rl3jbyWI4rNjSR9qWgt hw8gqVozFrXDJQiiYjDF9AqbSsRuC6cSkPhXGSzqDgT8q9zDYX6FeINRxPTJiYgwmwmlrt4ZnQZZ n/W3gVTtxOO2oZIwBTYMhEhxI8CEwtDIsMOGZuctMystnPA+TDwpRJWqwKpISb5KdgPD2OhMJhvP M5p0B0yUuzkUktT7rIceNITrY7i5z5+HGhAgX3BCLToM7G2ttUvpYk3c692uYeqNWlpYSUBj3QiS 4veGAXy465kLcJ7rOHcuz5OFNjUvEdBnK7EiWsHGE05O6GjXwnJWVZ8xzRpxjqzu7CsjR8Py7YNH khJ7trODW79+e/HNcbdzkurH255z6lWItefHhujzDIMCYl2gDk3wmuDXN52va4n8Egg3yVvdWMWO RnZZM2IIF7WVI0QW+RRlIc0ALIODOwS5psCho0nElMjRA7dhOdZ18tf/AJ4FqIlGxrtH2bQqVUZ2 tumpeqz89FfEgbjuSEEPzIO84EWvYk2JsQMjdcrndWFtDNhzA0emHleXPXNwTMCbhB1hwAabeVcb Nq523grFeJKFMwpWZmoU3T94B7nEODW3zIANw4DPK4PGy40mmblFNe80TE4izNRmp50vutjTESNy fMHOJ3fIfKtXMN8Dq+SwZXZ1jJaFAe+FAiOdytg1m8Ru5uzcRpkAddFxPebPMjWildmyyWzvEUGK HSeD6pWJots6LMSr4cFuWW7D907vvIH4C0odJx1MU2tDnzezTafOs5Waw5Mh1st6JYN6AGmw8i2o 24Hiuo3xOLL7I9pLzY0mogAaGId3ypYzvyKjZBtJ3nWoFQd+O4W+QqNMrm2ZIOyDaj72jTcIWvbe b/EltCKTObK7FdpcZl30qMy3F881nyZqpHI6luBEPZNjmXdaLKtsNfqsVzh+rDsUcUyqqzI3Z3jn lGQ5SUmnc3aPBPhc0LO4bVfpPqymCtpEqQ80qZiEH+xvfo4LLph1zsLZFM4rpVUnJeoSUUNe3f5F zCACDmAsxhuu5w1J753NAnYEdjmklj2jtmP1GS8jnMHV00AI72t0Dj9KM0noYLWOSybRU53Wgmdg bN/6Dj/nLv2WoYlxNnQyEAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTajk qr8veQ2e5Rp9fdZ7FXUJ2cEAQGjbZm79DpQ//awuF/6uIt0+JifA1geDLNHxOIsNQss0uBjfDDmn e8ChXY40xTpWPYRpeHEdzlouFvgZMXsRJWyhN7wbZQbw9iJMH+aCoTLNpkiP6hju+AhWgKdJg5S0 IforLJulIkhK3+t4X6oVuLWKPk5cG7YTAdfcrJlIrDl4G+A6Ew25xdAc5knJ3u2Wh2t9yFotixk5 W9xLwtPuQoSxiiyctwl4e7zbqgaOLEkZUZCBDte57VUJFOtIIdlBZbvJYtiIkrAtbkW25rKEsYes oHGAy3eQ1ujrWB/Ysz6Fq4TD5SA4/wA03yIzLIbLQWG4hsy6FEWPEycm0iwaFWaZD5eG6wLASMxm smErkOk4J/qzmrcriGykEWPJjJUljPChsZo0BU0kZw4W0QWLB34N1TRF7jSyAi1uZQEeRAC24ss2 BidBYRZzQUYsY3S0M6Q227ylzSRjfKQvuG+RCmOLLMtbdFkBxY1Plo0Mw40Jr875jQoCGUiVGe6T 4UBmbTZcE9pqhbnKgQYUI9o2yyzVzlBQgtlotMEhvQsgEXBVQKuYC3S6mtyrQxGXaXXstHItSpk4 O9csbf8AFQpLZSDn9TZ+qqaMzYMMNtybc+hZZGzix6dAiuO+wEc1kIYpelw5aIIspFjyzxxhxC0o uIOSYE64lzqrUCT/ANS5aFkSJWYcbuqE6bceuHILLmAlo4P17OH+/cgXAs6WikC01ND+/dn30F0V 61jO+3Jv45yC6MjJOKHAicm7/l3elBoZHyD4g7eamnH8u70qMXJbTWHIxI5B54zvSiHEuKXAFg4x D/eOVFj7GFZZkhWIUxAaXOuRZziRmssxJHYExAgmXM1AYGRGi7h9K0cZ1tNHejveOJJUZswG6Gky A25vbigSZ2Bs4FqHGH/Uu/ZaqZlxNmQyEAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3 ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ2cEAQGmbWm71IpfRU2H/APlFW4c5ma0NQByWWcJLeCiQ T1MitrGmLNDtFNQirhmrzCwFr5qXCRWIcsgquJSt+16UYKOIzWecyzA7IX1K2Ux5g3GShDlQX9rn khbHIaQRe9kuLFImuRuoLGB47yqIYjkcwEKiDnqoUqRwKAq4AjIK3M6ld02S4sN0aW8qXNEhoAyt dQWuVIJVM2LBLBseFaBIUuVF25X6UbKT4VEWwVuSxBPOqCWnJRlRJzORWTRVxAQEXFtM0BVzb5oD FEta1vCgOPlvWKAyNOSFRnh2ORQAjtllhFxujQKFJJyCWAb31bFRbJQ0ONrogCAFo0iDa+iWNWJA zuqUnKylyFX5ZqWuQG1r7qlmuAIGaX6QXacuCjlqCHErQJDuBzCqBZhzVByWDtbkqNgsB05p7yl2 NvqiBma3ecBZUcD6dGgsfMtDnBree11lnHJs2evzrYVOjmGbu3Cy443yC0YXE6/iNu5xWWUxuFwb c6iFmQxud7Iaub/s8/oWN+cu/ZatmWbIhAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc +7LQfGPN4qbUclVfl7yGz3KNPr7rPYq6hOzggCA1LafDMSl04AXIn2n/APlEW4cSPgae2E+2YspL icDJbCPGyyVFhCcFbhkcm4iwBJTn1F2V5NwOh7yrKmHMdzELJSm44++KAxuab+kICpaeAU5zDWpx 4rXj3pWjRVpuNFDDuWh30/0VNmVryBldCO5cvNhnmoZZjeeFkKrso6xV1NIjKxyKhSp1sgKXI0B8 iAHVAQdc0BF88kAcemyApwyJVuSxO8QNUJZlmuKMquid66hSd7LihuxIfbhmgILj3kI0A465FAkT c8DZCi4tqCgK3yQpBdxQWMEV53kFjCSLICWuyF80COQ1+SAsHfjKFLAqAtdQFteZS5pIkHhkqUO1 uFdS2uRckapqVIlp5yjZbk5bpzCymLko2xcq48yX0BUk30UuwRvEcPkVsCQ51/cnyIkAS457p8i0 gBvfcnyKIF2XuMjzlUHPhNJhZA3RoGVkJ5Nww+RS5TKyE+/uHeRVGWzNDgvBJMN2nMqLnOpZMGaY 89rYi9xqOIUZJ8DmYkiwnt5GWcIsMneuDp0KmEtTXHQn5ktOahtqxj5J9yN3VQw3cu2G8atQJPib xgBpbR4wIteYcf8AK1aQZsSpAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4 qbUclVfl7yGz3KNPr7rPYq6hOzggCA0Pbe57MLSb4cR8Nwn2WLTY/wA3EWo8SM6mE9OFo/lUwDz8 q70qtHDJak9e1AjKcmPjSoiInrupFuU/Hb/eFQ09SzJuoa+yEzf8oUCMjZuftbr6at+UKhbECbqF /r+byzH1UoUkzs+NZ2az/wCYUI2WbOzw+3Ix77roLkRZycIzm4vgdZCNGAx5o/bMY/poQpykb+2i HvuVFiwixwMor/1ilwUc+Oe2MV36xS4uXEaOf6x3lKMjAixb5xH3/GKhC/LR7ZRXDwoVMgx44/rX +UoauWEaMR/PP/WQq1I5aPb+ef5SgI5WMM+XeT+MUFxy8b+1f5UJcsJiLa3Kv8qC5BjRzpGf5UKO XmA3+df5UDK9dRxrGcqZuXbOTAH885Sxbh83MH+vf4EFynXUxb+fcli7xPXUzb64eboXeBmZg5dc PshbkiamQLdcOQtypnJu+Ud/lQEGbm/vh/yehAV68m9OuYnyehCoq+bnOEy/5PQguYjMzn3y9CmI zE2cjMPQGIzE4SLTMUeFRgdcT4FxORx+mVl3CIMzUbX69mPjChuyI67qIt/Lpj4woCevKnwn5n4x S5LAT1VBv7ITFvx1eJUSZ+qnL2Qj/rqlsOvatb+kY/66y20auivXlX//ACMf9dTfuVF2zVWsL1KY I4durdiwM1V96/slNfrrO8CRM1a2dRmT/eFS5SOuqvr7ITHR9UKN3BjdGqrjc1CYI/KlESxJjVHT ryYI/KlauWxG/OnWZmD/AHpWbl0KuM2czGjH+8d6UuQo9sxY3iRL/jFE2CBCjEZvfp90rvERYNmA bCI/ylVyBkAmQQRHi5cA8+lZuyl2xJ4HKamQOiM70q3F0jO2YqoHaz04B+cO9K0ri6ZnhzlZb/6n ODmtHd6VTNy/X9baRuVac7xjGyJksWbUa4Af+LTV/wAojkaZZtVrQH9KTB/SS5FYzQqzV22Jnoru /b0K2uLHbOyCamJvDUzFmYhiPE65oJ5txnpVSscc1Zm5qmQgCA8ddUZ3Za94v5vCXb2y/JVL5u8z rHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yGz3KNPr7rPYq6hOzggCA0Tbdf2qStvv5n7uIiIzp5uhs tHGzI05WIWTBYOytorc1YlnucslCl9ALZICc0BBIH+6Aga6g+BADnkgKgWOqGeBU5nWyovqQXKEZ a+SGQTYBAQ13QgBOaGrlbgnIlLlbLNNhmhYskuQpUvIuhllHREJcrv3KpSeUI50BO/vNzuoUxlxv qUuLE7xtxVM2LXFtc01KV3rmyMMcput51DSI5W47yGiwJspctiN7LMqlMbohQj0Bf0qN2BAfcXVL YguQpVzrhZbIUvmo5JFG8LqXRqwJyzGSy3qLEG2WQRB6AeRAmTe1lUUhzs1pBalmk6DijRqxLR31 x2KtCSbIwTfNQoJvxQpJNwgIvlkgFyVATfKyoIz7yAC51RAsQgLN0zNrLSRGSDzfQjRCwHQs2Be1 hzK3aBIOdr6LV78SWJcbnp6FN4vAX6LogQXEC50WkiJDfNsjkto0dwbEzfCs1+fP/dw1TilxN6Qy EAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ 2cEAQGibbvsUlfz5n7uItRMyOnL214ozibLte29lL6BFt+2QChXoBEuRe6thcsXi181A2S2J2o1Q XIMThkUDlYjfA4ZoTeJERBvEF/ShGQMxdAmVcRcoS5IOmaEJ1yugKl1jqoUhzrjVLi2pG8Lo2Vk7 1xxVEboF/OhsqXAaIRoo5wJ50IkQHHgdOlDRDovDNCjlChA5+V+KAjfJFt5AV3uclDNmSHgZoasB E1zQ0gCOlC2J3ssisgo9+WqFIETW6BkF9zwspcEB1uK0AXnnUckild4c6w3cIhzidCFDRW51vZLE sTvG3BVI0A7iroGrk3HSssIXAAVWoG94FeBbWLNGhum8VXLB2eqwasN65y0VYsSdLiyyUb3fVaJa xINze6hSQe2CAkZnmQA2GuaAdBurcAHNAWFzrkmgJBIFtUuQkPOl7IgXBPOtXRCx0vzLNwLkHJbV gHE+9CzZEaA3hqFrRFB5iVtFIyvohDuLYgLYUmvz5/7uGqccnqb2hkIAgPHXVGd2WveL+bwl29sv yVS+bvM6x2h5RqdXdQ6nPuy0HxjzeKm1HJVX5e8hs9yjT6+6z2KuoTs4IAgNJ2ySszO4dkZWTgPj x4k+0Mht1P1OItRMy4HV5wfiq39ATv8Al9Ky+Jx7jAwhikH7H53/AC+lButE+1HFRd/QE6OntfSh N2RYYSxSCP8AgM75G+lC7rBwlim/9ATvkb6UG6x7U8VW3fYCet3m+lA0wMJYpH/oE75G+lButA4S xTe4w/OnwN9KBxbKnCeLOFAnfI30oZ3WBhPFnHD875G+lDSTsW9qeKrH/gE70ZN9KEcW+BQ4SxX8 H50+BvpQzuSIOE8WAZYfnfI30rN2XdY9qeLb/Y/O+RvpVTG7LoIOEcWH/wBAnfI30owoyIOEcWHX D875G+lSxVFke0/Fl7+wE75G+lLBxY9qOLQcsPz3+X0qlSYdhLFhz9r895G+lUa9BDsIYtP/ALfn vI30oasyvtPxb8H57yN9KBpg4Pxbf7Hp7yN9KGLNsDB2LLZ4fnvI30qHLYg4OxZ8H57yN9Kl2LFT g3Ft/sfnvI30omxuk+07F3DD095G+laG6VODcXfB6e8jfSgsR7TcX/B+e/Vb6UJYkYMxcP8A29Pe RvpUZUi3tOxef/b895G+lZuykHBuL/g/PeRvpTUFPabjC/2Ozx8DfSlmLA4Oxh8HJ7yN9KlmVIe0 7GAH2OT3kb6VmzLdEDB2MPg5PeRvpV1GgODcYH/27P8Akb6VLMtyvtMxh8HJ/wAjfStWYuizcF4v sT7XZ/yN9KqREwMF4v8Ag9P+RvpSxq6HtMxf8HZ7yN9KWFyvtKxf8HZ/yN9KalugMGYv44cn/I30 rNhoW9pmLvg7P+RvpUsxdEjBuLvg7P8Akb6Us2a3kT7TcX8MOz3kb6VN1jeQ9pmL/g9PeRvpVSZd 5dJIwdi/4PT3kb6U3WN6JYYNxbb7HZ7yM/iU3WN5EjB+Lvg/PZ9DfSlpDeiBg7F1/senvI30pusm 8ifadi34PT3kb6U3WXeXSR7T8W2H/l6e8jfSm6ybyBwhi/4PT/kb6U3Wa3ohmEMWjXD0/bvN9KWf QS66STg/FvDD095G+lLSLePSWZhDFl/senvI30pusm9En2n4s+D895G+lN1kuh7T8V3+x+d8jfSr usbyMjcH4q40Gd8jfSpusOSLjCOKAc6DO+RvpRRZN5F/anijhQZzyN9K1ZjeRX2o4pJ/oKdHgb6U 3WVSQ9qOKBmKFOnwN9KqVuIvHpI9qGKTrQp7/L6VbsbyBwliZjS99CnAGi5JDdPKthtNHZOxK3tU mSDcdfPz/QhocclY3pDIQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOS qvy95DZ7lGn191nsVdQnZwQBAfExT9eUH/ujf3MVAfaaBbRASgFhzBALDmQBALDmQCw5kAsOZALD mQCw5kAsOZAEAsOZALDmQCw5kAsOZALDmQCw5kAsOZALDmQBALBAEAQBAEAsOZAEAQBALDmQCw5k AQCw5kAQBALDmQCw5kAsOZAEAsOZAEAQCw5kAsOZALBALDmCAIBYcwQWFhzBALBAEAsOYIBYcwQC w5kAsOZAEAsOZALDmCAWHMgFhzIBYcyAWHMgFggMM+B1lHy/q3fQgNK2IC2EZgf9a793DQ3Pib2h gIAgPHXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdQ6nPuy0HxjzeKm1HJVX5e8hs9yjT6+6z2Kuo Ts4IAgPh4p+vKB/3Rv7mKgPuDRAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQB AEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAYZ/6yj/knfQgNL2JknCU e9vrx2n5OGhqfE3pDIQBAeOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOSqv y95DZ7lGn191nsVdQnZwQBAfDxT9eUD/ALo39zFQH226ICUAQBAEAQBAEAQBAEAQBAEAQBAEAQBA EAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAY Z/6yj/knfQowaTsP+xGYz+3Xfu4aI3Pib4qYCAIDx11Rndlr3i/m8JdvbL8lUvm7zOsdoeUanV3U Opz7stB8Y83iptRyVV+XvIbPco0+vus9irqE7OCAID4eKfrygf8AdG/uYqA+23RASgCAIAgCAIAg CAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgC AIAgCAIAgCAIAgCAIDDP/WMf8k76FGDSdh4/8ozHTOu/dw0RyVOJvipxhAEB466ozuy17xfzeEu3 tl+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq/L3kNnuUafX3WexV1CdnBAEB8TFP15Qf8Aujf3 MVAfbGiIBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAE AQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQGGf+so/5J30KMGlbD/sRj/nrv3cNEanxN7VMhAE B466ozuy17xfzeEu3tl+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq/L3kNnuUafX3WexV1CdnB AEB8PFP17QP+6N/cxUB9waBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEA QBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAYZ76yj/AJJ30KMGk7D/ALEZ j89d+7hojc+JvipgIAgPHXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdQ6nPuy0HxjzeKm1HJVX5e 8hs9yjT6+6z2KuoTs4IAgPiYp+vKB/3Rv7mKgPtjRAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQB AEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAYZ/6y j/knfQowuJpOw43wjMfnrv3cNSPA3U4m+LRgIAgPHXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdQ 6nPuy0HxjzeKm1HJVX5e8hs9yjT6+6z2KuoTs4IAgPiYo+vKD/3Nv7mKhD7TdAhSUAQBAEAQBAEA QBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQ BAEAQBAEAQBAEAQBAYKh9YzH5J30KA0jYX9iEx+eu/dw0RuorM35UwEAQHjrqjO7LXvF/N4S7e2X 5KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ2cEAQHxcTi85Qv+5t/cxUI z7LdERSUAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQB AEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAYZ/6xj/knfQowaRsMt7UI/56793DRG58TfVTAQBA eOuqM7ste8X83hLt7Zfkql83eZ1jtDyjU6u6h1OfdloPjHm8VNqOSqvy95DZ7lGn191nsVdQnZwQ BAantPn49LpVPqEs2G6NAn2uYIgJaTycQZ2I51URmmdkzEIH1tSr3/sYn8aWOKU5LmB2mYjtlLUq /wCRifxqEVRkHaZiW1+taVb8hE9YhpVAdpmJBrKUr4iJ6xC77IG0/Ed7GUpXxMT+NLDfJ7JuI/vW k/ExP40tYb5bsl4jtfrWk/FRP40G+yvZNxHYnrWlfFRP40JvtDsnYj+9KVb8lE/jQb5V20/Eg0lK Sf7qJ/Ghd8xu2pYmGkrSPiYnrECmyh2p4nB+tKR8TE9YhHNoq7avicfalI+IiesQ0pGGJtbxUNJO jeGBF9Yow5FOy5ivjJUX4iL6xCqQ7LuKbfWdG+Ii+sRFuV7L+KvvOi/ERfWLO9YFX7YcVt+0qL8R F9YpvMpjdtlxaNJKifERfWKqVxwK9mfFoOclQ/iIvrEuyE9mbFv3lRPiIvrE3maSuWG2PFhz6yon xEX1ijmw0XbtixYT9ZUX4iL6xFNixkG17FVvrOjfERfWJvixR22HFYNhJUX4iL6xTfYsYnbY8Wj7 Ron+Hi+sU32LEDbLiz7xon+Hi+sTfYsQds2LfvGh/ERfWJvsjQ7M2LfvGh/ERfWLW8zSRI2y4ttn JUT4iL6xN5ksOzJiy/1jRP8ADxfWKbzKkSNsuLNOsqJ/h4vrFd40oXJ7MmLfvKifERfWKb7G4i42 w4r+86L8RF9YnnGNxEjbDion6zovxEX1ib482W7L+K+MlRfiIvrFd5k3CRtexUftOjfERfWK7zG4 BtdxWftKjfERfWKbzG4WG1vFR+06N8RE9Ym8NxFXbXcVg2ElRviIvrE3xuIHa7iofadF+Ii+sVux uF2bXMUHWUo3xEX1it2Nwu7azigaSdH+JiesRsbhDdrWKPvOj/ERPWKbw3C7dq+Jz9qUf4iJ6xN5 jcJ7K2JvvSkfExPWKb5VBc5SJtYxS33MpRrdMCL6xauNxGPsuYq+86N8RF9YpcbiA2uYpP2nRviI vrE3mPNluy1ij7zo3xEX1iKRNxEjazij7zo/xET1ibxdxA7WsUD7To/xMT1iu8TcLN2sYmOspR/i YnrFhzZvzSLO2rYmGkpSPiYnrFPOMvmkR2VsT/edI+IiesV3y+aj0gbV8TH7UpHxET1im+zKpRLj apia/wBaUj4iJ6xPOMvmolhtSxJ96Un4iJ6xVTY81EsNqWI7ZylKP9zE9YrvsnmkDtSxJa/WlKH9 zE/jRSY80ip2pYk+9aR8TE9Ym+PNIdlPEg1laT8TE9Ym+FSRPZTxHb60pPxMT+NN9h0okjaniIj6 0pV/yUT+NacibkSkXadiOLDfDdK0oNe0tJEKJex/TU3g4RubbsRFsJzA5p137uGrEzPib2tGAgCA 8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yGz3KNPr7rPYq6hOzgg CA0jbOL4Xlh/1rP2HqxMydkdTtZncjJVs4GyCwnQHXRZIWMPdOZt3kNFtxpGR7Y6oW+hJgi18zbi qTnJ63DzfO/MEZq1y3Iajh0lQpR0C1+2z5kBBgDd90guY3Qi0luo50FrmIwctUI9Chg5oZ3WYYkI 3OaGlc474F23JQ3YxCHbvIVFIjANFnVMpRzMtFLdIMb4f0LNmEYXw0WgKOhZjJLlsOT51UaV0S1p Gqy1cXMjRY3zVsUzAjd4rAMT2i90BVzRnlqrFXBQsNr2Fio0Cph5JYDc8C2kC3Jg6o9ASIY4BZsC 3JWtZLFuSYfQVOBbl2ws1UrhMycmVbFuQGFW3SLoncyCtzF2ZGQ7ZhZbubRkazLQ3SwBZbMhAUc3 PTPmWkAGGxsLKpMGVrSW5rIJLEBZrQiQMjWg8FqyRSHsCoMLoYvosyFiBDIN7HvIVPpJEM30KmhG BDtqEIN07wNrhWxpFg0X0WXE1dF91YsUrukniqCWtN1LAyBnSiQuZCw5G91ojZbdyVJchgBJDuZO BbkOZZZF0Q2HvZ+RBcuIZBsU1KRuNBvlpzrVyaEtY3UqFtzncGxO3tVmrffz/wBiGuWPA4Kq1N6W jjCAIDx11Rndlr3i/m8JdvbL8lUvm7zOsdoeUanV3UOpz7stB8Y83iptRyVV+XvIbPco0+vus9ir qE7OCAIDStsQBwzLA/frf2HrUTE1dHVjW2ZcElRnAWd7ofKVLFSLiGHOGXaoLMu5sOwAbfJAizQH XsMhoLoGrkbhBGqFSLlrS62SFRijNAIAzKpWV3cgVAkY3NNx/qhtGNzMtEJKNzG8HS1igsYHg3sg sYH+5sUKYXC2iERidxyQtyrm3F7qFKObko9AYnNABWU7migbldGEC26hviVLbcVDDTJblzlDSLAX 5wjKN3ouoZsRY9CXNLQEZqviChb217oCzW3Oea0gSG2zsjVwSO8rZFLNbxUbSBYCwvqo+ghdoBOi PQ0i5DbaIuJWyunBaZksLk5ABLC6LgX1AWd0qtzGRrQBdQodunitJAjdF7raAsL6FUpYW0ss2Ba1 lbItiCL6JYlizAd3pWWgDlkeCICw1stABtjkLXS1kUuWjdXEZK8nxtdCk7mQt4Vsg3Qe1OijLwJL RopYXIDcrcUYuSGhSwuSGi1xdOAuSLE53RtsoAvoiQLtGdzwRgm1+lQAZG41S5pImIL2N8lURlDY aWVuYehU34ZIrFUjuDYlf2qzVxb+XP8A3cNckTFR3ZvSpxhAEB466ozuy17xfzeEu3tl+SqXzd5n WO0PKNTq7qHU592Wg+MebxU2o5Kq/L3kNnuUafX3WexV1CdnBAEBpu10Xw3Lj/rG/sPQj4HWDMsw O+h474ksa3dN+JS4TMrBl0dCFTLNbdwPMqUvuNDjfMqG7ouxjSc724WQhiitsTbL/RUyUc3Qnh0K GbhrctQENJmN7bE2yQ1exhfrwsELvGGKbHvoauceJfeuhlmNwBbYoaRheAL2shLmF9i03tqhTEWj NS4KPGYWZAo4C9jkkSlCLLTRSLLEioghZKRxyVKWAzUAzUAvwQDd51WCN0XUuBui/MtK5bE6i3Fa Ik0WaAlwWAAUaBYjLQ2U57gs0ZK8QnYnO+i0ista4UJcsG7qBq5bdzQsdNC1hayiRq5NgB0LdyJ3 AFzoqWTJtlqocepO6LaWKJm4sEC9hmqbG5YX4IS4NkKAgL7ossakIsL3Wri5Jaee6oZYDJYkQaO1 yTRgg2GhCWAFyCUTQBy1yRlIBPEK2IWsLZLL4hk8RbVZZUWbcHJVBk3zuQhCL2JzWDSZJdxCGkxv XKFKG2WStyMqbXstIydw7FPsVmbffz/2Ia3E46nE3laOMIAgPHXVGd2WveL+bwl29svyVS+bvM6x 2h5RqdXdQ6nPuy0HxjzeKm1HJVX5e8hs9yjT6+6z2KuoTs4IAgNP2tAnDsvb78b+w9DFR6HWjYYI 0uTrZDgMjGE2BHl0Ql9TMGB5sQAAEKWMJu/ZpFjqUuW4bDtfL0oCBDJdawPeVNIgtABGqCxDmXA4 W0WWZsY4lhY5KoquYYjbm1rKlMD2khQhgiN0PAIbMLxdGLGB+RQWZgfc3HlQJGNwUuasYj7qyWKU eAjVylHNQXKHeulyjLjdZaRCHarJSvhTmNgnpUJcA8ypLgmxWrIXZJvzm6w0VMA8+S0kS5Iz0zVW gTZIaNAjNNsu0LJjeZcDJavcqbHlUsHIuL7qIiLD5VTZOajuZirlmmwsc+lU21YkW4qmANUOTmLC 2l1EZLeALZsi4UZneLAt76hNSUNJEG4yVRqwsTzKlJAFkBOeilgQSQdEsSxbMjio3YhNiCnEocRc XRIhGXBVgknK11lJMFbC+t1s0A0nUKaEJ0yWWtSE2yWXxF7AG2ZWrGrEixKWMg66lYaKRc6gqWKg DfRLG+YEC+qhl6MrmDfyrSYO4digthWZ/Pn/ALuGuWPA4qnE3lU4wgCA8ddUZ3Za94v5vCXb2y/J VL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yGz3KNPr7rPYq6hOzggCA1Has3ew9Li/wBtt/Ye qjE+B1vDY+3yZKHAcmFCAO6/tr2JQWLbjQ47oNuOSAzNYLAtGnQgIewl17DmQ1Yjda8XAItpfmVK VLATkSUQRR1gcx8iAwvYHZuIaL8RkhTFx9z0ZlQXMMYW4oaOI9tyQcghUjju7V9rIUwxSAUBx3HU oS5hdzhSxriUJFszmqWxjdbiSgKFwJ1WWLBxCzwCKXzyzRK40uCLnJCuyGgzKJC9yjnXNgVbEHkS xbE5cQEuEWOmoRi6I8AWbhokdAstXCLCwKlzTZZpQ47Fx31dDSRIOSjYaL35rWQyizRxVORlkMoZ GyFdxkAqVFm2IJTnLcsdQlkWyJAPQtFuiTYdKWJZADipYpJ1sqVEWF+dCl2tHQhUg6wNghACOayA kC5vxUuQEWzsfKo9SEA5pcoIB76XAAtpZTeuQHmUTKVuVVIvEm9ha6MjQuqiqLAvwyWWhuk3sMwp vGraBrsuZVsyTc6Epc0khcKvRXLaxBIWXwBBtchYYevEqCd420QWO4tif2KzX58/93DXLDgcFXib 0tnGEAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3ZaD4x5vFTajkqr8veQ2e5Rp9fdZ7 FXUJ2cEAQGqbUf6AgE6Cab+w9WJipwOv2w22uLWtkQjOBsyNZoRlks2JvGeFC7UDS546BUtzK6GG 2aDzXKFMZZna3HWypopbdd90EANi42bla9tUBie3K9s+Chm5SILWLgARxQ2kcSI0B175ISxgiC5K GjhxLlxcgOJEPb5aIW5xop6eKC5heebLNCGJxIORuhpMxudwNkNFCebNZuUgu6ULcjK6DUocjkiI AdblRkYceCIIhosLpe5SpOaal3kSM0sS4IR9BC2SiQJ0NwVopIIKjRbl25FSxouFEiNkg82a0oku WbrYKsha5GqiZWTc21VRm5IJABVsUsCTnbJZ5yrQnjYIavcuLBqAbx5r9Ctypkk/QhbahpvxC0bL G3DNRmHIW6LLKepFK5YWtmtmhlvW4LLBJtnkVEyoi91qxABlcm10sBa2d7hRoFC7tgFbFLAg5ALO 6GC4d5TdIVtxuVLWLcHXglwQ4noWkypjjkjFywN9PIuNo3cG3eWuBGiN7dOl8k1ZOBLXXbfNDSIu P/tR6Ap0k9CrV+BOIB4LNtSncmxA3wpNX+/n/u4a5Y8Dgq8Te1o4wgCA8ddUZ3Za94v5vCXb2y/J VL5u8zrHaHlGp1d1Dqc+7LQfGPN4qbUclVfl7yGz3KNPr7rPYq6hOzggCA1faUwPocAH76b+y9VG Z8DRYbN5pDtRxCHjSZeGzdcSCbcc+CrREzkw7ubfUWzWTRHJ3B484Qoc21uHfQFYjTlbThmqioxc mXHJ1s+CGiroNgXB1rHyoQ40Rtxe/FQ1YwxWjMkE30QHBjWFxaxQpwIx3idOZAcd9m5XIuhUcZ97 jPRCmB7jfMCxQGCIc7HTghShyBJyWLlTsQHIw9SrnW1CpdCpdfUKFKkmyidjBB3hlZauUg3/APpR u5Urkk2AvqoNCoIv/siYtcsD/wDLK7xN0lRl3SRZaT0ISLFDdlYsAARnkoYJ1WkQtrYkiyFLjnUu QsBbO5U4lLa8PKlg0ToelW/MSxYC2Z4obiizdBooGi2fBAiwOWZzQozve6pUgL3sSVTXAuBbIfSh m9xe1vSqatckHLmCC1gShURrZCgngSUALhYoRk7x46KGVe5G9bQKmyt+KEJBHlUYZBt0qJhAubzn mUD4kam6WLYE9N0diWuRdVF4C9s0aNIb1ypwKSN0k5rLYF22yUuCptbXNa4sFAdDzq2sZtqS51s1 lGjuTYYb4Smvz9/7uGuRHBV4m/KnGEAQHjrqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1OruodTn3ZaD 4x5vFTajkqr8veQ2e5Rp9fdZ7FXUJ2cEAQGtbRv6FgfnLf2XIYqcDS4Nt4EC506AoePa5mDAM3G5 0A4XVLYybt8gOmwQFWgZEEa86Fsy+6S29gSgKOZvAFxAQIxxGAgO0I6LXQ2YngEkAjJBY4kZudja x4oaOHGIBAIKEODNPBzbw06EB8+JqDcXBNxdDVjjPcS7ggSMEU304IU45NiboRIxPtfVRmzHEIJK iBU2yshUVcbqEehUn5FGiplTrqpYqVxexVaK0Te2itix04lTnqo2ZauyQsgjO/QgZZa0Mq7LA2zy SxqRN94WC18TJYNyN1LahokXAyVuLFgDxJQJFha3FZsLE68VpBqxdt7LLBbvokNCwvwWjaZNyTko zL1LjmSxOA46obLA2KouybjM8VTSempLTw1KFuiXdKpUSMtUDI3iXXOiFQJvogILggAJPMgDncB5 UJYnesLXzWXqCN5t1N1gkkDOyjYMbnELSSBVpuEsTnL3txyUa6DkuVuAdVbXM3BCal5iBc5JqQkW AI0WZGokutaw8qyWxF1LBrQoT2y2ZWoNr6C6l2zVihcCLcyrVgd07C/sSmrff7/3cNahwOCrxN+W jjCAIDx11Rndlr3i/m8JdvbL8lUvm7zOsdoeUanV3UOpz7stB8Y83iptRyVV+XvIbPco0+vus9ir qE7OCAIDWtoovRYH5y39lyqMT4GmQ2ndtvaqHCzND3hk8E5ZBCGQC4Jzz4X0QDM8Fbmrlt4WAAKl iAu7UCwA50IY3vN+ka9KFOJGIsc9OhDkRwYrri9xzIRo4cd9rkm5AQJWPmTD3XDb9BzQ0cWI+xzG SGjjRTnZAcZxOiAwPFuN1AYj0qmihI5vlUBW+SlgipVsQqTY5qMqFwc7qXNptkXHOlyNk3F8slls JkXshRvd5aXAwyRdDTdybjjmjMsnLoQt7hpI1KrIXB4c6Gmi18sjxVtcyW3u+iRUy7XCyyaRIIAQ j1LNdl0q2CsW3rnghGid7pR6EuWbkoCwJV5i2uWBUNR0B74VDdy1r8VQkSBYaqIjZKtzVyS4IEyF Tdxo4cboUjn1QEZb2Z7yAf6ICd4HPVZaBW4GZWgTcEXWd0FTYnVaAIF+ZC7pGZFllkehDSL6FEEP fLRyWDHXvlbNQjRB1usyVwTe6iiRO5G9lotWNNC+RNgpbUhW9vCjSQ4lXm/Ms6g7o2Di2EZvK3/E H/u4a5IvQ4KvE7AVOMIAgPHXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdQ6nPuy0HxjzeKm1HJVX 5e8hs9yjT6+6z2KuoTs4IAgNb2hW9hYN/vlv7LlUYnwNNgG+hy6VDhORlazdUJcm9hYlASAM7n5E BLQCNdUKQ4ta4A5oLXOPEcMyXaaFGLHCmHAAjM9ChuJwI7iARnmqaRwZiIBZo8KCxw47gDmb3zuh UcKI7PLhzoU4kRzi8nggMbyLWUZTBvG5RAxueAQMlQzFvdtmssFS4XUWhSN7O1iFq5LEXHFYbNRI JFr3RBOxUu43KWFywPEqtEF8lEy8xGVleBkXS5bEu0VQAI51SF97mQFm3tbVRmrk8VUQv0qgu08O hZsaTJ1ChkNvcLQRcX1sozRYFCWLNPQoGXBIyyCFQBPMhSwCpOA3uFilyssCdECJJscjdDdiRzq8 DLWpNxZU0QCPAgIJAQ0VGeg+VAMuc3QFr5WQEFAQT0ICuV73QC/fKyypsX1sUsW1irSedOAVib8S LKlI3hY2QkiocUaJYkG2qj0KlYm9hYHJZubZV3EXsqnYyL5AXRsvArxJy8qq4GLM7p2D29qM3Y3/ AOIP/dw1YnFU4nYCpxhAEB466ozuy17xfzeEu3tl+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq /L3kNnuUafX3WexV1CdnBAEBwa1TIFVlWy8w+KxrXh4MMgG4BHEHnVTsRq58xmEaa3SPNnvvb/Co Z82i4wrTxpHmv1m/woZ80ifatT735WZ/Wb6EL5tEtwxINBAjTNvxm+hB5tEDC1PGkea/Wb/Cg82i PatT+Mea/Wb/AAoXcRjdhCmn7YnP12/woNxFH4LpbhYzE7+u3+FC7qMT8C0lwsZme/XZ/Cg3UYYm zuiP1mah8Yz+FBumE7NKEftupfGM/gQtjG7ZdQHazlU+Nh/wILFDspw8dZ2q/Gw/4EFih2S4cP27 VvjYf8CNXLYqdkeGz9vVb42H/AolYFTsgw0ft6r/ABsP+BUEHY9hn7+q/wAbD9WgI7DuGfv+sfHQ /VoCOw5hj7/rHx0P1algOw5hj7+q/wAbD9Wo4pgHY3hj7/rHx0P1aKNgOw3hj7/rHx0P1arQHYcw x9/Vj46H6tLAdhzDP3/WPjYfq0sB2HMM/f8AWPjofq0auFoOw5hj7/rHx0P1aWLcnsO4Z+/6x8bD 9Wlg3cHY7hg/b1X+Nh+rSxB2HcM/f1Y+Nh+rVBPYewz9/Vf46H/ApYAbH8Mj7dq/xsP+BLAsNkOG hpPVf42H/AqCRsiw2Pt6rfGw/wCBAT2JMN2+vat8bD/gUsANkmGx9u1X42H/AAJYLQsNk2HB9u1X 42H/AAJYtx2JsO/ftV+Nh/wJYjY7E+Hfv2q/Gw/4EsCexRh379qvxsP+BLFuOxTh779qvxsP+BLC 5SZ2ZYXlYRizNTqEGGNXxI8NoHhLEtc0t6WiR8Cco2ymTa50xjiCCz3TRUoDnD9ENJ+ReZDLsXUV 4UpP4RfgePLE0acrTmk/e0vzaNcqda2NSQO5iOtTjh72XhX+V0MD5V7DC7N5hibtU3H/AJtPzPDx mdYPCNKVRO/8rUvrut26z4E3jfZjDB61k8XRnfhmXYPLn9C9rT2Kxj+/OK+r/Q9XU2uwsfuxb+ni fEnMf4buRKYdqxHB0SqQx8ggH6V5sNh3/HW+kf7niT2xX8NL6v8AsfJmsdb1+taVyXNykxv/AENC 8uGxOGX3qkn9F4niy2wxD+7TXb/Y4Xt1ql8peT/Ud/Eub0LwP88/qv6Tj9L8b/LH6P8AqIONaqRb reS/Ud/EnoXgP55/Vf0j0vxv8sfo/wCoe3Sqfe8n+o7+JPQvAfzz+q/pHpfjf5Y/R/1E+3Wq8IEl +o7+JPQvAfzz+q/pHpfjf5Y/R/1Ee3Sq/wBhJ/qO/iT0LwH88/qv6R6X43+WP0f9Q9utV+95L9R3 8SeheA/nn9V/SPS/G/yx+j/qHt0qn9hJ/qO/iU9CsB/PP6r+kvphjf5I/R/1D251T73k/wBR38Sv oVgP55/Vf0k9L8b/ACx+j/qDcZ1Le7aXlCONmuB/aUexeB5pz+q/pKtr8an9yP0fifUkcdSTLde0 SYj8/Izwh/TDcvFqbD0X9ys18Un4HkQ2yrfx0k/g2vE+/TccYAeR7IUrE8vz8hMwIv0savBq7EYh f6dVP43XieXT2wo/x02vhZ+Bs1MrexqeIEWv16RceExBH0thuC9ZV2TzKnwipfBr9bHsaW1GBnxl b4p/pc22jYX2ZVizaZi4zT3aQ2T0Hf8A1d2/yL1VfLMXh9alKS6nb6nsaWZ4evpTqJ9Z9wbJsODS dqvxsP8AgXhHmecYOyfDp+3qr8bD/gUauPOsdifDv37VfjYf8Cm6iurIO2TYdOs7VfjYf8CbqCqt EHZNhy/17VvjYf8AAjjcOtJjsTYc+/ar8bD/AIFbE86zaMJYeksNU6JIyEWYiQokYxiYzgXXIA4A ZdqESsZlJyd2fYVMhAEB466ozuy17xfzeEu3tl+SqXzd5nWO0PKNTq7qHU592Wg+MebxU2o5Kq/L 3kNnuUafX3WexV1CdnBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAE AQBAUjRYUCE6LGiMhQ25uc9wAHhKjaWrNQhKb3Yq7NTre0zAdH3hOYmkXPbqyXcY7r81mA28KzCo qktyneT6Em32XPbLIceoecq0/Nx6ZtQX1m0afV+qDwZK7zZGTqk++12lsJsNhPNdxuPIvc4fIM0x GsaDS6ZWj2N37D0+IxWVYTSvjIX6Ib031OK3PxI0+rdUhVH3FKwzJy/MZmYdF+Rob9K95h9icZP/ AFqsY/BOX9J6XEbWZPSf+TCpU+O7T/8A7P0NTqm3LaHOE8jUpaRafey8qz6Xhx+Ve7obF4KDTqTl L6Jdiv2no6+2daScaNCEehvelJfWW6/+k1epY7xpUS7rvFNYe12rGzb2MP6LSB8i9vQ2fy2h92in 8fW71z1FfaPM69m6trfypQ7qRr0aLEjRDEixHxHnVznXJ8K9pSo06Md2nFJe5WPVV8TWxEt+tNyf S23+ZVcpwhAEAQBAEAsbXspdXsXddrhUgQBAEAQBAEAQBAEAQH26Hi7FFDLfYmv1GUa3SGyYdueF pO6fIvCxGW4TE/6tNPq1+vE8uhj8TQ/06jXXp9DsHD23/GkgWsqcGQq0Me6MSFyUQ95zLD/KV6DE 7HYGrrSbg/jdduvae6w+1GMp6VEpL6Ps8DsvDHVAYQqJbCrEtOUaKdXOby0IfpN7b/Kvm8XsdjaW tFqa+j+j07T3uG2pwlXSqnF/VdngdpUar0utSYm6RUZWflybcpLxQ8A8xtoegr5ivhq2HluVYuL9 6sfQ0a9KvHepyTXuOauE5QgCAIAgCA8ddUZ3Za94v5vCXb2y/JVL5u8zrHaHlGp1d1Dqc+7LQfGP N4qbUclVfl7yGz3KNPr7rPYq6hOzggCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgC AIAgCAID4VZxjhWjbwqeIaZLPbrDdMNL/wBUG/yLhniKUPvSR7XCZHmOM/0KEpLps7fXgaVWtvGA 5DeErGn6m4adby5aL9+IW/6rWHlUxTthqcp/8sWz2NfZevgo72Y1qdBf75pPqSu2aPW+qPnHbzaL huBC5ok3HMS/6LQ23lX0GG2WznEauEaa/wBzv2Rv2nocTnGymB0nip130U4WX/VNr6pM0at7Z9oN T3misiRhn3kpBbDt+lYu+Ve/w2wfPicQ37opR7Xd/keixHlDwNHTAZfG/TVlKf4VuR/M0mq1erVW LytTqc5OvvfemI7oh/zEr32G2SynD6+ZUn0yvL87rsPQ4ryh7QV04U6/mo9FNKn2xSf1bOEvoKVK nSju04pLoSsfIYjE1sTN1K03KT52239WFyHCEAQBAEAQBAEAQHJwvSa/iqtxKThihzNVjQXBsZ8M hsKEfw3nJo4Z55GwK9NjM6oYS7qcPz+CPfYTIauIipXs37jtui9ThXutolSxXjaXpcNrDEiQJGBy rYTALnt4lhkBmQ1fIVdq5OpejFtvpduxH1NPIaKpqE0rL98T7Uj1OOC5yUlanIY8rcV0/CbEl5ls WA5sdhFwWjc7ZtjcDReE9pMXTqNuCuuPHxPLeVYedPc5uo+FiXqbcWSJM1hzFUtVw3WUnYXW5eOY Obdod0kD0+fhdrV5xSqxa67nhYjZ+lKk4QS/U6irMlWKDXvYTEVHm6TOlpcxkcC0S3Fjhk4Wubgn RfY4PNqOLs6fB+8+VxuSVMLBybvb3GNe1PSBAEAQHPw/SJ+vViXpVNg8rNTD9xjb2HfJ4ADMngAv AzHMKOX0HWq9S6X0HmYHA1cbWVKn/wBl0neNA2VYVpcefp9WlKjWatTxBiR7Ew5V7H7pcGOBHbhp dZriC4tuBYrrXGbVY/ESe5LcXQvHj+R99hdnMFRj68d59L8D7cbBmApil06FKUOgOqEZ4hzkFtQA dABv9U/nb2bkS0XJuAvWrOcwTuq0vqzznlWCat5qP0RpeK9lNPmqbO1OgE0iJDnHS0nIT0ftpy2Q DN4Ah7tQ3MWIzGZXvcu2uxVGajifXj2/36/qeox2zGHqxbw/qy7P3+7HTURj4cR0OIxzHtNnNcLE HmIXZNGtCvTVSm7xeqPgqtKdGbpzVmiq5TjCAIDmUaq1OjTzZ6kz8zIzLdIkCIWOtzG2o6DkuGvh 6WIhuVYqS95y0a9ShLfpyafuO7tnvVBTUF0OSxnK9cQ9OvpZga8dL2DI99tu8V8Xmex0JXng3Z/y vh1Px+p9Zl+1Mo2hilf3r9V4fQ79oNZpVep0Oo0efgTsq/SJCdex5iNQeg5r4PE4Wthqjp1ouL95 9jQxFLEQ36Uro564DmCAIAgPHXVGd2WveL+bwl29svyVS+bvM6x2h5RqdXdRHU7vZD2x0F0R7WAm O27jbMy8QAeEkBTah2yqr8veRdnIuWZU0l/N3Wexl1EdmhAEAQBAEAQBAEAQBAEAQBAEAQBAEAQB AEAQBAEAQBAEAQEPc1jS97g1oFySbAIVJt2RrlWx5gylXE9ialw3N1Y2Ya94/Rbc/IuCeKow4yR7 nC7O5riv9LDyfvs0vq7I1Cr7ecByW8JWJUKk4achLFoPhiFv0LxZ5nQjwuz6LC+TrOK3+oow+Lv3 bmm1jqjopu2kYZhs5ok1Ml3+VoH7S3h62Lxj3cLQcvgm/wAvE87EbFZXlUd/NcfGn7tI/Ted39DT Kztyx/P7wgz8rT2H3srLN+l+8R5V9FhdkM+xWtTdpr3vX6K/6HzmK2q2AyvSlGpiZLoul9XuL6Jm lVnFeJKzcVSu1KcadWRZl7m/q3sF9FhfJ1R44uvKfuWi/X9D5zFeWSVDTKcBSo+9rel8dN3X43Pj knnX02D2VyjB606Cb6X6z7b9h8RmnlF2lzS6r4uST5o+ovw2v13IX0EYqKslZHxk5ynJyk7thUyE AQBAEAQBAEAQBAEAGeijdglfRG2bIdnVR2l4mdCZOR5LDshYVGbgGz3xD/UQz90W2JOjQb6kBfIb QZ0sLpB3b4Lm+L/ep9pkWVb0N+pHW/PxPQjcQSWFqIcN7OsNwA6BEMGXgCG4HlGEcu17DZxjNaRE AJvEZdzSbWXxPmJV5+dxM+P7XVze56M+p31BbtNfvn/fOfflqBXathKvSVbq81JvrLuUZEDw6JJQ nw2b8Fotut3TvgHPIgnO68aVenTqwlTjfd7X0/kcihKUWpPifIksF4RlalSHyOLnNiUmYjRZVj5q DEeBFO86HvEb25v3du+AWAC55YuvKMt6H3rX0fNz/GxhUoJq0uBSRwdivCUOmQqNXoszSZONHm52 FDg3jTBJDtzdcTvgtDmgbwIc4HOwCSxVHEbznG0nZLoQVKdO1nocGr17DWOsHylCx1Q4Rq9SER8n TYW+I7bEhkRji0OhOO6bE6gX0K8bFV6uVSdbD3lay052+Z+738x5WEw0ce/N1GorV3fMl++HOedd ouB6xs6xW6jVWYfNyM2BEpU6+31Zo91DPNEbdoLeORGq7IyDN4YuF5Oz510PwZ8Ln2VOmlKnG+vN zo+EcjYr6k+RCAIDt3YfS5OFSJupVCSqEY1OZZTJeJKP5N0HIPc7fPai5MIWJAtva6Lq7a/HOtjP Mp6QXa9X+iOw9mMIqWF86+M/yWi/UjG81DxXLYwiTtam4knhdsGWpUtvndmYnKFkWNEbo4ucCPwA BbJfJn0prWEsFddVChzdap8OFSamXvkWktDqi6G1z+QbbtmhwY67iBYZoDa9j2IYVZrkzh+ZlITq bFbEnqJJzk08skXN7YwTGN3iFu9sW6Ew+YkIDWtt8jKwsXuqslGl48Got5WJEl2ubCMwDaNuB2e7 vDevc3312JsXjXOlPDSf3dV8Hx7fzPhtq8Io1IYiPPo/iuHZ+RoS+5PkAgCAIAgPs4RxTXcKVMVC hT8SVi5b7BmyKOZ7Tk4fRwsvDxuX4fHU/N143XavgzysJja+Env0ZWfY/ientlO2GjYv5Km1IQ6X WnZCE531KOf+W48fwTnzXXWmc7NV8BepT9an086+Pj+R9/lWf0cbanU9WfY/h4fmdnr5k9+EAQHj rqjO7LXvF/N4S7e2X5KpfN3mdY7Q8o1Oruo0GA98OMyJDe5j2nea5psQRoQV4W3GmRV/l78T63yS xUtrsImrp+c//FM782WbdnS8OFSsa78VjbNh1Jjd5wH/ADWjM/jDPnB1XSeFzO3q1fr4n6B2k8ni qN4jLNHzwfD5XzfB6dDXA79pVSp9WkYc9TJyBOS0QXbFgvDmnwjj0L3MJxmrxd0dTYnC1sLUdKvB xkuZqzOUtHAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQHGqFQkKfD5WfnpaUZ91HitYPKSsynGPF 2Oehhq2Ie7Sg5P3Jv8jVKttV2fU24j4nk4rhwlg6PfwsBC8eeNoR4y/U99htj86xP3cO1/zWj3mj T6v1Q2FZcPbTaVVJ549yXtZCY7w3J/yrxZ5rSX3U2fR4XyZ5jUs61SMV1t/kl2mn1fqiq/GNqVQK dJjj1xEfHPgtuD5F4082m/uxSPosL5MMFD/iK0pfBKP57xp1X2wbQqjvtfiCJKw3e8lYTIW73nAb 3yrjp18bi5+bopyb5oq77NT3Mtltm8pp+exMYxiv4qktOvee72Gn1WtVWqv36pVJ6ecOMxMOiH/M SvocJsTneNs5x3F0zf6K7+qPm8d5UtjskvDCtTa5qUNP+r1YvqbOAX8wX1mC8mdCOuKrN+6Kt2u/ 5I68zXy+Yud45dhYx9825P6Ldt9WQSedfXYLZPKMHrCgm+mXrfnfsOtM18pO02aXVXFyjF80PUX4 bN9bZC+hjFRVoqyPiZ1JVJOU3dvnYWjAQBAEAQBAEAQBAEAQBAEAQBAYpmXjz7YdKkm787UYsOVl Yf3cR72gDvZ59C9dmdaFOg3J+/qR7bJqM6mJTS0R6zrMOlbKtltNwfTok5KvmIESCJ6WEMPbE3d6 JGvEIa+IXO7WHfedo3MZdVU3PH4mVaVnbmfYtObpfBc52PK1CmoIwR65JbI8BTOIsWQBGrUeKZaV gQo7oj5oNLjBhMe/t9xoLjeJdzAXC5AAOlRlmFdUqL9Vav3dL00v8NGHJUIb0+J5a2hbSMY46nIs Su1eMyUc68Onyr3Q5aGOA3Qe3PS657y+rwuAoYVWpx16Xx/fwPV1a86r9ZmmdbS/CBC/UC83efSc Fkd9dTpWcY0KSiVqbr8+3DJhxGS1PigzHXDhcGKwOzhw2HLfBs52Wdivgts83wWAgqe7es9dP4V0 v481z6rZrJ8TmNS6dqa014N9C9/wO2qVhuPW6BP4rgOhSuJwXwIsSVmX9cCGGt3oUV4DnMikBhJY 0P3WtYN269Hs/LE06MXjI2UvWSevHg3fi39Pcefn7wrruGDldR0bWib50rcy63e+pnxBQ+yzsWmq JVYsnFxDKNduPY9hfBmodxDdEY1x5Jzx7qGSd3fc3UL6ClW/w/GKcL7j/J8bdNuZ856GUPP0t18T ydIRBEk4YsWvhtEKKw6w4jRZzD0g+niu2sFOMqKs+B1lmdKVPEyclxM68s9eEB6S2VRDRsBUGJK1 aHLRhBmpyJLcq4Oj9tFIBZYtddsMAElpFsr6Lo/MarrYurN88n+Z27gKapYanBcyX5HUOBeQmsP1 inVD2RlYVUZL7s9LwIsVrYjXl3bsaN2JDDiHPzDgNOIXhHlnZbvYmBsfoj8NzNVgQWVl1Li1ialX OjQYD4h65fAYLuYyIW7o3c2h1jaxQHxanJYcw1tdwa3C4ayWbMbkwYbX8lZ8RzGfVHjtn8m8B2ob ujnQF+qBEzMYcpM3Ua1JVmfl52NLRYstBEPkQ5jHtY7TeNm33rDU5BfS7JVdzMox/mTXZf8AQ9Bt LT38BJ9DT/T9TpddsHWwQBAEAQBAAS0ggkEZghAd77GttsWTMGg4zjvjS2TIFRdm+HzCL9038LUc bjMfDZ7ssql6+DVnzx6fh7/d9D6/J9o3C1HFO65pdHx8T0bBiQ40JkaDEbEhvaHMe03DgdCDxC68 lFxdnxPuE1JXRZQp466ozuy17xfzeEu3tl+SqXzd5nWO0PKNTq7qOv2e6C8LbjkKv8vfifXeSP8A /eGD/wDuf/imZF+ez9sH1MN4jrmHJzrqh1SZkYp91yT+1f8AjNOTh0EFclOtOk7wdjwMfleDzGn5 vFU1Ne/ivg+K6jt7CvVD1SXayDiSjwZ5oyMeVdyT++Wm7Se9ur2dLNZLSornXmZeTLD1LywVVx90 tV9eK7TsygbZsAVYNDqs6nRT/VzsIw7fpC7flXn08woT57fE+JxuwudYThS310xd+zR9hvFNqlMq cPlabUZSdZa+9LxmxB5QSvLjOMvuu58viMJiMM92tBxfvTX5nLWjxwgCAIAgCAIAgCAIAgKxYkOE wvixGw2DVzjYKN24moxlN2irs+NP4vwpIX68xLSIBHvXzkMO8l7rjlXpR4yX1PZUMkzKv/p0Jv5X 4Gu1HbBs7krh2Iocdw97AgRIl/CG2+VcEsfh4/xHt6GxGeVuFCy97S/W/Ya3UeqEwfAu2Tp1Xm3c DybGNPhLr/IuCWa0lwTZ7qh5NM0nrUnCPW2/yt2mtVPqjpp120zC8GHzPmJov/ytaPpXjyzd/wAM T3eH8l1Na18Q38I27W3+RqtU28Y+m79bxqdTwdOt5UOt8YXLx5ZnXfCyPfYfydZNS++pT+Mv6bGq 1XaFjeqAicxRVC06thxzCafAywXjzxdafGTPfYbZnKcN/p4ePWrv6u5rcaLFjxDFjRHxHu1c9xJP hK4Lts9zGMacbRVkjGSBxXvMFsxm2N1o0JW6X6q+rtfqPks22/2cym6xOLhdc0XvvrUbtddipfzB fY4HyaYmeuKrKPuirv6u1u06vzby94GleOXYWU30zaivot5vr3SC4r7HA7C5PhNZQc30yd+xWX1R 1fm/lg2nzG8YVVRi+amrfie9JP4NEL6uhh6OHhuUYKK6Ekl2HXOMx2Jx1TzuKqSnLpk3J/V3YXMe KEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAbt1PVJhVXbtQXxAHiQlZibc37ktAaw/rRD+qvjtrJqnh5 Wersv39D7PZhOSs1omd8iqUrG20SVgS9QdEpxhPhx5WLKxQyYDA4mC67zCffebEs5ge1pbY52XxX m54bDtta9N1p7+F10cbH1W8qlTR6Hn3qrcRPrO1mPSIZIkKBAZJy8MHtQ9zQ+I63Pm1t+Zq+iySg qeFU+eevgeBjZ71W3Mjrp+HcQMoLa+6iz3sS5u+JsQ7w929t42zDb5bxAHSvPji8PKs6Cmt9fw31 +hwOjUVNVXF7r57afU5+z3DjMSVxzJwxGUmShiYqERhs4w72bCafu4ju1HMN53Bevz7OaWTYGeKn q+EV0y5l4nnZRllXNMXDDU+fi+hc7O1cR4iOHaLMYh5ODDmLCSpUq1v1IRQ3tQG/2cFtnWORO5fM rqDZLK620OazxeLe9GL3pPpfNH4e7oR2btPjqOR5bDA4RWlJWXSlzy+L4X+JHUZ4mm5PaLUcOx48 SNArMs+acYjruMzDIJeSdS5rnX590LtnaGgp0FVXGLt1M6uwE3Ge50neeD5RuGNos/R5SlyMlS5t hLI3bse94s5jQYkT6pk6JcQ2AC2ZJXoMRLz+HU225L98y05uLPOgtybSWh5h2rUeDQ9seMZKEA0R J5kwxg4Mis5S/e3nvHg6V2JszU87hoyb1tb6O36I+K2mTjNRS0ua+vpj5UID1TskpVLrmxyUnmyj ItThSk1KsjZ7wIdFDei9n5d9dG4+m6WKqQfNJ/mdv4OoqmHpzXOl+R1ls1gVSHslmKlK4lxJTjCj xJGVladHYIYnYjoLYF2EXsXxSXc4zXiHkm84hqkmyTp8lIYjfL0yj06pQYjpWL1teqSrYY3uV1cT ykTtffG5sbIDU69DnJrargSnRKpVKlBizMKZhxJ2aEcOBeHbzBbte0bY8HZEZID7fVWytPpdCoNP p8tBlhFmo0w5rBYus0C5+MX0mylPfzOD6E32W/U9DtJPdy+S6Wl23/Q89rtk61CAIAgCAIAgCA7c 2GbWY+FY8OhV6LEjUKI60OIbudJk8Rzs528NRxB+T2h2djjYuvQVqi/F/fofU/d9JkmePCNUazvD 8v7ftHqeBGhTECHHgRWRYURoex7HAtc0i4II1BC6wlFxbjJWaOw4yUkmndM8e9UZ3Za94v5vCXbm y/JVL5u8zrLaHlGp1d1HX7TY3XJtHltTM8sq4Wm7Sklb4pp267WPZbDZ7RyDP8NmFdXhBu9uiUXF vqve3Paxdfm6tRnRm6dRWktGnzM/duGxNHFUY16ElKEldNapp8GiVxnOEAQFoUSJBiCJCiOhvbo5 psR4UTtwMyjGatJXRsFNx1jKnACTxRV4bRowzT3NH6JJC544mtHhJnqcRs9lWI1qYeD+VJ/Van35 PbNtGlrD2fEZo4RZWC75d2/yrmWYYhfxfkepq7CZFU/8m3wlLxsfVl9vuO4Xu20mP+PLEfsuC5Fm lddB6+fk4yeXDfXwkv1TObC6ojGA/nKTQnd6FFH/APoVtZtV6F2+J40vJllb+7Un9Y/0mUdUVie2 dDo9+9E/iV/xap/Kjj/+GGX+2n+HwDuqJxT72iUYd8RD/wD9p/i1X+VFXkxy7nqz/D4GGJ1Q+MSO 0pVBb34MU/8A+iy82q9C7fE5I+TLK1xqVPrH+k4kbb9juJ7iHSIX4ks7/V5WXmld9Bzw8m+Tx4ub +ZfokcCY237RYt9yry8D8nJwj+00rDzLEPn7Dy6ewGRx40m/jKX6NHy5rattCmQRExRONv8A2bWQ /wBloXG8diH/ABHn09jskp/dw667v82z485jHFs5frrE9ZjA8HT0QjyXsuJ4irLjJ/U9jSyPLaP+ nh4L5V4Hx5iZmJl+/MR4sZ3PEeXH5Vxtt8T2NOlCmrQSXwMahsIAiVyNpK7IJA4r3WD2czTGf6NC TXS1ZfV2R8rmm3Oz2V3WKxkE1zJ7z/6Y3fYQXhfWYPybY+rriKkYL3es/wBF2nXGaeXfJsPeOCoT qvpdoR+ur/CQXFfVYLyc5ZRs68pVH8bL6LX8R11m3lyz7FXjg4Qormdt6S65er+EqSTxX12CyfAY H/h6MYvpS1+vHtOs822nzjOG/t2JnNPmcnu9UV6q6kF7I9EEAQBAEAQBAEAQBAEAQBAEAQBAEAQB AEAQBAEB2L1LcSHKbdIRcc5+kzENgP3TDCcbfoj6V8RtdRth95PnT/M+42Yr763WuGh6wlKJRZKo dfSlLkpaaLXt5SFBaxxD3Bz9B75wBPOQLrr2VapKO622j65QindI8N9UPJR5DbdimHHYWmNMsmIf 4THwmEH5CPAvvMqmp4Om10W7T0eKVq0j7uyTEUWcpLaOI7oNWo8Jz5J7dY8ncl8PpMMuJ3dCxx+5 XXnlByKpFxzjC3Uo23rcfdJfDgz7rYrN6b3sqxSThP7qfC/Ouvm95tFPkqexjabQqdApcObmHTc0 1r/qRjbtjEH3EJjASG6NBfbVfBZrnmP2inQoz1kvVSXPJ8/xPtctybBbPQr4hP1Xq2+Kiv4fr+h1 BtDxFDxFiDlJIuFKkmdbU5rhYmGDd0U/hRHXeejdHBd8ZDk9PJ8DDCw4rWT6ZPi/0R03m2ZVMzxc 8TU5+C6FzI3bqSJSLNbcJCNDaSyTkZmNFIGgLQwX8L1c9ko4Jp87XicGCV6yPYj8OYei1oVqJRaf EqjYgiCbdLtdGa4M3AQ8i47XJfGKvVUNxSe70cx7fcjfetqePtv0SFObecTzcKILQBLypaDq4QWF 1+jMW6QeZdlbKUf/AJWEnzX7Wz4raevaXm0uP6Gnr60+PCA9IdSPXmRaRVcORXjlIEUTcEcS1wDX 26AWt/XXVG1mDdDHupzT16+D8es7I2bxSrYJQ546fqvDqOusTUyawDtgjyzZGFF35l8zRmTUbk5d z4hPIxST2p5J7iLHQtFyMivmT6A+2+lVOR2ZTOFZerUKoTTnvjzMGMYbHyu5EhxIjhEMQse7edfe sSQLAC2QH1NgXs3jjHsHFNYcyPJUKXiw4EZsu2G10eMc25akAucebeGl0Br3VR16HVdoYp0B4fCp cu2ASDcco7t3/S0d9pX3+xWDa85iWv8Aavzf6HxW1mKXqYdfF/kv1Opl98fGBAEAQBAEAQBAEB3f 1OO0x1KnIOD67HJp8w/dkY7z/MRCf5s/gOOnMeg3HxW1ORefi8XQXrL7y6V0/Fdq+Gv1mzuceaks NWfqvg+h9Hwf5mo9UZ3Za94v5vCXttl+SqXzd5nrdoeUanV3UdfL356UlrrL5PaPZLC5yvOL1Kq/ i6fdJc/x4rsOyNhvKVmGysvMtecw7esG+Hvi+Z9K4P3PUuCCul822czDKpP7RT9X+Zax+vN12Z+q tm9uck2jgvsdZb/PCWk11c/xjde8lejPrggCAIAgCAIAgCAIAgCAICLjnXsMNlOOxX+jRlL4Rdvq elx+0mUZdf7XiqcH0OcU/pe5G8F9Dhdg85r/AHqagv8Ac1+Su+w+JzDyxbK4O6jWdRrmhF/nLdXa QX8wX0eF8mU3riK6Xuir9rt+R8LmPl+pK6wODb985JdkU+8RvFfTYTyf5PQ1nFzf+5+Fj4LMvLRt PjLqlONJf7Yr85b3ZYi5X0+EyrBYP/h6UY/BK/14nX+ZbRZrmj/+dxM6nulJtfS9l9AvPPTBAEAQ BAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEBzcJ1p2FMe0LF++eRpsy3rtltYDyWRCOkNeT4B zZ+hz3AvE4eVnxXbzdp9Hs/jVSqqk1z38T1ptoq9QpVHomJ8OkTszTpwTrpOGbun5Pk3CYZD4OeI bjEaNTyeQNl1ll9KNSc6VTRNWv0O+l/dfTrPvq0mkpR/7nVvVC4VftGpEfGWGZV8es4ejPkKnKQx d0eAAIrHsHFwbEa8DUh7hqAvbZVifsc1Qqv1Z6p9D4fpY8TFU/PLfjxWjPNlIqM3TajKVWmTBgzc rFEaBFAvuuHOOI1BHEEhfTVKcakXCaumrNdKZ62MmmpRdmjeMVbQ5Wo0CZp9GpMxTZios5OefEit eyFCOb4UC2e64ixLsw3tc7kr4vItiMLlGOli1Pe47if8N/zfMj6jONrMXmmEhhppRX8TX8TX5dPx NAAJcxjWuc97g1jGNJc5x0aAMyTzBfbHyx6n2OUeFsYwmKviaUiHEVehxZmJKsG8+Vk5aGYhZlq/ MXA1fEaOC+TzCq8yq7lJ+pGyv0tu379yPa0IfZ43lxf5I7G2W1Scp2zeoYjxjMwoM+Y8zUarCa+7 ZEnt+t731hw9xpHAgjVetxtOM8RGlRWmiXv9/WzyaUt2DlLrPHkxOzNYrdVxHNkiPWJp026H/Zhz iWjvgEDwLtXKsGsPRjZ81jrrO8b5+q4JcGSvbHowgPtYJxJUMJ4kla5TXDloDu2Y73MRpyc13QR6 RmAV6nOMqp5nQ83LRrVPofg+c9lleZTy+t5yOqfFdK8T0LMbQcF4/kpJk5GpcBsFkV0xTauxu7Fi FlobQ8ttu72ZcHNOQuM8urcZkmOwkrVKbt0rVfVfqdiYXNsJiVeE1foejPk0nC+zyAyhzFUo+DWb ximoua+C6E0NvyZDeUJaTcWDQRrfgvXKjUbsov6HnOrBK7aE1tbksG4Qi0WnzknWas17xKvlWAS0 uw6XIa0OsbkNA0sCb3XvMu2bxuMkt6O5Hpf6Li/y956nHZ9hMLF2lvS6F+r5jz3OTMecm4s3NRXx o8Z7okSI83c9xNySeckkrtTCYWnhKMaNJWiv32nXGJxNTE1ZVaj1ZiXknAEAQBAEAQBAEAQBAc6u 1aerdSdUalHdHmnw4cN8R2rhDhtY0k8TZoueJzXBh8PTw1PzdNWWr+rb/U5q9edee/Ud3p2K36HB XOcIQBRpNWZYycWpRdmiQ4jivmcfsdlGNblKluvpj6vYtOw+/wAm8qG02UpRp4lziuafr9r9ZdTR O/0L5PFeTKk9cPXa90lftVvyOyMv8v2Iiksbg1L3wk12NS7xO+F6Kt5N80h9ycJdbX5r9T67C+XX Z6rpWp1IP/li12Sv2DeHOvXVNhM8jwpJ/CUf1aPeUfLDslU+9iXH4wn+kWTvDnXjvYzO1/6d/WPi edHyp7JyV1jF/wBM/wCkbw51Fsbnb/8ATv6x8Svyo7Jr/wBZH6T/AKSN4c65Y7EZ5L/yPxR/qOCp 5WtkYf8Aq7/CFR/+wbwXlU/J/nM+MIr4yX6XPXVvLRsrT+7UnL4Qf62G+OlefS8muZS+/Ugutv8A 9p6ev5eMhh/pUKsuqKXeb7CN/oXsqPkxf/m4n6R/Vv8AQ9Bif/1AR4YfA9cp/oo/qN8r21DybZbD WpUnLrSX5X7T5zGeXfPaulCjTgvhKT7yXYRvHnXuaGxOSUdfM3fvbfZe3YfLYzysbV4rR4rdX+2M V22v2kXPOveYfK8Fhf8ARoxj8IpfofI47aHNswv9qxNSf/NOTX0bsF556cIAgCAIAgCAIAgCAIAg CAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIDHMwWzEu+A8uDHizrarirUlVg4s58NXeHqKouY7q2I4 rpuJ8JdiTGMeK6egMEWgzjJgwIrwwkw2w4urI8MjtTxaBrYg9c51l1TAYn7TS4fxaXWvu6Hz+87E yvHQxtBJ/uxyWVGqbOo9fnZzF1djVaajQpyFL1HDcbejx4TOT5OJFgB0F7IkMBhe2xDmtdqCD4vm 4YxQjGC3VppJcHrdJ6pp62fwPM3nSbbbv8DFiGQ2O7Q6SMT4gkKvs9rM09rXGJBMF81FPBkMtImD +E1tzxVpTx+Dl5qm1Uiuuy+PN1sk40Kq3peq/wB/U0qFs32Svmmwhtimom9GdAbBZRnGMYjcywCx O8OI3b9C854/G2v5j8WhwfZ6P8/YbvTImyrZfQGYkwRRajjysOYWwKgxhmGQH6ERHNFoFjqA3etk vBmsbjp+aryVOPRwv8On62OdeZoLegt5nIhsqOPK5R6hS8b4lizctKRYMc07D8WWeXx3AxyJiYAh wWWaxjbXc1rMrkkrD3MLCUZ042bXGSfDhotW+d8xVepJNSf06fez4W33GFJZR4WyHBL2waVTt0Vi PDeYm865PIBx924uu57je5FjclwXssgyuriazxVbi+Hj+iR6/N8xhhKW5FX/AH+7nU0NoZDaxt7N aGi+uQXYNKmqcFFcx17XqutUdR85ZchxGy4RwzDxBMzsN06yShycqJh8RzQ7eBiNZYXc0DN4NyeC 6v8ATLMOiP0fidh+iuC6ZfVeBEbC7oE3iOWjTUJrqCLxnbrgI31dsHtb2Lc3g58PKp6ZZh0R+j8R 6K4Lpl9V4HNlMEvj42q2F3TobEpcOYiRIzIW9yvI2uGsLhm6+V3Ac5T0yzDoj9H4j0VwXTL6rwEp goRsb1PDD6pAYadBjxos2IZ3HCE1riA1xbY9tbMgAg52sU9Msw6I/R+I9FcF0y+q8Di0PCprWMhh 2Rmg5u/E3prky4Nhsbd0QsaTcXysCdRmnplmHRH6PxHorgumX1XgYIOHIp9n2zTmykWhtHXMN9zd 3LtgFoPDtnXvxAT0yzDoj9H4j0VwXTL6rwONimjmhVypUiJFbGiSEy6XdEaC0PLTa4B0Xtcl2lxm OxsKFRR3XfgnfRN9J67NsgwuEwk61Nu6txa52l0HyF94fGhAEAQBAEAQBAEAPfugCAIAgCAIAgCA IAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAwTMrBm Hw4j99sSGd6HEhvLHsINwQRmCCAQeC8avhadf7x5uFx9bC6Q4HZuHtsceblYFA2iRcROZKm0rX6F NPgTbWEaRWsIES9gCQDpfdJzXw2MyGVCrKWGS/5ZK66ug+5wmbU8RSi6jt8HqdjYXwjspxBBhzWD cb8rUpmKOv6lHnzHqkWWsd+Ax8Qh8DeNgXMAda4Fr3HpK2KxtF2r09FwVrRv06aP4M9rCNKWsJeJ 23O4QwvM4TbhmLSJVlHhsAhwIY3BCto9jhYteDmHgh1873Xp44qtGr51S9b9/ux5Tpxcd22h09ib DuyfDUJtQxTjyNCxLBc5pqlJnDLVKaYHHk2xWwCeViBtgXloLiLnivdUa+Nrvdo0vUfM1eK6bX4L 3X0PDnGjBXnLXtOtsU7XqjNSEbC2B3VunUyNvOnKvVJt8aozQtbJzieSByFhmBoG5r3eCyCVWop1 rb3MkvVXVpc9Xis4o4eF9WufXV9etjryUlZeUhmHLQuTabX7Ykm17Xv3yvs8DhZYenab3pc7tbsP js2zCGNrOVKO7DmTd2tFe7sr3evAzLzT1YQH08HVivmLUJjDbokOPBlmmYY0MLokJ0WGywa64cA9 zCebXgukPt+Wt2+zy/61/Sfpav5PcZh93zmPit7Rf5WnBvX/ADOhM+3h5mMolfxFP0+owoU9S4xg VWbix+UERznuB967lAXQyb7thYHLJFj8td7UJaf7/wD/AAeHW2LxNGNKUscv8xXivM68z1vUVuK0 OHhSSxRiuVq1TpcSHE655SSnXzMyGum+WY58SG4m4s5rCSXFoytdI4/LZcKEv+vr/kNY7YnEYGoo VscrtX0ot6XS9p0vgrv3HElcQYkEtFxxCnYjXRZptMizb4jDEe50K+65pvdnJsAJItkAsrMcsav5 iX/Wvj/KeU/J7jViPs/25b27vf6T4Xt7TjfmOXW3YkpFchShqcrFqGIYDAXU6bH1WDFLSzec0N3G us05WyGav+IZbdLzEnfomuf5Dx8NsNi8RTnVWNsoXvei1w42/wAzWxy6THxvF2hVeUlpww67AgxH 1GZiRGvbFhMDbusA7lQbQy3da4nJwGRKqx+W3cfMS0/3r+glXYnEU8NDEvHrdlZL/K1u+Z3qJL33 atwNVqdRmIlbm5WdjdczZjv5eYbFEVsV9yXO379tc53XvNm8XgqmZU40qMoy11ck191826rnpdrt isZl+Q1cfUxSnFbvq+bcXrKK477ta9+BRdpnRgQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBA EAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEBw4lMkIkwZiJKw3 xHO3iXC4vz20/wB814zwlFu9jzY5jiYx3VPTqL9YwCA0umHNvfdMxELe9a9rdCz9gw977pv/ABXF 8N/sXgVgU6RgR+WgysOG+9+1FgD3tFuOFpRe8kYqZhiakdyUtOo5a8g8IIAgCA5OGZ6aw3WIdXos XrWchtc1ry0RBZwIILXAtIseIOdjqAvnFsnlCd/M/il4n2+M8o20mMoujXxN4v8A2U1w96imKXPz dNkJ6Rk4oZLz7ob5prmNeYhYXFpu4Ej3btCL3zuotkcoX/k/il/USt5RtpK04VJ4nWN7epBWva/C PuRycPV6rYflHSlImzLS75gTESHybXNiP3HMs8OB3m7rnDcN2m97XVWyWULhR/FL+o4sXt/tDi57 9bEXaVvuwVtU9LR0d0tVr7zgNjRG0B1BBHsc6aE4YW6L8qGFgdve69ySLXt0XWVshk6VlR/FL4fz Hkf/ABK2m8/9o+0+vbdvuU+F78N23HrOdArdTgVynVuFHYJ+my8OWlIpgsPJQ4bNxg3SN0kNPuiC b53vmr6I5RdPzPD/AHS/qOCXlB2inRnQeI9Wbba3Yatu7/hvq+bhzcCZ+uVKerMSszcaFFqESXZL umDLww7dYGhpFm5PAa0b4s6wtdHsllDd3R/FL+oUvKBtFSoqjDE2im3bdhz3v/Dw1enD3HCq8zGq 1bma1PuEafmohixooaG7zjqd1tgPAF5WE2ey7B1lXo07SXPeT4q3O7cDx8ZtrnmNy95bXr3ouy3d 2C4NNaqN+KXOYl7o+VCAIAgCAIAgCAIAgP/Z --VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt Content-Type: image/jpeg; name="Car logo keychain.jpg" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Car logo keychain.jpg" Content-ID: <img2.jpg> Content-Description: Photo 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 --VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt Content-Type: image/jpeg; name="Carbon fiber BMW emblems.jpg" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Carbon fiber BMW emblems.jpg" Content-ID: <img3.jpg> Content-Description: Photo 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 bqJ7U99Um4O1Hfmg3GO0T+VVG6xzj8ofTQbo5j3EH20FgSrwoLIjJoWyGTSwsiMmlhZEZVQtkMmg siMmhbIZPjQEZPjQWGfOhbDIoLEFYHhQbpHaDxpYu6QXRSw3SC5Sxd0p7Q+NC7o5/OhbDmoLEFVU WHNQthzUFhzUFhzUFhzUFhzUFhzUFjx5qpssOagsOagsOagsOagsOagsOagsOagsOagsOagsOags OagsOagsOagsOagsOagsOagsOagsSHFDooj20sRxTK0yHR8rPrqbqMXSi+RWJau9INTcMXRXIrTK QeoIqbpi6LK0vIV0WKx3WYuDXIq5vOljGwKqCw5vOgsRzedC2HNQWHNVFhzUFiOali2KVcquoBoV XRQUAboUUmsrmW92jneT3BQpoN2LAkJ6Kyk0sOifIrDgPRWaWMXFonmpYbpHNUsN0c1LCxHNVsWw 5qWFiOfzoLDmpYWHNSxbEc1LCw5qWFiOahbDmoLDmqixHNQWHOfE1Buodofyj9NUbqJ7VXjQbiI7 U+NLDcHamli7iI7Q0sN1AuHxoN1FPOfGhd0cx8aFsRzUsLDm86Cw5vOqWw5vOgsRz0sLDmoLDmqC w5qCxBVVLYc1BYc1BYc1BYc1BYc1BYc1BYc1BY//2Q== --VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt Content-Type: image/jpeg; name="Car holder (9).png" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Car holder (9).png" Content-ID: <img4.jpg> Content-Description: Photo iVBORw0KGgoAAAANSUhEUgAAAxQAAAG5CAYAAAAXnnKIAAAgAElEQVR4nOy9d7Ss2VUfuM8XK917 370vdc4KrW7lgBIogBCIHAVjlgePPQOYtJZgbMMYsLxGi5lhxoANzNhrBmO88JCzhMgiC5E0AiS1 JFqhWx1euLHSl2f/9j7nS1V172vhP/vrrle3qr5w0g6/nY6p+KCnj6ePp4+nj6ePp4+nj6ePp4+n j6ePp49P4Qjwz6te/bL6C+CLsizl3WENr+S/jSHDL3wlv5Env+E7MiV5nmd/12tMpZ/x8uQp+rdv 9HuPv3S/x0Go13r8mXzyfb++nzy/av42XoN/3PVlmfPziK/kv/m03KB9eCK3q9LziqKQfvH/co7r Z1nw5yqx/aW6/VVl5HccpRsL7qe2o7LX6z08frIeZev6Ss6T9gcBn2NoEIV0cWtCt1/YoTt3z9Gd 53fo8rlt2t3epWg7ptFkRMNBRLEX8VgMiYYTMls7RPw7xUOqQnyPXnLbKu2Ikc/6pAJTwe8+mlq5 FqH/VTNXrXl2bS15rKW1/E9RNPNfz5+be7lH8/LcPGyApA6qlmb97+4IaPUG7bXELanvJV1oPRDn FMZrjXm3nziKqmnLahvPxtMV1re9pxs3t67wyrCINtxTzinM2u/du8/Nj338nXNfE25vzs/jF6Xc +IQn9Jiqcs4nTPl3fsd6XU7JWy7JZBlRmlOR55QkCWX8Ockzyvkz/pZ1n+XSxjwvqcDccnOrvOB7 yeIHgWmfLI2C9nhZCR363Dh8Dox+p787mqrkOWVaUsb3S7kdWZFTnpXyXLxw3xxrlR+V8znT+ZKO jpe0f5zSlWspXd9f0pWjKR2deDRdGuI7CD2XFTMN4/PayfnZAx4pHg9e2GHg0fbQpwfuO0ef9/pn 0GtfcR8N772HB3CHz5jw88YUmsAOckl5uaTAAxXwOKEdVaYvU+g6MvhuiYUv48iDx6dmMj4YtxLj t0T/iJY8fssspSRb8q34+7TgMc/4tyXNZxlN+TWfp9y/GR0d4rWk2XFCsyW/FjntH/LruKBZ4gt/ CZg6fcxxEDNfJAr5H48szxOa1HXtB7rGch7vDGNeyXDyGPEcVGB4laVfzGjVWv9G1mnhra47XY+6 bgPPb9aqe3ltugDf84W/4r1wdGbXhilKisfMu5hXbe1eoPMXLtPe+Yt0Ye8i7ezs8NQwf4siCsOw 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 --VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt Content-Type: image/jpeg; name="Car holder (8).png" Content-Transfer-Encoding: base64 Content-Disposition: attachment; filename="Car holder (8).png" Content-ID: <img5.jpg> Content-Description: Photo iVBORw0KGgoAAAANSUhEUgAAAnEAAAEUCAYAAABEXGBMAAAgAElEQVR4nIS9Sa8tS5YmtMzcd3e6 2717XxvvxcuIyMiiMpNIJZQKCSWMkBBMmDHlN/BbkErMQGKAVAOQYIRQwQiKTCBFVqlERGZkNBkR +dp777nn7M7dzbBvNWbL/ZxX7Bcnzrl7+3a3dq1vfaux8NFHH+QQAsXYE37nnCmlVP7uynuRKGaa ponylPjfp9OJtutNu24l35mGkbpuxdfg/RyIpjFT34XyfkfjOPJ1+Nte/H0q99X3ppzkmhD5d8bn pV144b747vF45N92r5wnbrf8Hbit+NntLmkYBkIX8Lk9H793u11tJ/6Nz63v+MEL769Wq/rb2oAX 7uu/Y9fhufjb2rDZbPh9+x6uXa/X/BvjiL9xnb3s2XZvGyP0se9793lXvpf5mmka+DNcdz6f+Vm4 r7Wz69fyXZrqGHB7cpRn6PgtX7gffvqV9AGvVY81knkt2H2moG3KrQ/4Xuy72v80yjPwPb62k7Gn GGjV9TynGDe00/qPtsvYdvw337Oshbq+so3PSNvtlscT37OxwHV49ma1lnaWccY1eNn6wXvlTnR5 eSnrbzEX/KzSdvy2sbe/bT2mMq5yr8ztxNijDefzqP0Z67NszdpcyvqUv2Uup9natnnhdpY+2d6x v3ndnYfZOsbzre92XzwPz8J7+NzvR8xB2z+yPzA/3Dfc93iW58a2P3gug7SjrKJ6ra1/PB/Pw8vm VOZMvmtz6F/4Lt7H9WgDvs/7Lsr1ttdsTGydQRZhXu3fNve+7/htn/m5t3bb/rY1h/etjbZ3rb3Y YzbO9lx7Bq41GYk1hXXt1yT6hXtbG/DCtXi+/ds+s7biN9qFe/h+eZl4OBxm68W+g31hexev/X7P 79m1vL91bdjz7JnWX3zf5tDWlfXH2mt9s2tsvuwzew/Psf5CNtj9bYyX+8+vGb8+8Xz8G/eDLMec +PbhPnaN7Tu/vpqOa2vf5h7jY/Ns+xxzbWvS1gbLNe2b3Wu5zk0H1D2jz7X1gmfYPU1H4TN7nq1N +z6ut2v8PsIzTJ/YdbbHrR1+Tmwuqi7Q8V7uT5sbu87kqF9rXmeZDPDr2L7r96DfK7aO/H1sDkWP xdoHG28bS5EvcTaf1l773L/sWfbspWy1vWzrx142jiaT8JnhEGsz3rf97p9h62/Zf7vO9pzNm8kf +55dY/+279tcs3yxDgjYsUFtA1EwXFXCuA4LZnICe9SbQ6myIk9NOfKC7da1o36Q7T1Kkb+L68dR BTt0Bv4r7cH97Xv+Pm1hDxXAeaUnwAeLFYsO/eJv83X2g8/K1fw++s7NSbbpB/6+TaotKttky0lZ bgJ8HwCjLyDKFg9jJn62ADHut256L6zmAiHwfMgN5No0JR4rWzzWxhjbwjMBDyCc08jz2wFY499T YsCNfqeMRTxf8LIApR+93qO0pnxHxmlkgK0AQNuJuep0/eA/E7g838GEnS5CfQa6ZuAr6DqzjYQx xqaw8UETMKdtDTRBP00NiNo41o1e2jiWOR2nkYGlCYkKilQooR0CqprAYcXZy0Ydh1HHFOtS7p90 3qSNya0H7CcDkqm22Qsu+1mvm9DwIMC3w75rwsyEiq0PPA/zM02JGjaSORxTAVNJ9iMDsTJMPB66 zouqK2timq09W69eAbMg0T7iHjaHmHOv0Ayc2r+xD7yQlm+SMz6oCiobJxNaBq6STD512hZeW2U+ IWu8PDGF5wW+CWF73xSarfOlYM1uTuuziaqyNQXq22tz4xW6rUmb28fmn8dv1fO42vUA0BgijPGg ffSgxOSbNz498KuCvcqEONuL9pzHwLVXxEu5ZmPsx8crP5vD5XX+WtvbzRBrc2Uvr3x9/2wefXsN 8Hsg3eRXrPd/7OUVujdC7H3/PS+jmzxKs+dYe5dr4jHZ5MfT9pxfH34c7Fpv/C2BjB97yExvZNpe qvJsAXLsMz+mjxmsM5m6WAfeMPL7ytbtElT56wwQW799XwQw8oiy7IeM1ZVR/8Z0LfXvct6Xe8/j BL/OfDvtPQ+aDVx6MG5jYWNoINnL0SVY9mvVr8Ul4LUxsv2OextB49sWl43wL9n8AuoARpj9AWMH sAAQUt5XW3y2AAFeMOipKG8IIvz4zjMrUMAX2DsDezzp+NwPani4iaxjbVN0JMxUYzrkOdIGQ7d+ 0dnC9Wj3scXKAx67yjzNFmrfVZbANqptGChUE6J+Q9pk2CT4yVv+1PnIsYK9aiEHAVXSZrt/27QG wm1fYLy5jTHzj5+rx+bfb2owSSHM++FBtXwhV5aNr9F/m/UKwBCyA/Ikc2tKFZ+xUkI7ym8Gdpl0 jqRvS0YEjKCxrF55+TFfzrcHKh40+01izzBL1I+J/3lMmdnGMmXD7QCw5f7G+je6hJ/Q9bz+eSyK UIJCZ4YLBg1AlrJdfsP7vvH4AqDh+8y1tp8RgEu/71k566sXLHUenCJvbEys68m/bPx5/+oP9gMD PXLgWcfCKz8bTy+gbOywX30bbTyxjoxNtH3rx+Expbqca7z83HhjySvw5b39PNvaN2EN4OhlxhIs +bVjssu3ySs53xf/9xJgWXuMybH72ecevPnng7UyeWD9X867Zw7w8sDYxtQb1G09PDRAbey8fPFA 355lc2rj4+9XjVFtgycCluO1bL/9nuumNtd2T5szXAtW09hWu+dyzXm9sdybHpB5NseDDGuDtcv6 6EHWEtj6vizH3RspJseW1/h1t7z/kox4bL0uX0udYWPk19Ky/csxW+4xvLwu9XLD98H/LF+PAbLH gKfNq18fHgB6ueXXm33fP9v2nD3f7uH1xHI+PCB+bN16+WzfMUOuGfBq4PmHCkukrJo+FAvaXDD3 +31lo0IBMedJXI1g6yiXRQjGK5cNMYkblgcom2BtAoAnOKlSwYDgeyTAiAezACd8IY9p1llbVH6h r9dbZS8OtaOsXFKjuu17fhIMDTNThUHCRsKz3furvrm6uthVipoXWqdCMotr1AZY0HGsTJJvu42z sWd+w3lh7SdOrA6xOKAq66bvS7uoCSbMmVcIYBShYgNczCMUPSa7Z3AErCIu6wZcPIidbXAsTowB CTuZswANwhhx63TNSEMYiPGYkfSlKgx165rwGlNze6BN2Smek1LVPCYR49oz+KwbI4gLnsdhMlq9 r5vBCxkT0HZvtMkYHuuzbWYoOQMKtu6MQvfWG96397wyjnGsoKMKLFqRsbvcBmrGh6yXU517D/zN FTPRXDH4drMiB0OMtQiWDXMBIKUgDmvCK3Pf/uq2UXdsFXTBrVU8pwqk3D7T/7f+LxkE21tw3/Wx sRM2hr4/pqAtJMFb9kvL2V6eRfJzbIDDvoN/+7+98FuO42MKxl+zFPKe0fLCml34Zd48sLf3H+s/ ZJ7vo1da/F5uYNTPne0PryC8QYJr/J4wEDeqkeSfuWS6/Hya29jcaI8xBTZWHtB6d93SRWv98K5/ u9fcQG+y38bcz6MH3dbH6obX9zerbR073luJI0iKzIks08FUm5cF193f3/P34Va1PnjQ49fLY2DB j6ufZ284eCPDGwaPrwEbO/PiBP5bPsNYPQQjmGeTXcaKLxkxz9LZmC/XmQdNXieYkYJrvOHr96bv jwcty/f8HrNne5xg7fXs+fLldbu/v/XJy7+lnrX2z3VnA1X2Y0aHhYvY6zEDxYeO+XZ5OWbPWM6L Xx9L5nwW8qLzzXs9pxX94Acf0fc//VBYj7xiBTCFAkD6M10Ngf7NDz6gH7z3hC6eXNLqyQ2tNlvq 1h2tt0Xp7LbMuJ2HQwFdBcyAbRjKvwHA4qqABXFJWWfhxoOLtY8as4CGMfsQxd1Tfk/KTrAwyLYp dKAAqPBfeQ4AYkhDXdgxySKfHLuXExxGkAInZtXGM9i5I/UbcfUgWuxuf6TSZDqW7x9PFhO0KhN3 ov3doXx+oMMw0qF897b8fX840lffvKbf/e53TIrttpsiuFfsGiv4jUHcFgpY3SF1sbnFZe9XAZFG jStLlZ1kViUB0Ozo7V3pZ5mrWMDYzfZMz56c6L3nHf3w/af06uULOu5v6dtvv6XUX9DXd4l+/dWe BtoywL47FAEW13RfwNxt+ft8XNF0KMogA4h/SWNfNvpYLPryvW2+4rENw2u6oANdXuxo11/S0+v3 aLMta+DF+zSVeV8/XdOrj1/Ryw+f09XFFT25vqGL9UYESYeOjDSMxQAoAGwoc7Tf35UpOLJ7dttv y9oqCqbMx6qAu4ixOJV+F0Bx++6+rKVjueclC9bt+pK6VWnPSlirczKhE9nA2JdnnEdxtxZki8Gn +zKHb98eCggpwnwsfUxgtuAW7ujtWOZ6cy7Qak/PN4Furge6LuBrE+6LUB9oXaZnNxTBOZX7lPYc Cmh9XaR+d/GU/ul//d/Tn/+v/yddXz/heUIQQOksKwoAlt31U/oP/sP/mFYqRKEsujC3LmUDN8vq cNoroOpxK14X4yAMJNbA6XwvAkDjAQ1IcfwpxrD0Z7PZ1XXEMXbTWIW3j2Xzws1eYTJBZcy3Cmt1 3WPM+J9ZGGAWtp0CGrC/Q6p/g/mLPdrVBH804Q5mInaVHbZ2bOB67rs6NqQu26jxsUOaZgrK9sxM iK02tC3rFOslxdCMTMQABnOVCVAAyIWhacZYUuHbd60NMbc2ok99aC5QD8wIcoLmrIJX1qyURgEr DKpJQUgSQczhB90ckNi9YtZ7xrkRu5xDr0TI2uXGx4S+galp8awY5u7KKTU3NIObfjMDqb6P3JbO FL1zQ1FjWy0GeDoLILrY7uiLL76g//Kf/BMxhKdUAbwpqmORsdgL//Df+AP67PNPazu2ZV+ty/d7 gL+yzni9LVi2MuC69xIbhpARR/5R5q+MJ2QSg5gQq1KOubnteXwdwDAA6Bm/asxrn3MNQZrY8BWD N3OICCt1zH1Ud3j516rfMNjfXWwqA2f73OYO728ub1g2MHmyXrUQg6Cgi411GMUK/oLEJ3tWjtdz EOKkU+MaTRFjuq2hJaPJ7Z6G2Wfm3q/GKsX6N7k1UsG3freOCUI+yv4j9W5hX0SO790UXLEusr7g g6JHGFQDNyRlZmFEZpNJqRrbwyhzbIaGGSH4Psaq2zQPle2pWX80/tdi7/0aF7zR9PQSiPH3xwa6 uZ3xIRjz4HxiU7vlBcTYzZ7rv8vPL1gCTWBcASKp/GNV8BOMjF3BYZc310V29aEGmk5AMmHNwIZB Vbn4yXaiF08v6ZMP36OnL58U5f2EtldFmV9d0uZ6R2l1XZQlNv9J4ovQr0ECvcu/2A3LFiGpb1// zeAOC7aTjgl4U3bHrHSg8RxndCUC4VmoQnEXYJWjWu1Yvc71CDewgCMMULluOLMCQR+Hqfy9hrvn VL43MjA7lU1+LAtiD2EDgFiEPy+Ow5ne3e/p7niitwXsdW9uyxDdF0B3ouu7a16MCGLelI3GQK6P HDu2ZlYg1YB/7pNNfPICkXecLGwGdkliZMgm9UIERBh4LDf9RK+eJvrse2v69HuX9NmzmzJOcJPe lIX9fmlXLmB0Xdqa6Zs3d/T6m30BalRAaCzg7lR+r+nN7VTePwPXFsx+CWhU/ihjgXU89SwFQgEJ qzKZK4CaAqCuipLcFGB1/eSawpMLunn/hj789IMiZD8un13T0ydlTRQwwcp6hTEAAB15rk4F3N/d 3dJ4uueFuC2gh6AcAOLKQy/L3wVp0dvXbxiIYq5vbm4KgFvT+mLHwqvfFINB3Y6mYLBxz2XODycI k57dk1MZ59fv9qXvYGbLMwDiIIgT4iMzfXu8ZxC3WZ/og8sVPb88000sFlFC20balg19UcYPUvK2 zPG3h0Q3WL3ba3r24oUoZACLEYkeWQK0k1hy2Fiv3n+Prp485fUHgyF0DwUA/5uMdc4qZEQR8kYf 2vo9lzHjtULNKiYGKspsgtGA9av7xF5TEoHJiShOcHkrn4VXpro3JYhYKX5ShTSKAQUXuIE4Y8zR ppiMvRMjDOumtwQY7HcFsCu4i6L00+zYXN7fmEJlKzMJM45kGzVyxjwHRUtLlVm89baCuCLRhJFj 124W133OlQ3l55bdZSyFgZbexbuJB0HdjZSrkjdr2xRxBTILltTaxkboeaoJTNjjVQlrjKW5vJcg 7v/vb/+S9dGEP7MN1FgLs9yZ+VmwRQbijG1Ijs2oRsECwHllMzcKNGQhtnbx3MeujhHkNz4WfTNP mrBnsMLt5Jrnz5/zOsYYXlxe02a3LUDugmUCZL+BEmnbWL08WYEGZASDuONZ9q0aTytdd2Ct+L0w Z6ytXwbW7MdA3QPGPRhLVq7nz841pGQs+iaktnZ4jEr7t5sLBnHm3RIPy7oCbqyVXTGQ16XPGAsD crK2GnvFIA46Y8wsHw3E2ZrqbO+qwdExY5/rd22uvIyoIAmelGnuguY+6edJ/21hEAay7DVa6JKO CUAtZJOBON5fCuLWW/yUvu4uxNhByFJuIEe+k2Ygbq/ub4tptvWDscKY9du+hT/o9HqwGlSWUZi7 oOuezI2RW655Xt/TnN3HOM+AXponYmXHUHom87sNbfU0KYjb9Cvu2+XFBeubm6J3e15suXUKQfAc dI9FCSu99Hw4lYE/l8aeMp3uoPCPpeMFXJTdOoRBg6TBhJUnDbA+YBABJBXLdY1NU+7VqVULK73n kPrynIF5J2IkHNgqRafhkoMFX5ZmETLI1Jl48vFal+8DjU5D2Uinsjm6jY6dbuRRqdBR+oPsxok3 4lCFFfRSKAJkYF59KIoSAK4AnNOR3u3vCY8KYcVgFC5RMHUAce/2+wLo7gsgeUeH8j4HjetzLOhb EhZEabCQBrCFADNBM04zod0jnq8CO0sIkVhBvAB49qVdXfnsyS7Q9dWKPnhvog9fdfTyKYTsG7Ya EcS+2pRFVYDFZQFQL5729PGLDf3u4ky37w6U+yt6ddfRb78uiqsA0/FiRd+cRmb5UoIy6dhNye7R BAajZ3fyKhzL744ZJbRvKOMUBtDeOwbHp+MdZyAfj+JWh3Xbj8TKGqYAmJTj+UB3t2/KOB9oU5TC VAyDsCobrhgJqYCv1aqMxbnMx2Ff1tqBJK2FNHN1X4BAEbgZmzqwwWDC9VjGBVwq5gvPAmgsWLAA 8nNp5yjxZ2NfQJywX2XKC6AtfWeruFzfsR0pom0itkqR6zLypkrM2J5TRyeMC+I6s1i6EQuYQY4m Y4BNQHzbIEIPa8ZAWJocfZ+9i2HiZ7JbvfQJwqAK0sHi6ogbxRs8tPtw8DudBeyU9X8axHVO0zxI f0QMK7W4JM8oVKofjchNgWV10VSlrUlNHNOo8ZRdMOBQ9lKUPZswjrnjcQVrF4wNR0IJyZ7GAkGf eosFCh5gqaJQyz+ooeMDreW1CCQHo9CtmoshNAYt8xhYSIaLgQ2iBCD8zXIndcUuY4BsrPjJWV0c NHevLV3WNtb8/YlqXCgHZ5OkdrBrJrvsSWpCPHlg4ACXB1Oz9/S5Hnx5IOfdL3bv6h7W9xjEAZSk hWuX5kpsqWj8+/IM5KrZGCYGcGNqMZm5bxUIUkiz/hhAEBZX5OegGcDYbwAwbHj0J/XUjMTKhJ/U 4mtl3Y4cKsBA3eIpFcRlBfd4Ya/yGDklX/vPE5VmLmlj4QzceSPDgMbIzzurbFCwg+QykwMwXnD/ DjGNcb7mAHSUFUJfLdMUBi+8Vh0s2bLo84xhT2z/gxBAkhIlxzZhXNh7JeEWPLYyYNru9GDdWP98 fO8stnWcWthJ0Q0YA47BdWPk1wXGia8vYwLg7kEcEH8wwxJJYyB4zhKCE7GHYnONm1zA2sBanVzb bD9XI8CA2wB81pGEg8wTdfie6kmATOfnu7AJ7sc0N16WhktwY61vzK/J3ez7OTSDhddVN4/htr1p LzEeEd9c5q2fqjGA/nejuMl7KEWxujXIdRLAhUUOxd6FqwLgLmk47gpouipjvimC+5KmzTUd++uy sTpIKdkSUAYnSC3uTRkgcGvbovx6HowEs51WcMJIw8tCPPM+7BkQlh7JzkE5E3btTkrNlwFOCsDO EmeH61Iq7x+yjZ0oqRFWWGCFgoE8HbHA8bytAEksaiQDlGecyyAexwNbSnD5nc97Oh7AsmGhIZ5G LOm7AuzA1r0tAO7Nu3fMzO0Pd/y9GFYPBJptCKHsXSyQfizMoV4HIY7J5AxCDfTNLcgRIAZT+hzs 1/WugKt3BeAeaVdA9Eb8szyOozIOzKIhLrHM5/Wq/Hz+hN6+A8B7QvdlDm9+/bZYLV8UwDoJXV3m I3DW4rrM06mM36n0KbHAASC6XkV2D3OYYhRQj2cgJg9TBg+meDHlOlnAdRiq2yJydmwB9CtlnaAY 4S7oNgrIW5wONmmlxrtW+oaqkJWgetxnfzzzBmSXftnEZxgBpV/9BmVHxDXJKzxzlB6zhGXK6j0Z QMPlhv6L5sdq4zYcynffFcB7T1A6a3HtK/1eFii76NJkJSe2VQkhPjMpO+dj8sQFa6yN7gHMeaLK 9NCM9Zj4R9iNFo+UQxNqMIosriUEqsoPc8QADT/QG5r4snxl2zxBWQKNwXzIugj8mAkwbou2R2Pm mjAKrEws5rHF1zwM0hV9n3mv87rP8zY3Rd+sVu+2NKEoSlziCsW16zM0Pdv10PX5YFxsDrLEBeI1 5jxzyZAaZ0nZh8fAlri6jBVpz5R9ntp8U3sef08zv21NmHvagx57r77M9ZravZbtSe67Nqb6CFLi YTY+OcxLwTx05ZrMs9+du78zDhzwNFbQrzGv2PAypYxo6am6tMQVBxCR4qBssOzhquTZ4Jg4pCCl lpTCawp7CQApPQJKU64uVLyUQBHAjp9ANYGIxUTUKgeWHemHgGjmgWF55e4dFezOnu91CMcLhwbE dTxBXjSDkMS1yUatJE1VI2ABoqxpvCdMB1lzcotfZsiXU01OSr5Dbv4RssDCP0fH4lMdoxTcUCS/ F9pzMX5Bshhr/6oRy4yqyiptcF64dM14YcOyo5q0l3Vfikybr13fjtqflCXm5ZF+Cgaax9g99prv p6WMbNdYf7it3PaHoNLfx+Qo4tq5t7D7w8RezjHLOHMYAhiqSr1yFHUCzi+D3PMNhjKY94dAbw8d 7YYNXeyuS59vygMKkBsv1D0pyq+DS6cozsjMSBTgRmyaFeAkbEIGUOMESut4edqoLlC4gFJgN2qP oGxXYqQjrV2jHqOgpTfiMJlRIYxSEsHZIdYm9DUWBW7jiS3zE7t+wSiBqTiwX19YHJOHAIJg5cDc HE5DAW139O3tLb1+d0e3d/cc/GpZTH3QkhXsDp1ko3E5Don36L2V7hZ0Ts0ilckN2idhemwiO60R dwGquVy6Lve72uzoyeUV7VaBAcqxgM7VGtTxWgAwQFbp96m0k/o9Xd8gJmegXQFsn3/2jN7s7+h3 r79h1zkETEiRhVuxZ1ggroqFOwLElXndwx1UEP+amQMVBDUWhZg5gcDMgJFM0ZMuPAFdsTMhRhLz RabEyvsYn91KlAgz2mXOV4hHE3AA0BRJP+d0TlLBIuU0OOaMgSyJN8/cFdh+XVkrDPa60h9ztWfu Q4Ywh4AE6MdYF8MEz6VxxWuANwisHaDTspiZ7t+sab3pm8sNcZllTZ2HiRNwYizgdyWgS9YimAAJ Euic8IRxIdhbFfJZl4YHAMj0HVN1Yzwo3ZAymc8qlRugTExMvQKyUbzyk8SBdXX9pcoEeoWZSNhj A1eizF22ZhKhQ3meXGGMQmCDauKFodhRQBuvdZkc7HsOWXSCTxiwwPuV9wAr2ZGVNrlEAhOHxvJQ aEkPPB6xKS4TfCbgzfJdClqVpcJOKDBj24SB6DyT7DGmrY6DA1KNiWrXy48P6J4rAn7fnpNlDUTb IYqD5wL9X/9aAgLf3sYMzO/jk3iW96og1rETvj3L51nfY/Tj0rLCec1GMcv53kWYc0b24tl87dBY HL6281nOZb3nVn6Gwa4CteDGWL4/0KTsLi8fLakEkCSGYCfzHhfjW8cw1R8pcSS/5z+xggthmJRd YQNNYsUMxFfwrTFi/Rg5hIUJCW/wW8yt/lisFa/6YCBt7sqO7MmSkk5+bmQfOZAY5y5BP9/2HZ+Q QmTfiTLOkK9ZfpgNU8Dnk6IMjIOcyOZSXTB1/LxR40yjyZF5yMfkgFt9P7fvJ/XSmUdEEhWDxkTO k1/879nfOde9Vq+bLK7T9jHV8W5fg+xSFy/miReiGEWV3SStRhFJdb5glAfG8He0jxM/M3GCWAO5 anyqnOmlwRbDBuVvG0eA2FAU076gv7flvcuM+Lk1TWUzInEhn07UpQIQJi1rURQuTVmpy46ZbvbR p44/LctWSohYsGJpxKZpMUms0PetYz1tq2LrmU3RgrvYiHBlamYel2XogiYDqCWUJREBm4oDbDmT 51x+H0u7jpo0AMpYqN6BA1XXvGiPp/sC3k70roC5N2/f0dev39Cb27e0vz/WIEq81hvLMLLSHgJo 2T2MhRtCzdhsy8AsOQ38tIKwVkMu677B1ltpBhLYwqGjm+s1XV+uabu5LouigFHEna0QC1R+4o7n B2ONZ16un9PheE95PdBwKv2OK7q67OkPfvyCbs8d3R1u6Zs39wVsgJ7t4QmH9qWEaYQjriy4oQDG cb2jod9wwD4hBkzZKMTLrXu4PQP/MBOXJeFEQENihg3uBdsU5saQkiOR9vsjrRkQRHa9cqkNsHer niyDkwx4dGKN8PqaNEEAZWTA+PZSww0bfDgXKx7la1KugccAkYn9pUU79HAjaw3DjIK96i7uBCQO o1i4o6JDZniHlkLPQC6Kq3K7XZFlWvcWJB1knhPXQusE0NaNO7WMaGZxGrhghtrmX1++TIFnjjqt y4f+itKUa9iNXd1pTQnKGLRyBhYLcx5Pqnj7ygIYK8a7KjRlYUCPyyGUsQMrCbexxXn0XV8ZtqoT uZi0gsSOI9RUuY5VwWt6MoN6jJkAgE6zs3d/B3oAACAASURBVFpCAjKjYzT3oWZJZnGNdtQyTX02 qRlJnnEB6JVMRV0fympgJ4ItptiE8NJ1EpRpMEW3ZN+WTBWRA46LJAVh2VrJEJ5jx2ywOWJGHjXG x9aOAWkDrJ798bLGg+8lO+fj4/gezaZUpWQsrASWk7uzDx9p/cZ7ff3brsP8caYzibsLRpF9Zln9 PgPRYsQYGOH+aTFupO5tNeyCW6c6WeRdW12wcaPZBotV+ZqiJnHxZfUBRamcELLIVA4RMuYtyC6R OK05KLfEvAXvI3p1wbxIX+Zmjndx+rlit2xucYpBWWbbz8sXx8OxLpf1kXVosq7xkK378rnEvjZr bPJuWAeIlqxWNZLcHHmGzsbE98WMyzkLZ7Hs0K+9A1NTc6favd13vsuAId2zdcoX4NUYN1kLoX5n 2QffR//95XNDlZWPG17Z16WlzhmZsbLy5Pc5r8UsdVgjKaNr4F4Y6x6ZDlwJPyCwV5bRREqvl24d y4zfly++Lm/uitUANmedhWXCU9I5cYBpUsoPMV6pExKan5rMao96U2ESxBUjFn5UyrCbbMILSIRy LhO3kvSPusFscIaiPBALJLF2ia89IWZrAjOYmc3Bfd6e9rzw1+eVxMmNqBgOqnBf7nUsy0TcqRPi Y6CsS9vOh7GAizPd3+/L988cKP/1N6/p9dtbjqGAQmd0DHdg3NApnmm9EpfwFDWwV8GGrwtXt5lb JGDu1NZpE52E4cCCOBcQdHUpQYx9EEvwPA56X6nLdVFAFmLLwIqye4fWXJYDQbsXN5FO4Rvqzvui sXt6++Zbevl8Sz/+vRv6u1/f0907uKAPBZhuZM56xDkxr1YEVk/3ZezXRaEiHBkZxQj8R2OhHDer FQfV90pHs/VDbHLoPE+c9QqXJvdVXYkdxx8UwIMsZcTQMXM2ctZYzzUIZe5kE026qDPHPSYtTcJI fZL+RhVAXWyKBCwZ8pKRzCCGxCgKCeFPHGCf+NlSpI1UgQslw5asugfX/QoxB1WAtDUIwFHWYT7x qRCwOMGSpmIkjOeet3IfWyA5HiJKqjEzDDZWvW7qTgQAf9az0oEuTJNlRrYaTCIsJb4qK9ipp2GQ GAatdpSL3ep8vEVzp7FAUanBRkXWOnJ4yxix2mZXVwnPDfa+ZJlyeSA1UIjHQN2pFXrp0xU4QZlg bjuO65laFhpJ7GqsMUeQK2oshcYKsvuHddicPeM4GFsN7GWQTELMB/avjVdPqsiSsndINMm0iDmi qjykD6Eqadyzi60cQprmJ6AEB9yWhlxHjZWqn6lyMjmR40Ip0cMyC0J+L9w5ubXX1qz/be1hAOTW tf8c+2MMD125vtCxvWSNSyJESq2cCseOwbzvhaGzWoKcWX5/XxOCJDSglY6pbDEzPWWsUmNWjNVh ORrjjAGS31NlcNjTIBNMstKIrTVx2XcKFuQ+rTMy7pAt0+QB1MMfmy+5fea901yCLct8CTQka3MO amKRlVPXGDkuQaFzZIwfkgWNFMDdmAlKwnhVEsG9OG6WHxsr+BdjTZlkehyoBLfHWBZM4lqs69yt h8fG57ve5zFJEj8nOoHTjErfI8f8sefB5heES2hlgzg+kaamW9K06GszSmZz5Ne+QI4H3zFQFHWc GnPon9HY9ApQF0yfsa11TwfR5/Ic0nUmccTZsZd+/O1+9n2bx5Ra3CiHGwwohr+RExtk0Fvmmwg0 oWBTUbQoT3GYVnQ7RLo+F6VbVsVmLAALDDkLLXFl8mSzUE4SrM1aqO4Mtc4NRRO78M7dVkpMDCpc i+CYcNJCQUInxLad3qni1/IMObC7S4oII/utY7fbKZ1LGwc6slsWD+oZ6b5NZw5s7bBBEDBZvncB MqkAuBjOFIZbQcCjPJ9drPuBTsczA8V9AXEoKYIyI/hB0Dmu7zmzshP3G/zSnZS9kBGPomyy5t2a m8EmJ4qgYCWUxtlm4HlIutIATNbab/WHjwwMMx2HAhwLiO1XuYDNW9peXNNms+V52Fxc0OXFswJy JV5id1VmcyjC9VCAxNszu2iRcfqqgLnffdnTl3dHqe/HwhlCtgBoxAyCoSrzD7ci1gEhtb/bEAKK OY27t/R4x7CFUAPAhcs51QwyY9S8gFhhk4LZLHODEQKQ4/rSyWpMmalia0iFcScuTSS9SIxaZEaV j0IiqWuIhRJXyI6VTDGsCICmuIXiNSEcleYeJc4P2dpg38ra3JT7HA8HVkyrflXBEhdYjQJyptyK 6PqXWMDpoXKtG14FNamlSFRPQjDXRQQ1mE0AGJtj8XWWhShzZrQ/CxC4UodJLVBxKfecjSfMjiQ4 WC2jnuPtGMYa06eyg/FS7Np7C+Fu8ynt7STOUZkLM33XOmasDMU8JJGlpiDwFWH82KVISW09VXqR lGkaWfGkIIlXIbpTJHKqZYy8orSQBWZQTZg7hRB1XRkTAS8Cx/h1opSrYHbFvquwTQL4Zs9bMCxm 5U9OwBtbswRiD6x2ne/UBGh9zmMvJc3sZjOFtvzOElQyL2xMcWWG7HO9VhWvfKguYx4a6/NUdUgM 8xMFTPHkR55vRi5etfZdZV9UkRJVwGNj0AWXEFDZDGMpQjUymFRSXiOYAs8CeCQsY6pjZkyS3MeY sIfM02wdVMokzdABr7sKJCRL0zER7FXygLTGhy7mVeKkLVZaSvbw97IAU3i52ItmunWW+BNlTcsj dX/lug+0N7M+eRll4MbcxpSWbuRFUL5jSz0Qneu3OfCLgWbxbpZ120quKK7A9uQ4LZlvL4e8TnnA hE+SFPDYPlhe+9gYLOfb963KW7ffA8XFZ8JqChhUuR5aOZMQ5/fw7ZFwFzPGMq8ZjicnNTpVLvUs gOFKAS3OhIFkAE4Z2QknWqVr2hewc9vd03a8p6/vNgVcXdJVUYS7e1hY5Y9ji/0QgwDUX1F6zOBk LjZr9bLMyuLYCCiaac81r/jILzwR2YNYeMipjSh+IQwHgoNPsG40BqorE7ounTiWvw+oxYPsRSpt 4XpAyPoINEA5FPCy7tcc7zX253LPsTR3YPDJVt5J6weNkjVzPo20PxYwcCj3vhvo6/1bujsfaQ/L 8XjgTctFRBEPBf22OpSfNZf5uEctjyDpvxO75YaygAZxfWnGDC9GFRw8GcyYCC3PcVvoHxfyHVix gRUAmwUgue4TrREHl+Sctqc3W878AhMW0knO+exQ5mNdvn/k9zdxx6UuVgjUP35NO47Vi3RVANl7 z090czXR9gui21MZ820BZ6tyP8SjpALcUdJkU1pS+jduL2gIGzqW9r54dkHddlX+PTLz1JfPVgoY EgMXjc/iuEbJOByPJ65pFDYXrHAh1PqVWKygLic90WBVEFbUUhYTMh1HARNxFHc8ACYA5yT+Zg6y Hdk9duDFvtkWEHhOdFeA6bEYHVf9FcdhpvJMzOEAsLYv910XoYhxRikQxOEx+MTzBGBhomKSul4d AeTi+Kpyj/szvfeyjAVibZBsw/E2fTsHMa4YUPWdAbBWDZ6ZF9w6Wm3ELLUOWTAIs92EJ15C6XZ8 /vB6trlDFlYsMBgVgMS2nYJf1KGa1MDqJPJX9lU+k53kJsJxELCngkRcpZsHgo0ssYLrc605gQQb NsXeAUuqlqu9JySZju0k8TMAygz4yrytEC93niQ+KUqWuubH1mdHPh1GmWteVhN/d+JyBVowOsk6 C8XYnKz0g+43xK0iLIFZ3DSKYRDk/MhBzxvukImNuS6gFlb+JNpbrHozbtFlFzOXtA6dvWrplCzz wKxfZ9lvCwXiEkHYYPGxXKQ2XKAZS8afcYhGUybk7mvPCBqbxXGRYc7CeQXEc1ZDZ4jd2RWY2/W5 lbPwsYFiiEcG4MMgWa1sOGUJzamgWd36DKCglMZ5tivXhdMMUQtXgDyAhwev85gWgNe8OIkT1LiA OUnCgbhsza2lCQG5JdUkrZXG/UJ7kbnca6BPVleYZZAruyvEApE/NYdZFM7IVle9+CvBHUvf1JvU vjOSps3qyo4sT3JuruiqyKdR9LEDUcln9zodizZMCui4qHsmBVcOgGuJDubcos5D1oQnm/cZeJA9 LGeSZ41T9QyeJHSIAMHf7RzxurY9Y6e4YFaSh9eoGFYqLUiYptTGjOFQFMYUABZyIigLDlyU5rUj /bNn/YkSY/9dxk8FT0GezYlQWbPCHYD/ru9ahn3dE9QyzWUtWMyceZNyDddAP1biimAZ0xhlISq6 IMZ5UKMWCT7IH4hFQVstXTy/F3BBUrYja6xOFjcGDwD7WBCkfaLD4Z7uN1uhxcEKhS2twUpkMXEE GUp8GpQZwNlmHQuuChxszwNmllt1y2QJ9rb6bmzQiIsEU7m9WHEZCMR00Yhq3HqGIFyaZcCfFOF8 ve14MZwKyNqjaj4zc0hOONO2dHI4FuBWwMYOXe8m3kDnw55O50MBF0dmgUIBahOYnNLXAofo3XCi 1wVgnm7v6PjuHV/HMUjGVELgQOkMzF1xPFOnMVv5LKnXK1hCsW9xN5MIkagLh8+dRN2obCaisEKJ U7Y1oSMcyvgl2pQ+X253dHm9odVFgPTiEikY5ykJgAA4WmvR4ahJEABRWBR9t6WL3VM6393S8XTL S+ricqAnlxd0URbFKig9j63DtZzYyVnasWYwNIG+2l7SVADdOSPgf1XA2xVngNtm4pg0ZoUGUh1a rVEoYuoVzAY7O67FNVVLrAM7JzW7xC1nJTBEWFYrzpXFMcEbdJMDEMEGQJxeiwnTw6/ZSodQlRpH kYtNT5zsAkOh56mIfI8Ve+5ydVfZZjeGA9/tYabkdkQQz1knJQAozxUoZ2SRtLPGzCwsMHu1rL2l EGnWPImO1H+n6vKUtslsshVAAvJsnK098kdLorE1GWJTKlyWQTMOyWXIBhU6S0EqDCLVc06Z23Cu aBN2EmiuDGYW4JzMzeLco0v3wpzRJAcetaZV2S89JzKtta3tZJWlAPbCt7peMO6PsWq5CdnkXJxj bkzSo6xXEmBkJ28Yq9ASWWS/G/tU59+AwcLfYvFF9iwf42Z9tALE0hZl2xwrJ/tnzppo7kr93H4g X0hBabRHAPxEgZ0ARho1Q1IbUEMdggbCU1PqPFNxftbq8sQLm89xsTdam6j20yckiPdiqq6wNndi 9ctvnyGrbi1ta83sdcvEyla5RzY5AwNFmfY22a3O4mwN2FrTdT6bT8fG1bkBjp3akY5WyqTjeUB2 aIt/1KAHWU/54XPDg3/PWaalDFoCFjmPu8WZCgTVbOKYa0wvf9bFWWSeyH1htx+Oh4E79CvUTFj/ /JlcypLsZndq+ywtfvLsfc9I12eH5T3mbfNzJMvLDANNEMltvyWas/QxtFN5xJij2tcaUwuDW4NP LZuX9Wbdy+qitbPGeW1LzU+TZ0kNIjn1AfFBZnnlRi2LVRfEei4A7ny8p8N6TfsDrGUUhdwWwHOg TdZgVDJquSkyLkY6qgUdSH+0s5IaxAyJDYjUGZM4kTDKId2H4cwnAWxK49cAYWfdDMPEbtjdJEIV QfFdeW+ncSbiWp1YCYLd28F8Qa2dct+704GmAvg2yKxELZzTPb29v+Njxfbl36ha8qaAuDd393T8 9o5e376hu/s9s0W2sDdxxSdScLGIvCEkRKCmHSyfAcwPSZwQMyZeMNjiCHK8WKexbaQW/cgZvJMo ZfxbowZ2u2f06uX79PzJVtizyzKm60QXq4lPyzgNezqfkKGERJE9swrr1Y76TeBTC7gyNCxquiz3 PTFLd7FC8sO6/O7oel0WyCZwbFrIYFFXPKvb/kKONutX7LaGS3dzcVWef8GbJAa4V9s5srwwkwQL i+tOEk2E5THrrW0U22BSjmPixJOQ21Eo8jmRnRfLNoWCObB5U71fp4yWAJE+Bq0PFBg4T1q2BP8h c1WyEyUeQzKoTqXPAxcFhutxDQSHosXIg8D9u1yFAruGoLwKUEBMKe4vsaVSvHW9ssDuoNas9Vdd iKG5vwI9DHb3oMIYs7mQocqKzIRavSxXIGeAxBRFAyV6adfYIKkFp6BMM9x6nVsBbRqP1jW2AjXa 2iupoBK3AgP3LKUeSAW6KA0RQBIfkvScXFHQzKIhnHbVqtg3ZmHOPvG0qIUk5+4OcgLCoO1DJpgJ 0KjzNxmbYsU8G8hhQBlFmVqsGrfQW/ZM0jZVNbm5ecylg34bkPG/G9uq87IAcQ1QUVXsMq5zt3wF 5W5tZPc3Z+Amyxpnq0Jdig008dAsYgCb8hur0jK3Xg3A50oGApBMEUmCSANjUR3CXL+z7CsUK+U5 YO9MrIWQbW36c0ANhHF/dKr8/phnAT/utvPzEo0NeQywTKbcUy3QWhlXBR32XlQQH43smu1PO69C ap0lZVsTuzV1rpLE01p9NeguHFWJ7FKS8FmWqRzbmjVb3oCprQsLc8B4B2XI1BDnJ+mALWGKnejw XczU8iUlhAyo9ZxtLwxUr6EN8xALAfM0MyjrvVJjM7k4ccpkRcHnjFckdVnMxnaZQGyvx4wnmQs1 Ksj2kc4FOfdnZdIbmJ1kUh8A2nZPt0/IZc0islcZQ7u2Zbem2n75qoYMZKp7uzLzGt5QSa8kJ1yk ziVHJStCzadOZaE2bYHhgtAGBu6y6VwUbAE95wK4jqjzBerzJGfMDToINVsOChlzAAU6dlx+guuK waeLDMZOY6GiFBTmgzvUEuRK9EFi7iwYeYVq+oO6OJDBlMUdBfCJ+KnpsKdjEd6H8cjP3iHIHEfd 4MzXcs2hKOYN0uhBv05SDqQ7HGg7SGHAr+hIx7yn++ktfXG6o7vzxAVfT8eJTrf3dC7ADn3nshQr U7gSBM/xURi/AgAwb1z1O5BsSgapAlp9PJFfHBCAKxaosQYwm4DiazS7arPe0dPLl/Te808ZxD29 Inr5PNDlBYKB78o4HwoAfU13x7eckIF6d5dXu/K9Kz5uqldWApmnq80Vt+v07kjj4V35/ZZCmctt 7hk8oTgr4g+7fiOxYGWG1mD8kGAShiJoIl1crujJ9ZZ221VZaytOqiDOmBLa1y/4FmwrAK72TYUi NnOv1pzVe2IXISQZCw1lhqIIJlNkVVFpPUAORB81VkQBSQxS4qa6+l3YimWzZTKlPpLUJST+jcLV 4FAFy3V8EoDoJYmJA4grUI/rJOJ4MVQcr5l6FsfBx8Yk2dic7GFCtKtMU1eZomY51ywxZgrmh21X UaUJAJ2d62qB246hTOquMAVviswzMnwfjEFsAtHmh5eg1v7juXBsHLOV4mepbcpZGEx+jr1fpacm ZpDOUabqWqhdqsBqHlRt7VoKU+bAWTgqGKxScqpun6RrTkr4pMoI2TqpDJA+n5QRsbXYmyvOjWHO TejaiRBVOgcR7LWdwX2khnFtvwIeDyarclAZPNnoOiYo5aZkzHCxz+pxXQZ0SGUOhx8o+CBLPAkS 51TvkeuDFDrV0I8G4JSdDma0zVmO2fxYPTZbC0nc4EkL5Zr71xt/VrA1W9iNW1/LAHnpwVif15Sp 7ANfFUCSUebgzLdVjBIFcuxzdK5jM7dM8ZPtH1xsLtEWx2fZ3rIXxOsk4aA6TkkM0d7NOZd5z5oo 5Po3A+YWbxXb6QJJubXs2bks4CgFi5ltxk/97YmFxXi0ufX9iRLWQgb+1U2NOqNBJGnn7sVxpdgf 0yMFtHMzGOr72cWUt4l5YFjY78dA+nd5NpaGyTyxQdeZ21PsFVCGPDjPxcMkBmLZKetVdAlfF3wb 1RhU3WisfuoMMDZmr7UrN3mgoLnKWNd2A8C9P06DlPq3bLKsDUdNtcMx84YB4Jv2a1ZsqOh/WIsl DmXb6+THWoxVsoDEhSb3lHIUUqJB6NaeBSWzdArizPWKoo4omDF2EnjNW2YVmRE4FLBxh++vxO0W d3L+5G69lTiytNVsp8hxDSgwF5UZYWGBMzenM70qSvC+KOXvn0709nSg4yAZezhM9XQ40nnAsS0n BptJY/O4jAbuxby3KJEutqM9xizV/WXDT3USbVMYDYrXQC5QVV/eMr1cycHsH73a0Yunma4KcLu4 KBbshgTslGs6HC+SdhTO91L3qZNsRhQwHvdlzDeJY/YmAPIghPgA7/S+PKwIzU25zxVOTcApBknc 42DrUjrR+uq5xBPifeQKoMBuAc3vzgNdl6t2BcR1HMe2kUxK0vErAhFxY7agpUhurEDHNgbWG0qC jKUdVmYAR69YkHNnqfCVumqxY6zAuSK8WMCwWKckNeQMsfHRUyTPXgVxr0kW65nIBeZa3TDOoJ1C DZjHMWo4ZSIBLEU71HjikxgQaNvlFj+UtXSFZE5lPkN0Jjy47l3XWO4QqsL3gtPHB03M1M7ZHvmt hFRQ11awZAdxLRqzxEdPueBfX3LDx2V54Wfzk8xZE6TNQTPnqLL3ynRRavFYqlTMNWlnofoacQ9K Yej8MvhlxTCvS2ZjVYVpBSmZYyStzSJMpd4jYhvFcBHZoSRuU/5uP876bcxGlsD06Nrpj6QSwU8V GHlF4ZXIjGnlPjp2h3zMYVOs31VkdeYS0jXVWXYGKStTr1VF7o2ALIHiXELDgcvZ+OU8nx9lDfz6 tPtbCRBOulnG7un+NMVu350p4PI+EpG8Eq791PJCyzi8upewvr1yY20pYNgAug70zHCxH2YQ1R1r wHw+4GqMZt9nY9I9iPNz3splTKoPUreidra3PoSTGLQkVbD4T5kLA021jEZtg7nfYmW5uIqBGaUa piF1H0kSd2LLVpXSIdb/1qcHL5YXgUUjfnfZjvLq+YhKAywISeFSMFi3XCcW2n2YJXhxG5np12P1 +OzeyKwjx9ImGbPssmo9WyeAZy6jbE6r/MqPy8/H9ooHcX4/yVgmt1fdecaLhLUlcDT7KzvyQnTe vM1c29MMpNiy+o08E++Mtsd9T45I48xBnkN4N0yeWw3a3rJnaEHnV8GgQA6ABmU4EBt23/WsEBmM rcSCqaUjomWYENPDcDiCsevZaJOiuyjbgBcmfNdvJSMwyjE87G+3DYWJOqM02VrOoExSUw7Hr2yu L2l7c0MXT1/Qrvy9ubzg+2wIDJ347dnVgoSHIO4ILkcApddLkCcSOH4vPa2lKpjFwObt5TqAkC0C uZVNmfR8OlZYzsIXdwjNDvWdbMHX8yC1U9PckuSg/kkDqd142w+ycJmN26zYZYfxBW5er5BJe8/n na7KPS6RXLG54O/gUHkcIoxaXv36oozdkfhsVBwof3lTQNOantMT+vHvv6T3X/2Yvv4m0+EcGRSi dt5wTnS7P/HRYr95J8AWrjkwULu8K23eFDC3oUOZ3ec8f1tqZyxSrV2Eo9emUahznluchdeq3qoS iuwOD12zwsz1xRsCSQJRNgnuP2jQuR1zNvDBy5EDuFOtNC7KG4WC2aUdBOQltbCi24hY00h26RDw 30WqWWZ6egOXzoCLrWsu3ubmbdYZAyecO5v0qBocV5WV/Uipxd5A8HSTFHbm4PqpHdDsrN+qNHIT CFGr+BsbwO7qpFmoLsBehPRc+ERqWYMmjMRjoWxYCLU+o734jupCrffRLFSeb9xnEpcXrrByICzQ 4C5iKSJuhFrGox4QnZuitD5xJXifkWsAK8/aYO3nabQ6kUxGNsFbFba3mrPMRT3mLo01Fsxb13Z/ 3q6qXStDufh8ply+4+W/uwRotXI9X0iKNPVaDIeykuZyqZcpgAlOOfgjtez3ODYXum+7V2CzfqTG I+LfXLTc6j6SrXceeLI96vvp9zHfz+JKdY2yodSFVkjWZV1jX/H5t4Tw55M+X42+zkrduLYqYPNK 3kAoJ/pka2tWF6goPT4GMVarUMdDRrZmsLo+yQkL7iQK1Y0SwNHKX5mb2bLqJwmE5B87VUZKCZFF lqmZJOvC1iobIaqXrTyF/ATRMZrUkLNzWxsLlYUQSVFllM1FaCw8zWIDl6e4tPHi74OkSFp/siH+ NgeTxndBFnHhdP1sknGpjJ3tR46vFQAItk7Ep/RBbG9NyJkGHpVOS1rNDJ7FPjQAZ8+ZgzgDWo4Z MwOYJOZYwn/UCNbn1Od9x/625/r4S1svmZr88iycf3H0YBerEZ9tvxBVw5FFs4ab8byqnrAqAMYs 97WGSWgNay1tgZrIgkRJDzAyrBCyMG1SlVoX+gLEoQI/WLFeXTBxkT6M5227lR7NJIpbtppOSo4S c3SfOXgfTODzm2v66L2P6YMffk7vf/oxpX7HTFTEgcqoA3cGg4RrpXjvYZQz9/icV9JTIaIIpxg3 tL6beCshoxM/TGwXpT50E/cRpSXYTap+6bgR37dUdO246LCPezMXAJmQiG0hVMuWF4cNMqNTAXrO QhAhHfgwe7ZwtP4QfwNxPxnn8x1KE87VXVsXgY4vn88IEBdONByLUMQ5XdcC1Eqv6Iff39Bme8U1 4lJec/HgiHE7Z3rzbk/3pz3tiyD6+69f069+8yX96u+/KKDpSH0RsNvStpvttp5gQGoBMsWrmU+y bvRMQzs+xcYihrq2eK7hmo8nzvZkUExW901KF1BoSRI1SyxrWRrMIMqg4P5BSgswcxQRxyfzgCOT AJg4r5UTH1Qp8YkTcorHFu5yrAEDX7gjytx0wv5AyEQ9YB0ZshDH5hbiMjPridc6w0WgelRj702w u9gRs4pJXL72Y8ygiIEWFOytyVquxmLXOnNtCLvXhIns3T7QbL/ZOqyCr7fDycXKqwHe9RWoiRaz ePuWzGBunKxuLK6FIwCJBZhjGgXcJWU/HMNhrKRzp8bYlIsHdFaKAS8ej9U82YKTVdz3+CxoIjUy 8HlkoG1jEd18VAFr90upMlut7+1Zy9eMSXLv2Zjb/p5/pz3aj7ux1MY6m1vUn7FaGQT33CW4XDIO dl8/hvXz3ICg3cOMBqIwe9+YYs/a2dmT9bv8HGfA6lqwYt5TkUkG0h5lhUgrAaRUYzVN+UoGJUe4 ybyTA3FqOPgxaDF6izl4AGapArm6a53DIgAAIABJREFUNl1tRHm6XivoYg4g7RioCix68ofV2/ud GkKi9KMwWZZswYp/Pt7kwVwKD0+YIEuWC+pQM6anveTYLQGsdU1+B0CZr0XsxdGBsMmN2ZzF1BrB 3/kyllXaS4IZKJI/Us//VAaN5iyxkSFe5/m15JOt/P1szv0+mV1XWdE8A9az9hPN2jZn5+JsfHWB PBhrA7455wdGQ7D+YGS0lCHWYAcsovqHYyYnySLul0Kndo5kkUoJBBG6sCRGF3eD7NAuS0YqMbUr 8QmSfSEApk913GoChSFfPHelnTb/Li9EZfXQkSFJgduLyzX9/uef0T/8yR/RD3/4Q1pfX9KAWLvV Bd0fj3S4A3Ivg4J09aKU+wJcEFR9wpFeR2NntNI99gQHk2Y690caJ1H4FLZ8fmazYFDi5EBbHACf 5TgyADoLzGRmKWsWnNZ3s/GTwM1UQJRTfiZwUmpW13qjoGSaHxFEmvE5jBKgzhB0kkDyITIoSQXg rcYbrpqP8WKGaCI9qFyYTpz9ullfctmNguLKAoCEeVuuGRkgj+OB1t1l0bvCnuGw+5vthq6vLtgd OA13NH72io5//GP66s2efvv11/T63S1t0p5207HsxwtODrAK+1Is2kCdWbiLjRwlboyzRSdzMY+V 2RTjQNrfzbJC5ptmqhalsFqmcNhA5Bto4WdNLICSyXwG75kTLgDyL3txQRT0X8YiIAdEzuntxMpP sdUfM1cBC2BuQJAYwm5dlRrGF6EGSALnshfOHcPFheNcka43m9n+q3E9ti+BwiZVGJRrfCBYZ2ZJ enPt8WF5ZNm6PAv8zL7ef6z3JlG4nTAGFZwocGpB90RG8ucqpOZHS3XqUhPJpzxT8FlhVBWSzNtc aLIxRQLwOAsPLnW4DKgxk1wySAGsMZbWxklDQKIKmSWz5NttQECOBBRGw2fNBn+t3WsBMLwRWr+3 +Puxf9cagNb3qPd2SrWNUfuugawZC+LkhLExBm5t3M2d3lsAvG/HAsQtyzT4lzDIDejx83nMM5cq Yt2Lz4UcIDPM9MQ1XpNIQLJQlon62l5xt7ozgfO8OLqUfJFMb5n3uZ7ivrrxYrefcZ2qiIMa0QyV AtUMwTp2oTEafkxFqug+Xc65rQ/9u4GDeWHZBthW2gYSwMKx4StJ9OoeMwri4vf81XmjQ49fsJi/ JjsU8FZ2XDU6D0dy/Xx4nrJW4K4epLb0ljFqbcy4r0GSnywu9rF9MNuL/EGnHgZxMdt3YmV+3VyT A3HVm2VZxx3ZySKyns3waMDYdqCV3fd7jofKBJ3/LPoxDXW+k5YQ6hayQcBZ27uskDuqRBc/v5Ja kcuGeHbexrFXfMQntijhgLXSo16pglUrJF32uGT9SUVy9Z1HzeJBjI9WdLfjd+TcL11cUIRaINbW gnTeCvNKGjazfEnjUvLkkGfmTrLvXWM42tFGItABhi6u1vRHf/oT+sd/+m/RZ+99QpeX11zrbZ8L UBtO9M03X9MGbtry73C6K/dC1fwjL6jt0yd0X5Tyv/wXv6DxLtOLJ9e0u0z04bMdXcANjMPsyx4b Nys+J3W92XGGG2qr7cpGW4+XtD/u+Xil06kAF07gkHDagWPAxEXALuUgWZY4Buo0nGlV7nVGXNgw NmGZ7KBujRm8n3STi+uD5aMKZLA9+/LdFcp5oGRLTrU4IEApr+FRXNPm4rPCkQyAUXYkCKBmwKSK UuIwghzM3QHMfSl9sFqeANCrtbjXxhMnRqzWO3r58pKevXfJIO713Ru6e/sFvbdbF8D3vIzFuayx HbeViyuXMTyckTRS5qJAYZwe1nMBEyyGXtYbavRlsUhHMGJBhBEYVT6oPgo4k/ZacUk5DcRiOSdm 3np2pwKAgxlFMgfEwqkA1+GU2X0+ILIPJ3MU4IlTO9ZbrPleYjXBqsHlj8LQxxO7o9cFXCNmMvdS PuZYhrmDRTJGPp4MdfdGOO9XEv9mQgZz2a1XkvxAGhMaTPn7mAYTWhoDE8R1XK39scVF1t3imAVz 6/LG1/P6EicNYDwmOTsYSQlnzehlF7+yJ50wbmxsTb3EwHjFkPuWDZkUcLCAjly/MUg5MFGgk1mb E2eudVnOEY7KzHa9Gm5Y23CjUGBgIex7ICuCyfGEWd0aVXB2EpZgh1kHBR2a8c6gAaeUkCRUpDC1 2FSLpcI+WwsbgiPqGNMghIEzVWXPsnCOUjIha1a4P04qLAwJvaApAA/6AlWwIQyaJrko0Bwt3ofr V/V8v8nVyJJaVcJ6gDVZ2UHxlYHTcBONa4sckxq0mLNY51i3kDNdbK7VxuJkpzKUdXKhNP5gepHh owAdbaPJGg5hqKcmNBZQWHQBj3wEm3oaOHSi54I8XC4K4Tm4xvYxZ9Nrpirusz8cRP70co72al2M o3XgMk697Cwx9GpFfQmTqMpXtX1Idog8kUbmL8BFAzGWzFINLdLwAVamRA0MaKZ11mQr9riQujhF h3IGN5KjepxPPXFIhoBKNc5xggWXKFpz2Isl+2zWa50rbeNkP0kM3vKccxgr+EX8bra4fGrslRXz FrUta7Yt46gyS44r9Mu7gWOpS8Yj6zwf9WB5jsUdzfcrhhvfOitu1KQOG3zIG3g0xgaMpA5i4r0X elRWsPsg5riT+YyNNffMm7SF2nxEc/mS7JFoQFaNX22HzGur08olVLg0liRu1YQGThHWuVwYbSwL ox25lqsBZVmp66C1B7k2sc6nrccobRPvCZEkf9u9W8hLsGcES6TKXOgZxBQ/H/q+NP2EfeYRp7kC jVbUGRQ5HSy+QDc7WXaWjAbHJaRmycg1yqyRa2jUiu6KhketYzbKCijXrji+CAUgMTnPLnb0p3/y x/Tv/9v/Dn32vU85kPzd/h3dlh8U7+3zkTZx4CM6hnFP+bxn4bXC6QWlTz/72W/or/76l/Q//S9/ Tm++uqVnz57Q1U1Pf/KHP6L/6M/+PXq+25X9caAJGZqlodPpwIoAx0vlAuTC+DVd9R0lHGaepSjk AckAu0spVpwMPctCG04yEVuMzfCOF23U+Ciz3oIxIqMor4zgV2ysURA3H0hvQhwpxGnFTBtpFnEK ZlFZAGrk+DNe6AzSmlAdjbWKGoiuhSIh0EacYhDOPDfIsmXgwGxPz0kcxlzykUfIAi2KYntxWQBz TzfbiwJuA3319ZuyoHb04uVLdsNOAK9l7PbH+7b5ES+G+Lgo5T2oVzoZTNKQ9TBoOcTYTmhormOt 4h7bRmZwj3IkOCoNcYLoV9Dq/dVy0xIcHel5ukl+Z5kDnHxx0ud2QZQs1zYLUo/JSnkCjE1yxLBm jJIIb3a1KaimZnVXAUNU+1EDURV4SZ08i1vSM0Ipq0KbB+F6Zs6zQAbY9YG6HkQwS3KNMCYc661B V/asoD9eIGY9Fo8rQ0ZqVmMvrmlSoNP2N1jGiQG3ADgR/J21lZOaiNkGc4dxILYaibwmzZLFPZNa 8NHFfnCJGhMbTZBKIpAaLDontV8OXPmXAGarSefYD2zoToUqwJ8JZKuI3plSoroe5f4WazZ3+9bx NMAdVbmmRbA1M4Djg+/NgrqDi7lxbB1/pi4/AVdxdrh4YkG/jHF+6Cbj96i5xrJbRzKsmeYOOarX BouvTMqcEc3AIbcDXoS+HSO1VMQM7Lo5U1hL5+j1diQXH6PXz13pAlLSbLxrv5QNMu+PvPlIQH9s YyPFuHV9V3bJxXPx17r5/Np4Ler5oVC4JPa1OC1+tpMFPha2Zj66sfBsli8gSw7UBLIYvVDXiHfz 8ToLSU9rWK6FVIs9+zHx62zJwNvnMk+S2DDV7yKUQqpUMMudNS49WHkxYiAn+0/ADYx5Tv63M5dt D2vxXSs54w0L30ZjFXmuewVxvm6oY6JtXdj+l/eJ55hZRJujQFrmSrJ7l8y7rb8l69q5v2vNN1rI A9JwMQq1EHV21/r7RZK0BwsjkHPEXewzyZnDfc3WUmHqaXN7dYJL+WtBWYWavGMxL4qAa9Bgfrj5 7cUuWqMtO7E6uOMcf7RmYDIWQPb06QX95Mef0Z/96U/o+++9otPdke7OJ7o/vCvfPNIWC/P8LbM8 03AkxMHB2sd5a6/Ltf/yp7+g/+F//Of05//qb+iXv33Dwo7BQDfR//3//pL+7os9/eM//Jz+we99 j7Y9XAIDn+EYQf/Damcmtli2+4FPQlgV4HJfBu14TrQt1v1qSBwYzwwCKwE9gJszEDt2EcK6sI1n 4yzuXKWDMZCdxO2ESReYLZrynb6AU04YyRYAO9go8hhHrZhtcxZtE5Na1dEEnlHLPVsdGCMImnUe 6qIcJjkWaYKFDLcxvotN2YmbFhDyfDwUwbpjt+7VektfvDlS+vIb2u6u6KIAYqAouBGz1rHJahEy i6sMYFDXNlurfEaeKB6pEi5JMFlZDf5GDhqIPlUafS6oEoM4dppopirpZllvey7gjGxjdu8qtY2w gDFIscaOWULUISxWjZYFwDhwdX7bdq4chcxxEgsYCsbHd/mNzRtV1oLVTTRhZW6MmjUKAyCI0JLc isfBSLO0pyZIDLDmlu1q18rIi0Vq555yhmKWoFoGb6G5DJLtb1fGgO9lMX1s+LYMQbiTbZ7B+q6j ZJ8zIxZbwdKRgZ6zMoMpTj3A2/o5y/Z0de3q2CYG4pbBbUKaAa5LDpmNwaOySGOcFmedsvABs6nK zWfbNYHbQHYDdbq/qRkgvE4qOBp1fhaB//pqIKH9m5X71JS7/54YeXyh7vdpBu7rfBo4eATAyX0f Jj14JS5jbIes+yD1bJVc2twFieHJU5tDr188k2zAZQnO/TNqMWAw5Qx4+nqEH+PHFKqS9MaO1Nic B/5LIywu2TFxClJTsFHOpmIVUbW5aCCcKFdAqGM1KVsCrwLj2p4NG7BZHMNs49A1I4XlM4wLlC/K ImNmwflRknas/BTMUIStBKN8ovSlru9ohWCnGuIgQGl+eJsnWioQzNn1z7kZQ9P5s3WTxXPGIT7u 5gDVbPhRVCZPXYbwyqW+Pp9FUGbqgiwRpO8tvMNCIcYHsn758uup2hu5zVWn85fsWrsoPwJSlQmT smdRv9+MEL9PbJ9542W5/iK1hKS29pfyrBk4/K9qL6uRn7Matk2+1fbq93rZ/g9dNtzQILXPuDOu QaKQzT+9iJ/Jmmmj/R1d9hRfkdJMIhm1KkF+KCS8BoKj7WZN3/vkQ/rDP/4RffzhKw7Mf323p3OE i/dEu3imfjjzkT05C5sCuv5chu40rOn/+enf0X/zT/8Z/fP/7S/py0MBXTcf0G6zpf1wonNROD/9 1Wv69r/7n+m3v/1D+s/+k2f0R99/SYf7L3iw+n5D43TmI7i2m562q0u6Pwb62S+/oa8Oe1b81+tv 6fP3P6Snmx2DIRxKzywL+jRKJWucfQl3JfkFaAtO48AA/Pj8GExY8mBATm/osrqrjWnR0Uy6egK1 A3v5HojhGuV5qGEGMNxiBwCUT+WXHHMGn/o5O8uYsrr1pirOUGEwRzn7CovmvL+nw+HA2a8XV9ec GPHu9o7+9uc/p9//4Y/oelfGeL8vIHdDh9NR3GrZnR8bxT0KOQ/oyseQET04m5OBBm8mEzKNacDm YGuvX/PJHLpvWZhlFdJyTSjtK0bBKXGCA7trUc9uGirrjKO9OIGUtBHIVgpcVIVOXAF+pRtM2r6K Wi+ukmCN1l8qI/x7rXXconPRiIKaW9vsStVnZKbck4QZZD0AmpNfhCHQCAlx24VAvsK3bkNhqHC2 rxluUbOqY9Bipsoe6OcSwK8ums4X2m2Mg7DIAq54TkksbS6kjJo1ENZ8oDIxa2LHMDXhZq7Ltp7l KB2q8gb3nzTjzwTuEuwYl79kdqpM+Q6F5F9V8Fsm9KS14XhdGFgnKQ7tWAjSel7L583uTXMLfFa4 1pI6qnC3Sn5ybxPy7d/aD5r3w8JOJBm0xS21NsoYmhvnIWBsyswzBR5oyRiM1ciW9+Zxdx4QBKta ZgDTtZNblewUklgTogxo4v1R42KNkeGYOBzRpvG2vWPF9O4a85aap8jNlbAjAiTs3/x7Qc6JMSHh GGxgu2dEjfUTjBBn/ZW+9LVPHpha3B+SqWbsatc+MxBXmTgmWtR92ym4U4+IGT0jyr+nBiblwPbF PvH1D/PcAKj9UvYuVvBKrbSFyTMH5v2YVtBRMQCRlIbHfl6pkWYAWtb0OqGShZgwHEYxaUxz1iP3 FLC3xCUhHkTOSOhGdnLVAyoBP4K4Rc4QBTfJxpLZnrTzrmUcWtax3ZJPh2CMI7Vsg+oKu0D0sOwF KfjcYjNNVxhD7Zk2M3683AdIq9q2uu51XoKWptHwm7puNBQHi5eJgZklRI4erqi2xbDNhZUemeHe ETefZnvppaNlINoTQueyV7BBtaaaLhIE6cP///T5Nf3o80/oZQFwcIseCyBA1mgGa5UOpfNnmg7v NFB94gQCiT3r6O+/uaf//f/6Kf3FX/2S7gugefHB94nWNwxgLjcb2uSeT2x4++Yt/e1vfk3/x1/+ BX108xN6clkGqICQ2yNqouHIsAJITt8WILChn/76N/QX/+qvKVxf86H059vX9Prta/rTH3xCN0+v KQ5wz+1p1UceB0b15R5TlgVgKcZyLEdQBqQTbw41ZSmT3SY+BWHcJDQ3yfl4ylCAMeiixcJZdlKn SQ+JAyjGUUGISlWOIcljBQ5nR0fzrNb4LpmPNQO/ia0iBtwdXN+RCyzjKLPL6485tuXLL7+k68sr 2n32KQtfuC+zVpTGi4s4F9BFlpGVNSZDnyRZTU6RmNDjWmbsTHAVr0UwZ+03avXxsiFJR2e+EYKh GH79ShQcLMFVlFpyIzZBN5S5QmyBKLwxoGZfZlDHx/YWpYATP/BzDsJaQWAbm4ZyNyz8uQZirAU9 ZkxcCE1ZxTx73wRjpzF/vDbGqYJa2R00UwzezWavSbkdL3zthhhznCGc9ZgXfwqABQRXsGbt6hrY Fks1VRcv53/k+RFa4uIf1SVtbJ9X+nMD0YMrAwN8bWWEGnvDIFD847L+Y8tO7Xn7NFZldj83FwZE wPD6dtTDux1rk8wgCEnPxhTwvMx08/PAhdJDi4fhabCSK0GenZKxpr0IX50PGYqgnzeQY+0bR8lu JN0fMrduPJlJnQdeC4vh5EfyRnZ7Ldm3JRieeWhIDSTuW5rNY/tcwGh0qsPu7Z9hY2fr2TOF/jq8 JE6u5z0uRd7n88ChA24/zIzAylbQ7DPvSuP7OOY3KKEwudMZgp15Hdtc+JfFE/o92s2+Mw+JsJNt mkGrYEKVvQDGxkrFvrHLNv/sLldWa8I5geaqd2NoLBc54FnHRRlGRTvS19wMBSkz0+SVzWgtC6N/ y5GEsq7reeBBmCg+y4NvqrFmPAaNiUtRPCxzA5/IHy3lGW+/Vh5jxh57La+ze/niODPm041TMgzk Co8vZZeMZSDjOWfNCVIb1wM4+c6C2c1ptl+WffKymD+D98qtCTWIGvqVRSJgTv+nVr+oWhWxuuBJ Leq28R1BMWtES9PVBaGDw68kwd8UpJQEjl3algX84cv36LOPP6QnNy/l8PkDMiFxnxPl4VbOQE1H pmhRjw5FanHG12p9Rbe3b+ivf/43zLr1lzihYEtnsFMofgt3Vbyky9UVnfI7+vKLN/Tl67tyvy2z Xr/6u2/pn/3Vv6Cr3Q39u3/0E3p2c0U//+0X9Jd//Td06tb04tlLWhflf18G/+++/oauN0R/sPtR AQuBmTV2V6pykWPa7VBkY7uCxjFkXsgsvINumiCxSFmhscSqDVSLPQY59kpKeEh2IQes6388T1kO iueKaRPKj6zV0gwaVzbIQmYBFSQJIBgA1M2mZ+AGtZgQIA9Fgzg0Yat6jlU63aMw8Ld0UYDt4byh v/3lL2hTQPL3Pvq4fHbLVu3E7sFWL4f7HoTGru4NSg2YGmDQLOCgwfiWWKNVKmgYk1i5UU9kkMGT EhNR6hOCmQWQ2xQhsyl9lRI5kZlYRMev1xNtVpEZUJgeAyybLihBhXhCcSuDTcZxbedBYvFwPdyF G85ozky5j+ehWpOZN1pmF3jWMxMkoWGhPBEj1ltGENXdY4BC+tp2lI8fqsKE9JiYQDNwJWPWcQxi TnO3gRlMkd3q7b2gxgc59kZcphNbli0TUBkYPiVjksPtURMSh8h3rfxI0u/iGquhWAWgjQGAftD6 kGSFWs2FGNx3ko7nHASbW1pAprmX5248AQ6jnPOoyt+3pQrDYGtTEgnYZU0eeE7swvOsRBXSmWau k+XLAFb7uwEZA691zLW/ZqxInx7er/b7wXMck7Q4Tqutr/RIG+YvznzrLdHBgQPn7kQGuxxqLwHy fm0qMlj0K1dXuIUE2MvrIXsOjukaSdjAuUtP4pWyMjk5m5EwV5JLENcAn66bSkiKngKA4zNKjdTW xD5jQtrL1sA8m9yPpzAn+QGIs8/4Wjc2fhxazNwcQIhRi/WpsYiaxOXXhDA8Dxk4ft/0r7z7KEsn n8wBiM3LPO4XY7ZidJDVnkLhX5Z5KpdNZqESQtbQHTuVgn9yPxuPpds21PAWScCU54qniuWqFvP2 bbcYsseKGrM8IMdRMZfZQDeznSxrVtWVuWyXtUF+pNj/5AJZjPvl5z7Yn/O1iNJYPiFHQLDqs0yz 7FcwxBZOYCV0JAPdL5AQatPsgeY7FiBn8SVJz+MLcyEiQUL6QHmrrzEHNgHzGAy4txic8LFO4mO+ ub6hTz/+gN57dk3btKP785HB16ZPRXGiKOvA1v+gLqfM5y1KbZ0tzjXFAeqljSsEdK6e0mnoOJIM bAgyt9bxmuJ6w77v4ZgLiHtHX725o48+/oR+8Yuf0n/xX/239Oq9l/QPPvwhffLqE3p3+1VZeJf0 4fsf0fXuCd/35nlPd5stHcq9D+eOLkIv1P0kFCkfKTYmKQ+yiPVg5sxcEUHZDTOCeNwnWQa5KdI2 wVEWF3VqnSdRgJqqzjEslPV0BAke5xMkJpnbiaurt03KoJFjsAwQmbCV9px1DhMDJJI6bpj7SZ5/ uv+Gs8aury/pl7/6Lf30Z39LN5c3BQxlPnc3SyCcLesK1DAuHUkM32g1fyZJepCjqB6Wq7WEGFm8 OHWjtHm1JslgjWpBCyO0XXWsABgSr1cMDobyjHMB/YdzGY9wJnjuN0pcBRVoKOSyyrytmckaOQ08 suuXy5Kcy/iiPrAWLB2nXA+WN8UGECdeOsz1UBW4ZaOKUo48z4EWYEBPleAsXWobnhZ/1y0XzPVB VUFU69m86KTYO5rwI3b1c8JKTDpmzSpnQZZE4CJUgEZhVGshVMnm0eOuNFu2m5e5qLFUY1PWbZ07 5cEZ7JLcROqe4aEzuZJzHSOiPLP4Y5jHRFnykPVBLhS3IsdPyaJX8GsJVUmC1/FelHUgfUizYHJh 81rgvT3DYmdsDrID6kvGiu+rruJcuzdHZ40Vs4r7EptniSbmhmWjnIRZXrJuHjTMjIZHnjVTHovr ooY0zD53c87ZgLoGm57Qy1wNSH8/Wx+SnDS2xKXcYpvM/TxnIZoirfoohOqBmLe7AbkYLaFs7oqt 3zEXHFk2s3gokuv3HATMS3IERZCmtI2d7zVTGPLBMzd+j9rY1HnTe+L7YCHZsEAmd5izkObC4+8o yOFDAoNT8FHARXJsW6TwoD+1n7R4uTVel94CDJnxJwmO5sGBzCjat0ucpMix3GjHiiOxefxyGNuc Mzs3r3XYXpGW5UpmAJ09Gd2s9X5swZz68h1CpnQM0puRFytIx0DjTl1qejDEBjL9fUhPPqKsp+LM 5ErmtclHi9Jyn81BnLGO8l1rzzzcIVaZZKyk6u1MkthQG1bHrQXkcbOnVOOvDKUKdS6LcjVpZ8go 9bnwqopbU/dJlU0deA0cFJdQYvr6+mJHL549p4uifOMpchYnLzhmlvZ8VincXgGlA3Cu6zjIqRAQ akccCn9Br56/T+vwczqfE60vLziL7jze0tXVFa0213TeH4tCP9PNkyuKF5neHd+W+XhBT55e0D/6 s39EH7x6r1xbBMp+oKsLALiXnNjwwdNntCsL8osvD7S+uaYXN0/Ls9fFGj1SD3AzSrHabruWMZpW YnEEcXUyWEAQuL43MYDoZdNwRLuUiyAN0Ee5C4lRVeo1S+oyWAVAVY5X02rOMl2i9FBygMcdIJIZ BdkUdpwaC90c2V06qdDiuAFsyq5tikO5x2k88dxKpfUCiJjVHAuYXVMsfXl3+4Zu3r+ifr2lX/32 t/Txhx/Q7332MdlJHpSakI26TqIqYXM1iSsc1uVGhUNgFqrT6tRJIV1yAgX3hgu0nk9KQWvLdRzL skUpBLCzK7Fqzxy7iL26ojPGDCVDzqpUtX1pkkrvXJ8ugZ0r442CsqXffMRbJxYmigxPYeBzUwH5 cObj3KUQ6tFKPC+TsT8q6KNYkTgazeLzSDerAEGN/wtzy3T5Go3BYUGf2b0uhkI2iVHHM6rA4jam Fp8hL0F8vIf1+DQ8fwUQoSVxOMtNDQ8mhqPdxxSrALU8dfU5yY71M7dobAINv1H3CKd6sDs9hiqc avwj+tG5+LypxVUhbijp/GOP2Ukc0Rkj9hwGQxQVxD08LH0KqYLS5NYZKeiCEeRBCKm8kvWwUBTu uVKUVv8Ojl1E2YncKu+b4ST9Hmf3m4N8aVgN8HdspSlGKR9BCmC+e+2I0ecSo+ihW3WanKILfZXl 1rbREmyUZW8n35DOxdyV55kcAzweyHhlzUwftv/UjmVqbJKQCStNJmOz3YABBc04jHrgSFOYS6DQ 1ft2lYXjAtZpkaUarXDvHOz645Zs7QlYUwanW7imFyDOAuTtc8tG5PhqD2L1yL7lqxkr83klia2o ssjGzfffjHjLuvfrCISIHQDwr3vNALzWauPkjfIfG6F6fJccDiDJGfyJlmORmG8iH1tvLN+S8PEv e1+WU8tolT1hCQBz0I35ZciZRUzLAAAgAElEQVS4CE8xF6Xp0LqPKFPLdJ2Pm8mgxH2b6vVii2oC BcJvVAckq6GpYx7UMBsVvJHuZe86ZVf/0E6fMeNWDOQ2Fj3ADRgjYXtESMqGVf+31nkKeowUZCoX hkVMECyN1FVqdz7IWjeNpJxCOxQ2ca0tE/yncKZt3JSblqkdD3R5UUDT86LKL1ellze0L+24O+2p 250K+Br5KCw+4HxCMCXYFZyqcMmsDk4wWF0UwdQdaOwmevXZp/SLv/0dhf2XtC0A7MXzV7w53ry+ o/P9G7q8uaQXH71P+d09bcpE7neZPvn8Y/rP3/9P6WUBZ2FAnbMjPbva0nTY0fG4p/7wTQGKRJer ia6fPKOnTy45LoYD1XG6BOjtKMdzgVHCQbfJit5GXRwxqRIMnAkrm9soWnFlsjsUWZSjxe5Qpd4Z YHNdrJPE3unJBgIU5PvMGAHk8P0l4QLTJOewK5BjI0ksWmTuptSYkLZwSbLNWCnLeX9yXC2E94FO qSjh/Znuv35NH733it58+y39zS/+mj5+9YQ2OCLsjNMvypz0qGdVAC1cmlzVfM2AFbFUw+HItaMA ECEABtUTKz79YCCpC4cyJQXw8NksWSxMHN82lDEqQJZr9sS1WMHlv035e4tad1i3SGQoN7za9DRt sLZHuj9NHI+JY80wIswk4S8+NzBwrb8C/0sbejqUOe2OZynYuOLiimX8npc23bElhgSS7cVGlNoJ TO8Fu+9h8KxgedbaXGK5Rj4jbOIaaAGV69NcgPG+Q8bsGkrTah0ZfT7OBOsW+dRmzVUeXdYEsyFj 1jIcQUppqCIRPJOkykUUkGfRHcb88snDcBevVbBUVqOrcXKxb2xNr2VjbL1CQAWwoDiurxomAOxJ T3Hp5UQFFVhZs3KjubYgXxgotgB6+4+fUY9saoVCk8VuCWVIcOEw8EuhuWJtLLU9LXMb61wKOfdw 48OdXmOmzDMy1b7KsWda4FxBOQNI3G3Kmrksz+SajHb8XBA2HuEGA4ytUTNKk5TjMeDaa9yRAYUQ HJtvYS0LZkhcvlNVhLHrqhL3rp2qkPqo9f4sTCZoxrABuqikzFRZEYubnSYJO2hqeFKm34HAOGnx bvEeWGiI1K1UFrfvmVGAIYRaccay9mzA9cwqAVQZ4BMeIHCMLe8hjJN6GDyjZ0xRjVELwoBn2y8Y jk6NQwsXyrLeJG8da2XFixklYlxicd2Dnd7LkiFk2TGfIyc3MLHR4jFt7KWNxPoz6ljw/agZqOZW bd6ylqlfI6lYj/bNnQlgkXX3YviSHH7XOFINkApSr5GNBloSL3pr1gUPjcjW/p6NgGa4CJi30hhi rEgSG4dtoD9B9mqX5OhEwv5MjQmNOnyVXcYnmoEbcqzz79ewyK9evFMmS4JdF+u8xFp2SgAuG31h w14VTmhS2dVpsgoSSFIYashGrgawHNfFscY4dlQOiJX7JWWHSeLeh9iMc6mJydXZdQ9HJbdUO1jy GYlexnMhe2Usssoc9fTl5kLuveW4fIlgnaRsRZZaWyOABVxIYOhQVDL3dRJndKsK/K76q1tMTHLU NpT2CQqzKGiKJ7oKu0olp2TV/zHpZZIQXzUELnvBvvdsiJaqSw7xSde7C/rs5Xt09y7QVQELP/v5 r+l8vKXxsKHbooyPd5me3zyjH3z+Od0gC/aDZ/TqySt2k10WoHFxfUHT8Vj295HZoJvLDW375/T2 7T0LScSB3Gyu6PkLJEtolfHRrH11CwWxQKaZVT632uZW9jz+x2oaoT+JzO1GLgtGEH+K5CprZ3Wv kXrT5vPKQDqG2bEos2Bqu7HbJBlu4tWqfj6lUK07LGIop9NQ5u54oPXVRLvdjr766iv6toC5pxdb ZkeZtzX2w2h3DeYO6nbrtOYNV+wHAxvF/Sn1e9qm5o3O/dOM0QKCsLhRnoOr+mNcuNDmVED9iTbB 4r3sLECpBL9Nay4MDKWBQsNpOuhZmlmUB54Fd49mW/kfiWURn5hkCxWgEoc6lxzMnkeNrYrOHUj8 2aCFZGOuno423sYMVZcS0dJd4P+OarEauPdriwVRsHi4WF3GlkEuTEMmS1GVvgnAkzyMSGuOy1FX 1uxQ8Baoa69lkhS36TSKCR7kdI6szM2YJAMXa4uCuGZFeUuUStK16AGs77/tp35Rh0yYxKSWrQLS ygYpwLT7YS9zWIhkp7J6Q9yOzo/V17PnVqPGrePoWGv/qkoopTrJ8sxYt1hW8GRMZZUHXYsplH6Z DLWkFBsTZb0ek79uTPTiKn9mbsmU23FnSWKAaiDZYi35e9cYokWwufyjfSdUBZYkiznICTwGyDim x5KFXBvZIBofIweUOYsyv/AlyFypYjWQF9vJEFGzH2U9WKZn5GXPEC7H5lZsLimJ5V4ef6W/63WK cWpiQjC2zaBtqBf5NSw/uR5ivtTBvmba8sePQ8Vyuf3UHmjz+drKlrXPOUtzFrPe5m2q62rJPM7r V9bYTQXvy88fe9W+kAKg8LD/Bpw6nSPGINIIGVHJAGF5znPN57Y2I61ijiBxs1aOQ+LKRD5xjh81 dlQAn7KvDPCjxByGoPfROdRyBrwPsiU1NTmc9YADYtGj2bYInVFGkhNknKxEPL/IAKtK0GnN0k5B rRkmSz2kpauWE8QNDULFm2Vjmw3gDQwDgsqRgJAGPo1UrV8vZK3QIlGlOskJTzeROBYILq+Uz0Ug DnT1ZC2Keb0tYGlNp/OJ78dVwOC6GsVSBZCbwAKGYsGhaO1KLMH7/Vt6dnlBf/IHP6C71/e06d+j m4tL+uKbb+hYQNn1+pI++fEP6fNPPqNvvvkNpXL9jz79hF49vS4AcU9jASP9akOr6UTXBeDtYZGn E9e/enbVS7YQCtMFyZIdTomVgWzgXLPFLGO0ZQSam6MJW2G+emoALpFlgZmk5wB5Y89SUx6kFhRW OR8PlRXA6Nmhdk9hQFUwpiaEbC5q1f/YFinPt/jP+XkmcPkUgtSCVeVv4qLIKM68Pu3pcrel3/zq NQO55wUkr+GmUECfzSrppE4g5+mhHMtoyQzGNk4MFmFA5N5nhIUae4IgdDGOhbZmVmVUa9aKaJLW IILFKQ3mRYjg+4HZARxfpjWLuLjrKK5uZEPwYCARppP1GK0IbOLyM4Er5Kvbxm1IG19e+UauaimQ ts9GFZRlbKe5UF4KSv9ZHQVfgFRpeQMW/vnictOuCHzTop8yt7bGslYnx//1C9C67jsObud1YnGt rsSGreelu8FAHIc5lu9PYHrHyMk/kyb74JrBii0rU6L6RgRr19yFre+2d7ySaABu0lhdS8Pi9qWg B7O7IEFj8ShpsDi/KdngSDiyPUyN2ZHnyH615/Ce1RCUbMooiRIkTRASl2Jrb5WBHA82cfJPMgNE BbUZzTEYu9pAoSkc29e+dAdRMwxlrhoo8gZbr/UBLcActNrSCBC3TXOHztegjokDkbrExGswtRho c13xkMRhtq7xDBhSMKysxIi1v4G4eWxemw+X2adArK4JO84KJ91EB1yj9U8MbGMdQ7At0ZgeDyq5 ukCar51gX3LA6v/j6117LVmSLCFzj9h7n5OZ93Y9h+qBRg2agenhIRiaAdQf0EiID/B70SB+AJpB SIhvCI36UU139XRX1617b95z9iPCnTBbtswt4pysXZU3T+6zd4SHu7m52bJlZnBEEH5+I3OyR7yK O6L5lc/H32XE8Z727T70Bq9P4jvlyRA7Ke7I7J2T/N3mCNkwLN/XS7H/3AHBe4MGYRt/5Xn2ZWPu +BsEjUsYp5lOUtmi0RHH6kZc8a4LVhB/dwNPhnK6ClWxF0+1REmtWoCoxeSdaZzPPBWvzerVFBI6 2D3ZjoYxi0TbnBjnD8ahXYblmqxUFGgpZRrJpKgIcrJzh07yxELatpdHdQOW3bJdVWs0aJjtwdJM guTtjZaLG3UeOlksQ0/kuv1HoW8NkzySwob3MaD/iZP3htfTY5OdvYmrZnHKZsR93AyCx3aQrFqJ fzPiHveX7f07Wnzw2hp2s6I6et2HlTHRmLYurpYi+fr5k/zjP/yFfPf3mzHxf/9fcjlP8s//+L+R l+sin1+v8rMf/Vy+/eZv5Pvv/kb+xT/7p/LP/pP/AK26+m07wDXscd2USpdb064DFzM01Op9+vBk ilN5TKbei3JCluAamAfv0wzjqbhHgYy3tQ3CrglsGxl10NUTrPguw6BbBwk0l3rh8VuyoS1A52oY CijF0GiUhSJMB7sf5nmjwdP0Q24ml9F5iwUIRvEWWir32v/2sTzk8XK1+nB6QPzm19/I/ff/Pfvd LWUPQSCR3VlX9L7Uenw6Faen02a8nxxmH4gYnjShB4U8LEHNHO8scTJPtHqhWYkCkthvzlPQg3oB 8mtomSLNakRouRHl3miIyEreoPOFhm8tkST2wB19D3VGJw0VPeHQMlu+2UY0QquXXOjJ4Ao5yfOc UZqsf1yJM7sVSmMYiwMJSdmr/eAk1RIJSERybR5ap0cFIr7LW/GyAPM8ahKdU6bce10ArFdvGb3+ 9LV4oofxLM9+GKoynZVPue2zeQGncEVIWbyEi9Pkfeww2cvxmdLzA1mdYGg5LQH7y9Ffz+Iu7n3D U0cGru0zpUFoiRqjNqzmGKoyXAks8EBy3hudGayX+L3Gz7GP0t88jdQ4tC4TWpKESWEFglOsaNaK AyCJgT2XZk6bgiaCV/x+/my1v5EdyhPkaxh/Nl+GvJVNZxK16I5uuGPYIPdN9sZhhIpjLbrQWT8i aFYvkIFvc6wecR0zzta77aPs4JMHdkRw+m4u9/sDCUAMdcGgYXmQ4J75HqwHdFH189SGswuHl/eq PvsDUeYzUh4pi42k/Lp35rjfe+oHygLbucdqLftxxRzK3nk7GnLUK+I9t5m1muXTIlM16ZlKw4P6 acgF533t7V15Wn09V7al4px4xIAGnNUo3ZXMyYT88W86ndmAREUESfVoxQw0lkqxJI7mdIuCWnqK Wlt3CEfm+OwuBPasQSER+qrY57aegjIvDLWLh4Kry1T0ZE1G3Ns1qg7OqQyswWE3rVunyDPors8Y /mU/YMgN9t/qdDE7K2r3ULPd8V1nyqIRWUg4RH7PqMD0mJUUvmpD+W5G3PV6k+V+k3tLG9itfJCU +06oGaKgVcnB35T4b7XNVuM+/Gx+lunpk5V3eNXelx0hxbuicesZULnlnip8OtlBPF/mbVyvxs6Y L1/J6207fE5P8sd//N/K6+/N8n/8n/+v/Obbv5Zf//Z7+e23n+Xvfv1X8g9+8rX8yX//X8uf/NE/ kZ//9Gfy8sM34D/MF0v7VeP09XGVy/QJCISG+6RabTTlEM6b96iKeT4tYaU/6Ilw03nz8uqHVPN6 Z3QHVSiFPCOGjWyDNod6MffNjUBa/qybZohv88r7DG91T1un16jmRvRm9BVOtZFYLH9/eDAEV7zz QobV2SLGEzPu+J31SGzNjDYtqvzNZkDfX+9yqUPQ6ZnrRtQw9LpKUh59MxhYOwnXRrX2sSvtuUie hWVpKJkyL5XgrEYLUT3boNqmZ/YDuKAOkVU1s0NkwfyLe8Ta89NZMFPxLq+bVfRhu/ZSkVVoXuc6 DisSZKn8bLZLtQKlZw2DM4NJJMjDpeyNkXGIJCVR+MhllAApI/OTxF0zZKLvZXEFLFE4GWHmtwcC 64jZZ1nhpKAq+Ckhb2bEzaA2gB4xR5srM4YtVDkyxWhoKt9l8cOAKH2zui3b31qGZFNUt3qTcn+A P5I5PzR6Z3S6MGKvvH3ZOimpXT9LJ8bS7cW5M+vg+RKFccVmAT13oFRpWkKDJhQZfOElG+ywcgM6 HZBco+ZoB/ipyUjvEnq0MxvYBI/JFC2MuE6EqhM9Q1IJ0XsQwum87FE8FmwOVIvz4uts6EBDi75J WL+t7B3B3nclOGovcYjjeWAc2PHjIfYhp0TeSsw9UTQ6EEQUda93Yb29sT+z4aYv/dkiPssolGoo auve7QWUAOZK6dxOgVZNHg4f0Q/ux+qHfHVKD5P2uiNTwwj1g905eD5T8XuirNmIQ8LXFLzA2GcV hsPY5c4LtN+PshjZXIr9nR3ena5I75HZTkM1ram+FnfEDeCxzzO1bU/fMVlu7oSG8zL0Tzx/H8ae FXBmQeEjAncwCmlMDkM4oXlyPH/47DCmMB/+jBVMO3W4V3/uxox4T3KKeevZ2aBuIkXCl4fz3Dm/ xc846CGuiyGBBUZ93jco0oHfIbKEcjIGexVmXI9rm8xZ6FgkL7p2PzqfT4kXerVohSXXKQCiDQ3G gsTz2H5uRNUPQoKQSRWGTmig6Oa2cOrjsRk3d7nebtZk/r60ALUHquBVzotvqBBxHtAdDYB1M64g vN8WbT5f5euvfya///t/IF99/IgSFYuWBzmDMGi8M+fLrSDa1/4s7aEGlCqdZwt7wgqdzcr+T//o T+TnP//P5f/5N/9Gvnv9zhCBy/yV/OM//Efys599LV+Xh3z7nVpMH/Cc27VP5Umu2zM+nX4Mpett U4wHqM9yeZbHtnD3bQ5OTkBEQ1wxpWlZfIShQ0uKtRjbbdjKArbJwDIZrtGOzGPa8Jaj1lw67Nfk iffuIdPqNCf3/ATNwXf3jvvBYhgKRiLLT19LhxB16ZGdFQlZinA0MxM1T8wOltt9Mbj4ekNDezWI 1QCAogOxubnXFZ6+ZnfPxZqDa0mL02kCpKyPXWDGPtpoEt64xLqJ1oYOAcVrnqW5jJCLo3Z1opG3 en/J7ufrfZOtzajQvq8r6uVpT0D93Hm7/8fzpiAuFzMUeWApcmdFjc3RqXG/eXaDsjCdfvRa5NxP ac8hfPzWkB7H8jGjDloAmYdA/fhaPUxgn+oD9cwvGu46ISoRRJcso2zbk+fTZNm82pTb0LgZ3nF1 zxKHOzxvk/gORRd14/W5Pfplz3T27MPV+jFhEM4zuekgH+512vtOyDfd6AHRaR+Kyt4w0ZjIfKVT UvaGQj18l2EgZL+OjEb0j12FVP04RGQY7ahLRmKyWBING9cfOWr7cav8elLK6nXECpwD+L6J0+cG u7Vzc4c4H/BAu8Cbjff4XNKjTyYMM6AIO8NgN65R00xkyGDInJ96+SAec9O9hERCqnjIOMkcNSYX FP/uq8tzkvJSIjuT/EY+E0NO+CO7n2O8ZYpDnujJ0G2opYnxFN863UtvdGSu5sK+TOzy+cXc2NNj 7G0gTmMs++eOdoLHczXtbTwf7/M+Enesl8YxHv9tiQzmPOwNuTDSicSrfGmUqZQdb45rS6PqPT4b jbi1jQScqPu4pjCsG/IrvHPJqFs26jIS95YnXobqE9fz7mCIl6MpjBpUdJeZPMnoWMMu5qgQNe0H 2e+7Me6McyEwJaZnTT9U6j1ya6tHDCZLAFUdiI4+o4ROcw45juPBK0YykRgtSPsDP3/8YJ/TBL/b TXu5A62evIVaOnJxLTqOeubUw4JSgI2FVrBJrYaYwHhQD1sNOi3PoTXXHg+Aj1C+PkUe4mGV+hEG qk4Wbnag6gbQw3menuV2XeWr8lF+8qOfyr//+/+u/PSr7cG6NpRHkdmbaKkLKnf0NjTugRqWWqbh BE/rvt367B7dd59/I6evfiI/+/oX8t/98S/k++s3NpHn+rX0R7Ow2bIdWK/XVyv5YErdlPJps4gd gdrGp5MMoWso4Kvh1c2q1i4Bt8UVjdakKSR3uxdkWZHnN4pv5yXwPWEqMflm4ghbCyUchqGs4W2u qZgnqmdP7m35UrgnNcmA1ff1sniIJSM8aZxTGOb7w5Pvlcsi9aF9V8WK5ap8KEFREbDrNs6zGnFG WThZ9qmYsU2y6AS0qoB8PgouosOF4T6narXbVpc7HAIzHN15guGneyraSfkaTIDflX+lpFdct/k8 M1DiRWw1g0vDqoYiTzhQV7gBl+7cw+36Z6vZxM2DbhkL6lq+6Y1qXzGb9RQe6lAqYy5d1Qg93z1i 1kOhl8M6hGFKmSjinCpPmuB12kEZtx4UHWafmnxpgeSp2npZbarqCCXIhI5yEAnuNm/dMt/QCLt7 ZxL999oHcltSWCsoxdvvzt3XgO5/Kk8kfSDaNRsgDlGGMSauF+05PVhuhww5LGNv1JL6J3aW5hyK 2vZaQ/X5Tmy7iyNw4K9iLZKMpZIPA83xHRQG4zISYdLLsh+tkjadvITAVCaSFNeXb3mBYSS0o5Hb 3IB+x+CVt/t4pawUTPaUWv+JSMzZFxGijkNMs9V7CrfmzyM7FUiXIcS+R1SvT15PjboxFwCmPkBS Qt0ZdcZjEjh5TMZ47xnFn4I8YS8GOLhWid8WTmxENYBYFTd8ms8vDRF7f8JqWqwkGZoMSbNYa+hj Rq3aWyQurxkdkPx+NjICvW6oVbh2kkXy/hi0GLvmOhC5Y3IbEdgvJSXkMVCfhSHWMy/OjTdxu/Xo PEmWnXyPkXSUDS1xR6149YBqfcSb8/ZR+YIJDnRPcIYy44Q2yP6ZiV6uca/xOxhJru8myrGX6fez E9EQccQV8lc7wZMVnYSsHBhQcPHs/9DvBupsds31RU5a3WCzMc7PTwYM6J8X+c5rvhYkv65w3g19 qyhRRad63i1WcQWQDf7JIW0PlVrKMAvaCSzOsHzdoABRZljYWeGFl7PgMNVCtNrBXo2mx+MsT5eL /N5mlX44VzndX7eD82aZf4vVo1scAreiE6JV2PUoOmuC29y9G4NshtxjMyru8uFHZ2mP76Rt19as 2ovVHdIitZtJWFFz7rcvJ7k8nUzAxWD6TYncXnAAa6FWTa5QLuD9bvwqFRwNK4Njo4kOMPDua/eC wxWf02esWsl5hpD3HmHVzI1DsWOdv1PUNhILa0AQtOgqyohUZDLVsRlUeBZnnxCe1xBa94Mc6c6P tE+GIcCNqp0mwrhLSiMOJM+A0fdGmCN54uUqF80mXbVG3xXy/HQ2r+Sb7z/Lpw8/RgJChcckptwm OywtY6eUqD1IgrMmULTNQj6ffXO6ojXUy0NUZkSpVK3VqoG3zVjSfqdqWBdHpxQ51qLC1RUXDogl lMhi9c8eJo/zqVrdu+Lonk3FZnRq4d8ftvXWhBcdl47v+enjJhcqB6/W9m2iRzST5wCPC39Xd4Ak 5q7KXjnb1jvwaUKZy1Dc+A77cLohR2MJXxQCDkBhBPtLksz4Ve3jptiwb1W2LBRcgN8WuPVeHgeH he1y/093xa0lNuzZ7aCdzOHDFfxOKxU2jQMoWaUazI1cOx1oE7YgChnsg0eVDYd8KLxBDFqu3u7J RFM6AMdu8KQYdy79flaBnwZMh3PR3fDkC86XE5ZlTxTPn7ERFBmH+1QDGcsIWn4hwaOmMfR0vZCi Ydjzc3GIrrsD6egAvJkvk4N0yGbHwPb8urvWkWwfjcK7FXzarQ11iCHrVpZmCSPOUIfHyOgmIvde FwcgdYf2Q0VGJmiES986nOIMJ0o/6BqDA2Xc1969Hp592/848XzFfO7n0Ne4S+jjMHCK7PoB2/O1 PUI7nGnQEY5rwrnOc5h1A8PD4VB1rAMcoL67zrEaQdyHPl5rcT4d/7TCELpz4Shj8Gr2ay2DG5/l 7K1BPeYFu7Hu3pOS15C6voYNsXqyQsEkhV5hgDxfj0Xs+PzvGaZGIXh3hNlZ8bHQiJOJChcUjMga TbqK91ubJwniXB60CLFzTcuWSUW5keflYa0+xWyF2T3YkWNQCOw06CjyYed1O/zQZgLK3oihDfwY ux+zjKw+FwQCLT3AJ+nakH4BAlTaCZ6+Ha+D6wDlmJSRmZbwztrm+a+vqtwemyW6feB0lh8+fye/ /vbvzVs/nT7KxYguipbcPRbsD6OyNCFzVesynUuP9y/bhGkFFCuxUK6G1j0MXTlho3l5iFU2w0Oz DRUVsvQpgyXcUtfN9wNaTxWkJK8AxoLQXdsnm59Js3U3JaUhKTUEGM5oj1vwNhgyOXuygx6Mj82g LF6wslhIcjV0Ul+aNKGGDTaFvr9YMkCEV7ZnnvowCLspwmaZndpvysvX+DrUIITicBIzhJYGAWUW jX5WkxRUICPtf0Vo0J5D1z6R5a0orYbDdWLqk8zb8/74dJGX6/dWkPk+T06u3byObY2nWT0N1Q4N vA0NX2v4TkehhusDin66VMtk08QCHGTI3utaimbG2C2aN1czVKq1b3MGod5Q2wWpsG9js43vJao2 W3wbR5dbLSiRpuF8I6Zetu++bh+6w1i0w2nziKaP2xzf5To/Q25uq0w/UUPzul1oG/cJofNl6Tb2 aXuui4aGF3ialZmf0zhsmVWo872WKJWdjDVklSlKMqeOAKgDxU4dUPCTtB0ROD7r6BFRQbzRvUZW ifCJaBhZ+WeapaWke0PEJneSioU+6dcXr06u8KN1Tm7gbbRNTh/afkvrK4UCnHZ/K9+1e8Fh735t 4NvJZHCxjhg0WKvvserox8gMtf+OWko+n7BaiZ/1QJKRKa4Fi0tk8TIioMapORcr64QBjTaepCUo +eekeuLMCF9UNzwR6u/Chx5Kf9T9EnLzVJe50Za5cEBRGubV11FD/Zq1PNXqzyx+KBRf6z06Zvqn gzlb/bnD4PVWdIW1Ckml4phbPxiKYokdlKN1gRMINExvDFqJod4TjPFmdApH05wrabhrRZ/YtUF/ sWwUDUPti8o6aOogvr6+Btr2sjmEhsLMCAXaWWl1v/GURKlQMNmFzrPASakIBLggwlHrtNsneMYa 8yv+t6IcxmHUqge+H7t/NiguXO8qgRZqpEEP36leYl2sn05x466PcJ7ROUI3v33RcLL91UZxWjgF 6mw1n6sJ4GJz/mxwLMXP6iIUUPLU7fp+Fq1CzmnjjpLBTUWSkkO7CM0CT4ruPjgH+T1kWGKOJ3Dr CvYs905G+6r1vR60mu4Ru04+YSEaDS6z7Q3Nno+VEhixAt0myWExQMZ0BjpeYFycW+qPCU+z4jqM dhlNQp20yV0A1WEqO9w75w4AACAASURBVLYOzbjTkxv22s3HuNcF/Ei9sporjwXzbjQdPc+qlc9A QMbnSKt86A55ud9kefks1+enADLsmR9LODp6rhfX54by+trqOs57D495GfTKBiw3FFTFZ1ggs/M7 OYY/vgO3E++9C6EWsaKNauxomYpf/epX8stf/oX84vIiP/v0UT59et4O9Gkz6CZr5m7C5MKvG2PV oq3ViwTyOTrIwZYVvgIpuMxQ1NPkBOMVC3I3NAjP3gtDV8xCcrJxcEiLZyJ6VfUuxp2yTJeC92yz JU/bSGPiPAqiETJqA52mJzvQrOK/LTs4Jobo6Ca7v+JwcUGHcTiawTc3lnlYrqwMHVyitmtjE2vr ihCte5rcqCCyJ6gGdkcGD0IKuUWIe7AVBZ9fXzaB++FV+vUmj9fvDF39tCm1c3d0Um28uey8oibD cxw1nSb3rhuUaekHmZGkCOAJFVfOuAaeWTNQNZTaHpNzGt1JsV6ezukQeFEaktWsyUmNsIVzufcS d5W0O5HP0SmDytgCPxU2m12H6DSvU0p49jTsGa7Bw/Ev1HgzpVkSOpdQgcnDPsiCS7uvOHpZBvwv jl7sb9K9qGS8M7xofiRCJKsQU7TPkN/lhH8YYEsg7tUPDNQ4ZHgjIfUNc9jj3qmgbx8HXkbe8GwH pNLl9vgiylUc2e6S+G34BP7PfeIHnyG9FesP53PPrYmisSXruDF3x5+/hEoQTXoPHbDnclQlDhzu u/r2YXt8Np7sze85l4Vo/NreHSPeGFfIqNtxfm2cRyI7Z9e/szzW4ALXOu6HuZzju5xbhlZpzKHe 28iSLRkF6UCKpSPLXQIBSXPgBtzxOfi0pLPk9W0NY0U5mQXtxbpfWPZhZdVpOypFKs67Q7X4nB6W 54YPoy6vFa9vtMcDutXfrkNxR4Ot2kImNAlg5bPZ07rTwWQ4/FzIg99hUq7PqjuDwuxdxhXIGUTJ neqomAfNxZfD0TJ26tnvhdXldqwJUdYiNHc7vZZa3ChrPmuuOSzjFmhZhI6rF/0ucJKYXsbkBlO7 IoFegiLRXU/A6ETLPdgR4Bx6vMvv1wqRXRl84ErDWAxQsG/aMFcDxkzX+h4w/bxqsijOUe06pTaA JupZndx52iU0sJwP95z9XcGBniPsEwJEr8N5IQeVwCKgauGWBk6Tkeb9u86ZDqu7+yGFyfFrpVCr hdetj+NJrtsh+tvf/Fp+/bd/Iz/6aZXTVx/lXK7b3Dxg7deHZwciXGtVu89MQYbg4UAb3sZaFjeI gAbZpl2935xVVNb37w5PumJCBUjfYUmJV8LMzRBIhEnucVjRCESJBcydjs/CBEJDim2RCE3fXHks sQ5MfVbEbCGHor+F1m2T9SmUYEeBJj+YHdqtq5UwwO8krkXBaKjEK86tHiiHdhxo3etkTRE6ykpJ V/tFeYKbs/7y7VVe/v47uf/2t/K4XeXjjz5J3wzQi/wIwl7Q4iYfQpCPFkpg8nA3ECcJWSxp8zfX 0iDalvCggtfhUK2O3GZzdaC/Y43WBzJTLVFCgMiqwbe5RTJr1nFDqMW4QTROvLsAEyVIULdoqSY7 rCM8bZ65V93Uw2ctzsXrQ5liiqGEqsP05M7EYUj/p44kmZUHpB/KFspZfI58bUM23GHirQytAdSD Z06tk/IhQ77LVJBNBx4QwlyaQT65123jbC31ROaBQmcHpF69nGZtqRKzMHKBQhTWhvPkCR2dlX5p bWdsUVricDsYMTSGdv/mz/5fylw2l6LxuX+e7cS6lSQAz8acqFQ6hXsmjPnD/bJc57/5MzNaaQiM w7oxXxHP6ajZ2rsfFrxfAQIgY5/aYeQ2d43Db4RpzalwGgfCcBjL4kjsWwS3h7zk+cyI0e6Ze5JZ t552xpIb5URAjwYj6TjZGcqFbvmznSMVBkOecZ5V+p5FlAR1u0z7uh4MMMEG7wjxkAT8W/WyIRvN yeouagvOjQmkYhgAbexnjbxkI64k+TjKw/Hn/Kq+3l96MXGmHK9XvIhxAScr0wnCd0sGbJEaD9/p pDTMAzmkw0jF5zQaYFTJxh2ZHFF7H/SWlY4YPMdtPM0SBQN8aEmPO7pIox33qyHn9hmOr5QAN8K4 S5QQGO+T+4kFhmmFXhi9jUvYCUTXeN9avS98k6R/fBxE96K4tIcyXafP+KirWxhdhoorKqc0HI1W ChzgyXMMdPS61pkLahGwxx29yZWuNaUuHqzLqtde946Qcs8jOzVvQnEyb2Fdmeyk9Y7FJLTs2UlD QPHd94S109LP12uzl5roQ0CbZnmIXM4KGz+clK8Tc6eFZUVGqGh5X166JY/lbHMGI7P7wQOBwYF6 3hZ5WcEFLOw/qplkHi7Viv2wiBvKhVQU9R0ZY/iutR7TtUa7+OASVavXhlp4xjZxGB1N7FU0X0zQ 5rmH90kOiHUv6F6MV0BoLKWMZ9Vncjiar5nkjgmhGL1DqzxoMxKH51udeB11dFywLbtGkUWDrxfY zaneX0sb4mHCslhNv9fvf2Nkzfmsc3gTckwtY2vyQ9wPwOrijWKIB6TQDTXW8xlGkmen8nkL0MRb Rw03sbAwKn1/OJ2jrROyzRD2Wbzkihr42pVBQ4Fm7Om0a793HeMDCK1F16fqcjU2nF5L+9PCmGHL mDboBuoVt+rJQXt0YHdAesFPoHI9SlRU/zx6oLo4E40tZWR0OprJ+eC7NPyiJEID7kXDyXr61dUT k8S8QvtdQ6mYOIjC4fJ7O3+R+mJ1uJ9GePeyKiXJZMu9c417507E5AWJm3d9SeVbkPhUdgYFficw ymiYutH/HqIFg9IdI7dmaWTGQXdAZ8ZhB+NvqnP6vsSzYq6Hs/reC9eaJfdCHdXd7QNhWJOEDhO5 H66RwuwiERYs/j0W5JVO3Uuwao8+Ud4GEjY4PJwzZOEP/RLOuB06Q3fGfVKUAnO4v95uvg736WkN +b6Gk/Tz2m0FRudsjiiMfj94O1td9Yh6IHCJlzo7VrcwMmE5tuqG2JgPRj8ARvj6uAOj+9o6cpgh sdpfKK+xd4SjuHit78+5DAO5UF7eMfTmUt4YckAR946EeFP5nJ18lJXxPjPlD0hk594gvDJqvLqk 4vwTADWT11bLciEeNgdHFvQTVM6DEaOVIFqiUXnRCxtPJbc76rdByfFsgK5xo9XrO9re2CWFQXca jciRM0t2rG7EJ2dG77BGCREJJ7m68acAw1Kao4iODIt4RYW03gX2RfdkrFUpXs0NTf+MVjtoD614 sP15XBH9saL1m3xbNypfgL46ctl9jWfT/7ssXw0HT8MwX92oNLtH11XLKuWFbcCRRegRyghvZGEb WV9vYXbClfwZqAh/OQRkzO058UN8QStQPUsl9p1l2Ul9jiy8VlBHCuE+CxrGPZfeQ/Bn5fxpcd6O w8U+VYfgn31PWKjVF7ezLlgBB07DAeiu4L3rCuH/gnh677QtLZulOptZBWrxkh/MakPmJee0RIiB IU8+A1sdlfvwVKQPTgWVdo1AO9/3dGiWLODh4JCzuNDweloXzO7f9x0CtFSLctWMcdiBqLLjAzNJ 9f1ngcGtl7lNq1y3CblbL9OHkdzvk9ei0pDENA5IeMvoTVk8rGuImk4dqiWGFxloUdkbQq2AkE9j Glw2yPBpu5eWy1i9eftqrCtdLE2OUQI2+BthHAp6DipC8TC91g1BAu/svYbq3coXXLdNOm0yHPWo CkKjHGdNXnu0R8tGkvEOV6ekcINKGCZ578QYLEPpEN5tPQ5/43WEEQbkrvUWjs3wQEmOHgfrYq3G pjcHOJTqYvQEIMUYVPYm/eIywjLViekPdwKKVxoH8yQ/nxmlrXsYmB7/UNrMFNQ2fwx75DhBPsjC SE6/44FhRk8f76/0WxNiISSOd+e/CZwudm/I1zwexEd9CAMmceRkn/m3W8PD64j2ce9knY195A7w 8XlpOOwMiSGPREKO98xdGtjnNYc985hbQlLyOvB+CAOVQAIoZziogDKo4Ubuj7bt09fLy+fR87Tm GqN0aikT3cuX1OA1whFKOoMGvdNORh05fMMMVIuKkFUoIl66xHpiF/+eG5wZibMzZia3D2WOaGy+ pzOELdSSUxD6Ien3o3wc5/Y436XIbkzvydR78inem7mnPYHPTX5ROiqjXI/O58LPOr2qtHV3j2Zc Pe+YIMu4bzgx607W+EvrfCB+3giqYWBwdV8E2PUWkOiGcKUwnO+0Aw8VR4Jqnh8PidrzFXCTmYCC F5DJyudaCVB1nCELOo8o0kbwhfcw2dZWlJ6oYwmBm44/ac3S2Y01/zx6dztgNNOYltDF0vcROHJI Q8dtczzn5rM2aHYd6ETb0tyHMAwypBGiY4I8Xt6gpMHneZuuHKVHTCCaw8EQpNXgxBUQiD5I0wav DIlUywZcnc+hxHn1uCzM5BNjCFg8dAUK0FGSQo21tXjvgorCltVCSxCkhwN63TezmY62OaqnqOOY bN4YTQ8cpcU3lqGweQIpGmFlRzVcbgsVovOxsGHOvmiPYYuZ4cr6Ytc072mTYKjb+C/S2uo60lvx FISxTOlWL1hqXijHOAROKBB9/B7nZRFmBoHCNLLewpgzA9Er0JuB+3CPVRWiZhRfbY1YMT34lIKx IlU81YNSgqgamxOyeytPV4415iHxRFZkYKJ0BjiMxpXTUJ42ASnwlspmuGnD+9Ku1katNK0Yv26O ARI3xL+jHJK7omwa4isoJo2G70Cg+MJaIXyhKCoOa99HRcZh4GgAkZRogeae8MOMTCr6wSmT7oiC pOKv7gBwDkrr8kbrH+aKpTWw8CN7c3WFVGeGlzyxQH+v9Y3qII+jfQ3ut7BOlCQPOymaeBUeflyr YTiChsYDbjiQQDXdKAyHI6YDWMHOYekgzUtCITz1XmjmHYwKu1dS5hxToFusK+Ycn6yc2bLsdx2q X3qNz04yeEXeG5r8Ytk7cqQOQFYSiuDJJ7vnSnuC72WHIagaSYZ376d55fMHUqfropn/MpAnPg8z 1r9kyI15p7yQ3D5Cp4FSHYwPjs+MzdbehCpBGRooJ0rLOKUmDlx3bHltdeCVvuMx6LGf8gEuMqIW 45mIaAE5HLy3YWx6GD7XbnzHSPYfdu8F0iPe0zSMwOEQjS+ALmJ7otdApqXwGZwnqz8da4iN2cIf Qv8xjurn+H68ud6k/nbi+ALpLm4wuXHsaL0PgoeXOfaYSy/aztFkG6EjgtGZdNNpRwA5DABFUJtN 3189sWl1/SHrnuNHkMDNf9gJir4ZzjSAFCCt4MHryb0uqzu57HCxWMRA+52i7/FqlQp2Dq+f+ewc tIrzt5NcmxxJiSLxkUXex5zr0ml3qCgYX6sXv/ezWud73RyI2LxRAqBKbpWhxkT8jrRF58XQgs9e JoUsuGTNlWoWjNR70bJ02myIVCEnJ5GcDaqthM73Crw0LxhMhENDacW3sFmEMAK50WzZ3eCyrg9s wl6w6Uc1bg9GJY/OBMdRKWRoYpMsBQq4FNR8Qoaoz11BVkkuE8FYuCGKzlWxYhkpRh+hSuUNaG01 8VZGrJMWJjQOR2bQWZ2a4uUdiv/HLcij94+/BYcyn+90Hp6ykyptS/qc2Rx11vrjvM4guWsLXF0n bUV1wuZSr/PcELdnZiDg72pQu2X8WBb0ZLXJgHogOw9I6kAOwMGDoWZcIR7IdvAvHqZCxqtuMF2D 2/b3h2mbneVqhpxet95vMt2u23u37VqL8THFEhualbmwqLheY9aCvrNXvB8cMg3XZqcne7dAGHyN zACs5o26xNpa8Pi2Z5IWh6pxflzp0eOkscXQKIqISsipPmvUu2Jrl+6GHfflUYcXkBpobM7kXvQa zhuNAtRNdFn0AyXMowit1RC1PBdUlwOpgzwhyZ0GLRBuK+zcIC+GLJUSaEo+7NDrcs+pymjee0YV uyrEZ33/2lKaMqeChGyZnILsOJIAkoFUAArs738YT36hQLkE/UI4f0RFO+QaCEdFRfruR7S136HH DcW9ktLk+4LJLSQ9l069kIy6ksJ0/vANgx2uRjqEigwjjkZIRniygRdhRHFDMKElO+QnyfSu3NT2 ut1ucQ/9eeeEqGP3qDHO2GsFBkppB8OPfeR26+HBVo/sFEDzQqQTCzoWlg5XiaQqGjb7yBONtTw3 kozMo2zgM/GPd+VFX6ioMH4Px2u1vVK97iSzVY1/6zxoRjCk8d75qnCY2Ipu/9qPMbJE/Xd0jmze ZSf+Ft6zMS8o5t1ZDw0Yp9eWlDAu7d6VBdJn6SkCtDOYXQatlGehsd0DXPF+Iq6PEHqlDd6d8lGc B617evW+qlgjaGEE1bzAtAAx0zCoRWEK+G/LCGAIM/I7jbdEAcvOCB/E+KjqJC8wzohA5/2THRgg gQPRNDtB9s6MGXuejFW8Y8XcPU3V3hRyDigEwazZLbLEcmLmsWe8GF73ciMUDid27wVneLIFrCgU nfSMNk3V1poq6K34sDlRixktcpj95/0djfwPlEgLTqKehVjYB0bg7HC6Q3ENimuq3oNNehh+Vr+t gXcVZPLOpA0aMYBiq1vMD89+Ja+suxGxCz04YoLnlaiNZZ6lwakM8SWPb9usJkQaSjCCuAuqkfen UBiinUkL+/fNY9MJ6vlVOYVQ9FBIu20YhODaaWh6fzzzaFbXC4DYSRZeLCwJI1Dn3wKoXoRRN4D1 Lt2W/eTzNXcgVSu9/84Mosk7OnimZ5doecMxB0pTuNNdBh11aZ6JaTxA68k4h7GjlfSsTMJ6FYXB ZTPi+mbEyfKqsc5tPGdrQN5Hw0xTFFZE2J49NVWuQ1mzTAfPC8LfkFlHjVW5lLrbqGq4Wop+hGQk DIeBaDnioKVnllXyIUGHI4e3SLrNh5n93d5ByNKz2CGeEpDyAcxjbZDW10B7aETiz+DO1KkOzg8V kSUT7cNLOWQB+icSj9hIurohlx2o/Hrv4HvvZd+dwB+xAsQ0blwHIH9p8ubVYjIY3/Visru+0lS2 aUy7+X7n/tSlpjOm/bMcnw2e9t5R3TnEAywfc8nrpPsmcGVvnB3ufUS84ndtX3Q3nKh3nlFDoYww 2Gel7Z+J9cuEmb25xyjuqaFUvY7ufxp05Mkh2clJ/cmAO875znlwOdZ9tezCC2OtbMwxJ31/jVjj CUXgE9qXv//en6MRx+uNP4dx92Ek5DHQ6WVi29A7XoeR69/AG1ZeQGP9VhWblYi0xPMFT0O8UoI7 cnZ9N4hjbJ2oJ78LPZ7nyN72EJeW+rKQK3l64p0LeJ4VrqFItLjT8a0JsEmvsdbQPQArwD9X4xkG 7UDUeh9Z6si8xnOyNuFIfgRwRPqVlvWy+yvgs94tTKo2iSUhhCzT8emR1U0n9uTgQbcG98mIW0fI nbIQPDcZ8g05dfBJ1zvq7o55YOKMcZnnOSIz1h1IQ/lF7lhA/ZAO7LGafldkxOrU2PEs1st0tUxI NGgFcnTaFumBHqYNKBcqxg9UbzXr3Ce3iRc4BpfLskUt9XaWVRXcDOajhnMmRcpUkSoSZQXPmt3P iPL6jGoNbxPysMNuHk1gHRqtXnndlMYJA9DCpIXhkO05zOOpUDxmqIlXQnYYzuD+uu9vKF6ShO9p 2E2TAyxk7uhtZehUs2rbyReKHgTqMJmudmEzhblKcM2I2Il9j3XFPPTrXhnqS8HoOCUoViyjFAIG quo9DGjjlqwtDAONwettZ4Y4FqJCHgLW9yw8yuzJHp6TJSKYgaoewRmcs+062obNardaYkCVD5sx ehcNG8K6Azn4jo3oc4xIeWFtRpcd79urisCzI8Wrdut4lyJ+2C9We06VFj5y9mboD/mweUGP22d5 fP5O1sfLdtG7nG53+fjyYpv4hycNVj4s/G/pM2qcaDZRA7FeC/7cH9sMni6mNGav7qlzeKnK+qve R7cZb1IPjEmLPz802WM1g2a530N2WOSUlalwrMzuszqiRD6Nr4PVC7I6YpCvCF95yv0j0IUyXFkq wUmzbPvg15nSxlqyQvtq6Bq84yglY2HXxYz7M1bdS41QwMU7nHidKL3WiifQjHVLBHFFM9Ex9Gv0 gzFgbse6oAWYcdFG9uDJeSscOwpZY2/SeAWA5yR56c5JcpRIBgJl8w5fKpAq0wnbYlWrceeFnjtQ YyrZlfMt42DBQUlDYITAhzE10NfuCKwko2WAMX6I2T/Q+9OKg5eBrNmB1xgCltBNxa8D8j/QE+25 aAh6ZPAOY3sYYcPIMl3kIU2Ge45GaZRl8L3fnbspbpDY+45InGZPAmleVNvGN5vz7Qm/5uAu62ao FZTuUHnWkgrkxXGP/PADaneaatZHmlxm6eQ0R/SUurE+nLtKI6ojvLYzDGiQ0EHAa6re9L1QZ/vM FRjQoEI5mup1UgulSI27Co6TPid+dlko+BOIWa2OCtMwHskZlfI5TG98xuqCncIIAieN965RfYHn Tk4Ao3ztja5sLK0Bl1tLT0co8XyTeQyTUZUwr/bMTCRMBsiaOJ7odb0Mx9E6GDwcJSyWKILonlgE pHoh9O58Xe8/b/Iz9ASdzHBfvEPEoDyRMJId/uyA5Bed7QZ70PS1JRio3t8MOKXXTM6Rt4hMJeIN uUQXBbsS+G7beO8NbSPFbB+xqE5T4KChCoIlvjXv4rA6T3YdHWTUHtKIDAorkAMo1ofcKEb68/Yd ODpEFKFXL9vZN48eX4NoXCSRLRvKZZjCF+dpsBifEsh9oeHIub1bQDrnYALdTlbt8ZWhRYxlr1Ti IOCCuqHxxos8XCcvJEMLHf+Izxw9p3wdhoO4gGZMhSfpvAzJGyWuIIRQKTxZ0I73IheHXgkTHRBa esejE3AKqheRjYbYZawfYN5TzKe9mNknSNrI40Zpzr2XObzUkTkbiSg+XuX45VIBWqSwWTNfGDCV YYgYO1FJcLJqg3c9CYz+mCdFR7XFWYEnAh6X0NyxcTyd0CngLqO12Fl/XgF7Ly9X6S/boXF7MS5c v28/v74CCS3bwfE0mcJfOjI8rT8uCDt2sGnXBwuRriM8wTWy4s5T2ckRs65MbmQvf4TSLYM1jPW2 k9njnkASQwmuTEZ4cw9WSV5flkMiEqwsT6OGaNcId8DIWgO16Y5gVS/3UuCUrYujBy3Q6IwOGRrg tak6kcsub5RrTeM8Im1Z/iYZvCKTpWTYybpHmOz+lngx9EGOJcDH2c8xPznm2h0Lp0HAoYe53Rli E1TR9qMr0DBTL13cqHKUsoXQePkb14uhk4isoIVZkzXpB0YQ9vorIxd3hqvb4NOxNyjmI4VsKhzr MV7fT40ZrsMPwM/dCpeKZ/wRLbCepIn+Ab1Ms9Iz/BxtrvZcHaEtdfisUbgiD2dr21gTun1EOdWo y/pyTWeHOg8qGxoJaaSE0FAb1m5AXejnPfmvnLNsa+3OY6uR7ep3ECKptrcaUc99hYVom2iHcJEk bqHzItzs8rY7oxIqPfbDkMyVxnLe00mE89l2NOLsKums2p+lMUigzcV5alOLsmCmk1mD0+XBtHLj WtOgTQ6O1ZKqyNg0WZxDzjJHjWsAh0uQBAFJwu/Y5s4nu3kUzMLBK8arhqxWlsiJC9S9KOvlfa7T 762URxttK7XTkEmWyRGMOE2Ks6RkA9SgF1rq+sMez3rmaaefWRFbb4VpfH11piwz9R4yPdk52eW+ rIhZcg97SMB0Xa0xTvywfW6FEW0UGAtBuiOY6kfO2XjDQVqi6WzhomD+KDY4XPUhChK0MSDn+vjn Vldi5z4EgtexiXYiItgOY/BGok8K/0hkNk/MjTgjbfdUwT1t+HimjgyqWgbKZdfN2uqdV75GOr1N cNacYdTw7PR0hmDDA9c6QkcPN28iHKwtiqpmIdc/d8sWdEUwcRJrKAszPJoEShLKsODZ8yHFew8j ZBCLQ3jUU0lIBWYAwbWIyafDF9XX94Rj2zinU7TMUa5dfKZjhmLD4ZYWymrVE2sMoUQHBvCyYERa VpBNNsjDc4Nnqte0+lkaQlcoXL1+q3Z9k3K7yum2eUWfr5vG/0G0jUe73rTZgrTnk7x2VN1uFnjV PrzN+qEWT/jR0GjzlmqLyW+JsKq+rLq2o8r0mNk8u7f9OnPOadTCSKletkPC2yT/hMY2Mk+h5Gy3 FFbz36MmR9myrxIFKNXb6PDwgHJCeNydG7bdcz5nXFMk8Z5gVBjCRp4MDw4zgiCQjXSFOozuHaGi 4MAn0mP3csXJEILJT3djahllTUpPiq6M6w3HLRHZ1/0aSCeK5WO3LZXXpnnYwxONPFkG92O/S0Qi uEPE96BEs3HqDjU6c6HtoeeOThxePOSyoT6l53rrpFoJnIbD1ea4gu9rV+vM3HS5avsog82lM11y +6g8LuNdRlISXPzV8Y9q5X3CQ/c1qDZfumeMkqFIzgyZWe6gnpzmZzmfn7ax6U1H661sZBBNVSfK gIbIqoXzqs7doz9wuNvzA/nfGXGMK/eUOFCzDsT5wbNJdi2qkkXrayKH+cG6k6/mBmScKw501VG7 DfVExTof8HnnRDMKZ9f/ZUhemtv8AjdzlDfqkosuj7PAwn6l7Nr6SZxXLiuF1xuGo+2SbGBzVg5O RD08X8jqhDNq6kzmK7HvWkS+BJEZPAr2SSnQH24nIGGuYc70PT8iwZPDXNr3Oe3GWVut2xEBhyXt mbUh45WgSa83nG6rZ97b3MwWhZkC0QbFBlMHYEWpV1paS+VwKYjS6LxbDdLN+bhrE/v7w1pSKgDh MLQs7Wr8wZgrTzZDqPQ0kFsmVa2zdTgqK+hUithPZeh+nYfZCP8JyVr95Ogy2t3QUOMfUxTWDkVR lOIhKAaJMPm2uY2wLG9eEbt+x4Aam7m9EZaSypUchZoWeE7H5YQQgbD+egeUIh9W8TN+ic/IQALs wN4+h9parOs2njmPJeazD886vJWMRpbiHuQYh/3JmyVtkKi23YcXF8auE7OxKQFXM5UfYwIxvrvB qZlC0ztjNooFsY38GwAAIABJREFUUc/CWkvjsEb4ZWwM5UKx0KX+vfi8f/782f6eLSQ+7jOMOSer Fz9MJ7a16ebttGXvZZr3MY1Dvs4Xh+ZhlGB8DUbV7SbLD58NgTu/vEj/7bdS7p/NYzpr+OyyCfF9 W88PnxxJrQgFdCZOIPlCjZHVD+xcn65XHG7VlS0z9jCGGrJltf4O2X5ZVvN77+0DEvOBnB3QWP9K y98fvsRu7vLvoRy9irqgFpH0kUCxv14RhBj5z+ooJsYUSTtdqCpwHnZx4m+o/3f27jt9I2kkaw25 zctdF6h9M6RKCSMv5mwa++Yox5TZ42uP/HAPdWF2ffFDiWuZjTggqcq18gLaNEKJHHCdhboI4zmW EMp66mh8mzR6OR6EJt8iLLGu4hnLnWPuEj2qeAjGfdxId2MWf8SzAIfzm19whPc609qvNW94P1GZ DyNaaSt8Xuutuw5enOpQy/DDrANhd+Qky0YY8VaioUUrQgs7aacHUj9o+FfqFg50IKM0Po8vHPzO 4/JY+9DDBfVAaZTrs1K/pHU0x43VCoq7gl4GJa9rGE3Va0d6GGQifeBQ/scrsHnbLwmawBGRo5Ml /qzF1xgVILqgeJMj3zJkf8gRz0GXO6UhFTeYqHNk6KDj96W8fY+oPbZyB7JHGpSU0ONEoWtIw0gU KL4Wlb2fdb+5U7y6XrTfp9ImOkhLwluBrPV1DWPR+og7WGJ6Lp47g1UAZKB/ZvBp19EFyfaC0wP0 rkuv7sxVcxZXL0D/2Ib8em9yvT7kaZPdj8/bM27GHJxR3Q9LnBf3tjiYcpKzzler6LIh4IlfTjqO 07aeZzuL8Ue8BBKeYbZWIbWODBAKaKzyHh3Sz18uFyNs68+vp0WKtsPSkOyCcgnWEaEDVP9Sc9ns dWWbhjXY3giLpEl39IAOVL4mFem7302f0dd7B+jxMMgeBhVN9jimMr25Ljev/ivCotmI69mzHvfg dR9JqRmwIaOaNz2U5qGaCFklUvYgpW5Ccicpt+7anODPFGHQ3bxNNfXge/v8xZNVrE1I8GDweVXS 6/bnu+tV/uLP/lz+q//in4NflLLIwO2YLOQ5zzgUxKtmr/FsCGnqZxc/xJQfoOHLyK6cvOZexSZs qMQYTdybJjG8bh7Ry2bMff5eyvV7g8pN4c9n2+T93qwkCjhhUDpWJlQP9YTi7EPozu0qGOvEVinJ aYDX3U0xgAVXhSWPsmExTcMYDrnpKdQvDH/51nSyDbtEsM5SNgreQ+Py71h+gDW0rMaeH7JZRkUI ZIwyPFZ01ffs6v/G+yKRQ5idmFxH7J26khkloVU6KAxAKFfpXziGv2y8xX5ce3RsGHKPBAwYZG4M JWSm0hjR7xbuXyCtXKNVnEytBcizMVqQnGOHjBU8LW/GuOctkV+0d1rNiFDZf9x3nz8i4RYKDdnw 6IMZpNhTVQZ537qcHBxdH7R9Jzub/NMOJTLs/s5vsvMg8aOQgKV79RHE/KslGvHsAMNyaSg/ZNni 9RIJQTskx+dLdcxdUZUl1UGsfvBZljuZUTazwqgBkMPBq4Lf6kYXEbs4PdA+an/uwIDXtorW+moF Fj5oPqtzeFkcFmicWFEgGh76mnayCcNEYBT6voEnmtbUjcPeBz0jstBDvukUzPLea+zfvSH5xoiT 4XTaeoe3Rn8QoAEdxjgPonB/2WXS0lj3+lDGMy0FoWw+C5z17oXs3Tnva4Sa4c87p7KDd+fJxf57 zucas1xIwTIDDkYco3U409zhbhMoQ1Z8fvayVpa/Z+x/M4zcgYhC4mqYd8iYRRirU8zMAJ89MxZ7 3ZA8fd84+ZNcb6toT/un+WTJEtYqyzo+QQc1bRmll1Ha0/Rk1CDommI5Ak/PT84ZPQEMsQ0weW5B RTh3nkbMO79KH2i0YBvIWYl7JxQzPJ0utrlOCms/0PfrdrvLctfWWHdv+izvat7wprNFvBO8Jrlh bRZMG2vxEFDvu0MiCyiNjmjhgjf3xmMSvGPYNn+G3qI+o77O54v9rc8NUuLei41NW4dHwuvF4Vx4 7z1Xbu17o1Jfg7c3UuAHilCGYtBrGuHzcGhXb+Qdmaaxx7BJnTjPKBoMBobI226OUDtuP49ECsyj fjzCcFUk7r485JnPinxboH/Oq4QShANhma62UxdrFq59CNe0Lib/loGKEIuUh20W/a4WDVZ0WJbq tetWS5CxTgRaeFHrXClirOOfEOpt1tSYholyIapx9CY7nKqxnR5pKWa2hYFl4UbaakZcDtXjWZHt nNc25OxLBsfuNSC1+H2SH/05o6xHQ23siRoH9Hv8GPA4FoSM6ztG1h43DiI91Sc7oEzCxJTuldbd q4WIRlmao6FIORup9UacsmezArDT7JXLOx15/xkHYEaE+fy15H3dR1ZdYWY0PH07nCqb3fN5xJAf ta2QacxAyt7wGQkXQBPy7/RRMT+6OCA7QzaoA0oSgbeGO3+J+mh9GPA2vtShwQfSGLJ19Hz171bW Q+Nc6z5dMCe4ftmVC+K+pc6Ag713TCTCkdBJd7knedt/Vh0u3RtmpFnS0GJzrRmoyps1UyAh0sd5 0M9dNyP2flvcgOM893BcayeCnPVElYCGC+c4G797/W73LaMjBPigbFVWhhyV8UekjJ1R0hz3UbbK 9oL/jkiYfS4MSPBqB2ccm6UXGlV754QdPTi/WKuMNGd+rYfXU+jtPSOOkt99rUsRry05aBfF4fWQ 9OIF5U2w227uOZfmulbUNbN1cgfdtm+Dk86IEiMMu3HKvtOHOtSsJdsa5694RjnqyKkszS6vUbvP Wu2yDI5zRUH2Q/kaL7G0rmpQmVc7WqgVyI9xheMR/ftWVUHSurvRrXuHQFcTC6tqhYx5sxlOJ5Rh yZzXiZGczcGZnHakyWg4jybrpYo/JyT2VQAZVpJLqQmbPTbnQcQGsDd9UzUsgF2wK5+hyIcJFqfy ha4NxszL61W+f/lBfvjhB7luTxxFTBPahfOyiyfDDRHqa3gkuaCq7BSM86Ns7Uoope5etFA40mYR F5qsHITKiN/vbz3Q97x6ChO81rcG37tIQNu/l404fp6cNDOE0nfzZoORhIMQplA6iPN9U4p49vRZ 8sUOdBmHKWFZW3efnzWFC8B56kkxe8aeK3tLdxaxEiMyjbpSqqDPMwylh6eQMwure9N6hElWC7eY YBt3CuFqOw4q6iXdX1dsvNojY8jSzp1LVoXGpRdc1E9p2ZfVM60e24Z+NKArOl2Lt0AxhE8wbvW6 rHm1ZkSe7fNPlr5d5DGVyKJFSHe/pgj58ODBWi2PZkWlF8vQG61xQs6yLKT1ygdoyEwfCESXwXFr XIdDuDArartnH0lLxffHLryvmVhrd77c7AYDrS/ZORl2jOocu4Izz7S5XVUy1weIiH2WxPuSxyhR BLy0VF9JoAuWQP9Vxi6QPTeEGOZvhXyc5GC0fTkWyOrI6kQJMU/I8Os5XuNzDuSNnWJ0HUlrzP2Z 8zs8bOGUOhXBkRyUQRA34sSdub1RhlVlLb01kfQduShvE1/y35a4tLSBjCS5MVklYNKzjPJREnew 95BjrhGMn4QCCubN9nJFwVXIEu+aDYZuoajL85OwHA8yFBEepQ7NTjgdQUYljF90h/Nskuu0Dd2o cxkRkbDXdG0nN0AnzhPnCs9TS93LiBkcNfaCgTZEn6oI+wAYEtTH3gQNAZ8/JtahaPP+TGg0GMMY b+MM8+9FLcHkKNQOhGm3p2ORR6uxeMvXMjKmS9n9QQ3E7Kj5evnJWdxJKv4b7vviaFyXvdFo+7wz 16BERi512wQPTvI36WiUkKrmiBecFDipuN7sJZkmKTGnUXvTCsIzdC3BR7OW8KyjOGPNpnrycXk0 yB15ooJ2Hs1LnGtwKvrmSDx8fsCLy7bAPI+WaxbpWok4Qk4V6Lpez3J5umx23Hkz5E52pml7SDov Nq8qrJrZW8F3247OwDgwjiFnZmCeavDi7D071LzxdGgbkUjHZxhPJ/N02d7RlNZtcGIHoSq6Kq/b xH1/fbFBI2yHFkhWEG8dC7Rz6XdCD+XNRUKD8YFiENnAQ9O7ygjV3hBleYB5nt/ch8Tw1kcxvd/l qeiLLWE0xVc/yqxLuz6dsXcMQI6Zv9+NIyE3+d98Lv6ZUhuOOAjDKE2Mow5vcyr7qv7vkam52YoM TlCh99XGHJJYrptDf8+WM5kjCGPiHv+2UgG3qyktnTd7NstAbQh5Nhya3duRdJKBK+F2CAtSuVfL YOvuYaJIcjeDzbKmdJ297Zk+pZH9xXveORl2LuBzVe1zOlUrB2PPUk/wzifA2YriGcK7GmXf2+10 uWyb71p6lGbBvYpbmZO1UlG0UZ8VYaFuBtzqxTm796bN65+N+bxWmSAc8sQDNoWY+LmoMJ5kNqOv tn/f4WJl/lEXhGyro4kirFzucuyfZUgzynekfpfiewrgeAl+mXneFpKkEeIH9jRkMjfFZvHw1gcH bF3HMyFLa6CSfMbMGat93c0hht+DYyreh7FM5PKluk3RqgeGyrKOmk1VjsYy3KF5fhKE7nzvrnwO kPyJZOcX10Fid9o3oQP9WfRwMidIlt365X1se247sMi7nRzVI1Ef/Kj58J1xkNl7lXpLwAE9cPXm eYoDlXOInJ/JEIfzfAkn86hrTLeWbYSbTni6zLZvdA0/f39FYoPLL+WOYVVFMShfdjCvCGdVD3mC x006pJcGEqcCOgLIhJTC8hYHXl/sMbPdPURYS1T2h4M8OI3QGY4MWSRiktHOkLzmHnIQq5ojCR4I zOu4W1ueZ9z7lecDoiVvjTgR0o84xjdOYHrvmJhm4ysMx2f4w5/ZARMf4O6ahNgPoi2RAFOKd2/g nKyW6Z7nY6WjQUOuZ4BjgC3jOfjQ1Z97CrCJn1H9MNk+gu04z4gcqhxPVly4OIf5ZI47s4sfWvLG BL25LoCeezpBJhbTOXomqjz2QKRZw03HiTZZFZzNC+yG0+WMTNfJy8+YATKb42y2lTlq3dHZFj3G J3c4ddxGefP7gP4GvmtTY3Az+OaX+82KwqLQqm9gg8w8tlbhl+j3nrZD+nJ+ltPTs/EbtLisKpnb fZHnF1i6SkDVwduhdlvQU9IFY9TIaZay28xmntEWaQbP57GNB4UIz9ukXOVZPoFPpQeyKx8t3kor FNko8FbYUWH1pt4mHr5IzE4dRmKH567wCxV8d45JMuYeSkTk5gmlA8EAQuPC5cVBxTe09eJrRSZ2 UTpsXAqz9nbtDldbjbeWyjD4htAwtuVdMuPRm75PJ7M+wlgiSmhhgQpSvSIxlk02wbPQcGdv3t3B X+Fdepy1OlSuoXGrE+cFfJYbDtlJUOCzW2u3u1w01Xv7iBbtvmnLqu2zr9ebEUM15K+NVatGNre1 PSuKo/NTxLJ6tG3M+Tzb+pvBoTWlGpTn4i29FFlT3lqdFG7eDMt2gueim1R7pG4b8rpNwXW759kV 4WIZnZP1dn3IXebHTZ6X582Q6/LDNiO37d0Plx/Ly9kTcnRjW2Ha7RA5KxemmVzObds8l2kz5lYL c7RtnKfLZrjdPsipPtDP9zEMBzNMzxeTRyuX0pZQSpzr1Z0VtI8b2b0jtAi0EcZGyvxNSS2sjdaa I5BtdUSpe4ihWrmUae2xvsHzivR0sY6yKi9ItffDw/+HFnh9JyfoRrLaM9iB2b30jCpCb/QO46o5 UlgM8cF+haLVoppsN3Os3g+vGWHuddMry2mV0zR7FnDxaum+v+3vxLnz8GfUNlMZEyQmiCNvPDSs GKr9GwactQ3qk0SbsBUq8HbI+s6haRSiBXpgKsvPQWZMWzcK+NrgFLoxZOAEOU2FnFV9/+wK3UNR 6mWX5yitQZRDpMVxW9SpNqtzj+QyREzCPxArX3cPe4JXdnbjdsjJOKT1vycP28xwxvy6s5X9Oct9 ou4BOmDlQyoOLMjStoe2fasGn+qTrz5+2A6Sj/LQLP/H3Qwu7hudTyaPseyVnotasFyxm8um6856 X0Ur3BFAwk83g1lN5omZtB3uXHMUbfi/RcgVMq5kQ1jZDuTEO8OceaQioVPmJLfiiC0iAkAsXQ76 MLpNVYeTUr2n9z5akssQqV5EPUD/vSZ2Td5b2eV62q1PtQgGxy/p2VFqagIrXecXUM72kdPOkFzR BVWICNvzFXBFrXRYxzMwBD+8DtRsbO6c13AMPNPebbemERK/12lyGbQILIwWRs8iLZJnkZ3F6FRk Z2qtQflCR5s5zmHxmnvKRZxtvz1sL+vnzhUGkPUlTcYrGgtoJYOLzS8y+NH9SA0nfHbT8+qsVZx/ +pmLnXu6Hp4U6ImhBGSWDh27rIguKpdtMV7oHY+nukzHbaW/JqtPaqje6Wyyj85SKO2D/APsT5sf 7RVvo0L5qtNZKW5n7R+eChQ6XBbxbnGlagBcNQ/p+fmyeVVP28H2Acpv+9zrY7FUXbWdXq93eXl5 kZfrD9vgJ2Hz4eHFt8CUB6TtCrVOnnX4toFwXoAjWtZkZMHla3JzIAyWmp1T0aVkAMD9vMEIZw5j K6Ep6TuEoXEvekX0fnqE047PwQb1wTlLG+uN5y4i5F/k57bvJ+Ixn20IKhTMaCLMNRjPlr2Y967D osnNNx1DqpxXKwmy3eZxBRKlfy7bGn58/rAp6TWQIBwsGSGEF9MXhrmhH7pvpmoWivPtpKe5SVwK em7SghvWqUG6F9d8IOGGmYaWfdqAFC8N3EQzGrQ1mGf2qRFZgZDDkHQ1E+hTQzZRtRR/oBnNOZNW escdGev6kJR0ll++h/cHr4ruB0MrVpA6pIDo9KijBNTy4Z9YLUSMdXWuWhnh0/dI7SU4P03Yh7J3 rtsaIfpe9gkS1XknLSGNzJYml1btH9SVo/bt7vgs0Vos2qcl+bTQE+u0rcVD9TMOJSvTNLpV9MKM RJWvSdjLsThyY90YbN3RJzcOrM5yIRUFPs07gTz77jH90MFCjzCUZfWaPM8IwT+dAjWhHkMRbEda PS4y+WHCMhZoN9jtEBloyei5OZATUBZK8vxDqev6bodE1krkfuEAZzgXRn8LVYFoSRijpab77ZGq 6n3Qjd8W6CvCXNZyT4bhbsbVfB6tuEzPPMzZR9HfVZ40S+/1e7vefX1YuJzPn/V6RmcxptlDVCfj rjKrM5Cd0uIM2Ml3Gwbw8T4Adt7qveNezSimvAlb4/3GgrWdKKzz42KPHyArf7U134vjjHcivF65 T4yTqgI0+IFZX4/zDzIxCniPec26/pRkLnRsQeZ1rkc30ElmpwO84Pmg38HZMvQ79VNrb5P6AoWN mwA4MjkXWoHO0w7Hdo8U5r7bUdtOAQL9vPKfZZ+kkxFKdkkAncmdaL88+HCIOmniw6x605OhzHze nA8FklS2EK4tjtxpCywiihO6bSjidoGOUNnFuUt9V82J1uiVlhfRd2ZzZGYz4vT+llizIA5SLTJ0 sntqMeHlcds+32DEYXLdCxAvMxJCIFBCas1uG1ANuQ8fn7bNeDEPS5Xm5aFW51Vu24A/v1zlu+fP cvrhtB1qtzhMbBFXawXrIdq3hld4t4eMzyx0NpzEszsaPPmVjTAUdBxeNK+zO/xlv6GPYYziByqE ZYR1iKSNz1X3zw6vaF3hXgiNNxlKC4dBjd/VKBaaxiWC+lB9NPzNYdkwXPPGseKzUxhwYYTVt2Ue um+6wb1zZdnHU9GTxw4b8XkMFXCv8iOX9vCQ3xwcGhy4OGikONLhzzUxc6yNitZvxudjMPjbQ7TZ SK74og1tFmxsrr2FeZWXY+3CUJ3bQqlai8eroGvW7LR5abPB3g88IjeU8j0VJj89i3pXN/v5hLBs BWlbDS/lhKozcrvfdvNFOcrGPF57cjzdztJvO3keBPCx5kSWd/V87LOzVRRfU/jseH8cfkOR715e RCyHOUaGoO9VN8azHJEsT2VNIy6HSc1YdiS9uRHWQm4nN3S2cd+ATPUTeuuaPon6WOpcPjkKAefP QhV0oqYTSrw0tN+p5uHWyNhUNHqZME+muN1YlKTwy3mOec/POPl32jQMLnZcyYhOcQJyGKKBouA1 OxKWDTTMr8uCl6vI4TDjJ/OAcqS2ZsdYPKtOS6E4MtQeae4VBRPO9SiLMtdxn8mNwQlQTBh4RJV0 7yGMNML5cZ2cSekZuuBx1s25O8s3P/kx2hqVt8YHdRnllAefoSCXk6H2Wd6gDzJaajelDTD0QqLh /C5A4D1nK/9u/IGzDoMNoUX2th57fVQmoKP25prvcFqZTR1joM5TikZqbQVdvfh1bUUwf0VG7VT2 LjeBqLZ3MEl9N0/52WeLOEjsMSvs3fbzAiesRR08rgeLcY+xcx49sceSfdb40xtlVnaywPEUP193 9fv0FeijQC+oRGpygpTguCLpxX/27FjIwhQypIk3+mpWLs0TW6ZTyKHOaXXaCxxJ6KvVUNzFkhWy PGZdi9FOQ2/Pk3GIlRMKfe2t5c6nHQquhpoVolbw4f6KPcWwrV4zO7HbdWYgCnU/8ZIPF2N/h2LT gWh443I6282knu3Au29WxcfrXT5cPpihp9bl7XayTNXwhkwLmIm53c8Vlk5GIt+GceBZG/lwHpt2 oDBBbk3o4dGws4UxJStocJ68q3UdRubwYvbXt8OojYOJCnu/+TP3hXwBGjhE3vKG3fOk2Ckhv2gk xs/ZwxHPjpS3yo+oCzz/Kdo34QjOc+N1pRgO4C0CONlnzhXeNQkq+9LywDHPrD/ker3K5cPveXgE oUiEHobTMObdvdBsNJMX6O83ftuRY/WM1pIQKV7LkSgrc6OG1zT6J2KeBaHvigMQvJkZJOZu6Lhl pc4a/51AcjbmWBulVO43DVk2U6DgIkkYnH/5V38tH56eDemo5pAMozdn/4XCokIuUC6Qv9x/chDp 3+O0wDh1ekDKRJReg8OY7xkyVxgCWGLudoYw75MSB6Ck2uEz3Tkbp1GEN6G1zJjEz0D58Nx8LJ8f Zv5yXxAR032jaOpd+2tWq9NUN8XZZw/RaohdQ2yXs5wuT9YSyLJjVU95UoSuuhLENdSGUJw7pVYA 2RX37ARlQ5aHQXLa9FgYrMmT57+twTYNPP/e7MiWvi50SOu0l1M3YOaouzfmk5/B6g/lDuOqg/wc Y2m7743v+qFSnkHTSGWL4ne9xThYA4xdQMJIjBIoqc9u9zI8OoZ5n/UZWInLydP0bF0lmjuPygC5 nCaTu3k6HHhJb1PPfvjwFJxclvGxcbmOIAIHQwAOtKT9zk4NIXN7FfvGgPvdhls/OP3UmTQUh+Pe nafIm/asWNNncsbP0AmyO/uGEYhwaeb3cW8a0NLhLMcz9FEZYTzL8bqMFBwBFRhIaJVVYBodnGkm LLx5JZ2MtpbdSQU+B238YY9uGnLSeyD5u/XJt0pGrp0LHRQS0CgK6hrWFe93dJOCITfObej8agYb xqoydhp72aswVG8xJ25sGnp30nIfYrrCQqCRNMEExTEnZ23DKMM4R2dTJL9BVdIpHhx+i6wscHII jhg3Tq9hrbyaMJxuRlwpIwywO1xoHBWSLKHgjHA7n81Iu2xesIYD6rTIbbOCn853e//ppEjds9zO t80DXJ28vrqBwHAeLfU6ujx4WQHyIWo9HQTwrRE3n7zBe/ON3XvaSG+9qnxYHT8bFbfTvaakuPMY wiGo5Bu9VUY2xkO4k14cnx/Y5EDOOD5miZ4UTehtl+naXdgxgMl5BPB2xNENECZrcAFDsDp2BDZq UgKSDNmalGsfgsSFwkHsyEFjaQLntNXxDH/4h//hpoQ/ICS0Fh+eGw/L3jDlQcKCjMzKtDCeigm7 GdDis0nvyMzr4KnkzC/r16iE6Pvi6XjeqH3yjCL1wNTAVKhaax1qzSItfqzJb4ZAIQSvm/BW3QCP +RCv6H83jokdkN5H9E//9E/l04eP8lhahM7iQE4G1RBMIpwyFEwy4GqSWzzcAbGL7MGWZNFDqWrQ LKkd03za3ZuGwVE+KddQTOP7u8/U8V0j3NbBI/GL27/Pp9PuulMZCDl4N96KrM67v4Xcqu26r9s6 zo/7ZqQ9m4NYoUGR5NCQhDKB1u/FmtEJw8qT6PUFhhL3hNVBdMPzokZgTWhiHfqPyT1RriCHY+ow OsOwiANwvKd8zbIzKqhT0XWkdIYjnX6xWx8YxJ21Mx1VmATJOzxURkcFASrlhysOT2tuKxr6n+Lw dwdVqHPwXsUgDU0x/pWhKmsgGzH2DrmzPcpsP9vcQZjYyQvKH/ke6DIy8w4GE2WS7+sB+fzhsp0J RPr9uXoLbmIJZ3qUvcgOIcZAA2h+c88jvSD/DMco6cikv3F5OOv71zCMwzAJLzXtNedysjoAD/o4 p/x7ncVq7IZ0BHCWrrZmOXnPEbJ8n+KT7s/KjOpYDG5Xz4KVMKzHSI/LBKcTegHZpx2ZwZ6cU1yH 09ALh9yaAqDskxa97RamPDiN+sqdM8o41w1MLeQglqB4WNcDQH7mmFvVBKeBVOO9D5pACfCIvW5d xxXQfVjfAv/FtaC3iw8N3MTKtpfb+RAOXRstSiM0W5IjrXtXkymsCPpmM1kheKy56s95YrZ1CYDG +qXW4tn5QFGNIuOybgZea6MEATYFkRL30L0khP5e47eaBiub4tPWKRflxqmhtf15WnFDLS2hm4+K vc/sGoCNZqUeCkiLQiF3AVw7DkPWZ+KGyodACJH/e21s1p7COfy7SCQ2REp7b+OwVyt2PsXzj+sm TpyMcQwUA5sMDcKn3efHON9HBblBQuF3SaUKxjWCV3RwdrAn+7Du+75kyRHpiWc6zONQFpMMhHAo HvD7xHsvFnAVKgyVngwv1JjzzDXzbpSLA7Lsz3/+c3l++pjmBZ0PYJgk/pq4ASeye+4cVuCMYr66 IW3aus2aJdumc65IZ7IAMn1MaehGttszG9W5ZaZIT47SdvCrZq+ZuHifXLnYqA0RWcGZOp+mUEz+ RMZAUgdmOEhYAAAgAElEQVTkz//sl2b4m1xOgxC7m/O0FvnAMYVi85jWu5G4n958T17MWhxyjCyp uhkRI5GCRgc3PxUPXsewzqiZle8nvjbZqDFCunKk0oEEVGqW5/NlZJQKeHSz0wUsUYi8LA8XlPkU BpShaZszyANfM72enlD80vgk2/uXbf2s2LLVWZq9aHmxEIUpQPVuIxxYnHw/uY46WagkwqB1HIjw fuconZPXjlxTTEYbxh65ZfM0vjO7ss8HdBjg23daMv6mcZhxfh/r5zgQ4Ojg75OHXkk/mN3gjr1C JJOo6LpHUqwoiXGSRrHeUtIzOHqx9GsctFF6oSHrw0LpjpLFNaTtZOWx3GwstjZ+8Fxf7yYbljT1 jnOdjbiz1YV0Pd/KDplfvVzMQeXukJCcfW9oiyavTGk9075616iUpEMzkBA6kN8bz2xj9XwIpvXR yEZykhpAvg/zLevwT0Uy2uW7nxmMx8K/xbljlkUP0r6hf0UiXFsaDXF/LtcJcJjjSmYA0qFGYgbm t2FAPrvIKpd09jSnLLR132HEzg2LP6JuZ/We0pY2oeWP9NnK4Glnxxffn93h23f0EOq+knopC/Se zgNLd03zPtM/DDmnOUQXpz5sDnHnEXvyFGuBahAEBKBXbH9ZUWA31CEwYdfofDy816oaX3b8WELU su0dZLAqNc0wEo+KnGbw65TyY3xd069l8PpFdjpzXmPSnTshqKDMDWVx/gYYEH+qoNCdQooX2/Sb rpSn7eMfnj/Jhw8vFk7SsOr1crV+ZEDX7ia4ECAW8h0FJaUMZTYMkLfp0i5r9mK4qKT3Qvj9LfJs cs05KSU1Lv4yhI5FaDs0Jf/eDFuHzHOpBJ84yJSsO85RCQMGRSHNAyYAmJS1KWgp+w3BuUnjM9Qu lZnIihDeo5PH9/vee9SK5DBM/C7dLyswX7zYMHbvNpSKHpz6Wjx8q8Kr5OfctofrAu+nBxeCB5fx Lwoh/GKGMsY/jFIrrlzQN1Xf1qwvhZotBaH7tXv3g8gd4ILElVGZ3sNxSiI9XYwnbBu0IFFCsz11 PNrIuCvarFnEHYiNGgf3R48DFZlIyAbWWkBWgkbgQT7eKQGS1003dhg5LFdAMrogtIv53qM9/MMG 2TCKHge0r8rTPDxBtoiCp+hKIAzMvaFGhIFOfciX/zZztExWKxv84HksVLEJ9quWoOg9nhHf8XEo 56OMGnADDavhUV/ciDP5cqWFwwiorbTRZxXbrocBhkyvFN5gWNRCpyfnmvS49imR5akky6Rlk1Kt NH+fBjONm4vXRQyEzuX1Xjy73w1iFIye3DmryNZO8s+fUUoARuTOeSzgjcJJrmYk0JuPJJp0rZZ4 uFmHUC+Sh8f7T14/i8+yyC1I4yrbc8Wza3ha11cz1bNck/JA5MM+X8FVRGLDLH/7938Pw276QqQl j5VjN53SfV4rA3MpRIy9bbo4Ocnk3GrRZToDSKAaTuhR/7+n67/8auHw8GV0qYJIRzbixt5P6AzV ajJOdmPpElQne2KCaMXTLHQPrNWQVtus0zrOEk9CAMq6R9gws+xNnYzwjCKacnZd2UaSGhA95/sx W7yxG8iyezZkb6N9nATYgChHhLe9F3h3pI2RoKjfJ24LEDhIPPtWQNHRwAd4lqB8TR75i0SfUhy1 JRI3mYFoBpuAZxhHJJF5RW6JjnuSnfby7ZhAUFL6kVvOxAz8e3HDy3SQJYssSEppMGI1Y/tRxGlI 3maRJZga7K8Toxwm3qAmTHWKRJ+5+0LRE4yNQ2lJqJXBtRQBjTtZhpYuwHZYbNv5w4fFwmcfP361 /f39dphd5aZNyDsMNyt3USZXqkA3DOmjwMogAQ+EYQj1MOIGhyRqXr2zvXDgu7dR9w3cbQR6gLon mb1t8zzIgSPK1gfXLEoFiAI2qCFX3XjAOKe9oUXoPFlS2AzLMLZUdnpKmPDX4Ai+j+RkNCXPmR3w KzMrx/wZL8BLVbyXnYosXeZICjxm8xAyCdllwL0aZI3j92q4zR3tt6wtV8WhZd5hGWPtXsrkaCDb 83Dd+6hzxjZJVhKg4/soiyO2KZqHkJr3bWx98MTMqPMMVhrO9l3PQsKm1rE90DDcOj3cN0Vw2p5n e0+Li4pBPNshDEL7bZNtQ0Q2I0VLJejG//Tpa/mn/+SPzKBRT84yAMs4ZPIajRpvQ6GT5Cs04kwb U3GO+cnr30mGZ3bsNl70OnVZ8FpnUGJQFI91GEW4rssPz3vyCg3KflvnLCNxFhY0H6EE/41lAfpm IG1qBkZdH7xS84gFXvcUMtfjMLDxbjrgvjl/r6+vvnemgR4kBECfhY7eDu1zT7v64WNh+lpccU/+ xKq47zEXE3ktyxrG2ip7tFtvRbJ9d+P0vMnH+TTIybZnfR5O508mN9ZFpI/1I+evVnY8SM6qjNpQ OLTGvNPYPTtCWF1n5sQGooEwrgeSEPefRkmE03mK8fCZYSyDC1gihFfM4TlP6ALBslNr9cSDxM3d GYJmRGM/6P1+7+uv5N/+1V9bEdXLPO24VtR15I/auL2NEqNE+CjoGz0hHnzhveTouJzRQYqwmv+P Yd73HC0bUyp2XQ6/G+/1WL8w9gXFxSU5R+/p2mNbyz1nOSGARMq7j8nP7Nw/W/UGaqGJB8dXy2Qk Khf3sXExe/2dZItkSBtlxWt6Qmc99sBCZ7apd+oh4uvX1xJN9nsvj1V2yCh4XZgwGlo0esFNhQOx 5/TyHO3epghltxB4nnw9RqZ3xX3c+CfKxgQmfqaST1x4TnoCDbtoRGHrzsA9Wnk1Gm0s+9Pdulmd 0FCtJmUU07fzDFUcrDWYoBYiOwZZ5YR7Q3cGT7DQkkwaETsVRgiAIFqHimctfK0brsxWNFIrzFtm aoU1LL07YVuz8rTulLUP33yz82Y9niysOllW2GbE1VU+bBvzw9NmxF0+yadNed0uV+lPLwK4v1lr CztoFGGx5uzNBH12z/lR71aSoPt9taheW67b+C7udT3c6p1hsTYUw6UFHEqUBo5JQ2U29uhdGYcS UTHUJcK/fNOxDpGRRcVKFNimrCV4SrOnlvfG8CarR3sCgZ2BIF+jis1im3GytOEJ3M7pbvypy4xW XrrnXh/ISCGCYD06LbMH1186uCC2iMvD5m/xSui2sUUc1XLhWzpi7mp8WCmQBw6C+YRuC2njIqEE z77G84NP0htqm1lRQzPC4BGX7b4qYMt2IJ6ez3Le7tHui22u22bgPJ31SVD+QY28k222yYqpmkff Z3Bltnto+EUNkXlarU6bebPTaBTd6jZP6iHphtq+/7TJxjfb87zoRng0eV4nK8A61dt2wc2JUHm7 V7msl20OHo7KnWV5KHp6267v4TqtG6aI86NZgVpDCZRMuhlymlJ+qp82OVzl0bWXo8rUCd5U1ZZC N5Ot01fP8j/9z/9DOAyWXeRzGdwPN0SYLcsm3zi0aig3Gg7hOot4S7XRyxMiPDp+HA0cHiijuK/X dGvjvVqGE2XK1o17Equn3nbXXLOCN/mYw3iSdJ3xGpmQMS5JaHkKx+QWa/ZeQWIJm8AfnRv957Le 4vP8m96v/jwvw9iiYZWvU9s5xhPf5X5qoAVEoowp98nK1nB+tDvJY/v7c3KeWBvPnql88wWnjEaY 10Rzo8jG4LX9rLj4Y43MZ+X3RWjZ97On8do4zSGSycO5c3CBgmieowUV5UP00I/wYji6syWvmZEv Ixlnzsax699th6LshxK8PRRLtNRkThaTN+VjWnh7u80P335jNcPa8rKNwfXePIdTCgMZdAbNStYE 7VMpHqaEQtD9BgdWhKFdLRNkXMiY7tHOy9CdImHgId5ZBkm+jMoDOThhRInW3IlfB9bMw8R1ftR2 syjB4nNZIjyJfb13qDGuKWRpGBX+mS5uvCXEjhCcr6VxqtVxE1BC0M/4FJ0ppIwaluCOeZZmJ4K/ r4NI/RP7dYWRYYVltY9vX3alimi4jYiey7cbZUtu+9bhSJc+ktRaMqZIi7GfvQexUUyCpkG6lyfY tBzJIU+uC7OzzcCr41w2R6RAvgdtgbppcNkYEVoNEUSmtp6ZWijeivA+8Kxzm1EXrjZw53Q9NGNV 9852bXVCreOK8+20BqnZVKue3apXPmyi/C1sKKWGPD3JD1oof4Iloifess3tKYCRamJrCX0THNJq WAQ3Gze4CxQ9TZF93Rz+jmERS4+dcRA9PZ3l+flJPjxf5PnDkzzdzrIuTyY0ixZzvT/soacO6NMe bgHK0ryUApGbPUrUvfqze6Lm3uzkfefpcJz5lVG99zyPt5urhJDifZQ3OM7FOND22aeco6V7Ad8i 0SD3oQRP5S5sAvJR23GoICze++2ErgtqWDdDypvVjbEG0I6OoFQBetYy64vES8b1Y2xtpCKz2b2+ AmncHbgiew7JPlzB93aJEod5zIc1fzY0y6ufT4J6N/QMq4fdTL0257L10TuT19Bs0PCgI8TezNDS bFhkGbOg9JAdPbx1/il3cZhPEt0Quh+q00GGipe9YB89a81yu29rd7bw6kN7Om6H0Pn0tK0pknr+ 4A/+QD59+oTnt5I67/f2pRK27d3eyiu4D012LrQkY4UIRiSb7Nd9cFIkPtejJtz4/OzfJwI8+Gvu 0ET2Wn9zD/xjDsMyCuXGs9T9mN7bkzKQq/13xTOSp6B6vN17xRy7975HuTn1Et0miAgA8fuy/K7J CFydcGT7wEvv8Ppr2lN5H5U+wk7X+55vezTYAzlu4HIubY32VxZpeCyBxqGQqBc6d1TN5HvtqesO DmF1gKwG2ck7GiyOSFof04GGW7DXO+zE+GMPlJGN3If80oCzOXCOT+iGnkLKJn/egtGdbd0jshkE ry83+fjhjMNwnvfrx7Bn4gfShe0eqTFelg1slKQBIjjaElooLemCkhA54bOQ+5WRsnh6cUDDAPGI royh1vjcfm/PaNpuk5wNpAOXrfd0zT21h8jpGxktPUVXgBKZbuLvTQT0mVfwuprbSKXD6abByO37 ztmul+UeUKfWUDg14NSQ8ZJRRx3PWpzYWqP8Ta1jX6zcX6tH4TI66El4b563J4dVKBucryLs8lI5 K90pYRYh6l4vkojrG6PBDdnEK68jUoJ6kCe0CKTz3Ho0NCgLOjJ0j2yYvK4jOmfn1vY5pev06Wzn vgI5JvNWd7dv+uGEPIKCgtfPl4t89/mz/a1Gm+m/69XQuH4vFtnQTNWzZd9rhZB59E6lt2lGnHcf 4EHCeC8+NxQWvS6NQZ83y/B5M+I+bcbbx48fLDX84/V5UzwfjCw+3TbLVBu3btbsXQuACkIMVtNh u65arYpsvNxu1sZIjRbjraSJH4VPJQinFOKjQO6F4Mu8hhyOjIwa+8eAvJGivof9ec1aE+eIyRWl +UYHmoDfeyaMVV1+QPi0w8G2QIrU6aJKAdcAtbX0yU9A+RqyoaImUcG1SmFYuErU4+P4PMQpruzH QTO4c3yeL80frp/KCtQS3zfgv7vRF9faFza2ufP+ciua6yGcoQrCPLjFFLJ5Qb4ZWfDRtNE66i1p gyEgISPsp+uyVBxA4Ef5gagp2toFZDPulFCtmYhGvBdw5FRerYvE9jvdkNq/Ewk3ktmLY26mmqrl w7A9bYabVkG3jbfJe7vCOHpSJPrjR3l4KFlL7BwTV0zuKJ8r6zyNNRhzOLKi9us0EjNm5yQdk0CY 3dy3edhlxfWyKxNyYls87m8ZMkFUN7+OSr86URuvbPDtv/9Gtt4x6NbDtXe/PxRZzVm67+3vMP5Z 4qWM69IIslcq+E2UdPeH/Jy21yNE9JCduY66a97thqHfUs+767U29AcVPZEPc7Qy8qn73jmV9qm+ hBHIMbVNttXQw8E6nG/Vn0tDwWajwSwjJJZRTZ0W1nLMLeCAsIhxP48GvHGDvILAKuv+OzzA/XM3 40SLhWe1hqLSZm8LkYvJUCTVDywjUnxPISw7mX41pNDpGmrEabKc9RQ1ORqcvomOoZRAxiT34q4e li/IZB7O1e8w4kpx4r2MJAF2o+h0GIfhirMi8b/qnnqQZXCABW/Rc+hYJhSkPeHnCgAFoImtjFZq lohWWkRKxJNeiiOPtk5K/LfrHHd3uk+jwbWi16cZco+Qwey8QOeS+gInp6A+k8zekYTn4NoGyi7J 2N6/Bj+tebeKEXmgDVBhsEU9zbL7vnHZuhv8nlhkoWizaFaJKqgescJZiYb0BZadGbDa20dD0tnQ s7PAk5dMS6s+UVoHHb5OyxnUi9v9YZ/XPfDY5vVpxilzffksd+Umd4BomjCn1SieLEF0kuvrixlz USFAjeKT9q+frYvTuXg5rOxZ2QAFKLEpl7XtDgcuGFrvSCh9HZJCjgojfjhf5ONmnapBp8UZn9qT bajVnKDVjDnj3jUgMtqqRydc6zGtZ2cE9LdoXDxIrn2Tis+G8AnXeo8gfun1RcOPte36nvw6FPKY J45rcGLQeFyt9eotSRzwR/kKK6YI+HxxY8bKJpwBj+q8aFxc0ScVyMcDcw6PVxXrPRSDucIctwtf A3EiDMlQ7JaNNu8M15w4cjyg+fv3DD4a0aaM8EkXEkyMqV31SKzBvHibL3BAdG4XJf8vCF1p6ya7 5zsIycpipb3vStJCoYt5KA/22rVevUhf17+VD1XFvW6d7hVcAzt32gifzVYzTkLxGiqlB+I279MJ Ro/OnaII1i+WIS2lAGzPcF4HwkJvFKFPcEenNOaYX4HRUCrDMcd1OHrn2VmhUzHZvObingwPlQ6a O+dWREZ4PqPa6ziEc20qHkrrYd2zuu1c5z6QuDF+/z4N7ryuySCq9ct7UOKO7Z33eZj2N/LJ0gNE M2LeSkKU/LPWlC59hvLH8S592a3bm3HyYLZ7ogsDjTgbm8yHfbWPBlgRYu6x4M6OEDnDcbjHHtWz g9Ychbe8WTO02hqsI+i0tzpSiLhEVrcb+jT22hwGNu+7OiI4QsODSzuMVfxO2/CpAal75/X1ZhzS X/3qb+R/+bu/lc+fPyPEmow4XuuIiLN8CWV9qqObbTbiRjjUqSWpDijDqTh8hzNr9QUCSeS8uCy7 gZ2NwRGtqbQAIwxNYEGEyVWZb71PPINT+vZ84d8wOFFCAxpBfFw9DMqlYr3MmRBUeOie4m84tspl 3e+v4rVB/bTacQP96h4FgBMAg3zZyZ7qN6NDCRMeWWYJqXxIfik2du4Po+L0wXkFlzOFmzsMs17y ftnTR4b4OmDSsM9Wn3XYB3oPRKtao/xL8OKwdm7syrAhYl3pzElzXUWa1HBU2NP03vCc5lCprlDe tJQoxv/tdo+n5xOcyccNLrcWGb895P66yodf/Fj+4U//gfzdX/6lfPvtt8i+v4DmZBm26uSrPvFm C+bYqLxs19Lz9bHZVPNRQRFqHhtIdhuTVrj9bYdVtZ1lxDxBSQMtBKxps8+XJ7m1m0Ha2qH13M/I cNqMkMeK2l7KsyjeukcVpvK3VClZWxfQXrHJqLg6jB9UopY9v+awQYhU7UIdh81yDBeGIpH94ZA/ Q+NIhMoLPlOJzayKFQcMWutU6xFqAiDg2KnoWOhEjd/N6F2ni3zz3Teb9X+Tr57P3u5GJ/jk91oH 6tBKIFeTH7TsttEcITMlKiNkZ4rXPAQ3CtjrNc3F8Wesf5rLfIAkZAOHTuphqVujItSlMDzWDehi t0KHWrz1bobSpGUebLP7YdAfjggTnRhlXlZXMWbCuDJX71B5h8rJM56QGmUCz8ucC9d+YffHMzjp WWpU6tdMahyckE2dV+XurF6ouJdR8LW74aiInPI87/dRNNc238QwwyAVR/ZxH7JU2Z3DDgryWHAQ QNQz4Z2KlpbR+Hmh7Lf9/u1TRmETP4gy46Hidlh77opjiLnmg0h44IErdCw2DLnZPzPkMaMRb/dX XIPyFfcffLLjZwPZePNe3/07PwcM8fO4d9//rY+z9EXy661OyCjqGmGX6kbc/rXPMOYzhZPliU4s +4E+zXP6vtcNzN/PxPvDs1umoJTd72uaOzjwfOi2w2UicaCM0k3RIq0OPTB1ji8hSd1L/+jf88n0 gOpz3SeX80f5s1/+tfxv//J/NeOuXN6WFomnbS2cEhuT7NdaM31XQcZvJOV18UhIeXNNGMiDn3aU a3xov2J0BHq6BsGO/StnofZoR2WJzHGfrB+Hc8wxrQQEGkOkLWg9eTy9hzsGnrIULzs1weDLKLV3 tGlengXX80hRSbK89pQFm8AJX9tw3mlJU48KdKndYxVDmizzWfVzR9IPF49UDZbo4nkZcms1Dr0s lJ1RUxhx+D1D1LoGbBE4eHH2SLZYU8gI0XU4BtUSMXPhbiQY2ATBGO97Pa08Nd6nVe9A47+3hATB OWRZ8A/WvIQNY0j4E5C05frZQC5tV/qbH27btc7yD//jfyT/2X/5H8mnTQf/+t/5ifzqL38pf/7L v5DX5SYfv/raxjHVB4CXtXs/6c34295DKz9NyzK+3IDwORGxaZ1fYPPSxmQQTocx1yOzQx9IEyQu 22Cf56fNiPsgr/fvgX5o0c/15J0cbpshpwZMs9IQ1oaidqs596Mf/cggxKmw9IajI8lowJ/x7/w+ hZevL/383is/f0sE6J2X3/eftwMwCcrxO+vq6dQmoA8LIVtWlx6G2tbk8lG+f3T5q//v38r//q// 1fbci/yP/+JP5Bc/+npb+KvNey4maAePN8pVFIrqh5uDisKTNVPq81BAO2O1jUOASju/slfMtR8b 5qjxwF3h4W0JENrCqvFQEDOU1FBlGY7+ULQKh8nSwTtCNpkEl8k2NiBKfMd/TwWPUiMF1ewrDBkU SkW3BguJnWczytbz9t7JM6DnyesEjSKg1srQOcsLitVZuFuNHUVEtVWXKiYi1Tr2SBLwjKHH7e7K v0cngr2gJflR59PD3B0EGiHCJDsDZvAA8ZYjqV5xfEqCeTQS9DrH7EWhYnNof8qGXzZ2+L0k99Nh D+iuD+dA3j9A959/zxg6jntv7PJ5xx5zOkHZO2h5nDYvpQffi0YIlT6M13WH/hK04HVO9XkY4dmJ 4WdiP0kg4GjxxddxfzHk5vM8iSMGDQWxJRkU4uGg7nW5xPddGr8V8C04oAKZ6sQlRjceGtb4fQ/U wwJC1Qt/p+XaFYztfTfPLf28afSdERuIYEVniYeGk9vdHKvWnuR03s6E1x9byQrj/zoKl4GCyMrt RKOmyDZnaRA7cCvCtr9Lr/M6+d/5ucI4OTgPYx4EoEF/e62o1tCRwIZLDAQt5DM8SBkOVnEkr3lY uKJNlBlDBYlxAxF6+3wYR/eerX5eRWsvotc6Z/8/Y2/+ZMlxnAl6RGa+q6q6qk90N7pxEkDjJAAK JDUiJUom04xmzHZtbPb4Zf+y/WFt/oQ1WxuzPWZtd+fQUMORKJEEBRH30Y0+q+t4Zx4RG35FRGa9 AufBCl31jnyZkREen3/u/nnBrBkWkjlSMueca4q0GvAK6ORao9i1YQeoJDEDTu73lF6ZUou4TSGH UllGRO+hJwYej4vFiXHMjdq8JAuU+vHq2mohpiU5IR1Ax9XE6+7fY5B5wMyodmYA6WmaA0aVVeLi BaD8TJy3Csbw+wqZXyrDpOeGuWtqJ6moJ+xhI8tyQLTDCwtPF+o4GlQs2YbuBjCIjvb9oyOA6QV4 9c134M6dN+DmdA1lGMBX378D7VvPw68/vAw//5tfwXK1CA7PLst0RUwBImTvqC1a57lVWNlLUsSp Y0xq2jsAReQt4iZVd7CpWyoTr0snCb/htU1HCbSF4/5+uNmRcJ0LRh4XYRUAHIkBj6HedJTkjhsj Th4c2L39A3jrjTfgmavXwuAuuNEsCKBDr8t6KcZK4c5ty7cHpEy/F1/OKOEjBznKTqTwgk/6Uy7p oQ3BIrbO4D5zPuaKxApFyUGyJICLnqUjoNBS1U0JT08d/PV/+Xv4m1/+Fv727/8O3njtBfjLP98L 47YDK7dmLtJzhV4SYFUqXlgUYd1iJoFQ+Ph8fn30XJcM5XcBYD+YAzoGEdSph5i1TYvjIfeImgRL I3qcI5YcHvZS0KMgkcQAYLvSUziTIJpGZXF9dZ48OynipgXJeR6SS2JAZEY6YnBxnBW04X6IoYYW 783IkLQNblirMPlXIwtrAY5VwTlLVFMhG1cre5QdYXNurIat6KftUlEPJqliVTaFgbiZyZkH9tWD hquaeeNJ85MBB3uw6YrVSLk4sxODlfKN6HmRSuikkXq8x7LhROYg83RBvVa+WRH0MJuWgfzeqpI5 YqAHkPShAMmAhnQL8c557pTW9s/byMZnkjcfH2I8c0Cpn9GwalH02w612bqOlb+grAuIQHMas/yY zExx7o569PnrGlqLDqS8ZrN5jhMnlxzizScDi8VZ0MrjLXbJ5h1duhgS0oeT1BPNUSJba32s/jOt Fin4uAnpucW2Pd5HqRSO+/o49hrPaMH07rsXuMhTg0FzZEVMup6uXScHSEKseH644VlsWSYzDiFm RX0qs/lkR6xKgElzkBxKlVeJY0DjW2yV6zFZ2zJaB1lEhL4nc1KHjz4gy4Demde6fkRKwVb4H1Ym jyh5PtlnD2m+u/yeZ+ed/cERhSyQSXfFafg3PZ9HYzScSA4A5Q9znldsn4nSHnhcCskhWCypRRoV IeL4GpbbyPEQOwvQL/QwktMnKTEu9si0ELVOHRfWKdPpZe+L4Wbr01oDzRE0UbPRCTCJY54VEGof b2MG4yYPq/OA9jx29Klin/IeLQuQy1phQW4TQRrPfCZhaB17FvHl+VPGXLlCcv9ROaPZ8LnRvoqA MDyHQA5/bwoWeu4UA4RP76BsSJjfp6sG1uHYu8/cgjfeeheevXoZTu59CQ/hEdy+fiUcbwSzcQE/ ev9VqJsV/Me//hCKyS61rMN7NMLWggrQTUtOAnrTyECXsZrR8qaixnWbh0KD3XJVJKJQZNQ2ZU0A BuacSJcAACAASURBVKUxsHKvrTtqhUSUcLjRE2QKUCEfmbjwec4rqinJD4kaU2JRQwvr5Qam+y1c OrhIcWG/PiYx4XyxUn6AMC1exPzsOTc3MmPQBx9DkKKVh0NvTcNc29irOIEsS6ao0fCdAsGWJDTo MzhJKTzYUaUWGpmamMyC+jb+1V/9Lfyv/9v/CfcfncDO3kV49tlXYFTtwfx0CWNbkeI8jjcn0zM1 XWOipFUtq5R0CXBWHJk2+i6FOvPcme1GLLENVEUjQoN9eh3OHOvsQ0LveO5Uoi7evfbNi4sw5SCk PcRSriAWuJCXDiA5mEYqE4SRsWzwrXqAXvKhEMSVDOT8GL34EdZl01bVFY4qU5uK9XYwnN+JQWZa nCuKLfXFG5OodSseJcvvFJGJ3p0Gp6TleYB6ZqqLh4mwzboO95nTZ8sMwMWQsE9GXgEHGWEqShFq Xz1gnxl3SC2YGIyBVGPwOKrgrm46LYW52WhK6wYCBWxUfT/nbQBkCIzbDLwZ4QMFK+TMF+N69Zkz wMPuNyc7bwVn/b+H4ds8FSKDpvEZXb85iIuhFDBRrJPCxUbHROyCT6ka287LS4cH3ULVozey8VK4 VUPI+hokNo/O36SxVaoramHhnCt0LDMQTfeBwXerrJdjZqK3fjF6MRInE3xkyIoed5OeiyFuWYfM VMo8NPk4Q2xbFFseRdkJEXMVmQ3VkKRxlbxQzDGtSMsKxUhHlCBOZVpVKUyOhfF0FpxUSaNp216k YST9anMb1bcPcp/wqYKo7F5bQh0f6jDjt9k5nyJOPoVGkxOjQ8eVjspm+y0/eDtaWSM222O0VRr4 dGy9gLyyM+ack+Ol3Rx8NJFFTBoCYvi0TV/qpMJggc8vhRh5o0e7zYK2HRVwWZIIq2iSVr2xzdeN FvOkfU+dTojnn+eCg2R8g0jP4Dkb6Y6jOnSx0ljGQvsLO5vfn/49zM8hv6/5QzuhxMIRw0DOyfko gBvqa2oaAbWeQyyBxXCGW1hysYyPRSkj7BM/Hge8s4bVYkGRFiVHqCjBc6GDp3zrGpq6pWKQEbX9 a2AVjr1qPFx78WV4/fs/gL2wDo4++wzM04dw7Y1LMDNrWDy5D+v1HHYuX4c3Xnk+4IE5fPrZfRjv B0cHpcNazt0j2820IZ8rjuW4kIbNngmVodfM3j5X/hWo2+UxxLcmYLEKB582m3BDA9hAzZRNOGnU CMMG4S1qx40D+pzBBG+yb6giEAdjHD5Xt2xMEWkWHbbx2oTvXsLh46ew2Z+EDXAZFsIO2T6iDx1X 8SErh5u7zGpEgayYny9COX963iZvIgE4yR0DruJTr4EmZxfr88QolxzvdqniROecLrRNGIvxNJwz LiIsGWkrmghYnFCF665RLiSAVtetAmregA3XPtq9Cf9w9wj++t//J3jy6BCKagIHBxfgvbe/DzsB PBSuYc00vwhAbQS7AdhhJ6hlQOlYkVlZDie0OK6eldFpgkrMnrS1cN+WOD23ywICJlRN13FFXekL uVatsk2GiAFhAoe9qjayqZQNB6eepTZsmAdhrhIwwvzI+ekKnoSJevHKZaoywnuHk9tWHmbhHat1 MDTVTrjGOm6U6O0hsEAGrsOWbQ1Xf23wnlss1yYeWRLKS1h07DQYykHEQoQRMX5mNAZ3ycPmBMPX ZZgzG9Jzq9EOosBpAHcIztbhmqbjipwQ2sfKivLZMJQ6DmOwRFkc7ONZ7IYfrD4M4w8XoArnV3fc 2xbHCvNAERQ2DX7PXjhGGVtKqX2Khtzka81mKQxe9AmlQbmD6NUb6ePjhGaj7CbD4Yw493HO0x8u fUZZWs8LX79HQ6K8uSf2rcco4XC4wc6p5xPDLn2GmN7hIOb5cLl/ConkmyRXCULvs7SuIlDxsSDI ChvE55ZCoNi7lmYoOkjCgliZn4UVZkAwNM2wML4jz1piCGBc7vUPNjO2fYlV42tzkRWmZGMMJWvy PGhKStr0bLrYeBC9VCMsBH9WN3x+n47HSPQRh4xe/JH34bWUOeCRcdXqUQaX5+fkFXI/ht+RCykr 8MhTMJCJi79LVIcB2ySs82AFxmEsuorY9wadLmyZNn4YhmxNQtQAO3z+opeID0rDAClui5WQ3N2E Nu1GwAqOTVbtq9eMwEYT0AuQMCwy8SJe3QmDxG2lsg3eab5buj5lElmVYUsKgM26RxjR5fMsiUUg 1yYt01iRLjWSmL9WdpwGQ6eG890YncF8/4pSgAZI4YyJLgU7ZhuxLT6yjqpKAEpyUP447gNjrvgX xgiMhvZTVxnDJyh7nKHE+QhMqTrBCVBrOS9Yrp1aEtP+XKGOQNQxKyRikKp3s/mH65M8aGCcTHlf uh74XrOOrwe9JL3HRTyerBXLAM7JvCkkZIo7C7HCCI9JtQArPI20tsKxD3tWy5JfCKBbz44n6SHi /lZ0QMIRUpWr0TZl+BvcE9odmk91tybbi9qiKBJsw9/LRQXt7i68+M678L07r4OZz6F7fA9uXS5h 5/ozcHK8hPmDp2A2TwIQDGvCtnDp+Tfg4v6U9+vwPWPUi7QBDmKBkMjkdAgGsOK7Bs6J04cXr2SY O8J0crZwRcMLmbgVFMR6jNBrRE2ZGn886791BiZhczcFyj3URP23yCyhyOwIRVRL8DhCLVfRMWsh 6B1vWlZZlHvZEM8r08Pa4tUP9czStfYZOTUeyRhkIdcMvPS8QnngZ8dYsUjXC8TGIJNIlalonMJC HlcFgYV1AASjcLzJ/gEswrj83UcfwWePjuFpGLdnLs/gn/3zP4G337oZxvHbAOIWYexQTHNMxgUB D92HogmTqqNwq3WTAOwW8XrTxQMzOfRc11O65x/ZzNFzlMTTbam6bNiGBjJ5TjZWiHnSeMNrJYcA gLShmnoFpHsJSYONErWpVZIPgJ6FU4tJMFQls32N4xZWBDoixZ7GnVkA3lyZsOL2KWVpuGLIoDgi G86iLWBysAOmxt/DnGtH0nAdmL3CRNMA9vTSUdLGiS6XikpaZPok9OxkPgydHJXayRNm8zma/36e VzlkvtOt7IOq/D3M2vne9/DrZ98/BGnKpHUReOhjsFENpgXl8PWYHgFVee2wyVgnBZNn5Az6Cfbp WD57r1YcykioLeIdD1QVno6u46ygVjZOL+FOJxhJCz9UzNxmhQHyQdnc+Jy6fFkZCVXLOervSS4l uw5lTAeJ6XycdB/s4Pq3PYZzI/9XR0qLRXrXIqcU12uW8B7PswdKUrqAvtYD59nx0zmw+gDkAM9r S7aShW/xGBWLCyOIs2YUbAO+30qEoYrpHWg3NcSqRWPazin2uC0SHGqavPBk0EIrzA9M/XESxbHU 485EfUgC/3L/reEe0vEaIe0Fw/Hqg/18D2ExWCZElNnnIjQWSUlAuFOgpACScIiPvZgx15xz0dt4 nnSPKUQuWmsYKSkkPEmvCZvpfQzxD616j1mj6xpWAvftFbJqnYX4Xnp/FrKutPBFFCU4b9lS1TQO RmxlZ9L3p/MwJHcyfC6fd8OlMbQXqldL3WgM943RDh1OCAXCDuDFsZOiI8djhI49sZYS2UJdO3TW yWE3qtW4Cvtv2L/X2Ea0pmI3gvrBtixajLjcD/v6NBxjTFgIRuF9mxWsDwPwe+4F+P6P/gAuXbkI 3cMHcLFewPMHExhf6OCwPoGjL76BoyeHsBv2wkv7liXYjh/C6eFDyV9Eprqj8+X2W54KAwujOc3a AiAbIJ8VOfBg8UTWReNFxwzByjqAs3lXwiQAMSp1DgBusw6vY9y4tYRIR5hPhJss/piAeMNG2VUd bAK6XKNURs05HtyBwoImVGp1otKzpFIs+VRq+GJf1MEEyDdO8MNpDIP3ux54g2zTZHq/jUUOfLy+ 5AZeG01gBMakmVXGChcXDNc8TIpN8DpRmXq2s0sxdNRlatYLaE6P4HRdw0//+Cfwww/ehT/60Vsw GbdhTAIYKXbCGDbQ1bNgiAL4wwxTZEIxfGrGsDxdwXRkeuXYusnQ7543C068tZzs7Psb5zZjnmul KWuiWlYsMpzahIEcm17DRGUA6Q3J7G0drtNReKUQRsJSGNjJAqAQOUpwVCyt0qJAqdAm7PEwk2ps SlSlhUeAiq+F5HS9VOLid5TkD/K5dhV3wtiMg1eE4ow16VYhdU5hEgpXj6jYQtkPUvNGVtFyexZq qwWQKn0zj1JDnWpMcqX6dD+2z79t83H4r/cpmbc3p7P7xUt04MQ45b0yAmhgRL2AlZi/lQPDLU5R vN0OkoAwJMCYM7j8ggfYfoh4/sM5yMdL9oZfS++JEq+xsoKz8TFPhwxzXkQAneRF+8QWZPYgJaxv d17iT3Z/zziO+I3W9DY+jTl9120fOkXpWreD9fM+p6+fV5SioDeO1eB1fLje/T+bjrFtPvQZlQR+ qbk3qO0RVo90MdHplAKcYgQYPdlsWpIvyfs+c94Rs3kI4hDcYSs7Aj0oqYDXIt/X08szXJjBEKTL 1gtnCktMm5cFTgENoRDAaGkOKcDqOevgI5u+bT3kew5GDDwBAksmkXAEhRdZxJaYNFD9vwwIGw5f EnOkvolhuRd+r4hMAzPNNLYe5HUvHQnSfYv3LIK45GjyD8Tf8xzRnHWUmUEjQGFHKZrBfZhyUB2D O6r2tDqozEw7AVGd4eiWgnPOy0wOuQK0HiAeFAbSe1zal3oPibDRGMaBK6UjgxXtPO44g3sQCZUa JgCox7RskJhiw10tHCh96T0XhOD1tbJ8XNiD/WYTwNmaz01aAle+hFUAY4tuATvjPajC4U7mx9i+ By6+fAde+tM/gj08jwf34Zmig+ee3Qtjt4RHD7+Cw+MHgFzhYnUYvnUXqmUJ7suvYP3FfTg9wT7c u9R7PDL9RuyvUTDnAANT5dAwcG9Nab9i8lLeVD7POUGOZBXWFGtvKUkfY2kOG4Nj6yNspYQTz3J7 rtaXpOaN+XPNKGyubQEFxrYCoPPYPqYruKOBYW8Dy9idTQaOS5vPGr88cV9vvj6YtTm7ISnjyMey Mpn6uWI8FiUMOxhQqEoVdshwhduw3gQgOwnX7qjCFkPFdjwNw9HCqd+HL7/5Fh48uEuaXAfTMdy4 dgOu3bgG77/zJ3DzmTtw+eoVQv4fffg7mM8fw840IPXw+RvXb8HF8Qwmk9Mw8sekrl/YA9jUnAtn y00Av0ktXZkBL16GCiAmwyTjKI2ArWzGClA64axJ4ybmzGwDDvg3t7zhlzhHBpN7S12kBRsz8lAp 4RSostORzhp7E3gC49mU6P0GQ7xoTMXLoVA70taVZ30soForCpXSQqQ1LJR9wYwh1TyU2NR+RFHt MMuIEcTWPVwVi3mYYcxw3uG8LSs2upCoeQRxo0pkQmwhhqgMTgqv2pjbIdIBbdtncfOx2gZSznuc xybrRD2PjdnWwLt/XDXMuuHkr6Vj54CzD2K2HRQysKLHPP96czY1/X3+OfeuUYr7Ug6Q0UkXT8bG Ck1+zUQ7IWFicUxyLTCyADgfTbflnE3vZ9vYRwBVsONJ98+yPYn5tz7lPPavfchmnX19eD++67Nu MO40P3V8sybz+SM5H/mz9szreYHBGXaXnDX5mgjorNxaPhYW/1gKbxWkZE/t/jDnjZLax2GsUts0 ZeQwwoMhK4xoXD64SI5h3ay5cEJ7dPpNL89Z2V4df2VKaQ5wdDJVJIqEB/eHT1plurcNr3V4zUOH icmEltZCZ6U7BaG4DqQRGH8OQDhsH8/Fyfcjm0SrovBiV1tJ72lYWgIgMmDM/oKECM+CTJN5bv25 nZxvLwVzyUEy/dejcWCRGrq/kpahUuNkL/lNYg+00CLJCEUBafBSrS9n4kWfznMKjxVm9LzIBctK yYdtug/4GauySnKP0a5XOL74fL0iENdhGg9edWkoUoiDbMu+tDvuIa3MKa2cxfQqaieHKhz4GbwX GFqlqe5htepgZ3YhzNENNOtH8HQZjlXdhJuvvAtv/vB9cKt7UJ4cw4t7M3jm8i7cO/wSHj7+Foqw b9RPVnBSP4L93QnUARzev7+GzXIBT1ct2P3nSaYN8ZeRccGGCDjMGApGhwlz401AjT0mbtukJe+G jKKqf6uXIIrdGDYjD6kNJ+a5nVT4D0vPcWBbP6dNEKsvuqIh1Ius3dKNYR68q1UTPLWNIdaEb0pH raaItC3LmPjem1gA0SMB02cq8knIk8j1jBo/DzHMqiAwTnYqm1YDsEVKw3MvVt6XlEZn9I+9Fh1W twQj9WSxhM/v3oXf/OYh/Oq3v4W7Dx4Sar6wO4X9/T144dU7cPP2SxQa/Q///v+Bz774HJ4cPWEj gyHoMH53XnsH/uyHr8Obd65B4bi7AZYtY1h2L0yKpn1KVUjqjUH0JpnGJ6aAPF3PxgYkR6vzUqEm DZQzsKwPAnTOCbAR1itrL+Kluk6Vq4PvDKAhCCcGr0j3DAFYqwDIcI9Y6v1YBUOOzUhEfR5If7Ah EVZf8CbBe4MjcWDMGWAPmjcHavuEJ1kImMLLK7gjQyF5BFCNKFewqcPmUBdcJ4y5guL5F3JfSZI5 HHMyLkm6A69vjWA3ViwpC5vpAXnOkUDmYNscPI9N+a990LtzIC3PR+CV6Ryee4wtTk46r/7a6Tkx NFf0lUE4dCB6l29w28J6eUhVWZrhe9L7tgGf/H3bmUKtJo2nJoZd3zkEpEz69iv0+PuAyQXZeEDA obJWkAH0GM7MmI3Iivg+3tRx/S62bTgu+f3YNrbbWD0L3IZJ7ffwe/pOcF5WLc6p5lZJFXt+Tmfv l4l2Mv5PpCv4fFsmBgyvG7RF1aggeZGmSY7PtsIpZbfH1IKootAiAjlcbwgEVeZBc3k1vNnTYNPu L2TjZEOk+8mVikYKt7SoKDnrfB226OcEDudlJBfIIeAKYYwyWEnHiO9l8yzg0cScLzA2OYYKJK06 hi0pNBidBxISVLAT+3YjqM0iBPxhgFz5T0EKe/qODCWBpyzXsvdQkd2YShQbe6W916diJhAQyJyh MqJF1uUiRfZyp6QAZgu9SYwhMXdbHJwIVjMBZZJzKYTxk7GkdCzg/Y4rd1sAaemIZBEVuKlNxe3E cR52rGRG8rPlceV0qnAt2AscO41I/i+2WcS9pZqEvXpZQ0BwsMICumvPw8vv/BSee/Ym+OND2F88 gNs3r4bxWgYM8BVs1qdQBGC5OF5QhK0kfOPg3r17cHhcw96VW9AF56Wo9lneBUEjSrlh3h4qf2Be qR9x/1WJIpbDSZnH7SFO2iT0SwKuUkqulC8mihYkdQBxA6dBxoR7xwyGo0RgnrQ7YYNcBdC2aCtY ovDryEFVa3m2I4FNBBGNGOSc5dDJ5uLm0zcs51L/0L9OfUSxX6/eWAqvsrK3j6/T95J3X8j3cmn0 eCSJ89hCKngBGzOC//yrX8O//Xf/AX710SfkGWD/tNXpHO4+aYjp+fWnv4O94GV2TQnHh0cMfjEv jBbwmnLJfvHz/xe++uK/wP/w3/xT+MP3XiPvs3VLGE0qWG8W4e+RssqJURNP+Ixnbmkg0/hpSHRr zo6RawUWYtbWTtLCByuL8S3kEVMKDCdQs2fJ4I8PwDkeyqIQcDZc5o69YTE/hnrCor+KrJjFe74h 2RGsvMPEb6pso+oqAd0cIOCEYsuLj3WKCirzJr0eZPE8524UIypn5vExcyAFLzq9NSfB6iYIHC6o qNpRkmSRje4KMiil4RZw2lOPdfoa+qT3Kan79z3OgqizIGsrI7flvVufz+Qp+sdREJLAoG6+uvkl ps6ACnhCZoTP5rVBL/Ff7UZ+jranTZKAI/+VOodEaQxrQXETPZzLzkuMrMlCt47ZSIJ+mdiwE8YF sqrLArbN9TNP9Tc0fz6rGu2RbPDovBqbxp029MGmlduxbUxc/j4dFnpd378FiOaf07BdPK4O74DF iFWrGUhLwM5unYfDa6frcGwH6XPZmPFnw/1tVlxUQE+6SATgumuDE48yPNoFBXOO8HMK3Cjig/Ij nmUeTHBuSeerDPtFxwxjXXElIDpRqJtJzeCze8542gsw9/E8OXNLqoAzjiyuDgUphd4PB8O9RvNz tVCB/V4+Ov5rhaHVOeClg4GB5PCgQ6MpKNzhA2KRA+XDda3kvLHMB4ncSwGek3FUUMegVPOUec6k 7x6CfS5Y8/5sJMtAf5/Q+Zgz6OpsabWsWBSIUS56mwRhs3le+L4VoepxzFMr+M7oeorzMVt3EagW CbCWAUtgOg7lM0desOPxaVpqe1goG8tWgr+j4wIWzKnUYhzOi+TWWyp5opX8vS4zYCjihixrtcE9 q4XDAMf2bn8f3vzRn8DubriOp5/Djqnh+q3L4RxWsH76GFYnj2C+eErFb5iLW5kO5msHn3/2MSzW HiYHt2F65aWAD2b0nV0Ahvhtm46lbLASHSteiTgI54w9u2kMthmneAM9tw3RUmhq1uy0Ca6AOWw+ TrlKBZfmksPNMemSQrOIjMOGh5WGAT0W0qdyhvkOYeM+LjsKm2LZM/UB86wplG8IDtJkxB8SB/aS AzUwjHGgM++GPucHxlGPFb3BoberelT9EAP3EuVcCwz/6gLE/C+DjdDD2z/8+Av4v/6/X8Av/u5T KC9d4bAs5gTu7MMYJ0rwrtZYqrzysCqWwUBNSU7Fl9zbogg3vwj/bhancO/bU3h0eBwW74i+t0Ix wgolLRoSA2zbOjuv7d5+fr1G9H3y5wmEqOEaPHij72LlFhuovNBD6QdD50/VnRh2dBK2Qg/CSbsv zDEQ8E+eXjyNxOyRnpyRSjSfn7tKKVjJxyiEPVPwj6axkpw2IGbOiZg0aSPhBEBwiLqEFXZ5aJiK N1L2jjl9I8zh5GRrlOZANX+s3qXWSbJGkAUoycMPiwvFHstpzM2J7K8keH9XqD8f3zi3ztnYtzEg +FAHJL1m44ZKxwCuraZxGx5DEvvhnHBsDFUNcuaGXQiceOC6aSc2WMGXyXrdDkKEvc1BXudEtnQN OZ6KG0MClSqBYUHDSrpxWhGodZHJ4PKL852W/kPXUar+HZ4/6Wbh6Q7SPHjzkWT2jBXczlBuz02N /w7eP5wjPn/ep/dvuyZ6jgIH6fXc8TDG9a7hPOCKj5g7lwkbq/MO2u3Bcx4tVaYKuKKCuNVGGMD0 3QjkEMRpcRAxb166TogygbJbef5XWU5if0/66TayL7VCRNQpb5oGK4m/8ripMLLY9VjcIDlSnt9f qHpBdn/4OBoiZFkQ76T5OnkiJWg2A73bsuOiwIA3YGUCU79dSvGiNKWOgZxIKxkpGNFiMmXKeuSG k9w5WXQmCz2mvDgbnZd8/ek1eQlz5nMut/n5/NPepiCjqLm2tLyt6b03ngdkhQ6QtFit9Ds9Y+t0 HooIdHREjKFcS1IksDY60tQ6lsamIUCH5BHKhKQ1leUQ4vdnY0TjLyCRWmKiKgdGBKuSpWRERmyE QUys8sXozt4lePHHP4CXvvcujBdzsA8+h2v7HVy6vAfH80Pojk5g8+gRrFcnsHIrqAOwxMrsbr6A Tz59CPPGwPWX3oJLN1+FVcfi1xMkHyYz2JD8TpgnlWHpnjAGmL6F+rp4TvRavokMFyrfNAOxua5s TsTIadNkUAkBJ5WHRLaAksljVxLLwlWQXImKE2uCVZphIU+R0TAtCdlR6yRDOuOSDDrY4Kw9U2mp C1JvwFC7LN44l09EECkHiNIZOskZAJYZGMqBjnjEmaApCb/igkMWLiCX+aaGv/rF38CvP/oMyumV cP2Y+1FBXTsqZ15ji6fRKICdWbiZDYwc6snMqNF0jRMEmSDU0Ns0sH9wBf7iz38GP/7RDymXq6Sw dQWLxQb29nbDGWywHiqeS2xs7qR6kNpcdaTzGFWwge9pJkTUH8/BhmILm8ZMxiOCFseeIerjcEsX ZtmwYMCIZ0tdJ+pWhBYthU5ZIoI9SSwcwPuMMi1Ng83amwBoGah5kRqAmLPGqro+Amy2tQjqW8p5 5kppbqyNybUd5ZwUxK45NqoFFjyUkoPC4rFU0ehZcBrL0VcoaYDU9QgV+6tEvUtDch0nZOIQxA2N Xc5Gnbdx98BM9jh/HfaBQnJW+p/tv7eIIRU3ODaAHsdEtil/GNmYNA9H2ZWz9W7Ca3hlatM8MuJk QTavetcn9zbPO+1dM7hoA8Dmn036WoV0XCDJBlnHDN04lzeFNlNUAR/dmes1Z35nLBZhUm/c2V54 Ifv0uf76Ye2s7aA8/67zABNfaVas0RtbzUkbtEQaXFNWKJy+PwNrw/mSb/bnzc3hhpw7zvQeYtC4 8GA0LSl3mrW1ADbrBk5OTjj9wKVuJ5qDhOAt17VMvXG5UjWNk+iCeWkIjjIMSCi4CdkRatoe9qjN omXbz9SzzGv+HAcGvLo5KUyYOQrqjG27Rwry8bqctF6ky6d7pLpllsN8Aj6s9xFAqZaoBV2Dmo4i zF8eFcKnJbysOm7EwmVzKbZFAw6Tc1778Nx1PIGcczvo7Tu8317GyysoBpA0BJG+IXsOEVhxrh/r vxUkAeMz9jetA1UrUGHgtE63MIMmRV4UxCmww7QXnXfYxo1SABDvAYeK0XajPmElDJZzyrnydZWj zG4YYTSV6aPRKShHv8WdFnVFK47I+IbndHv1Itx5909h9+pNWD/5Cnb8Y3jxUgUo3bY8fAij4wfw 5PQYjjE3j2RHwh7jqvDcKXz8+RdwUB3AGz/8CTR7z8LTJbaMbGGn4nQD3BMx2acsd6AJ3+3ahudi EdZOXVNbrxKjfP3efMlDtjJwVHNYaJJlQIWUvO8p/6tDEBE2TMS7ZUC6lENAoWdLuVq4FftqEt7f 0d9jg03ugbo9zEZFONkA5MKQrqsNEMbbOOq9imCnbcJgNW0CGxJ66bKJy15n1qYDFJxJP9GY45C9 n2ceswCiNK1VlwxQXDQilOfmOWRAVbIKJORguFBwkji3JDHF6egq/O7uA/i7334CG49Gaco6nieA TgAAIABJREFUVJgUSVLYawk3F4T+CaiE12qYQ1Pha2OYweUwDofhe1fw0muvwb/46ftw/VIAbPUS 6mXwKksP050pNJ30mbVtDAcgLCHZnXyTQF0mD3HaOtJkA05KQ/DV8hiRGpHn8e0Zd0oQ9RIKZaDG wyfVP45bg7V2Qt9dbsiNhDVuojVQmB29j9VsRMzFpC4orPd0s6aSae5wQRlzZHhRaw/B0Um7gCbg o1XDhogYJVygzjFrWzJL3G5a8rzwdbwkoLZXXZQc8ZRYUFDBTdeaAJYdNC1WSu/Q/NrYBQWLcWFv kF3Gi6HmxiMCg9hlpFsuAXYCWA/roA2eFwK7VY3nMpHiECCNOBBpAM5JrDgVw8lcKkzc5HMGk+2i uOvRcKlzm0LR+shTCwhItrmnmzZjBZQ1uDMGlI7cY2Dy1/V5ZeM1J5ZBjc3O8+wmf/ZaNG9QQVAf PDhqMxefg05CvrZ3TN6w+ky7EWDtDTf9ZiFmDp+x0ABvhk5dfmEeXe/o+h18fnptkW3C78rY1H5/ YM8q+TTW6bp7BRj4byO/a29gowChPx5mIHERW8EhG2N1zHg8TJeSyl1s98QMpo90iIa4+s5ABNea YtCx05rncDGodnGT1bkVmXGbAKLm5RjtZY3HxA2ukVSbw2DfmyUmx3B1cVg388MjPqexJUctrzTF ogZ0pJaLU+B+yyxJRI6AZWBDToPjxHzNNUth44p0tUYVn+y43KPwFQq1ku4mFgoYH0WgUfrEi1wH MWnZFk/3gbIv2MkjrGXS/kCKJRh2k32mNCIy67UKFfO6rTgimCdeiAAx55S3KCDV8bzXhyP2p6NI QTBuYDdrIUuAcnixGbstJ3Q+CISpRRnfrbhyee9C1sbG3DvtkpCDOUMVpRV92ncS6tZQtALzcA1I UmDRGSpENFbnl5f3lLHJfatzy3bS07sNtnrE4xkHVUgQXR/Uzoa0Z2L3lzj2eI02RQO4ZZaIz4N2 HsL3tXQPCpofKhGlxZklTxnpz46bBKVMMW6GMoCqjvpbcwpNi1Sb6yhXfWdiYRF2smo1gx3Yha7Y hP1kTvduXezA5NItuPnjv4DLVbiTX/8KXr46hv3ZTri/Kzg+fQqrk8MAxJakcdqsV7RvIJlzePgE 7j/4Gj77x9/A99/77+DCxZvw4GROFbBuPIElYglM40FCw/LcsZheUIxoLtPcw8nnN2FOt2fDqTmN z7cqhWyMxLwxZ63RHCC1iE6SgLN4v9UKEcsVgCAMG07scZjSs3H4QcQZkPKC1PP5MyTAix8bVYnB MRqjHhQyOPWu0gTOz2Go8cYXo6FHRxtu3lorZ6NI1M+aaLx4Y+QFpd4FskCF5VDhKoCHRw8fw9HJ sTh7yCZtYv5R9D4MfzcOH+aGca/FgpY5MkA+LM7d3Sm8+frrcGF/FkBJAEqbVfRyFhvOHcHqFePS deWbO49FwZ56b3NK44cJkyjBQR0hMGgY7gPlqrTMYqB327brJIKZeZF641VHi73YZEqorQsavPDP YrGARXijDV6PwQa+YUIvgmeys7dLhkrD8jjhcRGFKQ/zAPRXYcKuOzZInHvTBA8HYILivMCeSRte J02pMKgjP4IdM2KPjUIbYW6tfPB8Sip4WAUAuwmGakXVRS1Vwq4cM5gKEgpZzMjcIdA+tWEDwPke zrPJAFHO+Oaeus8MeB+YKQu6nVU7/3GWIc3vdf4vRCO4PU90+Fz+OHsMfd/gbHz/fLaxt3q84fds +132ZImdp0rXRB/1mczhOLSOw2GehSRZdsGIhcYNI1Ybps+el7moDIoyg3RqcU9Ti6iMy3lMamKP gC4rayCvB4tMGNsBBUn0vph7q90MkkOZjwPZcAFsZMfEMeVzkrA2pbjouCqbDvK9AtbsiIqKKBHe Jc013vQ9OXmcLM5gmY+TVAq6BlNsWmJB0HZRaLPLQpjBruHaweshTbZgENaLJQEMbD3YNjx/KKdN 7I6F/vWmn643j3m80tgrAeGzJ2ezWTinMVW6Yjsj/R7+t+PKUB1fD5FJN5DWhM8kO2Sm0LhoJiBn gbA95xaLmbSG4a4gpEcYj9+SPpn3LHpPgFyLx6ghe0fhtoJye6V4DoFnZ6RDRcuMkoyJI0ZP5p9R q8OAkoElM8rOpUhBdDakKITvV8pvTDlg+X6bsWIymQgQ67lYcU6sRrk4NUrvDd8f3MO6FNK2ac+y mdMR97DsXAmD2XRfXCFizkLP4HEx6Y7nOPd0R+DkrTLFZWTblOgoRUiXhYuZIHAUSiyoVePFAJxr XBfjDYXo25MOJnABpi+8AeUbb8Pl5TGYp4fwxq0rsDsKc6o5hfnpESxPnkK3XsLR/IhYu3E4n8XJ N/D0+DF89uVD+OyLJcz2/gB2b9+Cu+Hz2IZ0UgWQNl8SAG0r1DXFFK0y7S/SpxUL9zrL+yvm2n9n dSoNnJcCNcOAJw+nNhpStdKSBT1rxx0A2G2xNIhYsYlcSUnh1o4U+y2xQCUchQ15XaIyedhs6YTZ mMR8n46IvWxSqZERkdosnMDFDvRsXORnNhvPif/RsDqebMzCscGz0v0AB7GSUnA1WthRjOP+UgFD HgBplIf3ezg8msNiicUHB6SVgx9gDSvOU6AJRsUbfJ644EvMF8MJGQAI1FwxOioLeO72s8TgdW04 nmwA2LKrQHYNrxXHvU3X6jKBVQ1BaqjMZ4wmtS+TpFgS1y24+XI0ovmG0RnlGBiIR/vIuR+d4aop TFjFJHY8s4YSRR31mnsaxmJvtQqAzMAKARHmGFDJdwBqa09Ai1trsX6eJ2kZB6fYEQSBXLjs8Vga ZTcOlt0Kxi3mQvBG2gQPct3VNDenuHl45HYr2phWmPyJjGhtqeJ5HjaTeQCCJwHM4dylexwuqRHn omASnvMdDUsDHOF7fUfh7NqxMCklHbPkP6hmTz7P0jz1wpQwkwTxfeweIdCjvrv5pgT5ZsHHGAKn +Eq2QedrIc9nUcM7BG35d/VfM9BnnAavezj3fIbHj+st+zvtu/zZjt7DTM7gCNBrFA990BuP1wlT xTw0gzjPeUHkNHVJ1mAYVtz2MCKpwB/gCuT8nNJY83nZ8my+ojpNzCCmaEDOaIIwhxxp2O6IJc28 JOVBR6fv1qIUfI7bNaUzdzJ2Lvs+/ky+QdJnOz2nfk4w22BPou10RAQO0gZPK0Q714L2dOXWRVLs JrJU+DVdsPG4rp2rpcou2MjjI7bvXRcrUKkHceYgFZL/xIBRQWNGDhBYy8OuZwP9PMol3cNqPKKc V7RJ+F0qY7KpF9y9wKcim5hPjYSC5BxTJx8FB+Q08LxGk6l7Qyz+zNhYV9c0Fzk/kkFXR+PB9scK SLbSPg1ziBEQ49iUhvO1GhF2dWXKFefcQL7XLCRcRLbZiw2j/VqmGkVYCGDjuLZZGkYbwSCftJe9 Vplflk5Rx4OJBI76RPuTzV3Hk0UKG4HYU7YDsipMCsniozBOriDNXtV6s5q4FNe/I8BCRzKZHYp7 m+NokUn5sShG7FhcjexM4Vl5QfuMkzqBdEAyAmZxP2ikYrVeh/OZrKFoDgOAC2O3/xqM3/oAphd2 AB59CxP3GF69fRPGsIR6dQQnJ0/gZHFMIK5GNpmApIXH974J4O4QPvr8E/jwk/CZt/8SfvzTfwXz yRO4//QYJmH+7WAxxqamebrGPdJwukhRMCEDAvY1b5SxS1g/SmNve2jIA0z6W0EcT9qON11lsLLP 8g1nfSD6MQziEC2janKBYcuRhQs7YzhdFqQ8PQqADhP3aEPFe12zZ6deDbMbHpQFokWiLJkB2NYW JT+fsw/2WM+rKswTaIm5ivykJpDyMdqO4+cWk6iAjVK5M4F1UwZwOoJ8E2IW0NBE84arYLB6lRr1 inAu6Z6R7S4ocbjwniaZVoMiBY46au1qERb6JF6/MpD5/Yv3EXySagFuRoxfh1psQyayEJVrqsQs dAyKzIDEQSXApiCOK/nlPA23ZXkajOAuSsmE156E967CG2e0wIMBXa9ZT1B6KJKnL0D8JJzXOvws A5CrEJaVkteCyb0Ntmqr5doKylfwFLDhxGPcXCqqIm1hb7QLXThGHcDbIni/J134adcBVDJbsAx/ 7xluCt1gBwfLpeo4vsgJritufLze8EZaSU5Eh3S9tm7JCmC2M1A86iAbbx5Gc25YnACD46gx9TEc kh+3/zkFN33ZiO1LQo+/be7bDBB+F0uo53H+e7bNx8GnITFwei6aj/UdCfqg3r9sLABi8hlAONFK rJzdql6v4UBu6J1XY+bv83JKZ/NsIzsRmT7fO7Y+xxImZ6+bQ6X9l7zsuMqW0Q8nnWVSL/xIW57a xCHAZ800fYXPVcbUqgOLm1ndsxNs3xvp19wQ+8MOYkvrILI/5LRLiKoTJ77tYl9tbI2IdmC1ceQM Nw3/YH70wydH4XXi/ul81M7i2mJg7pLNB9EnjVfCTqNWg6rcz5D11nuAeUsaOqWoTol5ryMYV2M6 v+W6iH3AuwhoGQjQ3pOPTcdhZh0nrgwtecwc20tOATNUpNERy9ZIIRbnl7Kih1bpyjVhq8GGBasJ FTpHnWfQqNaYz9vUcmHcYcVy2ThDH5o00l5S+3Xr2qaPyBqmc1MqlgsIeQ4K+6pFQBnbmBjcnE3T WZfNcatzF6RoQ4CUdF5i1m0wR72sSQJ8UuGaO2u0djyFE5Od83TuupfRbOYkN3owmS8Vw3IsnbNp rcj/rbDt9YbYLipaAM7DxwJLSyFXxzJZpw1ps46vvQYHd34Cbm8XZot78NJoAQc3LsK3X/0DNKsT mM5KmC+OSLR+0y5gFP7eBIfly/v34fhoCR9+9CU8OrLwhz/7n+CNH/wYGtvA6hQVDiyRCvPFmiNB Yd5scB8OcxT7ypMUl016g+le8F5bRkCmN8eYONQpJAAUP9c4NIjUCC1svPEafwauRGWjgfF2FgJG QVZsJI5J7OQ5d6zXMwnne2F/AifLEYxGnHyI9HwRDO80AKLScbI5sm7YMBwBYEdsYBPnWZ7Yq49U wYNzVL1CI2FBBz4yVvTmFF5RsKa9WG3aADkB3EbPgsyIZ+FfSn4Nz2GO12wyglkApnWJwdGK8uLY gCbDwsai43VjU/UtUDVNRa/hCB2ezMO6vAFN8BZtAENo5EZhHNfYoDQYgXEYl05vqjCMeq4uD/lQ SDgr/PDpejlkw/dDwRyFRQTMpSTjPmPEz7GeHy44FEOkPETLrVQwxFwEL3Mevu/rzSmcFhs4Deew HgVA1np6jXopOt6wscoX7yV6/sgOLoJRReO6almDB88V89TK0SSsPzTwKzKS4/GM5E3wHLDR8LIO C8kF8OwpyBB+Z2OJi2QdQNlJOBYmma5qFgut0TOWrhstdCIeg9XGNUmXINOH3vG64U0JPTv1/Hws +ugX1LCX1Eoi9pkMrD7A+z3hwhTKOB/oDR/nHWv7e5V9GebI6cZ4DgA593jnMXz91/U91GXN9o1s /E7PFabRDg1CbNu+x0g1IXvqXRIXBX/mUrxcPwzuQU4K8qnlgGlQaJBSiNLDZM/1xkrfnL8n5qMM gL8yjR6GJGUhTJAVO6TjMHzkDpfPCm7ixkzNeXkdYFqIhvoYtDEDZkRqQeWlVFpK941FvSbwhp/H 9Yi2DWUbaipsYO1H3JgKlAeZzGC8M4MSPToUgK+5naOekya4dy4BO7224TrQH+55nHIk4w0QkECB oQxwqKOrDtHB/j7UmxZWGC3YrCNDp1X/HF7LxxQgatINxlqdZdw+iOUzG0pUt8KqIoArJSSmc55x G4dHqXjBd+Js6x7FzF+n39FJJ5I4JtK72LPjj/ssXb6x0CtI9Nw1gQSXMQesKgTwqLOxjelPnoMH jXT11+95DL9SgN5qceDQzQBhzQqOaHm+/vh+2aZQK1Tgm4yzFBXxidOBnRSlcGKFOi48B5zvznyp Rqjw3yocv6H9gfe+KpxPhQV30HBOX2Pgi+IAxq+/Cy+/8DpMVscA9z+B65csXL62D19/9hF89A8f BmdhAfsXpnD5yoUwn1aoxAuHp6fw8N43pP/WwkWoLr0JH7z/Jrzy5pvw8Ol9qEbhIucddWPCNXMS PocpUgWNNGuhphWcomSqDcokgMP+u479HN2MgCet9iqFGNJoyWCRKJ5RJs6JenHLnp/V0JFEt+l/ nMdV2LABI71mOoIsKCOB7MeFcAF7szHsTiuow8k9ffoUVhd3YH9qOVkWmRd1RNHguU56qiZE2rtF JiV4DnPc9LlU7cgVNHn7lvQeAYNq2MXz0jZQBOJazgmkJsqGpTEu7E3CzxSON+GaJztQr7kE24oQ pBrCKKhJ8h2evC4CUY492WX43Kef3oX523dgb7oHsDhkxioAGdJfI9bIxRBqzspoUYdWVrEQqZWQ rhoiZhl85tODqH9rMjf+tJJTl7w7L4uPf5jyLghUYqgXQ98IzkZynl8dhvNeXITjogoGsoF2gh0R CpiEwywxf6QBbl8iWlHs8QJ5shSy8dxPlRacb8LiqslQGWmtZet5vNYqfPE4eEyTsqBGwQgMyzUW 3TD9vOlqOFov4Hi1oJZvdH3h+bXtCCw+rQsC4qgM3qFMDjq4Fecp1pjD44TtwXENf3dY/bT5biY7 7UVq8BJg8kN6JfuczuXvAiz5e+Uved+2134fqGMWWD83zD3aBi7pPab/nIY59GmbfU43uXgt8N3H 5yjAWRHY/O+hjEv/OPbMZ2KdQyYL0vWAkJe5LuAlsoIAypLRuZkI/eT//WPwHwMMB1kBFkhfyuRR Dd/MG6s1vc3PyMIzoOHUZJ9Sugtrq+UiuNHR6HRMxY5K1WHbJptOeb8C6LCyVD+r+WQaTsV8xA2x cMz+lgGYVdUYqp09mKKWZFjz450pjLGDSnDgMUxUTWdhsX9KzlhbL3oOkF5fHgHB6iDqy6zX6mVc nHTOMbB1nur8NZlEjCggy7h1Mn8K0qQbhc1zFq5vuVwG24O5cyMOUcu54TVvsOq1a6ND7sX5YUDL Gpqe6UEZpw7Lm2gu4R6GxU1IVuAego3iaX45BsQgKQxGC6GEZQEtzkMnF4wUtaTcQKqMDhu8oy/A Bh18bDRe3Hkn5YVTAQI5wLznGIGHsusl4JPNJwb0JoJ2Cst6YC277J4ZboLD904KbHzyeQRX5/eZ C4IoNUX3lig8bbJ1IisvXwQ+pVWB2tRs1RAoBBAolNkWl/O5HFbFYhMOoXrSmsOzRBHfVmSmNvYK 3Pzgx1Bcvg7LB3fhYncEr76yG5z7Ffzilz+HzcNH0IY58/Dbe2Au78PV3Sm4+QrmJ3P49t5DeLJq 4fIzr4EfXYdnLlwFzJi69/gLmCETvMSGVQ0VAdXUVs5Tyg7mQs4mFaUcobKF8Yn9pnxfrYYHKfbI cyQ6CWWpMcFftQ+o5gwg6MCKDlzAHeWINXSx3nD/SisGA9kRx8iCBhWF9KhPph0RkBuR1hqX6V7Z 3YOTCzU8Oj6FJ0+ewNGVfbg82SXCOAKeTm+elm/L1MtlSKADhXc5UDJ640GSFvG6TBEbBuvnc6kR DRszwwi9RUN5j156ugInXFLyaxiLy5emcP3KJVg/rMMNmIb3r2P+By1QNEroDQlgaj3zWZSv2jUk IohVPu0G4Ne/+h384rWX4A9fuw2Xdna43yoaVo9lyoYUnzHT37vUz9RBf+OXAGXaMAnduxhiweoj I6ELXagKqNBoq6cUWwsNgAWNg94erBYNoLwOB5+IJ/j1o8dwPN+Hk8kUinlDHROqiYWZKWGJgLbh MdfvpGOCicyAAiECovj6BjWmMPzMmnAk6Og5pMnhCksMJTG4wOAZBRLLgufsPBjoZb2hcA+B4emE 8ueWHiuV1vw9UDHQRT3CtsSYM5hg6NfMb9JGWJQ6ZklaIuUTCfCgMeszcXHDkYq3beAl/33493/N 4zxQs42hG4Ief8ZzHRwzcxYUzGwPIW8vpjgfcJ39riF4GW7W7JEPwplZKyGvtguymtu4LuDMd/Bx ffqcgShpNDyHrWMTH+me9yrFe+81kg8oZ2DcmXul7JTLtihS6W854Z3aMTlVDlC2rKMKxxyIqQwI rS9VrtfOO5T3pULuXjTXmImiHtktb7jxOsn2ToJzw6VYl3Z3GMCJzAeCOJRhKMcT7iVcomKBEYc3 OFRhHU2mUzr3cVVSYj+N2EDGI0aIPDv9GnrLxzsP0Q2lpdL+wDbMSu6ql5QVfR0dZhSMpRSYAOTQ VmymEwmNpspprAJExxJ/sAVYWzdxf+B9QcCv50pPzr1zlDrEzKUjjTEGPBhIZgccQ7SY7uGoRRff 80LZe+f6cw8Yg6uoL3SNKAfwcYqSQ7Agyf8M5BNBQe2jLAMnGgNavzKnB3PceZ2DhQBNnV8uKzwx PQbUivQJLhoGUQBJ90b2Dy8pBrH6mSGYl/PN1wYxrV1mPzKi3kN/beocInY6E3WOEjHxEtXBYjav dSzRhQoaqM2H+1HjSvDTS2ADLtl/7Q/gBgLoLz6CnQMDLz53FY7u3YVPfvsrOA5OyPzxA/j666/h 5rVr8Nzzt6gI8dGTQ/j446/BlDtw5cX3Ye/gGZivsG3WggR+qZiPGtrvkAwWivriuCALWKgaAOEJ dLQIqokx6zLwynl+HMXKQNzwofF1jjGniiRnEkjqC8dKBavmKxgGFYVnNo6lNVB5JWyMJiyYgH+n YQJfDJ7b1YsubLAN0dqnq2W4uAvEdAAkQ5vT6Hrerss89UGfm95mQ79rPlrabHPBVL3hGlbEBV5w VmFW5YZ3vovVYKR7ZlhB2xcb2AtI/PKlC/Dt4TH1BvTBYHXhOCgKyELJOFmYYsdqXAKCtGY7WG6W wZjMYDYeERN07+tH8G/+738Hl6c/gzeuBaMYPttYTCgOxjG8pwhj2PauD5hxi4DCUP/WjnI2tAqu iJ4efgY1dKh1DSV4Wqp+Ynpf3l/m+VVskCID4KViCljYmfqlYpIycK6cqdlT/7ZewmJs4BICtbBy jhZzmGAIc4Tv5dYxVsKVVC+AHpGyrZT0LqyhGiOLBn5NhiWXvCBnNBy3kmfpfhat/O0j6GgF7uMi 6cKiwxyIyjDg4zlfADUg2XRYVYEx1TBXO/KSCNx1EJ0VTsI22ZirQCkfy4kEDq+xIWvszzyXz90h 4NkGYoZM3HeBQj3OeY/hd+bfmwO1fA3qXBgCud/PGv7+B4OY77ZPNv9eL0UNPn8PF0BFAGXMOSOO D8kDOucNw+rI/JoSaO1Xy+fdA5w7m6qSwu0F9OVk+DpQSog/y3aOGJ6mjUyPw+p3ZErU6YkhU8lx 0vPrWsmpbSAWH4Tnlq6gOa0V1bS+SLNtDFUAYJWANF0XCHaqsCbGoylXygGHB7HzAuexdeQsIevj CnakIjhT2xTOa7U8Cc5fR2FVBav5XqQ5dJ41kxhQC8mgY6grKgchQ+ehKOR9kZ3O9yug9B+0fTXl //I1zCaTGD7GvKTxdETVrXhcipIslzCfz2G9WkguXUeyWfg7OocI8CIIF0DaCcVVOM5Ha4QUwVw4 ZEG9gDh8dJLzRfYrd5qciZEQdVypI4p30b7RmijEtuDndOxMv4qeNeakKELsYgK3HGnirS6rRO40 ZCxjScUALKFN40l1bybdI5O5H14zGQmKcvQG34uTj+ZJmVF7IPfTp9ChTWybtuLEt3cuE+NWkCgF hDqOxqvDJ+COtPtkniEhQKFuTNvZQFOH76wOYPeZF+HghVcoCnT8zZfw7s1LcOuFA/jko18GgPY7 qFdr+ObLr+HrJ5/Am3deh7dfvwOP7n8D9+99A1/ffQA7F2/A8997C07dRcIx5WgJLjgAth3BLOzb GMK31Zzy4opxCZNgp9rVhtKlkKjBuUR5jp1o6BneJwk0+8Ta41oqaTAYnnOLI1zEqrgNkkuSLcSY pOn5ANoRgcpvvaMNkRA/xmrDO2qK0aOnUpMeCxZW2nDSCITGRfDoZmERLdZwaTKF5aV9WGBPsvD+ Dqu+SsfVXyWHBSCCLJ7ELTXW5NJomo7kcan+lkh4FGxYkQHU0ACW8mIZPF5ZiYCJjJujwos8F4PD m4x46VuKlGegSBjz91z4HLbemI4M7HYTeO32q/Dpl7+EVXnK0iGzYACCQdycbrgfLLJVmExLYE7Y w3CcCiU9aEHuMGCYWvj4w1/D/3L6GP7Fn/0R/NkH70CxPIJLJZam1zDH6l/NtRMviNhQy14yTdJN Eu6kBcix1FgQ0kpD6aippxuyCiuKhIF1/bBhKwnzqCTdrloC61iSjcBnh6ptS1jtW9i/dDFcVzD4 YeKusDgZPZ5gZVaGk/rHVnIo8V5EwOiiGDNW/EbWT55rBAyTcULxXhF7ZQNUS8WcGLWar5vCvlmj a1rUZUEFFmtpLJxCc17OAquFltyz1jSwXM+RI4RmVnCV06oWT9Qyq2dY0BqBZNOyfl+h2SRZTiSP q0whmcsuOhn8/tg7UIZctZggA+C4yeXhRA3leZ/yJyIYHzAUukZwA+5rz4lwprY5M6LDSD1/jJgN L5thR5uInoOmJeTzTRPU2Y73mUDeiBIjqRtI3KYNbyL5Z/J/ccwaDb1kwLJ3ndTPeMAaylBSmoaC PBrfohdqk5OM9wQ0tKmRCQT+TkJ/Vt4DfRCpFZU54IgsUQeiOdtxFas6xp04UeE4600rYyvFBtLB QEFCu14x42X7oq1OWLnGcfoG5qsh49w2mgON83RM3WJQDHs8C04hSjoRIKtgJM3oUSAbTaJWi/JP ul9YVGQ9O0SYhG1krErJkWab5FhHEW3PegGmXcFstgsnpwuYFJWMPRdisL6cJ6adWSlP95DuDrbV EwkYndd5R4x4y7L9CrUeeR0N8740JJfYn7wBOmsOlsR6blbI2lvYvbAHV69eonOrwyaLrNymEXYO wd1qRULGywDuVvUqbMQrAgbrlSewOB5PI/kxDQ7ser1kBx5DrGFz77yXgmVHifeY8E/ClXPDAAAg AElEQVQRb4ddYoA2axpPjGDItbCorowzeZ4ovjSiaAXdbzeXdcxamxVPSokse3JIfWYfnGH70cWx YoIC+9xuGk6pqmgPK8jBAj4ifTc5OSo0L0oGVqvTTUoe0QIEdswt2RDKNXeaOyhriVK0hAUWR572 eBUH9owFtBJV7ytIXiF+c4msGtp9zDszjpyfosOOC0xMuUlFxU8QQNkpVipfeAmufO+PYXZwAZan X8CVzSHcfuVWmKcefv4f/y08efQFPH70AL74/G64bXvwsx98AJcvT+HxN/8AH//jpzBfjuDG9Xfh 4Prt4OzsQhXAPoJv3C9G2BqMCiY8CcljFNM2RZzHyFJTCLjgrlZk6/E+YFg1PIcpSq2E77VfLLLf ZWLU0sTPH8hOaMgSjSbH1R3lKnW9FiXABoyzM6WcWg01sJgebqXIxFFfTGY+cBKNKwc74xZ2g7fj G26MrqyRFhRojopuzoxOMyYAUqVgZGw0UV8qbHOAFs9XPT2pZst7YBKtrxtE9OTS9fLga4UQUDuM WViot2/cgIP9jykfvwo3bo2SI7gBzHaCBxrQ97oV1og7C5DIbsNSJVws5CgsQV5c+PvjTz6Du6+/ GK7nveAVhmMsTmE0DRPEsYetVbK60ZPRz/JMnGYd6EbHN5YmetO2kX1UKZX84cWwDEM9pBulrxNY SJsd51zwdl8FAIuGhnq9YQaC5eozLsQwPdFZhU76HXoP+wnZ6f6z9yWf8xxJkMuMOUMOM59VrNhy 2KNTut1w79ROpkUMGYsBQ0+TQDqkvB2dd0RyFymfUkVP858++5bAg8nG2UuRDo9ynkgs4EWvKaMT nIDtfDzifMzuX5cBoPz+5euA2I4MAA0ZNSpcoqxhE8/bpWAJpVcMP5OzIdvYPX30WT59D+cW6XGK 2KDbbf18HK9sDIZVXAzgBiAQWQa6lubM+OSna+L3Gt54xC7x+VpJ4ADqdZzutQJrS4KuGsqia5XJ qnOKWNu8aEAYM5LdQZCGofzIvCiTwUCT5liwITXO75arK5VF98Kuddp+yZQ0X8cE1EYE1LgaVKrp w2ZQSO5oztp4l+RCvLDiWqdPwMprGMsLcyBacQHkoDRPQ4VsDR0H2Qsck0fffktivijKqxuwFlek ClET731+jymLMK++VufI+949jPYuAnfeFP3gfeetHXW68K2YsrHsmGHE8d3d3YXZdAp7e3s0/6n/ czh/ZE8WqyUsg43HiNIygLj58ZNg8zcBCHIObk0sHd5FdHTHxEYSw2XFJgIQUCcwbFjmArv0qG2g IjWp0CRmzkjxjpwrjhn2EkUnGsvplyvOfUQCpZAwqI13L9kXHQMtXtBcTQ7Pe3KmuyzFhcYI5xOp 9DuSCmEW24FWt1MEwmukC0guK611L9oQLIhCBZHMHfDrDqQYQ22udlnxid21elu3Xwue52a0JMFh Vxd02Ammz4SDz8PmjKTAfrgvRXkCh+g4Xf0ADt74J+Ezc+gefAjPdSjz9QxcOpjC//5//Bv41//6 f4adAPq+9+Jt2L8whvfffS38DfDpF1/Cl1/cDWM2hZvPvQKXr78IXdj3jxdM4vBwGdawy+cYmQhm 1QrRK9SpGdlRcZJTazIrMi8QHedyaGSHII69SCPUqAAc9MBQAJX6T3KiLCVbim4NWD5xOqqVZGIq duA+lCD5S+gXjFEnK8zRzcTBBTRE6xpKaaVDcXisZKwMqIyDhqqAry+rADTioSU2ANtnRI9NgR8t B+6rSZM2y52j11C6A4GRCut12vopBziclEweNE5iEYvFSi5MS3juxjV489WX4T/95ndUdTKiRu7c 8BknJR+XF9di3cD+xQNOmg0GArXyWBMGe3OyiO3Vq1fh7bffJokL9MzHoxmxkJgTR+XHWYCIKXeQ 8eiHvDjM7UEJ8CTKKL3iJI9G/475gjrYGpL0DDyFo5Xx72RDZ4qJBCsLLrU3xQXSafIbTxtWKcwL 5sn4uPLyzB8QcJZQmbIYPnM4cBFSdbqGWTKv3MsmW1JOkbI1svV66FWcJYbBnAE+FJhFQwvcP5HA rrVStVj0wvGdJjl3aa7kOVHbHk7a0igTofPLS8iAzkmdikLPUXMHZd7HMUn3PT6sgscs3JKzQW2a +zYLWXj5blzn3J9Wcqn4onhWmHQv8gd76D4ame96MIuXATTf/zudz/mh3h6AG5xL1KkbMjZKRWct qPLOL/E7IAOnugnFt2QK98BFHNyOyMkEQxDlZBwVpEkxmOZ8UZqFtjRK/Wb1dU0XyEGcd8k57jRP 0wuDWSDrz3MV1erLyYyr+6WlFQv3JqCm+abM5LvI6FCSOnAEJfbcxDmJc9Bp1wEWvUX9N2SzMYxI otiNSpRglTtL+ejMmgUnlBmbjtJJQDZ1tjeSE4ZMRCHMG4FIBgYxZ9mo3SBKp+c0DB2KSHebPgtK eBxFVeO9THPICVjA92P3CGoagSAtADO8xvVyBTs7OzAdjaGaTCnUiq0G8RyRbbt06QpX1of3N9dv 0b+L0yWBPPydQrAo5IvRmJMTar+ITBfehko0SjGpPTqy6pC65FCgna/D3jSuUs9sYpxwPdc1MVst FSJaqDc1sVNslwwDJYlgFRkgzomKTh07+t0Ap3VzOgk5IYUjwVkEuFGdgo5byvLS/cHFhVTk4VyN 7JCzr8w+3kNmcJlVBCGD2JYnZ8ZIbrpgEwFDRro58G1nQNTamsBsRTq1hp2d4FhRm+/w36JBPbcZ jJ77Eezc+X5Ytmu49PQ+PLtXwMHBLuz6DXzz2W/CPFjDs88+A4/uP4IXXngB3r5zE44Pv4Fff/oV 3Lu3gNH4Bnzve+/AbP8qnAbwvt4sODexVSfXUgi5i0QLjz92vsL1iCFXLR+M9oymt4ksuLKjmier DltP7HfokfZCL7opiagktd2S9iFUYUkEBZ4wBdakOTRXEFGPPMN5AJXD1haOks8RXJZ4M8L83wsr ZdGOYNWuaMKRN9dohYzmcnlirzoNAYrxYtZEEvw7iJthvOAOIluWL3DakFsfEzzZkxT7awQk5hIR 6q05Dn+h0W5LQQ8de0HItM0mF+C9t+7Ax19+Cd88XAuo6EhiBSu4MJ8CKzWxUunCzgUOIVB0sCAK vBAxXk/X6eGDD34Ar792J4CgU5CCWOqrNhmPyavAR+sAVOh0GD4TUrx3/WoUtNG0VoLGnomygGNf usyAxOGQ46AyNm8sDqLeEDaQx964JUrJGFSjIm8cNzPiZC1/f+5Um/7+yfMtY0X1fuoGptIuOfrr XbfhNnBZj2YOi3vZFjyI1hLnlrABF400nxt9DllogiyF+LJx1kWas3Bx44ctXn7uNG35DWKAGYRD ZbrdDkKdFHI2UiWXfZfOU/6ewRr2vu+JD8Y7AiN5zQlQxG/IlUCMMOQKoPPPu6jyftYpzB8MGHrQ PZ2XfK7pdSTp318AyK6Ef9Gq09zhomsffLcm+xtlauRq6RNnhIchA3u64QhTOOIwJoYUW5qrbEB0 /JtgzxS8YQqHcV1UA3BS6BSBrmreYc6UaK+VRh1P2byIgSiF/SrISWHWquKG2KaIx0FJHg0PUuil lLWd6WliOgWG58h+SV5oQWtKqjcLlthpNi2BNQJndQJpTrs0aKI/8Nq2ojRfTcacM4fFReHf3Z09 WGHUIQCgthONMAKvyr5ZskmbtTjlLTu7RiseiZkZxehANEte81n784vlx9htZfAgFcakYaHz7awu os6auu4iiKXOQWEsVouWus6chDGdjAOYw0KNomKAVBYUbkVB9osBBHRCfGB7QNLPE026BRZYLZdh fA7h9PSU9gRy7MFTHiS2B8Qx1XtHbGWn90RDmBXpfGrOIs7htrPECmPKDs0Dg3OACzFoHnkuoisk bFcU2VgpGLYJCGObJ5KNaT3JxqA9wL6ezo3C/eRUCzwgh/TzThtWWL2UImIc6/9ZeV2jPJ1EwjgV RXqXkm1BnKHMuk32R2w2bjesXFCQ/cb9lwoWs/Xn6wCwyymsqT3aAqZjDzvh3mOIG8Pdpxefgcvv /ynsXLoB8OAf4eLyLrxw/SrMLu3Con4Mh09P4dHDb2FvYuFf/vM/p0LMcRj+u199CffvfwF3H8/h 2tXX4NqNN8COLsLTxSqA2zYKWLssXUQFj6lUJ/dbFZwm2qL3UJmvbmAbuZMIdrrKch16NsuoYnU6 tKJz75yUmdfkqVMODqpAo7ChGXHStySJUxspAMpdMa0lSQdsQs5KxgZKzzpydQBxewGUzDdlDItB hqz51lkBcjIxdMF5LaPONlXdSFwqYtAJxmGINHE7r1slcP6ThEOQAfHZeHAIsGPPznP1bWzgLAnY WMQAxQZuXjmAd159GU6Wn8HJYs4Ap/CkjYQLfTKbRaOynJ/C7MIuTeTNag2TKQtRLgKaf/H5m/CT H/0wADhciDVMgnFYB28ODQe1Imt4Ehi9Nz7ttFQQIDlXfH0MVNXrB1BmpyWQx4uQjV4CT0UPlETg ohMwfi/T+vga2o/Kc87C965eg6/C84dhDLCbB+bQuQ7ZB2YGfJcxGYPJSx0NMtV83sBsrMblTd0K GyzgJbtf+HdHBtxHtML2gtkvrxGyDOtE9g0kfYDRabxurdr1IKG+LPE+zjf9LgOp3+SANUoXbWQa +9iUvYiUIh0UVOOslfvQORc3sRxkbwsT5SzFttdymYA8/BkBbFYJTrkzkZXisTfZNaVx0JM//5HO ofesXHYRn++y7hF8jvrOdB4grCW/Px2XvsNudw6YV/SCAvX+SvoFFWjJ7qbgTTQV9NIUpIIksdei m0nrQEKjXKij1Ytc8AJ6TkaSwq3oZDkuBts0It0ky6LREBiCiJJDoJjHW5WjlAbhWeJDUyLUJiET Nx0Jo+M3FBL3Wq1I44n5wSWtQRKd7kRWhHqNbihygM+rgG+74evKNS8rKrCylPyPeXRapVqOmP1D 5x0lPKjNVgABWLVahR8M6TZtKozTrjk8p9kGtSToneUZaksyyQnU+RkfRpm9fFPkqIkyNnK7IRVJ cAcbnlNZTq7MGSvFIUb0MjjC64mdR1WGRe0JjBEgqsYUEj6dL+nYmEM3QYmVcP3I2nH1bgU7O7sw C+OJUYpZ+B3z6FBaC4EcHouYupb7YFcSGuW5L8K1BNoKAtwY5rSmjCG2ToBNORIRd3pvRQV4JEpP ee8M1LFCFls8xvHyKYVFc5KJFXae7lVNkROgOVtjfhmCbOzlig4ARlhKzp9UcWUGW6pNKhWpXdez NSkqwq+TAyBzH/MRlX1CSfc+ThFpLCPOF+WIadtHcfRxOrQspNt2YayRbAjHfHS6gaXZgb0bL8LB Wz8Nc3EB7tEv4WZ4z8vPXgcfxu7xwy/B1it4dPIozP81Xd8s4BtXbeDRk8fwyed3YbHs4MZLP4TL l26Fa9iFR0eHYazC3jwbheuscPGGyxYxbZ+Jjos3Qmfuupjr31ltT5o5v6a/9xLh4rPuGR4ra62F 3PjnD/qQUUI0hRQZwJW8uNsNt1WhcAFWLTQcfgE2nhTOwgooaiCBIraYw9HAiOEplaCj4OuoLWmi T6pJpPvzdkZqFJVRo6RT5+LfyjrohZIQsdMNIfMyDAhrJGXvjgeV9VeY+cBFwb3w8mPyxmFEWVqH rAx/UwVZWKBY4YSeJ/b4xOTd9998FQ5XDv727/4eNu0aRsF4NWGBOjH4K0zsxYmP3ULrBY0napyh scO8imsBCP7ln/8MXnvpFpjlEfVhbTC3BfPlwueWi6OwYEY83uj15gZMWA7DteLc+kX1l6yP1ASe O+UlaKw9A6YsLNjGBtH4iLF5WqDsORK4FwAIwEUElWEBx3Jdw2gTzo0EiqV0nCPuvBl0Ls2t4fxT Q9zpNaXJy3mvnN+mdLvLdmsjmy92VuhrmbHR4MosBibMLRtiupxW9eH5o7J5KyXrA5Csc4k3hu1r yDNOThtOPIezIcj8+V5YSL6Dkp6z7ydGEZnUwfvTWuDHENwNHz1+NQN38bn8/FJ2JT2sZ9vg9dy3 fL+1269Tx6XYAvZ6TOWAectf9wLG6Tp8v1I5P2v1dI0cJyMUQdc3H5/nkf7OQAvYkIL0TR6wrdgX UbXZsMwihiQlRFoW0xTi9ewwIfuvbNwSk+YhzWvanEt0dkYcAh3PIljTFlX6O519nBOeinTIBY3r AO3QMt5Xfd6rLEl4fnFcUwi03dTEulBf0bYWmZGW5IfYMbMEHBGIKBih8wggYyQsW8pBTvOxwVBh hwwes/1jtK0UlkWCgBul67riPrFor9Vx7IRp571Cc1YpDcPreGUOBFPROklkD9LUitSZw8oz9Bmb ClF0flDcQjZczGmO5+JNBDeY2uIlFxFIU9ISqYHM8WJ+AvfuP4DDJ0fBVvM9279wIYazKRfRMjDD kCgCZGzViGDuFAsjgu33EoZrHEc0cuBDrKstolNlTB0T/SPoQQmYUUXhVQzhtrRnh/vYWunhHWzb pkj2FJKtKEsfQ3gtFjVgcUeDTJynHRy3zbbl1l21yLCQXhmKsReJOYw2UplfZcmzfuwMtiV9J1eO kGgbzjV8kGB0KSs2y78ejSYEbslh1lAusFNDYz0O59rUMA73bVU7uHcSHIPdy3DxzvdhevvFgD0O 4dKTb+BasYbp9QtwVDVQhX013Ax4fLyCU38KLqzRMXYfWZ/C4yffwjcPnoZ9eB9uPP8uVDtX4XiN 6/oUqpEP3zOGerGiPuA70z3wQgJ0atsH1skKMwwSRdN5pw8j94XmrRSqeUlpw2JJyomLpm6L4eeN W7IHoYu6K1TFE8AaVehMgteGRgB1hdDz8iVpnRUEO7GKr5CCs5JYLBYHDhODKlnDRorihK6EKkyW aXj/ZLSO65Cp6JYWNQfPPS8cxyE8Xbxed0sjiF/KcVn+AUhkkcCASQKG1Pez65KxBoihB6Psimi5 RVZPgZGCIkzcx3g2GSZO+B5NMBQQzjkYxKsH+/DTH78Lx4cP4Dcf/iMsTxawWnI7lssXL8LVAM7G wWN9fPQUHj5+RL09EZAtwgTauzCDn/zRe/Cj778FbhkmSACBZWkoURjHdUlVaQXLPhknZcfJK+VN ywsw9Rnb4KNHapSVyu77MHzZter1yjhQFCIltudzBzcfZaaIeQiG6PHX92EzvggmgHPU4EFKnhSp C6GJbX/uadRb2SiXfUf/3JSB4DCTLAn5jIJQqtCWEAonjxIYk7AFFgi03vSOyzmfPoax8E8KgNVd 7C2Lcgol+XxcwKFsJ52nsnBg0nwZgOuhZ6Xv7zFeWZhS52ccZ5scqtwjGz5yxnTIxm17DN/DRqf/ mZjjgoDEml5oLl5LVhG77Tt7tkY34YyH1e8gw3Wm40X/GNsYxhz4YVGN3n8QpwzEUKLBLGMikB6D dcniWDu2QVGkW8RxvcgtUL9dSilR6kbBBScq104Sk4GzgJ1JhVA4tuPZjOyT5qxRkQGGH3FDxNxZ ZzNQ5qTQAucw55rhxmb0vL28x6T1gsKhGIYjod6aqyi1mpJCg8FuK1tcSJFDFWzSdG/KhRDTmWzQ JW3SurnHIdNKXg+pGCNLXUEg0WB0wgnzD05y7TrKBwTMJ6NzrngzjlXwqeCFN0Lg/GOATJxdOmnm DO1gurGIgOZaJYdWIxHQ5awHyCYqDoEHAllx+Cmkyq3BqDc02gm0BSUDKswpnoTrvXxlH9b1Co6P n8Iv/vPP4ejoEENeZDcoNwrH0HJFsaaT4NgtMF8u/CiDi9+z6dqY3J9+SppfZCcsxCI5ZuN4PIgJ xSIWx7IoeG426xZhhWoZjctYSKhznhk1dWa4tynOw8axth064FR9HP6dyHzAHuk0R/A6C36NRebL lIPJ1QpsY9X5EiZ0KOujThDupXTNmJsoOWMqK0I6q2Gfjffatik6JtWb6AxhtK9beThaWdjsPgMv vvNDuP7cLZgvjuHG0Yfhfl2DXUxrWh/B6dEDWJwew2Yejrtx1N7RBxCI9/P+/ftw7+EhVNMAAq+8 BHa0H+4ZngtGE1sYIcES5sek3IHWYOu5tbT266c55XbKFizCz/3VeQKrTdT0F32/ZhdHO0v9dcdn CxuG4ZQzNWFScGCCB9oV7GXFlixYoVAy4qZiJVoEnPDuydhwknmnd4z6T3KYsuoqquAcF6NwEZk2 kiTLc5KronDxhCXZkQ4l+UIqJ50826x82uUgjjdObvVhI5ugx7KWE20pyVJDNxmQsGIMCkqeN9Tn kxYjhR+w4mUKm8UcLu7uw1/86T+BG89cgd9+9Cktgtu3n4fnn38enr1xE2Y7E3gSQNyX976B3/3u d3D/669hdzqBt995A9577/uwi1pzNbJwdZiQJS09JLWwZL+htjWFgDER75TQUqSrLbeJypNWo1dk U/WnCoWqt59AvBY+sMRECq0qwpAwNuXoyOYlLxFoWzewDAtiWaLhrqAldZkN3x/0HCspRPF9A6z3 jER9xdA57fNLBo49a23bo3S13mfKITGc9E8LhAwKiyYa6quqUiqeNpjkAXa8CeJmZgvS4cMkYwQs mA+hY0rfLBsOe5MQQ/e9dTRceFmOl7wiExjivE0lt3DmeBEk+LOM1RAkpnvXP6/zHsO1T+MPpgek 4xkzcugZmWHImMGmP/MdW/82CRz2v8tt/VwKf58FsL3rN7xpqW1QJ00PYV3OCjgRynUSGkWmbZ0x beIRK4en84dAhuZYlVI9KU5PJQnXuLl5ENaikpBVIayI2is+ZyeFC63zkY0mKyQsMYEgKykrVhjB DkOe2AIrONMS/tyEjadZWmLaaCMXG0Wbmy3IhmCF5ThskBjyw84KpchHoD5ktLlqPz2H+IiR1EgE 6PrNw5rJyfBy3uiAVtT/Eas518QaloXaUx9tTM62szyUj3Ypdyl0jurGN5zjOqYuzk0YvK4HcgLn LIFIXn98X/V3A2mDRRaTclANV0ziWTUCJDAagUAHu1G88OJzcOPGDbj17DNk1zFlRgvasMpzrQyu zDNUCZhOg31sOa0Gw7IIvLXgTQvh8LPLcJ/xNbQlmGNMoM+lUBuF7cP5073sSsqfRv06GpOSFP55 jMnGt5EhTExfqlLGkD92CcIuOanS2VBeHO6Rk4LzNnFO45zCQpCq4Pw0KgQbT4ipxZzIwmR91pUB LCvBGZLbWRphdRORgmF6N2KQaCTVR9uXYQsEZQKtrEVKoSEB1SKAt3AOAQjOFzXsPPcqvPLBH0Mx ncL67udwC9Zw+8atMCZhz14+gfXRQ3CLE/DrAKbrOeUSztZFAHVP4Yt7n8Ph6RoOLr8EO/vPQR2w zoq6lmCkaoWBuPDVk/Cco3mMQKzpFlCG5/J91A/Co5FEio4+58x1Mk5VBrDxpzQpYkZsKI4LJpfi RKcSZ8sUMUEXK8nwUu1IYUSs+MDQKCa6ymbWrRbQhBvVVTvgKk9J39is3DIFFBZuR33JqAybxeXC d0242ADDsNgkPhiTydjS5PRjpJg1n6QjyRJayF5CEMx5s1mTwWkFwET9mGiUZTDQaFOlKnu/+DfR m4URpmSAfDuIg8zh1yz3TStFWu4R2FUtl6PLuWwQ4I4nUunZwbRdwa39Xbj83jvwk7fe5vCn4Qk4 nY3DIltRl4fn9l+FP3j1FcqH8K6G2SgY2OAlmdXD4E13JMtCYQngHqNY9o26M6jNplUqtCawn6q8 Tv+16vXwNahXjZsSVi1hObpel+bX5NW6uffQSsUUG1Sh220N0zA31h1Su+G6gtFoUJPPsAe5U01h dBo2kVE4l/WGWKu2ctRrdRLe1xlu7pzCenzcRsJSSO3nIHxoBJLB9pFxsSbde859YzkU7JOqCbS5 sdewDLM1HGbarDtA09yQRl44PpIGMIJ1uGebsBBnbQDTdPiOwkLYSgxDGCqXwI2bWU4lZ7NS2I67 moDqWEnVF8g/Kt9SCtNgi6SPhaEWpws/hsshjaNJeXkgLIYCDyuWQpOF6yz/J56fkYR/VQUXtk1z OpSHYWOUwjH0eZ/1vcwYTq/nJOccc+vkrdGw6Wf0gB0bRfLAfbwCiPlrNr1ZoA5tTHETFy09KgCQ KmAFalyJvozMjjo33AaJixWwqwxlgmMRureycZqwMbJIa+V4reNp4VrC9lIV9n3G3ODw32wGMu5J 30ptq0MAhtIH5IVpO0FHwiR0/hSAECfLuajNidWsqPJOIc9gP5RdQ5Yff883CQZrJeztzGAcnEMM P1Uk1smb5niiOdFp7ZMdxDFpO5GYkVxIn8BvqWwnMiQ+9d7mnsE8fyrcWDth8cGS8PcIN//ROEpO Ues8DMvV63jPsOiLwoW+iOFHsj/KflpOfcD8PswXGzouIOALnyljblfXzw8Qltkp6xZTd5QS0VBg yrdNfTl5bWDutrN8rjofST8w7AsYJpuGfe31V1+EV166LeDIUFECut4oDty0LIpMaUJNF/vbtlpA Euw9atRxiJv3RGp1hlWuyw31f0aQl7pstLEyWEG7OugKBPV3LUxBviSmKsn3x+N1PPe7DYZj57LP +rRHkIhdFe2oVp/284BPY6i1ZydU782XYoPLqH0WQRwWTITxofD9mNuV4RqoEC+gw4FFjiVKV83C cSaIB6EI6w0J2zJMyDJsLcdHhzC6+RK8/Mf/FF74wQ8pqmUffwW39yu4MD6AhT2E02++BQjgDTtp PJg/JXZ6N6zh+nEY3+XH8M2DcA+qZ+HGS9+D4uLlgBurYP8D8MUiklmVxpoIEMuaj+FEp3R9/UiC FxsU56ywnjGHNttvyX6VAlIJOAkhkRFUyOSXefyVGQ2ZwPJ7HpLREnzOJ8O+k1wmjfpozWgdJudE PJWWvFH2fjWs5GiHIfBWOPqXql6MY8CHVUmFXFDTRkOscg3OZe2M4kQwsa9mLosRGRAdEFBQ1w+5 6Oaawi99oKBeiSL9IZvBFLF6bvlGJMm0GGrdPKEJuoNU+hjhehOlPJpV8GS6DVxjYs8AACAASURB VHnje8U4TKoR+ADeusZS/ptZLMn4czU9G8O4N6P3RqEfE0EhBRKprJ83PnwO82887ZtdRO/R2Pp+ QvyQyemH8RJo0hBzPhb5g6URJAk/GKvTwyU8BQR4I/IQa2yYGs5jYpm5pe90hoyE5v8ogMb8wFy7 Kp5XNtmzCay/xOvoawPK8SG1GYvHLtK5dz6FaAuqxDLU49U0SjEmVsxk0iv5XIrnaW0vVHCWPUvP bws/xr8HzFtk9kQzaphsEeVJtNJWmAgtiPCmv6f1jjs43+E55UamP/z+zDFzAJ5fp4qEd4Nr0vms dw0r2q1RiQuIlaMq4Gtj0jQ9S0CtMEngukPnoWNWA+eci+LWie3PHQMFeVH/DxkIBPQb3hzxgQUG LK4bbFhwXMfBs8dk5jEKh8pGQ2uSxplBhhHJkdizlWQ2kMUQIWip7CbpBRCtxRaoupWEesO5Y/oK VtRtVksSisVQEumNSVEDbnaoYZZy1irYmU4EEKYQWb7eScqC7lPS5zOg/Tq99FrVXB6dixkTSb1E E1gvhaHS93nHTbxRygKtV2km5LhoMRrbFI0ClNGZ3LjUq5Vy8+h8zuaeDh1OPv+MdevO2ifDtJz8 Dul8NWdLbDkr/XvQ1nnKEsbjcC4+gOkkBCZPeGGQDTNz+GAwOiJBdyzusAWzXyiQrOc8zEtGp7n0 NnY31TvAG77n1pc6T7t+vqb+MGPnIqAbgjrcuxXc5T/6OurbkRwKAsOujffECZN42qx7wJBzKxvq KkJ7lOhQalu3XH6mxh6lWL0NPtvnNdWASZMy7It6nxNZYQnA4b+7YS0usVE9rj9sR4n9ecKaW2CO uZvDy+/9j/Df/tl/D3fefR3mD7+E/dUhvHiABUILWPng+Nw7gntffAzTMbd+hOUKZuHclouH4NYL +ObhDhzDFKpLL0N78RZ0JCkW7tPujHoE74V5PRNHY0Rai7wPEyQIz49U1qfgvPV8DeLPyIDoNZoz +IZIspEUfzhm+3PSAR/7CGaHmyEbUvWeNPfJZsac86K4tUoDY+wnFwDcJvy0qAk0aTjnqPCiq8Qh D0lH4MmH9tRy37LWiNifaM0UWRJ5kdPymQdAYU6rUz89UgimD7T4Nc2dk1Uaw4vZ3q9rOdtwdKPP v0OBbP6dVipx8g2bFiWGmcMFUwgFr99zv0cqnMCcO5QTwQURPFGr3RWEEeAbO45j5xUvSgPrTsI4 faAC8brJIBSsI2Vc2kz1/KOYMqQfbVtkxLrlRqv3PaZvQGkseps/b9Soz7N+cgqrBjt07NB9a2AD FsMFpqKOHNG4CLXsSCpB8l9w4SqINuasEYdciLfs3RMF35pfQYU22KHAakUn0KbOOllp/mv3BFoX lRRijMZQbGpmc9uOBVatVhilcKzOUR9Bt4/jmICC3qPiDJIaOlUEvsD3QuQgGWT5ZhXfnx2HNyL4 /yl7z2dbsus+bO0OJ958X04z8yZgMAmDDAwAQqRogKRkkaYl0bQ/2P7gD/7gP8HlKhbLlGm5KKls y1KVVSoWJUqWAymXaMokQDEgUQA5Q6TJ8+blcPM9qc/p7u0Vd+8+9w5UPsCbe+8Jfbp37732b/3W Wr8V7ju/J75fQUPudIDoW98JQXpg+RF/tilTCa/qCfmQ72jOHf9uIRov7zVny2ZWrV0wwnc4c8Ak rzHxqeawNom/JavsT2ROpcIo+arWSkMQR1MBPvUmrHVDtNAb2ajaBFzrhYJOkpOQpH7SBaMiLJ6T mbA9sWGt9exmeME9ZfUkHKe6b74WFrYWUGmDTfOUpCAIqE0LYdWms5FukJX2Mnbcc5RY/NWVTej3 10M+neXUJZo035oXtkGyAxJ1XzECKZLzE6dGKzqh/bz8bJyplJiHKgL1piigwMeluLHxxpuBZKXh RuklLcTafC3bmfi8OYwd7n0joC3PtUXqW+vL1o4/eQ3L61BuWrR2eBLb+qFnK2iKl+zagUFebZWz mj8enBadwVahTkoC00pYNCr2yrt9CWOS863RAQ4UWL4XgJAa9NM2fi7eknMMpIX/0bmuySk5q7GN grSxv/E8MXDY5S4D8tyibkAeKCtKLaIgSscxyRmzN5NFmyWU3+sA5EbFsQA6rn42JrFoQCc156Sw MoKr6bQIbc4W2rudfl/HtUJ6eHTcTjWDyRECsMEZeOqVvw5/87/8L+CxrS0o792Ei24Kj1/ZgBqB 3Ox4nx2m4niXUwlGeIxuNWfJs6O9HXj48CEcHBzADw7XYGe8D+V7x9DpvQmDDEEbAXG0ATXZgiTh z1MHkg7J6eBz9DflxnOVdq4AL+8FkEdC/rZWB/0cjyF9hq1q3UAfFxFBEnJqAax6GLjEgLYtgrhZ yBcBOHUyyKSRxEM2Tl4a7oonUMIsr9krLLoF9wGr8N/CUdAvYy/UhCT5by9Gk6bpgnIkKjKCumlW ddDUoUfqTF26WdDGgDT/6ibPwKhIMhZO6HPx4HykW+VDuM42PANqjYFqg7OYrWp/t5xXTIHy55Vv t/cnyYCrqepSkk7lWORF5GwtRgmeI3nNDOzs+xyfZ2KVXHJ3RSdG6X+Tykici8CUHDtVsWWOmdO9 qpu2WrER4w4RTLy4wPS4KM9QPMolkLA8V0JbIS2a0PtNoDF31K0CF9W9HTg8nuACWBV2hFTscf5Q GYejRKEon81yvqx6z5Jsl8PkwUjRe7XYwzYwruRUr572G6mm1qRr16hfk4HPhJqSTiNyydLWKjGB RWkHg9aBG3mT0U1VnZ718aqGXWqtm1okW7yFdJczd6EBMh/04HsVzb3THnG+mjFt+oSyFzFr1r53 kld6ksUDB2GOx06O1Q81DtDpVbYxtDfRBjmX6Fw1TSMed7VTrUce2u7opuOkKMa2SgppMqvMm47l RzYgxbEOmuZPOtFgKxm4OZHbqYgB1nZ6IJpXVPWV9yVHaz0XlptzfbgppUhOWJ9d8kgzWTVE9CG4 l5ZWHIIlDz2ZgjFNwFpycq5UCEbjP52OJX9tNuWQqOmtVYp4u70hbgorsLEuemS8MUQVqkmy5EgF 1qMK66e571VgCSUlQhgPb2yygpd4PsWsATNrKgjNDiC9j36mPoyfVMGnAUgS4yTV7ZJjXJfUTB6k jVsmoDtVnTEROW7YCE6UJ7ZKjapFJLza98RgJj2XwIl1YpXFy5Nb5qw5eumpEjTGXlvY377Hqt7l Hz1ZgUlbyZpudDZ5/poQGzR5TEEMvO7BkDTfNBQr+mGatuNAOxpZ0R6I4oIVxahN/HdVn7PDZ3tT cMLofMXh5VSAKMp0AvxXZXsO2BHsd57PkS6mzRsdUwqDxgVz9p4AHJ2FEn04jvwTx4s6YjHwmwu7 J63EpBMI/TysERAvOuBHxFQfwxzX271JAbDxPLzwyl+Ftf67UNx5Dc4jIN7od+BgtM8yIIsprrWD IzgsjyHt9Dj0WkxGcH/nFjx48ADG8wzf24e3Hz6C2VGBl/lQGMeKkmxqrkqncGqpuYfc4ECLTQio ZR2r3ha9RmPqSCuWQVxXn0NnjCV4InmejgJBchbzbMAMf6/TVdCftEDimUFfq1NdM3jL3pfo+CTQ 6icIInlAHuwMvYpJNoVJB5FyQs3EuzjZutz0PsHFnXNFkVSosMxIRZIceGNwls47KecccT4SoXFV NZcEwDS0YGED7COq0TVej7cJpfkqIRQAknPBXnXoXWQMnBmq9uQ7LSzbmtDRRHdW7rsEKuKNkz0S ug4Q+pcTHqWcgseZqPYiobJsBQ9eKn952Trpyaq9AngB02WwyLmvm4R+FxtctnKt72c16KiLRQzk 2AAkbQmW5dCqGZX4My3vV5mmwEhG4r30fV285nxaQrY3UYaC/ruA3FPlHl1aFRg2CfsIDCk1/yto ZKkxjMutQ1GGtnjhxFfNkUmcgTi9jrIJocVMhaXtS4jRwkiNdmKmOQm8gGbSIzYlD5TubSLORhxy P62YxpBP2wiaMWvvIMv3YJljNSbCHnXE0i0/rDKqdezodTGiNmXiDbBh4pouEg2+Oo21+6AHOx7e WJ1m4zxRMGXnl7Q3jEQBWagK9RJ+tLnIxTEqiWHSGWEugvZ0XtScT1eyQ+NYIoEmqoQhcd6ggSTt tQyNK1X0sSi3GuF6PlVgKIUGnNSvGpn0c4jnSbpq4GcM8rossiqyBtTf+KAYy7kuJMxUzGcM3Ej1 n0Nd0OjAEVDsDwcM1tiAd8jAD5u1FuZPY/voPOL70NgomZMF9V3kp+rgAJrTxnbINnYCH2mzObfu j9dP8Wu2wOVnUYskE6QufKfH9SU5m2TfS85lKymsVsr9O6aeoZzf7NTRtvWWtPITAyvhnM7jhoEL s1JBmtQCtR3xE6AuWleN091EXawiXsVJeKwY+DoF75C2jtE0p5KQq+A4We9eyQ9KB3F2v1RXkRLR yrmTSs2i5DlHG3KidiRprdk0+t2HJu6cQ+llL4HoepYdbZ8GqBsc9fixDGA9tPezWsNAfP+jSWH5 sUDpJpHNF+AXJe8r0+wiFp+PlWjPVHMMKA2i4yKHXVjzoi40j7exq9y1udZOJY5kaBDUUJU1vvYA NuBu56oUF+2/AdW778GHrl+FzFHv9hGu50M4OtzD/QDXoRtxkSCMDiDFv9975w24v3cAV59+Aa5f eAqmswSeHc+ZlScmbLaYwTGuZ8qZK1gqDM9vPGESlsLNk0KenxWSr0jre8b5qgWMS69FoLqHWiGK sutx8YPNVd5LugLuBORp9XivK2F5/H1tdbWpTm3a08Y3RLTAlidITLkWpEODQO4op2bGZHAQxLke J62nOnkTVgInjydl5oaW4IJ6uS1wYPjMRbmbG6y4ZrFR0QVT7pZHoh4OM1o6JyjcJhs2aI6AABnb VMnI+cTpApQp1FrYEHshUk23DNji645BUDin6Kdsig3YKZzo6dA6Egin+mUgzaNzHC+v+Q8E4Lgx WSIsHCU4l6lsgty/tpRiD/GBJS+tzbBZXoS+Hk2GZdZE2BAfqnpPuz4fvN6IjrEQnAJZUJAn4dCq dXw2EBWO8Awn6PGCQ8kcXuBQktzrvKNj7jREkajuEEglJwFQaXKs98s2aFb2lmILC2XUSRnuJycC sHfUhOWtSLvWKjRmKiyxXl6h0w2bCs9BKCRsRuCQ8kNwvmXqFYt+SQLLTGE8b8JYOANFjTe8TDst A7h/14O/o6rCUU7MxaXzab3mjZ0TrvdUEBjNHXHwTnrqp7GEYc6AVIca2xd8MPaxmgo5myvxPLTP pwrMLHRirf8sRFOZRw8mBVJJB5TSjGXCjgHdP9JXpDZJ1DVguLqG3mwPVlZ76OlK0j+9Tk4A2yBb P3kKxUzklNgWJRL2nHO4E7354z3uCTofH0E9GeNmMAE3PwZY4IaBRv9w3mWQNy0mzLjRHCNPejgY cP5aF8+FDPSgq+GWtIkUiI2TiIO19+Lnozxhay8qazS2S/L+nNX9a2gSuCJgruHAADKS9AQpSw54 AJD2OUF7CrqpF2sWUhnM7lUsHDznBvEcIsPx8lphWUwPxY6RJBXnvCqzljT9rukh+VSV/OP7YfbF gUQd2tXP7LSojTeQW9ftORvPXZ6f+nV8JGMpwYUuKGLOaQ/MhOxoHcTORMY77k4g42ykgHwBf4c6 zY4lYhYwrWaQzjtQ5JnkU6lzmmkBjPNtp7DlVPGaKU84di6sv8YZW75uO78GlDevt96vFcKsxhB/ 3tZr1Xy+kSXRwihyIqp2ByE5vqJBR6kIteyXlfQy5i/XdU6PNOnJ82ozGlYvEwWMiro/HcMc1/nR 4Am4u9iC2WgG29k+Iqzb8PjTj8P8+BEeZ4o24QhGh/usmzcvSp5OGW4fuw9vwf27b+P35PDRj38e nn35i9BfX0dANsHjDGCM94kKwPy85LaaBPYnVBhITn4t83RRNcUhVA1MYE6kXag9Zsl/y3PUom4e wsnjieQU0mv2HBcpTaXTy2Qi64dfJ7FtauV2dAgzDSm/V7smJ04edbipjTFVqt0rxQlSwlzhhdEG S2rNE1ygB+kIPdghLugVSDole9AdMqSJ9FbzYAnNOStAE+DC62HPlbRwcrpR6gnWvsnZOu0h51IK yKx1IUZJ5vImM2iahO/aE1iej0KHNgJVUwSw7NEZWhZGoy1sGWRI6vYi4abD5A1VUs0WDI1PxABr YiuwFIL1BqQctgWHmAkwkA4dl5BzvLXk43G5t5bdN6yPGPYAiBTYiRp6W4pBSurbNLcco7lGHiVi Tbyo4LUBrOTlpfF8URYwfJYrAnFjrPD8af8iVo4U4mvxyqk1DfXK1RvGid58L22D8LIJuepkzoww ZsA6hGkExC2kbMdkVi0oiGetayMDKTk3DfiU0IOxj1RxCiyPkFF7Nl4eGXSoqpPuO7GGdSOUHOeW hLmRtAF1m8U6Ca6WwZ81u9eobzP/Ght94vPxw8RUIczTMDInvfLwBfbj5OZ38tFspHy84HGrsweZ shi6uSh7USsozEwMM0q6lvxFBXJUiFBDKzGbnrb8Gsodq1XLzSswZLmDFEFRtwOuM4ABAqbBGgG3 FRiuDWF1fU0AVN5hJ4nD8KmmeZSSE1epzMcEjVRNLFOny1pVJr/T4QKJBWQXLzLLNhuP4PDRA7j/ 3pu4KewjuNtBm0b9gwd4Hl1YW9uA3rDHDFu304d+l1rw5e37psVbpTpjZmvlPU3YzLbsRG1YuFc6 yHK/5S7QOcpkqcP4QG0ASBmnRJKubd0EnovvW4ePKYUo1gGgSTfIU2O1PTs4zFAuqOuDVM9SWyiW PUHACwqyy+mY7VtGTERkW52GTZcjBsG2LM3T0+ZvouxzeE3HxM5x2eALQDG/VMaDP6rtF9Ol/XB5 fdUQr7koesNV8RUX07CkVkJpLlnj7PF/atZULcsZbuy6TaWS25grq5+qmoH88yeYfkWZYMRF7CTy s+WypEU8hszlnngtXvbcsUkBnIXiBdTLVeRlTHg0Tp29rwhFMDZa7S+QXHX9vZVzaxXuqfY6F4bU UosyFnt2sMB1Pqr78KgcwMPxBhTzfVg7fgO21xxsXr0Mh8d3oJ8hiDrahdH0CI5GE8YdQxz36dER PLx3G+4f7sKxX4NPfe4n4aMf+yK35BqNjnFNVLA/PwAqIKdwGSkOUPYCdRvrk7pCDmw/COB2cY/o IP4xR0zEoSGkBYWonTld2nWo0iIas2/0sPZs9JhR3AodHcoJpKin5AxWzPDNqY/vIuqdujw540IA H56zWHYV/lHbj1ldUPo6XtQUBr059CjBMKs4Ab8T9NvE6Igmm+gocf6DS4MeEjhhoLwKBXMIK0zg 00J9dOK5VOBp54UAXmppP5I6Fxau7GV1NIHjCnLXukYbk7aMRcN82etEkUp+SZTY7gzAJKzT0+G4 f8nnaAUQrEpAYr1eyuxlYyPGYa49PSXvJitrPf2US855aSrYJao8jc5ZFpNVcTYhVe6nGJ1ffP5V 3fRLjVmQWFyyXb2na6u2cKepZFetMROPMsdzpIrlDI1Byq126L5SQYdfSB4LJXXqrBbWTNmO4On5 pHW+y0xoVbY9PQlvJmGhVJnIHMTsDoNq9riNSWw2rTR2HvimSJl4UkrzZx4LTXr23Lw4U4kBA9Lx /IgWD7Q3nWAYT9lU4vsZMxOnsalp9LeBtPha83TJKVs6FyfI6hQDD605HX+2fT4nr631HpCigESB iLD7CshUnqV1zWXVTrImsKTVmaWGIejBQAtvXbc/5M0jhBwoNJUPWEojo/DkmcuwvrkBW9vr0BuQ PEHDPXBIXAVkSz0mS5uSRpqT6x8OOvh8h7proUddc5iEPGkOzaeSg1unXRieWYeNc9fgwmPPwO6d m3CAm8N8dATrfsz5L9SWirobMGdYSuEEpZUQIyNj285tMiBC2oq8OZJ3U4kjXetOwIAlLaP7ljb3 z+ygMlN8TKfgTe2D05QTtlOUwG7ORthsaF6rtIPabM71o5WTCuirVXaIZE9KBNSkSVcR0zCXDhDS 45KcNtGG4yKTYgoJVzdKzpysV7vnTQUe3c9ge2g7tOuLCzPg5BqK52PmkiZ8vDTXjV0OayHM2Wg+ pwKXm7SiGCypRuYpa4eBIyeka3iVk491XZqsCYhTw3JPlbCNaS7H4zAz2WFn6gsQ0jXkp9rDpA0w l/fJIHB+yvrl97i2/TzxOs0BtXuJGCwxi0qKMAixuQou5HXbMTPOnawDuREzlTJOuY6EnKeBHn4P acHxuNWhzR/rxrJzpxquOHfed0/ATr4KycEtOFe+D5fO9Fmi6/jhLVhzBRyVU9jHOTmaoIM0RhuA a+5gdh8e7t6EnRsPYXD1Rfjiv/cLcP7xp+HW7kNIimPWtiurHiwykErbhfarYa9ebAV1ISpYBFz2 nR5n/gM7KJzL6OoQQZJLjB0TldDS/StlRk0corxDPcel53CKuCqljijJGZ1/DkxXiX8lZ5BzAmjj 5LvBkIAnLOnGaTangDkKC1JvMieVp5QPNEMrVBUVghQRDeyuehggek0zyhHpogEjqEq98iQXrSwJ sPWEacMDpHUH9igngE/Wc3nypKj4Yjo4ZIv5CG/ZFrcykUkoN1DYhYTpZw4tsHZTFQQDJXojQISB XCK6ZpL7ZzlKtoiFPm6L3XYCOiboLYnGXkU7s+CVyJxOFRyaGRD2jQsP2LNeQEGtTogKzhJm4/h+ 5oksZtZVkomgWJf/w62hmIPvNHkJLCKY4TUp44DPFejlmvxJaEUDIkQrhJ8IdlqOQdh1qeCDsZ1O CH6LVwVwJ7iGevOxiPPJ3L+UPUZqNzOF0YImdx+G+PN4QSXjIo1Cwoc+L/Cc5lxKTiI+VYHfSyU1 XfLiplB2ZlCPMhjUq9yiaEoBdtxEuzmC1hnODVLhJiaGzpCKFTQ3I1VDmOQaqlR9L17zLm/ub5Up k5AGlqLmljYJg8Y4jYDC/cZ8hesk52DuOdTmFxMRACbwwcsjY5VuOjUJ+6YM8OjelaYryK+rw7Bs IJVhMwMbV9/GLYwacUfpmpKmjZOQqWNhc5SvI3Z2FKPGbLJt7rwBMfsZt/VxoYp0EY4nBUaUHsGd UJzko5Dz1UvFZsiKq0LCv1P2u+bmvsAJ/aL9KPOKcz8pJFCMZGzIDJVWMdxEARZVwbmT3eGaABMc 51UERN1c2vA434Nhr4+2o0ZPu4R8dQP6m2vQX8vh3MUteGylI5t/IkBtd1LC3mgMo1kB09kM9hFo TUY4h4+l7Z3o3HmuGusPerC6PoDtjXXYWunBubVV6NIcLTowK1L06gvYXRyL04djUpRSzXf5qefh 4odfgkP8nvruuzB6cAemx49wrozRc6+5uAZSBQTzCobDoeTYeGU7qIIbQRDlyFU6fqJYYeySsLsV C1qn4vQ5UGAghsSr81zbfeUOEhmDsqCx51UCBV8rvYIVK+7QvFEq+nCh+lbnFdnjUsEH3j+ef4tC QFsl6Q0VAzcNcbMA8Zw3NsrzoyiCp1Aq2STKByZnKEk4dzHJOwwsGOQXC1x/SegA0VE5qaqT85Lq eLSFUIY8sdgxkeIkkbAxrUV+T2WssPDMtVsCz9ExZE24xmSGBDLZM9gGs72oWqx1qPquUpaBSpSB U25MeoM6a2ZP3TlSDp8VaH9yhzaSogsIPrqZ55w6/u4k1daGWeiVyteZGujNwjqMGbu6UgY+gM7Y jntIm9LBlu2wB4WJQ9W2A2gUHiCsWxn7BgS7KEVnYUUptYFNvupGV9AtlFWWiArZYKcdgWgOHeBl dWe4V6Aj5TMazwJtMOnUDnCvWYNbyXWcR7swnH0bziYjuH51C/JeAgc7d3F/nMDBGNc2S/JQMcMU 59oU1+0uN7A/3juA7Zf+Jnzq86/AxtltOLh/B9IF6dz2EZzhuFOO3sIxG81+EQMFHbd8ReZkaqFh WtfST5aTeVJZX9LbRx5J2Gp0ftNBK9CCiUUYMwKNFFIlmzDAa1lfX+doguCEmjti8NwkvNKh+qBo 49DbDAHkBAb6ZHUKW5yq1vCJdGIgHZkJotwuLtieX7DgK2nJUbyYeqpxQjkbaSdJwnSTa7wpHdpI pPcgUYUubaopxRMTr49V+hn7ODYEwr7VIZQZsyHxgo6R7wmPw7kW2ycTUkOSaQtGtxaAD3l6beq/ ebTze+olFiwcK5SAt2VMOBk88a3E9PjBU8Xr+KvR8L5JRDW/y/slBqj2LTBB12jJ8QG8JM04xqzk CSbJS7UZhxSd5PQRzMp9h8FWn8K+aQH9fAHDlBpq78n5zD0vXt4E0CD30XDTPV9Qr8c640Ro6snX 7yYsIExl8J1E9HY4BM7IxBKP1dN2jSacGVs2LIkYNsvgdRr+s5yhAJosjHLCiMsOGrxdaOaXFKE0 2nxegTYvxFKPH0+hpTVkG0mYt/HsiTamOOnVDhfC4Emmm3Eazt0cCt5fnOS88eZnr0ebUsy2xWHf 5XvOPAG9j/KWODTk+G/anEH75qbmdjKjrDIEBia8/L1gqYEi5IDQBk7SARQ+aCrHQZqG94eQDNZh FY8/6HdZCd5kGcimsNOGxnn3uIBsZRvWzq/BxQtrcOnCOm6AGZuoPbyUBzu7cPvufbh1+x68e/MW /rwL9x89goPDQ/BFDuW8CmLeMrc8E04EpPu9DmxurvO/i5fOwdNPXoOnnnwMHr92Ga5cQnA3ww1j OoPDScH5wQXaPZKi4TlFRRJXn4EEAejRzQyOd+/BKl1bPecm2weLEXTdEMZjqVDl5PZE7JoxPc2j jn0LCJtubQDairyk0ltst4wl57Ox+Bk5NFlwduUzCbMh7CjwfNK+rMGZUBtrAsmVaIRxOz4GaWOx E5qjyNWKteh80usLrYz3+i+Wr1hOSYltdSxTEWxzpInGI8L5nE2uVmC3lJ1y4qkw4cDXpLZWSsVs ETbf/6PY8XgttG142bITModSreItT1TVs+4cDbMTSZqqkpxpYjKPj8bQhwM6+QAAIABJREFUR9vZ H0grL8optEiE2AETsq7AEv3ZkWEQ18wVYzKlECJp8sztvKEKBQ1+WZ5qaY/0S1Wly49mLOTIcZRL rjeqFK8bWxKOCapvSvnfzqIi1gi+Ax10nGfpBu4TXeihw5SThptfg8PuOZh2hlDv3IS02oNrZzow 7KzA7t4DmB7sw+bWEA6nxwBHM/z/HkwrqSKfHO7Cm6//EJ2IDfjoF/8zuP6xz/LJH9x/xPaIZELm zJYjQCo0HSRcextTyLy0dBKJdkmYzBhbgckGguvw3zRIKxGZQ0A899QDVoiXuovf2htAvxJCy2XU l11CtCxG7kXXlB3rMpOcuOUm1GGQ2QDEE1dRv3mMMgugJq8K/yHOhSl1KaCKJFHQARN19Fy8kHJv NerDJlU1KZ9QWmmVFE80PVktUw9td3hCmUER5oO/P3EKTKRXoeDgJgdPWCkV1FwCavEjrkqtrFef k41QpD7qE5+RY7UBnP009orlM2rxhBK7x75Z1ORph+osk0IxejoGjdHi4usLcisOmrykJinVPMV4 QbEhgGYT58ICe00XmLUBMgBnFaJxuDXMk0ramyTc7YP8avKKcSOqc8jQ2PTTkhN3P/mhJ+Hpp56F +czB4eEYjsYjaeuDJ/PDO/dxEzyAvckD3JwHMOyegUE6wHtMFT7TEDYgpjZVr6IWjCuyN5UUOZz2 ECOmhhVceK493WMB0ZPhcgYfkIaNB3ShWfIzA+1F3dxvAN0824CttpsCp28SoHdqOVzKn42LV/Q4 zX04KTFh3yH3rG4BuOUHsc7Lldgt4M7L3jY/K0AQZ4BnfyrzjotQqLm7HatqxEbJq5xMJlCQFJGC N6sUpgInAi9UkUneZqjM1JJ7YkApJ5RuY45e+DBZsFd9OMPPdjfg7OAinNnsw7WnLsC5jTVeCZRM /cb79+GdWzfhj7/3A7h16xbcuHETdnf3YTads9dvrYaSuQ9zjHuYan5lyQnLANPDKTx6OMVj3kEv +1Xo9gDOn+3DC89eg0989MPwmZc+B09cvw57eN4HkymMRwU3fSf5+Ml8gmBtBYbr23DhxVXYv/M+ 7OIGsjYFWFmRkAnlZdJIEmg1uRzb+AnYUR5efI9POKHaVUOnHRirTldS6/7MRWUqgQDWs9PYOJ3/ HK41Bss19oLa/XHXm1pAGrX3IuBeqUQK4PoWYKXMG280qhVG7zWh3KoMAIz/cX6NFZvpeWoaBnUK CI4StOWfBNw1YMRAmM391pqrVZevbpx4O06cnbUcjmytI/3+Vn6oEaK8XwW3KvpcJZ2N6KtV5Nk+ L5a6DjmANK60L1Lhx+HhAdrFIe6RHd68KV+w4clqiPPTpTIs0X7faevcY9LFaWGiS83Ote2Fc9Wp 1928fvrzzevLr51kRcN7g3lsjuliWy51p/hHh7EBqYxWRQ2dIa6nOWmNopOUnodJ5yLsTccIet+B x/IpXFrvwJmh40rot2+8Aa9+/Vvw3PPPwBMfeRru3L5BiWuQVXO4d/d1/PshrG2/DM994stw9bkP w8Lhej2acIEEaT8Wih/Y9pCMWrTv21xs9lYH1nHH64XIe5sc7VpxTewou+i+1l5SMmyUOM+c1Hc6 lr+q2pc8P7PQwYocvZQr7FjdomHh+EtOztVmwEEoxaA1xM+IHlyFE3GOJ1ywIn/CEiKVMQEMTk2P qJawE8nYZaSp0seTWPDrhLyTZBqaXvvou42R4M1CAZoYq0Q3KB95n/JJM4pW0huHqE6boAKqGvaJ P08gdcmI8vs1rAqVsV0RO8Jn0yRshmNDA7ca6jkNnpNgxzh/oEH84TiuOV4QcPVt6Y/WPTvlGnm0 VO+p1FYeXjdo81LpyJXd86VjmLSHMU8k2At+LhV0XI2Ii5ASl3EJrCEw+8zTz8KZK0+oZp6HgpgP vJDxuID3Hz2Ab7/5PfjqX3wL7u3tg88nMkA4Bl30tIrymL1J9uK1AIFBrNNWPzz2cbJv23uPDcxp DFOi+TINO3USRPGmXoqoJftbHlTORMLkrNdZLkIokHOGElH2RhgD8WMZCLd+X96go3ON2YCqbvKG wnn79rnbgwMTaugbVkZeiY/dYiOW14dMAskh5A2wkrxGnvRVAGtcXk/i3/hvUYhgJ7FMBf++CAKW BFhWhivQ63dgff0s/02sleT7uKBtRuwEFQ3kqaR2ENuzN54ySOuvbsHli+fh2rNPw4U+wADnw62d e/Cdd2/Dt77/Hvz5t78Pt9+6AfuzMZ8HbYxrK2uwuTlQxlCunxpsi7kpJRzsPacKOHZv8Et7xOil sEaVq07SRnYePIB/fePb8Op33oV/ffFb8MrnPguff+Wz8Nwz1+EQ33dvfxcWaFkp7OeoYhV/L0nf 6epV2Eawl968A3fe+gGsbveh1PlBaRqxvIa1EYxbiLU3aUv8VlkopzluiYAjXhPMmEphF4fiQmFC quFSLYxwYuGMdQnsMrfekt6xBMI4l1HZtloLgjjHDZpcRhbW9qIdxvZJbT7nAisjxIAiEcYlLgYw tsiulSt1/UmQZuMgIrrKkNjepYAruEXGQEUOLW+qru1k2bibfp5tvMtrcXnNGqOvrow44LUUIdD7 y9pyi73oSwbmWzsSyCzD9YLrZDpWUdySI1d52uRKckibx1Aq8WWsRH/PeyvmsnE0XG/jBSKlkpy0 O0mYTzG7GI1zKBL7IJAXfNOlh42tnn80fnSaIWxN647ZwoYRTFhOq5Z/5MQc3+NQ5Wj4JBylV2G8 fwDZ9F0EcPvwzMULMMRxWsxINqSAupjAmW1KvVjA/du3WMbMUwHDm6/D7sEuXPrQK/DC5/5jWDt/ BcbFfZijY0nC8zlpQaCN4v0wlxQckuchsuFHOgpWFHc6xj1B7izbaKoLCBXMABC6pmgfcmY6QFhs wkuiCys4hQxXn7QUYyNuLJAkEJ5+Qs1NbEI0nKOWyI1gWYdMKFzSgKMGvd6r0C/JMlBuRhqWLxuW OQ4+5yoklV6U1xyxRjem0spLYl6kSiqRysk63oxsg29PTPE0G1o77oO6vKmGKaifL+O+iuFmJIHh CKTl0jFOO66ARG/pxPwchzJtEujh5D6qJIA/eezl82wAbt2SKFj+3IlwnVPmCZaMGUQGM7oWY+Xi 7+USdM3voBA3MbIlCe8m4lkliwmsIcA7g4sq6+Dmu9LjXJEa/427c3j23BZ8/Lmn4bErl+G3vvp7 cOfBfZxLc7QdK/jdAxFSrIX5aUKITbVZElV8SZl/A+Zk0zXj4Jb+hSvWwfFhAwnjVesCUl2zDGxe NAtZdK4EtJn0BZ8Dc4ceLES5rLMYwrs+KlwI59l6I5jRbksqSAGGsbYxO9ACZzqXZF2b7rdqXxHE tLBvyI2UzVCYqZTzUpr7DZLHVhqbVge9swDeFlVIgqbP5P0BdBGw9bs9WFtbg+GwH9pCSeJu0/uX 80ig5i4FfNaqJQWUN0e5pThn5vkKbF+7DM8+eRUub6/iVCjg1ZsP4A9fewv++E/+DN5+7fsw2T9E jx3vx3AA59fP87EoN8XAIcmDSB9havUHqiXI0bqwBoRdFG4gow0YQQzJPqyuUH7cBuzuHTBb94M3 H8Kr3/0n8Pu/9wfwV778Y/DzP/dz8NTVi/Dm7XuQk3YhtdIjWYE5fieB1ivXoLu6juM6g7vvvQ5b m0MusJA8VAGwFnLMuiI/1GJWXFx44zSl1emaSLUCVYoQTHzUJVJYYpan1lxI2ex9CHMaCDOnhVsa UlskaXQtr3GYdMGbFwNMyPj3EP6sTftQAACHDdVJ5Ny9tKk+ZeY7si3GdxmAE6e7jtaOMHeJwSVv kYhm7oe1tOQonebM0XOWRlEtfS4wI8HlXrYbsPT9ceqLh6YVnK4379XSLzFhCGJITIrEnqnLCMnW DPxaGBPKe64TBWIAWsFZ8X5qrR2XH6ftO2zbvNO0iOa1yi+DiOYa5LkSftTD8t+av9v3wEB23HEA IIr2kWyBMm/cRxUWHIaWmFrCc2vWOQNH2QYc12voFN2DjeIuXFhZwAUEYlkyhePiGI4P9iBFZ3Fr dQjrLz3LNmqEYO/oaAE33/4zKnKHFz/zn8DTn/4SlL0UDg5u4FeX3IeVOvgUOi48ptQ5gkLcpErw AfjArq+VU70k18Jr1QghwyLNpyUNiYvrrLqybl6nsbPoDxFfUeVu6OpEx0tx/oQS2NNOlDbypPFI ai80tFVH8SkkSWsSMJNFRsAJFVmi8V3UqrrPi1C8JgFTVN2iPdFIjyuj/DmvemrtxVxrVdbC8iuc VDNmzmLREMAZX5xvcpcSLWyIGatTQZeLBkkNZq3AtnE3BMCBApwk8nYaL0sGXooLmj6gPMYGkkBD cqVsmlSpZ9VL0e0CD815CuBrG5JlDyoGm2wY07TxtsKHzIPy0tzc6bkowGSz5Zv7FP+LQbOdVa21 IhT2miMQL3PghOua+1hOYYALtV9NOXS0QG8TpqKx1su6sDgu4erGWfhrn/ws5zv8X7/3/8DNhzuQ 9bosP5L2U1H119xHnhNJopIynh2Hhp5P1BM2wNKEQZwhZBvjZS88YuJChaeOQ6JjRV9L861STT8q zqHwUprkS06DF3ajkgpj+Y4GWNI5pHCSZXWuzRLGwLl1fE2Kr0Ibp8hDTFyYXyLjYVI68eYv4+E4 dNUIKsfzxwApVUrZ73NqlzMjMcsJ91yk91JPURurvNNDkJZzOJSKDQisQS7nbK2hmF3S1jzc6JzM pyVL1yJinSgooLW+1U1hb1GjAe/C1vYZ+PCTj8MTj18EWjav3rgH/+rrfwDf/KPvwNuv38bzAg5j rp+5gJ/LKB4JMx0/bqtVibB0zYRUyurnFApP6pSlj4Sodzxe0noLDSR1TOA8NQQu8wKmo0NKduMq 2KTTh5WsD8ezfbj54Aj+p1//Z/DNV/8C/tNf/EX4wic/DvceHsF71JAer6nXGUA1J2kAUogHeOmL n4Y0n8He7ds8Nt1uzr0kbZ5ZFCHk5Sq9IjlsACabxNX8TlIj+NSdpqrozPeaywvRehUgp5bFW57Z IgA5nnfaYxZXrEYySgmRB8CmfSydpV5oGgh4MPE1nstVEy3gOaosO/hKexTHdqZmJjS2aS3mgj5n m1mtTrv2Bm6vG53mrmE24uN5nf+y7jU3yfuQbC/Hsc8tO1XtR9xPtbktzXrNwr5Q6U91kBJJ/+G8 0nIO0/ExaxFWiwVLZ1CFtK8aFt+AMFSqfuBVDyDLo7NZyqtuXbMP+xDd1SSMWR1s+nLkYvn6TwfC J/PP40dt7SPBt143vOHTkvOgaQ2yQoFGWSpliY+SDswHj8Go7EO9fxPOJg/hsfNd2FjZZFB6fLQH u+MDmE+nAMdj7uU7mo9hb3cX5vvHcOetO9C/dBke/8RPwOMv/mWYVg6OHr0HfZjjvrQKE5K4QueK Cm0oupB7KQrk86PCyUU7kiLX3BS7xBnmlovNY2mSXlbVHI0Z6DqQyFel8xTAtcZasIyvKTqZyzhr 84M4vYlYb2biDMgJYoewsbPvUDcHl5MwmZBEcyw0sZIWFJXeo2EmFeKKKjUyac9FAncUEqOKQ/5y DjslfHJcfcXMTYeZGkL+qaJbvsAlYMInzhcnYR2e8CBCgbXlPzlhFCw8EbNT8QRsqSRbi6RTXo+v PQxy66b6U3/auNgmJ18m1lZ6OPr2d53S/yUc00WG8AM8zg86lyCR2ZpEPoQN7PuT6O/TANup40bj vDA6Xxar7yS6uXj2LDmEOsMNKSt5E+3R+pwv+P4Neyuwc+8mrG5sw19++aOwi4vvt//g3+DGOIPh ao97lEpVtXW7SHkIlZ+KlpCcS9P7VejoNBUP5+RYNUyqMzcXXLvCk3WBZFOtmUR2LcarrqN5GY1x uE8fkKuXRuspXrh2e04zhnY/QAsLjK1h1XOAAELD+jAQaiwcJM1mp8KvCTTdMGQjn4dNnNg11itS sdZC9YmkuXXBY0+fI3aNJDQol63fl9YwJq7MpitNQmhuMZ/K8765Y7Wfs7g1PWgzo4/2OhmzYtPp DN59fxeGl56Gx596EZ55+jJsdwFu3b0D//dXvw6/9YffhnfefwSTg4ewgYBxe30DqCqeiv3FQRTt wZRbaek1J1I5LtdRS0Us34ecS/lZy4vzh0Q+p5gWnFtGVbbsTNIGQ3IZFHXgyjIHK6tbUNQrMJke wje+9Trs3P6fYfyf/yL89E/9JEx2cENJChjPprACHeii43I8PYL9fg4vf+4n4Du/81uwd7DPmol0 E6mKl5TZCQCLcxt1pokdkpBy0oQPJe/ShXsbz8tlZsqKDWpfhAbbITfSKr25gk4qdo1la+yxOk9V pWfRhHWNkWLAXimwcfFakW4D0q+0WQHLdkaqzSsNm+qb6DNRq0hmq9xJ8BI74XEYL6y12uxfs+Ys jcSOsxz6Wl6Ty68rfFuKYlm41eySsPROZSLIxzkaHcHezi5QJ8xUmUoCybkyLuGYmnfloj6vbJhC 1MYYzoj9V3FhsE3fqf1ZsjEfRGycvMblsXBLfy+NyI9gR+WXTDc3kSwjrdSSCYAVRAJ9mPRWYXo8 gt78IVzsHcHZtRzyHoK32QGU5FBVMxjv7TLgXVDP4dGI7cbeg114cPshXLh2HT75E/8h9K88BbvH jxCfjPGoVAW8gg4ekQRdPo0ScQsVXdE+Y2lXVTE/lelsX0scSTHWLQZ3gkWEgBHLL50q5NVacYB8 UNaJ2P9mj6jVqVB4BqHfOaWkkjRJC4wABOFD+wabgqLPFDECieQVsAdHuRIEmOaibE7Gf5FVHF+m kINTEEcxfvYwS0lOJ4NP7i/ph3Vw40fHloX2WHsIxPCXPJBOo10SFuCWV6DbdnUy78updyihLs0d ipaWsQ4M8pyMeuNRNrCAy4VtkUPjqcRhWvNE4s8yUk61LdRCmMk4xCuskNLl2iZKxD0/IB8JTl9k lseS6Hi0knXVcw9Vd9FiCt42fh/dA85fsU3fRRMsCs8GoxglwfPmX0n+C8t6OM3ZSGTzJgNMkjJ5 vom/92E0AU5+38p7LNJLBn5UTNDhwfMc78GgtwYfe/5j8PbdffjWq69CiZti1etzjhLnV6aZtpIS D9fZpI2qKi3sGPSUQiaiGNHm/L0uUHVEICIrdNyl5Y9oa9VLDkVTwSdaVlXdzIOKWQxj0FrlqbD8 aN1Td/ocs3vB3+ua1l7yPLT+5r2RvVlndKsserm54I21M4Y92sDLUkJXBuJY2RxB3NwqD0G0u1YG Pfw35EKENI87VnjWOSQGTQj3SvrORvM31eR1m0sczqDiHi/SKZz3drgPx/iPiiHOvfRT8PEXnoIn Lm3AwXgG/9tXvgm/+S9/B773+hscMtnMhnBm+zzehiFMS8/zopNLWzSP5jrxY64UprDvCA08AVDq w0j5L3QOZVJo30YKt/ZCo2piIOlU14YruGn0YFamMKG1VFQsMzPsZiKrgec/HU/x7zXY6l8Cl6/D 7Rtvwa/87V+FeTKG/+jHfxa+O17AA7rsMoHxBOdGdwVu70zgzGNX4LOf/TR8BZ2WGV7rcHWV5+Ji Ya2KTla1x83nZfonCuC0etUKWUDuQWlV03HifR1Vf/pZYOFDnmvtQzWpB9Wxq+wealQBxP5L95Um cmJzSr6rDrlcoE4oSzi5hEPTdAkml2RAFaLjhHxmH1We+raNdHWzrMRhbgAf24rENZ9NxI6n0fnA 0ncus0rLe0s89nbQWONP7Li9T2ChS5Y/I4QDRwtwwh4fH8Ph4SGsbF/m/FBZfwji+hnUc02mF9q1 zR6E89L+rcG+nNZ9yTdjAg3zdtqYxo9QjPBB1x9F6k4DcvbMcqTP/iYih20E5cFBIdE7t4prZxV/ 3+QUjdXJDlzojuHC5hCyvIL5dA+K8T7uHQUURwcwcBnsHhzCzM3h4Hgfdt6/D0eHM/jQCy/B9c// dUi7PRjt3INsMYYOzce8w9qO0zmwZFGCzim1h+wgACkofIsXTTlyHS5IjK+7SckKz6mYuTx/0lkQ 5tPr2rSKVePKU0lFcs389GC5iGqyk1KQHmiol15TFlqmxJAkRsQEsMpanuqm34RxDHyQNhw3kwfp tsCTJs3Ysy0QpJEcFimgk+E/TPZhFT3OLlrlOW8yHSAvg5uTs3dHxjtnjTRHicxo1AhO5gPR/Zrs 7bPyNy82q6phQyR5KawZZmg0d4ygrT+obA6W86Zl5QQGndDZMnDA7B97sNS2KYXQ8oJbwVjz6G4n VNlJCFVy+OLwRGNc0wB4Go+YjEjVCBjSRiXogHs50gTpRAuACzqc5lnZ4kg0BM0aNJKfYIK0FNpj CZe5bEiSCCwGOFEw5lsbfpP7wqK4FIpcRIrdTpioSsePGBIDJ83xgWlnmasiFcOnWaN3g+9drXMY zWvOI2IRCFK8x/fMjyvoJz0GYuNpAWsrXVjMENUVHopBCgcI5lwxg3NZBh//8ONw6/5NePhwh/0c SZ3u6JjLQqg0jEvhaBPClFCrtrUBLdBoeYwW+rYCFw05Btwe9SplAWrJhzNAJsax5k3IvCfL3SbP mdZSJ8sUuMh8Sb2AKkFPcvQq7g+qTkQD5B3PcTMG3qrLQBtFkwNUqXwCVcCBMIK+lhZUMkEEnMp8 1jA5MUx6aVwwUArs7+Ga5dL6jtD2s5msgfWNVZbXyBFsL2qcXx1ZS10E6xT6o0qwGRpdlvVzsk3S OFU6nxIWJO3gWq0gI11JL/phJpNCQuAO13o273DXBZIdGe/vwC4a20e4oXW3noJPvPILCHIeB9fP 4Q+++wb85v/+L+Er/+abMB7NGbhlOIcoNEsuX47re3OY86XPJmOYHh4hCBwzcCuKuUgXJRlX4zK4 z/q4IeQ41ls8vp085Xy0As+FijHq45obTx/sj6A36MMqAqxevyf3iTpFmEgn9V6lNehHLN5LCelr l67Ao/u34Jd+6R/CamcDvvBjXwR/fwEFAt5Jn4AsrQsH7966D8899jhcf/mj8L1v/THO5Sk6tNL6 i4BzTuekYRlin4Q5Mq+8YhtGTpRMFQsHVsGecGGNlxy3VFmimjWp5gFQ8fXEBRVQN63MWEJKNy6t 6larGyrnWQGI+syqw1izuHjjUPGKItuZid3ginEWPaY3UXHFggtHOGexU+N1T/F9kiuZcrcf6XbD 58Dt75yIUpCDCI3YOF1uJYYs/M3zcN5U74qUlNjdBng01a/2QXH8xfkvbSyhAYdJ1AZSxkOceXuY w68rX0PjJADr2Emg9dYf0niO2RF47513oSwSWOltcqPzLKt4T6vrnM/DnDtLr4klOpLABPlgZ+y9 tm8215a0SAH6TBo55jwfIp+TnYHouuIxsgfraEI8ntHY0L7gqGNFB885ZyLHUU4l2g0Cr3Weyr2o EhjQnEeHa+JXYNZ5EkY1gqxyBy6O78HVsz04098Aj2vzeHQA08UOs96LGWKRyQzuTEvWrJ3u7cCt t34IeXcTPv3lvwHnnv4E7o0IyiYFa/NRRyk6J7IFfj7mNAlpu+3wu3EeaIuwjlBIuLdWoe0Za7+a XE5UKJSyxIxFbrhxqBQ7KPir5p7Xc5Z0RZPRKwgzlQQrTmQDKlJRXouPKGKS+6kwhHRGvtGy5fZ1 VEg2ppUTqFcIJ9OEc5rYb7ixHoKX7a1FTuRZm24aGRjJj8MNor/CdOURehxrm1us90R9ydLEQFXO WmAcly5xs0573JPPu05Qqa6VFaNkW27DUwvbRCCwtnypxLUYMz5f67dWeWXcksBQcdVa4gJ4szwU npwK5ix3wDZFKsmO5UiaiatAqTXXcZPyGSenBgYHXNAvomKNebZQaZRSwtRKeYOFDBAEhdx3L4rV IsypDFtqTFL0/bagoGFwzFAFkcjoHJ1rF37EizhxSTiGlezHnrJTRta7UnCK04lcAXezIEAzGxc4 B2bcK1YSrSs4ZkZkDn1qMF8mzNYuZjT5O3B+ZQ0ev3gBDvcPmP1gQ60Ntpl3oGKZWkMIaQINpLQT N7stgDb2OuNr+6Cw5fLfISzlohCDMqqciK6ssX2Sk8u9UOe1anXVCthiEFkZjV57lSOQ8yaR3RDi CpuMVPSKZEodqv+yRMJa1lOUq8GrVBXV6aCVSPPQfEqaPreWc7Fz8IhDoQuWs3AMVOhBa4NYAWJl KP+LxLSrudzj8RThGwKBrI8eLYdgpf8ldxjpVOopFszs8Sax0E7BVcFMLLF11ASek493xnB8LCzZ FAHguFyBx5/5HPzVn/kyvPTcBbiHAPI3fvNfwG/+i9+Bt968B5vrZ+Hpx56AcjGD6ewYNtY2woZJ BQsPdh/BzsOHMEUgRkCjO1iFldV1WFnZgE6vz9dEWlAcBcAH6S8J42qhwqgXMN7TY/T0Kdx5684d GA4HcObMGR4vAqusc4dXNhiuqjMj50GbxMb6GTg62IH//lf/Lly9dh0uXr0Er9+8BX08H/Z40cxN qGpuz8O1J56G/Tu34MHtG3hsnFMUksB5VXkFS8ay0RTkYgvbKNvz08KczbyVtci2xktnYw4jStUY zosqOA9WZSe2QaCJ1zSTeB2cZiPi56zIyB5SsOAFjECb8apVDy5LpfI3yPhAlPfDMiISKpTP2boU p+wECFtax9kprRtPC+vFzLedo0VHJAWhKUbjdewttBWPw0kmit5Amy2FyAfDIQMKdnDnU+h0Pdy9 /wDu3L2P8/QsrGxsiKQMRa3IrixKTi+0/SXuOXratYjs0emv2bk0O4PuFzZ/vBWOte/TadGD+FFG BVu294W9hTgWtmnEsM25fV1JTJjnruqQlRnnsGWOnDgHo+Q8FCuX0P7hmpq8DU8kR7B2oQebAwS1 k0fovO2xNM34qIDD40PIE7Qfsxomhw9g78E92N2bwfDii/DSJ78EF698CCa479SZFk0xTpHWerE9 jxluGwddCfh7KvI8zoA5gKUF1LoPltYWj3mWTgO2K9ljs67nPYDdA/kdAAAgAElEQVTzPzmcSHmu NbPswuGK5hjbde7HPRXiqJK2m2NfaRREIosUMjbswnJNiJ2yQJF7r6BQF7BXOjzasMOGHzM76Ann 5MV7yWFw6hEQjU+qx4Rm6cUuhV4Q0FSUC+WkhLqqC0gXaPj7OFAdBDvdFA19l7gOHLwOdJJBUONu zUUzCOAY1DVASxFtNDFl8CXHJRypblgZunZrPZWmktDMoJqU+bnNlbWxsmO6lqGySiwLJ0Rnyf+s DyuAMVqNphv39FSGIDE6nMadblqayO8gQMiran6lXTVqNWBJnQXgx15mZeETDSIu5fUtU+icfG9J ZnY9VWO4IIG2UXMuVNoYc0QAgfvbcemwNKymr6UedcRZU1hskK8wdV27WkPq0pxwmlGl45w90l7a 4fu93evA9Uvn4OatWzCeCGuQ2vmE7hFqMJYS8lvz5JTnlseiXn5fZMS9vs8byI1Bu46XgDinC83O KVOxAc7aDKF8A3+24dbRhgxgjB20wtm86TpQUGabuejasPPC97+yjqQgrzYbchU03uaqDyYsjs3J Xp7BMYKUyXTEyf7UU5Q6CHCYPeG0djS2jlMkKAROfWQlvIWfxrXcoaYspCVGYXW8t9wLlavxKu5Y VFIhxGTK7xkfH8HBwR4zXcTY07lk/VXOZzt/9hwsBufhyjOfgh//sc8BRRa/+cMfwi//vX8K33nt NZYauP70Uwj4PRdWEEs86K+jp7qA/YND2NnZQcN+zMclB+wsHu/s2bO4jkh/bsjAzYOsbxqrOYWP 0T7l3b44dbUIFFu7J976EaSdv7wC69tnmCnc3ycwdxeB4ypcPH+BASEDUQSgnU6XPeiMw8MZ2sQc tjZzuHvnHfgf/vavwX/7t/4beOzCGXj/7h50V7ZghoC2v7YCDw+O4dK5x+BDz78Ij+7e4vQR2uLS bp8Zdp73EIM0Xp46z0DXlIAaYZ2rsP7F3liem9oFbxuRrWet9dTXxPy78J4WbvDG8PnAQC07f62k a0vHoJFPZcGYs2yfYWehP2hCRuTIU0Zfaq3s7ARUWkMdnsaWRo5VdB4B3C6BxxiUxJ+LbULrdS8V loE1h8bO075TngC0HmIwR3sKiVPPtQk6kRrUrCelzRnn6g9ffxsOJjN48up5GGxsgcs7/DkK2YuM i/az9cvOaNLYCCdkCDjLE27LEjUPqWrVq9P/RuFQB2HenPxs+9qXbWtMXsRiymOao5IEz45t7rRT B0hOO1WjTosBzIaX4QidIT8/hrPj+3C2O4HVsxnuCfj68QGO3S4U5RHaENxXZjkkixSdyUdwNPKw d/ceTA6mcPHxj8Hzn/s56G5ehQcP78NqV7ofGBin5Fa2+bbXyaISpi2y+7a/0Zz1sqWptEszL7wW lqR5k3MoWCMF6Yuu94BAmfch3573Rt4r57yXzeaFyFNRWtpCqr/Z8VZdxaLQyJKSOpIiJu3U6Jgr WyuQ1VGuA4MRTQRuPLpaAV2zESWRd2aUsucs35KrBVlygLwPyGGEm0SOv9PkXOWKmwm+ew6DLoVR 8dgZlc8u2FPsuj6zAQui6ImB4XwrF4U0m401UQYoUechgfYCruvGuyDDQJutNbUGkByLFDeGOVeP +ZYXGE/Shm1zsLxw6FGeUtkTFyEYQ1jZeIIYSAe1AiZK7EzlJjvpjcagPHgG0jPQ6YF5Qw/fISCW FniucishdMeLSZpbx9dj99LVvjVesLQom3GsTy5cA5je8q9qZYOaZvIiSJwgOJjxRGWPxTe9Mqmc PHe5NPVNJFyd9vC8ygn08Lwvb2/B2TMbcO/mIwE+Xiuopc8aG61UG4gv5zLG58sJxCGvoZHokI2O FkjZmtvxP3vEm44YBKporLlCkvXioPm+yiua1kpZ4SHs+5otRMRxIyo9Hl9+Q8MkiDEoQ26FeHFO QqVaKWjGiIxNKNCxUnS7z8ycapq0zs8OApYz2xtoLPrw4MEDeOet1xmcnLt4ATY2NphRJ4PR5a51 c5ZCoBBOr5tx425mCzjEXPP9LcYjBGkjmCJwJ+BD+T6jwxF6kFLFSz1NV4dn4dL5bQSLa+DwOIO1 DaiSHnzo2ZfhuRce49Ztv/E7X4W/+w//Dxjdm8H68AxXKac0RzJNEMZxPx6N4e3v/wAmsymP88bW Jjz2xJPcbJ7zNbkPb84s2ayoQDqkJbLxklOE4HFO6RS6Fqxsn0V2OUaP70UngkKpi7LDa5LyAA/2 9uD9Wzfh3Jmz0B90OaeXPjoZo5eM50Xtssg5qmoExVsX4et/+m34f7/yu/ALP/8LuFHNYDSb8bwp Hcl4JHD70SE6LY/Bk089C69/7zXocXGF9upNGuc52BWN4TO7avPSxfNHQt88rVS2wFueG4QIaTO/ 1dH1YM6mriMPrcKAZcBjP82muhazoWDRJS0Q16gZtNdXrQCaWimWiyT0yGXOQ9uMBaAITUFTEKoP DF38U5k8/VvOFVq2mm2vtxBqe2Di73PROnVakOYDYGvbRxfdC1oDdE3kGFS1bsB430ja5vXvvwVv 37gNm2evwebFSzg/ewLGQKqDDQiFSk76mbbtjdjuto0LnGDreWOgTgJX0Gs7eU/hpEh4ZCuXH0aT mN4oPeZstUhTrIsOl0fAgSCWQ5AC1ueuB4/WrkDR3YLe5AFszW7A2U1cy5vSE3n08B6H/yfTAg6P xlBMcB0vcN9GNDc5nsKtmwjgyh689Mm/Ac9+5IswQsdn/+FtyDoLOEYA1c3W+IYkvnGgJZccbILL dULDIFaBzkwgCXINUhQVzxOWa3FCW3EnEz8TW0y2XVtk0X5Gy7WshCSruepdZc4qyv8b657vJHWK UtQoOqX9uMm+SCtQkUiir6a5RKlrJPY7XO2j40zXRh66hfLUawNNoJaNWehsWah1qK5w5pEv5pwg nKYCQsgIUkJiP+vDtIMGn4zv5ABW19bhyrk1bkhO/c82N4ZspEY4Ycf1DAaZ3FhqAjzEid7jNky5 5ifZpNV8KJV5Tt3SAvKxHwShoo/lIHyjNWY3QoyKMCkcXlUtKUa8qeSucT5NtLGXSjvHLFCLofQN QCL0zybIae6GnqScS6mitTVX0lE4iqVUGJkK25Nog+6llSTHJzBtJdxOvB8DupLkW4dKm7iRvS1C O3875wBgoufjazvtWqVgSihhbr9rifGVhEpG5RzvbwnHxRQ3tw4DTpKn6Lgu5zLNyhEnH1Oe5byY oFeGmz9ursM85wlsVDWHexJjCCT3LUnSk+dz4ndQCxVX1gE0Om5LRv200dYxFWas1vtUM8tlnlHl xa80Rpt+ryQe1iSMeyuIaAph/GlRGDUsUpXXaHcBb9b4/VXTC5HWYKW5GkHqp9aQK7HG1rvVkm9r y7GTOUZ9i6myi/Qtn3j8Cpw/twWvv/kG/PD7rzGTdWabwBw1lKbjVAi8tZCG8szwnlIYlhgGYtk4 JIrAiqUSNBUhX1uFtfWzMOwNGRSyUcJ50O2tslYgMfmHyRo889LH4LlnzsOt+3fg137jn8M/++2v oredw2OXLomuGbqEPeppOB3DGG3J0fgAbt15DzeFLmwjmDqHm+BwZY3ZRLIhNfXZ7aSSQ6hyGI4K GBIJ9bMKFbGFSdMuzJuAsbEudE/xb7JlZNMI3J4/fx42Nzfh7u3bsLu/D2eTbQZ2ewcHzGCSnSTg 2s17nH+X9FcgXazAb/+r34XPfeHzcGbrLBzf3oEOnivlEmfdATw8OIJLmyvw7IsfgRtvv0XVHcwg 0Nq3zha23sMaNntocKZqQEZiIa5anEgBIQ2TLMU8Mu9pHieRLagjPUYXradlR+6D/o4fpu8Zr63l 97EMDZidbt7XOgcxoHKtyiRxRjPbnigHMHq45OT5BDAcvzcS65U2XpEDx2ajAXZxsbk5ZUZRGjhs zqXZZwp0ZInhXvgFzscpafHAzs4efO/7r3M/6QuXH4ce9QbOVfc0kb21IQNc/MXNrwAQty6DIH8l SgFK/Efnm55gE70Cm2UG0lT7XDiHpYISi2SYFEbMcEaIt7/A9UMOC+W84Z7PeWck4QMrCGDWYH+w jW9dQP/gLbiYjeDKxXVwvQTX3CFkJICMzt/h0S6D4apA8DY5gsXsGA52DuDO+w9hsHEFPvrFL8HW Yy/CAX5XNR+hjZqIdEuWh/XCHQ9ACRIlV6go0kLk7GMwFkjBavdpCrLgMq+LSorGfKU50JoyRALD dSOG7U0kWyV7gvOhJJDpmuZocF2HBJ3X+LkcbUXeRZuRdwGSptVXtztv32PFMOQQlHMPxd6ONgaL KpeEeWnUnxkh2kSupRm5SAboYqeQCVW1uTlLAzgqjkBQR0aPK96AlI8LuDAcoEFehcubPUhxY+9R AvAwhRnezvEc4GhOFSGIuBcTblfT7XShn8jC4X+25sygGEYqm6Rc59oVTnxztJm9JevL8w17w3R/ JINgD94U0wSirPem9Diq+AxtqpplpvkS6nnClL+PNcy0GlIqjQQMZJXQ37TBgJf+lDRhKNxMHl/h staBBWgb4+ZC94RmTJwwCrr4qkgsdHkhWg6ggfcAfqIxEJpYe8Fpcn3pNMRHTJRTQ5DotbFnK/kt k3kBBfXTLWZwMJ3Aai9hFmnB4dZC1OB9wYnn9L6sSx74nGVJ5uiVZhouocUBdVOZ3BgyM1TtjSb+ WdmdsTGysdDfTYph2YiFIbdj0/OUU0lVx04YHeelEtXYQBlHKfagikgGWrbp1hEQdE5ZVSf0+dLD egzycQ1YgGy27MTUi8AapXojeEOrrNJJCjAsw8Ut5XvF82E0OmI2jhi1Gtfl9uYavPKpj8MP3ngd /uJ734V7792EC2c3YHtrFYFXykn+dH/2dne4KGifWDYqCtLimsFgBc6euQjr65u4hntQ93PYWN2S MSPh4BR9c0/t2PZhVuA4pdvw0Q8/Dk8hgPvTm3fgv/t7vw5/+JV/C+c2tmF9u4Pvqxlk5QnOo/Eu TA8P4f7tO7B/tA8XLl2Es7gB9ocSLi05hF/resNxW3hh73SNS9sozwxb5sRZo2ugXFwa2AV1lSCT yQ3WNZcJjaoBOLrOe/fuwepwBS5ffQwe3L0H9+8/gEsINPv9XhBAJtkVcQSpB2IP/HQAr79xE/74 a9+Cn//Zn4PVlRzXwzHkvQHP/7Ko4XAyhws4Tk9+iNi476JRr7Q3tM3FWnqq+sbGGbPSOFwuqAsE pxcE8IvvIy0NOX0EpEqY8+LIOaJ/vNybMCY91zRIb9bDqevDHNioEEpAXAOy7Lk45NrpdsIc536s vNA6TfeKOnIWo+PoQmnZtOV1vAw+lxn25cepTurS6ycX62l2Q5lJYty0kIE6A1AubzdL2Nn5+jf+ Ldx/OIJnX/44bOB6SRHY9Sn3FG0lFbM43OQpoT2JABynzBjztpxjaEyqF+az2Seb62ildSxdc/yo lu7vj3q02EewexVVyyMo6tFuVRMYkZDqPF+D4+QMjLIN7rJweXYHzmUHsHnhAmSDIZQHdyA7eMD7 Bzn/i3IMh+gkUaVuORvBuzd+AKNJAleeehmeefmnYeviORb8pZSQDulDMvGTo/Mk1edmayHaK4SS qqVQEWq1uWZrtRgHp+5kPlXQtAh5yFXc21edYgJiKUta9SHrZKFSepF0mTGjNAv6l9JPByEnzufd sD/wOXgEQ+UxgzSKbB6gfaUlJCSTnCedC+07zFzj+smaE29PUmMUmjw5kIurFuroe+37txCESr30 SuqZSQnDqVQ8EVDCG9Hp5XD53BCuXhjAoCJBPtzQ0UtO8bWUckPoGggIzjzMxzNISYAPUSppziX9 XPO72qEup25QHbW94psUhb5oMtLAgfdNT8cADASNZ7oBG2UZM3VhQSd1WKttBkv1t8jw60YZFoDT MCvl1hFjg+c5X1QcVqxDDiKxKl1eZ5wErsLGKY5rRyATAp6Uw1QJFVRon0oOXXO4tVlMph0UPETT ifJmZxrgI9ffgHYfeX38TgMRXlhar8n5fEwtorC/mapMBNTgjORqJNoIKMxLKvUzBPTHkzEMOqs4 1nO+H7QICrr3XH89Q091DlOi2fG7+uQEjKYww3HqUlUPjgeF14XnkgAJaHUob0budAN9WmiAfjab iM2TJLbDJ5gFA0DxvU8TqbqT8HxbeoQenHiquWymxxdvvGKIJcxlOoLxuXJ1sZe5TPVxUtTjwEyx 6XaZhELwimsRf7QQFGedkJitafx60eeS60jDPKV8tZzGeS59Qre3t+G5Zz8Em+tr8NXf/V348xs/ hM21AfRXKOEe5yc6WBTuWUGAMhhuwtbmgEOOxEQNh6vQ6/XZe2TDk0tLrhJ3oAU5Zz1gJ2DvaAKd zgY8/ZGPwvPPPQnfePU1+K/+1j+A115/AI+tn4HVrgO02Xhe6Jni3J/Pj9HzfgcOHu7ACn7nh559 CS5eu45zQ4zogoqEFERxxSi3rCH75aTNk44JX3/tuOk0j1BUGcxjlCzNIV57wtTTve92+gg+Fwx8 rzz2ON8DkofY3NzgZtYMaNEmFsQ24wZ+dHQEm1vn4c7NA/jq738N/tqXvwxb6wM4uLfLxV4Uhq5x TA/R7m10VuDpZ5+Hd956U0K6nThNowEIzuhbcfTFWfkAItmuWdgW4HnP7C5I+kaaRE5iImFViW40 LHe8LuKHrafl9RGLxzLz7CWES++Lc+ICS8Jt0Wj+1SyuSuDfjh9LArEd12zTmAFb3rc+6JxPYw2X bceyo/tB1/6jX/dsq2nsqfI6Z6mpGbePo3Z03//+6/D6O+/D+QuPw+VrT0I2XOMQGRX/dOhz7Gxl XMkfs/ROWppIjp4xf1L5IGOjoJ7tihbwGatvR5DzjcekIXBkHrWB7Gks6mmRC9l3TgLaBdrzDu4F HQohQhdm2Rr/m3OBwwFcmO6g01fCmdU1JncO7t5FR2yHUzeOHk1g7Ih5P+I0jdH+ITy8vwOzcg2u v/hpeP7jPwaFH8Iu9ZyFGSDMQLCMNifJuWAuZQelLcQuzJu09LI8UlavIFko7QfMBFVlGEKiIFLZ 7HlvY7YukyKGTHX9OGUrbQoxw/4CiTobtN5KzoUjeaNK1TDmiIdY/Jx0OIu5SnaVvN/LTc6kdzvV 8OF3U/1BJ6M9rMuAtTNcJwxzMhQVh97khlqFhiSThpPOvDR7Bql2EwFJqrKUqhOu+kTvgzaDjWEO HUTFxLaVfoqeOw5ATkrNCw4PUYI/JSsPEZkuVtbRK0lkA3JWLdWEVGXghQEiY11rBwXxKGXwWAal biakVZsuhxSZWaqrkDdHxtPeHzSWdNIyAwJpGC9RNDeGy8IcAuS4aAHfNy6HzA6MiwrG4xJ/LoLu Fn13kc5CZWIHEXyv14Ee3qShz9hbPssbkMg0sLaMszzEhI0wFxNU1t1VWRkLFftTNiVoDJVsXCcN 1rJhi8cszg/jn7WEOCTPQCtIqZcuHndezYPeWL2KC6yg6wb2ymbjMXue86MDFn4mtvYIJ/EKsSA4 N6iytcIx43ALfsc8uobYfkhOXmOjgoHR3xOwuZxA0y5rKSkI2oY9XgutcNYJJ6fG+9JU7zbjpUwu NygWo8GvewP6zdpKs2aD9nJgDtna7+Y9Q2BF5X2mvUVzkoxHfK+cMwAJnLwPaoA4JMDZmVkw3tIn U4waV6PiwiKNNmK3nn7yOqz8+z8F//yf/DrcvnUDVhGoDDe34NknnoSrl67ieqa2UkPu0CBrR9pu jRlMFRzKdPUEiomHNQRelH80m1FXFsqqOwsvfPgz8NJzT8P/+bXX4Ff/zj+GR2/fgxfPrkCRFzDv rkBe4zrIFrCzswvvvXODOx5cvPg0nLt0EYbbGzCqZ7hBdHCeVXovUs5zo5GQHpRoW1LKu5ywHaEc QrKt3CNxLp5s1u/yGBEwovfSg5wtehAL18X7O50XbOiz3NTxReuymKFt29zG83vIIdduv8NgpSim +Hufn+P0jJrkMga8eb/95lsI1K7zGq+zHs77Q07iP55MIbmwjc7OFoex33z7Ldjo9jXPqC3zELPq FgWw2ctVlF7nEb2PNXpUQiLT1AoP2n9aelPG+bGc76yAC1Ra57SNPP7+sD6idWOPZRAXV/ZLlR0B ZM9jJ+E5aT6+CHZGis+YN6mbri0ADeN6cv36aKk2oagfxSp9EBPvNY1jGaZZRAcgPfGZ+Gs496sq RaIC59Fb774BX/va12Bt6yq89PHPQq+/zvniZOfm0xHufylHZWiP8Ahm/WLRAKoPPHu76lNy+k4B riev0bfmVPthuoSnfJ+XsHZIXwyAWo5D86xDIASvf4q/H+UrMOqdY2Hr9fk9WJnegytXtqE36MF0 /JDz3KbFGI7GFDKVTjDjY8l9o7Zauw/v4Rrfhk9/5ufg4gufhF0KTVeHUCzmuE57CNpSBG9oA3JS sRgDkC+wyKQxgNprrvqkdIVK+v+WlZ24FOSJAyz51mQzep1VGX/f5HOStqs4ho2GKqWF0V5RclV+ IcwdHi+bz0N6Gf3kiBCdjxJhORRcyMkoJ+lwL/kOYgCWP8pJpHyBAL8rciaptCqkSCeBTmb3cn5v g1TNU7IcEgY9VEnqKCSZhpvJi9+Jp0Hv6aC3zAO0mOAXUkJiB44mB+iJzuDa2mX4sedegGt4Qv74 EaT9RC6I4tUs7yHAKUfrOh+NOJa8SRQ7bgLF8RGUqx2u1KlIawo3K5ZzKEpZwwQSuSWFTbfmZjGb AbGxS4OmUFU1/SBLpfvj6lv6aYKbBEq5qg9EMoPag3HOM14jyYeQdht1p6BKW9o++niOlc9hD8Ha AS7ER9N9GKGXjX/iBPXsbZJ+Fk2KLFHalewmjgeVS89KEdDs9XJePoe541yyfq8PQ3zfIEVPNZlD BwFSitc4JRaP9PfwvKllSF5LxSuNV4UGAd/OGn/xgyraGGC7hm1MveU41CEfgibMlFgaqlSsPW/Q SWQoODnbS0g2oUo/vAYKQRGIpeIbakBXThdwfDyGydYcxrMCet2cjVmFx5rjtbqiElCDgD2n1k5u AYf4+f2kx2GHGZ0rgQ6wEKTqvzkB8XUdeYCumQccJgLZBAIjEKUNNIORGDnLHpGxCAZWaegKJnVw wZTCeC5AhHFZ9wg3OqnYTFnXi8Rx816f2SOaWnndKNgbUyreccVLl3SM0qgSj6l92YWhhtjhgKbC UJkUXq84/2sWyvTMGCf6eXqNmClu+1Pb5piwoCWLcc+mfF+H1AMKB3SG5z1CA0qOBIcO8fd7d47g +vUn4T/4+V+Af/SP/jFMqx58Cr3fS1cuIdjG9yEAneH5k2aTtRebL6Qva87zEccAATmRaYvZCNdL ySrpD8c5vPDSp+DFjz0D//Qb34Ff/pX/EY4eLuDMygX8nGcD3OviPcA59ODWG/D2ezcg663Ah1/+ OKyvn8fvQOOOx6WaJ9IcyzxugOMpS4hQoQJXfzlpsl7OCXwRmKZ5PIByQUCy4Hy5BP+Z08b3W8GM sPJy/2eco+pYQ2/OyciSWEy3ZYLzczCQbhXHo0P20C0PhsRaubiiTFgrc2VrC452b8Ebb74HL3/k ZeiibaTE65S0qFwOJdqIvYNj6K2nsHXxDLgb72pbNS3A4flvYbRaihpSWY+S/BJFU/itMZu+HBKV +9OE4nzYpBsZDceabKGTTSDyo/QCdqZPSvhY2gk/x+spU3ZfQlFk9LgzBTps7EA4Syungo45g27u p8kFRCJfw/Od0ltoT8J7TIC0Yj9GtOIsxYf78WqKidh+E3xXxtEnkWxP84gLuGwcA/CLOuvEoJUs zAztVr+DjgBurPST1iH1As9xcx3Pxvi9C1jJK5hNH8I7796AP/zGd8H1LsPHEIgMhhfAdws85hzq Wcn7HIsfJ9I6LSNnX1ULeMRb91GliyphV+mP8KqHkD5iVa3hnKMCMJvziTA0+pxFauQeETAKWq3y iiojyIRINdJD5U3krJD7niZTZghJG47AzCHtR5vXYLFyDRJ0ELcO3oGrawvoXVqF1f4ERkczBGq4 1xeHMEdnxk/QaZ+P4Xi+gxugh507bzCjvXbpY/DUZ34W1q5ehwdHO+DQacxw1x10B43NwzVVzzTU SVEGtGvscJfCtnEFqN5/StOoGa84lj3LuChJyJw8FeKq9HO2qYmvNX2m4ChTufBKUpXM4JEdocpy /qkt68zW0zDbvCRAlpHYPRXl4crt5nUoWmBhbCuaUEefCjwrPAeWKaHCslKYQIefZ0op7UDg0g20 NQvdqeK9bZJL1LFT9o2+xAkFmXYcTKcFGrUBa6MNcAf57HMfhkvDVejMj0kpBrjNBjVKx+NTWf6C qhPnnuU8CCTQcdNMqjiKmsqPEal2c5bWqKEJe4TzDj+VwVCvyTy+UmPWTWcFCxG3W0oteyZhEWc5 eG2Rwu14VKuNF0SiGyWOUy8dMvjZR69ybzKDRwcTDpGQKChVxlElY0Wlx4TwQ9GQ5J1IXouKUVDp OY4pAV2yoQUzBrhhzrqw1u3Bao+SzHMEi1Q1iAYKN9uEuySQNlimLUuAx5+ELih0ZXlfsRESKt6F lD8zYsvjYK8ZwGfKPRIHZcaxbox6MA6p0PkLCiksKNexwM0Wz7kS0USSFaF8iIQ8LhDDWlfClBT4 fRNcbIejKVf1iBZeYtFESfRn4yJGJ9xDu3d0fUmqY2zXUIbNxooj5FWp9IvnfTOzItbhlDnCobtc PDbR9Yv0CfU8S95plNGQD0oyuYJ3zinExVnVUqTA8zZpztlr3qNXo2qhfz6/ulatuVoYNjUWxELR PSJDNOx3eS5RK5q6TBTglpJXQekKXfkMeX3UR5UEcucIsge9HoO5e/fvw3O4hr/0pZ+E3/39r8Bi OoW9hzswR/Cy0u9o1w5is+d676UtGh2fdNs8AtukQKPYRdCO43R01IOnrj4Bn/rCy/Cbf/Iq/Mov /x2YIHg5v3WOmbIS58h6ZwsWRyO4ff99uPvuLTh76RqcvymU89EAACAASURBVHyVCxc4qdiJQSWP l6ticSIMhj3cKAuYUZEGnndBHRDQDlEIi6rbss4AjkZz7pjwzLPPwaVrl+C7P3gNipEy7+BC4YDF KWmcO/hzRgLG1KOQ8mdSKZRgnStOypeKSmJDm3ujLH+lzFRozwZw49ZNOBqPYWV1AMd7I84ZotZd uB3AlNf6gKtrKTRt0/S04heeATTvlp5fDnn9qBDYacxUXPlo7M9ytMZel/t9ktVuHV87JpjtbTH5 rqlM9crAeRVYJYHp+LxLcy2dpXN4BoZJ0IETGan43OwRh8uX7f4HPT4ojLj8+jBPWCuR0nIWuG6S 1ESjCwGTCDSOphPYub8Hf/KNVxHgdeCVz38BNrfWcX3hxp7XdvZLbJiJ+up4uSYXuHUextAtMWlh xzZ2zNjVVsgTRBy9TWKG7whkoyophAKLpMEDFBbNKhJ6x33aTaBO+/hzC3Iak3of5n4V4NzLUKYD 6B7cgAt+H1a3O5D3e7CSjmHnHgK+xTEXK5CTP0IwO8Pxqo5HCPjm8P6tH8ARbMPFF38Snv3IJzld Y763Bxm1eiT2cjGVPNfKK7MrBQcyHxwznBwd9BJi7nS7UaVnwrqWDJnVprKgbzXDPbvUvHnRwy1J YYFytTXaIHq1NRdxsZ1A0NLVKuRef4WrsWnf6iFgS1LXsguyF+ic0v2BbC85JzY/rYqG+s6z8C9H GTPFNWmY/5TKkcWApV5C6YLUxYp4Y+ZqqcKgDYWa25NMuWew3uUTI0DWTRfQQfT41KXr8InHrkAf je306IAF/3oraJzwwqaIWKnBOUlil5UkHS9UJZ8V5dEYz9FDSxEQuf6QgQlXOmmnZ65MrEVxpnJW AQIqz+HChCy5+iqTRVFFkhlO8gGYyajrVtKnj/4n3gwoC5TJs3RzyXtNQHPEKAk1g73pHG6PJugl TGEyxokzF6HakvNyMgihUO2S4RlkAi+QJBVVffIOKr0X9JPDCiUlWFYwRqR/NM9hre9gdbACw56D lYKqAEVbpmLQhAifwmu06TDjuCx2WaumnBqNJAKt0f0XA6C6Y1WlTGZjgEM4kIxPIveFzplDxQwu SEi1FuCOngqBaVr78zm+Nheh3wUulEyBd12L10gdGGZ4UmP8zqPxnBmVRIV+pWOIhL4kB0OuByxT hpWwtXOD3DI2+Kdp5fkoNB83mJfNqwnHJEGSQx0bykHJIBg0/oyDUChDgCa1GnaezyWfYSyY7LyU W6SgLaec402ABXtZ2b0KKQu0uIk5YoNEDkUCbEhigWoyHMT8yHPiZFDVFNHzxzgX2WixwPaMme7B oMdGVPqHzrnyy2ulJiXl0nctWIy54IKBuw/uwmdf+RS88cYb8M0/+iP4wo//JXQgBiwzQqx2zmtA cpuoWrBOa2aJqQJrQTIoxPq5IeyPAVbOXINPfelL8Pvf/jP4pV/7B3B4/xCunDnD7LNDwNlHR2Wx sw/vv/kG7I524dr15xHAXYb++jrnorEeHXVVpLw7YjHpaikBupyy5hutZ2J3et0+J4XPypnquQFu EhWcOX8JfuLLP82SJV//8z8F0ibms3dSqUYpHdzuipxTmrel3Deq4qV5WOs8txxSti8UDsNxIvkc YvgsjE8sELFNNHn6XQRt+Jn33n2fdROHm9tw9eIK3N/bgSO8v93eANeL4x6162ubzO5NEXBmndQm suy6Yf+09lGnOSDQWqengZD47xPP+wgEJm3Ac1o4NXZc4mPI6mzsahOOSqVfrlbek23gnMNU5F/I Dlm6iX0Xa/i5Ro3A1lLCXR8aANecW7X0949q8v7/7xE7/p5CZzhHOt0h3x7aE8lGUH5bMSY9wxLu 3LoLX/nqH+G19eDTn/+SVKMOSHCaWGcZJQPPlu4heW+m3B+FywNIU/b+A8B5SK8I6RhN6N3eIxAx 6j4Th4HBhZ63TTqNaxVU2IdonwYCL3isTkm2CYFOvg7V4FmYuQ1cn/itsxuwmhzAVQRw6G/BdLaH 8x7BG+57h0ePYHZAQI7SaEaICx7C0f1bsHNjB6rzV+GFj/wMnHv6Fd4jD/ZvI8Abc644NbN3nbna zybUST3am9w0Wtc555BlWRr6NJN9ZHs1OcB1twjiufRvvijC/CsXon1rQI/AGjltnW7ODkRna1vA YOIC2xa3WZsXCwmVOnNkxB1pcta98qxCFBHGYLbbwvT5Cv+dqnNP5zWfSFcZqnr2bob7vJXE+pPJ 4aK2bb8rW6ceAkljsAIMJd0RzUStM70m5uPz51YG8LmPPA9n0ViOHu7iRoReJxl9otqzLpToNRMA pLwn6S0q302GkBBvVc+EmZjMobuGC5iod9+wQE7z3+a2QfO4NEnK1uoq4DnfTEYBIymHvE57WE4g f4433VTCtJwDV/OGS5+kUGqS9tDTWsDBUQEPRzO4j/+OCwkPUNkwtegh9o1uPG2MNYcla97kpWJF wgZyjiLGKK2StAOG7wrr6YgqnsBi4tHQd2BaDmG4WMGbvAF9vJF5PeIiAZYUIL2hWsYSkuVF3hSG 8KJ2oAnxPnbSgEGvtlezv20c4/wrAXqJehMCJCQoKNo4c24LtBAaH+89KfV7Ylcr1nmQSlUvmmvc moYMNkkzUKs2yuEpm/AOB3q1Oq85q0oBeKLgVOCRnlV0vqdXpp3c2JYYWU2iDpuQE6+WQqgC8IVZ FN2fUhworSyiSmOXNoUIfHxduBy2SkQ3j0nGVNrA0ThKtZ7kaND8oJAra8ol0ns08cK8saAkgcaO sJIU7qsWIi7JNVecK5IgWJ7xua8NB5wLNjo+YuBH0hhkpOh1ShWg+UghYQ7V8EZKbDgx5TPYWFuB n/npL8Hf/1/+V3jtO38GL37sJU6s7Wcgua0abqAHgT+aNhSamOB6GA5T2EUE1+1dgi/8lZ+Eb7x/ A/7rX/n7cPDOLbh65QmcuxIOI9Zr5/57cOftd5ghe/L/4+tNY+y6kjSxuPe+fct8uTKTS3LfRG2U KKpKYqmkWlxVvVaXG17QgAHDA49hwzA88AIDNuAfYwP+MT9m2hgMPBh4gIGne7oNT9d0T3f1Ukur pCrtu0RSpLgnk8zt7dvdHF/EOffel2JNFlgUM1++d+8950R8EfHFF8fO0sETZyUTNvRVmFYaiEJH uXedicw4nZ9t0m67S91+T8CpGG++FGjalWoAssiKj+no8cfohZe+TgePHaXrN69SkV877HQl66j7 KiapoppgxQ80yNO9IF0sxp5o5zHML/a4gBIGn4NJR7Sw0qBAu0GDAPSIIo04yNvc3pK9cOWTj+nh Tpsev/icAACMmJtBtyo/fuHWCXcxkDJuVqZAJaGy2bBpELc3U/aon/279n/yZbXQnF/9+gQUOI6Z LJES7pPzGalOWBbEWV06ZEYkG51THxJHWpGB07UOLhlZmJxHi2fTKsGXs4SWFqF2Qb9v1y7Nbv2q ysPUfcamgSyTHZn+coUTOkIDA5+pQt6hQWdHOFY59i+3b96iv/7J62znyvTVl75Dh088Jg0LQawE 9iiyXaQxWeK8jFhDl7/69ek1NdcTeSaIjabBa/b6s/dn2c+PKiPL31IRmOY4SnBqM0OOQ8k0puS5 mMBfcYe6AmSUeI1HhVnqFw7QOO7TUv8OreT6NLswS24ppFH/No16LRoEedpu3RJOGCo1IYNeGrbo PtuAh+0x1Q6eo1Mv/IAW55do0N6i9naXfRt09xi4eBWqxez/GJwBlyGQBG0CI+0cV8XGsXs0IPUZ UA+pa/hpAuAmBrixLZx6dp5mhEWLjTHHPAePWm71Et68cJBzuqd9O/bO8E5Rvs2Wm1WNwlU/QXqG dQCJ+XneMwAOpyIv5dG8a8qtqFi6oVxzn/3meDSgCabl8N/+aCSNEFEu1HJqNg2bJZ7aTi9kWews ufQPUGckvAmfLQ8QZ54fYsyOA0bxucfO0Lm1g+wA+uxcRrDoNOb3aEG9vTeUET5eqWAaI0gAA5w4 yPBQ71exPHb+/SJV+b1hcJEyFWX82JUZq+RQQnS1Gza0RPfYltf0gNjBzSappq+PXDMaLEPcN2lr +z8XxFLPvIdMcCCJjoGYB4FPg1HEG27IAG5Ifd+RkmAZwBYddewAY47mZdxRpINypVFDmjFIDqzV prMHahwMk/mOmo6fqGajGZmEkyK8M34WmGbgz83QPEcFc5hMFbX4x6MkexrFblLisRGZZ4j+VrBS gzB36sBn0/pZ0LYX7MvzDuOpKDhtekHKWrOcWNPhoCfzKhGdOqGK04JTNkYaHtlHlOBiJYOiowip aZTIXHbUeGahWROBaI5pYkktliyslSQxpzIpJdgM6HTpR0fEWSNpM7B7v+SePUoiXuxTzU7oXkHU DSkA5T64JiupytvqO6JkmLhcg5M6OyQLANhtIGU1CyUDZ5pfcNaL4P+ECkrEoKDjK19Inu14GIoh gwGzkjKFvEZyRYiMIk0vWWdHjAaffZUBGmmw4EqmqCDvkXyuAb3gmwR8Hrd3HtKxIwfp4jNP049/ +iodPnxIZqgWZ6vyXqGhLUgDURyaKRwTqpc8CXD6kxJ977e+Sffau/T3//d/RJt3d+jUyn7aZYA2 cgJq1uo03HxItz67TH7BpUNnz9Da4dNSYhnBwXu2lEDybDGmp95YpN6wRzfvbNBcs0n1ekEmIWBk kXCpMBGk35UxVl996nmO6J+l/WuHJNOPDtxGfZa69+4LaEOQZTmRscjEKEUE0iHSRcbP3gaAKj+k c6ODcSAzp62+pF1HzVyTzow1fDa832iio+d++fqr9Af/8o/ov/4f/h5969d+g++zTIMxnxG3zH9i aXDS6RP5Kfs8Daq8TPb4V2fZfhWA01Ngzm1ybKwzS6LfL/3O3vezWXH5vi3Hme+rbXOnsnSWuoM9 4+XVn6jkT1pmtdSN7L3bzxKel5d2uO4FcdZ3WRCH55mVNVFOlBWDfuRj+dJXnBXiS56BhFJ8PlRT 1GfbPeGAoQz+N++lLz7/nP7mtV8ib0wvvPxdOnDsjOzlclGbHdS/6rSjqQA6NjNMYzNNx0p8ZfdA Btg+6sva/diWm5PXU/oeRMYPGcdI001jGbxLbka7zGrG4mvM913ndcwHPerzuuyU9lNYWRMx9Hz/ Os0UH9C+mTqtlJq8Bzq03d6gzqhDfo/PCfvM/JioDe7zpEe99kPqbLf57K3Q/jNP0MFzzzBYzcsZ 9jiQXGyWyM8VMXuGqmyvynIdJVLZHAZl/oBtG+OLyUCyacATg15fM2qmyc7uC5upA3XBlleRNRcZ EOO/LI3FcmWBVwOpNo0oHJpg3Eu15uxzlb2R4REK+CXX/K2CvjY7FxU06My7eeOfXLFDI2OHB4Mt zRAOB/JHVUB8mSes4t2edqfaxUkFQ6cPqN204qDxP5l9pv89QtSPbJIZHzHo9GlmYY4uPHaaqmyc +4OuoNXAgWQAv/cIWi++tJJHvDhCukXJaDyU3wd5LzDipRPMJ2TQNx5NKIeybTK3LE4Mh/zbRFhR dgixq4Rf0R4yHZRWv00nysSGtxQZh283udXxMt/DQc9p+VPnpgJcYThvTJ1BTHcetmmXH/IwMilu OA98JkAXSmU5uGxf9ZIwEy9vZ1OGkgEbMqJG3T5nNpWUao24K37Xy41UsNSHUcurgKjgTF9S93d3 2cg3wDEoM3iEODI/0xj8BDSOeMp/yjwXyZPZ9HhoFELcL0emj4ros3tEHFSknY4a4pm5qnaaAG9Y dG7iIEz6E6ndx8VQQL4MfDD6fj7/D+TdSIxVoNw1aOU4kKlQ4iieayhnKdQStjE6cZzhaTjGIuHT E1JzLAAsnedrs6vJziGri6X3Oc23tM/BZi2tk1YOo2MAFYMkG9g4scm0BWKkHSczWNyxhzlWA2ib FPIFSqQvjBWw14JnDH4I9oek0z0nKdlKty2RZI4AsrDbAe4cE5DkzIBmNIdYYzQAkOb3qZpB7nZU mAQSwkUtaAdnrEKXMB4gkBc4aEHjw72NdXr+4jN09epV+vj99+gbq9/Wjiu+hrzxAyJwbEoP4uT4 2totly794LfI39egv//f/x905+3rdGLtAAOuiQylLtTQJLBFN65+ytdRo2NnnqTGvjnqR2yMcS8o sYI3C1maglIvKgzAvvLi1wXE/fLnP6fd1i7NzNbkmUD7rgwxTdJO8ZPHTtDS0hLttLbZNs1S6/4O v7bO3z9OGzeuJYDAGnOZ8MARL/Zlv9US+RSMBYxNxhWfgfgZ5zI2dsICWNiuHM4eCcoXkI99C/He PBvskRFHHnFkfePqZfpnv/8P5Pee+uqLHAR22R6w/eRrQAOQysSow0wSIJnKAhm+sjP1vezepQSk ZM/2ozI28t9x/CUbMAUgM9//EojL/iym9LmI3qWTZPayo7Kw5zFXV/FiugawubY5Yq8gdvK+wocz GaYvARnbxJTKLGVLrMpdte1b089ub6bR2rb0OVjQqK/DXpmMejTTqDBIgK3Gni3QZ59cptdefZ2c 2hy99Mp3aeXoKRGgLuRdCW6UJ6UjmvT90oxYykvzjK3K2GD52JQO8uUsZPpasdWwndnfT1Ccvpfr uFO/v/fLyYC3vc9AgkWRmRqRz9c6KR2gTmlV+OsLwQNacu/RctmnMgd6g9EW9TbvKl83ylGvPyS/ uylrsdvtccDSohb7CMet0P79x6nAvmLjoz+l/Mw+Wlo4yud9kR8VYwZ+voWAsUF7R0S/J8Il00ZE cGLBUdPKhU48KVfyYj/LpRrN1otabTAJEinDgpaReXY2oMYkoZRaY5JAWfcgoypNJO6mnaquKX+r AL4NsHLazAjsAN24fCHxuRHVSWlCgdhKNHSMxx3hJqPL3Wf8lIgJm7+RBIEsVCyVtppy4rKLmzgq s2BBpIJ40dRh4BcidQJ+iJNPurnwgEs5h84cPUwrzQaN2QB6E8xTzEvGDfyFHMpkLqNiZ0hDDAF2 tLMV2YxQZoiFwu+Bo5yM0VnGKBRAB92ieQU6MrrCZDNC83d2o00LwmYOvjl8Wa7FowDrlJEDZw7F DUfFf2GERryJdjoBrbcntNH3aYxOtFxespZjIbNPJFuk3UaSdzG6M2ESDQDEoY14374D0o2FTFX2 c0HsdXlzFrwUPDmORrAAMZ45eJPhDm1RjcFRiRaKNaohIxNjtJmJNilrmKfvVcEIJYd4b9Qre9V1 M9mFtFyRzOCzqvIGDDuG1wgHmnd1veDYeoO+gAOwCov8PVEvjzWrJqROmQKi7xGZDrR4ooRyZDEl SxQr8FUNJNuTY1tLTVHVZgVixWxhLo3OrQjmnrpxauDt/sk4qVQfKH2f2DEkbeFhaEOK59osAUBn pCDbCDLK87UlSvOMBKThmbPhx+vzrpYKI8sPIs1G4N0gpIsOCOUSOUY+Q7uudARLTnKUSK+rIXG0 G8uQwzW7lFIH0OiA78G4IVOHyQuDAe/hsc4dle/DmWIAc6tDUb1E5WpBJFMKToGOHD5Ev3zjLbr9 xU06fHSNvCLKD4bXinJYQVvhQfhev9+mE+dfoYOnT9H/+o/+Kb3x+ie0OrdPuF8T/pwa7x+/36E7 16/TiK/p6NETtLhwgG3DiCZRbOgGrpSnhWsonLhQ9s/ywUP04tlDdPzkUfqLP/kTvp5rND/fNIGT EWaOVMft2s1X6fzFC1Qqn6Q3f/Qzau+26NChwzTTbOoeRAmYn9mQn+FgNBZOZ7lao1UGmwDn7e1N eaaepSdAiDdUWSRxljEZbqKuucyvlbjEF+K12DRk+Ph3RESYf+/Q6gpt3b5J//T3/yH9F/xZj587 K81eDrB1nJNKQWTK+faMuqkPTgjte/eyPbeaXZ7mg+51/BFlAAClQM7+/FH2MfuV22M3EjtizmMK UJwkA6KBqHAItJNY5mrquRUQPclc/xR4MHY88/kJvzjee50m8+GovbKKBHoes4mLXwHe7HtJBs6+ bzj1N76gs1fkwGLY2xadRXTdv/bmB/TmOx/TbHOZXv72r9PM8gqfiaLJqsmJ5g/Jy1g20YTLZEvN pZPmx2k6E+qm3YupT3h0Bjb7LGyycYrz5hgA+wjwln2P7BxWz2Q108/nwCTKU8er0iS/wIHOEs2E vLf9z2mh0KcFBrYVCOmPWjTCAHufn08fo+zQQbrNYHdA27ttGveGUqEJewzABm364OZVWjmwQt/5 tW9TaekYfXGrRbdvY/zWiH0i75cxhL8Z+DHYgV/OeTrODxqO1WqFSnNVKhbLJihTqk/qv+LMngr5 rPdNEJLBD3G61/OGkyp7ORMQWZ8QM7bBzyVTKXw73de2GUH2OnibXs787Rr7YOhd/kCC8AGDteGg QxOfrycci+2EL4H9kikQJjNHsZ2N7BqZE4wyS2QL9tTQTUoaVsOZ4gLYRTWlGDbY/igSrxmOhrS8 vJ+efeoJ4eRM2HFXo6JEA7Gk/0C+1xqvZJxcCML6RupC3w8oGuNo8IBBgo/ySjYsw0F5RbPxIh1x IYAzTb3b68+SyD13b2emk0Rij9q8X4pmGXRCvjPSsEW65wbjmHa6Y9rcHdGYI/QJX1uRr9UrQgaF jW/RlO98Ldm5SikQUrbVqgNRGhH++aefpRs3r9ON69ekK1BLcqnS+cDXhgivIFMfJVM58V2ZH4dI ruwNqd9HLZ4/b6ZKhWqVyuiECCeKYtxpA6GGPT3USceXk04dyBp6W9qzpSR93TRpWB63+Kz0OQPA FXLaUQzyN5x2Me8L9o/5+xMAP342JXZUvkyr0GvRHK+jeV5cV6hGT6NmdQZpqUQBnb1eU/WUQ4jS ovABM6OKhKDqpslv/V6mo22vkxLygpe5T+0IjR3d/zJ6azKWzk55nkKQnSS/i//GuCnZp+bQyoSH yHT6IiCxLfDYLzkjUksaDSLTU+IIUgm2Y8lMp7y1SAjy+F1MCBhPlOwKEj9I8Zaki8/B9xA0AGBI K7tjJmrw74e27Fosypkbm5FZKKPidyscqfb5HA/HPQpqPi3VF+jMqZP0+uuv08b6XTrIICdC1xG6 zo0WHwwazvhua4cazaP01e9eon/9Fz+lH/6Lv6FmZZbimbJMKJjJYZ5in+5e+4J2GOwdefwxWuT3 C9kZxhN+RkVMPhjzvUfCvZXSczCUDCXKyL1Rj7Y7HdEYXDtyiDo7W/IMcP8wmhZQXb56lWbnl+m5 5/isXb9Clz/7WCY2tDZ3yS17KkeCJUPWkYO2+swc39cxOnPuHFWaVfrg7bfpzXt3+ZH71KiU2d6N xf6UGIRKF6UJ0ETfDMGm5yaZVu0SNvpOeK6Vmky96OzuSHnkwPwcbTzcpCufXaZnnnyCMLsOEkqV cp2DnC1KG2imQZJhfBLRdCCatWU6MWHa0WfLq8rpyU6yScugSRCzJ0s/Dar+3V/i+KUaoIG1NK17 tvFIecWij2ZK1XL+IfobK/fTZuOyIC57drUpSa9aA8s0g5elT+i5s9I7TjIeMo6nu/IfBeTs91Pg lsnK4YwPGVg46PQeUKe1RR99fJXe+fAaLa6cpFe+9eu0sLRCMe5Rglw+f/zHlWC2wGuTgiJ958yz 0w+f4v/Zq5vy04G5biddW32tCTrjdK2lMpXZR9YX2Gcp6515FmrrrVnUNczl7NQiXzizA36/cWGN BrkFyo23aSm4RfvLQ6rW+VyVY9rtDficQQ5kLFc0GO0yoGsLKX/Y7VGh2xbawLjXoxuffkjx8CG9 8p1v0cu/+3dp/xPf45/dop+89k/owZ07tFjfx3YB/NMczXPwFbtL/N+echELSkGyHHBdr1CmsITJ CCxKhM+j2Aqj65elj1i5Fdc2e/ix8ZNexpeSwURIlJTE3snoUuAc2CloL4LT5gJEFpPPC6Wsy9cU DqWrVqZajXYkWA5NI1VsKB2haVQLnHSmu1ZUDJ4xGcIiqnjQJxP+hlxAlDhzubGcEnNloCscMTtG H6NE4CThwLAqSKXSRI0M/97540fp+HxFyPZCls47YrAnpF1Eo2GPJsFACIBVzM/MawZhjIctaVAl iweiyRbzIkYCmmpeWW4AOlDgWsHNTxixSonJREu6Px2z+T0xnkFgOCk0bXjsZrc6cQkhN3P/sJ9j D/X4POUBNIoOdfkZ3eqFdKcf0RATBUYjWVSfnQq0zsAFACgFsEPHjmfeD8bdzgmEQRlx5LF08hSd e+yMkGHv3bktY0MqDMLgkLExg8lQQAQcrGcG3Pf5UIBIi8wMMn54DRTyR70ubfF1VGebkq4t8ObI YTA4+EGkQ71BnifJ7sTSdIGNGk51H2WMuTViKG1Ai4++3ACjQqChZCpEs0tAFaKFsWQifH6AOX78 TgjBVGRtfSoXtOSE2ZIwYuOoz0GpdmNhcoMLwcZSRQ72hCOtCB1eji/XjXX1HI24XMzXC5HFmnAg ANHDBq9BToBUqejK5gc3C+smYFBKF3lV5sCtudpdHEWZTmwztjk1/iTjwNB9KNlIvkZpWXd0PeXw oTkh9ESzJ3RVYxHNBYiginyAQUItw8Bgr4VQZHeEQ4X3g3o7gC6yNBIE+erY8iJb4gogcR0zZcLR 0S/DgUqlSMYsj1EvfD66LXlNpeBJBIdxU5h8gdZn3IPPYAG3VACgRWaIwJXT0taAo+AipM5DpR1U CkWzzzpqDLFmEAFGaXa3S9VCjZYO7qPDx4/Qxv0N8vkaR848Y7iI75ej4jFfG99Pi51ayy/St3/z N+jz9TH9w9//5+QyOJlhUDThBQDny+Hru79+le7ev0urJ87R8soxCVDgHH2XnxVAUYCAAJqCvJc5 YHShH9bzRbW8XsrRzvp9+v/+6A+lfAquagEhDDJ4EZ8hlJZ539Vqdbpw6RLNLOyju6+9wddXoFol L5F9xS1rI0k/pFJ1hgory3Ty3Fl64cJzVKzl6Wd/9WN6/713BHJAtFwkBfIKWIfIwAMQy2gvvlYG xTZbJsAFYZdE4xhFiFIbf169JnIvkGKCxlaX93y5GnbEYwAAIABJREFUeZgWl+bICzwpGXl8NkpF 3h/8XuVcMgZdIpTIEJVsRcSOZYqUK0KWOiDfR7Dg5lJ+lM2ogJPjkoJ6Y1cEQJnMvQRpMRkpBM8A JDI/ixLeq81a+IFvyOCevKc4tJwSyhHMRUXeu3xv2NyFfKxNMIQZkfxegfLbYLOgiQVgC7I6Zi9L 674firaXI5zsKLHT6ejDXOKE9UDHCW1CNegsd8lAG1czSGTEsx41JF6epxGBlcF9joJoyEqAk4Th 4yjJTUYTEejFjO+d++v06hvv0BcbfTr91Nfp4vMvUIP3XVjKGYqIcoDZ7UrAhtA0n4tFZ1MKv24u tb2GvC33SdkpMxpyRoaygLDek0BdXVxk1l7Lz8aGTdPp9BlEKTAI87C5UMfV5hTfMfSbGAT+Ig34 5xXMOkfGbTyk0ENgCJvHAVh1hTrNA5Qfd6ne/4ia3i6tzJdkOo/MVe63KRpvCr1od9CR6UwRAsLu JgdgY2r1eW38a3TjyogefPSAFhoD+s3//D+jS7/3P3EgtUbX3/wx/eKv/l8OwFZo7txL0hRZ4j0A 04ZLzBVromYgdAXYU5P8kQRUbDiHjrHvBpxigICk2S0qsCDXTSV1rEB+EuzoP8QGqq5oTrXzSEun kWTh4CMVyOm4RdWl8xCkRxrQy0QIcIUDDfYjoXoNkwSBnM8wTTjg6Es53JzbMNNhTaYDFhgtl4jS PeIrNhGR6oCZhgEZZGqcOMpABVdQJtSW5+dqdOLYYflwiPfBqYSRDtONk+5BRxyKG6tTGplDqhov gaQNwatB1xeyURyQ08iI6IGLZp2rHIwolcgw23Pq2i3J+1Fl0kfdc/ZhqmVwoKSraVS+6DE/4J3+ hLbbIxqPtZPIvn/WSOJ7yAbACWNMBq69Ui7Lz5DpAEDBMPDHHntMBiMfPLhGR48epatXAwGkUoIM dHwVxFmx4EN2EMIFYpCHn4+MSGkOnVwiSOzx53XYKfrUPLrMm4yBHQMkELy9DA8lOc2OZgmtrMje 6DqN1IIpwr+CXBuhmWYDx0ZzKgSpbEktM0I8FmuF0rkVDg09HVkl7wFtuzA0SvMFcSoTX8sjjUaT Tizvk04sqOZjGPJ46EuzjARRaILJhfxsZ2SPWVI7BHgxxgTNMBH4daSRd3rvaWn5UVmM7HOwHa5Z kCt8S0RaMZlsD6QpXBGMlAyCq7xNOOmpAd9GTxESITABKGXKpIFcGl3hS/mhemCxVyqVcgKY4UxA tsfPBgMOhGoVGbiuZSp1oqNRmExRQJlhZ2dH3hd7DXsI5XtbNkXzCPYpvvBvkfCIlVANJygxHF9j tVLn5ZtQq7UjUwqOHz1Mt2/epFu37tHZJxt8P2zw+WwU2D5Uakt0+/pt+s7v/Ps0v7pG//N/97/Q 5maH9i3tE+JxLEEEuvg6dPP2XVpZO0xHjh0VkeR+fygZN1wLyr7oEK0YkjEiWThXBHElBvroWi2X i7KP1+/do0qxJJkuAScoMWP2ID+/5SOH6eLFi9Ta3aLr165IVy3G6dQbDZ2qwJ4uqBTo7u4mnW7M 0IF6kwL2az/9m5/Qq3/6p8JvBEgc8HPyTLYIexalEoh82z1jwXUaCEYSkAR85otGTLSOLFynTQ8f PpQZrcV6ndYef4xOnz4j5xxEdz4AJmuaNyBD+V1JpyDZCp/NDsTJ+LnMD422WDTVOIUvCUBMcCA2 OadAToIeV0XRtRITayOO1lklq2Z7g5JADsBEYkM9YxI0sOPyjKaVVF0w+Jz/h4xqGGrJVKdFhYK5 XC+1ncIx5YhwONJMRVIGyzjUbCZx2rZ/mR6j4+WU/iE/i40z1rtQ+2YrFJm/7TMXFrFgPs/wf2PJ kgRBn/dql/fYiG7de0DvvvMx+4UJPXPxZXrq4iUqN2pyjr3A+ldt3hCwaTJb0oVqrllhnc08Osnf OIe2oz0t9xl7ISUeHcUVkvo/O2VLeFYGzOmkAqP16WgVypZDRQYLeyw0n4n/5MA4DAc0QYPNMKYe B85ePlBdNw6aNod5mj32HDVmjlCFAVmBNmmlGdO+2gq5YZ9/d5fPLTKT0Pks8Zm/D6PG+35A/cF9 XtchjUBD6u7Sjz7eoOHHd+j0/gr9zn/7d+gb/9Hf4720QJ++9kf053/4j2kSNunpI2eoOr9Au2zn Qn8gATICtd3OA6oVSknmTZ9zZBdfSo9BpqM2S0dIz2zGN1L6q/o7tqvDSSpWZPdXGGnI7yofVDPa psqHqzCVQowOlb8Np80xqgOxoY7ZjNreCpj9suSftIo47aeBcXJZPR/7giS1SrqBXCvYYEqr2CA5 12QsIGsBR8kPd40j6SMHV4X3BDkNJ18kDFeAhq9vpwTEynOC8RN1Y8h3RBpd6MxJFbtVUMeRGT8q OHBk4ApxPjViIZmuReOcnSiz+eMEnGRT6kT0pUNOThqIJfevhCcl6KPn38U8No86A4c2dwPqdKHa HEmkklV8t9oycLx1jA5DKY3fv1RyE0CJEwdn+vTTT9PK/lVxIpB6OH36rLzX59evybOAE0aHzRBc AZRk2LgdP36YVlZW6IsvvqDBxoYCAH6dcErcSMrPO3x9u62mdARFkHUxw9ItxyLLB5wCrERfMoqP ylzar8jMWg/dyEQfrmr0xY7hkaCMpFzJINaZiOWKI0BYKItGsBdyMoEpPWIGSpGNf5Od14HlZTpy ZI1mFuep0ayyg9duzFHPp42tHbp28xZduXGdtvotCvo9cgrQ8CnI/YoAqFOgAF2buUz7WUJQtoZ0 b9eeS1m+i90/ocBS5Ya6rlIMwA9zErK2qJXpPhLR6onIjCCCCoxjAnCxpVYlcuu/EV2VCkXpmJxM /ESEEqKyOWR6J448I1H7FjHcWP4tEiH8TIRfhXm0Uqr3BNSgTLq1tSXvVSoFOk5Lshe+OFvsLbwG 4K9eq8r3bOen1ZtLO7hyHECMxbpDgBafh3vbz3sX5r611RZB3RGvQZX3MQjJH16+TCsHT9P5iy/S v/jhz+lvf/Ehf7/G9oCfkz+kah7X3aVrVz6kHIOug0eOUrU+I12zAoKgvYZIcKJyOwoo+LEjIOD7 xJidiggU5zU4RFTuIbtWlTXNg9LAN9Pp7fLha7JjfYGW983Tz//2VdpYv00zlRIVGUyNZfyOIxl7 dMhV6zV64okn6OjaIXrn/ffoZz/+S95bXQm4CsJFnMhrLfnZMx5BO1Ztt2FaAtTuQH624HkxsAEB vlEr0/bWQ9rd3WUn2KRCtULnn7vA17fKDhV9dxW+Jw1YpEIiYuMm6zTFbyPJCthB2La7U2fuOtag mUyzk9o010tKvXh+fqyUEzI0D8d2hWIPRJqt9lzr2EwGCO8bKMcMQuYY6h1OaMqehNKc5XGwyYGk F8r1imZWX3W4oCc5GA94HUtyH1hXXBcAtu2gf6S9jikTUtKUvbI/yQadcZjy8WwQl3aKu+KIbabx S0DOPHOUxyQ5CduFZrRBV6oEyI5/8cU1+pufvU1OcZG+9d3/gI6eOCtVAAQYHgfufKNiPbKlTmtr JM+Cjnz8LPaUS7unXTYyzStky+IGjNrMnfaMGEqL9WOuYyvtcm/QsYtNsiYyPkiGuYOfF2KBsVa+ +benWSyh4+DvKp8r3ruDXRrxtZWXTtFy+SgVOMB2J7s0F96luXqRZssceEXbwlNrt7vaFcpB9c5k h/KTKg1bLbY3G9QbRpIEuH/7Ab310/dpcyegw/sj+sZ//D36xn/4X/H5qdLV1/+YXvvzP6A2753j J5+VSsjDhxsSACMxNAKNhG8jL+dqaFc6OYvaeKHgR/nWmSrTFLc73TO2UieqB7IHTNkY2a8Q65fV l1UJMXmenk2GWNqOjmoUzU+s2UTPbtIxbT5PXovoYE/WL5H2sdccm4ka5szvpTRoP4LhyOAbfpBV tTe/GGm2RflB0XS6MTbDvjE2iyPnIwf2U503fDjGCJKyDIFGGh0dJNB1kkgTM8X4EAPkQdySvKo+ QEfbd63aPHhSSKlj7BPIxtAby8fapeUaPkWiXCwyDqTdgY4yq2KazjA9KstkDzRl79dJEbf8Ny9g yJHkgE/xNoO4nR5KbKpTh/SoDIxGaj1Q0VYYfOhBwdkhmxBJJFwQTpPlkq2urlKz2aTPr17n/z4k 4A1jRebmFmi+tUsPHtwXcGdLJmtra3Ti2HE6e/asOOdPP7ksn6Vq1IZYnYulnOE6Rbq5vkXNmYOU q89R0NmUA66GXZ+VRIORknrjqc2fArlUU4+SDWsshDEkqYG1o1wcSgEzNnqJne7c3Bzd3+aodRhp dWSM0gLvOQjNogmk15brhuFAdrZeb9AiG4Wl+To1Fuao4VWoni9RAcR+DgryzUUK2em3z52l9e1t +sVHH9A7n16h29u75FYa7OhVEkKNs0s5m3EzjlBN+q/+0sM7TQbPDpGOEmuZdqdK0SXUNvZIBhj7 xqkH5v088zuRENohFIkvybZGEL4cyNnQsxgLIJPm+UKevGKBjeKu/FxKkCg7c4Svry8IGFPOW2C+ V5Vrwv7RFvWeBAkQDMaeBBCzQAPft2uN90HWFDxN/DdePzMzI2uP95EuV16DYi4vZ7dSLdDC4pyM GdvdbknJEpkiTClxi1X6zm//gK7cfED/5z/5ZwzuGnyNVQHzjbk6jfttunvrplAQTp58hkH6goCB 4dhP6AdOqNpMEVCJAcVWCgfc0VK5QDPNWeq2O3JfkDXCz6WEx6C4BXFx/pUnn32Ozj31NO3stOju 7Rv8TB1ToibRnqu6Jdrh+y25BfrGSy/T09++RHdu3qBX/82fUbDdpiUOIkRnaqzj51QDMZZpDWEm ck6kWdwUgOC/8bslKafyeeC1bDJQvMvvf/f+Ogc2Eb3y0ot0/vnntZOupNQHx4ukmUr2lmTDPZMZ SmefJl8QzDXlIvuzxIbDiXv+FNBJg7hIxJ9VvzIwnfskAYiFEaJIPxzIPrO2PjkHplwlLNZYGzqQ ZZVsJEaUmS7cYiEnIAFjqYD74AcQPACssUVXPUvj4JS7pvbGBjPZLwviyEl5W9M0ECepDth1sZw3 x5agjRXQ97YPMi1P2/exHMS8pxlhwD2cL3QVO0Yp//rn1+itt9+ng6fP0+MXXqEDa6c4UOEzgiwY spB+JBpe0rHvahYwzbiYZwylB5EUcXR9HU2WRFktO2OX7N/G+KrdiRSA2rWRzGommUG2q9FWYeSD I9KGMfhNtkU5cNX7UioWrdewRGo5cyKkH+6sU8BAfDB7hsqrF6niFSne/ZTq9JAOLpSpVnR5rdu0 2b3LARYaEdFVP+TbGFE07HIwtUXtrW3hc7tOhd5/d53efO09/uwO/ebXnqRnf+slWnn8Sbp5/TLd fu91+uAXb9IoyNPC/mNUY9swAT9+NFG9Tfh28MZkIkJs6FLTVCgnk91yEp3HNEGTBXHZoCtKEjpG RghSYXGcAjjZMfb8aKOSTRY5URrEyGukwS9MOPmOybra/Sp9PdLJOp0JnJpAhL/NpCHdtdMJFpu5 zqV8IH2Ra1LWaUYq1fx3pGilKUHRUQJKdTVyapTrtDw7L2OVgpGWH/oQEQ3GAuICEXKcyIihSL4X yKaWWEiI26p/oiAuUOFYiI1KeWgk2blA0pCxlKFsuTTOkFTjZPrztCbYryqd7v3+VJrevg7ZCT5k PWS5ej61h2NZxoKn0yAwL1Szhr6UUA8ePEgHD6wx2NqRMtY2Aw0I3JbZYfbZodrZEG+/845slt/4 tVUxgO+++668Pl9UXSW8H+5hbe0wnTv7GJ0/f15KSB9++KGUvzwTUTiW6I9hugx2MK2hy1HQdndC K+xk40Fbuhtz5v7IRB82CLEGL0vwzT4bdRgRpSOltG092/0mncuUiXDQ+szGpVzKMxBoUim/SZ02 A4M+OHyBOGg4ESjwF5EE8FUct1op0cz8vEjUwMhLK3U4onGXr993ZSg70vUguy+XyrSyepD2z8/R aX5Gf/HLt+ijGwwMojHleC/GmJQRajcsmaumDLDXXT7dAZeCOzcx4lJOJJ1hiddgXyJLhnKq8CIw NinSWXnCQfIc6RaF0n/gqqCpzdI4rmYohsNAX8fgq9MZknUqclYwPL1YlPE9AE71ajnJRiGDAaNT KheF/9HttrWpQUa/aCkLGR7sw9nmjOwTIc+K8KX+ftgN5OfaaU3SbITsHTI6yCAnOpCgRAx7vL/L MuoGJVhphOD9jt9HAHHgwCpdu36PDXZMCwtFMUy31zv07KVv0sKBA/QP/7d/TFsPNmnf8qqU7DC/ NGKngUBkiwHS2omzNDu/JIY5iDLRqi33xCQDpYueNkaBa4igBdc2OzdDlXqFNu7dldKE2AeUaTl4 RBakOxjTmTNn6PkXv0Yl3jcbG7eox8+rhmkVvJrYexgeTQMt63/lmy/TxVe+Rg872/Rn//bf0Nbd u7Q8vyANFJJZxfmJlSAv0W9RgUqOUukZa80tYVqBlCNB7rCv9JI6P+trVz+n9fsP6PSZc/Td3/4+ HTq8n7bu36eFhgafyNohE4fsomHuJGVVndKQlnuEjWllImz7oURtZKgZTuKsZP8GfqKDJY0vgdpf abIJwqSyILxe7B3IFhGJLZbSaKxzKHXAdyzBq9psPzlHVt5B1lNeO0KFmAr5Cv+sTw82O2LTQbWp MLAdhrqvAeBFpsOo71uglgKZlBKRdcRpaZW+9D07O3Q6Y2dfE5kgK06esWtSfaoaGfIZHMh4wxFG QwV9AeP3N3Y4kL5ON26u0+knX6ZnXnyZZlcPyD1J8I9K0xiUmhnlcopzsmVM5aKqDAWWkM+eq5k1 O2komgKvxslnrz3KdOOadbDl+4TXFdtO+XDqnUR8OUrFxKHNqUBQM685BO7RUAE1gAeaF3KzlF89 S/nGIQb1XarHV2m51mYbU6RSXKCt9k3e320ORnVij+OMZWrD7lafgoFDW511qs2VaHNjQm/9/BP6 8P0vKC6F9J3vX6ILv36JqnP7aXvrNr3z5/8PtTb6RNUZcip5qrsL0qEesl2SJjlMAJpoVheZRMxJ 9WI3XXsbVBnhbnwvn0nO7N0D6T6IE6pX8vNYO8wVZNm9ZeVurKfgzzATXeTjDdfOSPzJe4i3t5lR Pb0pKJPX7KmG7akKOo6XSSl8+frlLCcoPSPma7MPCuJcMUTayW3SsJFyn0LHNYcAM8IK1CiWOQrx EG4xkp7IjYzFwJrUH+lmgfSBcDNjJWIjIg18P+nczE6RwJ8BL2IykN7wG+yoIxh1s376wIyuTpYz kf3vvX+yi2sfUGQOsoA0GBbeqB2OBFoDX4Ybi5aW6ZazWlu2ixNR5qFDhxh0PUvr6xv0ySef0N27 t2l792GSPXu4+YA22IgfPXpcjKl1ijpIXl+Djj+bjRuhs4ef6112LDdv3tbPmmgziab6Y0n3R65K W+RLRSk5zi80hROFxpHYRJeO2pMEyGS5fNlnkrSyJ7NnwwTI4b7NblQ5EZPe0jVWHgfGLxUxG3fs CSG8WJqjeqMpZHXM81Ty/Ig8BnqYCIDsEjJDswzgcvU6+RDBpCKNcoF2UKK0h/XmwADaUjGD6VKu QPN82L/2+OP8GbPUeO01euOzz9jwtsirzsvEB+ngj210RiajrKUMLbun5ZfsIU4Ir5SWdZQ+YAyi SILkk/VPDlQygFtfK5mYUklKTlgHHyVUU1oXSQ4ovRc8wwHTUhMyk+hSnTBw6lgHl3MToCAk8gJ4 RRXRF4xyOlYukvK2IwGRiPs6Og4mFAHuopQZNaugThog0TW0COxBSwUoV4pyPQBtCHRtmTBvdeoM KEA2eUI3+J4gNlzgPb7NgGmBnnj2RXr9nQ/pRz/5Jc3wWpZc5ZXyjqXddos2N7cYhC3S0v41oST0 +uNkXBpALgk5WUUxxdjZ8perHFtkZJtzC5JFAi8JmluYTFHk70MAuzUY0aGjJ+mrL32D5hcX2AYF YkP6vaFkgkuVKhV4D7TZQTvjAj1/4Tn6yve+SR2GgX/1x39C9y9foyqDYJTMwQyHvhu+RM7I1fLV 2MixaL+BKT3zXkZkrPbGGHQZ+xdTe3eTmlWPagzK37x1S+zf977/Azr31DM0wPBzhoMeA9YcVag3 0o4912sooZ9sdthLiP32KzSTMoQnFSW5cLIi074hettzLrp+5jWSYR3rvwVsGbvrxHYOZSATO2Sf mhGC2De4NmSlAIgBzsHvg/AzBJTxM2SpAPzx70F3IBmYKj/z5sw87bY2+NM60pyEFisbLet5cizn /Mv22jq5jIPLfum/U4dtv7IVFstx0/cLMxk7J9HfULsYJdzQHBQUOJgZDVvCZb1+4w698fYnHNzM 0svf/D6deuoiFXhNMfIQx9A3vk2yWFBUyJdSn2qynSTdjK7JiuXle1HmmqPsvSVzd8Pk+rJ/PHs/ mZK7rU7B4MWO2idX+HJhokNqp6vwjqDYz4sfRXCTA/WFgfaIARLSFbncEuVWn6Coso8K4w41wru0 WOMgeh5ctCEHjR3q9kz5lLThZNTtUb+7S0F/yACsR0Ve+0+v3KDXfvox3biyS0eOlxnAfYfOP/db tNG9STc++SuKHt6joIUBAGUGbi2qlFfIrczL7/Y7XbJjr6RpyAQmsJGxZ5+j2QepNU72yt6v7J5Q 8Jatzlm/F2em3WXwwZ5PyY6oI8ey8rWDVdbBojJX7USsmj7mVTYjmy2fWmCpmMaduo8v34sElFY+ Yu/NWV6FFjFc5amA6ApkjI1lFImjsXYMNao1qiHCjzVTh8HwMpoLHCHzGQ60egDaTOMRyMfoUEMG Dl0bkTHgYjSCtAyACBolp1lnVm5MBxI4+kdeY2bnZQ53Frzt/coeAjlgsXLookcsuo808jBH7b4r zsDLqXPUzid9vai180OAg7x27Rq9v/w+vfzyt2hhfpFmGrO0kVsX8UD4JM9kWJBtqTG4KQmnLZIy F7hy3X5Hsh5WePTevXsC9hDxAhTCCQIY4CrhwMNEx8iTzpvQHYqB7PYHtNvxaY3fd9QD2XQi12u5 MTI82s51oXQjfon7NpV+toYkwzEkU9bH7xsyPrJovjSEhNI9deTQfmourvHzWJUsVcHsrSE7L4B8 z7HdN7E0MVgHIu8PyQzeWyWAoEh6ZGVvgkgajDoElWWXHeqJ5SX6wTdf5udaoJ+995GCkUZFGgT0 MKZRanKvKsikqNZJ9012D2iZSiMiq4CezMaLNdshh9cIxlrgBt6WD26EkFe1uzhwnFRQFg0G4wGD W+W1IZtUxtD5nJZCQ3SFGn4bAJWlygj4RSaW1x77BXpnVp8M14R9BEeN+8fvYX/ZjBxeX69XZS/i 81H6R5a41WrJNeHnmq0JhC+Nf49HKkWC0vjMTH0quMJ7w4nvdnbYyR+kze0RvfjNb1J9foH+1T/4 v2m73aHDS4sa+fsQ7XVpi89ywGD11PEzbC/qQrcQ7UTSWas5CYzMGgG4ORzQiPROPsk61xggLK8c FK5tp7Ut3Bt0XEK2YMRgY9/+Q/TC178lI45G4z6V80UzumaoDVMTEpkCZPX3nz5Jl779DXESv/jx z+jyu+/RXK1OcQWVhKE4CttkJEF1XsEQZEawVpFxohoA55PgR4W7jZGH5+Fg6MjaQeEO3r11m06c fowuvvg1KUe2Wg9pscTnv6xSOkMj8GnnsFqFAMu7jBL7BY7kUA0iAmXlSUsGRjmSvlRA8F4Anfa6 sDd0GoTKM2D/wSaBm4nMLrK5vU5H/rsxP0PtVpefX0DLi8sSaCGIwgzJffv2Ce1le6vNe5fXZGk/ A3Rk3UfshBu0uLBCd3q3hAs3z6AYM2HbnS15Lni/QMaKpTbZBgsRpVm45DxaWx9PZ6Vs+VrtFCUS TUl2Cn7BdN2S1e5LzrnR4YotT1bfE12FkZmtGQQd+bu106UP3v+Yrly7QwePnJMJDAfXjlMPo9nw e+AmAmwzaIsdbVhypYxVNnxFmy0y2XknLePpf2QEyrO83Ez5O9lLsQpOU/a1Zlaz2Ef7XhmZXykL Rub1MqVIf88zZVnx8gJAR1IlC3NNvvQ5Kq+eUx/Vv08L+Q6tLOalSjBg4Ob3dqg7wrjHgjRGTEa7 4utRdenzHsrnetTla/j03c/ob39yjYGdS0dON+jXfusleuXlX6f7D7bJuX6Z+je+4FvypFrlFflw DtmuFGfIO1KiIfsu0cE064nxjK6M91Qdy0ij8Ef6eXUg3jS+8abnZLum6pL+vqNBvqf0oGgPcNob RNkypWm5yayn9hNEpus10aGb6oTOUsKmQZz9sh5a/dWjq4dpJo5MpGl+0Y598gOjXGw2gRuaTA26 82TUk3Y/zc3PCpBDFsAzgpwTfyJ/B4Fm2RwACSNmGku3DiLtSXIIyS6USGdMpGTLVygda3Akkd2Y cc7Uph2TMbGL5Mpmz5JiH5Vp2/uQkkOdeTCxq5oxfjii/sijbteX5owCGmRldqMocopzlmdnmg8g H/Dxxx/ToUNHBcCtr6/T/fsPzBDukTgTlakw5YooEseqzlcJ7OCRwagCuC6zITx+/LiIF27tbOvQ csyZZOcv3U8FTzS0nCgnoBkk9cG4K/PXev0RFZslBRhhBrzCsIcKasJH8CDtgZHnZIjRNJXUjRIg 58k8y5x2psbazSYcN0/LBxAwrM/so7X9K1RrzMnEhgmyQVCvrhSoCUmRol4jAN1YO1YU5AyGws2Y xbB1EMoZ4HX43jCKyefPqbgydEWEIlFO2zczQ5fOP0273SF9cP0+g9eeEGX3bnqyjTqZL7EFe4Cc LSvt3TMKOJ2ELJzsGWRoAErHoA+oRA7iKESp1tGDd2bfQ6JL/vVauSJrL/w2XteKDKfXTu1c0plp Imo35agpF6wsewJO2V6z5RNJmZWfW7VWZsPaE7CG7AgcZ6fTT167sLBgVMpHCUiz2cFCpWSGQo/S EhkI6IUSO/2ylELdQsB7s01HDz9GF776PP2yWuB0AAAgAElEQVT01bfpr3/yS/7cmiiiY8wexIDH /B4721u0MNOk1aV9NOE90BviZwXhvzrJ9bviKMYclACs50N+buwc+8jYMvA/sLJIB/avSZbw7r2b EvTgfE2GMR09fpaef+lbdPTMGdkHjpSbCiILgvcuFasSgA3bfT5by/TMyy9S4+A8XXn7Y/rkx6+T A/kQXqOQgS6jPwkSsCUhwzIxMkjgecVYE9OoYisI2h+Q6q7BUUKeBV2xsM4H+Axc/uwTyaj/J//l D2iZwSayVsjQggKAkhGyr7sAppHhLfm2tByo08K+CuJkHfp+W842vodSXxzoyDOsF/ZUkW0yrgmc W9gnyZaN+jLhAoBs//wh8ncDyfYD1C/tW5Z9uMu/0+TXzjKI29luCQm7Uq7xnwpthg9kD2JNRN5B +NmYG1rlvzsiUuxIJ6fydSGnJHMgzR6zXayoIogNlWepFRjRXIwMXzRrl5LshbHre+y7zTbqa1Mb ZvUks2dUgIwTGQV+rRip83QkASEj6dBwhcay8Tbdu71B7779GQfzHr3wwq/RExe+ygHivNBsnEIk TXoFEcEr0Qhj4HMlkcEIJz1+PjkVJ48sV9KRZxOb6lTOSQWEE+BlAZvYHyf9WWxK36bUq/7SoaRh C5qacWgyeWYCjJdL6DaRyTK6ccrJQzONl4u1aZF6bEcH/M4NPvfHqLb4NPXy7CM6n9NqhUF9DU/S xygXmrA9GQwdAehR0OLzws+qM5RKVBB2CdnW7e02/ejNz+mzd+7CjdPFr5yml/+9b9GxE8fp2o33 6M6tN2kxmqWj547S1TvXqM3PsRQsCoha4+CvGldpwO+FszvCtBn+O89+EFQSjNTzMtzFR2WpsvtG no/rJPqDKWB2MvvDAGtHOZQ2UJef2a7sTLlTv/YKLmezeST0MVdkSUzTTDz92mxDqb7ddCLFeimb icsmoOw9JrNTcewKjnLNpITiaobJ40i4zwccRhKIe4JFZCdT5EM3g4i/4lHRr9NcdZbKAOS8EO1J IC38bp4PwziQDhLArkCkE1ROolxh4x4OpfwDndBooh2KYzbqoqfCRkPmoPGDGIzHoiiPIR8Qr8C8 wgJH1wqjJqaNXEdsTT3gPWKt2cW1D8LS1CNzEEBmhANBaQJRZtuvUgvcPujjMZiI+XDnkKLOccQc RGb0izpogBcAs3Znlz7//Ap95zvfo8NHD9PNO19IiQ9cJhUxnsiBW5xrcrRSkpEgq6sH6MrnV2nY VaI/rgzP/MCBw2JY290WrW/cEYVpycwgMyQNAq4IHsampdnjiAZTMEDIRamplz9E+dqAxpu3GIBz 5Jkv01ja/Em4GxakEKXlCDINENL9arp9YFRtqcgSuLFJA+hoxJqpkAxlgO8XqFadEwPV4/2xMLtE DX59FZwmZFo9NbhNBqs6Q5FE0Rwin+1uhzrDvnx+oVQUx9TztYO1mCtIB2qYByl3RCNkenk/MsSj ks/mpePT4dIc/eD5SzQZ/AW9zc+9UF2gHEfDvcFEI8pYOT8FXmdcq5sZqZNmdq2DUMPngc9lylLI FGFLoewZy0SRogguxpHOtI0YqDsMcCLRBSxKSU5mAvtjaXiZjPk5MLDxoBaOgc8M2tBMILIxfD6g EYiGgnK1TJubD0wGSK9RSPu8BjP1mjQ94Fkh6pasbq0i4HjMz863zUpQcByGmrWrlCQY6jJoKBUr Qn/AMGWUTtOZgk6SjUP2buSiW5ZBSzVPQR/NNy3JzqAsOx73edGg94exX31It9GFx09QpdagP/63 v6Q+n53TmO+KrIan0052b69Tjtdp8cgajdGUgQY4Ly/7BuVhoWgIXxKNQua84j3csYwFcye+7OsT TzxNZQaC9+7dofWbG7wORSqU99FzX3uezl28QPlGmVp8Tvx4xOtcYfsR0fzSfqpWZmhzfYfqlbrM Yn38Ky/QscdO0Na9TfrFqz9lO9el2UZVAgIZjzf0ZQ+SZH4nsleQCcF66kQKEmEIrA/AVx7juVy1 AbL+ILfHPQbQD6mSjyWb/Pp7b9PCwVU6f+krNGBb+WCrT5Uq24PJQ94TM+QWN+nO/S90SHcnL93p ANQDfn8JcCfa1Y91Lper7Gw50OZ9tbm5Kxw6dK9DtqnF9gLdtvv2rQoHcTB4SHPNKi3ML7MTxPvw Wi7NU6PSoPZOVwLqAu8LALLxBCCeAVmpKqLikzH0qIpUAf+S90ynN5L3djj4Gna3acRnKldlIO6i OWUgALLGz3HMz6nncyBVmqVStUFDfr7g1pULDO5dnbs9CWPpSAc/MXD5ubkcuEQ6zsmeRaGPxKYk bIRR4ZwlSxKqDBaqEmLHIx15l5xhqLT4KsuBMXjYR2LtghIsLDv2oQTqmHErkkHDMd8z5k93aHfj Jl2/vk0ff36T3PoyXfr+b9PJJ56TZ9VBowr2Zsz7hO0vh0RJ1tP1XZk2FIYlyQQJLQczYlHylik0 I6WkYC+5gSHBBwZgaTJDZIxcpRtJtjE2vFtbUQgtcDOTKBzN1NggQjX+2M77XRqBEsO+qmYoIS3Q ndgji/6o0FTAHWrTMIa/WKHqyotUXzjKgHuHFsdfULMW03yVn5YXsG/r8JqyLeh3hGvt8iEeRTvU 5j0x7LFfmjgyveL23U36+eu3af3WfaqzTblw6SI9dv4IleYm9HDrFzR8sEkrhSY96O3QUVqig8U5 +mL9GvXL7C8OPUnx3CzbH0w+kgiF91/BgOFYpqY4UIzgZ53nAM0OD7Jz1F1DzZCRma5J9hjfZrvZ PUyOwv5Dhhq+1NFMumCsIE7QmmtmWwNv2MApy9eMwpRTTpmMns0Qe1HR+FGVp7FBeJysUWhkfJRr Cq6tbYqEDQBnEsAc+9tyUhFAS6c3QD4aG7K6Rns7N4SjRSSpc0tWQPQGcANniA+SuewFdsj1hjwq RMXagcuLiUUOzEBp4VuoQ5SOCnF0yMqkXDjLtdMDGCcdRABntiSUM1pcMpQaJGPPot+syrTJxpkB x49Cr9m/sz+Th4lrNdEinK5Mu8DPPSeJaOSA5NQB2eeGzit8YZHgYNAWferUKZnIcOXKQKJNODM8 hxJHFHDeyMzIJuFnOddcMNMRIlkkgA7ox8E47+7ek2g6u14SUThpdkSuX9vT9DrQPMAGPidSBSr+ qpvPTVC9jVqz2ackChAtkOSfU80P9vml/I04KUd4lK7DXL1MR9lpzZbZAQxGmiUqKxirVgqS/Z34 2iiDZBMAQrVQ0fVFNIzsFoNoSU1HCroxfDyAthfUz8cTSPmJgwUAKpbrtNps0IUzZ2mzt0vrXfDu wCFzDNFbSxOBlJdzcslx5rpVLslmp6e5NXLvkR1LZ+8fDqMg9wWjiIwqgItIfxTy8qzBN0NUj+5S ZEpE2oPXHhmdgRGIrVR1P6AR5sGDBwrk2Emj2SUqKBBDFgOvJ6rL3qjFNep3tTRfzAhL47kBkOL9 2ju7cv24Lrwnrgt7DL+D7B2eJ6RBcLaQqcPnwEFHxiFIaZg/F5MnEGRNOOIG8AOhuMDBxkJzlp8l f9bsDJ04dYbeeP8TevfDj6iCe5dSHQOpXD7pgC2WKsKXkiEdESUGUeR5yGSY0i3HwJ3PFZ+FrsgR ER04coROnTkppfp767cYNM7S+afYQZx+nBaWVykuFhT0IwvGIDoAo55Xtlav0MWvfoV+dHed1u/f p5d//Xv05DNPilzLG6+/Svfu3qJyMS8BFEjZgRl6jfvXMxmS56b7QKP8UONE83wlwAl1rUQmF01X EwZf7Cj2rcxRv92iTqtNT7/wIs3NzEoWzhGhYTiAPvU32Ymx4b766XXqPYypOqvlxkl7RA83N/m5 l2hhbh4nW0pWEwanp1ZP0cboIYM8nwFakxqz8yJ/hDVBKVoqAAwcIO6NTJuWU5Vji3XAmcJ+xHNH 45RMzYFGXUEbWEb9kdx7uVKVPd5B6T+OpdQvlRp+LaZ74HMsgMDezOeLJuuvWVuZZjEx0iY2Uxz4 SfZD+U5pdlxsj+skeyLOlJJcwycTh2uHk2dslxVhxRcUHoCXtMHJ1VFmHITH+R6F3i75feWKerwh ZXSW35Z9+sX1u3T92m26tV2giy/+Ll148RVqMCAeB476Hcb2Pu4hGkp2JYwKMjVHxYZ9zVixbShK RQfzfIcmKaJwYiwCxnCdOsrNEwHkwNjQUBqjRqNAdBdDsjYqSsvHoWYqBaNYbh9GUFnSrhH0HfBn 5N0Kf2NIg7At4KWYZxCNSSP+FhXAo3SGtNPn95i/SIsnL9EQagytT2l/Ht3sDs3VGIiM29Qb9sUP DycKHLu9Nt//Lg22kLHmtfKv0U53hz693Ka/+dtPaYtt79lDeVo+0KTFRb5ef5M6dzGqK6SqVxFg VAhaNO50eaHKjG2XeI8eoiNza3wWG7Q96ojtgCwVsrZ2BKTkMnMFo9WmQtVWEixrq5GYmZ4Na7qA 4zQrioBa6FnokjbYzct7qR+M05nxsP3yd6jVLHyccJIBJj0t+TpmKonqf+r0ESGCWGqcofTYcZTF nKopiPg2+bL8qLoJWMtXRAkgO/rS2ktUbELTVJHLCkEKQvXSzjxVqXcyo5fQUccfypscF40/kGkp ldm4NGYlK4DyK0bHQEgOY4IKkX6oiPjiQLOhKJRKUk5EVAaisU5qiFUjLtLB7gAgohwdqSaZkmkD EZGUTqowNfVpmXC6w3LqZ3tA3KO6VRKeU6SStY5wF0rSzCAcLaOOrRm7vE5RCPx0wSAwy8YMBHVw 2W7fvk1rh4/RyROn6c6dO5LJQAZoPJqIYCqybzJ2hhcKA7ohJbJ+X4cElxmMIOsBXh2uC85chVC9 BLDJVIcopAzuSo2cWT/wzhocYcjUBTdIumN1zQOydXxbPt1bWrVf9t9JG7WJKmQofea1wrNx89q1 x4d9pVmn5ZkG5WKjBg+pGMzmLMCoj4V7hbWEgR8iekUruUSGgWS6MHwdjm0cj0VHzZOIDBueVBJH RktBPDaU9/CkhFWjZ44cpvX1u7Rz+aoEC3AqIHm7UlpmoIMsJCK6KMMJpDApr6eGkxKwOw36STuE 4RRHfeX2RDk5dHUQvt0y9bpdCTKwTtKsgIyOo+Vo3DtEfEE1GA76ouKtGbNq0tWHTmWU1gHUJHPZ bIrcCIAeAFqtUZdSLTJwQxMIVBkM4tDY84JSKQwvuuyKRV0r6M9ZeZEeNPYcbaaBODKmrIyNo8Z+ rpYrZig5SjwFyULh/Sp8j7j2BTShFOt05uw5WlxZpd//V39ND7a2aWVhRoQ2ZZ+I+HdPjP++5UUB dwASIUqxji1Pf3n8nzz3UINFdGsW+X4LtSqtP9igzlA17n7nd35Xsk/Y3y22SxMOWjCsPh8bmkE+ kvmKuCdcY//rLbr8yad0+tw5mluo0/vvvEcfv/+eZP+9UlHAtvKOlGMVhjZAigX0T/NnSDK04DMW +XlAmFg0udzYjNpjJ9re4n08oHp5Hz18cE/A3ca9dfqzP/0hPfnsV4RKsW/xIE06N+iD239NQ79K ox2Heu0h79FtOnHiBD3YfCjXL/ZgcYm2GNCBCF+q1CmXx+fieiEP0xRBdEy5QWc2GomQKQBIw/6p 1RpiZ/Hs4SgA4nxeE8yKxb9L1QoHWhMJRrG3wK3d2WkrD7GmY9i0g1lBK44O/q2j3qoi2i62iwG/ 2DXhOscSoBT4urqBqhRAngXk/lDEfE2WP2f4aLCzYQrm9gbaVj1BQBxpxipLCUr2D2mpLC/lxgnv gYlOYYh1DCQFKqyeiwZ8z30aD3dpZ/c+bXLQc3tjQK1+nRYOf5N+7z+9RIvLK9L13BpBoNVJsjlS enXaUrkKJ9gsOtBeZ3UqDWUQTVQCCLxNdOdKoOWLUysyUMYzAxDzo4mU/l0nlCydiKJD8iOX3l8y eQA2P7Svs8/K8P9wdZZ/xb9XYWA4DruULyGgrDAQQ7azT1WwBvhMDaTaxUHgga9Q6eg3ZO1n21dp td6TiSV1TAaaMIBr70gA1x8OaIeDEbBCJpjK0h1ThMkyGIHHe/2Nj2/Qa2+u89rn6dTJgzRfj2jt 0AodWK5So8Q2l+0HhL6R4XfdAR0+vo/qy09TWKjT5ltv0cLMCjWWa9SetDV7CRWAkBIA45mMFrAD KnCubUrw0mEC8ie0ma5UV0/8lXpIU3nRUZiSDJF9ZPYQMFBMBm8UpnyiilGnPNis30t54laY3Ul+ Ju/laHZU9TddsXkA6+ACI4guIrFlxm7JlBf2z9IUhyycP0oAvIwh9JRKhnOWS64iI8Fgsyga4bBz AFpEuYxMTRcoMafSCYh0GvVZqs/UtKUZZSdk1kJTT5Z9pQ8zzwCwUCqLoCQOPwjWAHBWG87+AbES zkQIlpHNCsbpw4+VsimK5qYLTKOTyPC3yCycO+WI92aast8XdWxZTM0QCAEVvMBCja+hY/hqqjEl HbvotY3cqffAl6rks/HmCBblMNzn/v37aWlxn2TSoLKPyBQZNgzgBujFAsJA43s3btyg+/fva4Rb rkk0jLfe3to15HWzWlYKwnTMJTIwRrjVdvCgLBUXPUMITcFsoGymRxrABLiYLekYIL83k5l9huLk SD87z2FqHjNR2XBCFwtaU2CvoezYG+m65/Jl0fhChyHWduwDhCnYl5FFbKhkbBKfzFyofBCUlHK8 h/BMZM1DjI0p0CjQ2bZwnijdI1Kaa8zT0ydO0uX723SXDTPKZ0JyhUSFpM9D0y6uGj5yB1F6P05i GA1/wqbqXTehByZ7jFQQFZmy1u4OA9a6dOsVhDzvy/QSdJdKF2iRgRaDpaF0XGt7u+j7meBAiOO8 Jq1WW7TJSqVikgFFV2/ObdL27m4C0tDta7tKwSEEUCyWVDeus9viwzkrzjpvygEwACMZFacSJxDS 3ubXASDOzs4JQBN5C2RLUOIKIskWT8YjAZrIJkL2JRQw7kkWz2nup7NPPEm31nfob9/6VHgreTT6 8OcVCwr8wPOCuOzM/AIb25xoaAFQB5n5hQmFxfTow10WeJFQHpyd30dPPHOR7VCOvrh5Q55vjUFH mf+38WBb5qciIwuQX44YHLPD7SMLg1Fk/EyEN8efd/TUGVo9uCaTEq5cv0+ffPA+O/EhzdTq0iUt /WAi6BtLgEGmk1gcRkKY17IW/vaiOBFIjkxWCM++lHdFhmPQ2WGwifFrHfrs88/kmd+/dYd++C// iD5571O69O1n6OzXfoNGnQdiH7Ye8BVEDYq8AVXmyuI0dEauIyAMfgLyLGg4AWgbjgMJ7tBBCw4i 5IXQ/JTPFXnpF/jM9ASkAXTB/trmjkZjRqgArV5P7rk5Oy+gbffhjpyrGu8boG/sBfxcz5w2SOCa 0GyEjlUAQmRF8HOU13C2Afxh4/rDkYD/crGS0DA0YCgmZ8c6S8lCmRGATjxdlnJMV6LNhE/ZcaOq kOrfmUk6mmKnEmwCX/8k8kSuAu9TBL8dXEO2N93hA+oOugxGetT32d4uPkGPHVmj/Ox+6Z4ulHOS zW2xrQrGE9N4ExhbPuCgs8c/H8gUGUipyNg9JC5AE+A/lfqS2PYKg1zYQ7XPmuPH++ZDnSeOcipK oyj56sg2koA0oXWIj0RGw2igCmnO04wfmcYHsy8DQ/1QE8Y2A5L5fIYGTl201erUIWfAZ7LH91I/ RqVTF8hZOkpOd4MWOp/TcmNM882GAMTBYFPuFfcO2wCQAcH+HoP7fq9FEcR7qUdX+Ez+/I2b9NG1 LVpcatD/+N/8XSqxz3jrl6/S0dUFWinzGRw8ZHvvivTSkG3Q2TMn6IXv/x555cdlXwEU3rszoh2q UcCgvjCADw4kewnfHgY6iUZoPCHoKnnhBMq+8LRJQxMxknrVLBocuh1plnAM46S8Kpk6GU7PfgZb xk2nMMmXZ7pDAdJw9gHIItWWlRGJwrPT988lI/KQw9JJPQUjPJzLWxHttBybh2xKbDpMZYqJloJ1 Hrwr+ouWv6mXor5IeKMxmcSAkRhJHBIiTVXESrJxiQ6ZceQ4HAXMusMoJDbsKG2tHlykublZNmbs LBFJRTmZtiD1aMdVm8wXihSgRbIBGwCRK0Frux8ISALxeQRCrujXKFF+iHIrkQoGgz9RMPVo6ZCd Bh5ZxJzUrKM0Y/erQMp0xiUdnSF6bRAQBfJG1spkLePIdO8ijZpXMUEZUSQGSQ8eHDi6vHAAUMZA RiW8EktX1unTp+mpp86Lw+53B6YU6wvp+NKlS/Thhx/Rp59+yoaxIiUw3AN4LaGJvuw92BKU3JcF dVY/zmr/RUrYFCcTR8Y/Kuctb6KPvaAs+5WIZe6JiK1MRmSURx2TndqbScFnj3kNwX0qMHBzwNOC QeHvQWwVUiEC3AOriB2J6CQCApio8ciVmYrI3GppzDWcLxXJHPP7QhDaDSfspPIySQRrFbLBWWZg cvLAIXrIIK6P3y3qoXcdbRaYgMvjeUlb/vS+SL80mMkMvqaUbgCjDAcGbgUOItY65vfdZNAt5QLe H8gYwQD6MjdvpKUr49gA4IXQbcCYlSTBaC18lHQioyzS60iABM5ak/fEYKSlaWThrEQNQHGr1aGZ ZkPAArI3Wzs7krWDE4djJXciDToIkDC1AD9DxgTXh9/Jm1FgNjvnc9CBPQyQ0+GoXYe4V6jd1o7W cm2W5g8epeUDq/Sv//JNunV3S8qSCIuhpycgpNvnfd6lGq5jpiHzIoUDF4ZJt3B2bzmRIUjA8U/Q HT6hJ59/jL72yitS8mjvtjlI6lK/06YQs5V7mBFMkoGDyGjM9iTvqNwHypvdTl+mJkw4sJpA1xGK 8Tdv0zY/02FnIB2oaKDJO0VyGfT5kZLL7TWlWpoKMkJTyrJ7AWBWAlFt/KYCnh1fT7fVov6gRSuL Db64Mds7TLvIi7DwsDeg1/7yR9SYd+i3z1+gsseBXPMArd+JRJ8Pb9CY20+jia4NgADkUvBvNKlU GdAtLi1Tu7dN3X5PMrhoYNnc2tGsXXNWAPfDlgJ2AHSsJ4JBzazVpcOvC5kVT/UccaYgw4KbwD4L xf5OhIpR5kBAVAPAy5RgHBWKUDIixXJeAGAf/OdAy6fSMQ1NL37vIkpWRCJFA+4b5qSKowOX1Ddi tPjjWCkZlY7IdvpaOxUZzpgx6ImdnwZytruTz80Ekj1lsGZ5fVEa7/GZ60jDFQKfzqhAxeoRBm/L vD+PUK3JAL8BEN2nTu8+7908711+LToxdzf5+T2gHqbEsM1BoiEa5STLJlw1ZE9k1iW7bofPt1em XOkzDiibdObUWWrmaxqkQP4Ht4AO3WgsvC+MTso7akcjU77HSxHoaVd8pmnGBHxSHTMTcFR8WYEw mewxbNxOnKMFvveQAXWQ4zPo8ffbOzSIKhTve4wqx79N5XqVwu5tqo6u0dpykW3CnMyw9bsPaHvQ F2COLwgdj3mvITBBxjrmZ9Dr3Kc33rtO7330kHZaPs2WXXr+6TX6+ovnOJjgoGSLbQx/btQdSLPH mIp06wHvQd7HF84f4H0e0OjOX9MHP36X6GFAzcoqP+82ld08zVY48HSN3Jirnbdky5jQU80jwC+Y AfVRMv2A7PxgNNi4+Wn7YvaNFcfGXvQjW7J3yRRdpArn8p5OJiiAHpFTvrxnqgt2v4n0kVRCUs54 WmZVDpxVJLDgMeGYowF0NFCaQ3+SVC7GE8UWkqiItNqH3xFKWU4zdwjUJIjKOqas00qinVjLnjjQ ysci7c4K0KwQ0MGVBTpz7DDNsePoPdxW3puAR017I9JWQEdm1mCUzEjFmCVwhBDB4aKQIYA0Q2Bq 3GClTqBThDKUuQGnWlcyumTe/KRmTWQzI17G2E6PUMre26P+WxdFFxKLhlJlF5s5UDHVnCyWb7KC UdrRlIkas5ItLT4su9s7dGB1P82wYUDW4tjRo3ThwgVa3bdfwKs9bKo0X6DDhw8LeAMYgOPFF4yN jlAqSblOo/5AynmSgYqdBEzquqXNG/r+hkMHoOmqh1R8nXbm7F13e0++0YmTdHEcJeKZ4uhJR9ek NtXyDUId44My+GBMFQYd4Br3sba8L4Yg1rIhlTUKFMDij+isIYMBiQQG85IhC/JS9pSkp6PASeRD IGMCvpbwNh1x/OCZFDBbFKOihrtE1bJIXLxf9KgDSYViSQC4tPybZ6fAUVP00gWWARXTnUTGiEaR AXQkjkU66wx3zKtUpLOyUqhKiRSNCujWrrODnRFpD9XDg5EehTpJYZ6BJgA6mSYSaCIh6rUgDIK2 yDoNpSTaS6REcP2YWgCniecsAsFN5Vlh7A3AWYMd96xrg4lekuWzHa/DoWZVlhYWTcm1J3ssIeXy 56CsJhmDUpHKQVmvf+iLY0cndsCO6fjxk+z0cvTuJ9dpwkalWS9ItgVCuZAOCH0d1YX9HIsjdgVs R+ieLeh5tRmurFPG5w8ZeB05dpLOP3MBPk+addDNDA5Ro9ogvzeWjmZU4ACo0emJB4L3GvDea8xi 6kRVNOeckiM/gy2aWZqhFd5jP7t+OVlD3JN0ToYa9aaaauZ8RE7C37UZEpc9U9FTTqGdeIPJFiHb jc7DdQ40kJnyaN/yHM3Vz9NnH38umnUYp1Vno78yt0oBO8tevEXtEYMmdtr9CYO21Tl+Xku0c/eq ONEDh5alZLm1dUcCNwA6rKNkR/jZzs41VWtwPJBACHIweJY7DOqRiUBmDTzfDjthOL1yrSJ8ou5g oLNoy3oPtnu+xAAf4B7BQqlSk70DMA/bV2swOOH1bQ/bYqeL5ao8+5F5XvhdPKuRP5H3RpkeQdoY FAHRKyzLvsVIPJ04aaWPYsnOurEZh+WoYkLWP7lOlodLJrD1ptbJajsKtxgaIiED+4DPFV/vAACO jcmYZmlSOcDg7TCfsUUq1BbI5b3faj+g2zffJX/YVQ4jAzbYcEwMQC0KHGNcKoBsrlCjeKYm+oSV +gLVm4tUrc/zPTLILZZlNm63d5XuXlgnvc8AACAASURBVLlB6/c3aabapFoJWfiuZLPR6AIB6wjE dgSvRj4kioIkO4M1sJNcPMfKY6Q8aASFGgBq97LjZrulXSpOtgjiMgypqdmH0oJP7dJ+Khw7T7VD ZxlEcUC5eZnmci2aOzgnRPlRe8znqkUPBts06gdSiuzxsxj0dMQhZHLAudx4uElvf/g5vfXOLQlg 9i/NMmDzqcDP+Yd/8H9RWHKpWRhJaVOqLWzrv8CkEgb1B/YdpPV72/TY+z/k975O3W6Jzn7979Du +B5dffstDhpP0Q7fW8mtia0tSgOZ2ixkKktmBCBmDaPClIwnS/YJPzPoPGbGmCUqbkmyxzPzazWb Zofay+8bf+4m3cOxKZmy3y3kjK9PJ8zAJ6DpyAbiai9I6EMWxIneqwnMrf4fElfwecjqwq4pF1yn wyBQiEKd+gKbYgN64Zf6ui+8XClTTo21jmtHMWXBjWwakAvdvACnPDpDGNgszFTpuXOn6Mg+3rh8 YJG4hQK08AYiZQkGvhL1kTp0pL7uyx9wnyb9oYj8Sjs8/0EHGDIEMocz9mThfTnMrmTy/EwErH+n g31Vl+fLsz+dzADcLO/LflmCY2yGtzsmcyV0HGQMMWQ91LE0OERBnOrKAEX7vkXj2agxSj5LNIf4 uS4uLsrUhSNHjkh5VeesBgnwswrq+J05NsjPPvuMLCYcKwwlwN3DzQ024gNZJwEUElm4U58vz8WJ TSOAKnNj5FEu5yYkYMc8H4Bzy5DLPpOs0YxMw4KkeWMDAD3DHMtmNbMZKiMKTdJNx89o5Iu+Ggjy Kj0SynqL4+QoGcYbRmwMJx7kdBwXfharaCqO6NiPBdxhFh6iwaBRkfFLTj6WrlVwf0YCcCdSkoDD cDwGDhz0z5TzdK/fUSK6zWKCf+IZCKuhF3LmyYQK+X/cd6yOxQ6h1uybI+luT4+/ljmMQwEXcv/S nACWYqQcPzhaBVwKZLDW0NOSckygmUEIIyOTks/3xVChJIODi/UHoEdGFgANe8Iz+oDDh33puBwa 44GM3EzDlUwOlNNzRicOv2tBss2m4Aufj+tBKdUCAonsTfOR7UKu1BS8wcAXeO3w3w12XgIgyg06 duwY3X1wn9799KqUhSDCHAh443PNzhwdjQiAVBNRnbNoIcbp0G+7DMly6GbSMjevza27d+iz65+L k5tBEwH2hqvjoGK+LpfvFeUrhDIo+0JnD3N9xwyIFheXCfUVlUYpUKWKSgLRm+++SbutLTM7VruI sY+M8KGq9z+CkqHnJU6y3ol4thyDQDIsnd0N6vN7H5yvSXPPDO9Xn5063htgByXcYyeP0YsXn6Te 1m1qd+5Sx5ljUKXlZTQ5eblANNog5SHCyvx74EMCUIFDC37S7m6bAfsMLS8uSZAA/htoGODcgroB LiTAHzJrWG/8sXqBAMT4nQbvDwQB7dau2Fhk/bBWOw8fiDrAfGNGQEuvty7XD703gNBefyggDa+H 2xOqCBq2ajNKhxHwX5Ysnugm8n7CtSMjbzP5yrtOOVw5cYpxMofa2mjwWfPCgXIkc2pnhlqKje4X e75NkxwaeHIkndTdIZ8rlL2decb0q1RE1q20KF3vPT4v7fXL1Orco25nUySLJj3+fpvtDZ/BcnWO 5lcX+DnyOSnV+MzMUW22KfxwftiUZwBca85QY65G5QbmFzPoKEvin6/xWfqLP/xL+vhnv5DnXakC AEDke6jzt+Oh4fnFRqTb+CdMcIh18o2T0DdImiVED9Q0HeqAdZPUQOYH5UDQT4Rbxdce7tAIY7LY 1jsD9r+NU1R87CUqLx3gf3eoceddWlqdoSavoYvgkvfAoL8pc23HfQbBvF9QAu22t2VcnhtotvXy tXv009feoSt3ury/iU6uzVAFzTL8WfuX+Nn4HGwVYjq5eIT3dEQ37z2gTYhAz9bopa99hWK2DW// 8g06ThU6892v0tcufp0K1fN0+d0NKvht/jn/yc9S3y1Jk1SX17A4iYWGAyPioZkMZXFPE0OeE6eZ uFgBmqglZJqRpv2c8duSoLDJn4y+oFQJowQHIHkC29HptpNzDxuGj8WZspJOwCz2v4UXajJn8J04 azhXoL3AVvdAJyqoXUSAZMWyAQwHHORrE0deMAjOzYB9Ac4aAlUkhJLMXIJIMwYqiq3whkGgqA0Y ArgOxw1lMy0trtATRw/xRnRpd3MbI9gkq2FnoMpYEwMwpCM1pyrW0lUyAaFbAYmAuozmlqQO0Rnq 6zgd5GFRHoSvlFZz0+CgBj8TycepYbUdmNkvu0B7y657ASuZOXeqE6klPidOI3DXTGsIjTO0X1nC I+61AXIwG0comsMRX3j2Oal7YzFVIy4QrlKSvTOpWDhHPC8pZ421WeLQ2gF6511HNlOpZBTk0d2V L6b3b6/PNdycUOvpKPeIU/Y1ipW5r5GSOgPjjCzZ0r5Ptgy998s+OwWsoY4ikqtwE6ATG+V3fD7G Q9Uws5J0gDkIq7GIQ06MKnhOIiLcq5YXfWkygEHyPF8GlfcgZzOJJIvTxvMpeXL9OdKGHJTj+6Me 70U41ZHwRQKEAHyKiwVc21g6qj23LLwSAEV0mMUTj5xMIC+T28jy/7JUg2mytQynN11DyNiCEGy1 FTXjpoe4yoY+yOlkAaslZrMdyqPIJZ2i+D5AlXJDtawajqH2vyvvK+OyXOWi6nzYWJpowMUIjJHA YQdBHYYFhgEZOJTyJVMksidKacBnylrx2QM4lA5X/iOAE8K/lapImAwnQ6ryMwuNmCjeG/cAbhW6 CxcPrtHB/Qfoxx9+yEBrXeaElnm/bbX4WmoM5ga+ABbl4BXIjqaVOa71knSeZTPZWUOL6ytWChLc +eGYiqUc3bl5i273+vT4uaepWirSTqfLa+GKfiXsElr0EfHGhZDfvyrZ/gcb99j46gxQfESTnW2t XqTLn35ArdYOR/1VCRRgLMHbQzujb54rLjgp00m07xniuna+w9ZJ8BUqx0+myeAMt1vkYqQZv9eg 0+Z/syPq9tUu5nV02JPPPsXRNwOp3U12WgXqBwXhXs3WGLTP1mm7dZ3XUQ1+rdqQbsAWr+nCwpIA c3QxDwcTBqkLApwQQKAxYYEBXrMxS7d5PWAhwX/DvgAAxOcvLy/KPgP3FvsIWVvstfuY0ME/B8gT h8WfBUCPNceDG4x0LFulXpO/RbQ8Dx3CupwUPHdcK957LLORI16jkmTmxt1IXAg+B6XXLO/aondr V6I4pmzGM+Uta1AuI+aMBJI0r8ROwhuSLmIBh4HQF/K8D1HiDAor5Db38wWssM0rU8fne2095Hvc pGF/hyJ0NHPAWXVWaZYBc365QlXY7/qi8P+K1bJo7pUYjLsl9mf/P1tv/iNJemSJmbvHfUdG3lln Z1V3dVffvNkckjOc3bl2ZhYYLKAFFlhIgFaAtAJWEvQP6C/Qr/plgd2VBrtaQMccGIrkcIYcHkP2 SXZXV3d13ZX3EREZ9+Xusvfs88iomg6imJ2ZkR5+fJ/ZM7NnzwpoJAmMjAwZE9O7pV1BN/Bsgr2p 9ySTk8aldams1KVYLXJ6BabZQCIDuqGQ7UCCA9WGUGQeEKJJBvOEsZ9AOUruz9xfRpaJYVcF3FUS 1CuyIUVJ/xbSKh3dP2UNCDG7Olq9Ketv/K7avbLMTj6RRnAsV9frCp6yGuz0FFScyOisSXAyUtA3 1IACMlGHT3ZlqLYVyZvD/QP56PYD+fsPHshuM5INZJhLanMyvqxv5GVjfUmquuaf36jIleWM3H2w J8ezQA57ag/qq/Kl125IQc/1+z/8vuxrkHDv6jdE2ivywnZKJrt/I6fv3VIQqfa3eCAVT0Hf9W+q LcrLg09vS7/XkTUNTsBdRcNMWoM4Nj7w2Vs51fMS7VjDNfA1iyDOSvezOX91Ou4x04j1Bv4n7m2S QQMQBi85CXzRiIYOflClKAmlD7isa8ImlBTnSgPgIIMmgMkw+B32E+xvEhTjhepMt32muKChdqFD OgMy0GjMQoPj/fv3ZXVt2STaZmnSa1iF0P2VCMDD7kCeLDUfr0UrKrYg3Hw3kDhRWkDGDL+YpHUh pGLyTq7Ua/KNF18WjU2oGZMhYTHPCHwUdZjpSCHLoMesqJEEPyMZZZLonbCFHanuEHP7PJLPUWsf QcxPHxACkRHKjMUSxRVBVO7r5ihB2iMwzSCq7rssWdKRxCjaT815A+I4fiDRB3KebmY3a8o3EWPP jsdjsmxoGcBU6FHiY6JRMUp6VN6fWoYpRnZrFjo+XHxehnIyIEDN6BZM1PORkYNuF4CcZTo8AtWE h5R0xtrYrYgbFQawpPePnYLkpUSsg6M7kALDHLacIuEbhi3jheSHoWPN1wcMIJTTxZ3Rr1MvQwM4 UwOGjpixa603g0pY6KJAjxnOp84lDOcGFeeSLEaUR2Nr2XWl2pAdZ/ja003X1kiqUVZHPO2bvclY F99oglKex47dFMj7aqz6+h40ukALjOvENR6ANzKcDuVsMJbJzGNmgWVFsYjzVJ06zz5KMjeIUHRD gS8VQhNNn0NWAWNcYISLRQCJDHTlwKhGsWspd5ufRVVkM9E2HsUuA2nOOYsgQZ8fQEwpp84/nlIA GoKy6GSqKTCp6Fo/02N3FCBMUFph+l1cpDblpsYz7/Sg/dXjPkCH63RmXaNMk/tpcp+g0YYs9EQB bNgb2lB6jD6a2NxURP2I6DDDOK2f2+tb+QxGxTpNh/o5XSvF62bG/F58RjGflkZxWdrHLa4RlHAJ gnBs6CLq7agu1WXaUeODbnQFYBNfjdqwS80zlMsGUV5uXLrETsm7j7sSTFL8XRfrHYZzllUQE8sh ApFCSZ1YQ/czMvqR2gTTVPOi8VNB1jygcqAuUvvQPjslDQGzWv/0zi25//GHUtO98K3v/I5sXL3E sVXgzeUyRcohDXXPxWndO+qcjj75VH759rvSWNuUGy/dJDB9eP9TOT3claODHXVAJVvf4Lwgs4I1 jqyFl+Y69X03WDyysgiz0r4D+eBXxur8oWCv6zKjy6SuPuV0X8FU81C2NpZkqM93cBpy/BjGE5nE QVouba7Lazc3pfvkkTRyE/nW7/0r+Xd//jf6HD6W+uWXJdDra376mE0IAGWwaUcnLXaRImJHI0er Y/IxtVqdoKkDqQZ9ra2sMLhqN49pizY3N9l8gQ536N6trK0TcHFd6F5ahfAyJ1oo0M1npbG6wmxB qHYmrUAcHc6dZpvaZ16+IPlaVQZn+rx1PXtl3VsKElsnxzwGzi2lNuvkuEuAXskvkb80PNZ1Gaf0 80u0q14QkWyPYJz2n+OhJmo2Uk5lYEhOLObtcvILddgiihoz6BPbhwN/JBnJqs3Td7D1W+3jTD8b c071eKf5i7ov6gqcdS1D55RjxiCD1ZdIHXhGbWJxaVvXd02vXQFNZUmBGkBbjpyr3NqMawpTA3Ju H9MGUklBg0u1HVmcW0dt00ht7DhDWzwNRvq5oVzsKfC59UBWde0jkD89fKKHHeg+CQnigD9QqaAQ DjLsLmMOkege9qHT8kRf5Wg8pt1Adyr89EjBDOx6L9JnJRkCvNSkQ/kmAAi0dECEd9DNS/3qtyX3 +rdlKH3Jn/5SrqbHaksaIktD6Z7uy0jtwGgI/TgN5FDSGzU5p/qk2dNH0BZP7dPh6Vh++POH8u7t x7TNa1dqCgLXJKX+ZFXt0PONotrZoaw2CrK8Esjte3fk3lAB5KwkHz88lddeWpF7n9yVP3/vx/o8 MnLlxsvywVEgn/zHvxK/qYD6+FQ+/OSJrK5fkLR+9kTX60r7r+WVV/9nBXXbcufWd2XS2dPAQO2I +v90MGEXNnwa5HFQ9YKPJ/2Iyg0zYhACr0z2qYzZaGT8XgRrsKOHBwcMZkhZ0X1eX25Y8qVcd74d IwunnN3aaKzKnr6fygGwdfmKPmv1M7FxolFlaSytWhd/OidVxS8QvN7Q4KvjJqFM9LMrqICAO6o+ rF4vcX8iQGo6HjN9gO7xCxcuyKHur2J1SQboJE1l5aw/ki6oJgqMU7EbNuxUaw3LuVmTSMdGFLpL sVSBpgMKauvvbl59TrbqyxQKpKglVeWpoic+CH6IGNSJ5NOpOQdnFp13oc6zbgmxlWU4NzjZlfAo OaJGLJ+yevU/5K+57JdLo9KFR0+/5zyqfzq7mByLZckwcqK3xqvB8TBaxuQ4ojmqT/4WXC2U+siN chHSIsjBIsF/k/OkRo0jZhYUyLHIEuJ4yjV6MEsZRnMNL5Tf8B4QjUGYhPBx0lWIrpQ5MIxCckus tMCzYTYpcKUHdDdioYbhdB7lJteBewUHHkpyPx0fSYxLEHvPqEkv3LvzrJ9JdsSuFTm5B+A8Utcs 05eV+hLv7VSd7aTfIecRIB/dTwBhSBOL08ujLtdkOl8HHLwdjdQwY6RSxJE26PgEzQrC0rmUzEsv XAtiDTOQDcDPRrlkXJYroyKTG7q2Ff9ctPE80k3KZYtdqo7g/kxanm3j5ElMSRLHe7BJi+owsFEj b0J+mkiewA3PFYYEGawkY9FRA4MXnimJ2ChfQKutUDZyeDw28njJdJESGRs4cxgn/Dc2PNL4DCB0 4w/GNnMX46lyudx8mgOaE5IMCt5bq1V43gOXNYSYK4/BkXkeNc1KiNonoBnMnN5bQGA40GeRK1Vl fXWDjQJ7B/v8OcAhukRTEBJFVgt7RPcTuictQBDrnA5N3PvZhpJnyx6UlNH78Tc/+D7X186D+7zm d995Ry5eeUG+8PUv6jFnlIBAABfqta+tLnNY+c9/+RO5/Yt3OGwe2avXbr4gOzt78v7PfyL7e+pM Uz6zc5HrgMc1nn9+bHNnnYh2wjF6ioqBvRCajmFRjXhK92Kvcyp7uw9luZrT80zJk50WZ8e2a23x UU1lx+9Ibly/JjUFROP9R1J/40Up6DlfvLIhh48qajdKCp51/WrQgowcSqfYS6enJ3ObgmcKZ1FU EIVSK2wOQFle11RO39Pt9sh3g1PBs+WEj8mUDQ0F/r7L8me9tsx12GyeyFC/r+qayBcL0mSDxEQq 5SW+v3V8wuBxtb7B8XDNgyPaq2UEFfrqj4bMYKALM2Y3sD1brHtyV90aw+efdXpuzafJ6QqCHDXt jAodWN+87nOUyxlwIxPl+S7jZnscGmAol2e6et8zagw8DZgEMjYK6Mc5PYcVBYyrks1cljEkq5AJ wRaDL/HL6peuSj1bkVk5y4C4WFGbW1RfVcDkLLWLOY8j1kZ9Y9hhjfSsiESKAMAD3Z3+rKeBCcp8 gJY5Bf6VTCBlPfe1si9/+9Nfy+HjR/LytefU9rU0eBzoGrVnAdF4NP+Iq3x4ceCy7GMGh/iKqg94 vwCxJv9l9o5BB7L+s7YG4hkNloy3PRbdr6hGTE8Vq/YkLL4p6bd+U2brl2TWeyiN8Y7UK0UNgpb0 nRPZ3W3JQO3IbNzn8adTDTq6TRlpsJNCEDjqyVnrVA70+f/0Z5/IrXu6xnIVubhalKsXGgpS0pLT JXBpM6f3cSKXVxq6plbkl+9+Kj9//zP5jX/yBzI86Upzf0c+GbdlJzWSRi0vF69eI//z4e4tefPm i/KTn78r+6CY9HP6nPJy84XnZXNjWwHxsfR2fimvb39dKsHX5KMf/VTvl+71MpJGI0l1x5TJQeYM mWLsT4quu+rU2amNJTxQ0FVTEIR71um2GZhAAQBrG7Oc0wryCB10nTUaywqQ+rKETnpmJAfcY6et pmxcvEAO87IGOskLx8JkJuzLFqoa0AUVm3leV9+3f3xIYfsZKwsF95nHlEZ6+OgR9ygAOl4rK6vy QG0cAi+bsLNCugz2ASdAaYCIz0GGr6z2Hf4mFS3wqp5y2JGN76DStdhG8jT6Q9bqteeuyWtXtiWP blHos6hxn6bUmOFvZ5bxCiMWupzwY3oO2BKHS54D26YTyRDrSJ06oV2kptmlCpmBvIlFImxJxBIj N4ok9Lw5x0s+B2ycj9g47yZ5ylkwn+NEhr1FamTCe1moo7sRHZ4hN+P9OTCwaNyTOniSmUvQfwIY rNbtc7i07wabJ9m7JCsHMjr+LhmThEUCQ5sAJ/Lo0sbK8hOKmpgQLnORPoubHLjd65tkCU4f9pBZ KJR/Yut195ykRzJpby7N8kw7/zkX8dzxEszaNwwCEoeHzjSAiZ5G95AV8UD3mHk2JDlGB15fOg74 onnEZ+dyhqluZjpd5yeyVZMQmbgJMyPQwWKbeJS2LlTPGh2mbiyVF8VOoHbA7xVK8h6zSYJzAy24 CIJzkvD58z1/9sk1EgwDeIRW9vXA+Yxd59Asclp959eN6OtE4+pKeZlZWHTqoTzB8iH4cNkMHTKF svXANvJqOv8Z9guA38npEWVpZhztFDNTZiXJ7PwZwRgguAIyGg57PBfwoRKnWdBoHD8jQT+2UTLI HqaRKVBwgs8ppAoMlACWdEFR/JYOQo1ZDtHndERiOiSF+ugknsyYKYEjw4QCzNMcjWfycGeXpPoo WxB3gvNOzsh1cSf7UBw4nj3T8TsPChbWGyZ5jIYjufvJLZMc0efYUMO4s98k32s8snLmJLLJFY1l i3r//ic/kr/90Q8EY9aLes9bJ4fy19/7Lo156/BQgbY6nWyOa8ss3NPBSiLOmZCIF89vHjDEMTUR kS2CtfPDnuw9/ER/pq60XGNjE6aX6Gqmw2isN5hNyhdScnWzLqPDx1LTz716402RXFoBjs9MK0or T3Z2NFAZy9rWBp8zSp94jii14DohJg4bAK4tuox39vfYSLCpTgZr7Gh3h8t5WX8PEHxyeuqcxAoB 0slxi0FUrbFk82/V3uCa1lbXuU6O0Wyj14v34+cAXiDqwx5hfwIEokkB2Qh8DoMP/T26YinsrHsS axkOihNLJlNyyBBwNFtnbs8ZKAMRlYr2fobNRkT6yNLiyej6jNHFPjMKDykWmOiBABAzXDMD8h4x KSJWIBikVqVQUpuZVgCXU0dNmwKwXpKCPpOUAjZRgJYvZ/ivWgo4dipI25pDc9R4HEq/Y+c3nXmU fJjMbAY4lzZAJuyC/h6rvZrx2Y1c0eOi+7MahLJaDOTTDz+Vd378I3nh0oZU0mrTjzRw4BQCBZVq E4v63HD9ESoXYUJTMn04TGrA+qJsENbgXBfVn/uQ2A8JPvLZPJslRnp+5RyC5ba04bfXvypbN/+5 TMoYcLMv+fG+bOp5VWugNbWl325Kv3VC/jD88KTf1f3U1vdqkDfqcvZxbzqQDz/elV++80AOTrtS bWTVp4SyXFJQgUkrqZ5c2FxSUBhKPhWprxnLe796V37x0a60p2n5/g/fl82Vurx2/aqCxX2pVytS U6A3iQ2sX3/xplQLFfno3Z9KqHvy6vWbcu36C7L9+ldl5fLXxR8/McMcHssVXduTl16Wn/3o/5Ns 2XQ3J12bM07tukzGKR1MqbnGRki9D2hGWVleYzYNwGi5sSodvTZ8ZWIkSJM/jDtc1r2H55zXQAo+ ua9BxsbFiwRutaWG9PR5QCYNVUPjK9cp0YRgCr4N3a4I0LGfKvr+vn52ubJEPUf4b+yXVrsjq2sb /Lq0tMzzRtYPexsDAhrLCtxGY+rsVqpZAra19U0FbGcMzC17HcvSyhLBYAr6YczEeImcROxGeBi/ gLo2mDIAORE1eNcvXpLfeON1aWjEFUCWoICxFymZqA/IIgsFYKGbJgudYgVzZRK5A5ZJyXdymTcY cAKL6Bz88AFQlT8gqJqwTSwlhaJlJXxJuFgxh61TSSpwQ81jmWeZAv/pOvizr0VQYiNd4nmH1JRE 20Smw2MKPY2yshPxtPtinZlGrvbmXYqLyso4Nh4kUqN4qOCyWTSaM82mVIYOP+FFJV/x7979zzh/ FV2Jv/Xt79CR3771kUb5XeqRxZSoMFI32p4BXPBeXg9GtUTWAZPPecyMtI861gQQWMPG3ICKlYme amSYt+kn0iEL/y0Ger1knihF/M6nP8Tu70LX2QspkZP2iVQ0gkjpisj6Ru4fO85Y4LLAbMrSdTGN 7POHCuoYVaUxmml6PlCenAJTsffiPO/FQA04HAjLq75pdoduOghKg0lWlCDLMy0h8bx5WYR/8Q9V RZ76mbWYu69REhykmG2EQ0PEPpnGrs3cMooQ5c2XUrJUX+eeotL5cCiJaHDSmOK78Wo4ZiKc2mjU KRWC0mgi6RHqMWA0Et4cjoNrzOdNlR8l/6R7FcAQ6XoYrGKxwMHmWKOcEOAFzDzkU3kaMKjCo/HF g3SPrp1MHh2sAwVrulZzgZtjO2GWAAPfkaoY9Gdsy19Z25R6qSZ9BZjtngkeY6+EeF8UUCl/wuxJ QAcfRpEr29ssR6xjkuQcd3K+NxeeF0BSDnN19fkj41/IZ0nmr2uUvLV10cAmmhoormol63d/8VP5 ux9+Xx0apC8K1M06bR7Jw+9/poEkSrlVyajhdqMozS0z8+wy9+xSNlCOhgyGmAv6Touc0Vkc8Hn4 s6Ec7tyX8bApF9fruh561InM5esEcZ3uUEp1jxm7F25ekK2lWAqzQ3n1za9K+cJzep/0uVUKtDe4 hsPDI/EKWYImrB1m3YpFZuWwTk5OmmxoQIQPwATQBdDU0Gc/VqANoJQrlgiisCYA2EFDAEBERq3Z bFN3DqARx2upgwAYZFZgZA0ROD4AM3iVyLTBAVUUhPV7JtwMXTo041CjEOLVpaKU9G9g93ANyF7g nNptk9XBOk4mO7D7dzZ9Zo/Z7GuTCLGReuPZGY0QteVCI/KjCxCFvyjAmC90GCpKya2rA1qVWWFd fVBDxqmyrumSpBspKamtLJcwk9gn/SCTRbMSsnsT6U3SvJbZAOLyAUfxTSb2ldYhtm5XrOUCmhwU rJV1vxf1vzGNIZdXsIrRidCrUx+BZgb85SMF0f/xL/5f2agrgNO9dbhzT6oKoKApBz51TtfmqNe1 kXRJsC9GxUn5iUg2ZpdPTabCIvU/TwAAIABJREFUBTwIiuD0aYk96JFV5XQIXcC8nk8kZ/1dmaU3 pHztdyR7+TW9prGUjm7Jarqr+3WVpe1pd0d6rUN9jmgU6xOooqdi0hvKsNPW/+4qWOnK4WlT3nnv nnz6yZGcdCNmia48p/ZhdCAr5VjquO0VtQvRWFpPFPSpPXpy+kgeHrR1LdUko+f7+O4TyY4V6K2V ZH37ilx76Xn59MEjygK9eOOGlHT9vYuZxd6S/OGf/Jfy8hd/U5/nWA76un5LaVmq3JSo93guKfby 6y9INNyRH/3guwpAFSitXTK/o0AUE3xQ5jZ/m9CUhOANHhscSXSrdzXIK1WqlOZBGbaQzszpUPSb GvyCWoDgHxUVZLsQfOA9phAx1XVnZVg0beHzIufzkMXu6P5YWl2hrfZ17WHdN5unsrq+wWOh4x/7 A9UU0FRgly9duaqgrs0GIvwDbtjYusC9hAk6APGjSSgrGnQB8KHxaag2F1JD8+7UuZNzG8pzgIld fCDyCrrC8vKNL7xOBf5QN3YWrc1sMrBoN8bMT9+zEScAJI77RaJp5MZZue7UaDpzUbgrv8U2C42Z GgcypsjPp0xJHgRbkx2w8Ugz1wgwL8vKQulrDlGeBiXxM946yd7ZtXuUUTFwYjwYcJxyWRPUIymR Wmc+U/kigdOP8giEEqLuIo8Mg67v3r0rX/zim7o5S/KTn3wgBwdH8sorr+m/V2zRhMnEBwNwQPwf fPCB/nuPBjXJCDx8+JDZJHSD4RyTTA7Sv8zKoWMLXD7PiTbr/a7pw89olDmbDG3GHsFtygjaKCt6 3vmUC04veDozsui0kizcYkOIAdbz8hfLn5F99gRNKOrI+7oZT5DxAchHMhVaI1HkRD5DOzcECeQA Tubl5rY6FTj+EVu23XxV34QyaeBRIkFH6th051Cy9oLzSRV8vkg4xskoNwtQAqLgFA0gmxuewW6L 3c/J+onnmnuRDb0Xy9AmGVFoFyYZPWzYakEdw2CqjhCzIo8JmpKMWNJYkJRnAbzwMyuJhtzQAGF4 9kk2FiAVunIwGng/JVYK1hDTbpmBIZBDG/toTIeHbAy5dm7APBspyOsYzeVGULbrhSM+e04a8KyZ AvsNfCbo+wXFnE21YKY2Mp6SGO4qqyHMqTM7aPao+4cOaJQoQx8CqREbEWCkAA5QtvRcZ3cYJbrp 7n4TlAdyPsx6wSa59QmCN74i0j/rD+Xmcy8ygDk+OJZBqMC2WuJotTuffCwfvPsLmel1lmoV6U6t ew8Z/BQafPJ5BpXjwdjkZgKjIRh4PC+hJ40t47GrHlBM1Y17svqrOd/YNKF6CtqPdh/K1lqRoq+t 0xNmjjAfOpNLsSN1b+dALm6typs3NiUVHcnmZkle+MoXZYwATsHs9e1r8vPv/VgeP7zLqsbqujUg YO8PBn25cPkSnykmweA5AuDhe2Tp4RQwAQaO4cneLkswG8sN3UNZOVWjjywduG4Yd3h6eEgO3er6 Oo+P7CT2GBoe8H6IROORQ1sum8qqQz1y5fkKg4XB4JTPBVw4juKC9MjMfg8Qkozxsq5Vsa7n2ON6 QxCRSLfYPXeC4xTcnrIqQsH1YMYpC7VUTTqTtoyjM+OvwoalijKRZZn5ORkU9JwVtHmpNUUUK5JW UFCu+1Kr6DPPT+VCNkPuLRYb7gE4td0xgBtoBCnQE3Wtqh+bilMgcF+ZHYyloXYLNr+g//K6bkp6 nIICrwJ03XyzDVQpGEc2iUJfnz7clX/77/+zBkSrcqlRkbPjfcmlYXPRtDWUroLoUrZoIxOnM9IO AFLQeR9HJiifkOCxn6LQ7gsSAJYBNspIBg1Ro74+k1ByMuT0o371huSe/30prb0g+eGupNu/or9e byjI9RWsnzwihxb6qz2IW+saxbzyUQ+6cB3yX7sKTG4/OpB3P7otd2+3aduuP7ckJYyJ1XVWLi5L Xvdad7Av4SiQgdr5ZkuPDc4yKBcZBfrg0WINl/W5pyLKcRyprZL9Uxl5Cly6ul/29+TWux/qOtmS f/ov/2t55Zt/rPezIIe7n8n7b39PXpqOpKpA72zvgTRWbopU6Hbl1S9/RR7t7Mv92x8wW5vOpOkX cc9qCpBazTMGEKQXINkUmP4hbBs4kZgogheaCpMRXHh21j2apzYiOsIRsA8xJ1iDIT4PD40HUwI1 0FasGpZ1mqwxhc2x9qsa+LBLHPzmtO6Pbk8q1Ro1HiH7NBz2mQRAg8+ZniOyfxC7RwUSmT1ggM0L l3gMyPfgOcMXLK+us7mD+1LX9an6gvpKzc03d2S4wKH7JA1hXXj6kLpn0lDD/pXXX5YrGglGJJJj nI1pA2HjQ+OsDO4ccBfAzNR0zAiIHAdGoMo/nlCgFERbvBBhzBxJ1JhVFgEBUFF+Tx0QHJJ1/j1d 7jSPnXSMeuctxiLzDid/AXjMJQwWOp7EdVES0DjQkrgSbM88uq80+ocBN4ednTsYDMxlHjM+V2pP Skd44ca/897bHIIOB/fBr9+Xe/cecHFldUFtq9HOgCTvhFZxjTu7jzm1wZoHRD689dEcRCHLQ1Ff gOvQtZMHKRshg3Q80atlO5CZW12uSYyyYjizklHkDKQDr8YbsPlyyd2J40RzxziAVm5OmkacwrVY ZorZioXSqnX4hSypQxNoqF9bCuD8zKlG9GmNFGdSVKcJLTc4nV53SGFfNDagSWTmspjJBI/ZNKYz ouClAmg4HJYosyk6DWQUMC8V5dEpDG9sfEBOp+BcVCvNzNhRcT4Pz0rs1kiSSMEljQ1Jl3CcjFeK zsWUGS0vlJS5Jnm+I9cJ5Yaf56xtHMRqClmPLAuLF8FWGBrJVh0DIkF01s4zbvoVWRIcG5scAA0Z Nfw9gN2c46bPASPsANrOdDPnJ1PX6eqzhO2DpwU+kisDoVwKfhKMGoDgiKB3ypmnnMcaWrNOf6oA Tw0ZsqcoA0MGoahAAaD/TI3RmPp9HonXa401SnUARI/47FIaNGSlP7MJHPlsxKwtriPZGxxVB9OL Z8Sh5Qs8w2RysqNX4McY7cdtriAPRhBZ+e985Zvy3LUXTBRzPGH3arfTlpyCtMf37snxsUaqy3VG y3gT7jnuMYw2VjrpDmr4E9mVJACJHUUjmks2xPN1kPINZPquSYrBD/jAag6ahzty8uSuVIp4ZpEC uANq4JVSmCaCbHuBQWq3fSwXXr0g9cKYDUjbN18XXyNqpKCDVChBocyZpPee3JHi+nUFWavMSh8d HfK5c7i92k6ALoDytbU13lOUWgGS8XvY00MFtuAgrq9v8noQueOF4ADvR5SP68b3eAaH+nvsY7wf zwldrNg/VXWECLhRnkYAgIwAHWKnbxxLlEp1fUNkGjaPhG1w0gYjTmkoIEMRRfNuOvwexyc/bzy0 8Uacu2fyVujapD1Su4rPZ4A6wWxlTx2/7qf0ki6IhoTBmgzjmgYa6uAubEqxllVHiLFinq5536Q9 QvCafTlG4qAPbm2KjUOQ9DHzZ1SOaWdo85r1/jHTpuYtr6dUVJCSS0Nxf8SmhkwKohaeBMmsTmf3 IMuX1kB/qn+DvorP7j6U//M//d8EaSv1qj7zQ107CsJ0/YFT1Vgui6cHHuo9TDnR8cUqTuyCxjlP 3I3js4z4OWcTdh76paECsyXoqaoBnDZeldUX/4nkSmVJdT6QwrglV9aWpVAty2CqwfTRPZmAfzyG DTFQC7mSCbQDx031zV05ODmTT+8dynsfP5Z7O20NBHJy/dpFtQGxdE91XeldkKkGT2cDOdXAZStV kLNIwRsaF2ELwceFoCOaCjTQLGPOst7b085ALr/wvBTKS/Krj34O+WF5MH6okeAN+aN//t/K69/+ bfUXGEsZUYP28Mme1HUNjY53ZL1Uk9WLuPuw9S2KN//W7/8xx8+1Tk7J3UNJFPubQa0CJggNJ8kU FPTw34nNtkxwxrT7ncYqstlFlyHz0yk+Y3bxp02vM/HpCARhcxIlgCCbmQO2sdoV8OjYtZ2xyRIs zcJ+MskyZRMDSq6oxAE7Adwl86xrAH8K0tY3t4gJMKIOUkDYT7gmUqX0vNE93WydUBuSfHqUP8gz cyM7xHGWvNgMMFBeTlHuC1euyldfflVyyHqo483oQ4OhZukVXLWI+h8ckVSAzIifSIVYJgV6cLGT ohCXlbPF6Mu8ooquQZSpIhssjhME4sxkLZORS2dcSet8VI88Q0w///GibMjT0O+p76PziRTJ75Ip FfgcZAAqGkGiZIPxTgZy3AB060V+6jOTrs0E2B0c7Mlf/uWfm0K9HnN1dZlllvfef4elEZa+XLdu Ii8ChwNjbmDhvNkhjheAVmTlaJSBwI1jyYsOzwxiTaPkhj7kbvuJPpcxn9M0snEh7LrzXMdlkn30 LJtJN8qMwzmQ/zw5lsVr5gBhON3IlSaRZQsh9qlAtj1QY3ssWY2YZ751mnrgTkFAWh9jFiOOpgao ULIa6+9ROgRwH7sMJ7JncEoEQBAD1v/BAIGQP3ZcMc7e5IBrjxw1gGZbzfKU8TNgH7gxuIG7zuT6 FtaG+2IjzM5LxnY+AdPbMP50BDBasT9vdmAEpdEos18pGzvlJ2vKleWsmSV22bvSHLgik2Iinudg EbwkHDMxFjA2yVpBxJk8E64HBSfZVJ4GBcYBINC6Ym1EUhpzLovFuXCkRfzCpgVx9yopd6FbM4Dm GoOAmPMXY436R2qkzto96auhVOvPEk2AiNQLzM3FxouNQ3Tf2uBqnGutrmASQ+bjwHFFPWZTz6kP C40lTi4AauaIRrvI9vgZuXZ5W67eeNG6z/TZ+15WwUGJvCYogjSqFcqjhLHxL9Ps+JuxdEr5EJQl FIhCDykWAwwc3UTtxWTfWgMQzzFj5S3qdXHPWwkewqzIXE96J3Ky+5lE/ZasX9CIenQqOQ1Wykt6 TlEg7e6IuoYI9rYvr8kr28tSyozl2stflitf+ANBb2UOaysaKhAuyfLWmow+flcuN1alrOtrf3eP IAgdaghikN3HvQTxGaB+d2+fTgOlZayNw+NT/n5ja5NAHBybTrevgGuJMiTgWkKqpKYAo1SG7IhN lUFZtawgC4APXdEAXCi39lunlEbBZ+NnaEICrSPRnut3Wjw/fBbeT4A2HNnf50vUYIN9w2eDr4nm CUg5JPpwCWeZwJglbGtuUKSj97okLXRpygWZeKv6b0WioCy5ckWWVgpSauRkpaIBMHht+pwQSKCs 2+3D3+ApAbgFtHdTjPVyawqyGWlmuTy5kEO1RQNEBeNZDqRXW6vvTQfW6BVLxpmDkA4f+o0IGCeh x9GFAJjTUVcqS0V5/OiR/If/8H9ItViVC6slOWs+ltG4IwUE3+FYquU8JyGIG2SPLBuAWDSxBimu WM+mIcEZIiiDzAd5r862kFYUUH/BMkFZvUcT3dMXb8rajd/UPaDA4uRdaWRPpH7pIv1tv72jz+yY 85qncY5B52TUkUjPZdgfy2hwytmxJwqA3vnwkbz9wX19prGs1gpy9VJR1larsrd7oPZjqvd/Iicn x5S9CKUkTW8ihaUl6qehGSDnC3nyBV0bsEVDUByGERuP+notW3otS9ifHFWn11zdkDN/WR4ctqUm +8xyHe7fFi+vz6W4JI8f7spBdl9Wrr0hJfVz6dSQciilwpZsb16QXxw3CVtKChaH0E/TtQFZDpT1 mWGDXJAb7Vlw2mrUalMQBp+FCgcnolQr1KhNSqYIXKjdOjF+HH6X+ENkTsvOTvc1iC4pwJoMbZwm bCxUJPAacZpOxlWsbN4wZZ7SOfVdE+IaBIoIfgHWsFcq7DSfcTINKCOjQd/AqD5xcBcRODX1XqN5 iTqnM6znhQ7EeWnSjb0BOOursV6v1+SNl16Skj4AtBrHGIXlmZNERMvsyWRss1BnFm2zHOq0k1DX RxmV2SQ0QbC05Do2UzaiB6QWprKhmg49s3DmOEZWGkrKUIsAac5HXyyBLAA0kyhIOmFjp3/3NADh u6Mk8k+0viPyjdhBihE0FKjUBzTtJbkCJwli47g871xwdx5RuZInQWpsYoERydd5GemDprGk5tMy r4sRgG8jnKxs1nHCrun5sHKLzlzdPp+dd/qitAbjgKwpUiMASDCw0NHa02iJ3Qwuw4B5L8h84ro4 Vi7wnypL8x44XlJync8C06eaGxxP0KhFNogYpE9bHwFH7rTP+vqvqwtfLaVGpRFU4tWRp9UAYa1g JiqaLDiaRwF/uqBRO6RZQNRQpwDhZxgB49HMaPhQ6mOZ1SntM3Mbmeo/SvcE2DHMuM9xbdaBHVDW IBWYJAquPZJzAeDF60peSUev71km03OzGjG8G9fOmbqpYD4/k408vjVbeKwpT6RUKRqhu9mc8yuy yDAvkOZF3KQLMdFePBw4R6wTlM0SXSCUWyt+ba491OtbViRPIV03tsuN4WIfH/eQ6QriPiRdg0kT zUTvJfak77h++G8AKxhEyNukAbCwP6KxZYcj06P76MOPZL8Xy5svXtNTrxBAs8FgiAkrAT9zCmJx ysr+0/6Y+wxl/6kk00RiruekFE2NtYVZqlSczwYsPyAS3b7xiqxfvCqHJy0QKnT7qcMNSiLtmBqA kUbwkFChcG23w8yR7/ihnOE6sRF/7LLVz0EX/mQ2njcmsVDuJfGL/xT9gvs9sukgWD7p2Ebx7Dy+ I9NeS7YaZYmmoJhoEFvJyWqpzvFaKyVP7uw/oEzGF17Zlo2VvITq2Dcv3ZAwc0Fynt6X0SH3W5Ct yPLmKp0UJFRSoxmz+bge2AncX2TJsMYQAOJ7ZOGSrByeC77HtaCrDUAeWTt8v76+zgYCrCfcexwP wR605bCvcDy8D6UcfAXhGj8H/xCfs3Zxi8Bt79Eu7+f6hS0K/iZzNeGgcF44Ps5jXY+H8+qf9Mkb TQZ5Jx32iQBqwoEkkI+N58lgLMzpmivIgf8lGWXVsVbrUltuSGM5q45MwVYepk6f+bQoA7Vv/dZU QZyu0yArmLCHf9jK2YlQyqaIZISax5qaoEbGl2oGWTfdBzMEwaFx5FyWDcCNbFX9ETJsoAzNhlPq WJLCgXm+4HQz3tV9rPfx3tsfyA+/+wNZK64Q0B4rePb1wytFBQIO3IBKAm44AlEkTlDag/80GazI CeULkxix44kii40gUFy2GDYW/GauQ1TJJnUpvfbbkr/whkzO9iTovC2r9Zw+321d50MJ+48IzqZ9 SODo+4en0ou7DMyGLYg/t7hvHj3al5+8e0c+ftzlyLCNzZysVfQu6A24e+czji8D/eSkOUNfCPmK lOKvqE3V9ZqF9BaCLiRxNDhA00tX1+qwUJPVRlXBaFfe03u0/+CurK7U1caX5dGTQzXvv5Rfv/+W BkpZuVQ4lePUQ2lPOrJ1fVNa/R1db/clzrZl5+ihvFS/ytQnOLyPnjyQxzuf2qQa2n/TIETAgsAW jUTUtJxXsTLzjBrsMIIWFAc5KcFpr4H2kWi0JhWPVK4g3ZG9xyZEBPSPGLMIv4zRXvg5nyOVPNLz JjUGxtF5cySpVnkDejg+9gWaMzi2MZwxmKcPgKC2Yi4ERMAepkU50aDN+KvZPLLcOeqvLtUaSJy5 DIvLRiFKJWIdDZklwUZ/fnNdrjRqko2giRRRdZ+IFs4aNXWOutGNGRnxO3LcBmqGsbwWMt2PTTea 9hl1oZw4ZldhyPbsDIy7Gh2M9IJmUG/UZvQUpy2JjXJGIY2UtjohSDogzTnzxI1YMNbTouyF+54/ jx1LLnZitFECWBJRVxtobxk408oyyQ81+hqllAt1XdTL0n08ppZODnpSEUp5WFAFk8WYJdMkbDA2 mx+QkUR2xUmBZLL2gFMa/V+/ft1KWeMRSZSUk9D3Xt2+Lj1dUO+8+0sjppPDFlnpIWXDdxm9QsRW 78E0yFC7C1IuyA93JyGN7VV1BrOTJxJ2j4wt6OdsQUN5Ghkk38qf5AW5WNMwsE/V9DloswEkCyBn xgjGCPqx2FgT/I0Zo2k0JfjXmJjq/bNMqBFGLMe6EQr5NDXIkNdB+3weJfUkDYtnidAibdp5yDAW QPysFUmyZiOL/jqcQPFeOMFhNEUQkDc+DbtSTUEbWawIHUq62NE5yCE+6AIDvzOV5VpPu9l2bJvF PSCB3TiGdOJuziy4Sjg23g8OVowxOdH5XEcqdDPrZ9pReEYov0AaYhKONBo/Y3YAZFaMSoJT7ml0 RQHXUoH8NEZnOXRLmujvcOwkSPRvoq7HcimMQqD/wAXta5SINYz0eiFjEaGJyCr4LRnxFvwYSkkM EQhE1AcDvzOZ1YrnDDCP5O1YI/N8psCuJ6qQK9Av6DXMxl0ZYD8p6AAYBYcRIFJ9hLz+fElOm+/L nVt/Ldfe+heykinKZ1gZ6q3AOBlP0YRT4H3DtYBEjPJmvlTh3EjwXqcRANGUUkYBB4aD1G9gEkKe SJ6Mvam01Oh99Stfl9/8x7+v15jjwHcvUfUPPQZgE30u6FzFIHOOilIDmkaJGEEqwHY4MT6fb2sX PF40f8zYYRyw9IHnbs97TIebwfgs131N7a8wYJduPgsO3L7sPLojw4Md2VqvSzE9kWG/rc8DmXsM gx8ogtB1rGtws1qU5y5tyZvXG9TvOmxN5Fe//khWt16XXLmqiKSk62ZJMnoSG6sbUq40ZP/ojgzS DV37fVlZX9P7ZvpRp80WO0rL6qgg9tvSAAkNB5gggO+xtrDW0AWIDBpKnQD4jSV1Ct3unIOJLB6c yUCPnwNIbDTs/Z0xpT1Agh+Oe3KizhAZ2XK1Qa4Q/h5lqxqU49EwoUE+yk+1pSqbT846A91OaclX 6jKaTRm8ofQPwVzMWgWp3MjmGQIZjGWDLZpGkK/S9eJBPqMlXd3b+fqrcuXNl3TdD6VRDKVcysrA V0eK4KBfltM4I12KwqvNiFKUxSGdR9dNSQFRStdIPqsOMZeShiKPpZSVSn2nh4pnG6RD94MUeaDQ jIQpGuu1ormqN/ZNbZ9TQAJWGKgLqnal226xmWF354k8vH+H3be5iqd+QcGU9GXSUV8HmkwcseMV 1QFwDClfg5FauGZd67DjzAnkkE0cUVx/OsK85FiWSiMJFdyHYYbVrFkAP4LRd5j5+qbkX/2nCog0 4GrfktzoSJZXC7KOFtXBkRz3m9I/G9AWhrOBdDB3l6XAUMZnCuY6B+p7+vLJvab8/L0Hsn/Skbra rZWlooIRT68f2ndt6aMDHPosYZpqBBOUcoXlDok66qtRBZI0dRqL2SmbNyCslFu/KHVdGyMFGxm1 vauNZXINO2fqRxWYtnWt9TsP5Z2/+t/l9P67sn5Jg9NyWm3mA8liL+/rOWRmsuRVZOfeu3L94rak i6t6L7qKAwI5Gwl5krOZSaBhRnMNFBK9Rtgd+HFMjEKAjWeTqERU3NrFKxk/CDCI7BuqfeikFlZR UqSAFTM52lwE36BCBbpm87rHe119P8rFTviXSSM0WadT9OtFdLEiWMW8gnRq3nBHqg1wQS7t+KAe R7pZqdezHgIFeKAkwDtmcC25gKVq+G7Q12C/KuWG7psAQYRFl0kpFRt8FlqJCryFC2pAblzbZmca ol+Ss9UhkOeD+amZgiObe06izc1A9KzLaDazjBujdOdAsGATnRsCCzkHX15kqtSJGgiQaKGYIy+N XZwAdgnI8LkT5fNei1mj5PsEiDz1+4X3J69Q4vmYJejl5LNlNa5L8mT/WCN8BSNZAywwfrMw/AfH ffb7KApd16WNLnrx+Rfljde/QM2kAUjAAD+uhbyhxvjVl1+W0+ND+UANdsLX8Re4et4C/y+L+6gP Gx3609iaSjZqeVmrFmT308+eOpenSqIJ98tlos45g47tlmTu4mSwdDKWLSJwtmPGjvAdszRmwMa3 4dBTk4wZT2KmgVsYK1JISwX6yCC363sxBid2gMiwuGXVkIYHh23KeXsTK5Ui8h2OWEYF+EAWEdHP SBd2wIliNjMT1wQxZZRkUpQBCNjVBuI8+HwB56R6LOWytJk1XlYUJTw4cWsxbTSDOOFLOQ09x1+x bG0ypcGXCXhDUZbluoEC5V5/KqVqjhkRdBbCwSKjhigR6wDgAWUlRIQJ5w3HIpifhud6gW46B4cl L5S1k/0yn6EXmHeauewGyplU20fEN5u4aD8pjwcEbDz3dMQWfDhYdmKnTQEdYBTrvDfQqBGcNjBS dC8gUl2vVeSVG9tydHIk+/c/lfWXjuTa9lX5ux//ve6PvnHvMAfQzcTFdeC4AABorR+PjB9oki0x x/GFDlCZ9EvKcRY9arDhHi3Xl/Q80roWQjZT5NTxQb8SEiMzfcAYhQQ5hg8HI8ohQR8RoCJ2JbRE TJsi4GLd5ixpwealbM1OphOKfwfpgLEFM48suQsbkOBccU8G7SM5uH9b+oc7GgmXaD8hWRByUaGK MCaRndSIcVOuPleTL3z5VSmUlqQzPKYa/r37RxJ9//+SL3zhulx87pqMI2Qscxqp53m/Dvf3Rcox n0MyFg2yIzhncN+wz1AKRdyzsbnGnyNLh3X03HPP8X4fHu7TuaAUi0rC45PHXHtXr14lwAf3Fr/f bKxbhuL0mOeM8j3WxvFx28ZyNeoK8iE+3eLvl/R8kHlr6XoAX4caiOkctelwfIiTo4sYGVQ8c3wW 3oPfJTqINs8ZgQjI4UWKr0beiBJCcYS5rXty45VAfvPyVBT6S1Ov+FCf67Cney5COUpkGEwkFabt GaJpCWK3IXi3wmAGRHyM3cvQTtr8UG9erbEpLBDJhXUbavB7psFiF+VF8CwZiKOjkcRMgp3BZMZS 3QDj5jDhQf8dPnjI2cBFgHtdH/32qdoAdeDZFKlAaDxg13baVA4AEJARjrMx92Fb11UWdht2aQrZ lIDVI3RMppaQ2Ag4WzdTXZaKgoLx6YkMshsSv/AdyW9/WTLDJ1LGPfZ6UlvOK4gJNJDvymn7QIJ2 XwHYjJzs0ThikxnOu7kTNEhMAAAgAElEQVR3KM0jXTupnNy7dyw//cWv5eRMFPiXZbVSZOdtH00O 4EeqjfLBL5wYMMLFwM9Mkiaf0JoSwUceoQqiz6hYsik08DEnR084NgvNPegoRrf6ZJKS0w7GbOre nJTko/d+Lbt79+XK9Q15AVzX1EQ+O3ige7com5evsxz+yUcPpVp5W778jX+ka6aua2Qk7eaJBhO6 N6CZ2R2Qp8tpFjOrYI0xpMD5JdiRpOGNWTcXMCeyTgBnCWcTazGR+kKA3u61SQVAEIUACXsCnH9o /XMGfBDMGxMJDtUHFFxlhIL8eiw2o6FrNgrnurBJ80oySSf5PrFXZp8Dy/SlMkyumF82bUr6B8zw TUZ6JOUNcAuQhsfCB/h4cXtbLl/Yog5SQvKGMeRgXgAJZAAix2dxGQF0tKKDkzIhE2tiSJwInEvC u4kcbJg6hBo5MjEuyjqYfE56KOnF57MmIwCkGll67R+Ar/PriJ6SAVh8PQvi2HwhVj4OJX7qOHSU 0OlCFkkNU71cYCYCZPI4SrpR5anM32JTCK/XP5+NGrpzhWNH9Dzo9vg5MHIEj+6Bw9kn+jEsUYol rBazjHTmwHIhdLw0Co7M0eTUsL1ydUv6p09k2m9ZdvIZHbvPey1yCBfvz3mnXjgn2867+UTcjNaE /C/uPrgoN0DDS1kjk4l01MGeakTm5WzIOLp7kLVL63ucJr7xG13p13OjyBAdc62EtuZAbieoTdmH 9TTa5FBslLUBaP0UF3za3TuYcJB+QdLMljFhIc3GGmReKT8RDJ3yfmzFlMXW5tifrwh8JiIkLzgX fabenGcjyxAhUctQXFr/DAT0tmyuXeDzxcY3cd682/CmKbfYrYr1znFO3vkQZc8FPAlYw7ETiRKs KzQSYDNzrzlNNtAX+PzGGh+nsnPQTvCG8yfQs1mBXBuBzSCe8npc0wroDApgcuAs6h4G7W8SAuCA DqDgRA13GXP2OocyOH4iayt1EqpNjiF2UaeB7xTHeJWYcSZfEGry05AZiZnT32O1MgrdPYyZ9SOd QaNgZPp//d67LP2lkO2AFhN0BRXB1NS5oSkGJZzDvV259eH7xnEpWQcaJhsk9xfBQMo3kVaQhjmG C6r2s5F1maZjyhdBST8myFPAN7HOycDDXM8Jh4Dv3/9IhgeP5IIGSoEihb7ahDSVSfAsSxyvdNY8 1KCjJ5c3a/La6zdlbauq14TpGXCoCh7SPfng17/S/Xsoa6ub4pVL6D/UdZ3Rz+/J8emBVPLImK3S Vpy2TqXVbkpD7cJStcayJ0qlcDzsxOu0meVN7AfuAUAdwBNKp5QlOW5yvaF0CvuK0ifWA96P58VS qt6zNZRWdRGc6vdYe/h8anE1m3Qo4OUgGMXxkfVGt5yN6TpgmWmlsczs5vFxh+sen49Gq5OTI2Z6 2aA1DygjJgSSRjTcd2alFbDgeUejWMoaVxxDcxKi07p/Z54CSgZ9Z5IaFAiYlvReVfRrGXskALfN 9q3CfLed3Q9YzhdmFcFLavV0Cfd70lcwyg74tIF8BFKUkhhM1XZ1SIfheL0xtNhyJN/fv/uJ5DGB JZ9jGX3cO6M9zqDhRoEVKEaQYGGmHJ2g0A6FDcf+h+IBqjNIgoBvCqmsEBzOIuNrjpJLOX5meksX V098XXv+0otSuvZ7ktY1408PpTJ4ICsaHJfLalPVpkxaHa6Tjq69nNov0GZQTh1gGs64Lye79+Vk ryWNtW0Jg5p89OA9afYhLZRl+REZ61CBbH/Qp43A/gOHuVHPSrlYkQc7xxqAQ2uuygrQwDV2IABK FwK5eHGdM5+PTpoyHHeknA/YFMK9qDe4P/Gk2dPzaE00uHhOvv0bX5EjtYu3H/yKdCpkozdXN+TK 9kU56HRl/3goWfCc9b5/dOs9ufHqawrmrnMazsHBjgJ6X/ebTx4s5aTQaT9BwOWRqhNKPB+RlciD MAs6HfE88WwQaCDLRu3DdNqVV/vseGVJU/cQEluc7+1Ksgl1BfIv2FuwSeTxT6yKwoqbC65xDASi bHgAuA2Cufh1EqzPQd50Oqcb4IUgKakKJk1Y5FHnS/PK45wTZyKCznEbSlLQUpLnNrYkD2kPXXCY gcg6/HAkTmOB3DY6ZUfchqE0MBRal5cb35TwtxKHiAWcgLjQOWq+F7/TjUA1fETwmMWYRgSc4sBb Yy74Dkic65ctAhD3jYGfBa7fsw0QizzAxa5UnqPjxsDgjHRDhFEgGysNdlueNE9ZLgsdOfycmH3e 3JBcr6VIkyyYEPxhMcHwlkozcgXgLEhaTdnImSnL0zH1vabziRHeuahwbPceQ+VR8vF1ow26Yzrs 6xfW1aAFcvezu1B9NMFmeZrvlWTRnr0Xnycl8owqy5zDsvj9IjeR5hIZjnSWRHLMOoXsCQiix62m xMU0y5xZZNw0+uSKiIwT4rmyKHhrJsGRIh8hmaVrEiZiI2+GoQnhxk5EObbMSi7jMbhApI9NB2Jt mEkz24kyLcVEFXChXIdh5zbtw3hZgbsrybNC4Tjt21g3a/6w+5HcJ5ZZ05m5ZAL2Apxno7Ksm6wm xxoNU92bTizL8lXSxGLAJZKjQ1PhB+8zkW1JojDwQQmCRBgIwTAkM3XJI/LPZ9XO5waKCRvzmTt9 JKZrkqYB17GLEhdI2igXoFNq5k1dp1OK2TCUYOC4KPisDmigEflgghFQW1JJdWV4el/vzZTdxXGv KetLq1aSQMt8LmWNUcj2gfszsVFjAIlHh/uyfe15u19Tm8yR8E+TbKPNEraSr8/5uSIH+3ssW3Eu sR8wCsbXqWnPKIAsWGAXmpYSGzlgcAOzTX6g4EhCriOb7CEMqlDOQrYXI4qw15MMK24pptNMcc8i 8FEUiHdP5bNbv5Lw7Fivt8QGhtOzJu8hZABQ3s4Wa+TA9vRZVTVo+OpXbsrm5oYMJz2OyumPCnpM ZDnRda921VcnibFR+k8PI3kIj+pPmq2uXLtWlMbyKp/z40dPeM/W1le5NprHJ+zw5ZgrXUuHjx4R XF++dJUNN3s7u3QUFy5uMmsGQAQnhSweHMDhkTVEQF0fSvZQsbc5jwWWWjGnkWODCjl1QGWOWiRI zGWlWClyLaIjGEAYTQsAc30NSmEzKwiW9Lng98nMX9xTcHjwXGH/EntD7uR0bIA5TBM4hNFA101J 3v5xW/7zS/vyu29tyLI+3k6Ul+MehKwjKapdqeQrsrySIb+tqlsCOWtKGCWRGJtIMwwocW97IwVk /QE1Dbt9m1U89R3AFwNMk9GQ+xTXjkw5xzD6RkyHo87lfQrkYs5ozo+kgH03M38lDsAFLoFRq5Qo Qp4IiwdOUxQvZIrQrBWDo5oyugfGFqbTZXbV4m1T/Z1XCCXf1wAjyslk60sSb39T91dByt1b4k0O 5WotqwGA2ohYAWfrjJIV+Lsc5qbGI3SWWZZZnzWmlBzsHsrG+hW59uKb8oO/fVv2jg6kXMuzccOP mxJgepH+91Ilq2u6oKcVSV4Dogoy+nGa3OTLz22TQnD7g7+X8cjntcRpk/CBjD2qS/3+mHxoibKk PAzJj01RfmgapZiMweSFf/Vv/qVUNy7Kf/Ov/3vy3LL+Axl1juRbv/1tvaYMM3mjcU82L78khVJW QegdqQR5XbsP5KRzovtwnRWYdrtFmZDhcML1B55mXt8/Hoy4VmF/wN8EfzxpmjSfGtM8Yu3DDrPS mDYpprJGD9jXHb0e/L0FwBg9aLNU8bPxaOhse38eZGMfiiEgvff+fMA9vi52uibjK22fFeZZ6gR0 ZpxkTSL1RbsYGRdSHxSvwehZbvgrnQL0ujSyQEcHukwvbqxLDTPk1AgDbffhgChMa4YVaUuMQaL+ W9IU4TkZChDbZxb5TuAQJ6YiH81LOz4Xd7jYKBqZ8Q6ZBdDNrgs6BwCXS5FrgpmLkTPssN1MyS+Q 7heBWfL9+cSGc4CRvHyXhfNdGWoR1CQo17bjVBeFGrzGpmxtLutGaZtcB4DC1Phvyb+kycEAcTR3 2D5FeCd0sGdqMB89fsDsUk8NGwnqTqgV9wio/NEjJzOCfnkCucXsmDlsOnoFRL3hmAtppVaSV25c k51P3maZdDSxbsXF+7KYkTOBSXnq988Ctsi14ifdl59bonbl+ATcEMT5pncEYIooFW3mk+mZNM80 amGSaUQyLJ5hyreWf+ghJeA3Cl13c5LVYUU3sOYHSIpEJkfC9ewZaCzkMtQAApcgnbbu3mY0lZY6 pK4a7kx9xUSRJwam40kSSLjrcJzAxXXA0rrVa89BlnuugW9ZuOF0YJMk3AYEZ6tUNDX7dmswb6wo OS4GoitkXOqNFW7CRHbBCLV57h2OIJuZTA+cMPmq+l4An1n4NKeTZUOXZQOQwD0Vl+3E8wuclMfU KbNjzyOLxaYj3XNZZggicuHS2GfIT3FtxCQYtTt9abbHGlTVpbFySbz2Q5lNIaeBbMJQQ+wzuXH5 FVmq5uTJWZt7O9TIVdz0ELxs5FKJQAAGE1E/G3HEn084SRTXk32LF7vK0CySMWkAnDfWSTSd2EQS vV+YX9hziu2YwoDGHlQTkD2HSHkCitNixPrIHd84s1ZexjzKiesSBKgFjwngM8piHmxWuieHsvPZ RzI5OZK1RkkdhE/jLuS22ExOTNjAvn/w8L6sLufl6199Qy5euCCTWYsE+HbbVyDRUSDU0H3vy6Wr FUmrs3y8c1uuXl+RXKoux0ePmF2IvKKMozrXSLvbka7jUWJNwUa0WtbggAAB9wj3NWlgSLJquD5k GJDORRYN76vXG7yvyMrZ6DUby4Xfw+6srW3wWezvW2m2urbEzzk+PGKJDceneCmU/gdDVgEyJFl3 6aiS54y/BQ8S5G5kSZCBw3useSvLWIIajjMnKxSZHBQknJDBAU3m6uWL8qtP9bkqsHzrayvkb4Jn ulZKySW9Fzk9TtYTUkioTUpSeMD9A58zUv8zGHmUxjlunhFEQw4ndiU2yBYN+hYkUvJInSm5Ta4z FHNJIVifVeAaztDFeSbjbl/auhZmk64CnZICOFuLOV0n4IoN9J7ADjEDo/scWokIImLXiZtkcRhE YK2Pp5x1jP07RjkYn06Nuhmb5iCMngoaEl/6tmS2v6i2ToFw62O9Tz25vKb3EeLQw65MzjqkE3QU zEE9QjeFTBVMjCdtPd9T2d89kGZnKuuXXpMXXvsS9VcfHz6W61t1jtYCP72kN7MEMU/cRlx/LkO+ Ooa8FzQ4KSxfkhvf2ZSNrXXpHdyRhx+/I8VCmhN5AOBwDU929hmT53J2rf3hjNURj02OAW0SqFEh JEuOduVP//3/Jv/Vv/kf5F//j/+d/OVf/JVU9eMjBWR/+Rffk2svbMsyNOA0KKstFaVazOjn3pUH nX258/EHUl2u6P5Py5bilHTHmuegcYl1hzWKZAsSARhhiUwaMm+ws9hDyejLJMDIpE3fEH4UYyoD ly3DK5/D1JgBPd3IVUiwb6AD6rtmnSRzNhpaKZaTIdCMpIEDO1HR6OGOj/cHbkwp8BIbsWATc7l5 QiC90CCBc8658mzsml4WM3ephKNm2QjrDoMzS+sD2VxdkSJG04yHalCMLzOAE0GUAP0aR0onZ8lV LhMqfFJuPBf2DZnhi2ZJt6j3VPnRJBhmJCqiEy7RWysXdBHpQy+SKzSeD1xPBHYlScuLnP9LwIjL XiVR3yLwWAQ1i7IiST3a1DhMVBg9A950KPGgJRtLZelurMnu4bFJKfjeUwAxGY49L8eKNy8VIDOF ctmdO3dk5/ETPgCOKgptVNfUcYiwIOC0EDVMCRisQ9A693wnLmhcssF4xkhzqZKWr7xyXY4f35Fh r0Mnls4XWN6KPgegLWbekgzffNzW5wI7E7ldkEg6v87YWJUeu/dIAyd30dfvKxrJdzG6Blk3dfiI EqE9wi4slAzU8OVcBgSjspi9ZHRsJY00hZ4NYEWGZDk2COsBpQoQrLNYJ2pokPko5UwVPuWAUFY3 2tmgx6HsaOqAuUd2EHo74AwEKdMS8lzW2GbsPp2xnfMSRVy2OXS8smCuNQZjYYTxJc5GRKkJ806x 0ebANm0jstLpcH6/TVsLXaY2JgxrJBucNyBYK7zwODjXVOwybg7AMUhyg9mRXePtjw0AWdnQZHsA mIznY5xSCvwCzPjp+VrPMENp4qKYfUx5DnRiTWOS1dc3r6rDrsqTOz3pHw+o+9cbd6WqEfS3vv5H 8uK1DXnw4LGQOOEbPwRyMRknxIkMEa736PhAVmWdET4cJfQA4bDiKCDHxotlns1OJsnAhsDJw9iG 5FVa4ABwgOtDwwBFwCfTuQh1Mo1kca4xfmbZPFeSjk0fzsaXCcvK4GYG4DhhEo03lubhoRze/Vji bkvW62WSvs8gG5LNC0baIogt1Qq6rkbkGl3YbMi3vvGGXL+yqc5rqL9Pq2OZSlv/ZhajDAywHLPB CVyeB3dvSyFVko3Vy/Lk4XucBYrSWLkI+YuyfPjhLeqbNRRQAdCDywaHAFkRlGnQkQpqBvi0yP4c H58SUMGRwZHgvQB5kAAxBzamk0m04uCskq5VZPZwP/B+UGEqtTJt2Jl+j2dYrlbY5Wql1aE0Vi/a 2KDjPfK/1teqdDh7B6cUWG3UV3nOcFLINOB8MbaINodyNAhiAh4zSMP++ZSNibxD+eo3a7K2XZKf 3TqSxrWaAl7rvL6qnn6Z2pC6XmXC/WqzT9Iy1PVzNphQYLyjgdtRu2McU9gmNs8E5G2NODVmKLOB jZmLHZhEUwpKuUYu1/Xd18DzsCv9s6YGZE3xoedVgk/KyHTQ5qQZAPchEnEzy/yyUSb2XbnUeLLg MInbx74LIOgTSmrfskVRq697MWQWNvDVJ6DCoEFVXP2CyJWviBTXJDt4KPX4mHNea6Wy5IKm7Lf7 7OBHhz+4uLP+mN2rAwVmod6Do86hPLn/UPKZsly78aZcuvllBcV1BfH78oWvflkUh3GEW7W+JqU8 Gkt03adz5LqX6hq0rTakWG1ISQFcffM5qTTWJZq05JPhieTRJjxoMttuNI4YegQKXH3uH2ivQX0C E0swaQd2CkmbQG3J1npeMnpfPvr7X8uf/em/k2/+4R/I1atblIVpvPCqfP/P/pN8fPd9eeu1t6S0 VpF270RBXyz3npyqndA9X6jKf/HP/kheWn5eHuwdyt2HD2U4iS0QVrwA6gZsNsD1bHY+lQj3H+Ov TLLLql5Yv+hmZ6ZsOCLXmtSZyBIwEL/GcbGO45lRPrDfWOTwz0dq0n47sWu8Fxk2JD/wHlAGKBnj wJcpTwTEKNgXLPE6m590xuIzkxJv0pBE2SX1+VTLcMdKRRwdlaKxDB3AiilRUZCVSt1mqELQcWQk QDgFRKwo7+Q4ENsyJ5AWSRy7DQ0wojIAIHS0KO6ZEIxNlZYnE/qWeaOhBp+OqtbW3YoFAMcMIJeH 8R5Hcy4dMwrejAT4z8siJSAqkft4NkOXvBbBi5XMzv+eX4OUtXNHI5l2TiVfz8jFtTUZqqEAiTuS c8L44mfPQR3OFWUjzxw0Fc17bWk1jxdIjOfnBvCWTEGgSKZeu++qYH6SEfN9i+70/RP9Vyvm5fWr GxI3n0jn8ImCuBYFdCOm+hNRlGeu69k66TOv89Lr5/3sac04SnDEIYNgP3TcJrbHq0EYx4yWkcEt rqxLJsKw8oIJROvfDHXzWJVSIxx1xOxExhxPRKexlQSRbQTBG9AwdCcEzhs2Sh2kakb7MKw5ahRl Eb0xWzuVFTWq22sbcufxvnz86Inc3T+SGTZPBWKhYwUikDkJE0re564PcuuSkri7D5AVSatTGA3G 1HtCg0uivYbMQ1/XB84Lorp4mf6bHRMbD4YFjhaZIGQukvFI4LUF1GTLc7g0MkyQBUEnLkFgbJ3T mXTGRYtDN2dSjFTvyPsJsITYbOSyicx8eQ7guQYkSJ3A/Xlxaj5gG/xAgBs4sX12F2ZkXQOXQrmu t0EDEQUWrUHE8hE6R3MffShv/d6efPNLL8tffu9n5BehG3Iy0M8Gjyl9LlRKUcwxODddNjSgnGZO z5uXC3h+LrDkjYdOoFip1aZzTFwZ3LOSTWD7d4xSGiVVjA/ZGXY56g2vpESLKoPPcnNExX2M5Ip4 bmmbgwtHAxFVcDP1/nROHsnDTz9UQDeTy5eWNQgZsqMYZHcmftgAkpVyuSA7CmaRmfiD3/0NeWl7 S04PHrObPwga0unu6Aqf6vtWpFpDBi1PPUY/0nWrx7h/6wN5pMFdX4FBrqy/m53I5lJO6kurVNeH zd3Y2OK1gwuHc72wtUG7iYkNsHPQjsPX/f1dfgX3DVmvpIFhe/siO9cfPLhHBwAAB6I2tCyRxQDF AyC767pY4eiwLgfDnpWb1LlgraJrs91ucs1V61XaJoC+ZEoDngUEq/EMoZmF/Yy/x7nj+SfrOHAT cJAZ53xjD0PD1YmmLfjHEPjLes3f/eEtuXN/KvWtQLZrKSkFyF71FXCUKAcCmcme+pIT/Yy9k6ac 6Gdj9iSDX8e/iyiNcyZDDZZM5sSybcjsonkOGUvQV8BdazdbcqxBGCYbdBQEQaswnE5oW+oIGj1Q i3Rt6bqOAqNyoMmhlMvSfiNDAzuBgA7XAY3QnJd36zDkvkOFBELfHPWm+9XXi8jwWGMZIyuXWpOg uiapK3/IjtdU52MpTk4UFC/LSn4i3vhE9sdqcxSoThSwtKdDI+r3ZlzPHQWdJ4d7uiZbUlMA9uJr X5LlrW31F2mO9IMNfuWNr2pgcIWZq2KhTC1FTFop638juwrJDRRyUhq4YYRZT+1Qu3UsZ7ufSvPg iZQrev67B2q2oRQRUzEgh0kHyJZDwidts3D7CoxAh5pBWDdbYsC1US3JUj4le/tT+eTXt+TTu59J Rx9raakhLz7/qvzhH/+J3P/07+Rg/6H4B/qUA92/kErSk7x6bVu++NbvSOXCFel8diJ3IYivz5sk f73XJ0fHvNfosI5Dy7LCtkJPcuQSBZRiAr94FnM/YZ0jwQQFCXQmJ2u52+lSNoQZYl074PQbdzfN UXVlN5UE994y1C3Z0n144sbgIdDH7xC8YF9RP9OVRq3SdZ5QSUYqzsWDCQ5tlCN9vcvSGbYZz4Fe ivps7Aa0EkgqwEmOpKybtVQsEkig7p/IaETIqMRW00+aD6yZIXYZo6T8Fs2bFaw8ZicO5EsH4sq4 02jsSlQzi5zFuh/xgiOCHgo6o+iAYjev00XNcF3Tz2leWHzNRzAtgLinMiwL2bc5WPEWHLiH+zEm EJkhS6iOoVJYlisXLsre4akcNPee+rxE7iEp4YDvR4FGaInhPoWWuUnlLKMSUtYAkzHS84jBulVS XJCh47QFToOOSuaSyFvoxtcN8eqL16WWncqhboR4eKYL3jhzmHeYW+CwLQKUpAnh/NdW/l2UafFc F5fdt6fva/I7K0Uzp8OyZugcJDIdhRwimrz0Iv2aq8mVzQ3Os/QDR8ZXw9dVowv+zRSTGxx4HU9w vBSjjZyuw3KtTjK8OA06cZMZqBLPUmBMAxvgPPWY/hS6QLi/KXY0rl64JM9vXZUXrzXle2+/Le/d u6vrukPhWRunYlm2pITnrtCB+s8B/a6ZIfknjjwLJ4CIq1ItcBPmCxgZl2Z36mzWmU/lSDqZ0PYO 6QI8J288ms/QNf27EfdJoVyZaxehVIw9Bw03lDGTY6U9K5+CH4ZgyiYLBASmUAfnPgtn8+PTaOBi SPJHphn7K3bj9WJKmbCUMx2oExtxn61sqJELORxVsuqYe2pANtaX5YXn35IPfvl38u7P/ka+/fU/ keeufk8ePtxTh2ORZxyday4mRHaAi+PTEzWKxh2BPhJB2Hg6X6d0dK48nQR480wxysHsVI3Yuea5 xo/kOQIggssCgwh9L4ozIwtLnca0a7yYuf1kHGCsP2ZGcIn6f71uW45P9qV777bUCr7xm2bgtXUJ qv2Z6+6tVVmuOT7eV2eWlu98+y25fGFNzpr7Ggz39RxL+qzauubz7J6rrWRkdVmBjQcenNq+kRrv VMyOxZbeb3SuzqKy1Epbkp+W5ObNV+T27dvy0a33Cbr2d54wa7bcWDHJg45x2WzmboPgi9/rPmss 1xkoICuM9YNSKhzDuRbcEsEUsmq4x/h7OBmsVwCdldU6nfnx7r701GFhADgazQDiEn4mOUCTIec+ kjLguI84DxwL3+OZ4ZySJq5IzieeAHcD02HqxixMUQ5lGp3qeWVk1FqXn99uS/N0V6JPSwqu1uWF N/S+lVCGqqot1s/VIGFfbcjO0YmcKKCZOeoCKknIpgy6E2YIoaPpi41ErBWrCmbLDAShfIBACHy+ vbNdaZ8oSNFrYfchus57HV2nHVlZXpIqxi+NbEwgOi5Hw45ROiASTAA2Y8AO4VnQJfBsQO0Qp4VI 6gg6GKPZfD8g+E1rgJCSiWRSNn1kllmRaPlVqW1/W1L9E0kd3JJypicbaB6atSgbM9YAoNMaqF05 tRIwpIT03/54wN93d3dl/2BHLj33lrzw+pckVV2RvgZI03GfzTzFwpIGPbFcvnqJo9gglBxOfQqF k64kpqEIibreKORILsxmraeH8v4Hfye/+sUPqIEHIIsMYKhBEKoDw/GMdgd4C5IoEmeZYc+mK1QI WFm5ysAhraATe+zT/UNpXLwmnR1dk9ibVV/u3nlHBsVNSc2gddmWFfW3F5djitk//+rXZWv7Zb2O otz/xS/kx997W54cagCRrTCobrVPmKBAQIL7gPWWALa+09SEXUhsN8S0YY84UkufC0rSANUAXdgH EIIGiIsdPsBegiZjq9VkJSHx9fg8jMe7dOmSnOh78ljnek+T8i2AIo4Zu2OgAzzhmOLc8N84D6gY 4PjYowj287pGTw6P+DOAOwQfAJyJfiizeJnU+axNLiyWSUNpKMoWvdFoFafSczJhAY4+NP4INmva swHsOAqc+Szp8ev76G4AACAASURBVNQbgqjGAF+gN6enkfnAQApuln4Oxg6pr1Lj2KdTjn10vkHy gLlpjXrKPGEIC3KuqZ8m+IjioUBHDzpxkBcAsCPfwA8kGbXFTo4oPpcjmZdTrA5NkAKnEFkjRtLU Ec1MTiNJ96dwHTNoBcEBKsjSTSRQJNeIIrtRltF0WTq9M4rGQoIgVmeA8l9KN+4E7dkoDcD5sVM9 4+6hnMt0wJkEdh6xNWay4xA1I6s2I4UXc4EhY5HOFqm1hGwljPp3XrvCkSl7jx6r8TmVjH4e2v2n emPzqYiDnJPGhsUMGnhDeAWYxRol5WafHT1JQ4Np/p1LqCR/f04K9QneYaRQ7gGAC524akrPr6jn W8Yw6sGJrKwvydUr2zSuUMlkI0IeLGgb+4QFiu5TgH04c8AJOCaIHuYwP06diTiB0MXycMo33qXn 1ia0mHzOFpwwI4duIQBx6BjdbNRl6a2vSUMd0U9vfyZddaBeemayI4IOq7E6f5t+QcAI6YLQRsAl cz6tWSApq8b8fFN1n3HaRK5UYdftUCO+od6Dcq4sDUTkyPC4Addcg8wyYsKJsfLQUAAjhT2FLBJL yjPHFwMpfxJR6wmK5mUofus9G1E00iMPhDNzkQ3NWActzg3inASM6DBlIOUxgkyaBwjY1QgjyzkG aGJ5K5J82kj3u3sHctbqWVu9OqhCStdULiXDck26UV6mxwO5/rWLUlq/Jn/23b+R/+nN35F/8Tvf kP/lf/23ul4rCtytaxdZe5QpAzdOCcCrCEV1vXPg4qQo95AynTbcd/1vrAXObQasdJ2qSYc7AjoQ 2APu5yllYLLzkXu6FqCfiBIaRpEFeQYFKPSA6wbh14Ct6Oh4G7PeTEFwNEvkcQfG0tPA7PjxXWkf 76nxLEkOoE5ByGyEXDAEkDN6XchiqvHO+OosWvr8PPmtr31RvnxtXQYH92So9/bB4QE1Dp+/fFUu oENUryudK5AT6s3O1P7pmhiEsjeY6T2uscQfDkZSjXryte2ibFWH1IX7R//422rMh+q0D9Qx7xGY QzsOfSlHT3aZ8Vy5cIGdlaf7LbXDM5Lwl6oVOTw5lcFpmx2lxSpmbSoo0WMWAWCW6jKK+nJycEjb VFJnE6uNGzSPMM9MqstrbCY7PjoVCG6jAQKA+8nuYwLZzZU1KdUycnBvV+KefuZShR3gPXCGh30G VnB0vVFPA5UOnWExX5Fef0Su7JSBSkQeGCYNeGrXQ9rhvNQLKfnwaF98lKXiphy//QtmHgsvfl13 clEB21juPjqSz57sGbcX5PrINSfpejltnxnfFOPC9BgF3YPFvO6dQpHngb+BzXl0V5/1yaGMFegN +z3u5zK6C9GsoKCo4I+krqA7n/HZnRyy29VoFBF1RyHOXeAAeVBfIK2TCMtWlqoiZwMZw7wg6yyW 5Q5SOYqd59VmjlNjGWHiEeRH+mqDKq+K//xvKEivS6n/qeT6j8n7qpfq6osm6mvaDHpnLikyaE50 7wbSGQEwtGTYPpBdDaIms7y8/MYfytabb9lw+KmVGjJopAls9BzATqcLAW7rXAelaOCNyNUCR5zd 3B4asYpGQ1GgOtE9VFl7Xs5GP5OHGlAEai8Re4VBxAkYPu8PujZzbNzw4imTO714LOk8AvIc/WhT Adzp0Z7eI6y7VXIJ07qXL2c0KPKm0sgqWLpQl+ra6+w6LiIZ0FVI9ziSndt/rdd5Ir0jXWc9keKl 69KvrZP2kM6rnYL+JtYvApKTlpUqzzSoUBu9stJQv4xOYV+ePNqRlaUVdcVjUlGg73mme6mh67rZ OpKyBm7o0seEC9hPBERoDIKfRaUBmbBed0SJnz3dE5trusfR1Ss2kQqBzcb6iu7hAwZ65OQpsFzV fXZyuM/mSIgoN0/O5OKFS3L//n36dFRfkAxD8gqADzxUBFqwgSsrS/L40UO+D3NUM4oHUiRzR/FT jjqTSc+lDJgdcr+z8RUTJyFhfKqZ49AFruORDgqwaGZlVtZ5p6ayD+cWRpZOhoMxhx2SX2cjowLj xcCBF/JSq1c4KxPgBVm6ucSFZw0UJKjGniSDr2bJOUU24zJ2BNKnukedZMcc0M25cgvlYHctHHkV Gd/Id6T3iGOTIi5UGLhrlzZlZ1+NafOU41NgTCDEys63nHUcRqSw4as7f6dZ5YmJnEaOaBssdBvO IjsXjH+ZkE+XZVar3xnq54zk4uayvPzSJZl0W9I+3ZNRv8noGzNe+xAaDfT8mD78vAza+depS+su ArSEw8XMRyLG6zJv7G1M0nixif8mc1btbb7TLEsR2PgxVPU9KaH8qWA0i1JpYPIY6OgplnJGCvWN uB+wtO8TGHL6AUQaQcxHlg9SNVEy+ixZs3quEMJ1I7BQBkMmMNR7jdl0BMs2u4Aba0kjn6+8fFM0 npaf/uqW3lsFWnWNUtVgc8ambugg7TPzE7BsH9Bpek4jj1yxTECQCTK7hOfNIwkYLdSLjAB7nJk6 NfDNOXwGkEGYjx0Qzrj5kri/kG0AXwj3gZMlADocqI6dKLdlnM6zefgZHKq1s6dIYeAaxvd6TgD/ vI/p9LzcSwAO0BjbMx06OQWcJzKXUxwfGbdyQ7r3j6UHg6/PoagAFfIRBXWK+VpdPv7ofTn4wQ9k TaPQX773oVz68/9HvvP7/0z+/K+/L7fu7Mr6xiU97oSZPux3DvPmNYxJ9EUmEGVcGEN0N+J6AUjR pceIZqHkb0GDOGmVc23Dxfmn873rSsawa0EAoItKg81AHI2mnCjhc0UEbPwAVy+tTjocd+Vw974C o3vqZMcKvBocjQai83QYEYSnsxOugWyuyNF2/bMTQWPsN77+mtx4riFnZ3tSUpAbpwpy5+1b6ljG klLA9kZ2WQ1/QJHwwM177Ssw98OKbK3MJDNF88hMWpi/eEEdsDqmrVxdwjLI5jmpqx082NmV0emZ BmppctPGurbRjYh9ikgd1w+jj721efkKvx7tH/D3EAhmw8LpHgFyfXVZquWSHB/aBIZyucLvMVIL gsE2C7U213bD3yY6WmdnXdoNTNHACxkOBB8NdPDpuoKoMDhJ1XqDFYVe36RGEJxiLfb6Qz5HdupB 4Hk25t+hwYZTgJCXUud2cHQom6tvSKQg99GDT2Rz05fqakYB3Jm8/evHcng6Jv3AbNZkPl4OgRzK 5vWlku6vGs8boBbZZfCbnhwfSEdBHjJl0D9DMAUh8nK9wDFHndN9XQsTHqPaqJoPgx8YWyPYzGWZ kaVhQImKf5zmJAbYQgjCI/ucRrNDDrqGS2oHs/oc+hgsDi6I+kIF7B7GxlUYiGDYV2nzdald/bIM 1HZ4Zw+kMVbnX8lwXFc4AaA/ZDckdOyGwxGDoaFMZHDWlJnek9b+rhwcayBf2ZSXX/m6XHvxi9IF 3cK9bFy0VRfY6Q//krZxjiFpMNa9H7vmEOjLoXM6+v/petMmSbLrSuy6e+xb7mvtW3d1NRqNHWgA XDEkh5LNUByJY+IH/RGZ6S/oP+iLaJoPspGGYxzROCJNXEAMSAAN9F5dXUtmVu4ZGfvmi+45970I z0RPtpVVV2ZkhPvzt5x777nnYJ5GTjdVAdv27fty9+EbEg8PpT8S07jDbokERITmokha4PBGgd0j dksGUCJdcCd1ToX6vDYaZblz7x25t7UrWxocwNHn4b3bsrHS1LVVkakC67YCnKdnhzJo9zSgnFry pzDVuVaXin4WRKVbt9+Q8q03ZHSzo6CuQ726i8uuhPrctpvmW32mc2lZ5/PRaUdW15b1vD6TUn1F Ul2nF/0+M2Pnp6fsxIZGK3QmNWpT4GVe6bhm2GCBW12uAXxB+3Qgd2/ckucvnjErxjNAgdXO9g15 +sUzuXHjpvkQM5BoMLO3rff6cm+PlndFWH61LRP49OlTrmGsL2Th3nzzTfnkk094XWbFOSWYA9DD 3z6ruLS8jiSGZTF8l6JF56ZOD7Pr4dSXmYyoCfX5JCewa36CRjqnPQT4bGxiMK4JFmgM0r4rFSK6 ZolTXwNNGoqpAgikyIxVSXQFQRLtxE0FcZVqgS3e0ORiFiYwaYBgbrh6VT7D6PcZwaKVXgyQhdni 9Vf5cS4TOe+j8+9ljQRUZwB3xd0nLYgoUjuhwCz4aIWtZQqQninaR0dU4urcMOUVjUSi0PgeHF+X SaKYMD6taBZQyLz5LkL4MrI0BHJ3ZgKiyHyiYQGNJm/fvy23dxtSSc+lr9HHuH9hnDLdMKcAG5Fx dXBQABTn9eWuf11v8PBzID+ueS5cfqytoeSqYLJ9FjoRpqbRowdETefSup50TZT/3CaSlEKqtQPw cgNHV5DTDMNhnok1AjixDL4/MqzsTkQWLHadrBRbLxLA0votppAEgZ9x361lvoTyPcRcdRweacQU Z28p8O3LRwd7lI4IdTHHmcl2JHxmgctOZwTgDHRCcR2gITdEBCPw1AWaT2Mr70K+AbIjWIwNncPg cgG0TPS6SpkJS5r0iud1ZvzMkV67QFkcICZ1qvCZNY2YmGTq+FpYA5krpZbI40B5ix2nxSIpEZkP OJDp84FY6tZxZC4i0KRiVjA0wIP5ghTVGHpx45gZheryhh4EJVrAYdtHCh8Cs2sQf1Xgu37rvmzd fSLf+MpXZGVpV/7sz/5Mbty5I//Tn/4r+Z//l/9VJv2hrKyvMoJNEidCPO/QS6ixhOcUT32HcDrn fUi0sM1LcsTk/HzMz2kflNln2B+UhUoKCGdT6xDmFqDjOZnZ3EGQt6KANNWftw9fyPH+U73mC1nS Ax1UEsybnm7Ug/7M9LwiBKJ9aWrggTJSV8eiWZrJ97/xjrx1Vw+Eqa5DXc+X0NTTw++r3/kXUtT9 LOtdsEuwMCoTDISx3rfOd5SPlqtDOe9NFRjpPJ1oVN+K5cmNTXn4lTclLX5TolZBfvnjv5fLkyPL vmoAsLKyqge7acXRlkvnFEo2CCDQsOC7VDGW56dnnF+oaGA+wzQcWXz8Gw1ByF5AJ29ZD/5GrSIv Dvf5OcurCvIaTX3mewRhtVKDDiI4PADiEFwgewgAiOeL7Rj8IDZBdDrMhNb09+FWc/j6kl16zbXW vDuP1JqZVVFQdqvq+kvE5GjMrzhQgDCUpKtrYQQ5k9eyvvkes0G//OgL+eT5kQKEmoKnvutUt/J2 DdzYWp1cT5TOAVJwzS/3Xihwa8tQ1zw4bgDxFTRVNez3puM+S1/DroKAUY8yHmhwILkdmXGU29BE EzBJz8AUxxgkLbBGkcVJ2Bxh3d/gwKK8lyoQnw0nUtf9rlhpyQCB1DBld2lQHMsgqUqYbkrr1jek eOeh7gNdqR59Ls2kI71iLOs1ZDbPCA7AtUO5b+I8o/F8u+NzmbQvpHtwKKdn+txuvinv/OBfytL2 HTlXhFUkOnN0mDB30gOkCbcct/Ys+GHFSizYgnXFjEFOkXMG4uwTDfKqS9uyurHLZrKpPtfACk1M egROsB9rH2oS0OkpYU9HJyiM3+HspOCrUtA529KA9exS2oXXBNqgSHzxdF8+0/WIpirMO0XdOsZt qeN51CH4HbHxAIAZDVHnaPw6PpKizoUVfV7wTsVeX1/dlioauqDtqPP57oOJXLbPmYSip/SGSUN1 BxNZXtmSF3sH0oIMiV53H8L0q3fo4FCrhPJa379Rb8qod6nAq6ogLpTj41PZVdB18PIFgx9wslEK vXn7ljx79rlsw9ZuOiP22d3ZlFev9mT31k2+BvsfvF1fvtqX27d2uYahzQicsH94KA8fPpR9BXrb +v6pC8wg2A1uKy0ZRThX7+heCx/2gqf8MIDFc0OGoBTNI3c8OHJpEE1nZkMDSQNJF/plHshRDNG5 PYTkV80YoeH1qX4fUS8yW7GpwZkXIcjUiYnDQiU/yYzADqPuRrNOnkGamh0WDlTKPcSWCTTLplw3 ZeAmak7XK0/kty7UxaZvOiWhBEGeC3WVO0aZMPLSrLzGFl9m0ibmvdg5lHq1Lrc2W4zMTi4HitY1 QqQe1Ywei2FmBwrfCwsFWTmAMwAYWQCh0HOBErOCidiZZ9o0aBJY1agQ2YFdjRjT8Zm81ocawgol NL7AFJyoNGA3IMZqNvlS3HaVvB+FDlRnJGGKI7ez/dnxG1N/aLoMpeTlToJw3t3rtbfMXxTRWUJ7 LYwXeHoh+WcmX1HQscImiywQOzYLADheTiR1Gasp74fdhOC+QfWcKuvGgwIywcSHbM106mQ5MNeC hIcsLxX3h6xW0WQIpkPdPHXzvr2yJL/7za9JqEHCzz98qmBQI06AaJbh8WhmLNOiy2qW2YGPMp4Z pScEYRbcpHMAgY3bOEATWj9VNWJDFgrlzSixbODY8b54P9Bnm5rNDqyxcL/006PfqJVcMTciZkad rE9q3cqMo8gbM9BL7UBmiSNrsnAZVuNluuwlLNUAUuPMAb1o3sEdumzWbObNySFyW5abt+66zPmE IIGt+TprWyubclN//0//+E8VxD2R+A/H8tWHj+Tv/t+/kT/47/6t/A//4x/J//a//3teFspZ4P+B QE1uXsk4JqbFaB1gxaI17VDkOLTyqvftnbqO0wUH0a/r1JWHLVPuGxwoi8MSrTXCzDLXUSw2hgDO WHcAw+2TFwpk9qV9/EJB9kB2Vpo0owYZG5ZTABqRjgNLuTovlhVAQR9vdHkqDQUIv/HdJ/L44Tat hs66uu7B/dGN9vEb78gPHzyWcecjefb++9LWzXbMzBMy0gr2QerX+Y+S/vSyq4f2QO7d3ZWvfv+3 ZOn+OxKH2xrcrMmLv/5z+eef/BepaQR/MRnwz92tt6Sq49PeO2QX+m3dzDGG5yenHKe15aW5zAEq Iqhq1BpVGencH/a6zBw3lxoKDHoELVjWIH2DB4ZMFWbqkoJvjD30t+jVvFonALs4PievGZ2uNRxs /d6cs1lrNuZySXhOraUlHeuEmTlMuEa9xfeEJh32RnJoE5/xNgoEzL+tCy9zHaUj6V0e6mtjPehu 6uHWkQ8/2ZOhrpMsgCxGkVxDXE+rtszGDSQGRgpgeu2hXJw/VVB5KR0c4NMJQQDKVMiKY3VNJxD6 dVmuEawBS7K21CRAgTpA+7LPbCEpMk42qeAqEdgP6EZSikh8R/bQqRKSOoC1XCq1JKq1eV6Mkzor EbWigv1spHtfxKxZ697vSKF5S+LLZ7Iy/kSD3YnuRyXpTouyf3DotEpHXH8AmDOIb4/MmWRw+kr2 Xp3IeFaRB1/7HXn0jR9KtblOAeNsMpJF7iJ01ZTQ+uy5PQZz+gbpDDg7A0cxSv0ZWgCbh59Fnlxi IGx16zY1EUsKQJBAgNA8VSs0aEWRHJQpNLdNB5Dowf6ugVgjlbpG3fVaS1B/HrahEzmSE332nZPS nJNMLcFqmd2yzSKoCy3ukciYhtiXxaqCiHuTVkUuNAjHvKzos6mXdS8s16WmoLCu8x7WVzXXuEJn ESesW66W+He33SWwW9J13T43sLy+dUvOOgOeo68O9vl71H7U9fTGG5vs5kVz49Hrl8QDGys7zKTd uXtbzo8PaQoAbvYrfXZvvvUWfXQB5E4OXnO8b9++I59//rk8fvxYLiCDkkGDsCgfffSRPHr0hs73 DoMH3P8nTz+TJ0+ekG+H/Rll1D0FeABwAHUwDiigg8/z4XwmxqsWUyl4PGGZMsJrQit7sayDA1lc dO/KsfnmgFQW5UoKAPPMTY18jWyR6/rzkiPmBRkyGsB7It0IoUlrdriq3WXEWANxgTeXpU6QB2wy L6P6JgmWBe3kssPdHWBX2i+/BOjwHhITg4zEMpKReMJ7TO032HuEpaast6oEVJVhIAOkvMdT6mkt yn+IMC0CisR0ZRLXADHvkAVwCgsOGIV6UESysl7Th6Vov1KggO+5ovV01BEU8Wg5iiwTxhScotB0 fnDN5dAkSq6Uk3MZDT9W+a8rQr+yyHZ8WWfq/Ht+rPNvho0B0hJpqIdXzJIfOgujokV9ZsdmXEy0 3yMbh5JHb2Zkd0RaOEAxHygGDT5ZPHPjYr+H6eJbs/2Bz5wqOtGQddN7L6JcCXCji78MUIO5C/sz fd3OUku+9fgt3RAT+WjvhJtQHJvP6GyUGU9tZmLWki104hLwMFFyBAUAmmXOazd0kiPw/0XXJbNr aTDXQJsl5lzCokxm1k8IXhDEwOgam2PqmkUCr5/mmmNo9wXeT2ggDl8cv4Jeb7nqmoScFpOE5oah 6xiHIjYxjBtKu9j8UB5GZMzuyixx0iqZ03g0X0vrFk2MKgErqkJZVpd1o10tEhjX2i3p6+H3xaef yY3NZZ13mfzRv/lj2bh5V/7p/Y/lt377B/L5wTP527/6lW58j8l9wriyywp7BzKCyMS4gIEWaUEw L62H1CFOrYOxVJoT4fOSQb7hhhk4WWSbMwaMmdmQwcED94tykH4fXW5hCA/YM91wj2RwsSezYUfq pUS21xSY6DVe9iGaqgEEMjslE+iEdlexoHNpmNJfene1Kt/7xmN5+GiNQr6jVA9d2Zb+uKTvs0tp kFe6AR988r4E475Uoiq5SLBiqmGhzEYy7SrYuZjImgbX7/7Ge3Lnvd8WWXtb5/qKFNpHsvfj/0P+ 85//laQ1y2BdtDsEK+sKsACMQNxGZhc8Hcwr8GZwIKAEk3dgQJYO3LSDV3vMegFcQbD3DE1Fvb6C lTrLrZBN6HW7zKaAqA0v68Flj2OKMhOAFQR8oQ8KkjbOiBNn5dVsLVPRANmqUd+DuhY11PC+AAkW 4CTkni2aVgoMriY8KyxhAO7QzCkRQFvy4PBzWV6qMnP98198JicnfWmAp1bRQ215l/MbARTLfZAU al/SQqxzoQB00uaJUdGxD6DZxozBmB3U0A6D5RzvCW43CghXl5d57sAajnSHQkReFOy36nDWyRZU Ify7VLM1j4gbYDl0Dj1G94H8z0ha1SX6u6bcC8a6JkcyCzekuPMdKemBno1imb78JynHe/qsTBni sqdnx+hMTiCDAleeyGhIaMJAQ9h40JGTo2M5fHkspbU78uQ7P5CH73yL/Nb2+TETB41qk92YOHdS l4WmABQSLE4fE3uKie+7xjbxVRhTSYAkSA98MgCocoGi33DUuHnvTflVfV1//1yxQcou44QVN1Ax KjzDkK4B/w/kffPBiBylo8y1jn2HcjuQ9AmmPKohgl2h8DkEjoekFRWrRaerN5ESzs0YZd3AMrGr G7Jd3ZAVMGc0kIqnI/LMhu0zab/usWPWHFuskYdakrCBazX599bWhtu7TWCXsl9jEwhGcBKhU1fP MZRYq6tb8unLfc6R847Os8FQ7ty4JU8//VTu3bsrHfC6dQyQVYS49ltvvkE9xzITVYoThl25efu2 vN57qYFWSy7Pz6XdOScgQ+kU5VQcowB2Dx484Pdu6c+QvcP1wG8dAO7WrVuyv79vkj8abBS4GbrM irC0Y5EGyJ8stDrSPervsL1li7Q71GcEZYmzSA+cgKMpVgOMwMTVIhMTumX2IPTEbqC6SLwuF8ny TqYCkQesTMChoa0RogN6sVrK1spMwjLXXBLEyXTkN3lu6v7eMqf0lfoSqgEPZn3keiZOxPXvGSAi OE0J3Lw7RUB+VMby3pC2MV2aKTc0bKkvV3SSldiC3JmZar65DsRGis9yZaCowsVukiExF2GFfAvz m7ypm22xBLuXC242sFGJXNfvFPeEymVoXqApzdhdcwZCqWJxXsbNg7e8Zl7snA58FOSzNn58rn9d B3AL3TTjQrIRwggWHOXpLKXdSsz+h4gK+Fi8nE+uLDoeDuktSMub2JTLA7FrTwLHI0wM+HPkUleG dJkjixitHMjv6TgUpoltLLOUPLspS3JGvkUvzwybmw7Dji7mb2Cx9UbyQqMy6NKlEEkGNy8tWJOD 03cD6KDNXNGXlU3TBybz3KgKpvRdr9Tpi4tFHsd2OMGjlONHfTlbMSD8o7EE14YMI/6fPrpOdLag 0X2QebmNgJlScG+8PRzmPDbfUskFCok1SMDyDmsrjOy6mTjOTCgSACwvqRO4zto016Ht2kRcI0LG 1npvc4Z1jAwMuiORGfiz//Dv5N//9f8l3/rGu/Kdb31Xvvned2Vl56b88pOP5N/+8X8rcT+SH//D T+T2vfuyurYpZ+dQVq86Kzqa+83n1lyZHI0QmbAUh/FnZ3ZklmSUI3KuFn48MWemmG+B74JNWR7G nEJTB46uKQ7OUVeGevjF+qerB93lxams1fWgXilSXxC8n8vepT5P8/CsaCQMAZbZuCNV/Xchg/L9 SO7dWpMffvu+PLijQHbakXJjWwOtN2RyqIeGgp5keClfvP+PMtPPqUV6iGvgAju8EQ7gkVCxvlTU g2R1Re58a0Uevfd9ad75ul73jnSfn+ifv5Duqw/ls1/9QmbFhiyvb8rx0YXMFFg+fPSmgoK67B++ lo6OTV3BGcAUngXM7AGGN5wAMLtOdWxW11c4tmenJzpWsaysLpsG1WWb5bnV3RsshR692jcApnMZ vEeArQFEqPU9wcEDrxm/g82mWa8RbPcVWCZ6aCLoBnm70z6lYn2zsWJ6V8OuceoUxKEpwoDZ2PiR 2CpAkdB5Dzsr0gvEGhPwVde12O1dyPnZkdy89Y6cnB5IoK9bXV6SZnNV77NJvhnWV+9MgVv7WD// RA9f3PdE5xHskKrmrBOblJWtA+PjAqSe6xhBexAZDgB4ZI1NdNps+OpODBaHs1crgLuKaRgWuC4D t34YfKHrvFRiYI2xRz/BcFKiMLYEA+libdeeSHn7G5Ks3pez3kupfv7PspZdSu3uhgygDqGAIUXH um7uFwr0QQlIwplizy6pDXhGAHD7+69l89Z35WsK/rfuPpL+qC9x91xfj+vRYGSAxoTI0Qhc8oPn Yej8oK3THneKpkTL8rsdIDAqx1jHEXMqU6CF8YKO2wxNG/Vl2Xnwjhy8eEpLLIwhdPrAmWOgDbWF GYKmmQFDWFtXaQAAIABJREFUx2lFrg7nVAmgF9UR6qqO9N81zgnJBvqsJsQfcKFI45CJAIBsNO1h a5pOFcSFVSkvb0hWXtX9oSFVSKEgg5tqQJJFFvjpXjXUNdKjP3mic/ec+0u7EM0N69kBCv5esSy7 uzf5e+D+tpZWSIsJSlXO302I8uuZgXun7eAU1IcNNsSElaocnpuI+Y2bO7o2T6Rab+mZ0uf+v7ra kpcvX5LicHL0mtIyt2/uyicffya3bt+Ug719WWo1ZGd7Uz788ENm3vb1ewBo4Il+rsANHLn22RmD QDRmdDuX8uZbj+XV3gtkJgM+sDnJP/XWWwl5WtQzoVVGwsNlLpznwBFT3ukCPMWpSYSEWATe/zEz MW1T3S9wQsX0dwx5WKOUxOoixTnNjwwLgWApE6d4bZszPc59CRjXGi3AhefEeBYV0b5Ly2UeyGSL JgY7CAMH2PL+oj6lZP6JHsRZ6SwkeC2YGxPtXPxhFE86zIKgY6QGYnhNNwWWmVO+DvyDWWIdn6a8 HLDcBN4c3g0ZfnQLo+tNgzqpgm4VX2qEoYtneilljUQwYsho4XmwKxEcxLRokhKMEmfWCKAb7CSd /hoQW/ifLsbNZ96u227lAVueO3elHCsekBufHOCd3rkoP8XZvDwHsA9+5FSvqRSYyTMvjeA9Y4km BCmZ8ijWJc0nk3k+VGhtFZkJPTN7jF+fZiwPoRRNmbDUAGzGe6BDsf4q88Ics8j5/EIfCOXdko7Z rh6E33x0X8Yffixtff1oBhBQtdI2urJS7oDWBQsemZPBCZ1lD5t90OgYG0kY5T98BiRS0sDKmuDm kONIPlBK/gfkDZCdI+8tcyAcY0P3BJNbYKe2KwUSsNjMd7zDlM4mSWB6emGweE5eIgZWbLPpbC4x UiqW5xlFDCDlRSMLIgIHmKkrl4Ys1aYod+nERFcsgrDRCJIoE1nROX5je4sk+3/825+wFLetUe2d 3Q15896mrC9/R371wafyJ3/8+xqQifx/f/ePCgo6srVzyyRkdPxxUEVV6+bD510JEJLMAbqUm791 j8fXsnB6n8VgnglOUxP5tSyP7SfFZEwpk0GvLf3uqQwUZID3VtVg58ZKhSr14CzOJqbliFI0+a8y lcLM1scSMoiTod5HIg++dkO+8uSObK3WFBD2pDcN2E1WHr6muGwl7kilF/MAi/A+1Zgq7xmoAE10 523J1vKu3Ni6Lbu370j6+LHU9Fran3wmx+//Rzn69HPdoE+lqMHFJGrJcmtLA7WKHBydkPuJbBZA UPvSHBXga40v+JyiAQNZOHDCjhSwoQTX0gOjoQAMBt8o0+DQXFpZoR7bZbvNvWtpeZUHvAn8TmVj e50K/Bcn5yzbwRMXn0v9OL1ndH03W5CfQuauw8Ab2SPsxx1XwvVgqHPWoexOjbIedZflGLrnaNzl hCLzQrCIIA9BKP4fmfnO6aHOE3TaR+Sw7ijY2tXDcBZrwDRIFCC9ZPn2TIHeeNjTZznQOavgrQCp mIwuC+hQD+fnhNEWev0Ouc1wk1ldacnGypLtballptlwgXVcsqoUM+muiQYSPJHzVUbSo6qHeOLW DShm5aJl/2OCwJZOKt23FcTD8zVYuiv1G9/SgK0mrz//Bxm8+kgaW/pLtVCGGkSWuqn04jOup1Jp U4O7jL9/2TuWQOcU3GDe/9VnMpmF8vVv/YE8/PYf8vrOTy84L8BrnOj5MJpagDjDdaZODD9XYaF9 JQDt1GUNfTLEUXoSRt12VoHLl2CNTGEcr/uvApehjufDd78nL57+XL749ANdH7HUylXuvd66C1nP EgSWQSvCuYbubGTesglFy0N9Xb22pGsPjVwD8iKtmU6vaZbJRD+/gn3O8faKkYmCo9ScVBoSL21o QK2BwgCbL87D1K17YXUDGbRMrxkACQHF1sw8gjFex2enrtFprGvnhONyerTPPRtfzNbpnA8VxCFD tqz7X9YoM8s2GjpxX91rOmfHsg6uqs7pbX1WyN6t36ixgoCsWb1clOHJGd8nKldIT2sulfUZfshm CDTS9HT/AHD76INfkRuHoBmdp2+//bb89J9+Zhk6/ThwklGC/fCTj03K5OSUWfCC3wzNT9AR03Pa WJjw6NzCNYPbxgMosljdG9bzDI9d+jtxBq5iKYTMkjIW2WBTK5gBN894aFS5Eiq6izLHdQpZJgtd I4EDO8wmWEgROHBGcBVdLRPmuy/96zxvz/IOVwGMxyNBkH+PnA6as5syDoHreE3Nu9VS5yXOGKD+ YmA+oqkidTQUNGEFBe0gqHcXAklKBahrMK2epN5WysSNqasGM3Ts/PFAQVtPD6CCSXZMR1zI8HRD wwk4iwBviJKqNCifUP29yK4nXRAADlFIc/FiGl253/wY4SsMwjmA89lLb1Vm3m4e1C66du3//Rhb etsA3qL8yntzZHbcX08j8tqgxnR4SSMMdnvGRrotugwWSvvlSo3zBE012FlQAokpKD0zZwgj7M0p AGjkQGYS3qyYlQDBIOIiS4bDA92WniwPmQBMBESUkFhBdqCoc7qq1/Tk3m056XXlJx99qAfQkl7v mGWBKLJmgSDNHBBLdSGOjCNXDJlFxAY/daKSxuexbqZyzdwk8P9cR3CSKJgciYG/lJmIKq2iZgv3 B6ehuCjLBGxuYLk2zlEWAhOQNrchxwFzmWNr0EiZ9UVZuxhG8zkQuLKlSbWEbCQK3XyOnFk1JYVS A0/Q0xrNwFcy3l+YGfcRnKH3HnxVuntncv7iVJ5rFLkcjeVrX/2m3Nx5IvV3vy8f7X8g/82//C0F eOvyF//pP8sHv/ip3L33pgYpTX1OVRmRi1lkUGcdstYZj1IX1dN1zK9rL3pDeyPHz2i1xTlLD15u Gs6+biCzswO57LQJ4lBSb1RDBS16KONk0D0nHSfWaINxcNSDGoMCXef6nOOpqejDR/rJW7fk4SMF SS181lj6o6n87P0vJCk2ZWl7KpurBVkv6UE8uZTlxoqCpV39vF0FYity48EjWb3/UCoaoWeDsXTQ SXh4Joe/+L/lcu9QOkcvNcDpSAoj8tYOSeCl9EKnekkOjttyCFmQjU0prTT1QO/Iq2fPNQhJCdpw 72wuSNO5WX37zLpUVzYsI7Z3sM/1QP1PCPbqvAVRvgbulx5Q/eGQ74F1hVIp5gIOF+zfIPhjjp6e vOZ74OcAbb1BlyAPTQTmOzkmKRyVE3wGrgOZI9oalQysd7rm3MDnmZi/JLtKs4jNAWzIQTCPRi59 3d7BC527iSzpWlpprlFAF40pcDi5ODmWWf8VpWTI20MzTlGo3A/agAUqUzYpQQiWdmUKMpmZ0X0Z PKnttQ12ZbMK5JqNUv0dyIZgP5XUzjOv1kC5HzTlFK2RiG5EzMhlGryXnDqDOTZAiLqI1GsR51dV D+9bIjsP5HX3Qjof/z9SO/xCNjToSTRQ68TWDIjkR6liDRldZBR1Hxz1Lth4cfJ6T17tHcvS2i35 4bd/JLt33pC+s4tCt3u9rM81jjg+BZYbdJ8CoHTNdGlge7cPhBgMYe/OVbQot0UOuhhPuhiRNoFn G1FAbKjnTUBAurRxU7727ffk5PA1g6NWFYK+M5kokAlLKZMR4azCwLyIQHWKBkZL2hRD49pBhw9z J2S3/3jOe02C0On9GbcdmbkapLN0H4UaQdBckliDlemsr8+tSBcVSJFNrVzH5z/QPasQeOoJs0Rz rv/mmgG6jAkD49vCmIDrotuTweUJ/xT1XL94XuQeikadLERHbJOBD6gNjbUtWdqM2LBEzUQNNCxQ 0TnU0s8Y9wjwwM/r6D60pmu4i6ByNJTdyi15+vQDgrXXh/tcLwCYT59+yswbRLhbOkeRWf/4k09Y TkVpFTw/vA7OTwB1hdiVTuh1qf+BthxA30UnK0ip2LER6UxmdsCj7RrWWEFqelTgDIB/NCHXxwR7 g8Q4cERIyGxAZwVecDBC10kJIJOVQtOuSRNySqDfhAMDOj2RPpBmtUhyOnS8pilKTthovWRExAze DO+ZzK6AE68l5R8cW6aZybApylo//2HyGUkO3IThQksuc2RynZJugnuvxcQkMlymJygkrixVWBSG Csb/GyfQwLJMUwmvx0GKyAiZz8hnuhKW59gJS7HVkFwCL4DM+wJoLmgEDk9KZDADB7aQ4ZpiwYXW kUmP1YJlwZBFDMK57IonudtBv9B+g82SL0kuxGZn83Gcg+DAZyzFNYumVopWoFmC314UMAMXTxyI LxcoLAn7IJgR9zsj2WgK+WSjcMT29SkyK2IecpRg0QNkpIAVowzpgJSdy0a4pzev62ymnpi7/jG0 CnWOhElEGkCK45n3nLDLeprO5hHoGPZmmMPFBvWwZsMRxZcxp5ermXz74a4cHr+S5xcDBS5LOqfR aTWmswCAeuA2PsvMFqiNN2UW2uZ5iaBeN/hagzqGyJimkbXX23zMmCX1PqAxNQVN0wxgEeLOU1dm BmEfvsRxOnaSLQaf6YvqdAwrzBKLmNdwxoMFpdU4dn7IccBrBx8JPCMrX2fkZrHRBgEHcseOX+il OpC1w5hBgxEcwunIrgFBBqKpKTuDzez59le/Le91zmR4+qkUu0fSnezIGfiY445sLK/I16sKXnQ/ 2Wksy+ZKS/7+v/xUfvaL9/XgjRT0bElNI0/M3JoeQCHlVELqHCaOQF1MC9xoUzi74Lnq30FkwQS6 surUb5zRhByHwHCggK2LrNsFo9x0eMqIfL0c0c4sCmdWFvCHGdYi9jbwpnB7oCPoBjUdg39a0803 k9u7K/KVN3bl9s4SOzmXoopG93X5QsHV9iSWrY2S3NgqyBozOnflxr0HsvnGm1Ja3xCprLI8nyno 6B+fymfPfiJffPpUjo8OzXoH91sx6kC9saagr8rsB3iQcbAi3YpeRliT1eg2FejxnC70MMD+eePO PQU16/Lq1Qs9BA757CCJAa/V10cnOhY6v/SaUKrvH53ycF9bWZF6a1WOn35Gvtvy5rZsrazRimiA clwEB5iWYh8T7A1KgbSW6jrJFBT3+pYxA69Pr/myo0Bx1JVic1WqzWW9T5ExOld1DwdxPNV5zRIv OvAjm18D3QdwdmD9T3QsNbrVNRJyn0DWq8ggS8Gf7pOdV5/K6OBM15N+f2dTD7Ntqeuaef7ipRyf n8nyrCs3VhUcoquwN9BxUbBD8WYDLbV6Vdd3hZzb4/MLDQoGLH9hr11p1PVZtZiZRDAXO8oBwFNE Gkpo0jRJ0RqBYB+HADNN2ZFuQtYBNIk1sKlRcgpBaBRqQJahPAdnmhHMsWXSfCTZxjsy0fl8/unP 5eizH8tU52mppuviQIFCU/eN4lRmut4qqOIA8MANSAHKuD+iTdrr0wt5dTiUjRvvyjd+4w9kZfuO tHVDSy56LAWO0aWemk4m+azsVdPgJsMe6P2TM/MDRUAKu73YkjC0KIQV2WzMOUQwjT0YTWKzgrPM s+QDghrqzsUjGetzvvvOb8o3z7ry07/8P/XZXjJrHGNv0gBvOOtJCdxksQYxasyKacCmsxKz+GBE RvQcsGYj+GkXQQVJucspbqhIuZTIzqqCYP3361ORTqSByepN6ev8qlAWgLKPlhQIzImF52Bqji8+ 4OPf49idcY77rfjFl8ML+nxXFRyube9aAgNJE10HyGJTJocdwW1pX5zIfvYpx6FSbrG8vry6pH9W FOi12CENO8gbN1b1rKqSNgPZnpYLXvDe67dHLEPff/CugvCJrr8hmx8gCtzUeTsa9OTs5EjuvflI Xrx4Ksu6BmFL2VYQ984778j+wSu5t7OF+AC8aQMn1mRghzQ0onC4peFVDpTXs8pndryeGCP7NKTJ Ns3kZ4njrthFpxSOnbrMXWr6wrGVeYK5A4F5JSIzA6K7LwldJ+an1rZnZbXgambty758iRXRkVDD zXlksjS3KKHa/y+048xFIll8tuci+c9htimbZ/quf1lWy5o3SEJn9G/lQr4nDqP4Kl/tupyHganQ OltlkfGavyZMcplTz2m4+nzy/LXr4+Qnt5/ovly6GPt8OdW4gh58cq44UGhcyYQbSOC+R3ubWUyQ z4PfhIpkBiNsbOpF6+jCeyXOLYI+moFY+R5q/EUj0vtrTWPz4J2kTrcNmS49IFeX9CDRxYNICAAP ptWI0OPQvIHnnY2QwUG6XjcjyOHAYglgq9ATRjhPNNpp/+ozOYF0QFS2kqyYbMAMka2jCHC+omxM buRC34/E/ZnTMSNx2/TeMHYwrw8AcMplajF6p5M5D9HJJHjSN77Mb1WYlfSZcgs2vSZjeKX5xGer sH7sm1fXkOejpqnXVEu5hkwrKpnPcz5/8NDSRbaanKXQGgwCMfCvZ448ePu+HH4xkIYeqLs7N9lc 88v3P5V3H7yjkWdTHj96g6W0gh7sWzsb8uYb9+WD9z+SZ0+fy+tf7fO9VlY2KCZbqTZkMOlyXUHS ApQMgGwAuQgBIigDFPIdm6UfiPMgs3cvWa5F1hokYjYi6O+srjQcrzYjQZ2WWvRWNVmVaWxZSayj KThMo4CC15WiHoilvrzzlZvy4Pa2BiAKSpI2AUFPgchy47Z87etP5F/86F0Jy0VypSDO3Cyv6Wa+ rYd0KEftEzl7/Qt5/eql7D//QkYoZ6KLuWggALJEATtzo7nm3xROCOUq92CUGmcawK5vbEsjKPGg 3ts7ISXg3v3HOt9bsv/6iEbruzfvUjw00Pc+Oe+w9IpyLUjQiN5fvnrF3QvSKWhmQCfrQNfKDafD 2e10pHPZZolnZRkC3AM6HYSuyQFzlURvNJ3BHi+IKMGAtd1QMA9P087lBf+NcUUjxVCfD4TJ+bkN y9QBaOE11m1eYoBLvqWT9LFGLw1GFEy/evFMn0kkW/d35eb2bfqUPtv7XI7ODlkinRSmCjxTOUXn aWrqCAiCqvWK66y91HkU0MFjOh6RlgCu8eoy5lrTyrczkyexM6zkjMwXlJGCy67N94/AdXI7Q2eF K3o/I6mAMxk1aWKfFkbck+Ohnq03f0eqrWU9qC/lxS9+Jief/UJkcK7gGNI3RTku69gNSizLco3p vBvD5F6DN11hOmfGsn98IQMdh8df+w356jd+oIB5Rce6xzVLa0WxPROarSkT6LorULIrIIXF056y zJojUIUArQVZOKsmuTMvs/MdouWUfuHZMHH864SZ7hI1+CzBM1QA3yo35d1vfkdm3RP5xU//gddU 1ffpKZivN0qkD8GKEbET8/2BBcRoCEvom63nwyhjJg1VhQCJGaQkYlCokLboa8DUIrCLFVAXGkuS NVbpxx3r+VEBvxpBUhgYFQdBf0xdeFIC8HxTp3WbrxJ52a3ZyNwcANIBcAsArOBEomwLrp/uWzW9 5Bps2WCjFdm+hy5WdgsPJgx2eq/67CROHF8XnGiUXmsts7KDHM+GAj2fKBFHQWv3h9LVebp66y7n V+nC7OuQGQ9bkey9PpeTi768/eSeHO4fSLnZ0n+35VJ/zuaHj5/iDPap05CkZYRT2P/RCYLmbxw4 7P0MYrfJLwCAV60Hl8cDnDQwwipBG7o6k9SyYYHnn8V2MJIEF9PvMICMAxTUUzP7hsArZRaizBEw bZKytMTUQ+bI29mvA6trXwG1vxYcL+uGdYv0CjcspxXnyfTZAjzazVk5Ne9Gyq7XYNHlmr8O69gM 7Rod0ApceZKchNj4N/7zSTAn7yf3PkHqhjxktiBht63r1w3svbzX6oIP5bN8V7Xf8vpvfjw8cFvY bC06UP175n9vcW8OaCSL12TiwYLJxIBWAUFcZKuG46n0RkOp0PDcOr+qNUth+yDCAJAtSOi/QYMI QD90zTDzDKHrpvSt8CjTlDZK1j7e77EdPMsK5IikBZMeCZNwflASNLkOM3DvkPXD5gvvw7fv3ZZX x2dy/vyI9jrmA7hwWoBmGUSUKVrtATyaFYomFBO5rBuzkQCYk9isrCAFki3G11h62bx0nQWRk3DJ TTeS9X0jkN94Cu5n9uyxUfn3IKUV+3CUuYaIdC6p44Mtb2Plv8emisii0SBblFslWGSli8Wi+IYR zhcnQ4PvdS5H0lrelbB5Js3NFqPEl7qZ1Wo6DytuvHRM7t2+ITs3NnUzjKTdfi33b/2mvHx+X05e d2ng/vzlK9l7uqcgxJwrpqwRw7qtbvMQ+0hswuECNwfoVTLKnzrhZJT9FBjp+4NaoLPPTO6nM+P4 pL6MbCKmWIEUHA+cBA2dHECGRilqKrd2l+Xh/Xtyc2tNmrDsQRPAYEwHiDCuSbeNTGhLXu1fSnd0 weaWeILg9Qt9j5/LSCf/QK+1jusILNipYxzJs9XnVjYup3lPZ4sufxx6RfNJhPzOjbuPpULLpIga neNeR0oA0vAj7Y0UrE4FjsN2OGRydtGloPH61i65cEfHp/o7Xblx8w47UBvLK2x4wHOE1MGNGzdY QkImD0EX9OMwL/BM8GdldVXB4YpM9GfenqvVWuLedXZyzr0d6w9BGe3zEnOWAZAazcbkZ+GzADDL lYjG7tPpyDIdLPUbcEDmhIGOAr1yOSCH6uDgubRWbsujJ+/KWmtNDl++lC+ef0RXDdBI8PQPzy4X 14Azo5Awc0V5rNGIlmApeY4xtbw2FKTSIxcNTwq+Aeq434XmZmLJiNTxWIsG2BzNhJ7V1q7t+Kko oUI+aZlgcqbv2aoi3T+WUagH9s3Hil4fycvXH8jer/5Gzr/4lWSXXQWjeuW6TVSWyyyXF2cojzUU eKUsYRdAh9E9ctwfyEUfzjYr8uRb78nDr3yPLkW98yGzypNxX/c3HNZGF+FZ7Hijycz09rw4ugWK iQX1ibPCSzOXXPDnTWoKXXg9eL5oMAqcekJmZPR4ChP7GbXfkL07et2X3a1lefyd78vr02M5ePoJ cxMBnXuMkjSnWk0xpomU0X2sYLUcmlViCQ3pIcZiLGMNkkJHuwphOhAZP/pCQWuUVaSsgd4SGqNg EVqL7RoVEIapOTaZJJburArIppMhs6czr7nplSwcWDVcIAwEo9S0J7AekdFPMtv3up0+gxITgs8Y DGB+lDSA2lla55ozanfCoAYd40gqYA4eHxxLcGJ8u8R159abDVlbWZ37FAcKglc2zOMY1ZitG2PO Tfw+dQs7p/Lgja+ya3x5a0f3uBK9j5Ht+/zVvpQRHNNOCO3AnvAOjlFmHoIstkBYD5MVIpmTCQ9I /iQwoqR1XSbzjTaJTVLEcEdgB11kop3eLgm3ZE0MRg5EIpW+oigHlkITyYUBOhFO4LpHr1oPzLNz HjN9OYbLdbVmi4YID1ZCI5Pb98I5ePNqcsa/CmShK2xAJ/SZKZE5gLoOfPzfKTsEs/kFkvOBz0lM M88sn1ICMpoGw8LKyYWwe2ieSfNAyluE+YgiM16aGBC8Uv7MLF3uf+azimFoQrjGgfMY1GVI5+Oz IMjP7951VVKHy5Vn2WFJm6gCI0DjPqauhFfSTacj2GLausHXNWJe1Qil6Kh1NPhNjWhsii8BF2cS G+jHe7PkLgugiOYatvS7DBR4TBs724z8IasRliICdzR1eA08D1RxwBBsJq4zFnMyntq9Q35Dr7G1 Xpc7G2vy+cGRXMRDRYhNlhDAbWNjghuHxCEmPz7zRgKN3FHuY4FdI1aU71zimd2m3GwByngNVioP nTm932zJHSUNLpyDPQkW3EwfGHAOzpJc1lScPIebp0Fh0Yg0v8ZQ/CMlqHGv95t75vmggddDdH69 uM4snmcefWMTdK/CYlXWtu4rUL+Qv/7Lv5ZtZtu+Iq1mWfziAUcEDiYPFBh9/Mkv5a/+6i8pWHtz a0UB3dvyzuM7cnZ6wVJgR/9A54q2Nv1j8TzIAEGPc+RAFkvQAEQgFDGTAfCAznh0JWIjnpJ6UHJN RG6v8ZyHyDp5IUiajPSwm0BZP5Od3aqCmzW5u7shaxr1TsepHO+1pa3XFkpZmksgLS/LRTsisfj8 /JJ8QYiaYiMGfSJE806tKCv1mv7/zIjaaLABCaRkmTeS4PX6yi7IsGdRIO0CXyD4VzR6LzbNNxi8 RcwfHAABaAu6LpbWQvL68IyReTUe4IjSKl4qAWKjpXpLgfYq92WozGO9NVfWZUmvrzsc8U+1viSP 3/6aAr01uewPKVq+vr1j8iU6dHv7r6WtAGR9dY18t74CjMvLDvX08G9Ksejn0W6qtcFD7/TiVPGF SQlhfo1GfQJwPLNqoSJTZIqmJhycMWChkh+BN/YOEEugV3fr9j1pKxh9+flnMkoGOq4wP7MOSNTS ykVzTpg6AXATwx3xmaN8inLyxsoyx84L3wL0Uc6nUM6tYZnva4EDbSkpMyZHlbmgnOeDk8TBfIP5 e0EBalngIanvXXskpdXbMqjX5dU//5UcPH9fDp79TEbdC/qHggNaBzsYdlV9DUIq6M7tadA5oN8u ANykq8+vO5Xlx+/ID3/z96S+fEN6fV3Les9Dnat9neOtRpmdmrHzFfZOJvh/yAnNmw1JK4rnZ6Df HzDmGKe54wkCCnID7XwCkPONBkLubpH7Lasn3IeQrRpLu1eS6tKmBhwP5eTl5xKDJ0yzACuTEwPg sx3fFsmbCIExuNCZaxYJLAGE/QnrCOX4QrVI4JYWKxK26rKxvCn1yoq0Id01mUov6UtcaDAwK1JF wwIiOnYUA2bzIwoQuwZHn/JxiRRIUCHLz3MR+3UxnO8V2IMjCqbH3G8MBKdOU9VeB/zbgwB/xdwp UH5d296UFV2zGE9Is6QKeBEknbUvTGdz2JcXCvSgK0dt0bo1XSB4QqDTalrn+Eq9qWflsgQ3N0z+ BCLPXF8j2oIx+wepHshb4XaKzksudBpmOCJQ7sGDnAK4JVdLcgYcQh4ySc6uaqENZ11HGAmkt4PQ dOBgr+W/vKtBSnFSPdCRetHBZzdLAVZLpbl+S74ctCDXL5oP5tmDHIDyX/x3unBnCIKFvAi/F2RX 3tOROYSdAAAgAElEQVR/BY4E6smP/v2vqMTL1XJz/rPn30tNINmnWTnGRVeCJn/tanl0Ubr2C9KN E9qt59dmbeFz6RN3b3OdvvTqNfx6R+niZ1EePLjf94vaX1P+/+39XUkv9PcccJFK4BdLQNkUcCan YYn+jGONMEu0fwqlXiw703FwsTRyHo/mhHVuwjMrr46nsWtqWNgssWQC3p1GzZVCTSd/SxpLy8zc oDyEkhmCDnZjAqRPzTYNwDLOctIUsZV7wQPB4kXpLeqBX1KhftxKrSwXF5e6wTaY/YRzhs8+UaqD m33IBgDrtDW5FkToJvli3sIVHMDIIGIjo2VWwTQS8TpPZfDPXgIDa7IAz5ZNjeagbN5kk117Jm5u smTBpHLAAINaj65cOy+Ty2Ke+fKRgdrMPX87wKzkaAEexhGfhcPPzzVm2RSkTnRTXV1f02gxlV/+ /GfSPx/K1x//QJ9DhewBPDPKNujEhKTDF69eEvR89vwzmXVNtHTGJpSqLCvIX68XZLVSZ7dvf1AU 7yrjgQnHM3V7SRzPeSb90ZhBqGnd2R/uM6HxaFlijkLXKGHK7TO99qYeolsbDbmxvSK376zK5voS mwY65229pxGj6+k4Ibl6qIdWSZ9rOdB5mA31UEV2zniPIf4Grwc6gbjmeMJnTE4k9kq95uksdpzH ggU+kFApuGwQNkJwhfWip1B1X9ogrQDlf2Rkp/GUUhUBMywTPVShjVa20p4gSAikWTKLNU9Uh9UV D2qdnzhMQPgmuJmOmMkspDauW401zmG8ZnAx0Hm7Io/e3GHW7PDojJWSB4/epEYWZLNPLzoKyhty c7cmK0vrCmhPZO/FnvR7I3ny1iZ5jb32pbzWYGjn5i3ZXFuXwbCrY9mxABbNCFNdL1HGAAagFLPP 5D3s2SJbce+Nx3rvJXnx7BN9Vm1prValonOujD0rsrU241pL53QLUnjQfXt5KQ0NJHa2NinLgp9h bKCTmNFqrUyDd8vOOueSK1qEwg50BKme0mHk1JB8Y2TXkzEQIbJKuranBRmVdyTUoGQwvJRnf/Mf 5PzFz+T4YE8Gl2dGK9HfRTMJ/HfDUcYMJuSOZqOhfl5f72UoJzq2zfpN+eq3fiQPv/sDKTVaChYw 7zNmGrGvTfUeLkcJkwDjqZ0DmEucB/ClnRk3GX3n3C8plJtSHNrra5IL7USWbR8hx4nVEGqZInZy 48nyX1qxPcTJtGCMsaRiSF5MTI8SFlLn+3syTkLu0UE2YQm2Ar1Hal2mFLyuUBe0oEC0Yl7R8BTW 54FqSLUMcwEhHpiWVshbXV/dkre++22paWBzejGR5XYqrw4u5NWko88m1WUTkVc9hJlAFlpmHef3 ZMRnC3kmJpuIv80ezSzTEpMwCs1SE19QDkAJGMFEMXDnKvnLBYrWW6ZzQo5lzdkmJg7YI1sHWzjs wxBAroBaoMHgHT2jvKkA9h2uRexnvYEGgqdyNuzJ3rMhgSCeA8YS1IaS6+qGxR/WRqWyZG4gOo/h nY0ycMHNXHJr2HUauQ4/pP5Tl72ACXiSXQEYJvqcyxTkQAIGnb2uOHCR1UtDtu4nqcxTi8C3WEjI SowVsUN1oIDuQTz4IoihVW663Nx8I4Iv22VWdiBQzOlMXc+E2SGXN4a6DmKSK4dhXqzYl1azcPG7 C27c9ff58pKjf2DuhbnfsQWzyLBd/Z3F9RvnKbkGwIym5bNtofiuXfvlRQfudU5cnjvlgVv+3ub1 ellIkeQzOf51HhimvgwEbgYyDu4zAmbIYgJ4EF2HKfw9R1LRiVofViQuTji3sJjRyDJ16WwsZhq3 Z750amAOHXHTeOLmQshyW6Nco3fj0uoyNx00zIDgj5IE4C64Z5D6iDKv8Wcpb3/PLFch7R1P+PM6 oj6k93td3UiWNOpryoECT0amYb6hYRG4ACUUsEaYSTWejAHjknWeOt0+drjinhgxp0ZRACBFUBOY E0iSWtAwL3kGlu0L/PwLbHzmvqDuWUAKwZ5VMA8qvgyM+ynon53/YwDZDibvP2u0hcTx5vI2V757 MJ3PLWQyaHDd1YO/WJe7t9+Sg/3n8vFHH8i3vvs9bmaJ62qd6Jg8e/YFRWDvPHhE2kTn+ERO9U93 0JXjo9eyh6APQZebd+YJ6w7WwHiRANRM8OFgig2gGc81cNlrK3WhaYOHr+PyWuZyymwvvgfe3Opy g40LDxW8ra8uEaB3T6G5NmKWYTgRllkLxYT7FrLoiK5jmUi5ogfoRN93mtD4G/x9RPaBmF8vGkvS eMG5xffRSFRGFhmxBTJ0RQPn3F8h0CwllsimUU3OphHc5yU5OmLZBHNvOKiYD6gk8+xK0WWTis5x xSoq1gQDgJ1YWkGqGt3X6m5PFQvGk2QR5OGwnwEIJJahwdwoTgbM5q1vNXiw04ey3SOX8+ad+yTF Q5IHJVvIx6xvbpMTeHZ6KYPeUDZ3dmVn9yYDs/3Xx3Le7hBI4n0gD4FKBw5c8K8hRFyqFll+nygw Wd3Ylu1b99ksMRteiF4+A4yC7hUIhIfj2ZyX6puz2Cg37BOgriwpyLyxw3FhhjwTp66gn6EBJflw 5F+XXKY+4V7Gee73SR50BQu0Hb80c2s/oL2WPnk4kVSWpbh1T2b6CF4//Qc5fva+tA8OZNB5Ladn hzys4VADEB6mIwUAkYz03qHzmQ5GEkAeRUEBzsXVO4/k7fd+T9742vd49l7o72LeQpppNO6Rc5vo PdCmEKALHZti984xQEZS1wlsLQFlELCQV4pbgCsMzhWXrYW+G3iYFqAV2ShIWzI02lRrChSG5q+q /0FSh97RCLbBW0MgoJ9TR8UsG8uS3t/G8qoMziB/Y3MTMknQNi0TcBvoLFdK7P6FhSRMEiGFUl7d 0LnZ4vpAxg4uENCLnVYbUtK1srvzhmy9820oWUstrcrdQV1uP7+Unz/7Wzk5eCGxgmZktCoKACeu +hJmtodFmblz0C85M9F+X3lioyYqEDg73PlC5YNMjPrgKhwMCGkjOpsHsyVogAVOq9RVNIBzAGoL 6MbWOQeh+zC1Bk6IjHtf8Xpzhf9fvVWTu8mMMkfo5B5Phs62biJHZxcSnHdMosuJT9OZpLksq6vr 0lBgV9c5XvAHtvcQBUYF8TZLjOhvCHVxgNvG78p0tP9xKcbUd3stDjxurIG1LSNLEQeWdQJhfTyz 8sJoMtULL+rvgdRYdMTHAg9CmYsSXjerN/BDf9bgOvC5no1zmaLgqtTG4s/VDNj1rN4V0ngu2zbP vH1JCZV/2ymrB4GZJYcu4zV/L/ARktRxZEICyuvZRA9a2Kozv/Z0boMltFHK69hl8zKX//381xVy ew6keQBnWRm5krnJj+Vch+96ds6/LrBxzkLjQeI5z6hvplFDMpTLfo/6TWNdAFUF6eVCleUne++Y GR/LNIXzRYF5SNKvG392xjWWyNNBJxD0BE1CxFT/+awTK1nOUGpIJ64BwOYQfTOx8aPhAlkdbnwx baVYFlbQmYYl2dAFUo0OpKPgENIukqW552elFWyixcAyW74Mg2ivwKYFAxeTWeJ8Tg0AzQ8BPr6I UXX+uRs/J+L92nsWc88gp2Xoyjoz10SRl87xn2XP0mgIYV5iJMd/5LoFx4pNFUULiVzpIMxCh38i Hp5+biw8SvVQ0aFvwu81HlG0FZ6K4On9+Md/L9PhmXzjO78hlfoKxw8Z0jt37skXB6/4fNc2YznV gw5rpdaoE1ilaM2HHdnMJEa4/mN7Rr7ET0Hp0DifnL9ipdLIldfcxHTjMiE4pz4YgMkkZafd5npT NjfW5NHdm7LcLAkYVr3TM+l24Tdc4uGJ+RMUmuajG0xdZqbEcnKq7xOjo3qGLlaT4imWTF8Tcy/h XCqSPB44r1t0CAeZ4y3Bj1mvr6IHZOIyrZjbeKMMhO3lTRlUN2SMYKM/kJITjoaUDp5Bq1lnWRYB OGVtxIAu1gP+TdkMrusSM03MQkEeJjAnDtgiYUuEziKzqwR9BqDwu8VobdHogtcG2bxUOdJDync6 429oWpUqdX32G2yy6LELry9r65sK7DZ5fO6fnGGFyqPH78hF+0ySH/9Ux3fCQ5uBIoNalEMNHOE+ NzZuSFEP9uHFpa6TkaSRPgMFsQV9BiN9nqPBlHsj1x1Ai2teQGYJ3XzQ0EudlBMOWhys9aWWUQ91 X8GhzxPPCZ2DJoMAkaVSt0bSxM0jx0E1KkpoZ6BOi+6srwfrqpTX7siBztnnH/5UssOPZda/kBMN Ai9fvuLBjkkH4FtGxWkWyGDcZ1YWDYQxeFZwZynW5N6jr8kPfv+PZOfhYznUwzxFhzArAAUZTsfz DNtsPHOeyMYRxn2zOx/i6a5qQOmWWcxu+Dg1GkLRUUwmrlQKvb3EZfCy2JQcoIAAOAAgDWpCwTUz obHLeLbm/MJO0Ajc0ClLwMNhlzw+cGchEcKAIGjaPAOgcjy9QlaBm7VM0zIrMUu6Z6zdvUecMUYn PCRWuH4T/nx9e1tuv/WuiK6JvliSoFIryfrDLfndGz+SH//Nf5IvPj5mYFPUeYjqXkR5klAAWa1p xHGKAy83ZlZ9yLrNZkPrhnUamszmOr5y4jjfSbhI0sw5yMiqh56WYgGU7bWhmR9QtDwzqTX+7bFG YP0HKLnqWkHWDWuy3lqRpXBdtraEFAVI/kBmB5lpNCJBbBvP/Oz8RF7u7/GzwHuldyomRqXqDuks M9IigVlAQm6WLQDUop5u0Z7PVLG70NkKxRR8TeYm9HSNzNxcw+KbTukjiGwDvCSnOpFoBM+Up1Bj LXMlmzwQ8eDhapeJ/NpX/ndmJNGbhYgvhRnx3ZA4QceXZPD8l+e+fSnfTewBXc12OEDjPq/ouFT+ ennNzt8o8hvYPCN3lVu3+LxwnhFZCPJaxA37Imx+FE4OPECcLSZTGOZ+5+p1Lrhzi6yc/39G9q7M Pr/fdKEl57+QbqcDQWaLi3eSLq4boCmjQG4gHQVxYawHQEMXdtOyuwBx7MBEvwpIrbRZMk0mcimp eVSY81Sg1dNcWiWXAGWoFDYw6DLDxjSasH2dWn7T2DqsMtOQijNzTsDGxmyOAyMg9WNuUlVehNpw ekVSr1V4X5PRiG3kQZLjPoqVWtC9hGyxN7ExntOi82mRLbVojhEsMvNOlwj/psyE63zjYeNEjH32 KYyKV4CTgeZwnqFLZZFxW2TgXKdjPDM7q2vzYD6/MsgoVN26DKxsmnq3E5B5I4JcP3f9nMm7eyQh BJwVKEUZBUbht1pfvkWng1/97BM5PDqWt598Xe7ffyIlBcZv3H0gHz37RH785z82bSaAFIC1zEAB Dm9whlK7EQY6dhJ7lw4zvmM1ILWGBPNRDk0Kxml9WUY05FpgxkXfrgVZid0Wu8Q215YVvMEG6lwu T89l2B7JdDRlEBpGyGzVJQqWbV+GAHnByi8p5m9ctmoBqaxDnR8ameMfiYnYQlAZHa6YC9VyZILM mbm1+KR7icC+aHQLlHTKNh+gKTWLZrK0tinNjYcKsobWkQu+Mfwi9W8EHwBm6JAbgQA/HLmMauSa fhK3XpCFCKS50mLzDq6rUmkwc8cqRyHjv4eOw1St1O2gAKColHl4YF/hYT+zYA9q9sVqTcr6x7RF jUuFlQ+eUsUBPGSD6JSR6LjqPQ4UhLaWlvUz9Nk+B47JCGwAcsnfKljFxfQhrUS4vLrB4H7chqBw R4HBRErjFZng8IPIaVih4DD3KsctTKYj2Vhbla2NFT0AB7Q/s/3YMtkTil4XKbHB6k5giQa8R6lY cuvWDOBNQ1Pm2We/rq3yYd8roxO5UZPj88/k5NOPJda5dNYfyenRmQxOXkra64hGqzImBaOqQHqJ /Mv+4EISfc6RvrY7HUhB18Z3fvN35Ye/+290/1uV/YMzdoCiGx4JD+wLsHLEfAT1YzrQvRTADPsP gKD+DEAu1vHD/cI6DNql4ARGYdWAor4OzR3Y/4Y6z6A1BjuwKDLwNqGvc2qczQxOLSNzt0inXJPM zNJ5QjhP8XvQ1ATv8+JoXz7/+EM5PNiX4UjXXGSZPXhIpwwKUuN84z9o6w2n0odgva6djXJDqgrQ YFNZrwfy6M4dWa5XKQJczS5ldeuWrD16xOce6H2iQUimZ5Ip+CkUlhn0sXnIAS0G5mm20NG0A2m+ +PJ7WZYuPJmRhQQAZcldLPBJgR2wF7tu/8w5/zABon/Kbg8nLxVuTijlYt5khpGS0Pmi4z9cAtan a+SDbSMyz93uuWmFUu/U9uJht891WtB9qFYtyO7OLR2fPp8PhKrxfKwsOzXbLRLVFfFCxbuGzsLY zMdhcwnLpIBRpRjJH9BTNwN0xNA8N3Hk/syVDhIxIjdSxZAcQUcVhWntME1JVp+ZxQcXVcT+Y6S0 wfsImf2aUuBRlxqJzKw9+ANIxNkOBaxDh/PM3wJ42WFnB1UBmRVHYveLME3s39fLTYHnQuQzcvmM VC5jwp/PoVcecHnelJV7ka5H1iZ0REm8hc8K8ZwqFuYckEIhct6aKYUmY+9qINbta2g+dG0SdrjO nMu9501ZxsJAnwdbHqj5jchfp+fm+APeR3n+kPYlCg8wrmco2XpvSSrLgkTQcxyTLwDeBMjLVZq7 X2oUnchA5wzMKYIxtH1mOjl1cQPQJHb9uH+kt8eZbkRJxO8hS4AxAhCMyiXyA8i1hG+kbsaDzHSP SKycLbJl7IZC+lt/nrD5xiLXqeN/oOSPaBTPBIdtvVyXqS6Ibnom1XXMySJ5NB09mPGkRhB91V2h Qo7z1EouEdnxUMzm+iH5Hk3x4xnFRZkhDAo2WxEdghuVK+lS2sDNj9gD3yCbO2CwNJ54CQSXBUu8 VpyBNsjxuG4EgjdxYFIcaGSEaW1ZVlrMl1P1ZSN3OHvrPeu0tXUAwn7RZWfzGcA5mIOqvtg1Ja7Z ga0f+uzKSzdko7UrB5/9RF4+/wu5deuf5N7DO7J2Y0d++I03ZHD5nvzHv/hLBVAD2AEzw4VpMUmg 2ddg1qDbvtD713FOR/q9iFE5x40aY1YGrun4DnTzGwAM0BbFaULqjc/0kpqlRForNUpKrPFPS4FE iRykk9fH0jkduW76gGWOUqku1bBsB3hoAQHAII3PM9hn6cEtM4J6NB8UAptD+Exs3uy4jM2GDl/o yIsCK+mGLqjz/MfQVQgg8I0GGNz7pLwitZ1HOn470kEzCLleZu9WW6mwpGNdhjrlV5bIT2Pg5eY3 gYzLMuMPZgOaDwDMOtNLfc2BARbXiSnhwtuX84UZ+ZKTwdG/9SChbzGT3Ng7J1LEGTGe2hwU3zQ0 IxUHBO3UBTn0NU4tyMLrKeGgh9YZRIXRJoJpWjKwm5EOWOJBirxcUUFtrPtA3H6p130i2cR0L4Oo p9cyZOYq0rU6ziKpV0ty9PpQx30qt2/umAE5pSdSaksiM86MJPjWxbKbxgoyytCAM8BSLlTc+ZRS PJpxAwzsG2OdaxXdR6ok9seZHqCpAvfmjhTrOzKRkTz94BdysveZJP229C8uaK3U7bX1vnQvVAAH ncCmAmQkJsaTvj6PkYJleOd2FeSUZPfuu/J7//pP5MHjd/jszjr7fGbIKo2HU74PSu0oy4FagjUb Ok3WGALj5QL5X2wKmxl4Hk6N9B5pgNVvd/k8IdzbVsCA79erZQoJQ9dzltmexIYAcGDH8Xx/L6Np ehZT0w8OQdA2m/gAGKVS/fvwo/fl9Sf/LP2zc2q/QfcQGfVyBLqAnXkoo9aKLe4nOLnDWY970ihu WsPGtCLvPnlH7t/dkLs31kitgkZe4eJACpvbzLwjgxcHENzVIL88kWzQkcu/+3dypOARYCspr/K5 15j5m5FLGqTmd44A0YTK9RyNAidkHxhH0GfWxHj+mUuQIDhEFp7whg13LqNeLvM8xny2buryglOO Zk7u31YBKcRGCdHTyPzhi+blDB1MBKxohaqVarQaFOcdnKbWFZyGMz7TdBpqQNARL3VTKNSYwa7V V+TmzYrjxOW+/CFOgIOLGYu15OLm0ywHVKyjhDIgAFFeST40TkGhYDIKcHkgedLLjCBDBe6QWLcq UC6QgB9IRtyU8jVezvWvOQC5kiGzUnA+y+CBXBgWroCPPD8sL7dgZbyr5Uy+Pk2v/Pv6dfgD7deN uRdggp83r6GJVT39Z0nmZCPSeQnMRwyes7S4n8B12pjSvv++/TvhQZR6XkSuDJ3/yt/vfMxzzz5f Js2by+ebC/x987njcPPZzIzCg9RuQ9dkqQxdpowdeYz2uNUEjCzhKwrJhHpgGQiU86jq7bswxaym CrpATNy4wGh/POxzoQIw9R13zjgMNncKgWV0k8yIzhMKJ1smjn+7hhFbtIFrwhHy9yiEnBpfTqia XnTP02v+RTy8MX8pTl1089bp4xUKpuJezMmMeNK5j9wXJfrQleeuctWiXKnTgHVsmkc4XKPSIpsb eGcNK6Nb13xOg3AxU43WEGfzzlN/L1hnydTM4xO7CAMfLkAJg6vUgvzXfB05Hh3H07lFUMTY3ffD t9+TTvtMTg6fy8/e/wuNpseydWtXNre3ZGOlLEfZlNa02C/Cpo6bgrW15TJ5JclQn4lG6rUC7LFC 8l3wWV6HD9c31ENl1B8qSJiwh72qB3pd50wVArGKuGGcDm4PIl1skn09GM5P4Rk6Ic8EciScc8XI AXNh5ozl3yww2QJs75llAtlShIDUVycyp3ifuX1SgtwztmdLN43QyqfzrLxbP3EIiQoAcZ2zCh5L rRWJai1TqUcGOrC1x3meefpD5kRdM5bjTITdyqjzTkMXqObXPbXVePBMmXHztAmAPVhuxTwkirk9 JeO1IfuCzmKuUxwikTkKUBg3MmCKPwjCjHNoemUZlfeRrbXuU5STQV7H88C1xsymFefSP9zvaQEX UscRHXjx8REzjhkaSgCIAF8UAIHEDyBea9Zl7+UXMhq0ZWdjjeAH9kTVesP8M6Mp5wvyoXU0nBRD Uj2oxoAABtkhlAoR3IEfpf8N4qEB2iJKiEsK6iJplaa6b/VlrAFDY+0my7wn56/l80/el875kbSP 92R42ZYJeLaDoTVtMP+i+5aCB0jOxPr71DfUw7s3gVNIRd7++nfk9//Vfy9rO/fk7LLHZgFIaqD0 2oMUDDhpBXO9mYEOMDNZDYK6CJ3VI52wJXIAUaKDZAo6s/FMAfzBP8PYg2eF8iepUkEs3e6EYG42 HrlKh9CeDv9P9w10gEIEW9cT9AFR6p/AjSOyPa6t/1/WudQ73JPT509l0usoqAB3VIFnV9fZeGRz 3wXnbGpgASqlHyh9UimZhSzipcAzdXmpIi1dr7NgyPOgslGRbOmuxJhbDagdTKXQu5DZWUfGxwdy efBCXn7+Snr62fXNW/S97nR6HJuo6Hi07gwuOvBuagVeNilzPOVFFcvvp/OO/VwCJ4z8OppyHOgN rOOP5gYmpvS9qpUy1yo1NAH2gpxFYGj2hr75E3u9Tyb5syZfcTEHm/LCxcKtZ78fwI4TmdLCHBTl uFRzzbBcxoX6b0HiJCQS02LJjBfny0Z2QBScTpWhFfAwYpRJGTriNNLfL+gmHNuBCp6EB1pWi0+t LRjRn5NmcB+Ru06zCJPAZ+A8kFvIZGSZH4yr3K58WTFfTsz/ud6k4HlMc4rytdLkl5ZT/ytf88/w 2bzI/74jrAemMj3/XN8a7kBXvvzrH+iXvb9IvvT66/f5ZaXW69ysPDD1ZdRfey+AoMgOEyqxw98O 2YPENpUig/0ZM0yABjAzHs6Q/dWFMFHAhCwAAB9SyzEmtWUmAOBQ8hgEBpBKYLfq6+Fbl2YW/eNA QrbPg39/zYHrmp4yq5nNLZtY1kqsGWZ+Dxz3SKNLoVgkylVTbIylBpXZUzofmMxG6GRuTKbDpEQC ly4HkZdrxwm5UlYBoMvPW3FlmCByOmsB5/YikLAgh0eYL5UHKGlf7Yz+NWAfRrlgwyRB8l8st6em M5elzi4Nz9g998h1vM71ocTJx5iE6JfMZ4qsLIIlPvPIdVo4E21+nmV1O7OCNNd2yGFc29qRDz75 uXz8y0/lg5//khvRSqPMAwdvUV2qMeArBDOKnS7Xi9KsV6RZKzPLQm9YNJJEbtx0E0uqZWnq96FL BnuoJkp9ABY670rI5vCSMwpqjgZjlkwBaCPybut0R+Hm6jKr1ggVWzlEjCcFwWNk6clfzIwnhGoF 9aJKloUjRYJZ1LwskNm8sQM+DJyXs8vAY4zdXibkB6Eroim1tRsSsdvaonlfNs9cptzLAqEiwpKy mIyM57banLBAOMzRNRiUlYqyrAeOn3M8QJzotPc49u/l1wysyzzQg20Qy3YijmtXZHMS+ai+AQWa WqUqvVOR+Yix9ouW0cNcDcV8UfFnFM+YZYfUi/FWLdvGGE2vBd2lTTGbN4jaotQ10OsZwtKuVGCG snuwL/t7LxW8KGBv1eW1gr6qAkVIDuE60M3IrKJey0zHbDzO5plG/DzkWYJuX91jwCmKrEs20J9D IT9KFHQq8JtM+9Slq67uyETX/vNnH8vBq6fSURADQ/R++1S6521mqoxTZV8I+lBsbvcVCEUaUI76 7OBtbT+U7/7Ov5bv/+aPCAxfvD4lz24y6pNigus713upFyHom1LQGg4k5ikOPc0Ry62Ym30FsAhJ UVKEvSGDL31m/U5fgZ/5keJsRXBFykoYuoBX6L4URlVmgtixnJqFGOYDwH4SW5YJ3EzSbAol/g0u +/S8I0HnQGa9Szb14ExDBy72N1h1Qo0imtpeQlkljkeo67PC+Y95VdUAoawPeKb33b04l8Fa2aot VezLCtRbTTl69VK6P9+Xy70DGZ+dS62UyVIj4jM5PB2Q/gKQOx325tksnjYEQjHnITZXNOvUag2W lnFvtPsK83QhdzYiux0seHRcc2JSULTRZpnVghfvqYvX0X4R5ew0cF3Wybyqlefk+8RAZNTn+Zia pZoAACAASURBVNnq9w0Tni7Mq2Mej6S5czoP7ArUqfI8tytZLHfxgXVPAb3LXCR3AW78jc+lECIo NBcUTc+sHMjNMaVgYuC6MsVbTmEg0Mwgi+YBcJroIYdjPKdnxZ8HLtLP8XSsaro4uBYAw2+YyZVD 6Ho5cQ5SU7ORmpdKPajxG6NcBWhXAF4O/P3XMlupI1Ly/9n95z4ntY3e3sP2fB4LfJGVqr3Wm79m 34hinKLxFXC1AAWL8un1TGT+z3zcZdG96jd4fw9+cl0HefZM8vMH2TMDBXjegASIfCP33LAJZ4F1 1GIDLgRWUmSjC7S1wAnQAxbdTCjZlPSAGM/Mv7Y4NFLtDIcIxiRIrXO6KFe/0OE6Mx6mX3y+LEwA 5LOKDggEmY0jeHEzHtjGp8Phjc5PagXhNYGVnYVd6s4+DSlz92jIZZo13CIsEMDmu30X4LkgV8SZ iet45Bpf00dpkTUTFPTw8wdqFngnjV8H33zucjW48M+UciH+mYdW2vfzFRGrsJxqQDL0a8NaCubl 0/x8ZjOrM6xPyAFcAHybQ6m7x4y2eZD+iPR1K+s35Ld/65ZuvgP54ovP2e12eX7ALBB4HsNelwci XBEy3ReaKzqeEIwFwXq82MzwzpViQMpBSfeC1aYBBuo1oTyuawL2WNPBTAZ6qJJLxqjVQDKapiyz a53BZjgo1liBEkpmSBd2QKaRJbxHOstA6idegGoGsGlmyhOZA33u/din6kW+UydQni6aHFgWB5cL gEwP0lJjU6LlLckqLcpJROgydPjYb/IGsE2olTIQ7rC4Tnfwopj+MPHR+5wyIZaxG/X7c79aT5vI 8599tg6HJMSRzXIpnst5gOs2dvpwAJVeqwwLjNmIioE7cC/xfXzOGczH9XfAfc03Wdn8CXhuMEuh BzAEUROCZssCAmjhe9hrBjpfjk4PTVcLpWV9Fien5ywVV7t987usD+kn21qGN6cGgYUZP7dS1jkx Svk5jWZTgzfjOEFpH9mV4WRGf0yYzp/2hhrHNaS+tiGdeCQvn/6TnCmACxUMzLrn0tX520UWDd2y s5gWiGwQgKUf9gZYTU51Lk6NTnLvzW/Je7/7R/Lkmz+Uyz4kJtoKiiYmvTIeyHTcYzYO2elRRz87 GWsA0jXajY5fyCadIQPhWrHKscd8AmiiTl/DMp39UY98RwBCaK/hPIRbR7lg4KOv74E5hKwYNMxM miaVy/Y5AS72WpRvSwqKUVEbU2ZoIkM0kOj6wXt39o+klE3oajDR1w5nei2VhcwNFQiQXXX7ArK6 6DoFX86aE6E0UOd9xKOZXB53Jda9fjzryJleR/v1K7k8OpRUQWwwHFuQWy1Ia2dVihoAolu0oc83 KBdIecF74z4xDiH56LZvc/1n5suOa/PcaGZrHYCLWPddSMwk7gzwgskAo3PFDFB6dEKVHW3Gr09+ bmj7NteEJE4sOc9Jnhf95rxovr9bf7Q5KxadPNRClk1c8ie/x6N0XbBNebEBQ03c66Jl7kA3pwU7 IBFp+SwBvtCWnie/c4sJ0znHhjIFFGaN+N5xaqR8lqNC48J4UIIBLkhh/l72HuKyC8mVrJAHG/y8 uUit6QaBYJEmljUM0/gKNywPUP175A+pPLC53liRf+0iE7WQL7Ahulpu9Hky/nsOCK9muSyyvtp8 MAeFcj1LlrhJYP5wQXD153YfNlEkWDRALH529ZDPA7p8lu16aveKPl5uvKgjxDyztWib+klo4rAQ YA1Md9ACgIguIKkYB2wCNXAQjZG9SFJGxdDfQukDC4qlLpjGI2SB6C/KIoXQcchmxLnj2WCefaOZ ceI4k164E4dXbO9HQGxJO50Xeu1OYweBBniS09T8ZwHkIlfWL+v7jlNzbrCxt8yJdRjltONyC8zL whTYgOBHzTok/TjbwZi47M8iSvMldR+I5DuFF1y6aA7W6WAR+nn96/N85jI0jIj854qFPXx+WebR h73umn9wIbSsrg+U5sGL6xhmmRb7Q3Ati+/uAZE/QXFQpOYaeDVZWJW33vomSzzFJ1915bxzOT05 km63Q99AtNsziwR+13BAdXZ8Gc0DnW5DNhOsFN3npdbQAHI2OudQfaT/KBNHCAhqlKUw4Jnx2UHT D1BOXLe90S8CV1YOmQmjoDmnc+hEoi0QZeYJP2OHWsTAlNnL3F5gPs+2tiNXlmVGL8o1PEFOQ5Fa aXlDGlu3RKorMkUglJnOIblmgZXdI1P4y713wPKbk7daBA2ZE4AVy8wS/LhmF/LmkCXWN0cWrlyw OUaR4Nw+54FhudIwPmChTPAT5cjh+LO140TgXSYYmY8Z1fljHvJ4ADikvL4fwEIHpVuUnqpVBj+Q vcB1kzTvgi9fGsb2OnI6ZwAVmGYVgD80b7T0/x8+ZldqHXwtBTspBK5hi6TAv4is6eUFM0yYawCQ 9XpTwX5dJnB3gfi2BgKD8YgSLonOM9A1GvCORRa53ZVMwcEwqMrK7h3aa334zz+VwdlzKacTaZ+c yfnpsZwqcETpkU4QiXXKo8QO4JPGA879cV/HKGzK19/7A/n+7/yhbO3eor/t2cW5BM4Ort/raAAR U7qj2z5TMFa1bk/9XGS5KQcymGhQMuG9omyYlMaOx2YADs8Yw47x5nOEHiKst2YlPp+A1paQk4kp LeLXaX/Q5/NAWX6oYAmcdgPr5nxRAOjrdK1zHlwy57ozkqr0xlMZhibDAj/sEJpxlZJef2veZARg XojcRKbunqkhRFKU/rAnB/svGcA9/RgBW18D6hEz4uXzC32WQ3rURvq8Mr2+3slAWtOQ+n8bu7sM gIbgO0+NZ8+yP7TekPHV5zt2EipV+Lnq4OBnuFeMVyWKHJ/YlU6DnC6tqzCS0+r3P7f2GRhBAqsQ OyuueD5v8TcycmEU5M5VHxAF5Nml7iyPovIcj/i//TrN45F5pi63PvEHFIPCr5UPc5IHfFO8UWil MEp5hbbQ/MFC0jnSsrTRCixylUUGB4djGFnkx82eWRR4sCHqRxOFzG8ycsbW7MKGthj4B05+mADN ZRB4js6FZvPlnkQWvDIfkV4tneYPoutAxacpr0ts5DNU84ciVuLIA738AZbnkc03x9zvLq4x4SFj 75PlOg3jRYkh9752/a6xI5nNZUF8WtaPiYHwLy/tXgWK4kCh2a/Zj/z9OnN3WWTfviyTRzFIcbwg tmQHLltmqWdET7RCwrkoJYLPBOpquql0KDNgGdWiHkzjgklRYAGhdRolA3ong7+i11ONLIKbuS7Q tJAx+xE5LOIKyZZhYwt97DTE9CDDAk0LDni5JBpOwMjr3rmUvwNPOLDIsePBHThpCNgFlXmYmsNG Ubyo7pw3F1hWmh7COW9eBhgOKJENkBXE5OFcZtUJaOfnT5rKXKLE863yncSZCwokN6ssuLC1FGeO EJ7LMtsccJvCNYu5xcZh9ITFl11jnmPpo8cwkivz069JNs6AuluokIuDTXPAKD6j7h9KoNOZzoha XbZrK3Lj5gOOJQ59HPZ4bU03ufFkxDlP+RZEqDpfDl8+lYMXn8tqOCaQmo0mMgT5GHsOFfxjlnQL kflFslQ4WyjXG0cNIM8kbMjtDK3BIQHxGb+jv1t0e0JgSUm+jueQ58uAB4g5Sy9NXz31tI6AZVZm KlFi4sEVSs01DbBMiaxuuSrVjS2prK5DbY58UtC/KSHiQXgWuCDCnkkk3pkjtIM5dSVy96yieSBn FQbOVZ9NdkLhLI1GMm+IQInTOG8Fo8/g99hYFjrRYeenKYuOviA2Pi73e/CE9DnXiwuDeAgeg/vq Bc/RUXmwv2d8IQZNgYllczxDSuLgM8GFHeuB++yzT9mMVG01mM2ADEa9EtOZBcCiWGso0IwpYZHE CtLWm9T8At/RiOAjCjT3YfkHEDcZ8DmgLImSb6HakOnplMKqlUpNuh3wx2rUP0SzXXX7iWzcXZbL 9r68+OCfJOxeSGU0lhd7z+VSAd+o3SHFI2SHvYLh6chxSSP9vpHrxwqCtrcfym//wZ/IV7/3Izk8 78jHnz3TvWesr9Hf719KgRvnjC4Y6ELEXjiYdTmuKLFGCG7TMscG3EbqKMEKE5SUoXdtQTPHVPoU 4S3b+osssOj3hpwzAC8sJ2JMCaKn+jkTBuDg8okMmb1Cxs4CRFvbAD/Q82R21mVXyDMGPWac6DxW wFUMKJZOmaugyDEs0I1izCwuyuaFcoX+vlG5JpUqOsABuLtycvFCwf8lG9QGnQvuIbWm2ZLRwk7H ulafye1b9+X+vQ1p6Z7RqNb00AB3UgchLLM8CqeeqGCYodftS7254NsbmIQOYjjfs7HXmASYO0cx x7GvIVNeiAjU5pw5+q4nc25rPhjH9fqzmCdoLotte+NV+lXkOPwzJ7vi38uDNXx533S/1/r3DeZn jIG+OYjji5yXGA8QlBUCSx9amTNh5OptSxLX+k+Jkci5ECSLD6TFHEobyB9nixIODY8zf7Y566H5 YCBSTakx8/8T9qbNlmTXddg+mXnn+6Z6VV3VXd2NQgNoEANJAAQHQaQkOsiQGaYVlB0Mh63wZ9tf /ckf/UOksEhZEbbhEB2ULNs0yZAsUeAEggQBYuxGD9U11xvvfHPwWWvvnXnurWLwgcWqfu++ezNP nrOHtddeuwTZVAECNYyq7smDrB+SiY+gknoXQfOFUmksdZy1oWZeVqpSNG/voaRfLwtasuR1+2VV /x1fUxhGBjOGeKQlIV8T/WzPsPcbSDJD00Q5MD64XLRrzQekd5+pm44onITWD6cB2O79dQhO3fIL eZeGHHW6f/uIH74GOJhW3sQzobAoml4gn5B7a36mGQe7Rwtmc3ScMUvEUO+NlRfhnDHerZeprh4C PzZwbNWD9vk5Guygqy3TfiKuRdVo2ZXv1HSIBdmTLI9pIwF/1qj2Htde9DooMBmEhGd2kK7WikDk lpFlPuoqCZQBs5PAn5OA6mUkIliFfp6idaGF9XcPrJBDZU+o5X368yKAlnt36K7R8H3Tc1J404iL kfK+a0VSMMDbhXL5LGrfw2YsakXjHFFuy/kSdsbU6T3XkvLh9D47VDlFdHW7a9lBu7EgBr2lFMn0 8IDTMLRUHc85EIT4pEboIuwpag8ZmcPjwA5kuwjyFvGcDkZ9oiXgpa0efJ+ogc7HrCmJhIJWYFKJ 6tPAeCUafPj6tIEL7rZWW0EhUJTzIK2EZgS8b4aRgw0DblYYOCIokK+LZpgeY7VMkcxMy7AMmGpD Pv2cMUBqeD9DBnGaza9jQtCbHkh+EIMP8MbKuM8BU4fa+IlKqXDUnwGzJ7ONzrq0wm07QhDJsAo3 67OD6HVVqrYeGhcUxTU6iWhACH6b2g2165wawsDZgj84jly7WTnmzJJEOF0fp6RzOLkw4s4H/Gbw 2bJ+QdL3uOjLfHbNoH6+nneBqPG0Wm5ffOvnT5/FQP6xVHGPTVancnTjthxNb0o+PgaBlSOb0NEM h1sjwOg1VPtHHjTgfF2I3Mbgwvl/0LoDWhTP+/WskssYHA2HJUWfocV3EJ/BYHIgF0/OKXmBwe5H J7flgx98XZ7e/6Ysnz+QzeVMzs+u5enzZ3INyQfca7SB2F3rGKwSfcPj4ySEfvzZsXzup35Cfubv /LK8+dZn5MNHD+TxwweQ4JXz589jIH0Z7dtSysVVK8gL9BqNFtVmJseHJzFwXVDdoQRHD12YlerD sbklwyD6GYNiBiXLORPPYtgQkUQnJgNqyCzF995kJqTOhCjj3FAENiy7l2pbgLjiNUC10amO954v ruO+HfOZgsJD1DHe760jcAaPiKiSUwfR3HgTQO+uDd3D69RXwE4uNYgezMh9w4g6yNDk0Z4fPJ8Q MQbgg3ubAYW+cUKx6LemMWijvuiQwRr85ay8jtu1z85UnkGcp40mDbhWBOnkTcdrgIoDOHG8z0Zn E1NixRr3qC8YHPgRabwL3/4oAqbVQahlsGGFFae8DQR7HH2npdG+6Zc2VddomLVNbg4GNbyuLvHf bbjEGnijkSNvjdv4IEb1KqycGrqSWZZ1Tr6xKkxdh/ZDGk/QKyOK2wB4Ci7mThhPMsZcOxIr2rpS tBtPOTr8TBJVdPgxD3BRs7wFgjgidtfkEem6IzvEQC0aniE4OukXNZJCbohEh7q5o0l5H+6QmnoX rfDv75SLkyCmC8C6ElTaaNBx1bo4fCfIxA8qRdb44GwurQpf6utTAV6uTwNVC2uJJu/i5XzGEOSF 7+0Ho8E2ga9Bmjm8rLSa8p7adagr67Qrqe9XVpoFZdIhNSASgzguNiGj1lPCRCHjvRh0j/VDIIUZ mKLB3ArTGlbKMxj3IfK5khGUriHNAmfboo0VUQXd4LVK3QQNOlzuoanU8enaBJV9yBXVK4puH5Dv gxJPnfFgDuL/KqATQGnFg9mMCHPVpFB4lwCRdrCtiWroXshbkusuB6iTudktmTq6l7c6RN4d2KLg uWoYVWXX0JPuR9V+Uw2vdo8ED9JMYib4XON4zRyKXTAkCGbEmmT/6DW+GMin52FnfzN4LGWD9YFO WQzSIE/w6OGz6JxuRGeFbpKSA7DxQSgpbdamURgdB76H0TK8VuSuMahfzqDnVshJdLI//vkvyF9e PYmh4ZIzK5HjoB85xM8Ez2eQjzgyDfYIHfyNOalghixw12gTFZad4wFNMqkSJd9jIkTWeLIWSEaG MeYAdJOw686VaKBY7yWDyOBRYrekBhaRCK9JCYXRWBoQpC1x5txJ8OHgNPa4qZn4iLRSHBTNXEfR AnWxPQxHz6AtKHdOnYGtAda4p00JXjpVHa/dZK/f1645los8y8hNpxAJFcJgyvSow8JZZ0NFbR3d bBQB8lqxTFcV2hXc7nPcG8rArNoodxUdrBjZNLu41jWQPgWGJ0Ap+4cyPLwtx3fuYKYYGzVY8ptf K40mBhJA8NAcBfu6XtXsjvTuTuqsQZMOQRFQkM2cMiSL1TwGZ4+lGM/lM1/+inz2p74imzCQ737j 9+T8wY+kWT6TxfWFfBgDsOfnF5zSgOHtKN8iuIdcBAIvahPiHMUAbjK+IV/8W78kP/6Vvyez+F5/ 8c67sr54JGF1RaRrsQT3IwaCmJkaA1pWX0zgHjsQMhLPnz7UZ4Aya6X0oQ35XBt2g2K8GwYdIcBb m74n9sN2o+Xx9bqijArtAqpbizllLrDHry8uWnuHjksglWxtikFlPz7HzQpjuXq0v3gm/Z6KBo9H yveCVE+xvpbJYXzttBcDzak2lW11wgC4cBxdNdSqCMebqcBIvJdArusgG8okBmgHxzFIm47lYDiV o6MT6oHivQ56G01K+jqEHsjhAoPtgWzH5zqPn4VzPsecYNBfJgM2tC3j8xxD1qVRKRC8R1tpK7UE Shk16wpVakvWcpF3K01WoQn5ju3UoxAoScNGkOWK9r40JBjTKtClu1/t87nxrl3b2mI7x97MwIAT SUKeyDqlPgTv24t+wpVBIGIHUmaT6eQErQWrZARb7snv9YYBXr6UTuyudI5iYyS8nNmwGprSuufw fjBc61DRWZeGwmX9MUY4EF6EBS2bDUUKdWh0RX5FUW1Vy448pZ6oIAc6ZjeyI9eRomONa2LJTodW ipI56bsz7J3QbVpWfdmXxrqBcgNwpOTgNT59QT9DUTj7LMtcQybJw0SWWnHYNPg2hRkzPgtkSkRZ QktsJ+qEuM9Kif2kbTotc+mA+A5BabWpGm9A6RAh3cAd8V+XUjlBCGDIM2ikzSJcuNbXBlQ1ik5i 6gG+H8zRlFrirGVDoceyWiuzqj+gQeeeKnR8C4UayYvDAPABtbowF/F6q4Fhw+aXICtoc3FyuTos UGi2RC0Mdas2ROccCe4OCAAyqKbbEHsMRjeF8zWCYuRV0dj1iGD00QTLAOxkPGXp5ipmSygFbGaB WkV49tAhgkcnGtfk7TNXDa6BGQ6VOmEwhpmpjZNac/E4CEO8/ZrFuiD92cGgN0GFsLG/EAz1Mw0Q cbbWLIMMO+mKRrNvzmmF5t6g36FjEmxygQbcpbXRe8CJvaWj8cp2Woajfzv7Pgs7jUhgQaJMqXtf TDhUkXsWdI0fiROO4d8ISiE7sy1X2lQh2jhFLSd2v3VTYpgf1h26hOddDHLq+10uGhmc3JU3v/T3 5MO/+jM6LTC2su2ICR2eTw5tpujhptHRP4+fVy6Q2PWIzoK7Aw7kCB2lVRsNkT6SeWXCOoOJokPI OFfUp8/XNORo1n3tDkUAQd6lPTuOJGRZqVHnt6XYDRXi0RwAfUPs8WG+ifsN2nJAQrCW8+jYIMVZ sBsSjlzLoSpZQTk7ag52EzgobEqtTy0DqWUquC9xby4crftKnxOR/8b4zEHs97qRbjw3+LNuuD8w jQOfXVlCpzMUc+WhwhkBeccyVaUiKUEHp2+MywyrQF4eOaa6X9jERieqnMnMHD1EiLdhJdsC44xO ZTSecJrB/CwGT7O1XDx/JIfPjrXp4fRjcnByIjdu35UiOm3q8TQ6FxRByGBzxQAIzTIQahZqVa6V /hPXYhntzjiux+rqUsKylNc/8Rn5zE99UZrNubz3l78riyc/jAHbXJ49eybPnz0hL2w9WxKIwOgu CNb6sPgeR8blnERw+vqPyRd/7u/K629/UR6dPY2/+0CuLp7LegH0aM0JJ+sYzGEPNVZCxvNQHqNS AGDFwf+kJp+R64HWDeOeq6EpShK9ViK4dkZfAiJGf1v0maCAgO8Bgjak2NQHio5nLVDgpPyG8kw6 HhCgDtA6BCchrh1w8ZDZiEyETZPoWyDQHS9/aomCoKIagzJqoEZfzjGDjXDsmM4aLbkXgIQNexAc 71unqLYajScIpNZE8yBUDJkScmM3tQIC+ZDI9jLeaz8GUGtQbRCYYv+tTVAYKrMYTSZ6v/1izD2H cXoj+ywd7agoJCSG1hvTRW2kbdAZj0cqBJ/p7GWuX6McWeck4/e9m5Tc2KynTUQxYB5ZIMn36PeY OG02Ws71pNBjEXx5rKLjuWBwdC43EpHaurb9PLOrvwdM0BSE/7pgpWkcGegyc38tBrhjqPjWOp+0 hqvRYlZVSeDQyT+QrNo07aYktGhwJgQrm9C84Di6a7G6NqUUum69/df432lgs8v3SZCC5PrS90gb KNLvebDnpdD0uva/dDCDcnzwex71Y61INo4Pf73caBbKbpeK5anGZCZYnkwCyQ5l6a4n5d3tv26/ eaPrWn15OXi/O/XF0qsHS937ItPPmaE0dNK18XI4qqfRQBQaXeDKXK+3bQew8ocaBhwwpmicR7YV cg0mtibHAbSL3aGZGJncOzmBV251ooh4oKJSHnB4QRdJEYp8t7svs9Io/i83YmvJwE+5RRD6RQKD kTIg6PYgIp+bU8MhahrL1gotI9v6aZbUtYnzs01oEmLHPZvRqEF51XYjcfpJqPd0xILKSrRQfc7n Vm5VmBu/i84olKPx63CauX+mOdaXnZ80gdDSVTcKjH9nWduck/I9dxHYjoC72Vo3Vq7dlu7gWyS+ yNtyAL5cS69LICp2EcJIKY/E7YzamgFb+KtWAgMovc4IVYN28/arsr36mDy6fh7XOP4+BEKxriAW x88YIdFplI/GtWeiqBAaEgfIXDQtb3HbIuS4FzjmDQjlOJ/x8zDMGrNws1AqJQBBN56lGXT2juwh rNhDsJPg6cDRlOBKlQ2vv2/8oAKfER07UpQyU5sLxwtR12E+bDmRjXT2KrPnuE2QOqdC7FI8pC1R 7jeduK3w0YapTaQwNtDfTIOzbe1VltROannHu7/brj6T8WFwsGcW/RwywUkqAKRgZJrg8NpFkRcI y8OR9oYDylGhMW4xv5T54lIeP0RQ+0OitgdHMZB75VU5uXFTDg6PKDr8yslx/Kw7bIxAgIHPXc5n dOrgmGHvHqyXdPzF9DX5yY/fkzfv3pSPfvRNeefbfxgD2EtZX5/L48eP2UG9uJ6p40RQG/cTgoxq rU1WeR+KDNHexQDh7U/+pHz8x35ODm++IQ/f+648eXJfZmeP4l5ZUu9ui0CuQWDUxPNrz7OxJhja LkWHeUZ6Yl3UalO3rLQ78tIQSGnMnyqnXO0UbAeQbTbDmA/yZ1Q7bzwoDQHv0wQ767XTM0yKKVPG rdN5O1tnhH+ACcMeqQduv3gd1ig1GBy2ZH/IwmgpVIg26wzpZD6yWiE2iRCkABIVdLQnzhD0ZGvy iVV7DDZOAYuMSQgqLS5XVsaADPO62VwAWSI2YmStJiH3OvigVsLXxGaXdkREuVSOv5gsFEeyNZ0c SMi6SowHhi3fuNkda+l7XT9Lf15YV/tOQ4Wf0aq091EEff9soyM/aHOeD0xurGzg3BdpZTWCIuei 0wKMCV/7K8SlkLQEs1MqAqrUlSL3y3v+fS0BGJE/dA5gP7jiBvWfhd337KROXiTgp5+53wXqzjcN 8PZLiOl7aQCiZNHQJOXULGjbo6SlJBOOte+5I/Lf4aiOYLV12zBw+B5kVLW0KNPuA94tc6YQ6/79 7AfSXXDn1pWyyuIlQv/ybMwNQ7c2Lwow40tlNeyg04hXBM7R1caMCyUSy/zb0NiHlbPDVTXN4NC3 BDlKGvYQeurQcRDyvil+41q2JNXqWFOXrJH2PrwcGKycKSHY8GNR7mejxkAHBwk7VXVkurBLVrv/ YlYYs6d+LwYRFKXWUWswKpBAcQTHD3x7UBtFKWq7P2hlscEnq5L9ZMFwpt1auaNeLd/JLrvW8lxG zgDHLhrnT5t91Ago0qYBSEGDW4l3yjoy3XlT3y/M+hLDDOPuAZxLsRR5gvj4WWu6cwRtNiAdLPcn nertKLFk7/reT4MJH/mDQC1FyFkGzC0gtz2tyLminp449o+mcnh8Ko/7o+gg19ZZL1reg8TNSjuL lS+JQHhDKYZM84i417Q0yEfmqJ85rm1jOoCNCk+DO1UguBF1Uiw9wgHkOgqpoWPza1Ub59aRtgAA IABJREFU0MtVziGL+whlwzKzqQi9IZGcfpioplu5iP8/XnNvFD83BqqhHx1dxUEklKCxaRtspqqa jrkanArT8XgksXmZVRRSse7U1in/5sVGLiaZjjYgUChD0gXd2bqm2X2v1t423V7zCoDsOSn/nY4j ZKP78GwwUaGHSQlbCsL2MmjNZTKyUWUeTMKpz2NQ9/jyqTz54B0ighCmPYpB3PHpDRkdvSof+/gn 2dV4fOO2HNx8jaW2IbTprq/jc2nk8PZIjo/GMmou5bvf+H25fPh9Ceszefb4YQy+rojCIWBLk1qM tAP36iAMZI1GgAUCuKl88lOfk7c+8SlZLZ/LD775HqsTZ08fyPziieQxsQiVdoySZATyvIMkQalF 7fplhpRXOpWFz8xQmrJWNJX3X/tZ1IpAVwmyCk2utAAv0SFwotB+rfIWW5v763sIsZKaIWvAswYp 79zGuYEWqKtJgLoA20USBvivLNNb8h0/Z2wi0ToRIib0PadtBe73PChKhyqgWMmTgZAoclebzBHm rvc0kye3T12m2ksOsad90YBLaSeBEixFNuINaekUAtWZobCOTDu4Ue9Qnvw5rMvSJi51UmTU8STG oE2eTnXhWdqqYoEHrn7u2EFcV+1rxQLW1vfyTl1TrvPvOg86pdn42LfAShnoKgU7ptyB7ByyjktE 1CnJ9Fq9uNoaGCxTZJnGNITERil5dl4b0TrthNVNKhQzzCqxclOl3LBGicouH4HN32S7BiANypp9 HkryQF72lRqt/UBnB1kLHvA0ml3wX7rFtVutE/Bsf1fXuM1K94MqR1sUkeu1h9idK74qd17J9bhD E9m9dv/s/Sz7ZQFc+hq9jg7texlymWb3HsClz4CbVDwws2wis1mvWusmoRV/iHRRwLRnlsK0eaDa DqQkIzDM4dxwvEAl2eVpwSGIuOBBcMNvdUZen52u6rio5BWy1oEGSbqFG1XqRhlf+TJqnxqWHtUg AFFBVYmdpzxwOlqIe5jdSgV5Tb5+rbyEdGupTjSzQKIkhA6SORHYTcXyhELl0RFQkTs3p+kK/Aan m5I9SdtEby04KnSyAAOZbWUIneqP1Sx1dwGdX2e7Bm2Q74bUpFO6Q9ER8ROHvn+W0kQB0jIkwtfK s/JyHs4j7YAhYF5u8DPh74GyhaOzrlyu59poASjP4fvmyOqmuza8H1AWlNF6lIiY0fA31Vq2KGFu MKFhwTIpynw1nmOlEzbYwIKynhlR2rRSS8AMFG0SDcoZHAPVaGm0JA235mv6mRKwfc/hGcKwQqcM chm0i+iKBteorygt0Dj8tyY2QxmEkcwgtIpxSJjUMB1TcBX2cAA6imw6PqzZjsISKz5zm/TiiOpO B30Iu88qea6+HxwVT5PVlp+TdfpaVeN2MBBxp6/gJPnS0Na8tR90aI3soPnuX/z9U1uYUlCkSUcD RkcVkwRPjrh/uU/02pCwbKITuzU6VqSG1YxSFjG4ujh7HIOvB/GMfz8GZn8ox8cnMpocydHNOzG4 ux2DtyGFX2+98Wl54/ZE5g++LR9872uyOn9PZpdP5MnZc3l6finVxYxnUsvlBasF7NSENlh8lueQ z+mfyJ23Pit37tzj+XvnvUcxsHwWt9eCSNvi6iwmONfstgfeRIsJmswKHacLQ7CklW/x84KOZ4zs wiSLXuZTcSryOCvtU6Fchk7r6RLK7tkm/iBoUwz/Ju9OaTQewBGVQVk9abDjz0SlwCjAbvFAz9D1 zM47LW2jTSxIgPo2oQcJOBKBIQSlGWBqwBVchaLS7llv7CMVBfpy7Z6xPZUpUuW915nDZsn9NkTU dWQl6fHB5n/avaT+F//zsmWLqAVLNBDT5Mm0BrE1AOhSW1MZfi7d/Gjfu12CmiXnznTfMu1e3q1u aCLfnlU8R+m6U9Nz7J/h6Hr7MwUPOmK7jg9KBsJLZrVffca7UHrTEWL3yo4c6iy7SFZqQFJDkh5m NdJJF2jqQPaqQ34z7b9l18mkf6efnb6vOsLtC4vmX3rt9pC6DzPYWwPYqtoNbHh4gr4OQQIyH8+C 3JGlzQ9aOtmYY++Ml3aZ5jv36CiNB3GOwu1nwul/t3Cwfe0/r04exAx0sEaMBOlsD/nelz8DZuvB wz3rtCEyS8ldlVYIYocs/g4cciMmgNqwHR6cG0Vr9HPQ9TrkEOeYRS5z6iflmTYikM5jRmi19kzW UImmsYSjC2LbZyPaaaR98ywK6j0jSSh0JEquD1d5U+T0xDUt1GiAZ5YG2un6MEAsddyQHmBVlMfH KV9NO2J5LTACTceH4LNEyu70gKZDq7qArMVedoLz7vlm6gDT/4UXz6v+e9d5tkZi7/w4L9Rf6++T Ol90qoVaGyvoWPG5cD7krHaodvoezvH0ppemVP297nqzdr/575ZW9vGJCF6WJSoR13M4OpBNfiYj lOCiQa/HY8HU28265hBqcjVRzhZ97kREYoxY1DpDkc88030Lql5hCSP01BBCoGyPZgmgAXA0EEwd YMpIX+fa8l56dl3+b7aSxvMJuJiOz6ZCxM8YxWs5PTmUw6Mb8uTxMzmbnUlxMYlODzOIJ3Et+8qx I6qsz4a8uEoTR10cG6mWJKrpvx39bFHRvSQaX1rOzhNpo7qlfOCV3kSFyQPd+2tXq3Yv2SihPftQ mU1x+9oJXO/uIf93zbJWpaPNzOfgnnsFtMsGxps0Qjk5dYoEgdUfsj6TQPCKh8P4XCZjwVRZBO5o BoB4rMyey/z8qdz/wbfket3Ixz/94/Kf/Kf/ubz52lAefPcP5NG3/72U1w9i0H8hj548lgX02dYL laNo9D4hsVE1zrHt0W71b39MPveFX5C3f+IXYqAylMcPH8n5k/dlc3Y/ru1csofvUXwcc5nJcqt9 7wcicdpZac+z6Z6fB+49xUpka930Xmb1ZzHMO/3JfW60T/fh+Ka8m+DhZ1E7UfsM3GrTxeRFBLWx 8KpFptMPNHDTZ4qYmjNFocnW147VzCR6iMQZtQL7n/QTJLJ6QdrlXHQSHAW7ZzseMAEA0TXGuDQG eUGbrWry1CptkquFDS2tykVjSCISLRWH1O+ziSBwH7fasUXPRgMarUa6sj4qgX3MTs5cnDfj7+p/ 7ybE/gzSJEP9gwaJXiZWukDd6jj6OdsHYPaBpXYig8VoXVCnNlzfg+jnXrkkdEZA91Vmm6tqeTP6 yVp+8otvCXnRKPcxKondVS+S7v31dWNdUaZ+LwYf16qAxOjXEYf0T4e8aRdgkXvjxC6c3xmcXWe7 zwvZX8CUFybi3WeKROrvBZMAUbdK9IPrkpDAG4X5iTBwZykPEJtSP9OzZiVD82EgkGg6tISdJ4kT 3Xkme2uSBq87GUdQJKtb986I+qZt9qPjvc8QC3T211EDZzjYngTrtKstwww+a7cyUVEgKbw/BLgm mEukVbkRwQL+gjyJQqYm1ogsj91pWLeY8ZYoR6BEC/SSwEbgmCyWrYKWLjO72p2SsQXeLFmyVS8o 2mbIVXtvxpPDfsT0Bjy/JX4RgYZ0DTr+RWkF29qOQGsztaLHHHiPYLPUzwCc32SOlphwrXXtgqdV iCub67PBkHeg0YpQGVLXNK0hZhDTzv7bfUaKamRsFNjfG763mUln/e6sQEC52T3/+8YmdRYd0mMS OGYkIROEtcnyXquliK+UYO+JDRyhEG3MaHCdfoCzD4SnCMn12dmhEwpK8kexHRIaLTJA1C5jpx2r 1YNa1xHnCI/Sg56eBV4WdDuSjzsF6doRAnjRfnz5gEEceCg2sikGYQzWCm3cyImaFjYnVctJ3Aco 22Xa0NHvj7hWsAejg4ncff11mb5+Qw5Pp3Lx8IKI9LKZyXPoePWmMTHqKak7UxS4trXXYFyt5Muc in55+acL4tIGL38OzolzdHQHGcP3ahOcCZxeZu+8G4gxKA9d8xM5cvUu53jfrqRUEF5DYwi23Vm7 Z1moKzQgCaKK/ZRd0HtaMCFYS1lUnA6QWTAK2zGBmn58n/HhjRjIrXiPi+ZCXv/Um/Jrv/Zrcvvm TfnBn/zv8vT9H8j82UcMlq5WhZxdVbK6OJNp2EhdnLBDflspko9mgNH0QIbxeVzPZjJF+Wx9KQ/e /YYstkFu3Lgpp/H9z8+OiJSvTu7J1eUzuXj2oVyfPeKMUXTENs1K6vXG6CqdFivDCvra+Hm5oj6c YNRIct4MCQvOwQptgOVfWdZJzBCpk0IlVtBMgnnV9K2VJdpWaWIlw8vagcm3ivtTRUW89OfVgxZ5 gqg7yu+FVt6QTGt1r+ugb8dmiiYETGbyrpTe6OYgx1RlNcSCvILXJCaWS/mnvGxLsPnQkXttqMGO 2bZ7vt/SQsAfa5q6TVp8f+mItKYNeFsARAygaBJ5rTY+UCTUz08r/ov3zneVHnaoTpnPu95trkzP ReA1dnpxFcW+u+faoXEqMYbrLPajP0cKxCJi8uCCGJRpqFNSQ6/a+ExlQPjBolIFnP5QduK/+46m RQFEswbfmD4EnK8Juwe//TvULaE9NRAv+/e+AUn/2xcrJSemju5lX7XxqPwh0gDuIT5Y4DUGTTsS I9KiJnAwWVD5B1V5lzZT9vfk5iqrjrQfdsvFHa9uF+XokDz9mQdxzpsQ6TI0HeeVDrbvuFj73MF0 TT3Y588y/SyWWBqt1zcJZ4tCz5kiGEGtP7kSQDZIZrdNj1wCxFeUmTiyxQ4PSlg9HswN517W22io R4EZIgIAdiaJlbV9n/EGHHXrEl3XQWTDiI1RCh641XqA2AIfX4TntorrtcJBBxmWyZT9BlCcrDb6 QbdeCMigt8UDbGR5HZKkUicI1Fx+og1skvg8/b46uUaRQRO8FuOmdEH0bsPGzp41DkeW8Cw6ftKu DI5/norB1jvX4uVNf52WxdIzXCvHi8TjXI0mMlEOYN90Om8ibUKSDnNGAJYH1cPTM1C2XWNANUne 9ZmvmTqZRrrAEIHV9fyKr4f+WoPOPzQMYUQQutO2awo+45bRyMCGBBN33iIAWVrJz0pHfL5syy94 XxgZmClIqokZnB+C+v4g7pP4mn7QoIID0wfqsECzyGxvFSrO2VAipc/X9aYjObxzR27ce1Pq0yM5 uf1xOXljw07F2Xotg+czOVsEubiO61BYkI7PyPQspQ4UdiY9m/rvlOKxO195P4HlmlflDufGgz5O n/AxWqJK85LYIU98Wiec7OOm6VDU1Ib4l6N9rnOpgbkGMTw/4Hv2lAhPJ9nouEU0v1XmdLPoYyCc XNsJQ3Gcgt2ld/TFpHAyJAo7qzJZV4V8+Rf/vvzyL/+CjKq1fOfPflce/fBrslqsZb7YyvnVMn5O LsP+RDbNQCdPxNetN+bDOAFARYzXK4wcW0u1/J787ve/Kf3poUxicIdZ4dPDEzk+fkUmR6cSBjco VDwYvyXTk5uyml1ztNZyfiGzGNxVyysKyAqnmqj8EVGuXCsL220yE9eDODHOKStB2yQ58mfeBSSV JYHuP9LX9o0C5edbm5NyJrueJPp5d7QMR6Pf68qGeNBA6bQxSe1ZnmfW+Kfd5FmRymvYuc0VfeV5 EbU97T3mSbDT2Cxb+BkmbrWi7zRxjU6OEQUMmtBxZ1v0SkKLamYm/+KNhS34YU0cuH4CvUlCREAC 0lm+51veePVCrOCVEdiyDslrus7VxlHm3bVI0XE+i6YrhTua3q2fa4R2Iv+FHzi9QI2Q/RDnot1w YrwLGs/WMXpg0QUe2DDQiCkrE4hN0LHMgplgGZrP7qOumPHONJBLulqrXei/NQDGgWoSwt/LOHEv ++/9bs6XLeT+Z740IAzSZsIp2lhZ99s6GkYozudlB7k6nArehm6yggYCHZpDyyLU7vcoMpoio44+ 6kHssrE15t8lTrwrTzi61Tlpvl3YRRvzJIrYR/bS+95BoLK0JG1SEiSZWombpY6CRG6WCAmti23O jlCqc+m2DMbGozEDOB4uBrcNMzvEFChn4lNASMcB6EEhf9DjgHmM62IMVuvw9iJXR8yyTPucnW/J T+4ORaZyODQSXGoVEtaAMGa5eFZ431y17fRQK+mf+l0hEV8U5QKRxFtCemVNkvWo7639NYP6ILmR YA2NwvPM5AWDgG+ipJwbmg2BUiJHfdWK29rQ8jwxFj4RhEPtW+JzJ3HjhiudSOKdhf6MnU+YJky+ r/fRXQ8CpNGkhR3JhqBlVjaE0XEn4dlqOt0CEipiQYRmnC79o2ec5bimS1pqqwj4eWrKOccVYRbn BDMRZ5ptzxZLdndeLq+11M1gMX6mJRoSlMcDb0m0UCxQzQzLBZcPAWhet8EFZ9D2hySwY6C6cxl1 iHsM0CDpkHdaUqwzUPqjT+ewXjc6KeDkhhzcuiVycigyfS1mdYeynW7JlprKViazUu6cB3n6YC4/ uHygFAxRzo6XUjtaxovJnZeH9FlvW2Hj9Nx7AsvnG3b3X3v+bY3c1ukLu8/Xioo7rWDP2vjRlXXF mu6oIxE+Mm43oddzyesz8jf0F9HYwPuEaoG+C21K1u5DIf8RjhX2hx3mcOADm46B75fX8uTsqYym d+U/+o9/Rb70t74k5w+/L3/yh78jq4/elavZ85gIZnId1/z+/Qcx6Qhy9/YtaU5O5emzBpoViiKh JIcKAJoY5kv+wTXNw4ZNUevZQpaXlxxef9HP5KO4J3oxWT+cnlBKaXh4JOODU85+7cUgcTDpy/T0 UMrZOXXYMJVhs17Ge1+xASto+MFOeL9frgG4prWi+4oOgdjeBWq6B9TWk6IR13PY7wThe8Y501Jq 3gYcboN6ra6l+mgvbagb6bpP2+7roPQCbyQgdpppIKjiwUr09/durzHxKfRDvYZlUqK9rY/WcifF daj7WlhgWrYBG5B7BJVqMq07X5vPbXbvMK5paMe8IWHB9z2wwvktfSxjoXY6DcrUZmpSju/mVgFi pSD+x2qtcl7u27cWxPl8VrwHVSjWnTainxEFHGpy7XzNO0DJsLSBTpUgipcVyfnswJuC+l1hovMk OdqqIVScK/EoHoScZHBmqiDnbnQ0NrKbrY1Xwu9Bl4mDpiuFJ3XAApS0/cOsjFWJdbq62QHgnbPN u2rWNJp1VXAkFwwANoSXAeA8N1VSPjKyqQZRnYp9Wh5N/+2Opy05irSLljqtthMu/pzoiXWGpY5L HeuWJGYPbzTo0oftv5fZLDeQYRfRsbij38ZDi8HM29maAcrTizOOFMLPzp4/1e6peC3D6VHcKBuq j2MzocuTcLN1JYFbUxnKxiAvccIcBl+t7Z4VyVGeQGPBlR7MFAF0h81Dkfs4sN1yGiWePNjIOkHo khy3jMEUnRfKIOw0yshl29SruCYjzfggRxIvYziYsDzFgcgsw+p64W98BlEacF56I0MY0JV4Ha+1 jI50IMOsT17WZrNkBxOEQbEmwn2hCAuDudpSQ+maZRxJ6NG5RyeHzsO4tmUMELfRas2rVbynmxpw xs8ps4GsIOhZDCg0HMKW42UQuHCMUqWOFYjQ1rql16W2/jdZY8aPGqUaSDDdLlTIs+W2KXqaN13m 5XxJBl9QBO/rnsutDEUf0+o3asNNV96v2rNT+d7OO91AJbuGdr9QS8X2MTJoTaa6AEH3VtWNeCpV k47XB/QPRtuyf3ZqRpuBskdtY9NAwVxvKnYNA61Cp1vj6GalDRqNGXA8I0zxKCnJF5/JpiSHCPNc EeRvrq9k9fy+bC6fxWx0zYaYejTgecrH8f2uFiIDXNuGxPKGYraqiaZdkIESLVtrJgFXRtHaXJsL KJ8TA/lGRwcKS/CZjCencnR6k7IbKFNh7VDWg4wOyq2Y14xxU0xoo0MvM4iaKh9u1YOcTiYH+TRe 25Es4+t7TGQw1SL+PFtI/+ZAJjemMjweSXhcybf/6oe8nsFwHPfTUrTYFm10PBOh2iTBkAfBnfyQ T/xw5MsRFj66diTdrt30Z+2BA75VUkh3dx8QZY7XTloXkh2WptZ8f4jFojN3beeAaDm7Jb1MFXj9 EKJdb2cxuIlnBrKf0IzLawroYq52yEaKdlO1YK0zOFG2s+7vJo+BXlzrQMdeamUIkjVsHCjl6VUt r3/2S/JLv/or8qm7x/L+H/+23P/Lr8Wg/1oezy8lX4UYwG3ko0fn8TMHcuuN2zH4ir97tZHtai7T mIWfz+LnTV6JAfxILs8eRl91xYCxGEwZIBhdzxx8ofOho99bxOBsdvERg4N+/yHnXCJhHcSEdTya csxXb3gso2E8pQc3aeMxc3Mbk384ffy7ylUzFaLTZHZkOu+Zlho0DJxfK3lLqHb8G8bOodmA+oQs 6zct/SSnRmf0L8XAJoDU6ssyLbEO+7ChSwbSOJfwsx4Awrn3C6US6B5TDlxTJfzd+Pxijh2fyZDP bDLQWbg+xxR2G39jHi27SYu+7c/CAizNpzAvNbch8WWpkxhaaSbYU+kRrRyOR9zPs6VNgojXBokc oKxFvxP01ZFc2gSD2AI+XEueGviiehA/kBWA9QoBYsFrzqxhSXnPoa0aQEWXkafpY/o4PI7LpHRA vMe1+uAeDb/adOiv4ouqDTZFI1WuqM2X90gbEFYEtkt0VR/xWa1ALRqgfDuRQjOxLkDp5a7+nVOn hKM9ZJcUu1NK6WpVSdmFKbhCnE2iudbVXne+ujJmpsFi2IVfUaLyxdGMXnW2iAyG3bKfQ5ptEJc7 eTEJtFKjZyWC0HTBXjqb0jPPtKT7Mig0zYapsYRNh26UKilbtEiaBqbQHmJQS0gZ/IaGZE0I2GLz YCMg+KMB5giPLdeUvCmOELVr0FvQv9N1bVIExdd6d+33GzP8339TSbm9XxqAFzsY27Vgw1klPohb IW4NEJEhjoYHNmops7JaN6wbV8amjyDkICE8XjNbRbajaKYjxxVKLhgVY4eyZ2UtjngTLcfptZqj sj2jna3aFafdrYFq4ltmgcq9qa00m5YV8aX3krXrTF5cNN51r2amyrbysjRo3BsgFBWhdhjWAyKq tXZMinQjzlQbbSnj3sA+07pUsae2nd4aBzoDocv7XUJSqb4TOjqZGSalUP/jezQz44xAGvvVR1Qh KGWbPNCz8JLuZeulg32gAbIsH3w05QfqayEEjOuCU2d2jnIGkTdtqKmtqcClObCYFSVLlDdbx/uC KPC2MvRVSk57wYDw9Wwmi7NLWS0bmY5eoeL/YnVGEdDprVfkcz99T27ffUO+8fU/ka//8R/HoO8y OgEcHE3C8J4QUF6XOv0A/C8NcgPHZmEfFD3lwLJsif0ZA4/J0bHcuHWbexv3Pl8uooGNDjc6phU4 fAGczhh8DOI9Vdcy7g/J8xzHtblxNJW7r70h49MbXItBCdumUyaKbBiz6omsNhARjtdyK8gb4aZ8 /7s/4JouN2sGBIN+zgkUFUVb25MnzmtKz2L6zB1tSzvqfKxi6vwdMeXzqI0TG7rAjjandYqqvYfv q5Zd4FqV2ZZNCa2ttLPdSzjYvJ6qq7zs2xBwr5DbQd4jUFdPRyYRobFgGzqbvbhWCDAnvQOeGeiv LVZxX6yDfOErvyq/8iu/KNP+Wr72f35Vzj/8Tnwmc3n46AM5v7iQo4M3GCzdunUkJydHcc+t5cP3 fihnT54wUDyLQd7h7Tfl5p17ch0DhIdP7nM9KIW0rQy5Nl504md8rYI16XQ6qtH5zubxTF4wMRlO xhr09sCz7HFs2DjaxLqeKC92vaCQPu0eBKM5KalmKRWNMr28siBbObU8P5XyjnkNhcpfbSnIruLR QHRyvrorW1Ym2D3kxA1taHGbBfpP4QFMfJbT6YQNRD4ySu+3aCVpXMiWKBRsdC9v7Y1rfW7LNW0W uatV2l3riLE2rhmDq/Wbbru8VA/bjFFnWZG3CD/2C2RmOBt2qZ8LW4Z1ZhApip7Pov1Qvc1BW5VI kxy/Lu7rsAt2uL2HXxJHl+2aaB8b96nueHfPpp8jv1af49rOcs20matHMfLog8pck54MiggrTWqr TAbQYm0S54TH0Y+R4QAGl4rfNbPXNmij4U1I0dgA5e44Kz3hQac4VJV1+nXOyV+nztVg9gTlkgQ5 a4MejHUR7U7LjL+EiQY671CNPa/Jxto4mZHBkzMqrfMs/aITd6Jg6IKX1KjVCX/IS8dN03ECHX1r 6o7o7VkvwZZGp14AnfHxSSip4E3m8zmd6NHkgNd3fnnFkSrIAobTQ6qDQ5zSu1zQJAGHRnHgRpGv LNdSIYPpRJExRc/8j1+7GA+sMVQuzcL3y8r7nJb9MjOfn/jayc7z616pUhb9eGi30dFV0M7CoOxo wPqDSTsWiiNxrFRMTmCjaujM+Tmypc/SG9cWwe7WeYQWkGEvlKqtw04wlGQyFU7OvGbq99HokSJ8 36iDJuE1vn4do79V1eMYF85UrX2GpYtFKteCwaMBaPqznjlKQ82sUUGNd90GXnrNSs7HrD2iJ7mf KYXqFfEMmik6spXnL4j4tiWnJBj3RMrR6dQ5+7XiiwELYYSw0+WonBoVmPRyLbPExsrmWReQ933o c0KMpxGy8wAZFe1C9nFndbs3uH8AszXZTtOUO3gkslUxjsYMI5PmcpANWGKaX1/IxdPnisRHx33n zivy2u27dKqPnz6Ss6vHcnA6kZ/7+Z+Wz33+y0RK73/woTzY6IxWNlVZ0I5nvOXMX+2MZCIEmxfP IZ7SFjIQMGfxesDZJMrTg0jvkDYOTgFlWzTgUAdrNGR5iTIL2D+bsQY7g1xOjqfy1quvyp1P3pNe /FtGU06rQUPDNTr2YrY9jNcx2KguVtaLwfHsuVSrKxmMbsiq0cYWjA8TnxUc9DynVIh9WsWLNqBD 2yhTYs7KbbrX4hl0S1eqb+qOQ9zahVBbGd+6W0VH0YW6LV4ouprtBmlw1nmmOoJZ3tn+YDwm7u1o J8tqhSXXBru6YTKAMxlsFnFxihFPMdGJ+wTHd7uZy9nZtfSnN+VXf/0/i0HcV+RQsvWmAAAgAElE QVT5D78p3/ij35Hlsx/FBGgu9x8/ksvz57KZL2Wz6svp6a0YmExjUv1MPvzgXdplNNQgiD+4+2Py 6r235dard+Xhh/H334mfX6+6RpGQt/4gXVufypJxMKAmaNz7OAOgQjS675fL50RLqYGJQC7a/r7N QcX9DSdTvt+0PuAzKjmJYtn6EsiYYHWwRykM3HSBELbrBsFz7fxbHRXIFa7YPy6zcqPocfs8jTRf 28g1m/7D94PfEm1i8DgA3eW1lcA1uNEgGwE43o7BWtHJDPWNI6tB7UJG8bnRx3NSi5YgnSu5w4Gn j1PU26sW6rc7Ud6qSQbIJ/PHXbMNZ1WBHdNoTbq29fqLVgzYG0Y8mWFIkyQravJ03qrPUu+aDhLa VrIv0qqWV1z8Pn196yR2gT9fLbcymBzGBK40QEo5xwAJEEBizm6x76RHmJEGQyWqyeRjVjgapHYl /87R68+NZ6F3SoPGC0sOsUe1+0hYq3KfWYaVcMD4Gf76qt7JIMmXy2XntSkil/I/2gMmO35cF7xO jAsTzl0nmaIPaXDnn1GXuyhgZpkJcQoEAOttaxwdKXGk0LsLyQtDG33TObAWJbLPyS2Dgf6Udgxp 0wcDDVFEiIWpJiTkS0lIrSkhOYh3nYYkePX1TRGndG3TdWv3jMfttfHdQsp1qOiguEGp7aRt+Zg0 MLI/RMuC6hMh+0OmTh046MnFPz2DrbHlAH8P0eFnWUoVnfI2mEK4dFptyDrJGYGjyzU5wcFFYqKq rqG98MyDWJQGkA1FQ3Fd5zKrMSKuUFHgHXiz5oggdzSebfkzphFAaXGjXJ6KBka5azBsWt6yCSe1 InZiXEhdY19XddD4Tstp6nVGxs8ijH+KdqfdUKUJ0aY/d4PB7B9GwwRiOSBdunZ5N2RGhlF+kfOv yPu05oBtt7892265ciKthAgRvtAFAH5N6gSsA6y9xo5svSmBNDZ0KPP5teTRSQB1efX2WyyzYA+B lnB6cpMO4Mbla3Jx9TzGRz157Y232VncH05kcjDl2dnMVyz5lixpbOlgnSdKQjfuHdew1dml6ISD CHUY9FrHisCaCDmM/mgip+NxTHwLuXE4ktPDsRxPRzIe9ijqul7HAO36WpaylqPjiRy/ckOym4ey nYykV0Z7AMcyPJRRGJFOAmQyP8CU0Pj8lk/lu1//mmyuruTg4FQqTHuAoLJrxgVFAVJHVxn3zM9o GtzvJ2Nt2SZxWkAldkjfbttqLTftf79ubXgghcBtDkZflTYSr7MH2McaJGgFpwMENPAoTD4IgbU6 arwn9ynPcwyki5xjpa5n13xu1WAr4/5pTIRrudhcypOrpbzxsS/Lr//6fymf+tRd+fof/Qu5/+0/ l8HsTDYxIP7wow9i0A3bAVLqgM0Fq/kFny32z1Vc67IuZHhyyuaE0x/76biXDsH7kGw0ksFwFAOp Be17EVSitWk6zm2ozS9KvbO+9Ml514DmZzyzZox1fM/VcimzbNbxp+PrMbYJZxWoktJOdESVo6Vb TIBA6T7awjUqNSXnY7KbGiPAmJhkje3tbuxeIz7poWZzEJUQ4hqXmcuVoKIx5vMgZyx3QVsfw1lb QINEdJuc68qm3VigI1pNIQ0oyzhFATYQCJyDHQoE5EzUlTum+pmNgxO2VuTHeUDXVhc0SHOkTAPG fAfdS9HjLLGP/L0EuEi5wD75wW1qi1znHR/YRYzT5sE0KNQgUSVgHCSnjw4dWocxfJgLjC9HANvE O/4b83dBQ9psL+O1j9nME1NF2uC82DC4LNJgBxYMRhFBXG4CkkJ1YhYx6Fj1ArU0WnvLeqO6MmKa auwmE438izozDod2VjkXjpm5BOqDNUH5UXxQWRfEpOjQfoChslEND0YaIKbGyo1YikakUxX2s1Mt s+2VE0P3sxT297+rWg9Im/Hinm28B5wMuQSEDDWohb6UimTWMh2NWcOfzy7ihorrPsiZ5RNG36zi f2P+26QNWutcW5s3IbTl5bJRjqKSTrrC8YvXKzubNQSdQJsKcqZoqv+9X1LdX7fWIUNFPomQFUmq W0Ims5wYxAGF7I+mMVnoEcXZNoZysflBOwE5g7fZEifhaBfiL5rxcKRSrdkLgqC60XIlDUrL/+kk MLZ1p/fTIJBWT6QZXPy9gc7korJ5GX9/1uRyGT9zSWmHaHig/M9RaE1XCrXkAUujJdO6hddpSFAq 7SkPEWVDZNg+UxQGrete1cTF1dDZmuFoGbu1MhJzV1v7naQhwZ8LZFfagCxB5NokCchnpeVsrk9u Ad5WNYYcAdMu4bSxRa8fXFVNQAoGw7zPWhE0fW3dzg5Mz43vP4oVByPGK9zIxKxqusaKbnMpnQLz Tb2DtuDsQwiqFtziy/lGpsMjufeJz0fnehyz1CBHRwfRuG25Fkc3x3JzfoNO4nB8Sx7f/4iK+ygX oXyfVz2KLrMrFfza6NDIDuL+0YHt1AvMwBFqqBeXYWQafm7Dwa8vztgtCm7TIAaHd++8KrdPj+Vo 3I+f2ZObJzEoi/+u4nO7OpvLdjmR+XrBwGwEJAOzFWMys6niJ8V76AG9qKLzCitZwnGiFH/9VM6/ 9e/k4Y/ejcEDeLELKQuVSYBqDNGPehkfWa9NJPy515Vr++U7z/RlDVCeeHiZyhNMEZ/TqOdPm006 uaK2pJUnFQoDHvQzFAnmlrNEvcY+bpUNdojRllx4A4R+NvdGDHaXGKIeoK0X9+PsSp4+/EAuL57Q H22aody69UgeNUu5LKfyS//gv5N/+A//axnLpXz99/5nefSdfxufdS0PHz6Wzepa3zf+LQ24k3H9 t5jROSMNo45BcR731mh6Krde+0RMAj4uzeiGLKMNmF9f0c5iX83x69g3hSjtIrGbHFbePo3OZnqi Vlfp97HXhuL8ZE3MtYzIedbxCtfLVZsk4ZwhkMM14G+c+6J3JOOgEhsI5sAPRvKASgZHyoHEz0S3 5ni3qkAjAva20leI+kffskUDDMfBDJi3bWNAt7ZABSDBxhqpaGsG2rRGpL3aiGqN2tzboMgjElgG SvBnUK7GOUKCiH0jSlPqFTGJj/YQNtxLnl518v0HeJHlWQuAmKwXmgwjcNvaVKHCqTpN4KxX/D2O Z7COwScQOKzZMAbiixgoe7LqcUPLUwe9AgHncKz6rpu5TlOyL/d1LrydniX/Ofd1SJ/+HigVnFqj dh/X5sBH619sDcD/n0GrMNvKQUwMcVzWi2VMWg7imdjI5WzBJLJopOM3IOMcj4baFUdRPSXyirjT 1kXSUqhtzNqNthevrcEAwQWCGYtiM3sfCarGzs6XqiupesDUGiL7XuUOK/P2YTNGLJ1udSzOHpyZ Rt7dwklraFKodX98VwjO9uke3A4XKHlw+judCJ9/ptfZgZwMB7q5vNbd73fcJbxuPB5qXTxz/R0t u1KeBe9Z9FvoHH1vBCwR0LVBrjt25WRooY7hGYOUxjY/n3Nr0MU2p0K2rSMPiWagdOsSdjbl/leH ajUWINlTtfUw/UCgiBzcPYiBXE87lRhkeKleIfzGYGvKqzQmYYB7SZ6xP4/cgjJFgdk7xPXQcVh6 3etqqWWXnnEmJLTPmOgYSLTM/HMGcNcxgFgD6QQyCpRrPtNERnSPs0QJo9T0dTtnqmzuz57rZVwB vFbnA1qJHSKUjZYFckO4oEFVFNrlKHv8TtyDI16OkO18TrLX3QH7a735Zh9lddmA0oxy22m8V5bL TBCZz8PK1O0+w/r1iu4agQpsTdTZjKM/H/LzRHWiGHQnSulF0TNRWQ8yLEmz8UvgyUHlfhl9+XIV zw/0+zYlyedvfuyeVKjuROc0wATzsidDaBZWIxUwlXhuovN+9viJzM/PpRfv4TgGBJuwkYUAzVIN siIDmVxLx7BZII7345nAnNR+z4fFB/ZHDEJc3+1clpfPdDD59IjfvzkdysdevSPTeJZxhofjAXSE YsBYygkc0Cw+i3nOQeEZBlxcXEs2OZQiBgyoBEAGFhl5/C3prePPnn8kF9/+lnzwp//BSrf9GAQu oyNtmAghsERSzGdjEhRaas/bs6DPO+FmJXslFf71Tj0dVZS3XXSp+G9rJ5o0CTSOXa3K+47KeANO RR5siugl9sRKfiSGo3M3mCQRuNdWZg22p1VQo4rPIrAZ4dF773CiAnhvGGg/jr/37P0Y0BVH8o/+ m/9B/sF/8Y/kydM/lz/8g9+W8/c+lHF5LZfP53IVg//ZPDq9Zs5nPFtcxvSgr0jUIO6LuK6bui+n t+7Jqx/7tExObsWgOZdFTLC3KIOioSDa4sHoQBZQD6jWolMJusYfU+6zU6GNP85Hdd+ha9ChoxvT kGQDVpbvvKbxJhUGWGtZLectiu5nvDc4IErXH8UAqD/kvXBvbjUwarbaEMcRg+CMohyLCRD093Ff I5EqGjY+ALWDlmlNmlRJuZ4wRtKzVgmoQZ+8USRAedgyMOr1NUnD1SrvTi02kG6sBv5GIOc6drhW IvZr8G6V2whNUMQKZAmgkbFRlAr+0+1WWsL3dUoRLyyg2j8TEK91BmsqZ1RWLgsirRhv6k88zkmD O8i/0I6ajApf7wG7dPFAViTdwQkQtOMpXwYcSWU+1L+nIwgxlxtd/lW1iGvdj4lH4LMc9NBQupJ5 fL6T49flsz/9U0CEg6IojXM6BtT0Ag9IBXvdcVpmD1SEZZFGXGOoC4pMay2ofjdH8dg8Rg+MmkxF X90IbLlg3k3ZvHCT+Kp8/BaRp62NgJE2Kk4X00u0KVqxv4BkwzSy85o0W61DIsnQlge7QEV/xRfe g1OxsnFjGylTiJe8gK34yBCMcAE3DJsC2R+M/nQ01RIhREtjmt3PFa3wzpkBVOJtVFVbaiWcXndX YZA+vlouAS97r0O36UpZ+9nEyzL1NsBLywD25cFeaHbXJ81MqrorEVPHC4YAkQM6CRstEYKgjX1Q KRBjqFPHL6BKfb373iqUm7VisnyOtXKFqAcmzrvSjrV6k7fOib+LgCNDybRkh+EGPLiY9a2ArFkp g8XqoAaVg6BtrnCLchl3D8GvLs/uoeVYMOl0itzZZS0NQCyAU/5InexH37nNpptl6evBZ25xXpZr 40VVdWRfNw6K7BmijukFmy1fqw67EO1SdgQwOb/SBfNtEFgriu0JVIvAwoBv1NBVhWaRPA6G/NbJ OU4RdSNRWFdiper61gyRiT5L3CO6gItRj0nJ1dWlLOIfzBQ9uRGz0vhzZKTlRq+Z/KMK/KIhEYzL y0u5fvaMaMvxJCanMeq7inF0HQOAqhdIXO/lIN+v6FSwVxDmoyOsn9UxKNQGj4LK9Fl0Yhn5WUFW kscsHUrQw/ymTOLNDOM+GiAsQEf+ain1dsW1XQPBWVfxdfE9bx2Cr8I9ny1iZNqP+6uI+yJm1NcP Z1I9fCjr978j14/ekYvFTK6bHrv45sv4bAc1O/7Y+13q86BenWiw1CXBngB0SU9aYvdz6fQOBHGO VHi5OC0VlaWWWWtH1kOnN8YgBIFpEnxQmBbngB39LlYKQn03njEk3bNY18ZGMgU7K/ieXzOQm3E/ p5TMk4cfyEUMcFH+gyQRgLrZ7EqGR3flv/3v/0f523/nl+W73/i/5P47/1YWz59wSsKzZ4/lOaYv xMRpGoPreQyglxhiH23R9fVcpsMTOZ+tpHdwQz7xic/LzVc/GYPmkay3S1kDiYE972nXcq8/kMn0 RK57E5vt3J152tIEDVVxeCQu3USVlp/dSsCAc+v+RBFNcgm1ZUglN2qVlgEHMIiWoT0BQxA87EWH fm10m16H1IF2Mol+JZt0lTY0ItTlhpqKmElbb6JNQNAc73Gc6Rzm7aphswRuC1USdnZXG9q+A/MX RI/UEsoojPn8hMuhyCzlw4wCVNdOWxIig77vyF8POhsW1+zBUbA9icUjB6/a9SciuzxPKmDYvkHw g1GN6GClekTcm71B0c4trUzay5NYR+DwfkheEASzGSImjABWRsOxlOuyRaR9NGKWDLjXz29ayRRP eqj/msxz1+dbKVLZdL6SCGCCwLk0Cf70s6G9V04bjqrbfLmWeXx+Nz/+GfmJn/k7MjpiWb+DyB2y pZPZliq42fSSC1HyeopCtRFy1sHmfMAu1rqHcklyA+3m9+CE3Xrd8Ox9vp4HbR3CIG3pYB8tcqMC R1okXBzfDLw2vI5ojuygFRpQ2kFLUbtmd7SJBouds9MSX9UOrGbXlnSzCJ1c6ZsHDyprbLSWpjOK OCk2If2gIoOdSKvJonDzWgCzH+0na6WHt9Pc8XVh0NEGEt3otDRQSIPhNABOy2VqrOQlw9ubNlgh pmOvARGzBvoiLnxcM7tBAMFnWqtGW01hbr2TImim79wDR5oam+Mn/t+VEV45JUKDSj6nngeSteY8 VCvXcncRjfIGMiENhtQX0dDn5DlRVBKlnxigDYIiEOokO800LWsFBqBETU0bsW2ogcMKLnAbWv6F l6H0NS5wKRp01RpIZZnqbrlgb1p29Pf2/Y7OLNeP82vD92RrXNBGu8v6aPaol8y0g2kchazrTPTd o89UB77DOa9geP2M9rqJC9i74GdhVikOf1Y44tOJ+a4pL+PdaypYy3K4rQFb9+O6l95Ugaw82Jg/ cHaA/kWHOVttyYXC71xdPpc//8YfyBtv3ZA3P/0WJ3wsFzDQEp3Zmg5vHA1xxk7lRTTCK8ob3Dw+ lsvqSqpFn4EQrnWGjtJG6Q8+qIfrS9kcpYkMMitvYGxOdJoDyt1gKkQT/13L5fmF3P/wfSnnF3Lj YCwnh9CPq8nBHAIdGZ5Kc9STPpqXjoZy3Y/vexGvK/7Osx98T1aPL2LQ9oGcf/ghvJwU4+hs+1fS i+9z6/Zrcna/ludXFzKeHsdgAtppuWwXK5aRsK9BfVG0oCEq3WS+N17M+tPxf86/wd4ADwzPM91X buvcNtOB1S928CNY97292izjN0oiNn2W8Zs2ieNZts/dTQh3k0N9X7fVMfEDAhSfxeMYjJ0/fSCD YcGyOMpiPO/jI/nFX/+v5JM//3n5k+/9lpz/8K9kcX8pD2JQfFE9oSxDE4Px7eZCVtcx4KwGUm0H MZATmU5vxSAml1t3X5U33v5xOX31LblaBLmaz9hkAtSDMoZxSdaVinmjEQvSIuvNgtIQ4vxNO2vK PS5pl9QGuu3WII96q2474b+yLalFbFIRdreQy6YPIRg6ryBKsG9lNhIOKGbAtIr4cQT542ct58oJ w74Y9oYxWB2Sg0wbMDiUfKzVCgTnRK7qRbQJMTDY6L0g2MbQeibRJZK2tXGUKyZFq2G/3RPzuIiz mIz0qYuWx2dT8nNxfTE3id9T+giCtNF0JMDHceaJlMcEhME0Z4dnNqC+J+PxoN1fbAIcjFq+pnej pg0GbGLDnmFgqILzCMJ8vwHwWbNZcNBWCdC8id+HjutkOGpHY+IP1inPK9OfG4h3orrf04pl1iZA ufkvnhsDV3YRVU/MXz6C1BNvlxjhNBhrgmR8UI/iGQIVJIt2cBF91Eh+4st/W+791Nvyg4dn8tV/ +q8hil0z84E23HE8fEfxDaeZQpsBs+FAJI6ba1tpdyoH3jfBCKiomyt5EuhSCc4cNHtAUs8bagvl VVAtG1GgpHY41HlLyH1z0zlDJyEVzlV+IB4ZOmv8HH4J+nGIdTZhoVypRnknYgrsmXXZpcKkECVo 2kHRSZu9FepUUDh0Dhj31+vI45SPaOod46XQukqAVHXCYYKTc8cb37cXslbsMp3WkCKGG0McYIAB K1fWcKBlUFELggPeaHbEMsNGszCvv6e6di1J3EsnHBwcumu0QBrz/DikOlPksAsU3ZlLm2VXZkTc aPuXAjwZ9bLUqGTSZ8uzZmQlSeCVTKGcjpb1TDkfw6Bl4nU0QBABU2EC7fBlUEZOofIut3TyG964 6tFVimwiM477FWsB5A0dnCOco1yJuOBZIGDYxD2CbIwDmrOMBHR0/q3iQa1GQDWCrOO1XEVjvi2G bBSBbUYpdbGOhhr8u/6W451AJC/jwRiCngDkahuiIaqI0Ijp82HNtqaliCw8L3RyhUP/zLMtewu1 TrHemgyJzinMKcuRFw3FOJtKddvyLIH6xQm/gc0imenCeedn2fjz0EASmTR4p0SAPIGpVc9tDWpD Huw69T1rnyXYaHG+Kuu21Ku+JRgnLOf587OGhIPdwaZZx/kXwbmJW0710HPVMCNVh22SAjzPPtoJ gXdGTbkyrGUTX7aA1Aw6nCcD+fCdd+S3/sk/ly/95JfkEz/3k/LavXvSxKT1itISG7mMxrkHvtsy GuPFgmWh6SS+57wn13i+8bk1MPTrJbWtUHpqLCjZIvhFqRWwcFyTFTuHV0xEVnE/jaqtTA8LOqFV NKpl9Uze/WEMgD7+lhzFQKsancrglVdkcHqiJVV2X8f1m13KxQcfyMN47Y8+fE/OnzyTGRoeyiU7 eEfReU360dnGnXb39ONyJwYW77z7rnzjowfy2puf4ZzWcr2RGa6Z+xySFEM2AGS5ipQqyp+1PM0N A/x+G6h7IkkpmZU6RjhdBF34PtAHDdh6hoomvLXazqd0iTf3CFD0GNCgnAT5FiC/m3VFdJOE/P7A OhF1nBCuhTqBoqOVVpt5PE8Tlgwximo4KtiwWzaFjKOzr6IjXc+eyPWzh1rxwSilmIgMh1O5XGyY GL5arOXpv/9d+f6ffk0e3n+fs2+JZsxiMIbubULxMXmM94Auvzx+rz8pKE67uVrI5OBQ0NfzLAaz dXwGR7ePeK/oAp3H58PsD3u6Bp9MRZ7B0RtArwuBV9zjW2/20yHOavNxbs2e2hIqmt9hGTCSRIQ7 x97NuiaJo2lsUgnew+RAksRrHZ06J1ciMamNaw4KwiYmWZuZ5EulT6Cph1y6Xt/GGw7IEct7N2UI n1FpEIG/Z9GHw92AH1ou1E8AIUNJG2caiQRs8Wy7kkEfempL7nFW8agi0PDf+FPF+1sy0CypGcnq hSgXTDtCe0zSEVhpKb8mLx/ULmw9VA+4dvHZL9caEGIt5gji40UO+mNN+iBhVeS0vwi+cS/LaL+x t1DOZQJiTSgeMGJvcpRaDGKH4ymvBwkwu6J5ftZtMO4gDWMES375b+xjPLdSqByB12ziGuI9glEL FP3zueneWGcJC/i/9YbVv5wHopKLaCv7BxM52NTcs+teJednaL65KT/2S39fJm/ckn/5//65/MY/ /qo8/87vMYISz4b4kC3S3q/ptu3n3IxKsvYokkY420Vs3AkECmbm2llCKLJpZT2c/1Il5TsPeFxX Rwsvjli8WNJ7GQKXRsEtgVF2y6tpFBySrLVJeEFpMJR21KWs1d3S7y5ny36wg0bqhuxKuDoz0Duc 1IXyOjyIa5purmMIXcevf6bdqyM86Trqvy0LDF3JU+w+KEiYjGjZQUz31nb/fe27O5kF0Tw6mIwc KWRaRT4itIwSPSQaVuiWMlSpHyMMOI5W6oLlsy2dGsmywYqilglVFgiTkIt7QakHdHFmlrpTwHHL 2bHXY1wwNPQOASGEq4d9HcOzjJ+zmsXvTQ+YLqCbjmgaRTXj9+MhHIF4i4kbmeoIerCrXCB9QG35 0oJyRzOwUtpVV7comiLGop3WnDcZqImGbJP7dFu2XAwEoeiArGzCSSoDoAFhZettwY6VvfA+B1ae QEPElt9XYrPOMm0Y1GX2TOimQZ3YNi1Pj6Tq2lG/Hud/FpmXZLSrtjF0ezKZsDvNJz9QANnKBMxi G002wEGrKx0no6Xbss18vZRSWzLlk1pwjRDcXESnD6QRiQeeXR7X4v0P35X3331HTv/g9+WTn/qM fPFnf1be+sxn5ehowjLa1ZMnsrg4k/ViTlkGrDfQq4ZKcyotgoBgg+4+yNYYAiS5BtgUkhVNstgx jXJKDFLQ6doD96iPLL0vw4Mb8vpbH5NPf+ELcu/em5zmADZ/Ha91cXUh9z/6Czl7/FiefPi+XD5+ JMsrKPSvWt3Bfq+R8aivshJxvxycnMo8bpev/+X35P0H9+X4zuskWusUhFx1wvDAQUcAtw9BMMug OIOdfhWJ5rmONPJn43yqAYK+upvBqmddG1v0jLt90qYV74RMbYHv9U2z1jJirU1dCChz6ZC8jsek zTvtfztKn9hVfB7Pb4Az1oQRd3B5eR7j7UVbwWi2XfkJ5cHHDx9IVi3l/Q/ek3e//x25dXqTzS5Q 0x+EgcziesNRY3IG17KnSMdsPov7s5AfvfNDef+jR/FZnshh/N0bMQgfH57INAblE0g5AEVFdSCu a38ykibasY2tXO404KSM3S2USNdqltrN5N+qr0I+5v6XYm/VC9/feY2/TzDgrv2ecmxT7uNqqUPf KeVkzVA4V1AM8GYJlCJDPTJnhMB+oUEKurlXtTaZZBXfA8/x6ECbz9bkNK/ZyITEEfqLV7OljON5 aKx5DXqgfUOaPOGlQLjZymC2lSPWjN87ikEibRKQ5I1eP5E87D1oUIatBnGssHR+fB+FplKCdCoC jkyjodATbJVzypm8+f4urGIGe0ublnfDB0g/CIoi0hZ7krwtW8kVT7zTaqZ3yPpZQ3UEAvj9UbyW QbQ15wvJ49ptoAcZA+36+TUrKW//4i/I4MYt+a3f+Ffy1d/4p3IWE5sbo560bGkYzIPpWCaQjxYl 9Gr23QVzdFDIlnPNMqTuWmrrrLYOlHjzldbLs0qzeNKVzLGJBRSUxaBSsWbB2IC9zCY7yItdkWmg ocFPTbVw73Li96R5IfDwmXtdCUs3Crs7Q2bGO7z4WZmKJDrBXrlySuCUJLjrulM8GNvtzkMGlG6o NMh0VCwtMwsHPWu0vntVdjitW4wq3aEbmM6MrZGdej3184y3oftH+TNi2Zqr+v9NAdz+f6cBfmOZ ogcXdMZBeR6c/YnJRSgvQRUfmQ1mWAbtfsaz7yFARZAdGisfVszuca1ZpunXuJwAACAASURBVCro 1MepFGlQhKnXkrrR4VRzHJHqEbJ8Z3N1A1lSG+12pJBSEw9kxWnOxfBQetGgP4+BDkKaslE9uV7Q /SqVSipoS72WYffXAcZJtZPq9hB7AwIDKhJjy7YEzxIuR8toMKpobtdoUDv3M+iVswzdT0W0ff05 WIz3qa343TizrvQaOOS6Fc6tVcKDQ9uDd6TpSKh2L7sYd+MlZGG2jqBuve06F90Q5syimzZo6PW6 e3e7sd5oCQ88Lm3qCXxe+EJQSfQn7xlZO+eYv7WVerSUoYEkkLmLq5lcPbuQSXzfw5MjWV6eybP3 3pUH0Qn/2R/9gfzEz/ysfOFnv8zg91vf+Iv42jNZXD+R5ex53E6LGNxdyWyxlhWy7BooHwz2QHIo 0GfWFEI9Q0UbepB08Jm+FOTMdJ5qvO/R5EgOj09keHQnvsVE3n/0SN57FgPH2VwWl9eyvoh/X82j jZpF57ngvExwhfvmIDAXlI1PRTwjQ0iFFPL08lLe/fCBPI+/Pzw8lLfe/pS8/sa9eJ1DIqZUHuT+ 6IvOrOi0q5hgm3NwxFc134I9l91Of3y5LUybYlIpJHf+ajvVofn7e5KNAB8SMqCO1LY3UnuChEGS 0XTi80GZ7HhTkk2OqGxsHgWgSxLvt9uZXMfAl5UHK49BY9JtL0YuPX/6SOrNNcdXYR/NYuAOC4Dz eDWfcx/n0U5A7giB/Gx+xRF4682aQTs74+PnrJ88k4cPvy8PsRenN+Mee0WOTu7Iya1XZHJ8LAcH MZg7ncrhjUOZX/W0hLcorRs1iFOD6Tsam1KxB4ak9JSdxBhVqESrcf8r/X5qgyrxKpR+adWlO8ct 1UV/U+0DpETKNZOvvNC5pToqakDUCknleKBB3TgmRU2l+6PcrHieF6b9iPddLC+U0xbtDGKHPqse DSkz6JJdrq6sjB6f9yr+znxFLcXeUMumGLuH8idsA3mZ8SxsK507zr1kiWnXrNWwixRiy/T8exJQ XZKg58PnpKbUp5RTh+YHIplt9S4nnYdnC1WFgY66c+41qC5V1U1XwHV5KTbfFjvd3ikf1Z+hX4Of Ndpq0K/iMwG9o4kJ3UFcn2H876frhQxG2F9Duffln5fm9BX5Z//kN+X/+V/+haznz+TONCNSV8C4 uoM5OjyID2IQV2bdbpbaIny2QWO9Cu3UC9D7CZ3OmL9eUbnA8SqI67bVNul01F3eljOZrSnHK8+c b2PBROYCoUW7ISvr1uPBD5r9FaazVWvasxtchK7TJH1w+wepSRa543sF/1gNTJq6Ja6+iEjZv/8a 1G3/e+k1ttcqFvg2loG1oFm989o2WBJr4bcNrIOCXb1MIXsnXLpD1WvpnBUPxZ7h2EXx/HTsdqm2 QWnQknQaDJatZERDoii4Rcz8YvY2HWTySnR8N2+8SiNxtbyWy4tZdLorWS7WOqUgvuc2ZlcbBjUb wu1kiiH73hoPJ9cDV/H+ld9XcJ8aMdi1isCx4jgy5T7ieiDSusmHMo+/twJaGDRAqEwjLMs6dA1B Zj/39TaEtdnlNRQsvXtjgJYbsOoseThRP3Fszun0NU0lcvhsWVOsTUtpRISNEP1mY/upUdqsIaxr iD0aId0RE50WoWWTlY3t4j3AEBuKwu7uykczdeVeXIPqUWm2ypZ8Q3T9czh2r2yodM+SfKXBLDTr mDDhPjc2o7BfGPpesVSqCbF2pTGgQDDVbOkcykbli6papQ8KSrsop3GJZoH4rFaQgDk7l7uHGF/U l0FxQOX15xcP5V/966/K7/ybf0lnP7+8YjA1EO1iLAIgVUWkkPlezhdKZcg7qQGiWXagUDKpGVDG 16PTDR2kW5yVbdw3MRAbHcVgUtXhH8Xg7SoGiJSCiYEBmADjuP4TjpW6Yrf/aDpuzzKbZgodMH+5 Wsjls/N4PTM6p8OjG3Lv7bfl1muvRwd6wHILJjis61XM23ptoxEHgmdV1yGJvYRGoaJvSUE3YJ57 rvYO0l7StKBjDLW81qNzUp0/RWo0gNd9zw5k36NuS1F9yXudbbEEN7V3mZX6aB6B1lUmZG1d9e4M NXDM2y58nq14j1ezq2gbrkydxjoBewlHOG6ohw/uy3ZxwE7/O3de4ySc2Wwh4+mh2g5elk5xQaKA cm2N/YDOWNBxggaN4N+OhjoyaXH1WM6uz+Tsg3flgxhcZDGwOb55S05Ob3DU0gQE+BgMErxup/24 vE+n46kgXRfIabWnNbaSfoHoH5o95K3Rbsr9ylhnq53i4KOjrLPcviprwnN6he8VTfLjb6wg51Tq Z8s6rvGMtsNRTwRbONsjdKIOxmDB6H7aahfzKu4f2O7lch7XRCc8weAex6CXGnIrSHags1s15MCz X23jOpvOXLXWM7GNAfhqMYtnWjlqbjcvr6+oizcMY+1bq2rbCz1D0roEm34O72V2jO9LNQHveNfk ckth78KmUIAsVhjdyiodRrGiLVut27WH3UBM5mPBOLEjaIMEu++tGqaTeHRaj3NNu+So4/Thz3g0 YFUAY9owJxc2BxQhTKGdxHW4enohN37870rv7c/L//bP/lf5nX/+m6gHxzUteE5iWC2Fk8FB/j2e TljTbpZG3EfLftG0KEHIdjtD3KCnm0rnjOqicagt+GhN1ZbEtFzpBrxm9F+oOBiNSG0lpbSrzR1m SqwNWXIgkkphW6o0dCiTrgTl75PeQxG67h3/wwCzbFqD6b/rUHUIL2rGMehLHLyvR73967Or9N64 aRtDOEXaILcNnOqmDXLrpK2/NNJneu+p9l9e2M8aRcdYqkKwU0gbNLSfn2UvNRbdPTam22YGJLhh rSQdvUVD2+hokwFKgdHRHEYD+8k3X5NX3viEvHbrdTmYHMp1dL7LeczsYnbG0iEcRTQo0Mibr65J lG7qLsBgNlRJ2zFMRIik+pxlJYr8VpoVocyC652vdWoAHPa2gY5SDEyKaHyiQSpx+MC71PiLHLZg TgXJS50naGtoElh8N4jfR2XVEFh3FCQh6DjT8XOi3Ih4fMt1RSHblq9EA5RRHkYDQ/2czM4WtZhE JyrQmJZVEnR66dQCsMWCm8rLaI6sUKDX5G50Mos/b+0WQ2ZcWIluu9Ugr8jUmcCQKT1B7xlBtM5w DRSt9OtnwZTcRDGtKeW0uEo5MdL4nCkMYyUlGDCmHZxCknESwnq5VvQFU0wOY+B//lQ+eAeI3AO5 99pNGWXR6U9j9toPMowO5fL6Ws6fXbIdH1MjNuRymTgxmhh6mZRQNwLvC2XJxjoJ4eDggAoll+Pn FaQkcEJQWdjU5HWirF7Ga5IYSCILrrOnxu3FyKL43KjXV5L0XvaikxlPlM9T15ZQRWcQf/9ydi3X MXDDH3z+0c0b8vnPfVZeeeUOeUbsnowB3gKIcBEd6Ggcr29oqJk+87xftJ37HpTloWtOUDTTOrvr rlmrO9NVlyRLkoRLV1Fg84k1wmgVQJT3W2JEUKX2IHSoHu1HWe1IQ9T1vi03odoYCEAyxREQzWB1 yg+BcyA5syVRTKxt0evLeltZw5ios6/W8uTJk2gHl3J8eEAEJ48+BXzuJRwwdUgz7jegceO4toNJ LQe1coHxrLDfLy+uZbOeqwA0np9Alw6fM+MM1XJdyFMEdg+G0XZNY4JWKa/SHLgwibYkTDoBWE/s /6av9jV7r63bOK/ZLxiJyP77Kl2DXf/idsl5qBVLnHzGSTKehwE/g3ysTJseNuXays/Rplxs2nIr 9dN6fZt1ikanjLOwae+B7DcQ67WRk8010Td0Z6PjczId6e8FNIlsol0uaavRNQ6EEx9/eXEl4exS pgfjVgcPhJlAGSC1v4wXir7ZN3TJDlntUTFgPQuYguOi6DllSmoTLFbbgziCjUCZBoCwOTVlu1wY RoWcOdoKnG36iSxBvbFna+PdrVohZqcy4HNBWUDDhzcstE8o6+gG+AMwA6Xoc3QOR5uFKkPdC3KB BPiqkumtz8rhZ74o/8f//e/kt/+n35DB4lLGcZ9v6izaB+z1KiaNDeNAmU5GMgUcmrF3i0aZDjoo 6qYlv4qQr/OyePjqToBXswCTJMALrM28Dp2WWePwb2FDvkVLa9DB4UzFZrsTZKlBcZKtqAMzbgVn devcpHZRHOXLmhcHOu+XZHfQuL2AMe363OfSMQOVYDIILsmhadcLMPlL0Ln90qT/TmUHVYNVvduq LpO10DJaSBDQihpqVkoLHWSrR1x7Axs73K32XJ21HEH/nf0y9MvugWvRdPPhxDZ8y8Ehutcn46g2 aQ8MOEeWi7116/hE7rxxV0bFYfzviUyjw1v1o6M/sFKdaAmVxFcrqZV1N8vRM3cGCo3NYiyarkRe hEQHTXkK82gwFtERobPn6dWVPHh2JR9h3A6MzmYWr3VIhCfj/DxtV5fa5qhmmlW2z6zpyppKUNbs 29FnXyciC3H/4dqBzsAE6MQDRxKhT6ewu5Q+CWXTQvF1rdpr7NILGrQbPqsJhOisRPCjBhxNpMYF ch1wV04k52eBhIuEJK/adULXaM7yZ+DzxGvx/ZGRe5FVY2hzTimHQ0UCt2p09SxkJripJWjPQskN aTqHjr/hIKl7xA5dHbED51rXKmA8jHZHLBnBM8HeB0+HAUENJHBD+Y+i2Mo67qPDk1ty+/W35Ft/ +m/kvQ8/kFcO+vKxuzEpGI0YkJ5AADhe3zIGSWgE2BBBVSkYlr1z9YVFH0+jx8AfSQ07UnOTctF0 OwZymoSwcl1oEEMdJwy13mLY9kLGE0182RUdr5cdjfFaQHTfhIodvAycMQw9Ji0X5+cMjMbRqZ2c nMjdV+/Ka6+9xrmwk5joQMMrq7WrndpXFSutqpJfbeh8FFVdc6YteWhWEmcyFe9ZG1jyVgDanZfu M+y3oJaU5amy665rbVOwjvANS2tEkKvK+JWh1bvEv5em1s+KhdvJIG0Zqao6++V+wtXw6SIKmwxU uRaktPbt+vIqBuUzJgVEFMX69rNc8W6iK312IJ/HAICdj7mhxdyXPUOJxywTale7UPQaA+inh0cs k48PTuI+KOT5xbk8e/JALp4+pKhwGd+vNnHaXp/GLH5/Ro5dn3OCA5uk3BLiotuZmY3WbYheSmJj 9+1q4gcUvct2+HH7/im10y/7b3y57yMwqkYjfk/F3e2XOuvNSUHOzU4AB6KsMUTKdazWYn4tc5s1 ipFy2u2JZ4yGCTSPDUlRquuC6HaMucjBC1ZunJ9bBSK+13A0iIHwmKXX+fxcxrO1HMRkR7dODByv VjEm2GhH7XQcg7I5k3fyZwdonLlshYGhHzloggErmmwwGbfmqgBOMZoKRCksqnzg3cJo2NxYV3cw +2o8tlr3YM6JMmkMEVqqh1cevGnR+XqtBmd8A9fF8wQ+y3ZHfUE2SZv84nswqYl7NO7XC/iPpcj0 U1+Rb/7F9+T3fvMfy7icyeiVW7KM/msUbdFlXCOgcszrgYQdjEdU0S8arScreVk7A32j+LzT7kEr 4ZvZGDNY1ZwjWoRIF12jRc3uQ/5KpWVJmNNePGAod1Vl3soztBs9ISjy0Abv7PENm2id1aF1jvxc BkFdE4N3j+ZJ80LwwyahbapoDwTI3pa58jONp+eInXaUWPNB1k1rcCRu/6tODuTLDp8/UD9UfB/2 iXg2bTC4dIGczn3UhgwiNF7mlS64awNYE42kSHOmfBOgBG0gGnavJy0pd5IDSQlaOqNCaeG94E8t uAYxzAcrFZ4cxezl9OhIbkwPpF5DrqEhQoWsLGcWu1GOo+iwdJQ+t1kn1lgbj4ybf7Nusxt0V+tI maAdY7lxJwoTYR7djNeh/dHQPTpfbuWj85l866OH8r37D+QyOiaQdfks4VyAYoG/h0aI6JA5pzKk oqkmu2L3WyUl7e5LHRXO1YYq6htZ1bVxKLxsq++H7HaxmJE07TwJsX3AiQ2DvpVgt23gnZkwKGNA dOxV5NLze3S4NuuVBoWEDx1bVtoaIptloBwdMOB+fBVWhmuFqjMNOkvViNC7ovNVR1qTmxINFc54 nlkGKi0nEGU6NfjDnUQKHBRwcbDl8drL2bJN/GoLPKu1BQ3kixQUz63iv6/nc6KWr7x+Tz5T/pxc nz2Q5/ffl//vj78lh6O+vHLzlF3xWGPoKm6AdGZKcIEtY6EMkx343zpJhjM4WZ6pVUol08kEnIkJ Vfg8MxqJ2jfYG7xO1fI1YQB6vCltluVKG3quF9d87vOreTua7PDwUE5uHMsbNz4ut27d4sD1NTS6 pmO1ZUQHa4rSZig5TaYxMD9gALlg88U62swhS+3amFBKK0PWSjuV1BYEwNaWUpNyvaIoilIAncDz d1K7l+2dXuO/z/2YaSmW/671d2m/xJQKrLLidrrlIW3dbuQt3UWDuaJFVMQaWiDdopWsmtMzrhFI LRYy6vV5z+uysbOlgwapRMCOVTjzGa/9YDo1JyzRgerIKnJoG0WGi6yzjSwnx/10NDmW26d35NNT Hc2GyR/PHz2Rd995Rz780ffl7Pkz2SwxiH7VBqBw/toF7GBAY/bYkjyvDO0Ex93XDpVmr/pR7wRy TjFqw70dW92WU5NqTvrf4BG38l3Nvq0W2qcWh88yQ6Yqnm8E8r1CudfkeRmqp6X6GT8bz2Wx6BKG tvHAkgSQayACDn4pVAkQaIPzWl3Hcz/XZDS7WMZkaEGEk52povZ3XEb7V3bTmA5FKxigMOAzjqI/ 8SYv2Mu8V7LRChUQlS4JRP8RZCIi3QIhzras7nDNg1YXyN22Sogildhra0Wgs47bpl3bNqVK8jZZ we9sjMOXSpkwkCs6Tryfr052RruIca/DeLaAsDVAnzHSrx7I0Zv35NE2yO9/9bdk/qN3BFRQgALD uEevzh5LMeyRB1pw4LaRd9GtBucORKVioNNdgM8XTMuJWdDxKi7CF+hJKg0y4BSjofFINMujIYMa NB5go2hEY6XXrTUPOFcnJdY2LwmMHJHBRsuB9LVoSUeyT/kWuui7HSvp+C3/0vJsh8K1LcUM7qzc 2SJGdlgz1w0LrbN7gROyh8alaF1bwvVSW4u0hV1B4qywRKreEY71oC1Fz5T7IIpwVF0Z0MtqGvhl yiHbNyDtdUj7OyIJApUQpD2I88Pv0ztyAlM64xV7Cp01lD7AXrOmh1D5HEUrP/CPzqnE6yD9AKMd ouPCuubW3YaIqejnllFtiWghcCu0Hkolcr4+13mo5UYHNmP+Zh2v8+BgLHdObsmrt1+VT959U37n m9+UpxczWUHdvGdIZ6OIS4/mZFdWoUOHdzuY3dBUpldHtDhew3g6IcehG6cSWjFHPpewYWCCEWtA a6gNFHot/6cCV6yubGtZQw/+I/Ou45gJTzVQQjBIsrfpdoHg3R9OOe8R3KH5QscOQdU9Ywfgxhoz hIYZOlAaxGm5ZLttWmXzIuF44HoKdJ2jYxQ0C2tu8OYkdsIZVw+DxKmJuNpypilFNqOhBs+FQUUf 0hlbzo3cJBp6wfbqclsTQb68OmfmC6cBSZtXX/94NNgjuX3ndXnne9+NAd0zee/xs3iO1nz2GFMF h308wLPr8TqAkmUYPQQ0rbJyb9AOQ+7mYI0lSAxABwCi0dN6JMbdcPs1Otv1/OJCSfRw7pCawIij oOcTpXTo2h0dHMrd27dpA6fR4SCIQ8AGxBT7AL+HvQkl/h6aPlCiEkw0+f8Je9Mmy7LrOmzf4U35 cqihG90YiIGgRRIUTFIURVsWaUpB2eHQB3+SfqK/OsL+ZkfYoXDINkMMmpQEEgBBAE00eqjuqpze fCeftdbe596XVbQfkNFZmS/vu8M5e1h77bXX6fy7FAge7QJ8LAzsxlgl3AsgEJ44doOasmJ4d2iQ MfgF+omgZa6AHMYkArrBrxO2CSRz/GwLbbSycic0z8dRQKQmn8KDLU6JGKLMLhHyjOQNmhoTdmQe 49j6UaIhO0JHD2PWK0tfToNgAOhNZ7DK5Mql84Jtg6QJ7l2V1vGxcx4YkpD0yUhMWL5bX8j+zko+ +747t3OdI9mYWX04trZ53PE81sXanqWA7ru//jv2+3+UnCbQ0xTE/eyH/8n+4s//L/v8k4+oEQee HsY7FTZXWa6Ouc/B7ulpR8418d5BEcop+PmrL0o781cTH3X+/cTXCFo7e796W0bN1JgmEDxEtCCQ 4TGII1crxcznjYpGjAAc4uoK5495xIigagrCsBu67ZgcYOYwuLPoH0ApFvIui5TY1TMJPLPLFzSN 9P5PvrilHed4PKCvjwe7vlrY5YVKtg/3G2vSsx1IVdlRrBmBHLvjUdqfq9FKfr/OCZaqG6r2IKmc UXOyIMI/m88yICDamKSdlGSWZxp12W/b2BCEdYT1hhdsY+jAjpWIQy4Nh9/GMWJCCqb4QEIpLSrS M9oKguNpXzWl3aYH8n//u39rH/3gB2mdpn2PZDbZ8MY2Nr8sbPNGzVJ122lcys11WvgXc3JQCh9l gSgdRrmDV+7UlaFBxBXnXNJpVXLWmqnYaW4kIGtkVuguOsFoJCeTsuiuTE4Daum7ZERzjb8ngZ29 JBBcBTm4iYXcUCdraCXQOqTQvQeEOMyZDdLxI1gE1dQh4cL5eNgeGv/iAVkuy44bgJug9Q8ri8xD 4waLrNvFSmNEWIhQjkhaqFLzj7KcxDjaZpwoMe281UPGGCFloiWzHG2cypV4qQ9kLR/g2cakbLzr 07FRwVyTpveS0JAlJ6qycITmSbBK5KPls4vX22VlfEalAM1RoBgDpSxGKGjBzd8LZeWw+uScsVDp RCo7AtFJG+Yb1RJj4Biov9k/iEfQbtNm2nNDw6FRITtlvFQo79PCnlOvmga3b0bSKKwTDCgHNxfe RVqkIAgCkWndIXvHei2Hoy2SEcftQsCyB/dgd7DvXqzt61//Sgqevm9/+pd/ZT/8+Auu5R6zSk/g Skk0s54lg3Gc8/rL4cAAAmLtkOyAg6KKoq83RARw0IhiyVVEGW2AeKa0pRAIYL0iW8RawAbfp3MZ Ws0jnKVzLifcOzr4dL4wEljbDBicFwKuXWSBWQyZXZ6l6+lJquSQnLM6QFFSu0gBVOgYKkNHlxed IJyid21T1gTXjueRVuAuGRiWCwuhpxfztYwYjGmHssmBZVMGAAvpJdZO5tki0cLzx95LAcXSh3c/ pAATgUx6/Co3tp7JzpXJcmwOjC6EQA87oikQIaX8Swp27tN9QzPK8vLGfvN3/pHd36bnd9zaF68+ sV98/FHaI5c8v9csx26oxRTsLwbqKLsV0gojLaIc9wU1BasiN3LAOIMnRYRv5rOPfR+try+FsOLa 0Fl2tbYXz67tGQK2iwsS4JVIKohfLSU02rlkQZcCxiXmpRJNVkBwTE6vml8wCFAnYEdkEJpuuP5j u2cSg+ej9dhKAmVWOoJWeHl7x+sgdw33Na2PQ3NgaXzmcgiLhboENdO3d86dbDsRhUnDy6peEVlq qN3pQtGVJGqo01XNPDBr8+zMUy8bWcV6LYNyo7FbtCGunj+4oC4sO7scK0w8wWi4BRtBiNgDAaxn +VnB6WN0FRpt4JBr56ihXM91dEhhSnXQBIFAQODzQOMBvyokgWoAD+me2cHuHr/kvFRQCdbXV/Zr 3/wd+61/8k/tn/6rf2Of//JjBnJ/8+O/sp/99Mf25pd/k/Z1So4Oe3oZJrAla7Ysa1c+55kOu/fg olQChW7ZGXTQSsVenY2c28qRSw2TNq+ahG0e/Zh8j/atgqpzZC7oNfQFJqmvsOX0AUV0lGc3d+YP FvXcv5dgrao7jlf0UnBASRuctSyBNKhsCE5rfxRNBJJTTSU5qSVHzKlh4vlyRntm5HU+V4OTz6Le Qsfy81d2C9FdoHuz2pssFpyji5Xy6qEgegcpEkxk+Oyzz/is7/ePyRbP7HJWExyAn4XOHyRsjl0h OREoJ5wUB6xQ2UjHETdbZVDEOkNawETj5xW7opGMnobGFin5GVyaaHc8ePLnHeOebOPZIfGEPRUw 5NxflGA7KTAcWkm09OkaD8mvrLqSWn2HdD0/+fhkn/zp/2rF6ZUt14VtmxS0QdvuPvmw023aI0d7 cf1V2TVqByF6jCg9yqel5XrwGIiEpIecQR1IjusMOfc1BWwVM1x0ZoE30M7mhNwRkSPaxLgukgkH yV10hWb+jVy16qw8+RafbfJzLea3eQTx82lGc764BwmTFtoXg5cOueAljX2myzY9l/gcvMI44DUv 5me/QxAZJbIoTQSfJJDC8bzHUkOc34LSC6UPDJ9kvNGB1I8Z2/Ra8zUXKndPpWJ0q5zE2fd5GHsx uf5on54iTloT58+EpVYEEYWMAwMDcMWagaWroa+5NmYuv0H4unWdweCDUV6gIAeH9wRISOnSMKc+ t+kLKe1zCSPuIyQcjtTzKihQyWkBcLx0nHOXwTjxHFmGrgd1zKU1+OsffGiL70OM+Of2g19+mrK7 jdXQ68FYtN4o2AyRSm/zInezdII5AgPqlvkkhwyX160cVNcSYWE2i302l0QPzi2eY72Y0zifa3kt /HgauE30y5E8/BvlAgSA02HR8ZxUOhNXFb6V5Ny+y0E8mxuOp7z25qU6ZDENoE33GgYJfxvDtqNM wkCxVyntRPmXsSMRwcrcVcaDCN/3EtUsZtJ0ukhBMz7z8fGR79Hlzzg7VvwWBXfoLKNOYBuDpsfO Lgj5qsPQGJBAgwodqM9u1jZ/7wPbb2659l6+fMl7Aw7a490XlP1ANx2Q2uDuhZBxNUTj0jBSLrwa wRJSWkOri2siykANl3ORvGc+p/TmxY2kGNaam1qX5o5qzuuaeXk5Am04DwT1ufwE9Hc413psWWJd pmNeWt1BGX9ne6jOp3W5Xi+Z8GlMmO49GoMgpmzefYe9JsS95rVGQol7g3NvyIuTu1Y36nllIJAC OLL7h4e8toKkjS/8jrNW0Xw0yKuLLK7B3lFORVI+tYexRrn2WXYap9Ck6wAAIABJREFUkxasc3x+ BJb8KqWQEGRwHstZG1PqRyBLU8SEP38HoqXfTbW7LJ9jnDclqIAQ7Y722e4TjrS6vLy03/j+b9pv /94/tD/c/7FtH+/tk5//1H78ox/aj/7jX9hnH39s24db227v0yZvOTVlXu393mOKBSpVUlYAn46j p5xvHlOv3WTnNRHTe3Tib5dlif35/eimjQ5Bk3mC80X1Jr5/lz7d9DVWwrLH/XvfK/9z7nen97zz ObHHY2WL/VF7FLFHet5IbNcXK3vxXCXwwrnQh9O3GFihXH7YN5wS8Xi/sWUK8pnU3d2ySe10kfbh /FLrJYXieza4VHaXAuX1Sg044m6WQsFNa7ylDme6j91KjU2kraT/nRzdXMifH0Dh6S1zP/c+MWRB Sbbz2dVn+nAWslHVJEaZcLsL+UdUKNn8mezLwwEBbGef/eIje/XpK84at36fEppkY8HzbR/TIVKS MXtuX/3q1xTExagHnnRp+UFEWZMzE8Xc9IkL0vPiQ1LrEQ9EYmrOZnsSBruCU8TSAq5I4IMmU1s3 4ighqwSHgxoQY/ceW9GLIBpOSKBPNt10gbx7AernI2Ix5hm5VMrOunGZRhkzBqU/xbrlDMcBxudC fk5+9NJBLjNalIcjwFQZmt1k1Xh9Gqcicqd0ujpz/VXXxOlsEr7mIC0Cq5G39a4vbUgZBhP6IFM1 yfDOX7HowrlkCH4S1FVESC2Xks1btVGOA4K6B7KbNusaCARGomx3aUMocMPHslTILj/nxph4la13 sPXdeG7gVvT+N1l/x0nVkE4Zisphf3UjksPZiZdyYlDjTpOtpwM5dM+SYfnu8xd2+lZHNOknb76g Sv+ADc4O0VaITSC2KMEsS8pB9F5BVxVD5WntiyFlhzMiygwXfSID980gzhrvnQtull6Sb0+n0fnw mapbkzNivTuXDQirBc8VzQcMZC1uRZWHY8dzozp5sZIsSKeyfVXVOUBHsAkuGhs50jXAUbENHxy0 3T5ZrwPXz4IlQCEIh9Mp86w43eSoIer1QkrnCAS5h0t1hj08PCb7ciK5HPeSqMswMIBbpOAuyhbU rbLCdZZiZjJQ/qOy8FrCm7udGijAeeoOWJtCgTCGaFavyDOUM0ZwBd5Iw3uL5IErvgJn70TnMHcN wiEmuvi+qp2/OCsGBt+1o+OzSoH0ynmDx+OenBsNAxdiTb4tF1/Lc4jAJI/eSw4BwSC5h4u5zwYe hUjZFZjuB8rb89W1Aj5vWNlut5xUEusfZUA4QLyon+VlHiyx6JhjKRxBWKtRQrE24hgRJJvFDMpT DtgwhQGNIWGfOIaw0FB2fPEYblemeoilc6ugxB9d0ZEYKlg0JnlKsuRLpnOwM49PqrI5YQx7xhF1 EzvE0rzLVLHT0ko1EeSZx2G/x++jg5NWZ1BAVFF7s84+IzqKsf+3e3TM77jvKb8xX9r3/uCf26// 7j+zf/nfb+32i1f2sxTQ/eA//Jn9/Cc/5oi43e0nTOLwVc+7iT3GPm+459htP5RjYm4KFug/xUKf nH+cuc6ryj8fznxVFF5KOwcv4vsMBhRv//5p8PWu1/h3T9UXzpsGsZYZivbCDwOpw5XVCJJ7jPY7 pAQNJP+NrZYzu7laU6z56nJl68W1Pe+v0v1/z0dRNZptujvYF5u0hgEWFHurZ5jOIDrAvML+vE5/ u7I2Bc27/sQEBvccSQfsEJ/fAiPdxIlFgggOdM+yc0OEm0nzYmXRhNAVDdFe6G2y0aiyHFPE3o14 AK/O9W81rGDI/l/Vu1Y6qeCBDmpaQlPpQ7K3t+3SvkyJ2Sd/+9fkvEH1DeUmTFkBwt20G7tcXdhv /dYfpPuU7AqzLhh/HLhVezej4LIVutarqyseXA7s/IG99WA9K+Nx8J/mxPq+oOZRCRmdXCArE1Zk INexFBebl/chgg6HhKfBUmR/VowB31toXTGiSk8XcCzCGDE0LtzIVHT80P7Jvx9C66qnc8UrHl48 TEbynnUElygg9Wm2G440fhbnp9Z/lSrVSdZOEMix7Fv6qKLR6Y/weT6XfpppDX5tjt9bzCks8jMO TaczuYxJ88c0k46AFMiLyuKdCM8QwQVvABnVqSVyhgXbqPhP6J2Gkd2OkgcZfCQPbhtnT3qnaOvB E/mBjobhczrvjqxcz4gQMOBtOAbqLQ1UAwfETtZ/gazLqN2GMmsdJY7dQ/q+sm8+u7bjf/Yt6/+2 tx9/+aUdEDymDI/yDbjGmQs5sjPO57XizPtaiQsDLN3HQCJglHHN2Fs8b38W0hWaikBHQ4/m4XJM VuMCwAg0r66JfCDoiNmDKBWwVH1o8i5EsNh6l1/fuShr13oAobKOZWTVOU9YA/zsiiRolLIlbaKE AGXsyldd1UtipGkjUK9dLHvg5IPTo9b5xfqKXadEnlzfrizGUXaRkaPUAJkZ3OOGhPrWEZ6ZhZ4h RluBrwvNPFz7ZrNV5r66Sde+4XXttntbzIBAgQul/bMnER3zPBshhdfPyTncPm7YqQZleuiKkTvm a79yO1XaKAy+nMnBc7B3pWev5tWSgdv6cuZ7rSCVgWOHvLOWPBznKC6WM3ZOBq8Qz6Ue1E2M//cu y4FjXoJHmQLT7e7IZw5eJSQaDux07dj1F4r7RPtmEk3e7SV3EJ2ouPcR0EfSGklcdEKPYr5F5sxG sEm5iZP2uvQEFYBNk4R5tcrSU9PXEMhc5TzivjjjCgl57Fn6DVs1dn4XZ8LSbnbP8mmmOH5N9DWV 2/qw+Q7XUX2B1QCvmvizyQm+TaWVlFxHMh+TZOq5+LVI0ijUnZ4NSmoYL/bm/iPNJk3r6eZr37H/ 4pu/Zv/4j/7Ybl99Yq9ffW4//cFf2N/85Ef2dz//WQrq3liTAkGsr5nrqaEC1Q/j3GECYx5wwB7U Q5ft+dCPPiqC2qf3PDcFWlCCpm+IoGy05U+Rvac///twt+wbJkieOHbizDnmQ5uk6oyfeaHmOmr1 4Xx89vOp6gyKIXebwd6kYG5998C5ps+ev2JieXV5Yy+eAWlbpL0zs4dtK+FuTga6S3/72u6bRyt2 9zYbUjBYpMQxrc2ri8IDtlpIG6XP5qymoKh+tV75Xqg4MQH84Z7mEKNIF3bcbTKyW7tWaCSZeJHD XMoW4L+BbMf+4hxrDXP06w9JJ6yC2nnkHWlPYEm9ud3bZvHMPknrZ5u+Lle1qfKa/r7dp+D1lsnx P/lnf2Lf/95/aX/xH/4dfNlIpm9Z0olB3j3nU2qhF14tdT5NoTml+G9X9doUCrO1UDxbs+gWLZVR IUMqOwU/UT5gexV7zHt+RSfi8A6Y96wU2kvhe4pE4fW0rDo1XlPDkIO7ctIWPvkcLtJ+yHpY4Win xH9ZlvOB8IU70DCMXT9210xlTnJG+WQjxfFzqaw7v54IlOM4crLS+ek8sNVEqCEvNB6zCF7EuSlU diC+QyCPTzf2FOmbni/LNNRt02dpdNIg0iiCmuRwVlXaCNut3R03LKVhDFdPHgvGIGFm3TU7GTXO SfpK7BKto3zZjPfJnxOzVKDDxQlZiBws7jHWk6OVPcm4PbufrRaBnZybPppihFAgo0LygG7Gb728 sX33tRTAHe2juy3XV7lIDjIZ7XqVgkA0Z8y9Y6+WeKTGZTVcj/F8WBrtVDIegqIQa7SMQL+wENqF Y+5dSmbmjQbkkqY/RpkSXDgiGYPKr0TtGqFhwTXCK7TCVD71crwT14emyc45yLowPIfDnpILQLqA naCbs+W9lYI7OFQwVNvDcZQOmXu5F8MvZrXvh84k/syVmvdbIDBsdoDcSNfmwA5B1KpeK7AZjo7O WJ6rGJpycyB86f48QDYEzVKenMBAXi7XDIDYdUo5iXTMpeQHdrtt2hMLckoxDHyeAnmQFE/Njppv kEo4DBsaViSyQI8xT9b6MRBfLAaLruK5c7HwYlm3ohXMk2KAqkegMnhCjPMEVw6/Rycau+qWNxZz RBGk1dWCDQLcp5AwgHMfvJsXwrPpPRBdXaXse7VCcHewGJmF7mWgc3gv7ifQTa6bmfg9kAjpSOIc h3aXvK7lWfIZdhJcz5mXwIXotY589ZR/qpwwjjmVhetgTe3s1EbgC2LU4stNpUXepmtM7czUBrKB 6x3U/1wNYBllIgovkyxeIzG2MXChTRbmfPa50xIYj91PfEHpovauBzCjEO6C/CrstfmiY+PJqdlz feKYUNy/fP9r9uyDr9l3fv237ffu3hCl++inP7K//LP/0372479KNvGO6IshQBwmlJ8Y+2BvKw0U 2c/9/f5ueMf38e8pUPGu+xnvi3+/K8B7+jdTHzb+7XgvOU5xGLt0rXfZlUK2KlBXJGOlj0zcd2mv PJzs84ejvXi4YEl6fXFvNymIW6017WG1vLDnNxd2KJbJJrxIAfV30j5IQV3yMccUyJ22t7Y7PSb7 BaQNSJ32J76A1C+XyZ6hwtLts11b7i9S3n7UyD00jF2cbDXXtQWqDdtEJB4NFmauP2e5YQH/LooQ aD5vbIl70jiH9LxyZna/OVKIft+W9vHHH1vZ7sA44cx42G8b9slnbu03vv/79if/3b+2u7s7++L1 G1QNZBClvN4wUtXSF++tdBVkOfgoOYRDl4QHVY0CsubiUVPAAIO/0MJEByGXW+VCqiB3DtI1knaR b+QAvBgQwMCci1HmxeJfGcF6ghhlpC1KtJNNG79XRjiWTKdB4hSJGrOet/lhmVPiGx/Z//RzgpOC 94BQHJlsUUhuQR8ohwhJljj+mAmpkSJyIpggBsm97nlc1zS4LCaaZcSGivHaOj5Gv099lFlVvmWT QhFB7si1etdmni4+wsGDNOcwQsm8W7HbnwiCQcAZxwefAd2BQ8xrTZ+3228U0HXxHAcGX5BJOOP4 9SGT4t3LuI5OgXzBLtYT+XDQNiYHbjjRebPxofMJH2XhyG2lci2Gd7eNOG7J4eEu/9r7z5JR+IY1 P/mFvdkcrKHuXSGV+FKbu+8kbaN7GxSAPj9bvKDFVroRAxrD7ysVNyRq3DtvLFBW6ZQR9Rssd4Qe WjlrBvWmMXCPxy3vNblDJvHToCDAwLDE2XtQ1zWOeg5ZPiKcbePCvBCsBAEcASKcFDJlnNdm/8iR UCJjW+ZqigqQntmxYRcgtd0qkPqXWUwYxi4+Cy+gSHh+HK3j3bO4lzc31wxCKEzsxO7WETwEZJVP BMB7cKwXL18SbTntNjnRQWDdHMUlU5bf5hLdcrYmMkseXNOy8/bZzftEFhkcldqbzNYxEgt7ygOX 2puEEOwp4GlYbs1ahNCYKsesu6rGsWPsNk3B7g6lNO+YHuVcat4DImGbjUqbCyHKhdsUotWgos+k A8gOQNjRRSBt3gkIYdb0tUrBbPBzjkefXzuv8jNAM0gE8SF/oAB7dL7x81gf7CR2qZFIFPpu5O4F 8pJtK8cFntvXeqh9bY4NVFPO0DQBCVvDz6+ECh473bPQkIsX9lTbj8lnXQp9KzT019GoEaAIsga5 wX0AFU2W3eE5qaAqekYfk1oAMqjzlGMhcZSm5bOGJFdXKXktUXqfeekt2Ye7zVYc8+rCZtfv2688 /8C+/p3v2rd+9R/YX//Hf29/84O/TEHdT1gaC4H70psOhj74v+WZpFeUhafmeFqBCQRO/bwKZM98 3jv7YMfn9f/3/Tv/rpwI3Ad/blINggOIkvTIcR+D6JFicKJiAVQYqpkCZTSpPLZLK9Oa2yRfebu9 T8nXo10kO4URofjvLCUui9WNXc9vkv15Yd3VV2gTIccDMfG7x9uUEO/tdNhStLnfb1Ow9mjLesPG CIy3Ywkd818XW7vYLb06l+xjsq/HK3XRAw3kuoPdO0myCesT/N1yAiaVagem6HQg69O4pPNkwoaw p5qbCjP/+UNjixdftzcffUEk9wLd1ukaZuU1EzuU57/xzW/av/xX/8aKi+f2i5/8KAW1Fwrisg4X OkGr8aELiqZGxkQjbuSVCdlRvpMDPVPU3VYaerwoNWyaI6BKzArsKTkBPgFeDz1IiCg7yECq3Oqc gUmvzLuCsAjk4vfT300zhKeZAs+xj7lm05FUw9mxnqJzNjVY/jNu+n6YZJGKwCO6Zyt8FdpiTsD1 jlAGrn00JfiGZEDXZTSPXbFFn5W7iXj1MUaseit7zZ8btflhcGJs7+dfOp+kzKUHZwM6+hnXfD43 910vobIaJUIUpvATHEqPeTt2G2ntFAzUCmngkweGxYvh1ipguYhnIRV68rT6PpP8ueE9s8H7627w 7sKGxyl4nh275thp2GuKAJtmnP9T8nM6asI5LY6l/go8N5S+wFUqe/tGyvjevH+TAoXP7IEIVqUV 7vwVlVJLKbs7Cb6NEk2ljs9+0IibGgK3fev7JhpXxoCUrfG1StIoHUfQM6fe3Yz8J+uFPAMpY5CI ruauzULNWQxZhcDkOHvpuLE79qTMEw697bPzZfNHMjQcUN144EDOydF5iI64YF1U0u/C71kGLNXZ iOAJCvcxJH2XAi0GD5yxqQ7phXfmYuIC9KGorWumQDN988knn+VGFCBdi/R1SjaBPLG289mHQpkL p2IguBqWyYHu9nZ7/0aBxgJD5IFqtCkx2CbjemIn6Xx2I+cHZf5ip2dWqJSLcUCNI74c1gA9K3JU NbeWjh3XC1R3GIVZo+lBgajlEiT+DbkkJGcFuunQhVcVeX4jFejT9wjILtcqw0I/67RvGXidipYB Y0kpjYLryIgQ1nZyFACoLQa4l95YgbFvCOYhqQLtMgS+IlmfkuO5Tvf7HAmgiv5pHAc0m9WZNxfB KV5RWsW5hm1nORVj6FoF8gycXDtQc7ZdULhXEIn1CyfWtSqdiodXnNln3s9cvh3tasyEFvo+nn/8 nimnI1hlJXI6+dxo1Am7PGiCBUO5YuIDiuJMTw1BGAtBpudZ+vrmPpzPve4HCa05gzUzvbfDcKQh aApqxuI5sBNDszqPp0dSLg6Dzmv1/Ll97bu/yXI5RF1f/fyHpAwgyOCid06x63vbtLEw7EdRZHFA IV32BOAwy82Jw6QzrxzOEcjpPX36/dPX3/e+oVRlSGcX93REYwnFDENuqOXzmnx+ILmqWmmsHSsb M6CUc+vLZBcWS07gaDERokl7oVja7i5Zph6cshTYLfY2X75Wg1SyN4vVddpXl7Rt82fPyDck5xZ2 ISVuROr2G9se9sn/dGxeqovOVvUpJUMHzk1W49HJbh/ecJ9s017S/ijJx4O8SQR2AnPaiR1Qh7bW u2sreiONKmLRpdqwlFqTk5eS7PIy3YO5ffzTv7Hi9EBfhfiqsZ3tmweuy9/53f/Kvv6r37OffPKJ 7dO5fO0b3xDMFU6AwVwheJchFFqiu1gAJmfimbgyr+CRDDn7MWZZo6o/2nMrDqHX5kDZiwhrulCM QDmlm3WC9MJgLrZZjdnZMA5sji6mPOfQs4xZPXJt4oaGgXgaxAXUHwRavOqydO2tSZlUu0CL7sko rSlSFiXScRaasvUpPB/6MGOjQ5H/jVdVjOrlY1DWZDJlQNO6hrEUNxQqBVe5aeIchYy/6bKG3nj+ NnjYhmN1Qt9CqiU+g3lrPw7Yjr+dXpvKP5N703sZOR0HnVjFPL0nZUHQfsIInV3aNIu5shx1orUk eeO4aDygrq6XXAovJ6kj0h0tjKjfb6IDKWNr0jGvr9Y0+g0QJZ9ikEs8gKF7rS1+DkuhBRRErE0b d5Z2FTSyKBScbsxdynYgW/HtD99PWdzOdq937BBuqKOiYG6VHKU6KE16R9XYbYR1WtVDfp6KKCs6 tuBPhDHAPkImhT2E3yvwFocE9+KU7g2U1gcX3IX2WE66WG6aOTI01z2lc94npyCJkBg9h889URR4 dJrIcleYENAJrRB5Xhpn4OlgLbCcSpR0YPDWsMmjYol3DqOafgd9N4y/EcrUU2KldxVzrqOQTHEh YkzPiH2DoA6fgyCkqi7ySLdIRkDYR6D4+eefWpkeEHTWtsnh7R83FHnG1AKsjdXFBbfr4bhhyRYZ OO7xs+fP0vMf7Pb2S2bji2XN6TO75DDrAl1r63TcUUmeRqXUiDEBtwUD1qqQ5AiMe5TlhMLhfKuM OmmPWHb6rECk+6EZj0Ififi6bXzz5o2trm58PVQjmR/rFFILh6M9f/kB9xhRoEp288QGGAWP1or3 FjI0eP4xlov3oZYczKkdxUgpfNq00vFKpxkj74JLF3YkhJ+jtAq7riSxztfctJqywlJ0MZbR1Zyl ZpkoKylRGPLaiGa6EEcN2xX/5fvcVk0UkixGBWodjXy6sTxlY0I6DLmbNR/f7d2UhzdWMrwUyBEe JdF6oNMIpJVcps+tNXEIAVK7L8l5FcU4mo8qagyCY7rEWLgag+KP3EeoQM3XV3bx8j27vH9M9uWV Pr89yhYzKKoYz2mqwIi0RQPa1B91/rPKccTCzoO53BlnCi6Db57vn7dGTO97tueepOS/n7xnBGym tKf4rEAFJeXD45RjS141AUOG0pFXB0LYKAcK0vGUbMuGidB2n4LqxZVVKTiDlA/oLbjn4JnWaf9u 04HnyfbVac9UO8jqvFFAB/3N+XUK6i5TcHdl65sbu3q5JCUD+wSjxfb3n1uX/Aa40Q+g/HBaREeu Jmz7gom4NyclewFu7pFzoR+YmGgP4cqkOBBNogKjajb2EZsZJLOkxEkxE+0inEgL0d/C1s++bp/d b+3zT35hF2nNHDg+7MI2hzfJ7t3ar3792/btb3/PPv7sU9umc3/5wVdtf7wzKZtgvA3mcN1ccjFB qsE4Aieg7oa7AAFWOczYJl0VIu5SyfyJFMW0nwbjaZBRzuuCpSKGndhY6X0Q8Tser2xfwdHfJeew thna+Uufx0aduJR1Livyltj1ZJqegC2P8Tc4X62byWI3c17dQMefAxrA9wisJrIMjSNWb5ViPQNq /edVXXrQMzCAKjyYUpNA4UO7jfP99Pnmorq141w9gxwmWIOyFZF8fcYbSc+dL4QLN1DKWqZBqTED dlkI5yWGEYrrbruREzHyXrz83akeX9fKWguXFxla8eM4xnIWRnE4Q/eeBrMKtsRdoqxFWqgLd4IQ Jj0hU0YWCqR185CM1mv7yldqySOgRJSCJ0RT0FtrEXwgmC8k+tm74GSPaIvoWvq+PNGBUDwRsy3B ScGa7AbOy9Oz456gwC6DPt58jL/aj2UcDnDW/doBYUrP7QHNBGiiaNOTetjZe5fP7DsvX9gn9zvO ayxTkFEOXgJLx6ooGCkkVdIOQjMO3LQXRO9gHI6bHQnRMEbIytSVlBxDJTHWQzeibyLLz/kcNDor OQCXSQFMDzQGpRcK4VL+ouDnnzDEGbMlS5R3hjy4mqT1k2bKgm+ShbzTcdD52JWWtb1UTlyRI9g0 h3ReELw9pcBxYUtIZyDx2O8UxBcqJULQF1w1Fv5mUfY3oqGkT/SapnGkKrxKUBfrOYOGq+u1Pa8v eU+BIj3cPlLdfZEM7Tydx+NuYw/JoFklvbslu30btJXavKgp04HnsOs35AyuZtIRm2O81+qCn8cS 6lFJ4GK9squrZG+IZnltoDhQZPl0UNMV/CG4cuCBke9W+Ni7SkxSjSpTaRFZMhICcukQ2Bbih6Hb bZ6eIQJUjNK5GNSsApQSgRYGg6PB4vH+luu46HxsFa59MWNpn7YDQRH2yOHeRY4XpBpo6ookDzQQ vGLAZ4VKrTV1vVQq5PM3cSFRUdlu93RAKv2qXMrmjPUl5Viwh4AuhIQC+HHFvNI4RHVz+b5XI0Hl 3Xwxaoj21asM5IXy/TNPDAuijHU1zliNJoeQy4kmMPL40v7Eej72Wtu0oEVvExPE9db5ZBBO3SjU rVlI9I/nNnZvRsUBdmVmMX+YiSrWMMfSFUyqq3JBwW1UlCgjXoznjKaqolVTAvbBHHJZ2FPm+ZoQ CtlGeNcOkkC90D1TxesmJW7Ni/dtc/tghw+/mhLEgg04lhx52WttYqoOBc0L5wkPugdM/nyYPO2x 01A6O5eXCg40Js7MfOYyqv2qnKh9R0ILpWab952jd8NY+kQSOBWrdy6juW9RYKnEJqp18VyGImar Fx7UjcBHL2hXAav1jtzreK1XjnDNRSUJ+J4jGN9Yub+3ppZgcD9fWZuSzOXl+0Sf+8XSOozISn93 TJ+FmcNFSmYvMP3g9j49i4IJ83x5QZQOaN3NzVesePmVzBM+JJuzfbizwzZ9zmlLrrYVyS8lG7Ih d3WfbGFNeRPY0k82r1O88pK0hcVKjWbVsbSLFPRdps8Anacp9pTZWq6umGzD1u2TrwMnFfp61Syt 6cetve7ft/XyG/bFX/5bNZel9XdKNm6V7GxxQgWjsquvf5PaefXjXbI7vX15/2C7z18JicPCYqbd ao4i1PGpXwOUJ88yFTurYGZaccEyK3RhyCnvDA6nisxocCeXVhWMWka70IlKiFOKxh++/2FydCsb 0oOZrwRnD/054XQapEWwBeHhd8HDkAK0cjynHGTa29mGPfnZ9PU0Q9Ew6C4bobYZR9pMoep4f+h/ TZHB+FtuPnfg77yGUhE70S4vexaeVlI3rh/LY1GS4MxSL49EhjvoA85QNGa6zPr93Hl48bSGZixN BJ/vKQzPR9hHR6YbjOGcT4gXnLwmFBzs9v5OQsUmDkLlJQc4nOg8xfqD2KlKtRU7txAAofwOlAeO YDWPuX3G3xWcNtKLLO5NE7g/0G/bY+KAGzQK1lZC9iliOjQsu3aDkKMe0D7+NgVCMKaQCcFM4e1R gWEgwYECj8jD2JkcM/1gNLF5Z84FQucTzl2yH84XA3Liit5CJdRRiHuAf0ONHI43uEpE8fz4w6AM dh86XWYqKRZzb0RQ0Fr2MujMBidcSRxjsZxT8LR3KZLtRppWRS20Betu7yrkQB40ZaHMHDZ8PoKS MMJ4H5sWHGlmsFqrM5Ajjrog5Pfqxkyn/bB9w4Bh5ZIbaKkWndbyAAAgAElEQVTHc8R8RSzK1eWC pcFTMn4noH2dtNEuLhbpPBqicyiDU8KhMCFSzSkFPz6IGjNJ+2QwK6GZWHeYUoCAb1ZqD0FJfgmi PpGJwTNm6TMOQwRwA52cOqLFFXaCAlGfEyU3nNhfSsNQwU+fR1rxOZ40DBV5JEowKHFzzVTesNKf GA3EXkX3cVcPGgFXSronzoPrYbFkENf4M5TtkN1QIjZSYCIRGzm3mtIRqFroLuJ9oULPqRIchTSZ uIAGpJTsdOWQkV7pMg5s4gh7FGuCQVUkreUoRxLC6FM+7zRhDMR2ahdVMZlUXipd41MpjREp4k/z MbIfcHNf2bkaP9FQH/WUcaVBKgFxboUn7vxdL4IIMbyhPPssvCSY3Gh8n88Sx33Gun3/vQ9SQH8v nmFaw/uHdF7NjkGLpgIMdlZN9WfQF+KcURhoiOvuc/Cm6/ep2YVoLJ1XXGLuOIJtTtRh2VBjrvoI DHv5dtLFGXyZ+4/RFweiFyVtIGNVMVZoprHAW76tH/1gP0F8vKeWX/x+sLNSLKVtSBXYSWszGXNI VlH8fJES5+U6JWUXya4taW9hD9vySoBU+trs03F3qCakgLBSmRRizvr7pV0+u7Hr91+67TqST9w8 3rJSuE1J13Zzaw+IVyqUXAsGxd3d39pqeWVXF8/Tz9a8b5t5Y/cXB00LSQHffHZpuxQUil8KKkay c7vS/XpKnjbJX3/tvWTLt/b5Zx8l29TwmSxS/LJ9fOT5w84+f/Yi++MHzAH//GP7/Md/bTUVT/pe JZdkBJZD8LFM0gmla0mxxKLaPzMTX9xtPJCq9MCtOgsUZoNI6OByQOgS6IOEfiWG+tWvfpXZL57Y IRm0x3ST+qrLWdr0NaJ9WtznQUUgRRGMFc4pMIvW8SH/zTC2YhcT7bQngdxZ8NePJeIpnFyU8YlD liqIz+cnhZ6eG3v8PFr1p8Tv842az2DCb4vAcSQCE97vurPzeXr++b+FE3+LEbHkxoZD90yT2dlk A6KUPDW6OkyRyaxs5iiD+yDDwamuQ3Bo0r8xJDoZsUPKKN483DNQX2OzJb8PvlTVKnDBhgN3S3P5 GuezFRz/BsI9ArgFu4qWfB815jjqqaeuFRFIlD7KysvQGmsUzQhELXEPO5VKME8VnDDQS1CeOQLZ wKQIOCk7MJAB4vn86sK+OO3IVxnCGDqaxfWC5xjZsHekSvAWHaYHjlAKbayDD0OHYUVQCjdXVCjt 99kB4x6SF1Wq+42ze818hq+eHfhTmp3ZEVWEww0UI5fkHF1DBn/qxgHMvdMS0PWIlRQdpMEbXF2u VVr1st1+e3CekDJzrHKUYoHYxOdF4BqBm4jpCvpCZqRJ+w+OCy90KT/e3TuHZG4XiyWPgRLHw90j /+69957xXpzaPSd63N29SRlwMrb1jKg4S4gpkOMc3UAG+lFahbNvF3ruCqgUYCqIW6Xg1nXOeiGg CCLpbIHs+FidbMdKIeA4JnhnmMNaeTnafO6zxkKNiuwo5VjnzQzUmhqkU1dqTE+LWaDHI0WLCwld kHIyFB2vD8lOOQx5LfO+mhqnqtk4wUWIWe0SB7Xv1VEaKYIdJD2LxXrCW5JNw4ihKPPjs3YsR1WZ kE01+Vaoo4LiVeY3Yo4j7lvwIFkqmo/2Sby70oOAoFpYbqqYatWFXY37Hpxe2SWnf2THH1pcPZG9 aE4xb2SYHq8PuSav1PRu26pJUs33emAIpJuj5vreq5cjNxj2nfSXKoLhc3sbI9wmJ2BTjQ+h2DVL nKv1tb34APsQzRVVDmh3jzjHncUw+rr368l0GB2Xtoz2ObiFlY0qomWuP3esAImPzfvXS2kC4AzW OnRa47ktWLXS3HSsIfKAHcQhWDeM4ytJmzLX7gT/q1Mom5HaIkrpRT7v/P001i2f+K0hgrnJTWWQ PnjDhrrHYxLS8fBox2JGvmJRJzuY/MtslfwE5ubCpzz/kLpxs2rNZwcfOMO8Z1N14DVQOsolLYnS rdZrW16suFfm4N8++5CBo6oq93bY3KUA7JFJ5aHd814ed9Ct+zwl0Ara56gwtivcHDZbLeePRJUB CiCpZEWyWtjl9QsrU4B4N1zby6980z76m7+1L7/8O3EroX2J6UIO3tzcPOcsZe534OspeYfE0i9+ /nPpxMHIb/cpm0oLuCud8M3F0nuWMcR45RHG1crnyeHhRKdYBCjaOHoYJNr2YQhbcgeWyH7TF+q6 lZN/b+8f2Y136BvnjcXCfRsFyj/PpPwoU57tolgXFhMlAi4uHF7vwwGYnW3q2ISs+Uc3qIn3FRsy OBmTt+su9WODQBB5h2Hk6yk7nsh6vOu6/Dp6bsNOky1MPJvSZd7o3D3TiWCwqsKRhGRAlZ/VoN1r wYtTthlZpAKIIZ9PlMfe7uwdr3ecfRg3IBJfXafgeKwpcMi+uL2l4HP/LAUYjRwO3BF4NZBEQBl5 PhRnG77AeCCf9lBw/uqM6KFQDc0ZBVokTT0I8c4skAgNUC9ZktB9HQNeojsUwlVZoW8lBkutOwRq e2mQXS3n1B1qBg2hj/tAIVqYlEDnJg6I96EYO0yRvGCOqRIB/bxphQxNibBTlETkapVOQw2cEyx8 /c1c6Xx1da1gC92L4OulAGEaPEVQh+Nz6DhGE/Uo7WD2aU21/whI51nA9siyG36OUttyWPHcMNg9 dOow/5AXmX6OoExNKLPc5IBXkOXxXwgHNy5zcp2OufMueMhi4G+B7iGBePne8xSoLUT2Tue/SQZz mYwxENGbyysSih/ubmnAoCeIUlh7PNncZ1diePnQmQ8+lyYYHwkrRj3FOhegGKCCkOwMGim4R81c pLdkh/UoEH504d+aewhlZK4r/GwmJIOduOh0c3V3JMUkBJCvtRiRJv3ARwQW/MIHc1yetSr/TxqT 5NjpwXz+b6Vh7oWmpJyYyLltqcbAE1ueSAJLk3UOrMXlG8YAn+jbItu9aeIcgRaHmU903YoSJWNH 0QvLXchjqazNTRwcK+Y2SDqBBZuQYp3IDo5o/+jwhzObk9G1jLaJw3wu0TCM8klPxX1xLCyAqNrE cePzPDkb8l7psxCwT1M+O6ZMnSNlPm0Ub2Gww48vMnoF3UoWCMuQ5TJJWKC79eLSrl9+oGaYaL5K 63j/eJ/W9C6djzRUs802R8ZCy86Dm97PDUmhVBK0robw4zbeR/k+NXv5JjWM3uzQ3BTPv5TdYsJU zccEsLfJ9/3oRwvwk4NeM/qLXh/q68vnymYVi/DG55w8e/LMQa3hmLtiDKqpL52vWcFrh+k5TcdS 5HH/YPtK2qGLLz/l/Oj1xTN2sc6XawZ59VIaoIu5+Ne4nuOuSUH0lwRMV6HB6Bqdq9WVra/f53mR S3dUUthsv7TD9taazZtkk+6sTPZiDimhTt345DvPd8nOpPW/hPh9So5hG1KweSw3Nr/rbPHd79ks nd/PfvpX6fwfNAoOjUvbhgErPvPlex/a+uqKSeTj7cYet3e2uQU6mN6PZwCHsklGc3dq7OZi4Rue sq/M2FlOqISySVpBBoWcKlvkfZMXfZQDALW3QfhuFAXX48w+OJsK/JVOGc7lpS7w4RAl2vPNnMuQ fXe2wXN88XRMlw+qf5eB6Lxns5i+f5Kd5UXlEDQ5BtmYxOf0DuMXZ0Ym0C7+rhw7dXKb/qR8EJ33 5+c3tuqbnZdfQwNOD6XMw7DHe2RnQVwYV865g9sMAnFkVIFW8vrGrHFs8hilVs7urf+MXMBicPhe z6Xj6YlDgwsEaoEOx83D1orbO2A5KWup7JAc+KXronXIUMuG95Ylay8dYARXHU0e6ZBN0Zw5uaGr J80XmM/njQCmxgEYwqYf0SlmiWii6Fxuo9T1wxkxwcCIODAxILmRNvoiBTuLopfuXd9lW66SzJDL 1NwfpmSkIA9II+get5tcXorzRvmLukTLeY78OTOSTQ2ugG8KBuYeCLL04dl/lEPDSQJaR1CJ/dQ7 qo7/qjTbisM5KcG1Tmto9qczugLei2CKJVHXaAOHo3VOZe+OM1AJ8clOOciM88oBA8vanSvgax2y DNLrv7Wjpp1/Ad1DM8Pt7RtNJkiff/MsGdEUHGHoOUqJ4MahwQClU2hzccpFem6ryxU7erfpudYo u1cL59EW5JNA6gIIG4MSONNeDguCnkKSR40zNoxUhT+vo0pbCOwwsritMgJ5wqSKpRJXJlruyEty kOYWWnCwBzgmdTWBqnGDQEAWaN46XYNrSVLqIIIxPV+UhbN9KEIvTIEQEbyZmhQQxAOhVdA1O9vH 0/07VZQfS5WRPEj3b6w8nDeFwYZ3BwX95HsVmt86pVxoOkF71jCAAK4sO3Vb496WYwNE7IupfZnK jXDt2thcNQ0gYHdKT27Lwpuyiiel1XdNoylGfxLXOm02m54LKy3luZSHeZBWWDV5r9/jSPIm3LII XvT+QRw0xj4zu7y68QA/7TeMY0tfd68/t/3mLu3PlJilZEXBpUTUycx0FDL0WvNTxDGxMYZIwAtC AOELRh83Unhqk2QVhdFhA3hh6fvQKa1HgeYot+eysycF2WeWqt4EohLVJiVIozh+BHa8v0/E9sdY LtZoLdmpvhv93qTidQqAhPJSvYJefLVHVlkwN/m0eW37+hOrIN6+WFu1vLY5ArpFCqJTYqggbWX1 WpqVHEKAa0uJ7OmL1y4JtEhfEgOGnV1cvrALJHbth6TToBqE7tf9/esU2L0hl7VJnz3H9Gl07pdH K1OQiIaJyytUnDb2yy8+taviA/vef/1tu339xj77ux8TWQVXrsHjBrXItVTf/+BDooWbw95ep/Xx eP/Gfvnzn9pu80jiGLkbKGNuU3R5mJf8UD54d8KlFwqrwiHtCdwZG8Zi80SA0mtYOrrbwGUhj8Jc NLNSAAeD3ZDbIzgYZZW+vEyLOznnSg7maeQfmy54EQqsxij+jMM2VDYVDQ60LTZYwPVPkaan3wcy 1DkSJtKAO/InQWYOmvwV5z5mjMX5zzL1Nv62z+c8Inh1Xrh51JOfV10UOVOODXoWZHVDNjBxvtZL dV7lFxGA1ZY/MX4WnDc722S5DBv/NudPDCI3DIoyIFItCM4QrFymxb+1zeaQMpjGHjcad4RdhsYV oAtNn7KUowu8OppLWY1TmXW4pgF5XCMMXQRJ+Dk6JSO7j/MGgtD7BAC+vLwIW75rd1kFXwOkOxpC lEUqrMH0u4vksA7SsnUtKn/WOAc4bDwf59U93j8kT6jZqeAxoXEDZUSib6eDgjxwmWaVj58qvGvv kJMbonc+H/Uw4cyh0ytkQEJzLBwQ9hMbK7z7E+WwuQfIaCxqvWM0kCQGr2ZZnJYZX9vnmZnm3ZKh f8cSYT0ibWgcaTmcPAVC4KFNHG8EcuoCH9iN/iwZInwOurUQcKBkjKANkx442szLKg8P9yzpYbQY jB3O45CM4yNa/ZEyzpYs4TEjT+v4YoVAtqbt6BzBR7kEBrfshLjGehDqVvFZ1cWCnBZK/JSiESBQ xnQR4ClVoTUFmQI5LKcIoHEAiHWvSgEAVfAKy3qgrAmex4WrvoNbB84sjf5i5SVEjdqb+XGw9opS 3FCuA5ePgMwIKARXV9eZb0adP6CM6VprF0alkib2RqWSbARHCBbwLEMIONYDkI2YmEF0NT2LcQSb mpjC6Qutq3OVRbbS75fr4+032wkCWHEQ+dTusTu/iSDJOH1D+xkIc5GfzZg0WrZ/3O+OLA2ObOUE OAcBntwPXr3M9jfI+NrTwqw0Qzj+pgp7HEjVJNGZlli0102TKWwiYeLD6cfzVnJ81j0bgEBbnk03 4DljlFx671UK5IJPS3R9fWUPt69s//hgp92D7AY77xtCa/20GpaP52hX4R2t3E/A2/vs80iTQsMf p4O03LMN7EhReKCtWeF9gSpHw4CucSkkoMSBrjKBxH2aIXxQItmGcsTQ+3WKqoQGHZ1raWc14SF8 SGnveon+4kLa1Pes/ZmrgiVJmwAMpH8qAGnIiB11HoBck4ObktF+m7L1N1ZslnasMaN1aa+xZlfr ZGue2Sp9Ycwdgr2qXjGxXvlaBucU/DvOcd3ck0eLNXx99ZKc7NXNtV2898KuvvpV6zCRBcnwLiWZ hxRAbu9su79nQF5tQF+ZoQZrb97c2vp3/nO7+uBr9lf/x7+zbvvAytBsmLFTtvQY5+X779nV9Yvk H0/2+HifgsVNCt7u7OH1K66JemAN3DRYNm3o7VydoNUgdIBZGoRTEZeBq8ZN4KrkpnER4VhjbA1H B7Unf7iF+Dsoa9SQflmxmwSdG3KuvTg+iDrRXDGcJNMxjONgpq8I5qbok00wtWnWKU7EpDQZ7x8k vfEUrp++pn8TEHkEKcqqxsxw+plnpdBepegh0DNvT+WhSp1b8Y5rPEMehZllgdx+0hwSOmHTv+un YpdF4QFWOW5wJmraVOPmGvwWTu9D74hi8dZnTAPgaYZK4zv4PXJDggH2xs+u6AARUEC5/kQ9kpPt qoOcYHFQAOcTCJRZud6eFQyIpqRnZt2luntpXBwt6KMsEedo5sK6gX76c8dXWm+70866dI7omCVK ZSc2B3TULURwkxz5fGaPsHWTDJbio/6M67LISQUcLsa9sLlkVjJY2acg5PaNBiYjQIKhRgkSEhPY C4EQBlIlZKPK6zx4UcnN+1SLIpe5xL/TM2AA40Y2OE4q0ZREe6IpQ6XYGYa5+ai9Pk9IwExPcBCx J3fHY57XGpl8nYIRdJ+iTMSyHPhmMbrJRs20KOVSw880luvN7R1/dpkM3k3KhDmWJhow+Fy1rtfr FQfKo2wBvT2seQR86EJmZzoQIciToHF5KN0/jPSBqtJahAMxrxqxhDdbegBA36NRbuj84p4otA5N 6HjYivlsle76UcLI7LwW6lpQy818n1ZE34BKsKMT92ciCErhUh/23g9ShMeaRKAO54cGFqwJBHzY M2x+aVUOn9VdDnSgGtBXsj8IjE59WlOFJGZA5gb6pzKoNAmnvD6O+oJe3cyddaFg6uTzeqP0P0Va qP3nCvUxOo5dryeVfmeOYESASX6kSyZFST2aK0IiKhKQQG7D9OVGhXLsgo9qTOEcjWjcYmnNbVTp Y/Ci4SujQubxFTlplQVfjgUME3UkAk/ut9oTxdmoERdd59p75/xsVmas9OlECgCjhBqfH/YXZ9ih EtJ3+fedJ9bopu7Jr7zkOeEcAG4g8ds83NFpY/LIEdNHmj05u5FcnfuKIZ+zfqFriAaTQW364hNS y1Bo/fG0pQh2d9LEE3Lcy6j8l0KtEewhCEoJ9bEck2qic8tL2QHcvwUnqE+QefOO/Ci9BjoKOKTO IMbTalu8eDvd/riz09PjP+Vr5lPfGZW7PtBQqGNo/jiqASgbMU7pU0DcHNhccEznd3yo7P7LT1Li h1LrFSWmVpfPqTn3LP2b11rPSeWJvbFDA0o6t/2uofzR7CIF5Os5kbrF4ir99yvWXaf9X/+K7TBz NwXjx+3G2s3eTikIbJuUlF7W9o3f+0PbpDX8dz/+K5uBo1u6DWr3Xhkq7MXL9zkl5+QNN7A7p7Qe 9smHzEE1kjyEkQODNme0rqNzFMaXyGynmaqIzocUydUci+QOBjyhshszp2hztkDOOstSGigvgfQ3 17BorGdISpz6ljPoEMQdWgheqiuknmnz5lmr5TmaFRuttDGQCtRgGlSx3IiMeNDGP9M1G84HKL+T k1FMfocmjXLkS/gv31p8Z8heMULxI99pbBaYBpxPUbz4eSBoNKzeIDEtr8SxVGoZzj8PcPhEjDgM C4PLPsoDfZyo8sihe+t63hVQj8cb35eNWKGMfY4xVSh7IkBAe7c7GnAKwF8ARDybCaUFtwLOgvpc 6aNIZPe1Vu4VyMX9oFI+MtnZgmVHzPREpyrlJNAN2KiEXznCiQkN0SksVf6eJTxoi/WNslSsM8DX rTsgDE4vUlYM/ld9EjeFnakWI3DGtegz7RWo0Wvp35hIATQEe+jFzTOqvD9uH8mRo+L3SbNNhcrF vpEcA34efKbTac/jccDzQiXAzjvDA/WKWZrIFiOgE1VBKI9xfuVc3adw4CCmQ5XckZ6+nzhZz3AR 1FFvrmkyko3AEe/BPsYUktr3NTJ7XGtwqYgOpqBjs9lRMgHdsHhe+PzH3ZayFhDDBdoVHD921sJp HRW4wEiVxZwd89CHw4xKrAuMC2uSoeuaI53f0RHZFy+f0QEhW0XjAtCsErqhi5qIb49SMwr6TEJL NmnE/hLypGwe6yeeZ8/Ad85SY+moHYWcSxHSOR93ockRslVmzbFlUDUtbyN4w8/kAFmbzcglghXY Xp5DOs4SExYwiaLRuu3djoirtGBwGzQVcnP4vBdevQjEQqPNYCUjyCojMUiOrOzKvMaiBBp7NxIB TOyAg4csAmR9mDxA1iTZaqztGPsW+yDQ32gEOx1b17GTTl5VjvZRdtDObGO8pjwszREd7TztfjnR hiujYes8mef7BjtDy4rpKEk6mDEoiWuOprf89zojCw25ohglNrh2JuT8XG2JblE3rXyHl3wLyogY 7SyCzNLfy31dvuAz4WintC8Wz1+wZAZUrkvPgPOmPfEyDyAtjmXvqDQN3qE7iPvLgLccXFMODQvi BsMXQymigX4adNMAwrQnoXSxLliJ6ml30JiIF/Y2FjzRYaoHLIloL2cXuZoy8nI7R+GK3BU8RWCn 9y+uBR2erFb1lpstBBVVRNjKSWMfA1U0gjDe1qC0i7T5wdtHVa5vlMAVlQLJtjsQIeUzgP5f2sen dK+72y/tgGQ27aeHORod1imou7H55TU7YNE8Ubq247bfWXUsVDF6k45nB1ustra6WnJea19f2Poq BYXXN5Qzq9L5NZAyefNp8i9v7Gvf/8f2d6/v7dNffGR1SpxL8JIxS5WVnaNdvrhhZ6oC7J42AgDZ PtlOUBvQR1RjqOr86ioZ7bm9ut/by8sVaBbMHoZy5pCoukfZ40L9HGVXUcYrPQMqY5CvWTYuxSCk ZI3Oj9Wlhmaz2tpK2wdyE1VPMVBon0D3qOnE3cJ7IGZYQKiSfK6G5PZxM5daGFb4uQ3edadzYPmm a3x1RBagf5K3R3rdSKw9R/fMjU5kCuwNU2BrE1kJX3hBis28IyeOMlObLlD8rAuhX2n3KEsN5Wrv FEXbOYZzu14szUihK+V4n9LLiegs8+yXIpy8P+OMWGz4we/T02wHjrVoHb1wbp1F5otrhoNGo4Df trHM4SVhZN6gcHs3EuB3SK2ptAGy6TH9dkmDw7JMWvyo75eHI5HYjh02vcjorNzPyD3Q/W5s1qO0 XxP9QKZXNTVRDjozyDhQwgE6dEA/Goo9EgXyLCna6mV0o8ysdnMOmUcTTXNS+z/KahX7z1KWc2K5 F2L+J0hrpM14jfJnuk8pHEmBTWFHBA/1kvfi1El7buhPtr1/SMdLFzNDljZLBviW9xeZNULw13ev GbjlYepzDF6uWE7FfllfXNkqZXPgzUEnDXrdKMUBBQLtgV3kaXNr3uyROnlAmBCsU+tof8zOHsYW Y2mwBubObSFXbu/NDBDaTMFP4WjmUGgyQzh13C8gPGgQgKwGVc+PW24mBAcIGlBWHVg2jPFONed5 UrfOx8kgQGqSwUGH1ZyNALv0nNNnQqS5Gqcd4Ocdy6FzanHB+FYd9Jt21uCWprUBXb3hCK4g5FNS QJEC48anaXP/YjpAWjsYCYaOzMv1tR3KDQ12325Yxll6o0zfYN9LmxCIK9FY7DesMQRQSCZJ0p/z 81SaF2JB3hyCpiFmJipYQblXCKSQir4SFwy8UKEdLcvAcKTiMMqW0AYgMEsJbd0VREpx/7Z7ScwM KeNnZ/biwu3FkXsGnXQMJDpx+RBYHtiJC0pKz7IspUjy6KyStg/f4m+AVl6u10oUqJ4f0keSkADP EHxAkMbL2Vj6Wi2WDObZ3lvoesALah/GYJCKBmzB7hlww1TPncfZegKCJC9sUkb1fYA61g0624H2 4XzgvOCkSczvOz6TWSFbAxvE2dyqtKW3lVzPglVL+iYGfQgKsNZnIvAX1N2EFNCCXN2hEn8T8jNL VD0gPVP0WTONsluMKEsXXO8ngZ58A6kb8B1euWkViU6AgZ4VGCSTKcSwrhZNA1p1M/qIhV2kvQIt s4vjXbIhV7ZNgQDQM927kypdbBm1HCSFKkAkdrDPRHaYp5+kCDF0XgWKkZXYy2ZXLwiXshMcXK79 IQWOKdg4puAxEknjBIGCe4L+CLqmTBSTHT4kO5oCmdYFzoFiIWnH2kHCRDkCm2sqA7+K/KyDS0jQ xxwX8VmkHRq86OrVzFG79Al5lYwdiuje8OqP5QI6Q+2UADZEARtgBPpM9519BXQt/F0nHvegZqYW 1443pwW2fZgRbCBSt7hMey4l48lOU5fxEvSvOWXHWmiHDgUlsh7u9uTVYo28uF9bm+7ZeykQNCSy KdFsHw/29V/9Tbv64D379H/7n6w4vuYcadzbN+3n6Ram4Lho7MV737LL66+n+1na7etPaRe7ZKfe vPqIMkls+otghSrGzYlNDuD50MBjWWcl5ZoGorSA6HXjIpALdvx0dBAi2RVVji+ScZNSOGFkl/1g +aAXZAraMbLii3V66PvONsc3KcMVSbbyYDKjUk/Qs0DXFOS4fhO+58IYu5fOEDK+R9Ml4h5kwuyE J5ezrfjdNK3TyvHFeNYY/RZqFejgFCXjdXRTXR2uXh97NP6dmhLUldQXQZj1gkGMuIry6BAlUvFA sMj7/rzsO2Y7I5LY+ZSOfNqDD7NvTt6xVGSYuigldcLmgiEySs9cawUnMhyQ1TgyayeK2GvCA+Vo gGqgN9XLRQyCiHpUPgA8PXe0Z4PDM0gfCEE6fAZLS0CX0jUeu+IsK88k6bgQGIbCLLiCRWSprXS9 NrsH3l8a+ZkaDTAojrpWECJp5xjlIGS6ngiVFkIMMdyTf+0AACAASURBVIi+LlYsWSY3Zg8Ptzpm jY7VlJli9Nz6gkTbXdq40H1j2/kSM//Q1JM2/G5EFw7JYD5++UoaYum2rp/fkGYQiv7YpwN50D5s 3dXwQyYIBG9OOqjrUb+rO98vuQxeiusDrgWCA5RDTnuVcznKab/PexzizfudAsRnz24YmOwd/Ypy 9VjmLelkgMpBxiW4fngPmjAQsAYnFsdo25HnRO7WJFHb7/YqhS6lgn7Y79IXZIhKu0oZMgydAo7e 5SyExohfNCf3Z9yP2isa3TXnnmJgQFs1y8kJHYhp5FvvjVnQi1v4OJ5oKGFzxszLcsX5QGt8VEse 4Yj0YGu2gxpOmgZzZBejAXEUa4rIA+HT4G1JtwBtTtaeyVrYwKNz3jihAw6uHri3Zh5YqkFkkWVg gOwBqWUJFeUhEx8Nz2POMv+G/9bYoZ6BWugA5jnRCO5dlZ50Ai+tqRpyjoTh3Msy/l2cXd9TmzS1 nTGTFiOmpnY489kmqFhl57b2zHbaOCnA1SryHuDf1wpSOS7Pf0ZZIgt/UvEbrm8MSi0VhCFQIaFo 6N/6zGEY1RKmvmRaJRr3ougulEBBAp+rGoU6lmfPUgKL4H3NCpUauoTGcG5yM0W63JdN0K+ic4+Y Eh4EW+SHBRo7oRRVrkZQpueOjvebQcFiB7sFHhiqBw8psANShYTFR67l4JTVOg22Z7cokp1DStI7 8SJh62a+ZsqyylS4WbXMQeep82fG9Rz6CGq4YTOH+z5RnIQs9EOZK8hBcRGBIwJmNViWxUjX0Bpz cxBCfIJK/bhFbrgYcH+B2qHrNdnJYbOxOtl47CnIAM1TMIeO19XFNQV9cf8QWGmsYMVke9/sbZ8O t3s4yI6h7Py4t3/47e+kIHljP/vRj5gMN9CCTH6vpqSQ9Bmfv3yPyDwbzHycHrQdIaAfybrEfp0T A5mRbTJMN+iSqVRaAxIVJD4xCoJfxbAiZ+39hCxb02hfMIPSg6vVmYW2+EbdgkAVMHwYcwlR0kGr O1EksJKarRUH7Zfex4/Esbnxc0dMlQO47mlwNfmZNsy5XMa0jHlWPs0b8WnAF5mDnWVeyIaiuaPz nZv/tlRJMQifsbEZeLoBAFIZvDQZwfOAbzyHMEVOLpYGzKQz7PweBfLGJgGlteZhm/7tBq7XAsh/ Kx6e5UwYz7Wg3EXlM0Cp2+2Bkt7XgvzqZeeykNAz+NldKRR05J7I+KPzaQATNS3a7rDlulAJQ0RZ bcK0PpJDOgIZAw+MzhhohyvEF+oWPTa7s+BYFmnaDdrka1Ppwp+xcwtjXiITOlMwOjivE+sMRqzq m7Qf5gzk4hlwdZG9DqS+5fkiKz+kLA4lY8wMXiZbBTkLTKN4dX9LJ7xYAY28YKB42N6RGB7lRwQ1 NICdiNO451/efu6lnjkbgjQUvvIpBhfkqqCZI5A1XMP9w11eN5y/aULXEJxQof/6ij+jOG/TTSQk NPCcwaLLgeAewWjgv9F0gUAUY2e45ilDsk5BADopj0Qoy0ZcotbJ8VdX+jycZ/AC8Wzu7u6oT3W5 vuT6RMDRHg9Wr+acCUrUMB3vCnMLfQKEuksHXsupS0ke0FzwEGeiadSlqgCVVwqIFmGp1bIvLMF4 4wwpFhEQgY8003QVBSsK7IbS50r3kRB69g9b5dpeGivmCR5KIc7lDC4jAllsV3ANn6eAniVjBLhw CghWqJZfW8zspC4cOt5wHfOawZW4h64N2Xdeal6S+kKb6HYj5rQySUpJx867h0fZj5HfOOOMX+ka Sv+wzBzL4FzinsZxIxgPzhN192biP0ZARk5kNR/tqLXj/vRmkeBNBk/uLR6cJ6djwDdy5qKawsDV irGxzl/UarP/j1cOntRxXHj1AvcKZf4s6Fs44hPBZS9kkZxw941PGxt4fmWcr3Opvfwe/+bv+yro +bS0UYFRo9QgjbBozEr3aA5xaefpgr+GqQWd2+KuH7tPp02AOYhzPwA+L0SEFQRJhLriGDD/fVd6 NzV3l2gFM0lQ3axbu3rZ2Yu0N9E1i1LeKSVTmDxCOoqPBZw5FYH+AzqMRyRwMyJH2+aQZx9j3WZt SfdhWOcV2jAGdeAHJ3MW4EiG6OQrSi95wy3wuRSFS2V5Z3D/RGkC+2w4L9+yo7mEXxlpTEXxZPUM /m/ea0i+AOhKPgsc6bQO9o9LTlmByHA1v6SiASbGYEQXArYZpo+kZ4qpHMehYSx09+pLu7xe2zf+ wXfth//p39sXP/+5XQBFX85o0zrcNyR5z57Zi698QIAANpdNbaetffHF59ynq5loNXWExGhF3ieD +ZB++eJ6YatixgdIxIKyDaXLcgzkpylYGMUocUEsOyAD9v8CikckinmGwZHgAoPxK9DFlZxCufAb WksHa2gpLElqPDq4QjBwwruKUiqRqQiaxjrpWYv5OSJWjltn+Pu7U6evd3Lmiol2Wq/PVEh1Hvw9 5ZUFQjnlvp19dqBrk887Ox4yJaJUYwY1syfNB/lvHIErehvRyPNjclRUNAoM5i0UOgdmuGVpUyv1 NOBluRkoAz7HJmWFEFaG4CocJ8euSZ5mxTl0Ldu3UVaHsOHQh5wAOl/SpqB6f8WMpThiksKeXCZ4 qtZL1615ltafzp4NUdg2LezOyf39WFK1UK6ns41Nrq4nsFQK3+SDwjjetxLz+HifBgV6fbTV8x8j woL5omzNXyXHdpnOE2KolX3x5SsGMRJvFWkd48Z4f4FwwdDOa341pj0yr+fZiHeHx+Tk54jCbH9C Jy2CyYUdylozX2eVI2K1ynNAFzcPPP/15Yr3P9AlrD9sfjrhoXfdNnXE0XichjMqwDolcyC2484i KEI5J5oYtC0KovNo0sDfITjDKD1xD0u7SP9GaSECA0iqaKyYHA14algXEOw9uVQIghXcZ/wMx4E2 HAz24SidOdgU8PQq50hVxYgCcvJMI56RSp8xkkkd9kw/Bo3Y0sQOIL2rFCgeSOiGkafe3Ny74olW 1QzgqZnZKgFVNaLIaBUWAJJdlBR57wq/1nT95EP2A5t56k76cBz5hs9yjbwyz0+WZE9UMxBonDpN 5KiZ5A5EVjhpBSgaOUDi7YFriLmOkZBHUCUkb8jPDQjqtBoA3bxA2koGbSs+L4kIV5zfKyT25Eih aBW4/qurS6ImDLa9akL7XjSW5Z4KcS11nyRdMVUamNqWbA9tTIar8rwqwrWI5+jzuclvLcrMUSPu 5NQZaMMxlxaZwkdyVRL/njh38+A5mjDoE0qX0sJfDX5stgJHIKlRVVnggwFd6ffHLHRJi+L82p5e 79Quq6wvkAQJIWed4lxr71fo1XFQONJNezih8UwDuTPFAiakrdYMuu8VJdF+lb18MwIsI+dslKAi NxT0hUJ0AKyNi7QfuTeP4tCdUhKO7vFdSkbb0472Nnf/43ZF6ZJRa0c9OswEPQZCNluS+wnUCY1F 5l3XpAzZnMl7vg4i5J247YUHxIVWRB/i1rzR5/zKYEpSU1Htal5pKTJXSUL158/IoTrnXCIIlApD FT6a5wUZmIPtjsnm9jUlWerZ0if0JF+WgrvT8sYOSF5urm2dfN/9px/bP/itP7LL99b2wz//cyvS fVwlW9gmn9fu00o9tWzwu3z2nq3S/e7KcX9hnuzd7Wv6TNw3IuEZkgapG1IjxyYZ3nSrFgO5cegI K5T4utOLIEjyFTHLEvo20YXFZoIOI4Hc4DfO0ZqVLiCozQOicDvULqWgGZMQa+XszOSzTx740Vh1 quOzX6ZwDbIp6jXZKIHOTR/IFIF7VzDydHNN/+7vOxavqdLGKvsoh/r7BVTlIPAMKZp8VtZtGoqz jT0iak/+3lE4PMQePJThfJJENUQQGxCylvC0i3QsY1gO3nIDR854lEWWvnmQbbFdHpla69fuMwoR EFXxrZfVo0RJwjRK8uAegmNDtEiSCkAblmn9HMBhwhrD+aIDENnMzWVycrWtksNrkqHo0/oQ+tKS 04WyI9IKkVYnZWC3om0jBADgvrJrBdrsULIQjlTWG6LqFFEtvKyAICB9C426ITmwssLnhUFx7qLJ iPCS8X29tmr9QYqsr22fMtQBeodrsy0+EU0SBkrEjEYGZTAED5fX15S+QICwOx6oiTaUx7QXFXzi WiDLgDWNPbJP95EjZlLwxdvcjBpwaBQhyoBh7UAVCijAPwhRSUHAEkr7KRh+uL+jIwCChutE96yc m1AovB8yGeDH4N7gffBlgaSh0QMODvQLnCPOz7iWNf6JAQjuB+bEOqFeumbxktL+8uqaXBXOzkz3 erZeEXETQnikHYEMAEt6kPu4XJJ0zaaKhXPp8sOLYN2EaJnpfSuhQi3FnHtfsxXXNgcs4D7ZIgcZ Q1F6WbVlAIM1iZFcCOTArelOEoSuixA1l+Ou2WySPrPZctg8+GmYjzhfrRzZ7J2EXhIdLcitQ2Iw k2OOErcHP2qkmNnupDFkbboHDMBgXwN1A5eu0cSNvlNlIpAkanwi6K3VkEGZBFZNjvk92NOHx30u 9y598sd0/Fbt6BS3Dmz6fj9O5Ui/v7y+ctR7mR3NFPmLCoLQwiH/fmrXopqQ7ewwcqbIQetHiano oi+9CSuQkyHKAk/sd7bFzPtH+0qpBE4Zmp3TMPwcQmA2EoQo4+oJFpPUVg0POreR/xx2wp7QeJ7+ t3K7k9G4wpGlksbH758HK+TtJltBeahxilAABP2TQG6wkS/X0Tc4FQllksL15tpSw+m5iCHJ0dgo PD5Q2JnPG3QND2aRZK+SLVlc9mzSoDQOxLmTvTil9QEu3YHdtEfu/3hpTakpjVfFxow97SCCE/pR 8qKX5JuRLlKN00kwfg4X33niJMRwMj3DbUE51LIFJq1NN/uy98UYyCnQH597POOQiBHq57FFfA0T AIYf1pmoeColD+h8TcHsqSmIvrVpX/AL0xp2z+32ds9n+Nt/8D27/eKX9tFf/9AW/vwFiHWuvbi0 lx9+k9xCIIC9i5o/3L+2AykUM147tSpJhncncEpv3iPj9zITLrSaFV7qqmRfCtWsKZ3phGh2oaUb 33lmwKHY3sYsqHSm7MkDCwxzhkTBHs64E0ESt5ACwJcXyamnCG5bcebbCA+fdyfFpsmbMu+pc+22 6QJS4DLy+XQc3yT+u/H45kbxKWdNm84y1K6ghcKv5KwVZzo+py46Ur3saV6mHIRWlflc49zGhfKu zp1xM/hCzIOFlXX2w9jVRSNRnaN5I+G/4O+mnI7SZ4ix+3WI8uh4/UIMRgPFEjWNbXDw/D4XymIR RYBLUPqzwnMuA/EbtJROGNAOlAjpJuaHovMH47gYpKCZoOWYodKTZnRDgu6/H9RVWkTjSTzPaUZP 42XsbKy4iweWSNWXKANbs1EnDLExXydVwDlj0OGBo+zrUx7VM/h1VmxqkKGl5l7KHJfXH9owf2E1 hr5fwODtpF8GZftTMnCgEEBYFoHqEqU9yEyUtt8eJUDciJmNMi67VuulSgamjkmihOl3B5YRU7BQ qcEAYspdo0Hi2G9Nei773aMd0/1FScyY0W4UUCHAAEl+PiMfDsFeh8+2gsOyke3utyqXIjnbbprs ACuX+ABXCSgfsnfQIrRWhUwuPUPsm84uL5Yu6DuQT4N1C2QS2S0MP4Ir2A8Eb8fTwbbJAaABgM1Q KXjEKC7wb9YraaM9gjwP1LDTeZTmjUmmSSYcrVMqsYjmDPNuebKnKhl4oQ8l7VVJLTQlYKF4rz1W q/mJDqwnL1MacpKAQRCAhIaTPJIxXbCjWMHMEU1Ju4MQkV6yIwjAUE4vfE+xs7Vvcgc+Sp2K4+Qw EGCuqnXmQoa9IrKF/VOqPI5SIIw5UD8EYBidBhwjJnms11d8HxP1o0rAWicpMC5XLJczwGOlYJuD OnUtO0pXjpI1OBYCa3ClgMJGaSzKsFNh2apSpYDrwc5fT1GoSLLZTDatfHQ+03myz9WzWEgn1NGU voiQxyxXXAqltNHFGdw3fek62byB49HudZIS4pg90Xu4DvL5esDpx8titf6Jpbul3s+hPx9+amPV JPxOf/bvKW+1kNaNysuFEEoer3AuH/ni5VmVi8+pE9o2Hle+YZp4C4wBKj3PvFBKhlWy5wgaFAh1 mkySggYg1ycGdIj9Bg+GCtrri4u1XQ6aYINpKoftRpx2dpqDV7dhEx45quDJ+XOwmL3Oa6xIwWkO KbCrHtSQs7hy+ZeZtBAZeFd5HZCqFYDH0GY/l+VMqqeVtkITNcbHkddiSHYFmpt/7QEcn8ck7hiC q14UIcvHaosF/5rJfZls9QEy47Z5dW/3P/vEfv9P/hv7jd/9Tfu3/8v/bo+vvmDDHEd0Yab2XrJO 2MNf/ca3mbB3+1tWn467vd2//oLo6Ar0EKeH1eRK9V3mn2Hs1cnnx6F1mmKUlRobyBtg5lQyM8UC iLmNEA8dfBg8N1kyiuDw4F/sTkkXDPIepy3guOBUNEdCtZAMWGDm2bxitx4yZnCxSifdhuyCjFjA s4OEIH1jl5MbHy9cUztBqsa/15Kd/mx67Gk5NDZtFrOlRRhLvFw4LPGNw+TPjuXJ1DBZMJ5s8hqq ajy3cZ9HUDf+aAjdtlw1dSPn/82GM19PkRdmP7keaRqZRQG6m1xvaUO+1sh6Z8UoUsmBywFBF2O3 bA4QSfg1BaGk+aNJplDJxflafJ5+XSzTpL9lhoeW7vWlzVZQ076ktATh9wM6nFsGUHjGS3C8VgXR vX23kX6ejc8vPAWfif+899b0wUu+g2BHIoVBgB0GjZzDxqQBZblNs2MRVPR1I26UBSIthBpzLlHb 5UB3ENHTubfL67SpO3US9QfOulveqEmkZ9mwz+W5bjjYETD5bJvuxUFq/gP2ycx26FiHYd5seDcR jGL+Xon90fRMqMsao2Z2nEogIdsZGwdC2BfJ1fEwEPmDMQXCgyBqD1j/7g3vCzTYet9fKGce9yfK R6gZQQHakSU+lecu0nNCqSAGvhfsFFSyBuf++PqWzvzZsxc01igfwywEegYjBD4N1hpKMggMj8Xg cwEL6ZLNZrynKNdSdw3JpUunoNNWYrHi6WF7Hw87dqnG2sLfsQGhP45OEc0pVZ2DIomXC6WNZEUl WombBo+TiU8r51WX6pAunFcHvopKmD3fi5JT7V272FFAK6Vfp+7hh4eNgk6iWNfJMAe6K6I51qcQ MzVOLHw8UDQzcLpF1+dEAoE0UFPwMCGkfOa0aBc0zSEaECi+60iYRmDVWZxZDQq131PZuMfHBzU9 eENHOEwK+wJl9KQRAaOOL+REzRuNI3nRPf+0ChIyHONEgawFmasHXf59No85iQ25jwhW7Ow9Uxtf eGLJ/3qH+yhfpbIs+07hC3sFcgXLY64LOg02J44/qh0SEc6ppLooBzWM4RsFdz6FZvBTG0bbPPoM t8SFJjLgXLGW4cRZwu06TzSBptVMMhWYiYAf/oBBXB8c4JE3jWS/6wqNIaNg8cBmMmPP7YzrG+2H KNsLQd4rTCV305P7vh+5gq2u/5R9P0ZKXdh6tmIwg2d0TAmnhHI31IWExtkp/dcgZxboKJHxMq+H 3iWNmoMSIUh6ILFnQu8SPVyjtWIAjSBzVLZ3JDdGVTJAHMutoxSagnwhcl6lysFb+HGzacA9fVbG qTwhUST5lD6vvYqXJt51azNICD080ob/4b/8Y+vXC/vr/+cHTP7qy1W6jSlohl0nh7WxX/2VX7Gb Z++zEgB7Djt5eNza5u41eqjZwT+0EnavecNihAYaDtqe/JCWpFMfuYVNW0vjCKVqGOxVelAY7o1F 0XAYt89YRaDHCEUOfgZR0aaTpEOgS52yTQycvUiRJkstg/hLh+2RDxwOsXYyQJBip5A34e7esh4P kbHBezL9xlMTqB0DnvNS4gjXF3kDxagv/5uyPMsqGXk7UqVXmcmu5tnEzAVyI9urqvGhn31uzrbe Af8/QRGfln5HiF//G6c0dJ7BqiQk4mhnoYafuxJtRDX7ejJsuhhy2TGPPMsac1EyEOKhzTKQeNqa Ar7gnrCMilIaSqnozhukpYTS7xEZ3mBZBHmeMjhO9EAJB109ywXlCyCwC3JsV+zISyk86IHhQuZy ZOaZm5zeCsBD66kIJLIbxUWLUmhbWOPC02fep0rOJpBOtZx3apDodY9VkogNX1CAU/wYdfk1q3X6 XXo/asSnEdXpq5S4lCfnGqa1CsSmUBC0uO4p9miU02loPHf7B1ulzJRTDU7J+RPdPqE2yHE54J4e +kdfT5VCbJeoiTVmNRootPcg7zAnwoIgTw0VrSNCLK2mv4OsiaYelAxywLk7tT0rO9ERiPMRt65n oLVYLWkecVy8IrF7vL8jARsEYkisUPJnv89irxjb9eLFC8mmpOtaU5ZAPDHoVsXkASFtlnl35l2l WEMx/UHlvcI7Y9scaJQ+gopzPz0pG3x6B8qaM18fvXf+lcOoTynk2SUzvAMzHLqQIXXEgstTUJdw UNLrx2ZZ8iQJodb5aKMd0L4DybtpjxlFCX4aeq/jPfF81VU7o306Zf3A0yjoOqiEiheaIXDPoVcH UjRQM3Utz3l/cM+p9zWoISQ0FANxi/uHgJ/vzUFele0P7bYjhNmeTOyrgsOWQZxEp2uWxUe5kzFw PhMHdtsbpcJA4bxeKrRugtSdv6Jbf2I/A6GbolyByBXFhF5x/sqam/7emBphPpS+Lwe3v2/b6Kdl 0/A/5z+TXSscLYuk/Ozce833hh0TuuQcZ1MZvwt+uvsC2PBO8DG/qkg4C0FFaFyAfekCUDDz5gjd c15MWzFh72SgLc+Mdm3OypslYI/rMrjyCo+Cd85wTnPArFisOcnj4tmztM+OnGiAxA7I0yElNcem yUF/xOMVS6sYNXhSExp4dCkYHAolBbVrIlbp2EWpEXZV1vnT6MVhwu/llBUPtIRxuARXBGsZCPDn 4P5j1s18DY2/ZwLuoA5GLDJGZEDspe2JhsUcSQ25rOkaU1b+jQ+/Zr/7B39gv3j1pf3dj3+hylS6 p5ttCvAwjQXrJP37m9/9Dq8D934PGs1+LxrRfktZKdz3hqMjTeVUA6k6Zf9rZL8pg9wgg7p6aUvw VPqKGx/ifWxWqKtctgBiQD0vzMSDolUXAUZJTRauh2NPzSLUc7FhwP9ZgGNS+3gldgbVyXlsWJrq qC+VjMfFIl17m4fT9h5YsSyLbLXoRSjoqpyHxZDhPlT5EVBUIy8tb87Jhmq7fTbu6iY18b7wMIrB ZTVGDpn04uIhdc4p87XXGYMX8fhKahkVxaiCHgsqdz/5BlNQ6CNzoMdUjZ2pnFHopSnGskwAxO0p qRNUMwuggCOhBeZRhHGbQVEtN7sJGo92fKANeBYnPL+yHp0L974ovQwCCyETLCVRU85E6CyCp6f5 hZhXh3bskrpLgy2KBbW9TsOOQooViLUpuNu3VNVNjqG1BUZO4U8ryG1c2WJ9xfmUs1IZ53HzaEtX nxd5ueI97QZ1IvWli2eaxquVXnPVsHjpdoGEy3sO1MzLwxL6NAo3d8hrOnU5K2B1GZJeU0Sweeel ugD3ZcvZvi/m6dr2O2sXMHoV0bQiZUbztH4fhxX3DInCswPLYURKgVigLLCaOYqbHHhHkUASYumo upWCRDyn9P7Fiw9TgnRkKRgIDFA8Q/cnzq2HICe08VRePFG/DbpQjTcIFPbi2XNmbSi7lRRcXZBH iMaH44Ewny0ubqzd39r9/p5IE84DJVSUe+H8K7TYczrDkP5+SW7g9vE2E99LiHqmvQ0CMhwItcwA xqTP3Bz3zI5hYqBazkTxqAAB/LyL5SUza5QQoiyFbJ3BBBql0JHaKrECWgj7A74NeF0o8WjaiQ9W R0kZvJG+z6K9eCU/wSAJ56/RZNL5GpywDBX9cOo919bA+YawA5jLOvPSHhGuXtzQgfNge/2ultwM dxfWbKukiigP2Hbr67TO9j6PVo5JXd9KfNdXC2s3QgaLfi62DuzpsszcNpS8hRDXtLcITCMQYmdp v5dA8FoJMbtfIQbKbuMFA3E4SARyi1VPvTMghUzwWu9anaszVSXZGYW1sb4WyzXXDs+FFZrGopmD ungedHemedutzwVezIRkHsHncd4e1z3KyQh8sTebY7Zz3KvOl5Ngt0a5QZ6IFQCfkoOpFewSp/xb sh+l722L5L1zpL0S2l6oIYnOmx3lJb/Q7VmS/N9wHxTF4JWIOFhJqa2Bjkz7t3I6EHlQ5gFPMdJc pnFgDjCdmtS7hNPAWdxKkqPpbJj4J5XlsBdgEyB71JECQi7vIIQZthfnww5TW4jsz3FtKt8CBRTY X5IWImGGCS0I1YNkc0B5AiVk6fI/OZguxR2blRrJKUqRuuYlaeVNG9DcI0AoVDsAC+q7AummHW11 /b0SlxJaaPWFXS6u+bvr5wcm8aBvHNHxikDNZX0oq1Oq/MvpPR5kQoqqS3YdwW2b1nRQFYjSoeOY zRHi59ts5IKz87aX3z3hvnekAfKZcJhB6QnJIH3SAp21rrCQnysCCs5SHo+pUjfeF9q3koHCd7v0 +6v5rQ23SxuOD/br/+Jf23f+0fftf/wf/md7+Oxv7fkVAMkTBeK3x08JBnztq79hN8+/aUNyO8UO +nsDtVR/+ernnKuKz+igYpe+P3Z7VTrjIuG8Oc4Frexoc06Z8goK4+VMxoBBV+FliFLlvU4kdZas huCOmcO/6cOhQpyOT/0nIAHIykoXukUZBQTf41YjJeCAO82GxOIB1Mtsde6bx7w70LtX8UImTVkG QuABgU7q7BNOQqAUU0Sr9CCMYosZ1xnLlNxwLjEwPkTL5McoOz595c/wrF+lzmgqj88YWEojsMM2 adX8PUqmEeucwzKQi1MTXSTUzzKn8br5214yCVTU9oyNqNmg8nfpTkaaORJvprRHF2NivO2+ELpI 3hztAregBF8dtai9BEGZGIiKFug0lIOiLhRhC9A5jQAAIABJREFUft3fOThn4DBBhJVdeicaxxMc HoIPPCLqvhVcG3MQW2GcgDZRHNWbY0zE9ciGg+vUuCK8ShDK4CDlUPbitIEImyVVnIQuzpHRIHXm GuCui8gMCwjjoCI9sqo9Z3ACrSkzEhFlgEAvOjeQd3dvkgNWl1eVAp6L+io350QJp6S4MlDtgSKc gfIGF4VSAi7MWdbiUKkZTsEtrA9G4WGPFcd0XHBPu2h/36Wf75Br2xfp98tjS+4pRvYs5vuUPBUM AhGo4jmCr9G1IQ5tPhcRa+zETPv+rsnltM1J+mIDuy/1M5jqisiUkG/YAXajQyro2PI65NC09hEg sGMyfdbt5s7sQXscvLfQ5Q4JCpXH9Xfgxu229wyG0PkZZHiV60req7ZxnmlZ5RIfbAk75ucqR263 x4z6KHjwhIzC2zOXSSjFhUTg3Qx5ogaDtF6itWpGdITGfbAaASQRwiYAiBq3QqEQtJ4mTR44UTYC uMQLnn1D0dQ+NxJIUqVGZZ1rtWRmHo1DVPyiDieR4lOTAyDuXTyXcpZ13ijL42jkdFZqdCtHqRXa epRHSXsTQZ9F52w/dtfHvUAwiskrKg8rlY0xWZ0r+1OCydGv6ditaUelbPM5shZTSKY86GlJ09wK s3v0HYBcppYw3orKhfZ56XqPI9LX5/umRHbs8K+cF1l66TX7hcEyrSZXWCYVlGnlJVDAt2g773Ac 0ypM/pzJa/xZaVn7NDyKS3/BR5dxTo4axmFURRipOP2Teyt0ypzzo6pKcJ6HJ9fHWL7osiLEeI1l Pi/+plczGekCuSyu380wkD4lxXOIVtOfHDl9BWuvOZ5YkdBakNhwYT5tolT8gWQdCbZBYJ0yJgrQ YzJKX0aDjqgCGJEFmx7SZR39s8czcQ2d1nvhsk3T9feu1+DBPL/v417qvi0wLua4sofNp+k6L+xf /PP/1tYLs7/8sz+148PWOjRE9a7BOkiw+zvf/bX/l7E3bbIlSa7DPDLzblX13ut1epkVPQMNIVAk QMwABEGIIEBSRpEy0wf9Mv0FyWT6INMnmWmhjIQomgiBogCBMBGEhjPA9ExP99tru1tmRijOcfeI uLdeg7wz1fXqLnkzIyM83I8fPy6bbHPvonbKQmCKwBsZSqRcB0Prsb7wGLoGCsYDcm/7A2Q+MBnW 5Kip86CbJLa8MSqUiDRibxIG6qWrMzGRJzHRSRmM7ErRX/IluiIfgAUOm7RHJaFxVqhLht+jbtiD pVFjUxVSoHg812lKp6QYDQo1Lig30zYNSEkJ0QXoA1cWYmyqUkQjAN3/YyMKaDc62potnDZr/1F6 yfJMm02sLlBHBlPSvoc0ZA3nTyetygIgytCetL2arKRLg9nkfPNHKyjozEFh2sUXNCbrWOUWyGvy tDQcoHyszVAlH9RZMkkVLBdUz3Xadg2TcrBKJVanLjSS0d54OQIRL3oYDTVFHIYuBgM3BOi/IeJB e7eEdlNJpWYij2sREoVzIV6YN698Lqt+Kfs+UNzSq8s01SuGPPYqcGsOJrmHncoSuD4aHUq7ts74 kS54idsxGr/DBT47j1ZxXnDgckSHRX+cUJvalVZKGi2rc8I0BDYlcMJ2aEOzzg4qOGyT7J2TafMG HDpPSzGytuyZ9rJUweE+LSidwdl7VOI7FOaTRdOqLzipkd3kezOic4aKvXZ5bTEazJ9H1elu+zJ7 TolSAiwcyAFTzL/X2YHc9CuUp5OzAXSB6SPjVKGybNofZAUaBTT7iMJEdXbA74KCPlAXSITQ8E1E pu7jnhICMNs4X/QFRbVmNEpG6DecB0CX0I1gLRdEirAu0d8Vj0Wv6RCgU0Du8LkZummTSpV0vTqL mP/QuXKHV1HzjkbP1xD0JwdTUgdnTuVsajA3m3HWar5UkBEFxwedbzwmLV4OZjfsxuH8UQS9WpSw 8m3SZEY0P3DIDq2mgKWkTFlZDEQvjhR1plPXoQr7aO3SQnFwKOc0aaA2mc1RCQatmHUemaNYeGzW 2bFbKQcOmyGcReq+sUBI56FXoI79XJw/FUse9D51C01Tj1rMAF9ACxvUnhMNMqeM87p32Y5k96Mv hQ5UK4ipvLdsiKl1CGoatg2yo0nZAP1326rLSUPu1jlyPpNymzS4TsXuVu3NvvdgORiKEkuAzbnB 4pglf+s9M8026azdnqUym+8u1ySnqdVz56598HU5/Uy7T5w/2rHTNG5n+4xysDRtailaFh1ZQO3n IbVdY3sOzRc0TuppGtgpIaVkwzJOWufYFV5LKHqKyiNjKVZnrlfUyk9dUUjzQavSOxWt6Mz16Ipw kYOTxzonp+2NjEelb8yjBq7Uu6Po8cRUpdprPaYWo+TAZK80qWGlnNIZwR5aDqJ7Sm+ajL0CIb3x ZFl4p2krXhc6gow+Zm+6dz5OXiHfgkBeejPt8np8Ii+nO/n6N78nv/Irvyz/+v/5N/LZDz+Vi3VU oAoFTvv7fM6zXD55LF//1s9xL8E+u9vvmUm4ef1a+YEoHsP1pFSKnQYgRb1XWFghwY7Nr9GMXitd EitAzElKynWD96tprYEnAWPWTorBNqsrkJRZ5r6iMzKSAFkbIpMHxcgOixztdbRQgErHhyqmOZq4 pEZuGv3OUTXrvNTRCa5tRZBHxu7I6RD3mjYLDfk9eVrTH7opdKE2EKbD61IV5igS9XMeHYmfwRZ4 LAa2XQjnC3Q0orIal0UljIqiPfNEEpcqx4P8LGLSLlpl0y+dQ6PImvMXFsFV1JvqUhq1+cRgEm1w qL953s97slTIOFVRWNzvzkRF9V4i7TiZflHSSlKQzWFVkQYAtH1xJf0MiQzRxvCLC9lmJ+D25kbe fvtduchz5Gq5ljW+A/wIaIvB8C6r+KIb9nHS6mdhqlfHdDauSG8GlhCqydjo2E10bOzOajoDiCYQ rj5qlG5jpDF7nvOAq/O5T/m+HMlFWjKgwef6oed3KiE+0WlUQWzo9sBZxkY2cX6wrZIXi3SaqvaU emeVsV48xDScqfxTW0284k3lFJAKicGjYwzvURaQ+EhAPPO55HFUnvPMptvx0Xu2PGZKkCQ0vkbK IkLWZZa722uGj0rkzvd0N1P2Yyb/bpYnb63lZnfPdDqujw6JBTtEY/dTMd6zIUgIHx6hH+pqSdmB ftY0/KpfsQcrCPjaLL0jyg4HXLtkKCq930Xr5KA9JvG9TAl33j1C24sxYAlq7JGqd4FaUrapW7li WllRltpb1M9fHbdZjXrv82uyooccRa9XhjiJVihHlUaBPaOG5uyV3qKbJp/Tuaqk+UAOmxc+qHxJ pS7o5qfkdXJhoiFTnUqdEJgnp6+jQ6zzNtKoewoSc8gLEYhw7TXd6g4WeHDs0BBqFsNTmy5p4i2V QHgncjkNZf2vF9aZQVKREFFpmepsOZ/Ox1816XRcoqUTk9FhvEcuHc9xKgidB5Gt8O+JM+HbY7GP 6pipI3T6cGTEeWBi6dVkmnCpKbBo5UVaJw+FLeSxkveke0f7XU5gb/ea1hHz47UBe/v7TZ950/Pn x9N/sy29XkNnRX/JHbjmfB74Hp3ZJD+mMCXZAhi0pbFKurgT7Vy39hzE08/NdVV5DilgBy1qft/C nGFfZwy6EDTaOmJ7LLtv5KtC+3CjvXsvUASJQAWt/9C1Zb+lTUKasWYAtSkarzSpegScI3dcE1PL lnZlO7psYykyvCQglVR+Q68JQwpbO51y6MvYlnnmHDt3yntD9BS13eSA/n77BY/z1//WP5Cf/8Vv yv/wX/5X8urpK3nnQkEm8gTRGzuv8Xfe/1hWl1fkj+Oxy+e/RZ/p21ek2Cytyw4DL7vvRScu2MZC Z2pUBwoctWNHN00Qj8Px6ZPRFpNCgNrPTSdB31WUgW2FVgvKDdDhGmcKf8KYubo8DBzV+OFMsBFv 3rg3g0WmRkpmQ3R899xwybT7QSkjlrrgC6LkzmSvfClJteoSBrEs8F6KI8Kb3/DVmOl27S0yygxl jsHJC5rCdVQuOdQ9l24R3jGgfZxA6+JOFn6PxaD5ZEfkT46qhFJ5qUiCOtzO6eECgkNm3SySlYpj XH1DKQ2yk54fnTKL1lwiwA1paac2V9kAPKBC7X0qNZrvuSCHpbYk4mdQ/ZIXxHZ/YD4fgsSoLPzJ j38qxy+em6MbGGksc8S+GVDIsJIVr3G26so9eZOztZVhtBxS0SFL1pZnaaRsNIiHYO4mjxe7Fuqg 8eFIA++jF5oYr0OBVL1vXVQHpNf6nxyFDbLv1xLzuaEv3kxtJW3VRgL4qBw6bgY0RpPc37wkXwM8 UxjM5UIRZfXVNL2RLIWLqB4cK4pQHhVhLea2Uw4IRCDL33Yfe+NMopFvmDa20Qv7WAIomiN0inZy sUIl8EVjONfkoVDFPWr66NF731An97inBltEg+X9li23eA8EvMU907RLFqag88OWTh/WtldkAwlb WhqUY3OAqjtQcq0igzAl5qKSmEdKo8BG3B+vS4DhaVSk0C1TwGhY+bdG2ItacanVoAN7cjrpf7JK OXWONHjb3W1tzFTw1+eC75tDQOowFCSXZjWqwFKIFWHguhTmCUECIpeIHQiWygmLxyoyjLlAtDAl So7QGUUQwTmggQ8xmF67FlCbD51Khr44NVrUEWpjegS75jQwzTjH8p7QVLizk8K+Vv1h7m0uLziu SHOP1omD1Adzkj3F6ms+dL6hB7m9uzHO3NKyLuHEIdvjuySVdKSnZd2Ooe/tEBy1lpLK9Z9CT5Dq qDxAsnQCW6ZDZTJY9I6nY7TUmqP0sUiNiCFWUmRBOuu24IHhqQPn+yCCJK7QJCeve2oN+wixWKSK u9Pr+fd5nLz/BAir6VPfy778oU6VPzwFqioO7Wtq57z4rR1nHR/7PJyROT64hiSOmiZz3LwDhCh4 YeoA0bJViopVB3IZXGGiHpfcRUvPrxBkd6ddJnwu1YERFQVeCYXXoSe5Pj42pG7LTM3RuMGs3o3q HzjrJbplNQoAipjQEgrXw5QrJNA6RemwvynyPssWyH88VY94AMQEbQvma8LvZwkK8h6y3d/J6u2P 5Vf/418nT/hHf/rjvEafyeJxDrDYX/5Iu4uuD9/49nfBOSGlCQgkAI3bVy/ZJWNBgXEF1MoYwYmT rlZIugMEVE0rxrLBsxYjo00EUsrtw5qi7Ih2bND2ZlGV5t2QKkypBgeRPbhRya6V3zVb8+o0mbif OQ9Jqw+RfgtofWPH1H5xBy2LJlI41iggPIyGoJ9Uq0BNkT86MqYOnl+3R2JlkkeF2r0/JedBsvSZ 6b4p58DQq1Bha4/2pDstTz//0XG3fqDDqoydcqeEG4nLC3hJvJ8nUyAL658GXlisC1+5TT2dVO+k 4Ju/y66whU6sPBc8fNNwNfrd3cSUGPg6bNDe9OXszSgqEmLVgL4RIVWZ7x3kLQBPvH7+LEcke3n5 4pqRFTZKSijkc+C8gcN8sH6AURFaaOfEw2QGIZSIy3vkevUhGsKjkT0KPYD+hOhtiNR74r2NVnkb azpBx1GNP9MCSRTmR/oUDkIe9yN6xKLgB45SWNAJgpQENcqC8cEsmgfq9LOf/JAR5zIbGjhZy0Gr PlEej9ReRzh/oZVMQSUZyDhhVGwcHUYLyjO7nl3w2ZzrofYu5pzr1lbdbbIPF0seNywuyR1L6Hfa azHFGDs6OjpFekath6TVUPBmIUy77K2DxdH63Y73goQy0LspO3KCrhF7SATcyd39XKJrfGYTe0oL oHk4+n6iowRSynDWpmPP53SjR1utSDSfToBVhKUIN35TWu94N4xg0S44dtPYylKMbGCNYBFrBMf3 tlOcR+RUTfa6z9NUigJ0XAOdSvcVlDcqhipHBieKxgWN4gd1voPC8LYeI40u0CdkLjCyq143PDhO IF1TLR8dJVyWhe3pAtu0TbzWQM1CHcrELAMclu1+MgcrFQeZVXh9sF6oY0mXri+uii1jt5T8+s76 3zpaRyS1QYhQLer2MFpRiAZ65kSOmgBz24MUFvs8znpeuLfubIJ76dIj4PZALJmOuTlx/h1eiZjM prk9awPoWrF66uB5CrX1ftosx7nMlIj37zlF21RWxESWicQORH8804JjsUim+W5/uHt0/rw0zlm7 B0l6mIUpTmoTuH15OrV1rtr0a+vwKr1Imu/VOV+duRBicTaqE1dBET+2C1iTQGCbRwrNsRvf8zyd 7bwyT6eW62vT5c1no3MiRWpVsu+h+f37SV/nakqqTAf7hm4+A4qt1leqG4k5CQ1JOHT7g8pCESzS valkn5LpwaKIAddxmFlVT1uaA64k2W5uLkA0y+apL3bhJJV9AsI0r5tkld8zfM9xQleLpfziL/2i /MZv/5L8y9//gfzoT34gV4+gEZlnF4LQvJYQQF+9/6G889HXZVqofRnz2kUl76tnT1nQtbFglNzZ JBpQdlqcYc5MLeWO81yMwwweW9LKRipGy8QBHTrNK2OjgG4T9Ltg0HGpnv6c9hOJ472lqlQzTdN2 eH20ViDa01KLCyBfgIX67tvvsuXEsLQ8dl5cm02SJ1CRXo5ELxTurhFG2/cuGiwbYutEVTjXH+hj 6Y++WeDlub6SNu3WaI9U0SodGjExUrO9h0wbJ852p0bo/AeGRNNGVRldpEaA/u+KkC3KZ3XDqqmP SgJuJ5I2VS6kXUTZFr277pPyYSoZnAiXoW+HjXJ6cK/wQ3FRc/IUKVRnbzzWFE8yxKJHmWJSvTKM gqaDZqbKGR0OWuDAlk/Y3Abn62gLNlamuaEKikAcraE5AjvMIZSWa8NhTW+CO4GqbxTjAN3gBoLI upPTaN0q0qbQcCLFUv15Veyhb4YehXks7lPV7KMe4CDkMg2Dtlqi3hyKDfI1v/zip3RIh012SJZ5 nIJunqieRGsZRUMHnltvkR/nCjgbw8LazBkvh8HDUtM5oujNPPYU3XSl8RDyJr2zOZP/vrld0bkc BtAYolwtI/uLBqs2Xi0veM50TPL8QaU4NyzModggI0HxijQODNKYjh2PhPQjHPq9cq0oKjvuKeQ7 5nu92+o4gli9PyB1lp0kaAVPWuSAyHy56pnCRncDpJDRTULn4Sj7rcqeYH31Cw1MdtuFpv2c0oF7 1imH69HVFT+nNsekkmbdBODALQ0pO9EhY/WaIjIsuEFV9cKJ7hPvyyqf0zxNpQUWXBnYuWSBIPi8 mtQyO4EgCgUws6LqTHXk0Tmw84TOPU/5z8lTyJ1VgS/LGifCBU02rBeknEz2h4UCo67NOKv9Ia9n MVihVyXqC9fjkdW1/WpZOixQBd/WtTez703Am8Vk42T9cftiT6lzFucS3DlJnJ/Nr0Pf07Mbk8QT G8I+s4M3da/pS78foXHEHjhE0vKxhHy4IVS7aMJQ5TNzy4nWD5dN2wNutf+nzlwsKNtQbLYXIoWu OkkUeRYLDOWU/3Z+vu2jci3Tg/f6/1rn7dyRO33O/344RuW9JWfkr1dJHbMS0nLjkge4SYpQerm+ mM6uJ5683o7BCZBiVB88NYry5/W/1qGCnJXOPTOlthgliVktqXsYwKGyfqH+YOlgF6NXClSej+sc PABFi9kJw5qFE5ejo/3hVkW/AfzMc5GS6biGJgWa2AY0aTYQvbjTO3Lx6B1mD9h7+Q3X3NyBN//b NFNpO3Yr+d73vieffPUt+e/+238iz376Q3nv7aV2qgFYNen3f/yNb8rFk7fznhPovI3brdy/fCkv vvicWZ4eoEuYyx5oMCna+Z32sXPURoX+sLnCVC14cxgt5k1ljbTVSnuDDYNxTJCCZZ5auy9Ej7pA 8BbzrqM6VVpNqrwJkiCT6nAh351Nj7z37vvywbe+rroyaWeTU1E8qvuj+AHGR5TnUCqcmsbn54vM o4AWbePzxkdrb1Bood/zbsqsaPSqnkC+YHBOIZ2lqUD6NGSNTtz5Oan3Pps+jhtHI9GeCReNpv+k CEx1Mp3XEp1Q2okRcfF3l415PEmVkBIUhIjBDoUEdMKMhBlUmZzXOHV0VC7QqumobVfYEJzoqArW usSBGmZNqVOaIWplIhuOzyry7LwZpjOCpeRh4EFaz5/Z20asOlK98ieJ+NZOF2UhddosejKEF4tt Ey7kdnufz2fH4pjLTc92SedGtaP+USrrbaaAb19S83NS7aAjkISl9tNDOzpsdjROFhSQ0zVUAUhF mDoiVEBhtmOet3lfWAclgUunmzVFYsWduF4W64FyJEgFD2xbtyQfB2KORDqczI2NHmgpJGS48apD Tx5VRIpMaAggetuFhUzdXu7yWnyxvLCNFwhU0g4YmJuWjkY/T64ZpD16k7zBa0t18keTgdBajpXK kCD9mK/9CkEHkK48Bpt3lGcXs2M2Qk5kRlXoKEuU6UN/Mv+dR4fSQPfbqBEzkN3lvSzyOldOlzZi h2NC3hnmBYi9+Zi4TqKWg25Ky+wcrnKQgI4Bx4MK6zpdAA415tDmYs3tY54U6XOUCcdUh6mn9hIc 5yerJ0TsjqmuL/K/5n35LGzlYXtgup9tw6xKlkh61Ko5LbxQWRLMeSDDyeaqE77pGM3Oqapi5OyQ kH+jGph8w8nkmrq+cH00QFUnPCE1ulTHsm2FtbYOCkAmj5Y+ZVYCjepTOrGRODcNzHoTg3ZEXnlz K5OfQAAnpA+YXp1VsqMnrF8DVOa1P++WvX5xrOPdztaMBn5eUHFiUs+QK7fRKl6tybBT281PkceE fWU2J8mRoMpXTpzXjgq1D+8gxFafrWPWBePOnaJ21VmqbR3VVsfmNTm5tkLvkYcOnM5Tfrx83t// prTsOcLHTEOU0lvWnR7NYrXv1QxUm06tKKDu9+dJ22DpTkd1JcST4/oVEoGNrY6fmOMrpc96Cmrz +5NrVEcMEl7RUEQxnp9mjqJ1PZo1Wo/qtHUekEfjcSfVhSVoMllALlqIMqx7zo3l5VJ7bU9QSDiS 20rU7nCk8zZb9hni8vRB7o+yzz7Oo4snDC7v5/sHwMvJGHaNQ2+uap1vUW5f7+Wtt96V3/nt35Iv Xt/JH/5ff5AdyBtZpA8kLveSdprGxhr85Dvfkcsnb8mdbGV7s5Vpjw4Nz9kmkWsOWYFR9VeDF5uC g50sXUPBU6IMatyhHXZ1+Ug2mwWrxaAZs+rVeVv0XnY+kwuCSFZ5GrPqGUl1DMkrEW3aPFvJOA2R IXOMxo0MuxxWskFlXh7Zty6fUAh2Qs/C2VT+d0d6rqx8CpBHGGVt1Sd4/VTI11NvVmGE+WFIj27Y Juo3NAvEF0xXHa7JnDFHrJKkE+RrtnRn8kkflpyImJcHGMjJUjSmIE9jOh4tsg2y7jf5mjTaSGNv 1U8V0j/MSo6XQlolxdgWTSTkO5lYqKdIvLINsgx4ylGzltBcpAgK8fq0nL+mZVSfzjdHr4I7EtKN lJgBebwfouxu70gSheOI9m1f/ea3qCavLd2ifPH0KVuyLLjxZcM4qtPAzhp5gQGpunqs6VosMqKO SdupHIkMH2zctEpSXcFErxRN4S82Aysy4WTG6VqOq61crh8pX61T+ROkxNAsHM62bpqBqMdFryKh 25SjsfweIFPAnFPeqBfg7s0dN0UZxhzdZYdh+SifF7hnPREa9BM95L83GOe4YwozTYF6Pj4nx7Cz DbujqhD1p6yIgULaLGxRzSPlLS1U3gcSEev8b8D9PE/oeC0ZRCnXD4jSgimsoVPOBMR8dQKPxBCm ORupY5D9GdsZoAurthp0lhwyymHBiV5yo8PrQz4HK4sWzfnGotjfMQ0Lp3QlqxzFusGP1BUToqo0 pHlsjnM2UIf8g7EZZtneaTUsVOKpIQm7girakdFGdsYRYgA5Qsp8yXs55QDjxfaGTqLPX2iQwQGi 3EU+91fPbni/8YBuWVwsLe2n92G91nZlV5sNN5bb233l5txqkIK6IXYryLbpzrTXWJHNQCDbrakr NBAGrmzGHdm9RmuwgqLlnYnoJk2hBXNG+mEj22zXOpN3wXtQiKAOp9pFrttOansrIMi29cLQK7Kn rcDYnijPJQz6Jq/JxI5KLqUxk+uoFBjIRrFpUkHl2Mt6GgunWeUmErXj8J7N5oIiwq4Lh80PDdCT oSKzZUI2lrol1zb/gJ+pLdCswKrrqU12PG7FRb/b4NqDcoxV1yva3YeZ10380gItoI99qEUTVq9K FCiWdoq6zXNXAjrSKW+CIrndzEo/zU4YJxoIDaoUO1VJwAaRzKlRwblIORyxbVqVGE6dtBat60wH lAisfcopPKmx2fQf6QDVIjjajNkko8zZgLlDUEJ5306Mo6gSIIqstlJfMwnylE1KasdxMbOnzz27 FCsfnPsClSVE9Uqlduzxa0rmyDLlDusyiNRuELNWxfKeDLVAwp28JNa/VFiMpOK5vv8meqYOAOlH FNEKpoLhou1+LiiaYtehIEbTUsmgLir/rUva8QWct7TIY7lSO7Qw6SrKEG13RNGhDYchQnuw69tr +crXr+RiuuI+quivOasWdGG9QV83e0cqej9jb1vlObHONi4Hf6u8Nu6v5S/9zX8gv/63vyd/8C8+ lT/5yZ/I+49U3LAb0WrwTu72r+Tjj35BPvzoP6RCwyLP9fEu73fpID/7/CdMtT663BC8wrwmvzWf I+hGi9TVwoYT7zKE0ggZukFw2jxyUVizcRiCRTMGd7aPzi6U1S5JOT90xqL37uxl1a3KJqYRayIi ASFXvH/MG+Fxsondb7gI9tuDlvRDb8zEeEVK904l60YTKJSp3HD98kReU3FWGl6Bj4GnXnh9dOBq t4nWWeJ32ntLhZXtkUgHgsS9CeHEucJDq7cqB69tCu38FLcJO6rga4Qh4gTQ+vmxVMj5fYzFELKk P1Wnzp04d0A1gh7KQj6PAuu4RNuUXYYkFeI0JUyGRPFTzIvsblAs8ZD/fZ8N/Pe/9ze4edzmKASo CRAJtlczTs9sjhkie1lrsQQ2kJkwus4ujoEmAAAgAElEQVQVojGuvH02wyD8MUd1wEH8RB8/dEEA P+1ws2PPvwUcSWyKQ2LKCNwJjAu0w8ZRCR5YihQKzs8dB8DWHRsYJ1bmJqa9ytjA2AaVefGIlXwT qTB/MXrdXLgkmsr1lL5zf4Qb/xT24miBlr9bej0qWgntO6Auwdo+MTWbzxOOHZE2yIUsVgXNdccb 38cNVQZLrSgdoGwSU7R50XOWqeaXOW1dw8EcekN01Q4sjP862obbh+r8p9gEBFELDBbTmmlYKFj2 4Ql5IEDtidAiBYk5PR9ZIQuO4302bnI3ySI75gOFVqMWnuBaMWdRVDCo1AiQqgUFaldEkXGPgU5S k+x4r87RAsiQdkHQjhy6RoCo3d3cFKTYux9oWj/PwWz87++Avt3ytUeXVxaI7fN83nH3dYeHgr4p mbOl1437S67O7JWQYinZsSKcgwYCGtwGbjJwDkhPCX3hJeFagTqqje6NtzqUezBN84l96s1e95ah 8GDOHVXIO2DMnSPYdmoodkpSKTghIjf6eSt14fLyQhGRuVa9F821OJXe2kdrhF64xWazHMVrq1I7 C2RLCrxRE6gcOa+OfJjWdAQqGeLO9zQ9U4utdMdRdJz9eRdEr/a0P1nTyT2GN7V5ODmHh8+lVO3q m1KnbzrGm9K0f9H3tOfpOZvGDZOij4X9NtV9yOfF5EVgvnf5GDZASUUEA5GwlNxZrYhdldywc4jR +HRNpqu57zyeVCf2TWOjvnmoaVE7byngVyr2Fo85WdKaRk1tIZoTDIZMrlYo0NqwYBN0BWSfRvt4 NP3EaVqIyqIYuioax7KbjKH2swUj1LfNexJQvDEHq8he/Pr3/5q8+/iR/MEf/xsZX34m3eMnObja sSe2sP/tQj746OuyeXwl96I0FXSnuL++lvvbG7t7yt/VtWZ3k+3T4kMnrvXKtaIrWIpVS49Lef5k rZp8gFMnXhlT0pL4PWu0TlKiyTp3c0d+A1Jnh0nF7FJBu5LschT7xcuX8mTo2ItwvQjsBgGS8PXN bfaSb7iJ4P2eH56NR0NI3SrvtBLNnDGV6rJzPxYpjnE+nUSto8bn5zppfXy8sTYjl7gvlTY6cHrt o/FIlsY3bH8KP42boxr6any7EydR749+l3av0Gvy7/fjeSTPCM1TgyB+N3wbd/z8Xvu/3bC+Ma3B 4CgWCJxGjU59z4hECd0TvxdILZyyBSo6gTDh2WPkfceGKnbOnDtB0VA67uNBRkaVmp7nAjCR0Wg9 JHWT8HuQiuFgOoAdGlJJgWBezZM6rkixrvL3bC603+cShHUQ2cHHjGLtSwKduDjkCCqv5gMaisOJ A8Ix6dwl38ciwt4cHvqyzdiJcXbY77PTzhkhTmeJHDd0HADlVaW53DPOSd+cgvLUymbTa7eBQF6X ojJE0TrVHlsMa9twl6XYJaGqkBI/qnulInIuZaLyK6qHpuT9KVTuTe+V3ZZ69cIYIvW9VzQvTM7D ehkiJUsEseNXjfGejugAxgBkOqYV50rKDrUgxXvRM2WLCBvRc54wFCMeUHaf1+kdKtYR8ccDiIjk 5A3dpEEDQjTrEAB7ggKBZT8TIRg67X+aJ6WOReftoiovCw7Jxtp0uaQJHA4GEZg72c7c3akDhGwD ukaMo7b80nkbeRtR8OHrS1G5BdEMOkGDtkNTe2JzttNCouXCtC7RV9F0t2g/rGqVxV7mPLFJ+SwF cQOfJxbumXVzCNWR4kzrNA0Mc+KVrO7EKB+WRqPYElx7tZtmo/oq3TJNtQWhzwMtqlgx7eo86sLf NbHhy6u12uhGSsSlWUihsMxOqba1AEltqtmoMJgjV9eROjdf7si0+5A6JUNx2Eq1d2iKHNrgq/w7 2jnU4MtytbTVqXGPqg39ix219vn2c2/6+yEHq15PPWaT+Tp7b3tc9XFOz4P/7sJJUaAf3wXMQ6gI nO83fh4uT/Wm72z3zOL80Z41361m9IE/nM7OVc7Hw365uK5SJJtsmr3fHR79nEGZ9ErVbiOA2sBO QOAekjfI9ExKBbDGi3asZFky8xcdPTYNRHIyO+VcIlu4zK+9fHYjH37wsfz9v/e35NPPXss/++e/ L5scnO7iV+RRONJZBMq2Wl/JN3/uO1Q0QMsz2KKUg8QXz34q19evVHw9tAU/6m9JUCRzOJ8U54gT 8sfSRxujpETxgj4YGmGD462LTnTaglZDap+5XltxgNMIRADKwqgqyydM0jKV/KM8/eKp/OjlF/KN 735HvvW1r8lmfUEC5Gc/+bH86NOfyHavTG53dmhQY7uAagluNXJCHhUdDuOtqbbcQ95Uawi7k6js 9DU+Z6TR3iIIlxZxZ27fcCZa+ZAyWQ1g0ihxECVt1/PxyJcOg4ZEqpmVjOBt+lTaiUGvUaFwZN2W 7GggUSOywSJRJduKoREj0xNa+av/0/lgS4mbuPLsNDXRi+kgE0qPnUW5xmVgZSnmSz6Pi82S/DSc 0hGN7MVkSExvimNhnEA6xFYR6WNLXhAKKsaZPx5hKyfCNIwsqqRsBpo2B00403nNCxTN3Oftlmnp i+zIoT8n1fsPia3gwJ2aMBdzxDTmzxzBa0MqHIcOqrcHkn7vbdkw5424q85VX6NC40Sp2rLKzyTj zdRHNSaU9fG+bSXSsjWYFE2CoCt5q9AvM9J89ACAmlepzB1smkrar45cWOm/F66NhCIhKKQvlXvn 3DrqaCE9hVZXNush+MpOGfhOrJn5NPWiKTNH0rWbCzdEa6rODh+oqhTdQIGG9gttWJ+CCuiiLUg6 oChgUumbCUR4FGdc5peOsiFSCmLylmRfagjGI4so0O3iQN1JbVN2t58oQQAJAaCySBduWLE5Un8S c3Y51G4QuJabm5vS0cCdFQ2UJjpOm82VXtOgYrXgHCr/sS9pSdAjcDwVFl4U/iqzBpRTWbLyUde/ iRKPs4nzVv4dHE3w7DR1lJjlYNqEdsfus9SG697U27lcvum4gj6ryMdjtTlJ+XV974F7b101at9S P55v5o7g+9pjv91pKsVPSnGYS/YGzhweyqmeS8qqPZ6jcPwuWzsP0ahKfal8JHnwk+Kp7S7jYXZb Bd070m/KnLX14g5t7cPanaBuSq2Lhg51xXfT7ipm18900s6duPbx5ejcw5/yfuODuaQHbZ39TSbJ ibap702WppT6OQ0Sg4EtswaH6bTQJM2VO+pBzvl5nmZr/POivLSmaMJTyn/Ro73O6HvPg3ng36SP tuiQ5+QBb/I7Zc6fOXSVky5lTPQJvYdoKgDdUua6egUmmIHI9hJI+K6rxYLz+f3DPjDr2bGNn2U6 mJWBb3M3ya/83d+QX/3efyD//f/+L+XP/uxP5fHVhWwRtDH1fGT69L2vf0fe/9q3GLDO2Z7fb2+z rbuXp5/9hHQFFBZ6qtszOAzIDdUcztGXdoCI8KyW5kSk4qR0hibTceiV45OsaCGm02gQlYYkXwbt 9YYp13OCTBqZw+gZhMtoL8+2+92dfP70lVy8+5Z8++sfsZcmAvfj9k5ub15QA409MaNC7epZi1XP 6h3r6XAGlvh2NsUUyvJUrgm7hrpwiiPb1fE4NtGuDl6ya9YNbRiqw8MItFy7pavEdIz0HXTQWqc5 Ro02Nf3lzXrrJF7SJkarkFUHVTN0mnq1+iYlPpOjp/1mFa0x/St7aFGEciUc9Rs6e96WkfmJOjGT Vipr1a9W03EOEAmbHNqkA9fTudIeelzY2UECcrFaL5hGfQ3F6cNOVrh2IGVJe/Id9hM3gmWT8sWD Y44047Q94euVIMOMVbT7ObBqTx3LYgCSyqhw3uW5htYlMS+ai9UFDbdYuyaBowREJjsz06A6euS+ cE5pab5bA3Wooraew3B1oayNYlCaNeTpav/bDYjuM505SVIiS+v8K6rGblRZi1b1P9HWX2LrLbSG YQsZotAaCXKz7q2S2Xp7spdrNyj3btDUrKJrqutF9AzO3nJdVM17c4Txd9ngaSwD15qmCxMd5yPP M1Tj1usGOVAKYIlSDhrFYRFYCRpYWR4E0xvoaL/ccECn4+CrlYLSs6jsTKJTeJB5GLn2SVIGR26z YEoCTuZIp27PLg9IzxJdeb3l5xFgwFhjPqxWKvTpmxf+RrN4GEs4ajc3O9otNH/HeIKjVnTQIB+z GkxKJDtB98cyX8HjRBStTd97bdcFVA29W71HqWmoFX4nxjqopMdsLYy8EAmvaQcHfK6z9VHXCNG0 YaGb12h9RyfdWHGt4C+j/ymnjjketOljR36wI/lezMA2WyIch7YbigeffV/7QDtiVzMBtajMbanb TbehbX9UBt753Lx6uEXNlKPtgtfWZsmknkKxT1Ls7PnDUXFbao39U31NaRy44G0Ou5pOLdmp7nQt W712OU+uxvOg/NyJM7vwBv/t7DMPHbgv+2kpMefvdbBFmt88T1GDpUBLePDdund/mUOcCofvTQ9H RPXh6FU9t3a8WPjQ2Oj2Gh5+rzx47RyZTO012L6povb+ugZKSU7nSkkPi1EYYlPRa/z12STUYAN1 H2jSxF09b6wlRcZ66m9Ckv+wn2W5fiK/+jf/hoAm//t//EO5f/1Tubxc5UCtk7sb9C3eEuD65Nu/ KJdvvSPXo2rlTtmG3Lx6TmkRD44qCmfUqSbgH85TdyWNakZbCdcmAumLzRqF18oYYURPJgMMskUK 3Cd71UNCpIwUo36fRjAQIAFhHdVonChBGOE+efxIrg/wRneMipFuC1EbH3t0D+mOoVOdGV4IELVe jRWFBztzehzVMi061feNRi4OxXlpgFgpUwDoV6/ETZ/IjIQ6nXzQqBsW69J7sp1aFAxNek2+aNoo 0/859FW0d46npEIuVItGoznNvA9ciMZrQCeFZGRpCXadiuZBlzU0nDd2oEhdA4EnokznjnwL3fIc xJ08OYPOVZJB05zKiYTTou2ZevK2sHzubq5lv1WiPTcusVQiq9yEFY5qlGrUj/k0TzW14xMYGySR AytsSHYsOnBJCczKJVMZEWwA60HnKY59YPuWaLylJVOeI9JC2LTo/2iV1AIix2g4peQHNYDGR9Ro LYlXG8YCxdWKNkbv3cMtps4BS9/A4U1aAKQ6jEHpNr2Szmv0Z0Uv3KCidXGYq7ViFB6NEhIo0jx3 2ck5JNvITOSUDtairnGQzxedoXeDcuz6RSmuCMO6CLiyunZQNXs6wJR9UIkdF1SlAjwbAHRsuRNH FHHYPTVyNR1LOHH5xC4WG85VIGSKEFmVdIDG3oWk9T3ROomr/P+LfDxrjo1WXrN2nwARGRQJ/BtE dMi6oDsF5sO4vzPHYeRxus6qzSw1T/Qtn8/NzS2v0asy3YHD/ca80YrRnvZmD+mkWVMuF+tL06XT 6lo6WF0jPL5YKhIVtNIzBFsDoXY40HolTc15wIJzOJBjNxdKSMs5i56uXbOnB+0UpursRPsjbPSx IheGgnnKsp+rREhbrX/Oa+uG2scV+VzMBWhFesCl+8VQvkedWA38wNnENe4Pc0HuELxj3NRhjs2x 6wbNTiiRBEjr0+0bcMGIT2xk++8WJbJnbV32GlCZA3fKjzNpKqake7GmUOJivu3aZc6lgEHJ0Ll0 8h5H1NvnkqEmX+bMPUDgms/5fuE/+pr/vDltW/losfmOipCVz82Vs+sp7VgoSJ0VMDzcI6rTeCrO nJqT9DVwcn1lHE7FjEvy6dxJSxVp+/d5uANXaUPNtZbWmdXL62HLRJ1YViWLggwIZuHYH7c2n4N3 fhIDNBTU0KyCout4DzI7Mdue67tb+drH35bf/p3flB998YX83u//37JI2Z/p35IenXN6pZGAr/31 T34B/cGyvYvy6vUNVUGe/ewzGXf7Ulk+sw2hqM6kKPLpe/FwPmk4EM0kL6+ZQjnTeUEvWsgJq0hC 6LztkWmrdd7aRmtGljTyKkCb1j01spbWoBZSJOCfwdF6lB2jq9uF3F0/l5vtQdbLS25OEPZb5ou+ P261NybSEZ1Bsaxy6dlLLVpFEO9VZ6lgbLrkByb2vCMUPc/GI2ucuHAGUeMafeIb4oc5PketRDuQ u6IfdF6FVm+pM7lo2+yEcDLONCBt+650JgrJGahqvXTcOo0ycCF0E1iFZ6TO3uQuQrRoRxft0ESW 5yRiRtnTsVy31KtUNBD3xqrupCw4O2erAhLTABwtxQIDgH5vj959X9YXj6j4/uz5U8oO9OyJqyiW ApBdIVRTQgbFGLu9aUh13BC81Y+nopyr42iNokLaqQKOPlDmRdebaPRsnUQWnGczxHuPykVAD1m0 9JpymDRnR2VEhwYjzMN9Y1eGiESgonKtESvE56Z904MIHseh/9eU9ttakK4iCp0J/FIoIdkWlVJB EKoR60oQIbaIOed61fqLFlx4iyAx3TD0SVUEQ8mxgPnjdOA5YGrNKTs8R035cs2aTh2cjt4QuoUV TMB5A4K3gDOCFCy7rlhhxaApQ6J/nRZRcN0htdCpJAocUrbKQ0W3tRt7jTZRnRdBVfSGCmpADpda XdjZ/U7WPonZbTrLSFujqnfPDhqcpeChMa8+kW/S5znez3tNZSbdtNQeBNluVQfqFs2oYSDzcYEg QwD4888/57xF3+cPP/xQ+8Dm8727v6FDBkckkh9n+mOiRTtqUzSliIpWv/9w8rgG8zs3F6tSaDBZ Sy/cU68U5fPzXG1GDKVIQJ3NVFJeGOsVne6+BNzO0/VCBdeTLNW3FlCD16cZBS18wMORPhwHwqnu oBEjnpX3J/Yd64sN06kucULnzdJxQPaUN3xsEDipGqRE8DTwpBFssgb1EenUd62UgwVrug5O0e/2 oeuxK4GVotO9zdFOqRCUgero3LXFDTHUggZK5RVnUoOo9jv8nN7khLVndo7SnTtgcvbe879bp8f/ ru+L5fvOjxktFeh2gqMWKlVIAywpP3Os6W7fv/1az8+r8t1IrnnjdZyMjQno+7kPZv/S2fvdS22R xXZc9FY0smH6bGM39TerUpMG3Klk3cyWiHJkm84HfJ1qHKsN93DysdEVqW/GKigXjm6CiXorsNVz DR7Bkc3B4K98/6/L9//qN+W/+d9+X372//1refLoStZ57u0O9+TdQe3ga598U95+76vsWY+er/v7 aznc38nTz3/GYHi5WjIoUwBM92HWDxgPHtdZChvcS/ZHu/FzwLtTj1tYaRIbYb9owoFBHQzRzS51 9TMk5FoTXEgSsO9ncEMUKKMwHmYVD87G8C5fzIvXt/Le2x/yeIvNFXk6qBa8zIMcx50cRA0jy807 b79i6Faw8nLbFJjWtOo6nTjZSLUBm5PUuwpbyzQXjp+jF1plM7Mib28aYm3bqhHVeYBiKVI8GOek Gd/UfKlp33j7Dt2wa0oaJdLOf+uT95xTe6cAS3UevN8a/4YwaVT00zcVJ7DiwUIQqLpLNVzn956n GvS+TuaowCnkXDAOYmcNlzH+6xxNQHsOPKCvvf2OPH7yttx+/lxevHiWnbnrMvGWkHqAYY/auNyd NOpyHSzNFE6dOC+s8InrZHF2n7AKPorjsuGz8fuw8ZlWHIQfIZPTockyriEHEJDD2GUHIOWgAQKx iHHIGeJgaccELMo5nupUeUUb3jZFbfMiQYUzk0H6Fb73tixRivZf0J6/TBdj/nDyWRog2eeKs+Zz IpaUfGcwtxZ4DAx8ku80RBQc0QpcE5qa9iIYFWcIRDtMi4/wHfrLzjXKBoqe11rqm9QTxtc4ddRr E9AlNtwI2ad02JBLoj1gF5q+zU4Y0OquX6kmk2hai9hVymtjOdERGw25XopXUCqZPe0C08YYx4UV lSiBYtLUM/hOvXWKicpr6dAJYoxauX1Uh8TbJHHr6oKxL1J2fi7JPeRYWQHPMc+V43SvYpz5vff3 W/nii6dEke5v7+TZs6d04B49viQBmVX82dFDatCRq2BeOgJFNKTHGIKfhsdqs7RuCvf5/PeKkSKY mY+lwwIdqqBFOp0J8vI6Yiz6iJ5exX1Q7ajTPsPcjJbaKSOlKkNUJEbya4f9sRzX7bBXo7abr9q2 VLoteOGMSv70NRhLqdhJfC+O691f1MkbSvWrcvx0zvI5C+i1+LNmg4JViPK6SiypVAUgosVehepU ia1VEX+tN+RkKOeXGuTcf2vluVRnKPoqTNxU2Vxe+0bpHtEtT8b83/X4Mufty547d5xOUbp/P3Sq vv+hs4s5coBEVXOflTfXOIk+ruFNjpxlRE7e554Uxnt+4HD6WL8pFc0AqymEaDlwfMRqF318NL34 EKxTBKsit8nAFt+I6z2erKNPzzmuafah9EsuaXf/7iCF+48rANWBRV/oIHU4qipEDvJ+47d+S+b7 Uf7pv/gjSXevpXvSI5Kjnbx59QX9pm9++9s5oHskd9nGbXd3cjxAI+5abq5fcT2tL9YMkrQXeNWh S7YmcEaDVz1Cowml+1PSKiqIZ43xoAYWKEtw+LkzyZBI5XhoT3GYo7a0SV4tapVYpHngRgydQdmD et/oE7qbiZRNlASIFALVZstB1leP5bOXr4jE3WdnbZMNzuWFyNuo4OhU7fiAmsKJTYFI9mf0a8gJ HJ/e+GLJHDoDSw0X1JRjbxsXHTu7SY4d8r19KilbEKa70rJLZQogegLDL7gGm1CrZFo9MLRDPj7S ecWI9cWY9ogEkUaJWo6v0gdSJphO8lu2dcJiGZXYx02SyAxImaKpKAaIRz1rOKwsP6achKrNO7rI sThOZeMIDRekOkrqVCoaoHptA7oo5M/txoNcrNYyoAjlsCfSeDiM2THTVkf3eRI+ee89Ihfj3STP X17L85/+TIYc0ffoH4l+i/l+gr9EKJ+6bYPsd9js89UMF/kYkyxAeJ/yPYZwbP6top+GarHIQgtm htm6MMD4ogUYOYcaWS3RSxTGntApqqDzVa+u8g55IeNiI/u8+W97be49dzaPLSCBs499A1IpaVAj QX4hghRsrBjBRZAjOyvQ/cvXBF4XUK4L3gPMcU+Bw2Ep6a6kkTEkTxgJGr+xL6kiR9PgSCkHde7U weCcRX4fixY8KONfqSbTVKP/pDxTvZfOpxQWFGjUrG1sAthsxbirkzfbXIndVAyXb6IkQ2xDIYaP 3Yo9kNHhgggcOrdkZ4bdFnAmK+2cgW4Bq+WlGUopiM0QFU3rzXCmNKojLcoXXEEMetZOf2xGHZTl 4s5uQfxwnyAxgmAGBTLrPBd6pDbXWqQwQk8Nkjssk6WjxznSaaqEVgGO61IFl+EPLxdX2WxZ0/js kDx/9lI5wXn+3OU5evv0lkh210FH6nW+brS1WtF+QoIE9/bdx1+RqyttV7cwxwjcObaYw/pKd/l0 tOp/2es4oSApmZOxZc/VSS7BVcz3/vomG/c8r/qlVhcnqJwAtb7d8zZqQYs6QnuM6f1I2QSkNqHz RpFeOHHg3QHBWyn3DRsSO5AEDUxQkMTuIUrW5Zwn5zZptx28ZwAHdqxcuOVS+X7OresM+eJGiGAj HxsIBzdXbtKsX2dXB3yPIoDaBYeFHpbN0SBEVCC5rwFmLIiYdl7wXTyWYC9wwkbYpk71wqBbt0CX DOtk41Nf+dEGaHSqGBCywQ1LdxomBj6a2my4c2LCs8YxVgutmy3pDZoG4sqpAJ6uc0WG9bS91VU0 xGUufUxdtSCVH3XI/LlYUFVH2lonSGkbkdsvqShxLF0anFeMcWE/0aTFfqE3xAz2VTQJQyc8iQEa ytzlb/T9tHMJc3Vui9oCnJ+5kQzxINwd1Cab4QiyWKrSEmYS3CYq2VuPk05JULMFftrhTe8RZXr6 oZEM89Ru41Am6xOe1/kBVIrsW2yW2sVJ23H1ZU+2KLs4n5zbqaf25WJe573ghYTLR7J9Psp3P/or 8nf/4V+RP3z+Qv70n/2rPM9usj15P78fGqhP81hFuczr8Tuf/IZ0K84quf5ZtiN53b169lzur3ds qYlXGATB39nvdEyawAUWnEgcKTTK4tEBlYpEVQ0yuw7j+WgUpWKh/KpOpSNip84ABlu5V5p+JJcF 6bBsdTBwIdYb590NdLMIPPl0hGTFUp5//jPZf/0jinwOeXAfv/u+PL25xf6lBiZYygHGHVViQRFA Pd9U2rGIG3rRaIp/R6u89E0O52TyHdb9WBeLpWCcwKnwcygoSQ0WjGMmujn7JCTUSoPUc4L1XWff Gejtq/Cw8dqSp9e0IpIqPGh6PSvKQ3KxGUZFx/JkC8YzW2q2nLYr2GacKhG5RKwwrp2W12Nhe8Sq RmBSDp8ZnIFdAXTCu4YW0TGLbiDxsga/JY/965d3eYNby7d+7jvy9jvvyWc//UJ++umn7Pvmxggq 2VOsUSEJ4VG1BxVx05ZtmDvjrOmlIizsizd6xRhNq5S0tHiKoL1XnJx0xEBuTKhMHVDEEEorrs7R e1Mbx5bTBXO0kA6SOlfLj9T0eFvBPLtmUtB1JC49I3oeoZqkivba3ClJgaDQv66/SbTIIVQUMsai 5dZ1oUSrfiz/3RYkfVnkL825F4mLWD8fbCJEEywlnI+/kSYOasQPRLY0LcUiiEEJ5By/pQZuywXk T9Z06ERc4Dg/v1mbwPFCf3r7bR0yUu/np8cMXXdyPc5NCSbrQg7ogLRmdliwZsYDNy4QhsGTQyoZ FWEjdJry2jvGO0Vocd8QiMIpO2xLWjcsrIE9Cl3yuWzYJ1qLcDAnF8M74hWYY0TXmY6ZgsNBg5q7 3Reyef2SjsnCUM3B7AXTmNBFzD9XF5fUOAyuUyeKRh+3M1vTxZ065HD+YEchVAyStFjhAftcQ5Ik 2144xl5AlaIVfuGIk9I84NwfTRbFNeiI5FuVrXe+kU57AzuPTotCVpbOVZQCHVK8ulc6q0qdatWs c3q8s4JLOzn/qjd+cUXEahGZo4a+/ygi13TbkRpcnD66Yl8K36+rDpp01Xa3GYh2jTtXzvlhWoxu 3TWSOoj6vrmkKk9SWfxy6w2auvZUiKQAACAASURBVBO7UZ0wddrqejx11uTM7rSP1HznObrnPy5r ow5VlbXSzTE11zxXFOzEVnRSpaWk2qbk1a4PkcBzW5MaWZrynNFC3Pq06OJ5Orhw7qhVWr+nZLaR InW7h+uYnNuWHmjSndtHXj86D3X1uoa+L8ixcj7beaKp03LZ5EkfuGcfu2New+/KYbeVlB2uv/zr 35Pvfu1j+a//538uf/aDfy3vPH6b62qE5iz2/PkoH3zj5+WtD95ne8rdq5eyvbuXbfZtXjx7qnJH l8vCTZ1MJ7U7s3+wx5W12dyEYpRAnM3RFRwTtqCPPhhd2cAI99tGGodGD8acHBgOmH3VTRuL86a0 qg5S7tquKsUiMUGYHs7FHOT6+VN5lb3Z7iv5YnM0efHkPVlcPJPr3T0drQurEiGJnaRp0+gCvwrH PoPYtfLQULoQSxa/sxJAypMkTQuLb9S2uYcyieukmEarpLNIztWmfcBVOsF03jAeczyZtP7oXDzX +F2lelSC7/iMYpRePPN6x26icv9k/L8yMVkkod+zYFWGoatikhhWkMUCDevbqlh4alwMmw+WEpmM 1MwURlC8cwV5hbw53qMqL/90q0v58OOvylvvfSB3eSL/9Oln2ZH7sRxh6LFJAKVF+oEIoTBNOfSE p5RXkyc2qnkREQk5A6PswZ1BOyeJ7m9YsUhFTTuD05mox9xKjeOOSQ+OFBAgRJxorYTm9kGjQsiu sA5DdLxDZ/clzpZWMa6hnPbV9fRB5wFisyFo4KDcCxNzsU0olHP2Y7g50c82Wkr6bPNdNQWh66cW ULTGqaVHPND/a173ajMaRzrBXbkeKeeUvAhLkeoSIOg+oOCHoQB8DwbvwJZtk83t/b0KSh96ReS6 zjW6tOKVTttCW45hfQPJ06pYTZEC0dMenEumbMnFa8YQ7bnUmluEjmAQaM2CriI15si9AneNaRPI mKDCda+dR/avFOWFA4YuEsctHT9yDuEsDVbtCXTiqBsakOP1yopD+qU5lpdWfDTQfhzNlt3ubzk+ 93v0nr3n53sbfyLzixVlRS4vEQzt1KGEtE0ftNgDyBF5MdqoG48lpFog/Hudg6MLRekhgYJbqX1k hRW0SPnCURXanYPs8gYzxbkgZ7j+zVpTu1gMnqLtjB+H3yvjt7lT2wqhOxcS4+8yIskC8sGlbha6 6YB7xw4paS7cQM1G1NSdzoszJz34uqvrpMxvImnVoXNnyReVBuNe+e9Gzx05tQmK5FYtT6I3jV0u xPzgG2gw+M4Bj9bp0HS9biXVkdJ1bZSjk/efOj0PnJ2z9zwIJFOrm+fr1FpRpeqkFVRMKt0mldeq 8yrleyr6VvAuQ6v1oHORO+F3hiBtZWu7F1Vnwxy0pq9rtTONc9UEtmV/tEKEip7VHeq8MLPMheb7 /bXqBpwNWjMmCLagTXt3f2/B28P3tg/oVWbHJ38QlJ2F7J6+lLC5kv/0v/j7srub5fd+749ke/9M PnzrY9nNoAbtckC2I53kk+/+NVm+9Zj0q3twZ48H2d9ey8sXzwkcoYPKaN2wWCx4cl26J+H/Q4GA jVPCDdbU/incmCNlvh2OXPKIvTaa77QlgAmJBsLmQSyix+cWOpCoToXhqU2s7fVRG53zuwTK7kqc xXEe5xv09O6ZfPqjH8pFjlQXl72sLh/JVz7+WjaO2zzQr9Q5jqm042Al55A4vwh8AbK3u0pj4JWU IqVKko6lnC4gG6kyuT1yOF9gXUPG9cqphvdqufO5OIBiZGVPKRSuVbL0LcU/Qci39JWR/1kpZCR5 wuFw0EIt/5dYDR55LarIJ330YguLaJNC4hO05gx6dl2dZkqXawRnDsacyv75/iF9Cid5nA7M/+P7 Xl2jvdFKfv5bn8jPfec7VKf/0b/9t/Jnf/ZnctjemxyH8ZwoyTLwPihEn+h4o9oAWm6YCweo9wNZ QMsmmU2aJtr07Ax56Yzsrs4402GxOtSdEZcPQ56/6IsHxA+/US2I1LRWAcjS7ktvTE7X+Uv2emcy Ll3oTnrQMprsDUWw1Hw1IrPWxRbHzdM/vtm0Q61oaSeNsTan/MRhbBxF5ftJ6UMr8hBVaP+um0l9 vpDVW6T6bBMJJWKvRpZ9VRujqxIv/p2c8Pm5Y3mdTi6N/ghsic/DgXOmWpxdV25pC7ZnpRb01vB8 FRGGc7cuzl1n92IeVoW0rgUZitjBOeT5wC71tfOE0x3ExiROX+NcQ7p1AjqXDemYDe2UHQ1Un2+3 N1xnx2xot/m1sJuyczXRwDIlvNypxpyLL+f5DbmcS7T0yt/xfv8Vzl83xKwpi9bQPq/d3e1ryird 3I/y8k77REM2hmY137InVwtZwQbb3Hn85Co7VgMRRWjIoSUQWg9i44HT5z2PgV6j08VypSnOESrw 3u0h8SZY3+g6zzSwHbgmD6bJF63VFx6uEYcHEDm97oVyg2KUii65sHj+vu2sxQNBA2efO505q+0c 938rWqfZCQcIxAOqLjQoUMlznaypgjhJqwvXFOuJOn/aa9UzQH3hC5+uA7MHouhb+x3pjXsCE+4P UL3qVJ0jU03qtXzGx7KuvdaJa9d4K+XBpG3zun93dXylzPt08l2GAr7BmaTbyfiyOmP+KH2obQ/1 170Ay+2Yp0x9YwzxtODjL3okOXVcqwN3Wtnc2T1lICBC7U8f6/NHez9UgkvHGTYI3FbQFGqvcgU3 6mG8SEykzI28Ly/z/ne4R9boKH/pL/2K/Pbf/r784NPP5F/8/h/K++9car9Wqo9mR25/kEdXl/LN n/+reT8K2Y/Zyfb2lgVYr58/yzbhhlWuXDOoAWhVPRpbzvMHN/UEWhQlAMNZA2EWeyLQE934wfGK xVNuUziuacQoJBoB2qBx7xdKknMe3UU4XQg9xEih1A/NIAhjJtNhyt+3fvxYtp/eyfMvPpf3PvhQ vrK8kuXVUt5++115792v5MjyVnbHO24UA7VdvDXMbMUT2rBdJSm0vyPkTqZZCwSCFRX4DWIE0xnq YIWAep26mM83tzYS4+QqRqC242I6zmxB0DuuyEKnDVZ1YYqRbJVz2PddgZXRc5QSu0mrL1XKQ+8U j7foiYDwOOwxmzgW+Kw2E++Vm2KyDbzO2WQIwEFcV9Ixp2iL3mDKob8pdPmsIAVRA7S4MMl1Exvk w69+nW1DvvKVj2S/O9J5+/TPfyT3r65ZhVPQnU75F0wc5smwCCumipCyHftIrs8ub6Tr8YJyNuxM warGaO1hRCNCKwVHX1EsIMURrdAG503huoEaWuTAAYnLP0ihUgsuKYeiY89RrWb2puftIim6VCUJ 6tGpOtGOaKkT9+boLjo6oEvw1Aiz+8BghTTqDCmx1iZLl6x9XKRz5KmkNppP5tR1Z7bKz2ZuFny7 qZT3KRGwpB006jbjz73Rx6UiEqV6m7ZPN9bOoDldE8Gc0FCDF4ya8WU9fcN0ItJ75HcORbMpWQ9Q OHE94RbtUgGDFizliipZ7SNqiNhC9e/o7IFr12uRgVfcqtNgOmfNxjasNnme5PNYX4hXrTF9ERWV Cvs7UgCOh3sZ8w/agmEu7oEa3x9kDZkhcDj7mbYFFfgX+dwuNhty01B8NVBS44KoG/mc1IXT9bRM X81BS3bm5pH8SyBlE/pRI22af+8Ot3L9OjuTo3JkrvN6/PzFtXWvSNnJu2TXimlESpPlWzLmTQLr c3d3S60qH2+MFxDEWpwVKHbsyBn4eBAsZiCFqjwM/TiVe+VVrEArDhAs3e74nKZTFwWpI6Jn83y9 VEFpthYDujcpHQPzpdWVq1WO6cQWaRGCBR8nW39DPXi4T9fXuI4Mabbm9jUFqyimO3DhbG9SsKN1 4lLZTP0959pq+rmp0D38OTn7+9zB+zIkzh26ZNqVxXGw5wvKFjWr1CJv6thVakZK9XVpHK7ynW84 B35XDOV1f0/nklP2+eBj0/LxGieXCFyS4uydHL/9zgfff3ZOfPpUV1Bfm0/9knh6/PNA1R+k8wBx A6psgQn2HdCDnK4iD1zO1mfC3M777KEjsDHmNfjXf/nX5Z2LIP/TD/5cfviDfyvffm8tx+1ovXhV F/XnPv4FeffDb1CXFBXwx2xn9ve38rOf/JiB2dXFSsEa6/hUg/JTe040XCFMi04UFNBWMjFaSbZx GmBgYLhYgYSBM8FG8WqkUY0lKjWtOo1H7TqTJ+hPBCadwMnNvFdtJ8hPsA1QVFQFlWrvPHoiz16/ lM9+/OeyWl/KW0BE8nG/8fFX88Y1yhef/UiV1KE/JMng/aBVv1OyQbALg/HqTKw09aXKcvbNlTfM 0jIhWfQRjPvjCRxDVxwRkbqpuZlR4rpuyCRoY+7N7gQEpqg6O/Zo6FGYNRqUpoUKHhgfOllTLKk7 7ddmaYqDL1AlgLP5uWmagY+wC2Mp+XeU7ugSAuBsHGo7nFY7qXikR422cD8hCUNu0rDKm8cTSi68 8/478vZb71L65eb1jXz+k8/li598KnfPX8nx/i7fQW2mrL1Sl+Qs4VqUcwO5l5UiXYjosXiAGOQF RHGPpIZpTlUAtAvV8GJFU9whGOifrDIZlbnDRXbelnKE3g8cOKaBVVpEG0ILDS2dQwP6ky3+qhnk EL+UzUUDgr6oIThy1qW6qThCHcwoFWFiT2eIpipbA143pXQSIEVr4O0G+BxhS/4+aaLb5vlzp+38 4VWr9W/jHwVrKePRc3DEojHMKYn3Iq08ptnWmqGZTFVKHcsyZrM5qhokxTQqomPzbkbVMLTukqnG u86Xy0CY1h2xlIXKn8CRo4Nnjh4rZPuuSKMgbauOXEVlSMNAFSdTuYpCJdq9NVPti+kJ00fsWDHt VZLHNNLws9++ptMDmkTIv+/RKmybA1Agdvk4q8VeeW8z+GpHRRKRGl7lqD//XmY7tM6O3RWqOznn O1vLOt+GuZd9Pu4uG/Y9OtvkBQvEMD9DvuRnz7MT2YEvd5vXh7YjgzJfl51KCG1/kJ3TmdXyEx3e mZvI0VKbiVXDPqeA4K3XI+0DAmEg5H03FEkQ3dQ2vMegxqC4DBqZK6agtPBiNg6Yd8AoFfsmZULn crcrKdoyzy2QpE3LY6hculSQQkegicYpOKLgQrIAW9TZV8TH16Gu41ScNwMYRHsH9Ya8K/peHSV3 1mY45qmt3jdeaOu3xVoV7AE9r8lRAKNpeBrx1EGb5dy5KAhY49CWvaBxeP213tfdmVOk52B7kx/X Hbi58rr+IodKnVgDMYqTpuNNe3PmwDqDtrU7vO5wymerj4o0ftnjNOiVcn983lBol2ulpoW5ttOb 07PnDnQnNa1PzURU67pCQuc85HOH3P89U46KBVGQG8tBnvQb+Xv/yd+W/e4g/+M//T+yX5PXTj6/ Hp2Bso+yv7unn/St7/41Wef989Xxuey2t0S9b1+9lOtXz8T7irO3dKx2X7NAuB+TXYOYjZiV+9H5 5LcNrfAjTD6jzx4m2hL1pgfkKQGktFREUcu3F529H212giqDs7eiReUSrVk4+0VGVjz2i5kGbNwf GVVG6+AQzSlDq6S7l9mR+9EP6ZhdXj2Wx4+u5JNvfkJl9ZcvX8izF8/lDgrj2dDpd1vqcPZNQJhO qMQ+YVUYfSj3thuugxYYiFZliDpkTq5vU1FTOhf6Nc/fIo7tvC+Lr2te90nInog2/UOoBqT0eDyo 4XDnjXwaqZsqJ5SnRAyCZepPKvfJK8Q8HbiMqgzPCjwjcfK6QisnEazibG08xYVsLi5KeT70qq4u L5nSATD47Olz+cmnP5anP/lM9te3MuSxfXd9le8jeDyzagZaJQyNaKcNh7F5QnwXumGQn9LNRAsn khU6KKSvabLUeeVSKJdPNwzRNPvFr3J0s8oX9kh7odpYYblNcNyRhmR3EYvmLKVcEp90ErzKtzpZ lVfiBQOGtgJJa2wUrrMzDknVgFN7XqJHkSLD8zDyPU2RvMnAhuZvCaeOWomYpUZq7THKhnh2bJ+P 4ezfXl3rz5kYXTm+NsvWAgpWjzryl4KRwqszXDYhGD/rSCHNuSTrKKKR5GgIgEeeijS7hEtNE/Wm +dVJFXNVhy/Yc3DevEtFMIkL7ynM7G3+90iZkpWiTzDKsHWQOTp2psE20LGDE8aeprZW0vSxNb6f 2fP1SF7dXlsN5v/dTbc5Ss/fgSBsu5flcGQ6dL1ZyQbtzxYbRRE5tgsteiJfUIPnQ/7+J/n9j7Eu ptGKDLRi/rjbZsdRuz3scsB0d38tu/1t3izuSC9BD8fd5881PTkfZLnq5RKFJNYiD2v/anXJ74Jz hapSbmCGhKHoxLt1eEYFY8/ejnbPuNkg7byrvVn5XqMXvHr1in/3npFp5mWMtVdqnY/RuHaDcZJs vRntgDPKqj3bdaGL16okQ+t4iRUlaEV10XgU5Uy266ra3onzJERVEGgfRDWjlO/w5xjcSoPYvWHd tu0oz7/3/NE6a+eOXfuZN9kHrnNzdlX2ZTYZosYBYWDixzrlxOm/fe2dIXQ0uPEkzfmmx5fZmBjc fLRp5mR/88SNVuSopjTXE8sYFltoHXPOr5+f6bqS/Uhf8p62qEZBCrTKO3DP7co1OKexooNlfsEv OC7k0B0oQP7Lv/B9+c3f+SX50dMb+cM/+GN55/FCwwS89Rhlf3sj73/wkXzy3e/JmG0cNOH2d7cS s9/y9POfMlADBSKY8wzgLKamp7Bx5bvOec15nXOhxHPnRI2FcyBcE4iQe/ZWHZNyp0aRAP3sEHpz NgbN0Zu6PCK3SCRjFI9CWECRn8fGjJ6p2ucziVehwWMF9+Ir6/fl5esX8urp0/z9ay5EQI7Ly418 +NHX5eqtt+Xy7XfkxavsyN3cqspydg7hXXihBM54tMbVlaQ7ikslePGCe7idpVaKXpI5ecqbMFQt /16tLx5MXJ906iR0hVOCyev/ruchZdPRxRVojHSj6XgNi35p3CBrv5EsskRz6kFRNtdYIscsaUqV Dtqo1ac+DmwnIoo22M0+2RTbhUPnzwxBb8hHqZY5HOWL7Ljd5Y3p9fVLeQ0n+vVrpnnW2VGDqOEy 9Jq+RIshpKdQtczxUD7MeECKe52jDS3lHlbaRYG9KxEJH47UbOOC6lSw1PUKxYRxwRP0iJue4WIt cXkl8/JSUnbisKES/UvuqPWUBPG7mIbOOBrBrtkdxMq5MFyrpnfIJ7LK7W5R+Z9BeT9z8JpJdizn +orFhZeCKCi/w0pOTwi/qmnmhvU8zfPvItv6+3xNt4brfNNsdZhaMeryunE1OR54juBaNfxDJ+V8 uFl2zsusvKCCINrVK8lZN0hTUCznxt+F96TzWtM/YufQOnHpxBHQY2iFqtM5xDZhrBXy5YjSVSdu yPaMqAxEjfN8CdYTtbeAp8/O1jGicrOKeetxI5HGDlWZRIlRnJGDnHjJwCy4s7mf6OAJgkn0cAWS ttfOIds+e3crre7Uqs8Vq3iXy3y8hRacLC5X7LEIxw48uzmuSgA3Xj3inMf4rPO6ezIq9QWBMDSn kFaFtA84frv7G7m/3+XvNY5uQgAn8iJ8SvkTT4Wya0avjhhapkGsuHR58Kr4qbYVW2208T3sbcdM i1au3t/f0yHE9TCQnLzDQ6CAcJHDObl3lYrjweI5HcD+YT8i3rPz1FnQlCdld5o579/TS+XotcfG ZhmThm9dUvHtaF1UglGFyjwP3svWnULN8BTnonF6fF85fZzyB98EBHh2xFHKFpUra3ueHx6jSVmW 6tQ2w2PHZlehB2nf07E+r45VPnkqadTCtY3pYXq2uY4Tx8mK1M67BdWA99QZtQF2X615TTjv/L56 0F0cM36uSX02DmCxgzGW+cY2dujpPL6JJ9zYp2ABKOcJMlsruQ2fM536d37td7IvIvKP//Efy/Wz F/LBYp/XxWVef9cSxkjg4oOvfizvffRNeXV/w25UY96jxsM+76c/U6qBteYLTVVzi1ZzDjetQIcI YwSiAiQ6IFIHQ7cQcpW2eYBe5S+4yAsvL3PtrhCUixTVQ5M1FO85byz9haqf/Pf9rA4gxDDZVxNa Tdm4BBc3xeTKC/tCVBR3BeOajSA2eXA/tHJNrIJrkLfWa3n26qXcvfw8R6dbefzee7KOV7JYPZKL fiPLdz6Sj/IPIP6b25ckKEP938monnKC8WhTh+SUddaSyCZH6V2ISiXj3PhmMrvAsQ0qnau+RnSe IvDBXnrrmf2+ePveWoo3AunScSr9B/3zznE75jFaGrkYn/HFXLh42fGBg6x9HdUATWY0jtDAyYZ4 iyba2TDvsLkcR837u2K61InCBucFKtZxYy8FdlBQQ3Hc7TnxYIgRuW93+T7vd7K/uZbFBD2rFYng qqvaUQ9nyM/FKTuVSaP6o2jlMzaBIxuEJxaIIEXZz66TNFNaZe5GagxGW4SK4uFu1f6a6KsJgvu8 2si4uuC/p6AVzrugPXTZxQJ6RaaxU1rJmZPoLc8cDXXEiPamD41Oojlv+fUVnGQUeyCJm899n8dk 3kQ2nY8mxxHj3rhbwhSZo6xYAnQPkePtGoMRtXUVao7oEHmqPxpKUdLJzv+Yi+GGPWWz+sZhnI2H VtZA1MpWzHWvcPW5qgFyNXDcNIoxsxSvNXhWE2qFKXE+2Sh9nbEIoqUeNEh2lGCUg/lkg60bTTXY nkrza21AWFVhF0NXeX6YsQfrI4v0eSyFD1JHK88rLXbYhWVpOQaHPFlRxLCsFbJehUmeHWRCCv+u A+9Ejb8ggjfNvmyPkoFD60e9pZi9W8RMeYEdHB207oIg5yGvwyOKhoBMI9jakRcMcnN/fMu4pyqU u1pqAZmjwDgnbDzDKrL4COO1yud7mazHKooZGMxOTH2iYGN/2FIKARvG3f6ZvLrN0f5+m23CvWzy RH50sZHLTQ6y7l7Lsdf05iqfy+OrS5XeGXfZrqOwaiP32T4CmUP6dbVay2b9iIHJ3faQ18ORx4ns YZztz81NXi9H2W9vpMu/wUeVtSL92pKs9gNlOhd7kUZqdA7pKLmTYPXSYFXqpq5IjYXPhXfoRXcl HYqK/N7SpvEow7xi0R0zJ8guRQX0fD5Os+0VBbkPDCC17zLoMObEdHoMyhEVO6rBDKW1XLrKHA3N BgRjNnvgqGukyHp0vpZqmtCdFM2g6fqjIoJUaEH7lFvVuK2VzhrfzxZkRtpmdfK6xkFwR7EWj6iW W0xVioS/gwa3Zd2SPhGb9+sC7i3F2jpOzvN1OpXYNQZHu/xH/BzeUIFq19w1c0bfcOYEdm4v7FxT lYbSRQp9PEgcXVCUHHvp3f1rgiMUI09TfW8NQxVISeC0ruTxo+xzfLqTTbiS3/yHvynb66P87u/+ nrxzuM97bS/Tfd5z87Fe7/9cujzff+473ycPF5p0u7uD7PJ6fPr5Z8w2gly0ss4pe+O2Bsu+uai8 hHovsC4GbE6DGTGVthCbSOYIZCdOUIkIpKRXlI2E4V7RoylYfz44b4gCU2yqsbLDhKqMA9INOVrM xo+Cl4D683dePLqSVW9IF9XFVwX5GZM2mEbaAlWtXTa2b0NLKRu++9cvsvHZSsqfv1leygZCmhCg XW8UAXrrKyxtR3k9UKwCggbjvylGTyMMR0+9WkW9WkeMkPHRddRMS8/TQkEdtYMhXU4WLZo1vX4r ZE4g/OnR7A5RuPVn9Idz0spmNldyKlT02/J+fo+nXVPVW/K8PrsARNVqYseCZVdSqkxTHsdyvjjG AujaFItivnOzCkFWtJCC3wddLTj6FnVBKgDcSVbjUbGakp4iJn4ZY6+NvfH3rBwoGp85mhBzdaYA 77sTq/6P8+DUmVnSoCeVDzGYnzYahPTFil0XjuiFmpYyzuokOHcmulZbCqUAwI2eQtLVBrQo1Pmj pFRDEw3meZmwBqgBljfkgTlhNTtEpnrjlXQFPcBcS8bj63v/8k5lfDrVGtS5IOKCSHW64NxUO87v D7/KtOQUb2yvoUmFNtfozz1AAd5w3f5oERP93Sni0HzHeTSf/P3N85ryr3pTLbDoKQqOCLM6Hok/ PH8+7QUlRSTUHzquZVNqNjRvx6frKa+JfOyx8O0UveuMT6drT4sq2COUhRPq4LlUCgO5QVuVgXZA lC9Y9Wyy7gSlWwecvCV5w9mDUYoAFdm1KCm7XNlezHTyQg5g+uE1NyIg63B0wD1DIFg6xIiimijq Wqw6Q3Z1M0b6eLzwqlNNwU5AytF2bdbxORw+YWXucXsn4+4O0AaDny+yY7a722UX8964UAfpnm2z MxdkkwPHTT6XPZzG2zuexyqvP8zB/U7bl2GjvgQFh029a7Uy9O2OEL4ess1eD+x/26INLVLM45jg sN/Zk3ls87Wdd+UY3ommoYe4E3YSNHTVSWgRXuJFxnfT6n1ztOg5qMMhXQ3Agu2X7VxWFKw6LCeI U4vUnaRJTyU4KrLlKFMqxyrSSkGrfr3HaYuAlzELFRHU9ZBK6rdde5Wm0tiPZFw4jk8talJEvq5J d8DO7SeGuNRzprPKVO4N5rT5PdGL4j3A2mjveb0eO2KUB6+fonv1OZ8zJ3Ys6fxyoATIc2/V7Gl+ iI6eI8dw8rCnx7wX/ke//rfk137tF+XPsxP4wx/8vwSIoN+4zLYBVDFUqH7woRYB7qHJ2CUGNPN+ L9evXxK5XthezzaStEfWV7xxbCVYqR2en1IjMWIKM9Fy3i5ZgWATC3GcFILXNilekTpw8bKf4kJL /WFEELXARNHIZcfqAMcvnwAM0GApOS787LSp2qPQcGz3+5OJHqE5dX8UNkRC2gxw9zEbIESN0y4H sFsZ14+zJdrKnirnmjaD5tQqO3w6WZW/QdIwiLViqS1bgNEQMi7WZtInM4S9teAqDaG77gTK3O6O 5mCl4qh5NQ83K2icxViqn46GmoGno8bulG+V5licNR7DdfDcobLIpMDtUSNlOp9BOUCKcMQC/4cQ CseEaGho0mmspTA4uquFzfyP9wAAIABJREFULJR9OSCVHktqWPtuKuLHdG0+180CnCE49Et2h8Dc Idm2F2v7NVJLj+YA422GpEihdNUAK39SnbpjOvK6um7NiU3trKAiILNFqUyRLR/RiZsWm3xveznE jpW0fVAUq7fIUI1ey2OpRuNNDk41Frr0T527aoiiIQUzW1Ipn458oHzbKFo9WqQNyReybTuLquz+ FcqNVrmKpVm9IjaWdGVtPaSl814dZptXqdii59OcbzwplDjfMM83v/Y1/ZwXY9RjlKj2bLzKcfA7 mY6XpFq56s5Z15XNLphBKk5a1PvSuXN35hie3y8dmlTe5xIx/qBOZCG+2z3GR2ZdH9o9JrEHKg/W 672KtjmPqToFncnrKIKu/TcXi431mFUdMhRR4LWhV107GWqbpyLL1FkgzGBwwcpp2ttOndY0zZYx EFkhsAZ3N9vCfruztM9Ku4bkz68faUsvdMlAEOxOZ+eyKt1Qsw/5vJY52F0mRUpVP2/Q783OLGwr kDIi7kd1vtLtC3LeIBW0vb+Rbf73OAW5PuS1vd/loHlm+67LFZBp7YkbkrbX02rYTTkW0bY4EMmn 7Emex6u+ptzah8/Dug7DCULWzltdy/FkXvgc1t4f+l9PuxJDChoweZutOWjaVCxAVbqAqAagWAW7 1LmggWcqliB5/1ebbWwB53SjZGnI1KJIiiynuYryngeQraCuX2dNqdU5X1fpmzlzVRLD9hFD8VqH q/0eXSPnPLLqXGrw1yJlUhzDeHbM5Kq84vQM+0zyYPj0np/e/4cOGsffNE/tik9eOz3npNqNZ+PY PiAoj7UDGR/MD9AAfK2izV6T1JByU6Q6cnlHlbg7Es37/t/8Nekvkvyjf/xHcvfss7w2AgO20M15 L72lxNBHH31bPvzqJ7JPEwW3IQw85YDpxedPCXZdPLqg/cZ5jVMNLur3V8zVH4PfWKI5ydqN2Aki mkRRQQTCkR05IFv8Ib8BKdhjdp7yRn9AJdLIEnWibQsr+xfj1IC7YSejzc4VPXqdvV7K1qLBq1VA 4dEiTxNRuEQHjq1zYGTgDOTP376+ltgflFOyVoIwA0xGzErWDcY1I8yNtJmnd4Ly2+LhWCdOg0qA L+epr3bxqLNUN7zDOFtKyq7NIrI0mRMX6oSOlpqczGBRM28+NV5lAie9D4uF6TF36hz4xuqcJG45 QO4cnQlW2NBpG6TONk8SmXHsoSuwPDkqOEIfDGlQbhCu9T47ewmCu/t7PY88GVd5fCGXQG4fUhQ5 Kl+u9HxwTZNVx6ZicDwanUzmQaMbzK7eHQu4Zb3yEZUjNtuGq+mnQIM1KR0K/j4KJDAm3CAXMg0b FjOMPYoYcsQTtOJImOKM1MmLZoxD16SqbYGrbtXDSM5TeJ6SOHF+cO7mqHfebSJHTBM2g+3rfD47 8q+40YuKXfc92qMpn2q2dUZnPVTjyFZdxgNLVliT3InSfjJSMUR3iGyjO+mL6H1aq3SKX5dH8O1z b5x/NscLQTt4lV1TWCHnFbZuZKszV8bS5n9XNkIpSLJGxHbQBgl40/k9cOjsjLzrho9mSSMFn2dy isSJr8mpBkz0BdSRS5Pah5oO9jR3R+ROiygCAweidp2mxphmHVTYeLGwf5uEh/QqgAsHbrBU7Wz2 SSWSTPOOQaYWO8C54PfGwHZjkGk7khKgTsstKTCmJWladcNyXZAFIGZ+/XDsoASAdQCuMn/6ZIFE DoSWq8JZ3kTNxnTvfUxqyjTu6ejO7HaxJ63iSJmT/DtvRK8P95J2UK8/6rqDE5fP/e0r5Zoh+zKS PjBRePnxppPDEa3CanVsO0fPgwyd1Y1zUOyEFz00c+INwVl7bHf2Yzh9ToEDOLee9svv631eN464 rdESP1i60b+TQQLtXg16yhWkUB02cecuFjujactJr42n7+US8ew6bE5Hq62N08l1OODihXfYZ+ZG o05S3UO+7Kd+pxcDnv6t7/H08EM+XHu+ngE5dzC7xpapxdK2hEWSJFRnVt9/WvR1/n3nQbi3B/Xv b+eVXmFgD21w7UF5Yl/grlZNt1mGIr1k95h3Z5Fkd30nb7/9kfzn/9nfk/u8QP/R//q7Ioe9bC4f 5Wmyyg7c8+ygbXNAc0kHbnP1luyPd3Lz+oUMOXi6y79fPH+miHmvYuGco9gfONe0O5aaMqP02FrA 6A2nA2sn6OmihAbRF+ztxa4K41SqVtUZUScG/IWZasT5OKt8E0DSzZOfzbfzMK1M3dzTft6KRU8p HyMv6kUet6u3HnGRQGsMx18zTbEiQoNc9Xa7YGqSpPdsQNCDc3d/y4FHRcfKDFZvTY4ppmk5bY1A RDQasmbgkLpYGJfPXxcniup1sgl2I/IarY2Ib43BIl4ObkwF0ZvNi15aqno25+/yYqPVYFROXzH9 y3FoInW8zyFd8EbouCHLYxItWiBoRmOuOk41LduXQgQQlduUGc/dnDimV0f/25AMtLs6Jl4P2n69 wD1D2mSYZQNJBPQhnDQy68OCKRR1Xjt2j3BUUXu22vd2p0a6jSo566IiZjR8U91sOX/mA9O0cD5n IFF5o4sorlld5OAij2sHIdSBaO8Ix6r3yR1VNDmE4uicLH5DkyXOD1/z9VAc8FMD4OPF+waklenj RJ27LVTxk2qB7S2YCb3qnil/ckHUktedpLT20nWn4y4NKuGQvxQ0vS/ndHJteC42n2nO903E6TZt 0jpMc/TWQjaOqqJpn4rlI3YUIllTV3kp+looqu0nRtAOlRrDfL7RPjg/ebOB9kdXZCWsMrGemiqd zKFs1i0Sx7fgnoXy9qK0L8Y5VVBTE/9EdJOOAYPRoAi8WBBHbXfImdARG4rWHakHvRfEqOxJ6Bcm TqyFOKzqXyws+NUgyRvFT1ZM0TcZgGBOJS/kqA77gYj/nmsNxQT4PK57ZW2EvF2WV37y+/J6vtjU QitU+uvaBBKvUiQBEgorcHq0KpapWjQGt04Q++y8cV/IwR4CPnRnAaIHKZZDPuant68scAOSPrIj Rg/BU3TywdoGz9D5ydKkv80Gns4Fv39tK7tT2+ZvDaEi4MHS5J6aj817zh0Al0jhGqem6GSah/ge D6gVsbOZ/TAt6ciPBZ7FQYzuxMUTh8cDnNJHtFmTTJ3OD4sf/H1scel/e0YnNk4uBzWeOVgPHbbT 85mr/tsb1ufJtVqa9YF9SYpOpu4hYpea6zs5j9apbhZrEQuWxp4YwNcif+d7DG9VchN3di1+Hh16 sj/imnh9c6u+iY0P/Y65deBOA2KeBzjZ2Uf47vd/WX7lL39X/tXnz+Wnf/onssrzDTUEewQ+qFjP Tt3b735DPv7mz+d1IewdDvpCl9fYiy8+p8Av+HOaSo0PaCQOJtUBrucx1IqroN0HOhWDTckhd22w vlzlqHJ1ujHAeduZXhIaROMzIPdCb4g+blJIHUaEXA5WPC1lYSkJLtKkjdA95Ufn4jAxZ8yJddTJ OrJ78gUbu0NoE0jT1WaTjU2Um5utXF/fstwWzp47XVgYo2hbqcJLmI38GhXpW26q46GDpWjHbFU9 B1RIemqimQxFIHNQEjRrH4bOhHY7tiBjv8ApkIzsxvOdd94hdAvHh+kFuy9tA+bWWYAEi7c64hTm 6c0FDaQ2jaWBgFCisqbQNWAw8ngULSE6lyrESU4N0xnqREKRfjxW+RhKwiwXOSLPYxz3dF5h1BHJ M+Ngm70S3o3LJots0PfWlUPH7JgdbZYh4Dpnd4hSjTTEpANo9NQ867WLqlYb5xCabyBBS3bepuzE jUih0psdBKUyU6qN29k6zaph2zZNyTYIOnDOv5NU0NOyPs5g+RapayMxLxKAk0bBW6SO80ZG8jBS z2h5ZoR6OmqGwHAz75Z6LKblaspN2wB1irwGLaio5e0uWTKYu9IY9iYIOznP5L/r/A7uAPDvU92l B6lli4alSQW1D/Q2JUk7hFOD6uPVPTSsrUNVouIGJVPH9dT5O3/4ecyGWGibvFDQAkf7Zovo3/R5 IoP9wiQr6vPqFOrf86yOgctUeFqp9BO2eauTqGPaLZpAJwSMvYvIMWhvWQoW97pmcKaLpQZ1h8VQ XuvEq+VywAIJEpurxWZauyh+/2A6nPnfQLpY2DKrEgAoMNswF9TPncDeHDvq61klL6pxkcnA8+pM 5t+blUnBrCURsZxoB4A+WDZOLi4e8zx6Xn9ez0TqDgx+YeP2/Ped0mHgTOTNarp/Idv4af6Ooyn8 1DnrdqqknbvhdNwNuDlPq+o987nS0Aesp64KPFvv6rJOHjoykdRdy5RY0Y86mDoPCt3oAcqnT7nD kKxto1egK+O1E+ebO/dcBdzDyXnw79nSpEDYDBX1h9rdWtfdOmHuwJWKVZGCiCtsaOvQ0O8T58++ zx3Bk/VwMtZ6zl7cdO4QelcFXcdvQOd8beOUXONTGpsg9R63OnfqsDcVq835vSnAe9Mj2Pf7Zxjg bC4YVOy3B/Ub2CpzVvqNiaG/6YFxBt0LeM1v/93fIif1f/kn/6eML76QS/C0kbUG2gygJe8Hb739 gbz1/odyN96xOOgi710v7m7k2eefcxwh50VZmKYmIRuYMh6l6th0D8UqpIcKlRq8G6tXSwRpPKDW i45DjRYp+EW+1ObikhMdbV4gEknhXYrlzfRoWSBlSuSb1VorL2BM0Biq0w1g0a8IY7sCuOskoaiC auST9tMcZy0np7EzjZ91NnJD/jw4WCzfR1UsPN29nocbg1g0u2D0HHFcyPHuWBYADWSvHQESU15s e61VVFOrIq5sKyZbJuPC5H+z8bR3t6bgDSQMErWo0NmATmpwDTjhQoTMQsuZ461wPaH8lYB5J4NV QaKMc422Bl6XlM9w4fSKosz8GbnMcL6z9mmy5B5WwsAxY6QZrAqKlU2JzmiAMGq+not5k69RWIGG IpChkUOZ2EqtCgVPbO8z03nqTWIiIjUxdMqPa6UKCu8vFnRROSbamYDnjSo8OEh5c5HVpcT8k5Zo o7VSA5vfMwLVotGManzZiSIZJJ3vHvf2UBaASB3nIpYpp0bK35PkNN13bvDhIHDuiUbt5NngvpgT jfvQW1UvjPLMrPBB2xB12oc2JO0t2g1Knsf866xROguHQJhPugF1QRFf39BYi2M6bUXqoHFAfaNo r7lNXWq6vzu55nNHTo10d+LIte+v1YIPN1Z3xpK4Ea4pVk3xV2SuGMaghta5LG9CcNvrKQigvd83 FpebO3FKLdIPzfWzD6ScOnGOisAp7ZsG61WzTiNjPIiWi9JGVMcKgcLEgHHRTRrwOHqQA7qJxrfh Zo5G+u+1tZg+b45WdqSgdehOHINT07xj5wpkLWYp8k9q63KQ1R21Y0mCBNKK5wT6C2yx28Pt/p7f CwFginAPhvKJSi1cIOiGzcrrHUViw9AbpaOn4xfYT5EJO6skH6nr2CN9vLmU1eNEisVjS/+ymhGK O3k/ufn8h/KDf/OHpGT4PWylbtp7UbqUtOtP2rCq3svU/LtoxfWd8WeHMrY8btRq0uCb46ipU3KQ TY7o/y/sS5slSbKrrkdELu+9qu5Wz6Ju9YzGBmEsZsgMZHxgEFqQbGQY3/iF/Aw2E/ABTEISMoQ+ yBgBWtAs9KauqrdlRoQ7cc65190zqySy501VvcyMxcP9+r3nnnsubUjSnErdPIh2iUhzV71J3oh5 9qHvJTp4oNgQOGZ+WCzQy2w4X9haR4U4ht637u+XiFz9WbMQuCvHpo2bV9B64VmyRi25HvdSGr+7 /c7Xu72dvdA6bA5cvKhFp6dSPx8LXs+sOXk1oAuHvb9P8OLJJOlsAP/086bmV1+MkQeUb9kmRxAh EYb5/ub1I+9h7D4X9v/aifUDiLP8+Gjvffxt+/73v2dfbnP99/7L7wOeZgA082OnbV2c6KB9/O3v 2nBztOd8YkHV5j7Zpz/+sX3xxRd0Jm1oShFncteLuK1JnVhQjCVufPFqYNlqT6d6G5y1lUIjLYwD g1zOn/NEBfA172vJNn4AAYK3NSGdmY90VtJu8M0Fk3diyoW6YPBwnzZnj0iAqhST68rlvNS+fCDg svUXeBRhBAnGHOz28B5ThCTLnoT6wIM+7563iG9HxGY8HMmlG7fBhJvMHDLShCiz3w61eiUZPfF0 w92Ok8jTlZZCIgFIy1IjwxoJGwjPmS2pbsF7yeg2ID7WLqL6Ii953M92BkH/uKczhf6ge2zck5DC xR0nvEa2x2rVobimGVzAaHmPYXPuDdJoK32xSU7burrUS0x0R5/YQzUx9Y1XcAKJFmV9hhypSXAf VPKJaq1SV0cDbIzPfDqpfyqlBFo6fJ5PPqs5zQg8wRkBKgrOC6KUvanCa4lODdYWehUX9oXWtVnW 5yBnA1X5EUUwB1u2jQ1FBEzQQBanjP7dVT1aBy9zJzo2eEWxub5c28QCCWRVYblURu8XcVQi25UR 5XqBMR4VIIB3Ma/ilrJpuMm+jComprGiDIhXXEHWh+LK5UzkBjy72RRhsSLXHbl19AbwRO8O1qfU WHFI4Uc5SJEGJcqT5VDEGMcmee0E/XVIl5DGvjK2s2GdI1xHbdDcogyJdSjbhfFLdQPheXxsL5A6 /x05afFeva52fTpeuK9C8/h5BhmOhNvqAVvb+Gmc/V++2trl+boizb27Jm4UOdCA9vvaaze+TwmR OG5RWsTvgZ9dNVeDYrB6RxT2BB5CasKJ1YPQbRb/E8n1PrLemYJzE3IogzedB4ma1bUTK2jxs3p/ Y6LOgzbU1Z8DAy+kddID51HYOGRKTn4t+8Mt59m4nyp6x1ZnCJ6360EIAycP/D+odVNrLclt3YEb B63vCVp7hRma9z/4wA7n18SSR6QCx5bOvc5E1HG9CJ6W9vsUDlebk9dItJXroOQSfVJGBs9VyNaQ FaTmyKfDWRtUTcr+4Vn2xRPuLJkQ1qaxFW8vnDj12cyOpK3epeiCm5adB1dRwS5o6ee5NcWC2tLx 6l5k4No9NmSsOSHcJ0qu3WR6B6rnutXzrnXB6SfnunZ4VVfOYm+867rNXXr0+hWRXP/qeq0Oni1J uaHzcU/U8Bsun/+1w3VtuqLIofhnkA2j7JWrUBAdrfOo2Ym+8Ca67eD1/ObBfuGX/7n9/N/7G/bb f/qX9id//AM7bn7KYdtP7xcAaZsP8/hsL24+sJ/9zs/ZAIkg9FAt8/bdJ/v000/tzZs39mLzrWK8 NG8X0q2wqbGjFdZJDk79Ik4nRmbe9lSoBt/ZLTfPM9Ea6ccAfdnf3tmLlweiWnkRcrJQn8i40PdM VS3sfTnRk5QSOXpfUgBy+/zjwwMjNGz+rLqaJSLMjQwDml0HpaRLPsSgiQsvWRLjQCWmVgEKhxDo H3Tsbo+s3KR212HPYwG+P94dtQgxvxe2p7AqSLgKmj3R4qohktoHiZ9lREkKSa6oMsSL9x56YUAm wS1BmnnwlCLIyZP0jAC7UNDUZGzhlrOh97AnD41ZkUq2j4Uy1OpNPEcY1FOWicBiCQdILUHEqUmr nKjRK4NhINaluMMyEFXDIgFPcMmq6sH9Q4OGmwzKn73focqtIzW1yEmCIQYCe7OnaO/D+d7Wbbxe vnxJ+RQ4KQdvgo0ek8lXCqpvVlLOZucV7DxdvlZDiOd0nJyW5sgMngHvAymbPd5/zxbIh2yO+Wlz YsogfS4WpWyTee8tSIAErG7ghXA5j2xRYx1W8A0NAVllVeXUmlUnp6YhIvodtk+cR1v2hQsPPED0 jdwniJse7XG7+OMWUqG+Y9zG+vV27Weij6Oi3rW4oG3we1SFijQbXQw4FwgY1kDGsNlinZyYHtvR Lxp5nQtTcpOjNs6fQHIVsjpEuHcqmrBWAbkU6UZFBEuerCnVjj7F62RVMJZIU2obwci+vFO3oSpC 7w1/Cv5ch+ixMMOstkSqr37DSL5lpHQhMlyLDJJ4detgtRIu5EgiqJrS0O6rOArim0CkzGqHkwhq 4hr8Jhd3AqOlj8XmkUxoeVrqphK+AAG8FNc01g0nNsKRILyqAgOBYUDgshdGHulav9cc0gYnwLFD YGBTS7ObG/iobOX1o4DC6SkqthjZeYIdJxAI7G8qlYNIL21pyESp8CkQOMwMFK0xSIp07bNXs6dU VQl68fdhp3Wlf+8v/mSgvO0HQN/Aab3bn7bf31l5+f52jmckkCh5El1joh8zkYhlJgVHQvGac9pk p5buXK9kNOJF4zlw7LBe1A+8kCIy+E8EjkAtWZCSXKFgWVlxSITVgw0GTpifnkYNdFAzhnhL5VaG c8C57jpwvTNF5L1z4tZB1cj4+oTiFW87yS0EvMOpo1MkRYSodmSK1VF5XYrnUtZLeoT4cGsV+2WI EHug3xuKWdY1Ojpkznvx7aK4QOtVfzRHOtZstBgjMlU6atIQgFCqVCSd1x3ytXgHHutSvi5my5sa 61jRSU5C6Zgw9jSs5eaki89Y3AT5+s9GACOTooBCoZnBPjJGLzb/BtQmdB16Pj/RlrHLTJEgPahA VpAdObFYCPMzz7fk0Zt9ak/3ezts+8Gv/eN/wozLv/3t37X7xx/ZN+yFvSmP27kfbIAm4zZen3z7 Z+3w/oeW0dpuWgz5zZ+8+aH96M/+J0qlmPFDYSiyh+Sb0lk/U0cSPhLcNmZCwW0t6ISEa93W3uEE HdSxGcgwEh3JHpA6rplpzYyU6clh6h0dlWXZEeHaU7hvz4WOk2EBgmdxu3mlj/cP9DbnbcHWwgDf UDlZAMptD2fxiT141IzFwka0iDon9Pks7BBQovNDRumu2sU8Pj8R9YGECHSWKKfhKWCmqzyKSqsW DEUrQ6ohl0pmFBKHNIJm7eDNswl1eqe9QbOM+i+TF3BQBJm2AymYwghh9DQZjjtBBX37+2G/qz0F Y6z76psazcQiWuX54/rHWFBOHCdxH4vWRZghTIzzzmnVveF+ETkj/Zu1+UGcUoinNsr83JqRV6kR OJN0rJIEQ60hZmcXCd51pH06Cu6U41qZunHDi4ba4sRlGog1LUpfuTOcZ78/k2NsRH8Q3x7oED8e X1jeKa1kFPYc6KCxtVVp+nwpl8qvUXVT61UafDOauo7/Eahqb5B61OiCq2NdxFvXhzhI+LlMZxoR YEbefgpRtsJhVMWwCNPDhdNSr8OULjgPjZ/CKt15vrguGHmmlp93zvEjLOPVituGt7qczhQSGYFA JQY+eWndKwLBNevQEJdaiOuSca4jVueqdZwlpVQcbbtCAK28e+O9Rgj7V0TY/Z91THUBckBLxPtB DI57iMi+e65h76w5cHFbfb04WzMxQ1suMGI8VjlaIQYqBz0O6qUHtf0er2FQFwCtZ8k0oDq5v/fr MZGG1iiH0K9wqEUk0lE7hx0hn3IkuoU0PyvzHdHlfCDnzlP5u5bCDzFj9pp1uxznio4kAZbMqfHq wqGUsxydLvZeGbvnM4CmHVbuChV6iOzud7Xjgy2t6CwC+LoWYk5cITv8Exv38K75cpUWR3osrxVF q9qXXQqx/119fpEiTeLOlm7Omjvqqa5l8eWC1qJ165XlHeJz/dMkpbr1kLsipOLyGCF5grQJezQX z5hoprY9493nUIHCOxBsf6kYrrd98eHGd3vXq3dM3/pEij7fqa6lHiWrT2sYKtVAFIhOoiTOY5f3 ZO4Uy0n2Sv3UnPLizyjGPZxwjkPQbQZdDwt8ppvNf3hitpFFRfALkLFbvVgRBS15JwcOdIDdWX/a h5tf8yf2yc98bP/iN37Nng97+4Pf+i2z+2c7bc7Y09OzHQdTT/ebW/vwo4/s5sVdDQTPD0/2+f/5 kX311VeVThCBjPpzD06R0DMCVe1pc/zQzWG/u2W7vj2KktBRKxZjPJg4SUDX0QkAnAhUKZ6Xkwj/ 6IkJsnvxNM4QnIxBzZ0P6lRwBzFeaBi9v53w5Qe+OHPlfQF6B0oHZw1esAzBUKHDgnL6UYrosGeo mlrZDkwO4Xx+TceC6B5QDPaEm00Z2EQUcbd3jbBVchBpaATawY0/owv4EHjArHB0pfZBIhFjEnzJ h4mCBgoXD9Bb95J6VeKOaD5dhOjtRgfZE30+Sa6YR2OOBexgdD2qAD+NbUBM6EMsQj0fQccc46wK qhywehddwjlG+JFK7K2S/wgonYiXdmxHPNVOBt9bS1vQcnSp9sd9GDl9VNRGOx04cS9evOAmrWKI zIhcc0cTfgjNrSwJFDpwZZYqumHBoEp3J7XzcmZKgw43+Dxsm3Ww0/6GnLgV7XyyOkEItTJuiKXr SMDVyUXd2vCE8biuBnuXA9E7cX06J6D1y01G7ytGHzwlsNIQoNOEpCK28w7BHxnqRignUwaTmlpF 115btRUB+bgUpoPZ1Hx0Z9HTI0CMvYqQEj3pWZiAowQZzjU26S2SJN8SIsQ7IRNIxamAZKwiwcMw +nWZhQAmr6WTLgjHP6LzyvXieGh9JDfiddewhiDVTa0b99T9vR/39n7vSHdffuu5NWcoeC29lEh1 jOO9OH7p+1vw6VwcP4qCwsntz8t1OnRzots89C5+15Vbw+YN4hia6wmqHLv4/HDH08ZasGGdVEXc Y/TXYPp4tcvzFq+qpJTI5EVOrQ3ZEKl6r15H762wA2wdNu28mlqI9xoSIN62TGngQYr/jiwGClu8 mGlgZa33WgUCB0oEZE/STDQOfV5pBIq60XBo8iWCFM3ag17SP2uhYrFRtfdVtzBaTWZfeReBGAVy +5aDld924oYr+xEOwzBcduZRHYOvvU7z7UIW5cqR1GwbrmyTbHspwcm8Lnq4dtI0m4n6Nfk35/o1 FDPQ5EDK6nFW/0KtMvUALIvnmVO261e6Wgf6ZYxPIXft4nmldPETYAkDyTy/89gRFMbl0Wfwz/DY a3BbS60A7q8pzoN1xLnNoMnXD8Tmkb043m4OEByur+rYA4ELbiLBBLCV8rRdB/Rkd5svsWw+BWgb H27OyBv7ub//z+yN9qdYAAAgAElEQVTvfPdj+80f/Nj+/A//m91h7z+gO9HRhu19OHH7996zr3/0 iU13NwacF1I8rz//0n7y539BrjkK+NhFqdeH7dFFBk3ai/FMsf+icAivm8MOxVVuQN4xCHDezNsn TVMrTwfUPW8XMq+uSG0uMZIbyR3QJaH3dKRDh4bprMaMarZpqJv+YZIQ8IUh7/ueuuHKpauMPZ3Z qwwvilImEe3LqahiFN/bjv/4eO8IhdE4qV+uT+ChGXnN4ehX5kyX5BsUYfWREwvVnjgIUTejWvJ2 H0LitHAiTaLoldHudl7wpPaT+skW5xENRLGU6rsQSeT6U+5bzl5yQVL1erUQliyqEtOYO6rjqTSl XrM9A/3MzdgwMkmtETmQGhK+2RpGnEG+t+q4kQKNijY4b+C6PT490Nk+SK2TSBpargHhzHPwAgc6 NNm5YMocR9oc6Wale9cizt+wzYPdFqnn4x1baCF9uhqKXqZtnHocJBTQFfExYiXv7u2qsZCaCaMZ KHMYwd6wRBByGTFecnTiM+bjLgMhbaPVq6xzkrNexYncyPVVkDI/XHB1U9at+QZSq8Na66toYTM4 e5jPGs+uYxMnT0fAt4XQcOiQrefg2g3e1FxBF/uF4v5HbfJydEbfkIZ67rd4RRoZBg/ZI+SGDKSG Wl05T/2xYi3349uPfeo+X+1TA9H4gYGpomspBEcfag7IkTrr0Dl3J4erZ1LlSOovlituUtyW1uro 7rjjMxUNKKU7V0xSHzM5YI6qeQDHHsAW3T2ynzO5Q6psQeitFq9clqKcz4WLjgAwn2cLWQ0S8Onc uFiKo3MUAh56juVQuXVA6qQe4EU2sCeTS6AM4mhGxwrd40hbt2ZIScUxR2ZGFqSPxwOpD4+7Ldh4 +pK2ZjeomKznG8XzjrnBfsm16vzKKyviMNXfh+zPoJFp9+XBc4fYxDj1jlV14DvULZ59j8Qp5evF DVn7Z7hkl/NDvN0e/QvUsZtgrpigC6KQucuDqO/4X+3E9VWtdfMvsS9EQdUlz+368y1AG0TroBdo gSNbSFtcBLg+30RRWOseyvcq/83HLDUkUMdQIUJdn/lqXTktKl5rBK1OKUruYPZcvPAzr4W+VwdM LDdNPO0dxgzj8fZu+/tgJ6cMWPTU7gR90ehAoIfW5XLGZ0Y7Pb3aPnJr3//+9229Nfv3//F3bffm KztsfsyJRSGDPSNYmYt98P437Ke+9hGzJkvegpj71/aTH/3Yvvz8M14TaQMoUvJmB7FnLd7JxSJ9 H+OyBUPZ6Run07ZHly6Hzj3H+x1S1WGS9wfSH/ldSCGCtHe8sXKraiN4hXSyllJ14OpPUZsmvr9N kIdHRR0YI3ifEKJM3nsQHCJwHIh05WjLBOLuWoXttEC1KcF4I9+NQoqbmxtGPEz1oQ2Ft8LheW/U gBlzmdVQmzE9r6oaExE88vduEhFZu+EFl2j0snALulDy8fGUCSq18DM6KXIoajWlKEEK7mEYd+ij GoKevukska5K4v+YQ71pHZUGiHTcUsQPSqvz91y8uHSIQiAkdFA9ZT2LM9EjUi110aqAwBtYvDiC TuUgmRUYcXJPvNE0JtxMJHR2deujO8yJSJ1arBRtIDB0YxB/JwXNRVw0n2os8gCWljDXdts1HraI 5Hiw0/b80AppAGnLI0u6GKMWLUUc4WQOjmT6Ri7HKLkvp6rK3jGLsW8SKe33vbGrJvaKOC2Jh4YU g9QdlYoYI/InZ1WuAt0dve0SDWsnfwERYl7HEFwUd9DC2JnuGQyggKAC+ZJQq4zNUPacPxKfLyo9 t4ZYrEA4nRNEzw4xCDhMXpz0PD56FefomocSox0WFYaUDompUjBmjsiMPHcaI/gYKuelOkfF2+aU oUvZXmou9Y50/Fw71+96NqVuenb1DCX4TKPvqS3PoZg5wplKZxT9WNnnTuS1tYFftkFqL2Utahu3 ot6/THoWRynpYDsaH8PRZpan/4WeFgtHnLOgfsYqktOuS6GaKosvNtfu6sIpYeXsoJ4FDakTiqa5 NFS5HXHmUAwUcyJRCseI6g0XYsVjVFCbc/S2fQEaeSWcQpfNwVXB9s4jnMrMJuBPD6/rc89O7+gd mz5d2zss735hrGSbrtPRQsizC986Nlpjpewdc9igW4ipF4gEp9R84+xRpJi/QcUYOtrGejWfKB8y OSftHalc3h/RibXTSLOLY6yuShDV9jpPVLjyX5VrFwBCOEs9ST9HOvHq+HWkiu6CIcOF/WvOp/YZ zctr0Kfes13+266c0Aik5BN0znF8x8GJ69cFstf9/lK428fV7YAyFlYzWuyhvdm987bj7Pa3tjvc 2puHRxbcQROOz8mCtuHPA9mfUe3XsPHkGWDMYF89/bl97cO/Zb/yi9+zV/tkf/Rf/8j2KAC9hQza TCkvfH7czvetT75rH3z409wTkIl6eHxjP/n0/9qr+1fKjDGbNdvJ6wjUest5+zJCzk/09T8aAbbB eyiTE9drlBWf4Mt2QHiGh5d3rKg8P53sEUUI4IGhdQsWMZJiOxdTPEY5cuMeIeU5u5O4+qKZV3V+ eHoq9oCUo5OGsnWQNczU6miLXaIn/QLAz18+v6EjuXoT+eBKzHmtxgH8rIXzx/XEXKwY3xdXa1Ak Sch2uABzqghutN0qIk0Szh1FVhaJ0hxiBw/DU0hDK6GPyRpcstrIPq11cRb3rov/3fNssZw4HkJL wqhl8VWyL440uKZeERxMFrsEf9kbF+LMGKtVbbpq94cU6EG52AkkEXIWJO/topBWvb0tdr9FE9SB whzZnPGpg7QxHuOudcogsAT0Fals8HsgTVLEBQTpeTyiMOaWivFIAy0FxSlhTJMjfcUV9OXRkfOH iQ5nxFwmxCe8eF/iqmBsay/c0qpQA1GLBsO909AbjWos/POrXToTyStDufFsm9jNdh/Dea5jB1mJ VgknXoscntBw0n8RRTZpDf1MnoSPsVzpGKi9l3nFLXmlRenVNnd13Blj5/OKTzB7ilRPZhtvn+fu TKhVk/OrErty1o27EuyHwdPenkLNmrOezJaLEVVjq0f2tTm5mXUpsneNff961+/696IdWKuM1UhZ uVzH1cG/Om513i4O7CiZyTGOTa2XAaoIiTVOo9VveeWgve14XryS+JQXryyPI/lm1TY50SYakrJw TRXaLV1DTcf7+o+NTffu11Ekr1GRElZiJomGh4Ax3g30Fzy5mkZlaoF2LqpYw0lMXg1rSZqJOwgY Twf2xMbxsbbHLUg7bRsonDhsqiuD4PZ83oXWXo5d42k1B5+fvrLZV7SI1JDL0dpxq11O7tAF5zDm p8nZ53dHR1KH4WKujmmszsPaB3weiHnkffkTt5Raio9IKh+4p2c9IGKWIgTF49mHEwdgIudmu+Pe V+fCZSEPxW1myFNpXqw8dnKbGXOjR+g433sHLMdaiAAkVcdVTmvnnJbLv188D3v3ulC1bavz5e8i tomiI6ugto5z9dwr0tqfLwqdijju0xaYoGgTEmMP21xMrrfGXt8M7luwp/k/CxggcgxwCH7Fo/3C P/ie/c3v/oz9pz/6M/vhD/6HHTZn7gnSQkm2H88BShkfb07c8cX79pyfqA/3fH9vn3/6mbKEUwMV dHPZqS4xdwNddgTfx22em7M79YPKyeoTC5v9w8Mbu/n2R3bcQX1+sPvHx+0iZzs/P9gD5RQyS8UV tYzKx3Onbe2NdoEMRc9LSomcVeQA0l8Sp+rsJNeoskK/wBkI4BQ9AM0hxqV6+Ljeh/OTO4fbcSGL gckNYv9ZEZ66CSi1mS020yLCqDmhvsLszg/y6A1VuiXJcVLkdlnWzQeNBxa8HVP+3aIfKK45ecN5 cI6Ghf+mRz+0yCii5qpCfYFmrlcbnDgy1fCMAbW26PKM5rrkZ2HiOnIZQpejoujVuWSrC/Biga+z Ilrq0cDBnAs5P/EK4UtVn0mfDQ2veff7WEAja200uQb2ZOTCJBl3Escv7ne7ymWLgMrm8JXjC5t3 N3beFtgZm0Pyyi6c16URhoDhsxwCciq6DVQpo2KXFt3eMiaBwsW8743A/+/F4KQsdELpGGMewlYi gh+AVL6w4eARK5qrn9faDxf8TqTE47leOIzFNdaBtA5ts8EaKJVs3jkqNE5GZ0lFCs7/KC2tkALN Lh6xuoEL4xvIcYwTIsVlvW44DQfTHbhOvw68J9zv6khniBpXfa4e7eH/+YY7JCc8u8PfFZy8y9Br g45n5UhClRXoYQXZNKaWe5Qvzqtbab9P4cCVJjQc86i4I82vCGml7YoxLH5PyVp3m+5V/FiUOFl1 Dxeoh8V8NK8wDASmOWHJ77+MziHq5nElwpt5OjVHK0oZf38Pp54CLTNt/gpCJT2bIgFcmsC7nol5 m7yBLbXK0AYueUESA1FWv++pagD7hqKGwmbMiUivUOuDHSHBc5jsPMFpe7nZjDc6F8zN7hJ5uxhH XxdvO3JXRRAVJSvddXoadbBKc6lFJrnZgfhTRQ2OBnb8t7WE2O/g3Uu6ooRSvGKyzaHgxlUs9a20 pV1cO4V5gweX27VxNQcFBvMhkBiO2yqb06FzWhseJFr7CbqC9hOBGiV1683Tm7F/xLWtgQz3zlis 2e751DV7ocPZ3k9qCNyCrdIQuuT6Z36AqwA6HOrFoqXZhW6eO6dD58VVuap2AfwsAmGtxZUPCFJl kM55poD9I1E4oZaDbx8jfSDKDdEvER/VmPk52evNCduNX7fv/8av2osPjvYf/uXv2MMXn9p0t+0J kOgy+Debs/b0ZN/67s/ay29+U7JHyFw+vLIvf/ITe/XZZ2bbXnC4keD/OTIW/qxEecpd72N//kl8 zNEzKfN2/VODeLuBGJt21sPjK3txc2sffPDCbl9CqE6O0vnprKqOWdwLGIwTOzco1RNpz9UlILI/ qEA0btkBYk9Dr8UeC0volyQiEsnYxSfu7N0hlkUyJXNELVlVHc+EMBORKDaa97RsRJOsUAV2Riva yKPNCMgRwxQYPcrLPiYqgtB9xeY0pmohfNG3xUzbCC0wttQZ2XoMfwaihhdJlHMr//adhRprIYZr WbxA4jHurGlzrsk1X/hKmXF82Ne2mMqvV28Bpk4WKQxwOMSLGzzC+kFC57SHWDRLodnzFEjc2boS dmkgrUCdpjOLPcQ9XGtKfKZDC3LWzsydCTlfA1EjHOf83uZQ7nc2A4Xbv6AmHKotoY+3epGIUAEt RnG+Bi8USew0MaQm0Fznsdu71DkJYdBCGDXm4vWrOYVKBcUrDD7ROBxnu985C2UuTO9uxzt4dTNI k2XHRhMpyymmcjd78kr5nvHweSEvEs4Tqg4Xj7ZWd3TV9kmbp0bBr8X1m3KZfS7GxuXRbI3SnHOU nWMT4+EoXnHHPGgCNLyd4d5PuOcz+ffoPpK9HUg4a6tzXxFsST+ydRXgn2zNVup1a2zV63QNlKjb PN6K1K829j461efHZvzJO0zdeWSB6t+vHC4hje0c8g9TdYIU0VdMrWY7S7zHo+fuX2baXd1RI0oe p26OHH41xjV2x7+ef3gN3tKsy6Za8hZAY3WuIoofZMMcvhiZchtdNSYC17UWTxVmArzIyodVFYIm TjLWy9D08QMxInK3nWum3dhvAXQh7w5ItJAKOD9e1Y82P9DHnBM35N04c85SO9SGi6xInz5vG7H9 ta+eU9mv2+sUfQgShx2I847ZndnUOHEhIxVPPZzWKEarY1Hc2/eghPMpWeVJksbQBSf996ojWFOT q110bnA+mwJjaR5ypynOVisV175wEt/1o/0pvzX3BWvoXOEQhhwOsdwSc+by1a/V2hP14hNaPQwk 8GzL5ffq9y8OOrQKUmvrtHcI9Wc8I50zkMDkUiVjRzMgT7nEeyN7/7IYaFTxzhMUN9D9idJlhaAH /eDOTqCifEy327HO3E8HFOY8v7Gvv/y79ku/8g+33fHR/vd//1MWPtxv8+u9dGf38Bs2v+iwO9o3 vvMtu3n/JX0mYAznxwf76tNP7eHLr7g+cW72jSc4lep+RRltyKmVoF4lzrWgYBC53fbrEZXgaX3e ps8NKy8WdCfAhzIM9PbvdWfnh5M9QyvtZrSXt3d2C/FclLUP2yZ9lIPGpulmrDI9Q17CkQe0gMrL M08q7ty6ecAT879sNOuiu8sitIrO1SoDBQ4ZJ7V75HQ4uCegIvTAqlBOhOdHe/ziC5tPmQUGWByU QQE/yx8YqyWzUovmke1aQu9Gk3Hykt7Jnc+ojoJY3+n5mZ85eA/Ew67XzhrdvRi0+a3y6nE8KK7T fyrbQG9jPK6HzafZMdVIDtkCcu/mGM+uFj3K0WSlETbOOfO5FId5iWZ5eyFpF23/3u518pZbYZx3 1I/LHEsKBS/aqJ8enulUjiq5kQTKzryHaq6m5zQ/61z4b5vcpBKifRc8PkYBI3mIrAou2+R9Ptn7 xz3Pj+dECZXtmpmqRG9EBCErnvFK5xi5bRRtjJvzthvf38YKPW93HLfMDcrh7zzRsUEqY/VCBmpY DdpG0ZZot2oRQKNv9PQonwvmKBp0W2wmRk2+MCwBm69eBBKGvhonr7pN0NybZrvZjjdPB3s9gwcH iAMaW1C6f7Ly+MzzTDcvbUF6nI3Rt6HCGqCzM3AMC8Wc90rTZc2/AdVLvtkEchzXxznBat6m4xRJ QW08iddgZhfpljD6xnuNAgVJwCxR/BHaZTtJPkiJfyQiI9Qs0fFcTMgtjN0uqUodmwt6SWJeURZh 1hUVdwaX0mSKRhanuMbh6LQFzH90GnABy+R2P1fj607rlNwhcM5PNfieauE+tJp6lDtykBqizU0q MWy72NAjyqftwkaVQubHnYkSVd8KDlLOTVm/6wPMFHY8j0DISkN9LUtDO3g7RE0diQhyeHE0lZtm ckTXNxG26cpCB9ShxQMLnDXLeYA3SK5Nwhh3TrHJjlKrC64mPbRwCqRBBp3L1TqHye9p0OC4cxJc qBDlFn0DLb14z0OHivErZyGE3Jy2K2MAuLPhaXPktps97b/a7CJkF462AsUvQ9WG65GYPLuTNTQO ccgbRVBNzcRIRya/Z4IQg9M/JmKNbIAOAePFxIsCf3F774QKevETWJQ37bdrPK92SC1Fro19IRUB vMJ05TQiyAK1I4IjrIml2o+ZqH19z4GIWBviqYmEsECUGWPL7IokmVDZK33W4ntgq16sgr/uDKrQ S9l4/ERB2eyoaM5yQqIPK2uXMG5R0WpehAEgYmlabUvM7+gx7QFZOPekmuZAg3PNEqSi9P7g6Wra 25Qq3cksuleMjW8XQE5ZfP4mCwBKtym7H46v1mquc15GYaiOnvb2TNvF5zGstDkvbo923OzYq1df mtoOLgq6cfRJewUyV1Lm2Ozjth9C/3aZn+z8Ztsw72/sH/3637ZPPnlp//p3Prc//l//2W72q703 fritiyfLr7+y+enRvn73Tfvpj79Drd1lPNv96zf29Hhvn33+F/a43G/zBHx90ROGzQmkQ+m6fVhf qlidOQDJMyDaF9zp357OIWMmT5sDN+5p2DI5X3CGsh2PyY6HZF9tXudTPhEZgUVS9YsOhnwueA+c kNuNw0E75oOiEkerSH5HSyy25Hri4M+zIhaq+BfywJlm5QZA+FLyDNhQ9rc3/mAzN849FJZdm4ho z7bIjo9P1ItbvVp23ByH0Y3t0/nZJ4I2r2aEHe3LjRCPDdhS6IcN0Hml2O8aUarnryEPCRQOBEfo wg0pNGiytO5MOi8DUKtR2maFy0EFFeapWaCF++nAY2sSwQk61ZQxld3L6gtEpcYSDy00bkyS7Cci kvihfwfkMjn51eHj5PcEpGRhY2s5teDnAcnKOynUQ99tcaQL/+PigmBvkgDmzGIJ53Jt1wsn9Xje sUz6+XGyu7sbyqqEFiAkWKZRu+0i34DXvG7XsYI/s98M+e17lqfd9hz3W1QzecpdkDbGeCIfYfVN PFtow9FEbA7K6PpJFKgGVB5N74s5h2ipQEU4Z4kJ3yxS8hadpSKZh7GLkAlb41p2t2xsD2FjFH+A E3i48X6O51kGC8hlkqQDjkqpj2K19VY1OI6fKngvdGim465uXGmX2YszInX87Je58Sdz5+A54X4O qZ7cIzhjjUaJcPvmVnIUsqx+cTWPqHWJFPsq9CWcQHHenCDP+xFPh6g2nksOiZLkkbzWl5BeBHia a0ylezeK4TwwQqZuWYeK1ioeGypizPZwRehi3eBLM+LcAOUC6ZvJk8tFmxoqcYPYzDXdCT5rYxHX U+ntQXwoTx3xiXF8xyrvc9kKqbior7/X87ViE6rzybzoR38P4WLfahz7CBQ1UC+rXDSaKk990gdP QkXV/UJ6UgxuyIcbPauQOogkkEA52+boes+zizUS96d/i6IQ/0VxV02bO1pK17hSQAozJ0Sfd+Ah z7S1wXtOE4TXFzpU18UA/TVwXo3hoDi2VVNmnimpyF271RTHWjP1tY7eciucxXixz/W2QQeSTLkW HGVeFWxQXyzuc/DuJd21IWhcZGcjHZxL9kyJshIhSCzHPtUMVfQfXd1L4VzHXjRN1amBPba146i9 g3JQuxsEepebM0UTAzH4VcE+Cwq3eQ6Bf1aTLYt/Vt+n1mnxAiy/D7uQcApnvWWOGHiZj31pn6v/ 5H1728e6dtY6h8zHgXMsh4PmxUeVFhFoujJZPXodUi9mgfBdXK4KjuAPbN9/Ls9bwLzb7PdL2vKn p5ndhGJ/aHPDxwISWPOjshnPjwaat9Kai/3TX/0l++aHL+wPfv9fbX7NG3u5R2Hg87anPzODhODm 9v1b++ZH39nGaNvnsvqof/7Zl/bZZ5/Rmb473PocOlWUeOwQd4nX+3zDvSxrLTiKQBFBw1SovyWZ jFsovJ8e2bR12pyEF3fHzWsd2Dbi1emrbZIn6qMdNsdj5KIwe75/ozMO3qM0IF5HOH7q7qW6LqRO yM6C33beoiMgUmcL2JeTnjwtl6Igf2utLbliscDZmDcv9W442tP2kJbxeTvWSYYtKW1Ip2ZcvZon FrZPGG8S3DYgTQps5Lsu2kaqYCxq5zM5Pw/bBBC7AxXSnXfhkzX5ZsBfeiGjoo9cixUQ3UlbDxW1 Jzc8WqRsDebaObjKyRcJC62KecSZahHEBPkNV/kenXyO95lqRmUNypo3owRVajggQAHpqAEtWiWf wApPkNTpPCpdI/K8IjCSb9ElIrvUSlJEi1Y7w3vvuYN+YrpYz0fPaBcoT1UIhzOwbcq7m23Cbc75 8daebu4YtQPxYXeDLErlEPIhURzSVXaSyG/OVUQ6bZyqoStejs3NeEIUdarvRZUeZpIcke3f6Mca DkGRw6Jr9Q1jdTmFEhuaUYeQ58huJCjbsCOaFRVwUpi4FAHmxpOjVZUM7VyLV8PZEleEyAccAKCa pVSx0sHb0yV3DobTqeNPXiqp04erxHGnBfhnaOQ9Gg8Iv2pGdS+tkbZprL5Jk1iN+ZnVGsc6BzjO mVcpvktHsBNWBj/Ue36WaOHnKDcduFEVlLBNa9o15zs2/SwrQ0fVC3tKbmlT8k3jPvggIjrvuEhF RREVoQskIpKlSc5iqmnBwEDDoUjuRKzVWarpfN+AuF4tKuXqXqFUZgqbYfV4PEaOdG7YJFFEWGDh 1d+aVwPT8BK+HercittuXMezr0moHahjCx0C71Ui/azcPbvOWXbH99JxkCPEhnYY90WdaIQ8CtaR I6GOJegVnDmXQ8qo1DSujnc53+Lc8bx71CnsdaA44STLOUsVAdK1ejBddO9EVfZAj9UVYj49YASJ rmMsYfPRqhE2a2ZXBaF5hV0t5NzzPhy5jN9hP8FY4/5CG1LOv36/H84W6VEhd07tWOU8BcKrwjM5 gyd2JTJ1dYniJTh4Q3Nok1cur5PV97MjaWstasE5dzwXEXU+2x3vgxxaz2oIQS6af8m7+hQvmEu7 9lz4AfUaLh6MxphnR4Yv0FQEoZSdWZqTm5vEikR4F0s1opEDFx4hoY9OGqTOQZdUUqFfK3jsHfR4 SRqMmzBBB3RFOByO9rg5cOxmsWs6fZasrQMPcEDvAf8bslqgF331/GRf+8537Hu//n17td3GH/7e H9jpzcnee3FHZYyhHLfxhqD/e/bJt37OPvzGz8hxX5XR+9EPf2hfbE4cnsBxj4Bfvg0yXbShzBg5 jFWNiY99Mrd7wU+UMPG0o3TAdiA0RN6MKyBDVFcA0j1vB3k6J3tzf2Zz+tcPC5G3owtEYtIe9jda ZENyo9w0yUZOzNdVMT8WZDXILEiICKMR+LNALaVG87kamZLs4rv4wXWdUMSA9jcD+mpmL2JQNQ7S WRA+VUTD3IUfTw3uoXW36zZSSJwtXjnJcwAeX4XqTICmV00w1CStp82JXLYHtB+VZmLkZUwFQAKk zAOjzvV5e2fz1R5H5d8hhkxD4hpXQtZ0XeGs4rUwXbV4NJrb+KyocnUjtt+rqAPpUUcVidZ4W7Hd OZGn+PR02iav+uGunv6C43VKQv1qNe8SXI9QotezXFYVQVCYN8nRwHXMWCS7I6Hge7ThGmGQjMgU 9HfYp48eQ+Y6pB0BVM3oeGJ1K1u2waNY6OFY5MNgRNZBZPpIb1OAeEhCPcMBdji98Uycd4TUFESg I4LEv9GuZBHnkP/OpbZyw6uXAWAlMauQaVG5Lij+7MZ2ApdvljGVXI0MLxwbacV5Nagpk1iRGRKT PS1kTYIk1Y3SfIMtldRLhx0teGCMA/rHGpyGis61/q+lBUsICFzIU18avVJUCFAcf2L6crTVUWuY if0gY47/plEyOrnbYNEZJNpbtfY/8QT0rG+P+9YqLwxtlvYddMJOqzvZi77AlAGeA8aKgY73i0WH gWFqyAFT03AeZhm0GF86F6ufX9kF3naVXlkqf53zeI3nE4imI0lOWN+xtaCn2a8QIYqJKyFZ5148 v0iXVbCz28OJIu0AABAiSURBVNzquXGaqaWTwnA3qgY24oVUAXxWiJb5GtCGSsS/Fkgtqgxn0OHr BZQQJ3Z7nlQ6gxZFDubpd7+vkMsp4oqV3CNvEjaPcQKKhP1j4FVGf2mld5GoxdxchpkpSwY4eLZe QMDAZGgt12JsejoD59jca4+qKrtUNDBxDU6OXjV5iJVjhHkwAV7bbFM+KbcNuzwdtu+eF1bp22Gz f1sklf05UK6Kc1yO6bg/NNTLn2vfAWZJUdBzmZauz7rs6r5XA6G13VP2ucWCwnmp9hvzu0ffYj0H 7SL+Pq3teL0zU3+XnqvmanGHp+4xjsBFgGj5UiIs7rfVi3RIYA7yjQCHqW+NZ+YSKNvPWYisxsyd 7GilBQfTnZcYwwhUuSZDm7W7r+hbqgJF31s8+LYSKfCxrh9QjdDfm7QZVKZidj69sYevXhsIZKBy 9XMvrgPzflmlPrFscwcUKqRK1/tX9vO/+Mts6/nv/s1v2o//+Ad2t93X3jKpZI8PbzYH8Y399Ne+ bu//1Ht2vv/S5tfr5ked7Isf/Zm9+fwzQwoXgAvbenFzX2vxZlUK8U5PLXDx6xqCtiH0dkJW6OOP vlkOx9vNSB4JPdPgwnBsd3HYI5IYq/5bICvD5IOEAStKgUZvT1Y0kb/jC8/Jq/0kT6k5dSUvF5M/ HpCijbFWbcgDb1yE+MF1zr5RZ/ekI9oBWRzyF/Xh8KLb4iDnza85DJM2y6lzhtaLQdQMbbyIOTWx vuA8cIySnIAgxqfSJoraVQ3V+a1Gyx2p3qEYh5BXabpmUpxWi53kTdcZH3m7peTXyPveSxYCDluD 8gtRM5z/APR16RygIr24iIathOByqj1bg0OGUd1Djd0Xf69/p3TAqmL0tDC5wGIRjANSXNOeDhr5 VeRGjhKLLupVyVQmgolVHDsdb6ZxHscmFXMdIPQvbrQlEI+2OYaBo0wCxItPp7cMcMz3cYvenvxa JvSbBdq7U5w4YXvcTzREnA/oi5ul3WdZVWdrztWwaDwvN6rr17Uxwf33a6d/L0SiIzCK++ffs3Nv bOy4fqWes5J3PT1dn2vOVXYFa2f1daJ0fPKCC6trbUrded0f1fm0bsApWRU1uIyDuVOudQZdvbAv IUCcO8RsPi36nGtWziEoPqp3J7hdvE+XgFhCCmgYtP4qNaE5Bhcb3qINc++B6anjXeF9zj13kMM+ SEfTkaJBY9pznWKNR6DZP9u+ypTfH6e6zsPmxDMOtXbqaJoHeLA9k/c5RQCKlGBpm3j0NtVmnZmC CVmjpXNuYaO1PvJbc//CGbDSretWTRjrLezr83yuthTraTRdN3U3l5izSl1T0xIcvqE968uNOqro Ybca9SMctAh2415j/Ou8Ma1rAQGLE9fFieac3e8qd/Y4NSQHGy3bRbp9ps1cG3Ib4xtOQkhO/ZUO nBnnd29/cK39fhp9SLVnpIvULJ/ZstRz9eeN1HCeGpJ0gVhHwcggwICak3R2rc7VOg9z7IfLhfNW P3Nll8za/nfKnbpDaUiu+G7ZnaiZAWiP8kbrxj5bm4YeAW5Ztzieft/2weLOdj9ne98g7g9cyrgn nBM6t69evSLCNjgfv3eYmDn0Z5IGFAqq5ebdix17ro7Tnb14cWcPj1/Yq0ekXc+GvvaDHYhFzMuj 7nXdkye9ejEY9sHz4/1ms84U/7eiLE8DbhqAEPagopfd/hr+Duaq0e/CvaIDQzSp996n2IDun7bB H1o+HyjV86wKEDosaP497vQ9DOhq3QCbSKHrXA1gRDEBjfIheWqq35zCkNEQlrZhlXCsuo1xLO58 ja3sXQOhAnpURaUuHcRz0KEaiUpw+HLpJmkh/69OxjW9pSqec6saAxow+wMAciYOhHSFkrUNTg8j IrJc7zP5YpHhNVX3unMJo7es6sag8dA1zHP2lFVhyhYGikjc9vfDwUv7kyJle3ZUcB3Isajj7ETl GeLHTphVU/WJY4IoCpEQN0FHMbxNs0lYxqM950HhniffSM+nFikyyY/jDKqW46QzkfrBBbgBMnRS oQmLHopQ2bpYSaB2KQhcZ1qoNce0zeINomPBBqIRm+kiQWSS6ouQWb8wVUwi2BhUfBPztpGOFzmY KMwBrI9A3o+FptULCd7qirG6uLMI8BMLP/AJOFJzcZ5WFhIZUbeMXqqK6v2Ctc4YKUf2VpbTVK06 eE/s1SsVfeMYlKqdXKAX52Wl9jA2DawiFhn6+WI+laz0MtAR6aEZUyHnRWnRMfhVq9ba4P0cJ3bs 0DWxUMGUll1zVFoN1TljdZcb0uDOUWuubkLiOdWoGo4AjCPbji0yes6PxJk4tdCZIFLaSRyetOpe wFGG/eKmicDHm7bDsdBGKjEccin9OaEKbQy+JM7jG1xyDY/rTYI9QxU1qWLaUx+Q9liYSZi7Z2nd MTTGOJ8+rzE6L+dqa5j62+057zg25mnIIioBuLiDE/oDOR9HIcCFlA9kIrzYgtQMbyK//W6XtcFG mi9ssKgEpeMAmtufruewV4ODUgGkS4jQwvGms0WQcOXxqVwwStMsELhIXalN4ttOXL8Zx+Yre6zs QuwH/WbekK0+/VuYWRqHG9omOkxwWjc7chhk19fTE/cxfgd84fUshx6BEII7D46j/ZbX1stJAj1o 50FkbpSN/nqeH1J1quO6gx4UnYbwe/x7N4qzvNuFGHnbN2G78Xt9NpskvbZjnucLFL/2lHUU9rS8 qk48eoCSGwq76deZPBDs05yBMo/MVlmzmb7PVWdx+w9FWZH+NyUsJJXk1fbQZFvXJzrWwScVTWXl /fWV9NTkiw2Wx2wFI5Ge0zNoup9TaKvWudNkc/gZoMV1v90CtHza9ko0lj8T8WscPO39alvoxY4T OkM9b/vI4BmsWbSnbU69+vLR3tx/acebD7bxLaTYEGM+r6xUReeG521u5fVUA3n0fwe/TnJp8/a8 96ZuSO6buCD6us7VBwBlif7QrOd8HShiXk/Q9WFUtm3eN8e9HiYgRp9ct7sbTTjc8KxU0S5LbRnd ACZUHiXxpLR5qe0QH2hSu5a0S9VojkOTL4ExmjxdVqttXEFcDtIIEf/qsKmFTHOouGgXITdKDrkj sEY/RPCWkjx8LrKIcn0g0sjNQMdTilAPnp6hjj9KNHTOLQ2MTW5HuNM5gCl4VKHg3yIppAur8+qW u4fkFxdyzDWi02YWGzsqOGPCjq6Mma0ZXS62aWd7XwgTnI3BNdZwzHGsUScZAqPEf5l6wf1sz5Ap Q6JfHukUkUxxthlj5c7Hrqjd2OAUCsp/hLNblrrgqVE3eDuesrraOHTFduJ5MDXnyNx2QEiirJGi ZGpKmz9TznAq054E2m3i8fcsS8DmhB3eBY55rsG5J6OQG23epTqdc3DZBnE6ZFR2TImNLqJMR4cI 6oloW8pPNiD9DRtydj1CjqueCzpp6L5V7OKsIaUCcfS0q1Fz7UbS6SgOtVpLBnUcopWPHJp17NqA dS2iKOmAtYTuI7jyZD7OMKAewdMQje5ZtMg0Uk/VoCZxTOEMwliB4xSRtFrqbdGoq+kglYw1W2rS uiG4PeJej7ssFQGUsLb4b6xkRusll5+R1Q1Sv9YigyfXj1oIb66+rtRRplam+bl7VDbGlwFp0py8 SDO5HcCayo5axPfCUPZIWg0Cw/vqnO4eUY3N8JpE3ztKF6igk8tVUdp6XdZ7gUOcVvFWY6YUFZGY ieKggMeLbViRGIHBWAPANcYqOFmBvIf0Twm+lewEQ9AkTbb+3hSYSbqGTufm6EzVccuswsa1qgij KJ2d5FAxWHYHHam9tUTBidVx77Mk8Tvd83oRwMcrMhdwbNBKCVN9wTr3Yo+wxULAzv4dl5MgyX9i wIEN87gf7fGEoG0np3pz0J7nE7lUMR84/5yHO2926pDEmYsCBW/kKecPxVl7ZaiqpEnXiaKfN+Ca RzDP9yOT0mU3Yp31Kc9xP1UHTs85uMGJ5OL99ELOKuyfqaAFdhPvFxLlJ0/br7SfXKu+V805+C91 BugahhbITKUF7FynnSMeqD3QpsntcaBnbCnHnuit+nbo9Aj1b6vrq0fW+j/79dSv7z7r0n+/R9gx N8+uVsHU/iAf4+Q8VwgD583/GUAXwrk250xdG4SC3dx9aPvhsNn1eztvv9ujn7p3PsF0wP2NEwKX tdJpUAhT1nC4zawDdPpsEYP7QannwULcG2Ohnu3KEs6b74ZiOKhqYxMFj2CVXg68Oy5QkPFG9ekq o5MI44Hjc5vDMq+9k7KqFVR3QfgTkLsNIj+yajSgBRiUSRD7soo4jGikuKAtW/34A2ZijkRMacOo 8tKcWyaiZxrU5qUEvTRFRwYN1uqly4hiWDkJFOJ8sqgkC07f4tWVOGY0pp2pbeTad+RcDHzIhRtz QwhlTF1te1U15yBetC/yxaMPcammUajAOmvDIe/JuzEMjYxgaBRcSpBMl7rZrY6cBkw/51Y8guc2 ETWdfVMYfU1m/m4g7zHx2ZIQ66lt8lcmFVRQkdyjcPKKeC8+PuwzpHQFUbocKTShrXDOXmzHefZZ w00abjMLAICGzQZW25wlK3EcVJEaGy5Jteu983NGFt+YIyuJkYpkaUQBUBRH59RUHr+SQ7SaWjDR C+M9T0OkmxbqRE1bZIbUKD4Dp2vH7565f51BXEbEREDrmY7rOCo4GVY32GXw971Ck05DJhXgOOwv DE4YoCgXJ4G+er++0cdniylas5bKuEhrlFJJxuZtYTivQIZOMthr+G/e0UChRlR/uU4aHMfVi0Wc a7aez3aaz6birZUBjy5R8gShw6drUWshVHKHQY2emivtQ/TSLNooVAdBx3Fkd47E6y++8auKb3Qj mKr0CseONUM7J/4bN1qlTMV3ncax8nLpLyDlzUysgr8TuVBzTaWj+AXR8kyCOo451oBLhQ0efHXb 2NB1tpA0xEQSeaSmMQ6QBoF8QhS4lChQcpCA95hEhGdKPAffyTMW2NSnQl5pCXFkF+zW2vACLxL1 1dA+VABwDKWFpiqSnv18+DN7RSCvwat3xQVs84IBbW0Z5lqFpDokfwiaDwsKmvZ6VpEBiQKgxTM0 Y/RhRYDKPsm+wZYo++iyLZ0TQGL8fqrzPWxspFaja4l1G3S8Yl4OdBTU9WRl3CfxVNFDZudVLlQa uIGMBMS1iXpMDPBxqfvBkVOTE0qEEUikS00NXnywVlHJYtGrN9ZI0GziOsMJiuc+sQDAHT4XmAU1 YF/552rarnEovr4y9SIZdCQhx9IXbdp2h1HIWEYBVNHaG734C0GtrTuH+T3PwgA7kK31Ykzb4Jqe Ja4xT9VWae74vY3iT55mz0zBiYsgIKunNuVd0tCEkn3PDjFvZt5oI2M+xmSpG6rQSH8/quNLvRZl jpY1GhJILxbPgtSwVeJgEVjvJ4FYJx+rcQcJrJV7iVLQK5sUQPoKdEoyYglVIyOhIAHzbdqLlmEo kjGlsHceYON6IY1Fzj0oCMcdb6XnYWP/XPy+gjaQSnNoA9kVOJPt/wHjrCq1zCYmLgAAAABJRU5E rkJggg== --VO2=_4cvuc9G6HPycPcUh5KaKA7M349bzt-- From boaz@plexistor.com Wed Jun 29 07:23:58 2016 Return-Path: <boaz@plexistor.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 502FB7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 07:23:58 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 2081E304048 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 05:23:54 -0700 (PDT) X-ASG-Debug-ID: 1467203031-04cb6c063f2793b0001-NocioJ Received: from mail-wm0-f48.google.com (mail-wm0-f48.google.com [74.125.82.48]) by cuda.sgi.com with ESMTP id loFJYFZZFoHPnVU5 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 05:23:52 -0700 (PDT) X-Barracuda-Envelope-From: boaz@plexistor.com X-Barracuda-Effective-Source-IP: mail-wm0-f48.google.com[74.125.82.48] X-Barracuda-Apparent-Source-IP: 74.125.82.48 Received: by mail-wm0-f48.google.com with SMTP id v199so178579784wmv.0 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 05:23:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=plexistor-com.20150623.gappssmtp.com; s=20150623; h=message-id:date:from:user-agent:mime-version:to:cc:subject :references:in-reply-to:content-transfer-encoding; bh=e8lNV83EE/Qa2swaf1RWKq5TSYOR/ToJv15jTkJHy9w=; b=i1W1LA9gg0/UJ8Y9cwPzwVQhPSjEAL7OUso6/Z59ukLPDkQVMX4EE4htRtDKO0zhYi jj98G8OlWVwaex+M3NMKMaWCadnIVlnxa4somEmK19boUzZb023ixwTMKYaPDn/4f+Hs dd/GtMlEzQL1RAvDlvuFsFHQ0IGYZoOYLzWJVtfJpXs3zZL0Oh8NAqjCt7ubg9MLRnai piuuXk+zZZ7bU1U3BbC8006WnR2obWtVAeCbNP6T316YjRXQBcqVHZFYqVGU8MbRFF/p Yb29pVXHCuNijT7cE1cnJRQSajUF3J95IOyaqF1A+N9irrJFEO/hsIOHp3jsIBbQoV0K +vgg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-transfer-encoding; bh=e8lNV83EE/Qa2swaf1RWKq5TSYOR/ToJv15jTkJHy9w=; b=D82YVdXvdHAttWbbpR+5SLRUlPHBFjfCVc4WZT+66sC6SQIIMKPxD78kVo6qYLsLE9 SMGKjdITGj4q2ZPYZIsrF8oltEY6Oe0hpz8jLZi8UfGrB7+D3wk3BACJ6eunYaq+Wvfp aOPDvJWeei5JJP0gDsrYTGzfmuA9XxemA9UgvjPiuJLHQ8MXp8rCB8hGCtkQZhhpZZ/F GWHQmcckWNl/m3HfyujHIrSNRDnW3SPEUqeVyL7gY5NOecm4KgzaYXBnk6q6/bchtuJ3 4WiK5WU9LDyqmT5C8gMXVPVYnCpktFruBgAHa5lN9RCIbt9KTx3c6h229XdgyEOGEuE6 2iag== X-Gm-Message-State: ALyK8tILOEvT6GFtPB0Wb4kBpoXa5NLHbF+NnZkzMhPYDpbtibNF4CJ7Yez3mg4P49BdoQ== X-Received: by 10.28.148.1 with SMTP id w1mr22307066wmd.63.1467203031259; Wed, 29 Jun 2016 05:23:51 -0700 (PDT) Received: from [10.0.0.5] ([207.232.55.62]) by smtp.googlemail.com with ESMTPSA id q63sm7296323wma.0.2016.06.29.05.23.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 29 Jun 2016 05:23:50 -0700 (PDT) Message-ID: <5773BDD4.60705@plexistor.com> Date: Wed, 29 Jun 2016 15:23:48 +0300 From: Boaz Harrosh <boaz@plexistor.com> User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Christoph Hellwig <hch@lst.de>, Boaz Harrosh <boaz@plexistor.com> CC: Dave Chinner <david@fromorbit.com>, xfs@oss.sgi.com, linux-fsdevel@vger.kernel.org, linux-nvdimm@ml01.01.org Subject: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking References: <1466609236-23801-1-git-send-email-hch@lst.de> <20160623232446.GA12670@dastard> <20160624072612.GA22205@lst.de> <20160624230045.GG12670@dastard> <20160628131059.GA30475@lst.de> <57727B27.7060104@plexistor.com> <20160628133928.GB31283@lst.de> <5772820E.2080403@plexistor.com> <20160628153925.GA2643@lst.de> X-ASG-Orig-Subj: Re: xfs: untangle the direct I/O and DAX path, fix DAX locking In-Reply-To: <20160628153925.GA2643@lst.de> Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: mail-wm0-f48.google.com[74.125.82.48] X-Barracuda-Start-Time: 1467203032 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2550 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30860 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature On 06/28/2016 06:39 PM, Christoph Hellwig wrote: > On Tue, Jun 28, 2016 at 04:56:30PM +0300, Boaz Harrosh wrote: >> Actually with O_APPEND each write request should write a different region >> of the file, there are no overlapping writes. And no issue of which version of the >> write came last and got its data written. > > You have one fd for multiple threads or processes (it doesn't matter if > you're using O_APPEND or not), and all of them write to it. > Yes so? but they do not write to the same (overlapping) region of the file, each thread usually writes to his own record. > i_size is only updated once the write finishes, so having multiple > concurrent writes will mean multiple records go into the same regions. > Now to be fair in current XFS writes beyond i_size will always take > the lock exclusively, so for this case we will not get concurrent > writes and thus data corruption anyway. Exactly that I understand. And it must be so. > But if you have a cycling > log that gets overwritten (say a database journal) we're back to > square one. > No! In this "cycling log" case the application (the DB) has an Head and a Tail pointers each thread grabs the next available record and writes to it. The IO is not overlapping, each thread writes to his own record, and even if they write at the same time they do not over-write each other. As long as they properly sync on the Head pointer the write itself can happen in parallel. This is not a good example and will work perfectly well with the old (current) DAX code. (Even if such records where 4k aligned) >> I still don't see how an application can use the fact that two writers >> will not give them mixed records. And surly it does not work on a shared >> FS. So I was really wondering if you know of any such app > > If it doesn't work for two threads using the same fd on a shared fs > the fs is broken. What works? the above cycling log, sure it will work, also on current dax code. I wish you could write a test to demonstrate this bug. Sorry for my slowness but I don't see it. I do not see how the fact that there is only a single memcpy in progress can help an application. Yes sure isize update must be synced, which it is in current code. Thanks Christoph, I've taken too much of your time, I guess the QA will need to bang every possible application and see what breaks when multiple parallel writers are allowed on a single file. So far for whatever I use in a VM it all works just the same. Boaz From cmaiolino@redhat.com Wed Jun 29 09:03:22 2016 Return-Path: <cmaiolino@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 379DB7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 09:03:22 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id B91DBAC001 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 07:03:18 -0700 (PDT) X-ASG-Debug-ID: 1467208993-04bdf074b71e67c0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id ENmRkrFoIE4lk0vn (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 07:03:13 -0700 (PDT) X-Barracuda-Envelope-From: cmaiolino@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EC33DC00E919; Wed, 29 Jun 2016 14:03:12 +0000 (UTC) Received: from redhat.com (unused [10.10.50.36] (may be forged)) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5TE38uW013478 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Wed, 29 Jun 2016 10:03:11 -0400 Date: Wed, 29 Jun 2016 16:03:07 +0200 From: Carlos Maiolino <cmaiolino@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, xfs@oss.sgi.com Subject: Re: [PATCH 5/6] xfsdocs: reverse-mapping btree documentation Message-ID: <20160629140307.GA26533@redhat.com> X-ASG-Orig-Subj: Re: [PATCH 5/6] xfsdocs: reverse-mapping btree documentation Mail-Followup-To: "Darrick J. Wong" <darrick.wong@oracle.com>, david@fromorbit.com, xfs@oss.sgi.com References: <146612808918.25586.1147874927753492795.stgit@birch.djwong.org> <146612811976.25586.4109341284933778121.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <146612811976.25586.4109341284933778121.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Wed, 29 Jun 2016 14:03:13 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467208993 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 28772 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:48:39PM -0700, Darrick J. Wong wrote: > Add chapters on the operation of the reverse mapping btree and future > things we could do with rmap data. > > v2: Add magic number to the table. > Hi darrick. Just FYI, I'm not sure why, but this patch came to the list in base64 format, although the remaining ones are in text-plain. > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > .../allocation_groups.asciidoc | 24 +- > design/XFS_Filesystem_Structure/docinfo.xml | 17 + > .../journaling_log.asciidoc | 130 +++++++++ > design/XFS_Filesystem_Structure/magic.asciidoc | 3 > .../reconstruction.asciidoc | 53 +++ > design/XFS_Filesystem_Structure/rmapbt.asciidoc | 305 ++++++++++++++++++++ > .../xfs_filesystem_structure.asciidoc | 4 > 7 files changed, 528 insertions(+), 8 deletions(-) > create mode 100644 design/XFS_Filesystem_Structure/reconstruction.asciidoc > create mode 100644 design/XFS_Filesystem_Structure/rmapbt.asciidoc > > > diff --git a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc > index 55bbc50..8ced83a 100644 > --- a/design/XFS_Filesystem_Structure/allocation_groups.asciidoc > +++ b/design/XFS_Filesystem_Structure/allocation_groups.asciidoc > @@ -12,6 +12,7 @@ Each AG has the following characteristics: > * A super block describing overall filesystem info > * Free space management > * Inode allocation and tracking > + * Reverse block-mapping index (optional) > > Having multiple AGs allows XFS to handle most operations in parallel without > degrading performance as the number of concurrent accesses increases. > @@ -379,6 +380,12 @@ it doesn't understand the flag. > Free inode B+tree. Each allocation group contains a B+tree to track inode chunks > containing free inodes. This is a performance optimization to reduce the time > required to allocate inodes. > + > +| +XFS_SB_FEAT_RO_COMPAT_RMAPBT+ | > +Reverse mapping B+tree. Each allocation group contains a B+tree containing > +records mapping AG blocks to their owners. See the section about > +xref:Reconstruction[reconstruction] for more details. > + > |===== > > *sb_features_incompat*:: > @@ -529,9 +536,7 @@ struct xfs_agf { > __be32 agf_seqno; > __be32 agf_length; > __be32 agf_roots[XFS_BTNUM_AGF]; > - __be32 agf_spare0; > __be32 agf_levels[XFS_BTNUM_AGF]; > - __be32 agf_spare1; > __be32 agf_flfirst; > __be32 agf_fllast; > __be32 agf_flcount; > @@ -550,9 +555,10 @@ struct xfs_agf { > }; > ---- > > -The rest of the bytes in the sector are zeroed. +XFS_BTNUM_AGF+ is set to 2: > -index 0 for the free space B+tree indexed by block number; and index 1 for the > -free space B+tree indexed by extent size. > +The rest of the bytes in the sector are zeroed. +XFS_BTNUM_AGF+ is set to 3: > +index 0 for the free space B+tree indexed by block number; index 1 for the free > +space B+tree indexed by extent size; and index 2 for the reverse-mapping > +B+tree. > > *agf_magicnum*:: > Specifies the magic number for the AGF sector: ``XAGF'' (0x58414746). > @@ -570,11 +576,13 @@ this could be less than the +sb_agblocks+ value. It is this value that should > be used to determine the size of the AG. > > *agf_roots*:: > -Specifies the block number for the root of the two free space B+trees. > +Specifies the block number for the root of the two free space B+trees and the > +reverse-mapping B+tree, if enabled. > > *agf_levels*:: > -Specifies the level or depth of the two free space B+trees. For a fresh AG, this > -will be one, and the ``roots'' will point to a single leaf of level 0. > +Specifies the level or depth of the two free space B+trees and the > +reverse-mapping B+tree, if enabled. For a fresh AG, this value will be one, > +and the ``roots'' will point to a single leaf of level 0. > > *agf_flfirst*:: > Specifies the index of the first ``free list'' block. Free lists are covered in > diff --git a/design/XFS_Filesystem_Structure/docinfo.xml b/design/XFS_Filesystem_Structure/docinfo.xml > index cc5596d..44f944a 100644 > --- a/design/XFS_Filesystem_Structure/docinfo.xml > +++ b/design/XFS_Filesystem_Structure/docinfo.xml > @@ -122,4 +122,21 @@ > </simplelist> > </revdescription> > </revision> > + <revision> > + <revnumber>3.141</revnumber> > + <date>June 2016</date> > + <author> > + <firstname>Darrick</firstname> > + <surname>Wong</surname> > + <email></email> > + </author> > + <revdescription> > + <simplelist> > + <member>Document the reverse-mapping btree.</member> > + <member>Move the b+tree info to a separate chapter.</member> > + <member>Discuss overlapping interval b+trees.</member> > + <member>Discuss new log items for atomic updates.</member> > + </simplelist> > + </revdescription> > + </revision> > </revhistory> > diff --git a/design/XFS_Filesystem_Structure/journaling_log.asciidoc b/design/XFS_Filesystem_Structure/journaling_log.asciidoc > index 67d209f..0fbbcee 100644 > --- a/design/XFS_Filesystem_Structure/journaling_log.asciidoc > +++ b/design/XFS_Filesystem_Structure/journaling_log.asciidoc > @@ -209,6 +209,8 @@ magic number to distinguish themselves. Buffer data items only appear after > | +XFS_LI_DQUOT+ | 0x123d | xref:Quota_Update_Log_Item[Update Quota] > | +XFS_LI_QUOTAOFF+ | 0x123e | xref:Quota_Off_Log_Item[Quota Off] > | +XFS_LI_ICREATE+ | 0x123f | xref:Inode_Create_Log_Item[Inode Creation] > +| +XFS_LI_RUI+ | 0x1240 | xref:RUI_Log_Item[Reverse Mapping Update Intent] > +| +XFS_LI_RUD+ | 0x1241 | xref:RUD_Log_Item[Reverse Mapping Update Done] > |===== > > [[Log_Transaction_Headers]] > @@ -386,6 +388,134 @@ Variable-length array of extents to be freed. The array length is given by > +xfs_extent_32_t+; this can be determined from the log item size (+oh_len+) and > the number of extents (+efd_nextents+). > > +[[RUI_Log_Item]] > +=== Reverse Mapping Updates Intent > + > +The next two operation types work together to handle deferred reverse mapping > +updates. Naturally, the mappings to be updated can be expressed in terms of > +mapping extents: > + > +[source, c] > +---- > +struct xfs_map_extent { > + __uint64_t me_owner; > + __uint64_t me_startblock; > + __uint64_t me_startoff; > + __uint32_t me_len; > + __uint32_t me_flags; > +}; > +---- > + > +*me_owner*:: > +Owner of this reverse mapping. See the values in the section about > +xref:Reverse_Mapping_Btree[reverse mapping] for more information. > + > +*me_startblock*:: > +Filesystem block of this mapping. > + > +*me_startoff*:: > +Logical block offset of this mapping. > + > +*me_len*:: > +The length of this mapping. > + > +*me_flags*:: > +The lower byte of this field is a type code indicating what sort of > +reverse mapping operation we want. The upper three bytes are flag bits. > + > +.Reverse mapping update log intent types > +[options="header"] > +|===== > +| Value | Description > +| +XFS_RMAP_EXTENT_MAP+ | Add a reverse mapping for file data. > +| +XFS_RMAP_EXTENT_MAP_SHARED+ | Add a reverse mapping for file data for a file with shared blocks. > +| +XFS_RMAP_EXTENT_UNMAP+ | Remove a reverse mapping for file data. > +| +XFS_RMAP_EXTENT_UNMAP_SHARED+ | Remove a reverse mapping for file data for a file with shared blocks. > +| +XFS_RMAP_EXTENT_CONVERT+ | Convert a reverse mapping for file data between unwritten and normal. > +| +XFS_RMAP_EXTENT_CONVERT_SHARED+ | Convert a reverse mapping for file data between unwritten and normal for a file with shared blocks. > +| +XFS_RMAP_EXTENT_ALLOC+ | Add a reverse mapping for non-file data. > +| +XFS_RMAP_EXTENT_FREE+ | Remove a reverse mapping for non-file data. > +|===== > + > +.Reverse mapping update log intent flags > +[options="header"] > +|===== > +| Value | Description > +| +XFS_RMAP_EXTENT_ATTR_FORK+ | Extent is for the attribute fork. > +| +XFS_RMAP_EXTENT_BMBT_BLOCK+ | Extent is for a block mapping btree block. > +| +XFS_RMAP_EXTENT_UNWRITTEN+ | Extent is unwritten. > +|===== > + > +The ``rmap update intent'' operation comes first; it tells the log that XFS > +wants to update some reverse mappings. This record is crucial for correct log > +recovery because it enables us to spread a complex metadata update across > +multiple transactions while ensuring that a crash midway through the complex > +update will be replayed fully during log recovery. > + > +[source, c] > +---- > +struct xfs_rui_log_format { > + __uint16_t rui_type; > + __uint16_t rui_size; > + __uint32_t rui_nextents; > + __uint64_t rui_id; > + struct xfs_map_extent rui_extents[1]; > +}; > +---- > + > +*rui_type*:: > +The signature of an RUI operation, 0x1240. This value is in host-endian order, > +not big-endian like the rest of XFS. > + > +*rui_size*:: > +Size of this log item. Should be 1. > + > +*rui_nextents*:: > +Number of reverse mappings. > + > +*rui_id*:: > +A 64-bit number that binds the corresponding RUD log item to this RUI log item. > + > +*rui_extents*:: > +Variable-length array of reverse mappings to update. > + > +[[RUD_Log_Item]] > +=== Completion of Reverse Mapping Updates > + > +The ``reverse mapping update done'' operation complements the ``reverse mapping > +update intent'' operation. This second operation indicates that the update > +actually happened, so that log recovery needn't replay the update. The RUD and > +the actual updates are typically found in a new transaction following the > +transaction in which the RUI was logged. > + > +[source, c] > +---- > +struct xfs_rud_log_format { > + __uint16_t rud_type; > + __uint16_t rud_size; > + __uint32_t rud_nextents; > + __uint64_t rud_rui_id; > + struct xfs_map_extent rud_extents[1]; > +}; > +---- > + > +*rud_type*:: > +The signature of an RUD operation, 0x1241. This value is in host-endian order, > +not big-endian like the rest of XFS. > + > +*rud_size*:: > +Size of this log item. Should be 1. > + > +*rud_nextents*:: > +Number of reverse mappings. > + > +*rud_id*:: > +A 64-bit number that binds the corresponding RUI log item to this RUD log item. > + > +*rud_extents*:: > +Variable-length array of reverse mappings. The array length is given by > ++rud_nextents+. > + > [[Inode_Log_Item]] > === Inode Updates > > diff --git a/design/XFS_Filesystem_Structure/magic.asciidoc b/design/XFS_Filesystem_Structure/magic.asciidoc > index 301cfa0..10fd15f 100644 > --- a/design/XFS_Filesystem_Structure/magic.asciidoc > +++ b/design/XFS_Filesystem_Structure/magic.asciidoc > @@ -44,6 +44,7 @@ relevant chapters. Magic numbers tend to have consistent locations: > | +XFS_ATTR_LEAF_MAGIC+ | 0xfbee | | xref:Leaf_Attributes[Leaf Attribute] > | +XFS_ATTR3_LEAF_MAGIC+ | 0x3bee | | xref:Leaf_Attributes[Leaf Attribute], v5 only > | +XFS_ATTR3_RMT_MAGIC+ | 0x5841524d | XARM | xref:Remote_Values[Remote Attribute Value], v5 only > +| +XFS_RMAP_CRC_MAGIC+ | 0x524d4233 | RMB3 | xref:Reverse_Mapping_Btree[Reverse Mapping B+tree], v5 only > |===== > > The magic numbers for log items are at offset zero in each log item, but items > @@ -61,6 +62,8 @@ are not aligned to blocks. > | +XFS_LI_DQUOT+ | 0x123d | | xref:Quota_Update_Log_Item[Update Quota Log Item] > | +XFS_LI_QUOTAOFF+ | 0x123e | | xref:Quota_Off_Log_Item[Quota Off Log Item] > | +XFS_LI_ICREATE+ | 0x123f | | xref:Inode_Create_Log_Item[Inode Creation Log Item] > +| +XFS_LI_RUI+ | 0x1240 | | xref:RUI_Log_Item[Reverse Mapping Update Intent] > +| +XFS_LI_RUD+ | 0x1241 | | xref:RUD_Log_Item[Reverse Mapping Update Done] > |===== > > = Theoretical Limits > diff --git a/design/XFS_Filesystem_Structure/reconstruction.asciidoc b/design/XFS_Filesystem_Structure/reconstruction.asciidoc > new file mode 100644 > index 0000000..f172e0f > --- /dev/null > +++ b/design/XFS_Filesystem_Structure/reconstruction.asciidoc > @@ -0,0 +1,53 @@ > +[[Reconstruction]] > += Metadata Reconstruction > + > +[NOTE] > +This is a theoretical discussion of how reconstruction could work; none of this > +is implemented as of 2015. > + > +A simple UNIX filesystem can be thought of in terms of a directed acyclic graph. > +To a first approximation, there exists a root directory node, which points to > +other nodes. Those other nodes can themselves be directories or they can be > +files. Each file, in turn, points to data blocks. > + > +XFS adds a few more details to this picture: > + > +* The real root(s) of an XFS filesystem are the allocation group headers > +(superblock, AGF, AGI, AGFL). > +* Each allocation group’s headers point to various per-AG B+trees (free space, > +inode, free inodes, free list, etc.) > +* The free space B+trees point to unused extents; > +* The inode B+trees point to blocks containing inode chunks; > +* All superblocks point to the root directory and the log; > +* Hardlinks mean that multiple directories can point to a single file node; > +* File data block pointers are indexed by file offset; > +* Files and directories can have a second collection of pointers to data blocks > +which contain extended attributes; > +* Large directories require multiple data blocks to store all the subpointers; > +* Still larger directories use high-offset data blocks to store a B+tree of > +hashes to directory entries; > +* Large extended attribute forks similarly use high-offset data blocks to store > +a B+tree of hashes to attribute keys; and > +* Symbolic links can point to data blocks. > + > +The beauty of this massive graph structure is that under normal circumstances, > +everything known to the filesystem is discoverable (access controls > +notwithstanding) from the root. The major weakness of this structure of course > +is that breaking a edge in the graph can render entire subtrees inaccessible. > ++xfs_repair+ “recovers” from broken directories by scanning for unlinked inodes > +and connecting them to +/lost+found+, but this isn’t sufficiently general to > +recover from breaks in other parts of the graph structure. Wouldn’t it be > +useful to have back pointers as a secondary data structure? The current repair > +strategy is to reconstruct whatever can be rebuilt, but to scrap anything that > +doesn't check out. > + > +The xref:Reverse_Mapping_Btree[reverse-mapping B+tree] fills in part of the > +puzzle. Since it contains copies of every entry in each inode’s data and > +attribute forks, we can fix a corrupted block map with these records. > +Furthermore, if the inode B+trees become corrupt, it is possible to visit all > +inode chunks using the reverse-mapping data. Should XFS ever gain the ability > +to store parent directory information in each inode, it also becomes possible > +to resurrect damaged directory trees, which should reduce the complaints about > +inodes ending up in +/lost+found+. Everything else in the per-AG primary > +metadata can already be reconstructed via +xfs_repair+. Hopefully, > +reconstruction will not turn out to be a fool's errand. > diff --git a/design/XFS_Filesystem_Structure/rmapbt.asciidoc b/design/XFS_Filesystem_Structure/rmapbt.asciidoc > new file mode 100644 > index 0000000..a8a210b > --- /dev/null > +++ b/design/XFS_Filesystem_Structure/rmapbt.asciidoc > @@ -0,0 +1,305 @@ > +[[Reverse_Mapping_Btree]] > +== Reverse-Mapping B+tree > + > +[NOTE] > +This data structure is under construction! Details may change. > + > +If the feature is enabled, each allocation group has its own reverse > +block-mapping B+tree, which grows in the free space like the free space > +B+trees. As mentioned in the chapter about > +xref:Reconstruction[reconstruction], this data structure is another piece of > +the puzzle necessary to reconstruct the data or attribute fork of a file from > +reverse-mapping records; we can also use it to double-check allocations to > +ensure that we are not accidentally cross-linking blocks, which can cause > +severe damage to the filesystem. > + > +This B+tree is only present if the +XFS_SB_FEAT_RO_COMPAT_RMAPBT+ > +feature is enabled. The feature requires a version 5 filesystem. > + > +Each record in the reverse-mapping B+tree has the following structure: > + > +[source, c] > +---- > +struct xfs_rmap_rec { > + __be32 rm_startblock; > + __be32 rm_blockcount; > + __be64 rm_owner; > + __be64 rm_fork:1; > + __be64 rm_bmbt:1; > + __be64 rm_unwritten:1; > + __be64 rm_unused:7; > + __be64 rm_offset:54; > +}; > +---- > + > +*rm_startblock*:: > +AG block number of this record. > + > +*rm_blockcount*:: > +The length of this extent. > + > +*rm_owner*:: > +A 64-bit number describing the owner of this extent. This is typically the > +absolute inode number, but can also correspond to one of the following: > + > +.Special owner values > +[options="header"] > +|===== > +| Value | Description > +| +XFS_RMAP_OWN_NULL+ | No owner. This should never appear on disk. > +| +XFS_RMAP_OWN_UNKNOWN+ | Unknown owner; for EFI recovery. This should never appear on disk. > +| +XFS_RMAP_OWN_FS+ | Allocation group headers > +| +XFS_RMAP_OWN_LOG+ | XFS log blocks > +| +XFS_RMAP_OWN_AG+ | Per-allocation group B+tree blocks. This means free space B+tree blocks, blocks on the freelist, and reverse-mapping B+tree blocks. > +| +XFS_RMAP_OWN_INOBT+ | Per-allocation group inode B+tree blocks. This includes free inode B+tree blocks. > +| +XFS_RMAP_OWN_INODES+ | Inode chunks > +|===== > + > +*rm_fork*:: > +If +rm_owner+ describes an inode, this can be 1 if this record is for an > +attribute fork. > + > +*rm_bmbt*:: > +If +rm_owner+ describes an inode, this can be 1 to signify that this record is > +for a block map B+tree block. In this case, +rm_offset+ has no meaning. > + > +*rm_unwritten*:: > +A flag indicating that the extent is unwritten. This corresponds to the flag in > +the xref:Data_Extents[extent record] format which means +XFS_EXT_UNWRITTEN+. > + > +*rm_offset*:: > +The 54-bit logical file block offset, if +rm_owner+ describes an inode. > +Meaningless otherwise. > + > +[NOTE] > +The single-bit flag values +rm_unwritten+, +rm_fork+, and +rm_bmbt+ are packed > +into the larger fields in the C structure definition. > + > +The key has the following structure: > + > +[source, c] > +---- > +struct xfs_rmap_key { > + __be32 rm_startblock; > + __be64 rm_owner; > + __be64 rm_fork:1; > + __be64 rm_bmbt:1; > + __be64 rm_reserved:1; > + __be64 rm_unused:7; > + __be64 rm_offset:54; > +}; > +---- > + > +For the reverse-mapping B+tree on a filesystem that supports sharing of file > +data blocks, the key definition is larger than the usual AG block number. On a > +classic XFS filesystem, each block has only one owner, which means that > ++rm_startblock+ is sufficient to uniquely identify each record. However, > +shared block support (reflink) on XFS breaks that assumption; now filesystem > +blocks can be linked to any logical block offset of any file inode. Therefore, > +the key must include the owner and offset information to preserve the 1 to 1 > +relation between key and record. > + > +* As the reference counting is AG relative, all the block numbers are only > +32-bits. > +* The +bb_magic+ value is "RMB3" (0x524d4233). > +* The +xfs_btree_sblock_t+ header is used for intermediate B+tree node as well > +as the leaves. > +* Each pointer is associated with two keys. The first of these is the "low > +key", which is the key of the smallest record accessible through the pointer. > +This low key has the same meaning as the key in all other btrees. The second > +key is the high key, which is the maximum of the largest key that can be used > +to access a given record underneath the pointer. Recall that each record > +in the reverse mapping b+tree describes an interval of physical blocks mapped > +to an interval of logical file block offsets; therefore, it makes sense that > +a range of keys can be used to find to a record. > + > +=== xfs_db rmapbt Example > + > +This example shows a reverse-mapping B+tree from a freshly populated root > +filesystem: > + > +---- > +xfs_db> agf 0 > +xfs_db> addr rmaproot > +xfs_db> p > +magic = 0x524d4233 > +level = 1 > +numrecs = 43 > +leftsib = null > +rightsib = null > +bno = 56 > +lsn = 0x3000004c8 > +uuid = 1977221d-8345-464e-b1f4-aa2ea36895f4 > +owner = 0 > +crc = 0x7cf8be6f (correct) > +keys[1-43] = [startblock,owner,offset] > +keys[1-43] = [startblock,owner,offset,attrfork,bmbtblock,startblock_hi,owner_hi, > + offset_hi,attrfork_hi,bmbtblock_hi] > + 1:[0,-3,0,0,0,351,4418,66,0,0] > + 2:[417,285,0,0,0,827,4419,2,0,0] > + 3:[829,499,0,0,0,2352,573,55,0,0] > + 4:[1292,710,0,0,0,32168,262923,47,0,0] > + 5:[32215,-5,0,0,0,34655,2365,3411,0,0] > + 6:[34083,1161,0,0,0,34895,265220,1,0,1] > + 7:[34896,256191,0,0,0,36522,-9,0,0,0] > + ... > + 41:[50998,326734,0,0,0,51430,-5,0,0,0] > + 42:[51431,327010,0,0,0,51600,325722,11,0,0] > + 43:[51611,327112,0,0,0,94063,23522,28375272,0,0] > +ptrs[1-43] = 1:5 2:6 3:8 4:9 5:10 6:11 7:418 ... 41:46377 42:48784 43:49522 > +---- > + > +We arbitrarily pick pointer 17 to traverse downwards: > + > +---- > +xfs_db> addr ptrs[17] > +xfs_db> p > +magic = 0x524d4233 > +level = 0 > +numrecs = 168 > +leftsib = 36284 > +rightsib = 37617 > +bno = 294760 > +lsn = 0x200002761 > +uuid = 1977221d-8345-464e-b1f4-aa2ea36895f4 > +owner = 0 > +crc = 0x2dad3fbe (correct) > +recs[1-168] = [startblock,blockcount,owner,offset,extentflag,attrfork,bmbtblock] > + 1:[40326,1,259615,0,0,0,0] 2:[40327,1,-5,0,0,0,0] > + 3:[40328,2,259618,0,0,0,0] 4:[40330,1,259619,0,0,0,0] > + ... > + 127:[40540,1,324266,0,0,0,0] 128:[40541,1,324266,8388608,0,0,0] > + 129:[40542,2,324266,1,0,0,0] 130:[40544,32,-7,0,0,0,0] > +---- > + > +Several interesting things pop out here. The first record shows that inode > +259,615 has mapped AG block 40,326 at offset 0. We confirm this by looking at > +the block map for that inode: > + > +---- > +xfs_db> inode 259615 > +xfs_db> bmap > +data offset 0 startblock 40326 (0/40326) count 1 flag 0 > +---- > + > +Next, notice records 127 and 128, which describe neighboring AG blocks that are > +mapped to non-contiguous logical blocks in inode 324,266. Given the logical > +offset of 8,388,608 we surmise that this is a leaf directory, but let us > +confirm: > + > +---- > +xfs_db> inode 324266 > +xfs_db> p core.mode > +core.mode = 040755 > +xfs_db> bmap > +data offset 0 startblock 40540 (0/40540) count 1 flag 0 > +data offset 1 startblock 40542 (0/40542) count 2 flag 0 > +data offset 3 startblock 40576 (0/40576) count 1 flag 0 > +data offset 8388608 startblock 40541 (0/40541) count 1 flag 0 > +xfs_db> p core.mode > +core.mode = 0100644 > +xfs_db> dblock 0 > +xfs_db> p dhdr.hdr.magic > +dhdr.hdr.magic = 0x58444433 > +xfs_db> dblock 8388608 > +xfs_db> p lhdr.info.hdr.magic > +lhdr.info.hdr.magic = 0x3df1 > +---- > + > +Indeed, this inode 324,266 appears to be a leaf directory, as it has regular > +directory data blocks at low offsets, and a single leaf block. > + > +Notice further the two reverse-mapping records with negative owners. An owner > +of -7 corresponds to +XFS_RMAP_OWN_INODES+, which is an inode chunk, and an > +owner code of -5 corresponds to +XFS_RMAP_OWN_AG+, which covers free space > +B+trees and free space. Let's see if block 40,544 is part of an inode chunk: > + > +---- > +xfs_db> blockget > +xfs_db> fsblock 40544 > +xfs_db> blockuse > +block 40544 (0/40544) type inode > +xfs_db> stack > +1: > + byte offset 166068224, length 4096 > + buffer block 324352 (fsbno 40544), 8 bbs > + inode 324266, dir inode 324266, type data > +xfs_db> type inode > +xfs_db> p > +core.magic = 0x494e > +---- > + > +Our suspicions are confirmed. Let's also see if 40,327 is part of a free space > +tree: > + > +---- > +xfs_db> fsblock 40327 > +xfs_db> blockuse > +block 40327 (0/40327) type btrmap > +xfs_db> type rmapbt > +xfs_db> p > +magic = 0x524d4233 > +---- > + > +As you can see, the reverse block-mapping B+tree is an important secondary > +metadata structure, which can be used to reconstruct damaged primary metadata. > +Now let's look at an extend rmap btree: > + > +---- > +xfs_db> agf 0 > +xfs_db> addr rmaproot > +xfs_db> p > +magic = 0x34524d42 > +level = 1 > +numrecs = 5 > +leftsib = null > +rightsib = null > +bno = 6368 > +lsn = 0x100000d1b > +uuid = 400f0928-6b88-4c37-af1e-cef1f8911f3f > +owner = 0 > +crc = 0x8d4ace05 (correct) > +keys[1-5] = [startblock,owner,offset,attrfork,bmbtblock,startblock_hi,owner_hi,offset_hi,attrfork_hi,bmbtblock_hi] > +1:[0,-3,0,0,0,705,132,681,0,0] > +2:[24,5761,0,0,0,548,5761,524,0,0] > +3:[24,5929,0,0,0,380,5929,356,0,0] > +4:[24,6097,0,0,0,212,6097,188,0,0] > +5:[24,6277,0,0,0,807,-7,0,0,0] > +ptrs[1-5] = 1:5 2:771 3:9 4:10 5:11 > +---- > + > +The second pointer stores both the low key [24,5761,0,0,0] and the high key > +[548,5761,524,0,0], which means that we can expect block 771 to contain records > +starting at physical block 24, inode 5761, offset zero; and that one of the > +records can be used to find a reverse mapping for physical block 548, inode > +5761, and offset 524: > + > +---- > +xfs_db> addr ptrs[2] > +xfs_db> p > +magic = 0x34524d42 > +level = 0 > +numrecs = 168 > +leftsib = 5 > +rightsib = 9 > +bno = 6168 > +lsn = 0x100000d1b > +uuid = 400f0928-6b88-4c37-af1e-cef1f8911f3f > +owner = 0 > +crc = 0xd58eff0e (correct) > +recs[1-168] = [startblock,blockcount,owner,offset,extentflag,attrfork,bmbtblock] > +1:[24,525,5761,0,0,0,0] > +2:[24,524,5762,0,0,0,0] > +3:[24,523,5763,0,0,0,0] > +... > +166:[24,360,5926,0,0,0,0] > +167:[24,359,5927,0,0,0,0] > +168:[24,358,5928,0,0,0,0] > +---- > + > +Observe that the first record in the block starts at physical block 24, inode > +5761, offset zero, just as we expected. Note that this first record is also > +indexed by the highest key as provided in the node block; physical block 548, > +inode 5761, offset 524 is the very last block mapped by this record. Furthermore, > +note that record 168, despite being the last record in this block, has a lower > +maximum key (physical block 382, inode 5928, offset 23) than the first record. > diff --git a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc > index 62502b3..1b8658d 100644 > --- a/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc > +++ b/design/XFS_Filesystem_Structure/xfs_filesystem_structure.asciidoc > @@ -48,6 +48,8 @@ include::overview.asciidoc[] > > include::metadata_integrity.asciidoc[] > > +include::reconstruction.asciidoc[] > + > include::common_types.asciidoc[] > > include::magic.asciidoc[] > @@ -66,6 +68,8 @@ include::btrees.asciidoc[] > > include::allocation_groups.asciidoc[] > > +include::rmapbt.asciidoc[] > + > include::journaling_log.asciidoc[] > > include::internal_inodes.asciidoc[] > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs -- Carlos From Martinezant2141@live.com Wed Jun 29 13:48:40 2016 Return-Path: <Martinezant2141@live.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_MESSAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id C05027CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 13:48:40 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 4845AAC005 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 11:48:37 -0700 (PDT) X-ASG-Debug-ID: 1467226110-04bdf074b71ffc00001-NocioJ Received: from SNT004-OMC1S28.hotmail.com (snt004-omc1s28.hotmail.com [65.55.90.39]) by cuda.sgi.com with ESMTP id RsQADCCmyEpEfgan (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 11:48:31 -0700 (PDT) X-Barracuda-Envelope-From: Martinezant2141@live.com X-Barracuda-Effective-Source-IP: snt004-omc1s28.hotmail.com[65.55.90.39] X-Barracuda-Apparent-Source-IP: 65.55.90.39 Received: from NAM01-BN3-obe.outbound.protection.outlook.com ([65.55.90.7]) by SNT004-OMC1S28.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Wed, 29 Jun 2016 11:48:31 -0700 Received: from BN3NAM01FT032.eop-nam01.prod.protection.outlook.com (10.152.66.55) by BN3NAM01HT231.eop-nam01.prod.protection.outlook.com (10.152.67.10) with Microsoft SMTP Server (TLS) id 15.1.523.9; Wed, 29 Jun 2016 18:48:29 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com (10.152.66.57) by BN3NAM01FT032.mail.protection.outlook.com (10.152.67.233) with Microsoft SMTP Server (TLS) id 15.1.523.9 via Frontend Transport; Wed, 29 Jun 2016 18:48:29 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) by SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) with mapi id 15.01.0523.024; Wed, 29 Jun 2016 18:48:29 +0000 From: Anthony l <Martinezant2141@live.com> To: "xfs@oss.sgi.com" <xfs@oss.sgi.com> Subject: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Topic: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) X-ASG-Orig-Subj: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Index: AQHR0jAXIVEyd//VeEGYMdUD0l4C3g== Date: Wed, 29 Jun 2016 18:48:29 +0000 Message-ID: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=softfail (sender IP is 25.152.66.57) smtp.mailfrom=live.com; oss.sgi.com; dkim=none (message not signed) header.d=none;oss.sgi.com; dmarc=none action=none header.from=live.com; received-spf: SoftFail (protection.outlook.com: domain of transitioning live.com discourages use of 25.152.66.57 as permitted sender) x-tmn: [Nj2qviwx8AMUwYL787NGijA3TmfEIkU+] x-eopattributedmessage: 0 x-forefront-antispam-report: EFV:NLI;SFV:NSPM;SFS:(10019020)(98900003);DIR:OUT;SFP:1102;SCL:1;SRVR:BN3NAM01HT231;H:SN1PR05MB2317.namprd05.prod.outlook.com;FPR:;SPF:None;CAT:NONE;LANG:en;CAT:NONE; x-ms-office365-filtering-correlation-id: 2e7dd3d2-5807-46a5-592b-08d3a04df635 x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:(1601124038)(5061506196)(5061507196)(1603103041)(1601125047);SRVR:BN3NAM01HT231; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(432015012)(82015046);SRVR:BN3NAM01HT231;BCL:0;PCL:0;RULEID:;SRVR:BN3NAM01HT231; x-forefront-prvs: 09888BC01D Content-Type: multipart/alternative; boundary="_000_SN1PR05MB231785E5196A5D31D0D833EACC230SN1PR05MB2317namp_" MIME-Version: 1.0 X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-originalarrivaltime: 29 Jun 2016 18:48:29.0317 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3NAM01HT231 X-OriginalArrivalTime: 29 Jun 2016 18:48:31.0005 (UTC) FILETIME=[D4C2ACD0:01D1D236] X-Barracuda-Connect: snt004-omc1s28.hotmail.com[65.55.90.39] X-Barracuda-Start-Time: 1467226111 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5635 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30873 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 HTML_MESSAGE BODY: HTML included in message --_000_SN1PR05MB231785E5196A5D31D0D833EACC230SN1PR05MB2317namp_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Hello Anthony here, I'm not sure if this is the correct place to send a question, If I am wrong= I would appreciate if you could send me in the right direction. I have co= me across the oss.sgi forums a lot looking for a solution to my problem but= I could not find much. Here's my situation. I have a bunch a tapes that were created way back when using an IRIX system= . Some kind of version 6, perhaps even the latest version. anyway I am able= to peak at the headers to determind the the file type on the drive is inde= ed: xFSdump0.... or when I make a sample using 'dd if=3D/dev/nst0 of=3D./test= .img' '+ 'file test.img' I get XFSDUMP archive (version 2) So, instinctively to get the data off the tapes I would think would be as s= imple as: sudo xfsrestore -f /dev/nst0 ./path to where I want it stored Then I get: using dump format 3 xfsrestore: searching media for dump xfsrestore: preparing drive xfsrestore: examining media file 1 ... xfsrestore examining media file xx the following dump has been found on drive 0: hostname: isp---------(stuff) mount point: /isp-iga volume: /dev/rdsk/sks0d2s7 session time: Mon Jan 10 11:47:42 2005 media label: "backup" file system id: xxx.... session id: xxx... media id:... restore this dump? 1: skip 2: restore (default) > 2 (enter) =3D=3D=3D=3D=3D=3D examining media file 0 reading directories examining media file 1 reading directories ... and so on no files selected for restoral =3D=3D=3D=3D 1: media change declined (timeout 3600 seconds) 2: display media inventory status 3: list needed media objects 4: change media (default) 3 and 4 do nothing I get no media needed. and If I press 4 same menu comes back. 2: media file xxx (xxx) where xxx is a number used for directory restoral first extent contained: ino xxxxxxxxxxxx off 0 next extent to restore: ino (same as above) off 0 and If I click 1: restoral interrupted use -R restore summery: stream 0: /dev/nst0 quit media no longer usable restore status: QUIT Then if I got to the directory where I pointed all I have is: orphanage/ xfsrestorehelperblahblah/ where orphangae is empty and the other contains like 5 files that are just = something else. What am I doing wrong here ?? any help would be great. Thanks --_000_SN1PR05MB231785E5196A5D31D0D833EACC230SN1PR05MB2317namp_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-8859-= 1"> <style type=3D"text/css" style=3D"display:none;"><!-- P {margin-top:0;margi= n-bottom:0;} --></style> </head> <body dir=3D"ltr"> <div id=3D"divtagdefaultwrapper" style=3D"font-size:12pt;color:#000000;back= ground-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;"> <p>Hello Anthony here,</p> <p>I'm not sure if this is the correct place to send a question, If I am wr= ong I would appreciate if you could send me in the right direction.  I= have come across the oss.sgi forums a lot looking for a solution to my pro= blem but I could not find much. </p> <p><br> </p> <p>Here's my situation.</p> <p>I have a bunch a tapes that were created way back when using an IRIX sys= tem. Some kind of version 6, perhaps even the latest version. anyway I am a= ble to peak at the headers to determind the the file type on the drive is i= ndeed:</p> <p>xFSdump0....   or when I make a sample using 'dd if=3D/dev/nst0 of= =3D./test.img' '+ 'file test.img' I get XFSDUMP archive (version 2)</p> <p>So, instinctively to get the data off the tapes I would think would be a= s simple as:</p> <p>sudo xfsrestore -f /dev/nst0 ./path to where I want it stored</p> <p>Then I get: </p> <p>using dump format 3</p> <p>xfsrestore: searching media for dump</p> <p>xfsrestore: preparing drive</p> <p>xfsrestore: examining media file 1</p> <p>...</p> <p>xfsrestore examining media file xx</p> <p>the following dump has been found on drive 0:</p> <p>hostname: isp---------(stuff)</p> <p>mount point: /isp-iga</p> <p>volume: /dev/rdsk/sks0d2s7</p> <p>session time: Mon Jan 10 11:47:42 2005</p> <p>media label: "backup"</p> <p>file system id: xxx....</p> <p>session id: xxx...</p> <p>media id:...</p> <p>restore this dump?</p> <p>1: skip</p> <p>2: restore (default)</p> <p>> 2 (enter)</p> <p><br> </p> <p>=3D=3D=3D=3D=3D=3D </p> <p>examining media file 0</p> <p>reading directories</p> <p>examining media file 1</p> <p>reading directories</p> <p>... and so on</p> <p>no files selected for restoral</p> <p><br> </p> <p><br> </p> <p>=3D=3D=3D=3D</p> <p>1: media change declined (timeout 3600 seconds)</p> <p>2: display media inventory status</p> <p>3: list needed media objects</p> <p>4: change media (default) </p> <p><br> </p> <p>3 and 4 do nothing</p> <p>I get no media needed. and If I press 4 same menu comes back. </p> <p>2: media file xxx (xxx) where xxx is a number</p> <p>used for directory restoral </p> <p>first extent contained: ino xxxxxxxxxxxx off 0</p> <p>next extent to restore: ino (same as above) off 0</p> <p><br> </p> <p><br> </p> <p>and If I click 1:</p> <p>restoral interrupted use -R</p> <p>restore summery:</p> <p>stream 0: /dev/nst0 quit media no longer usable</p> <p>restore status: QUIT</p> <p><br> </p> <p>Then if I got to the directory where I pointed all I have is:</p> <p>orphanage/ </p> <p>xfsrestorehelperblahblah/   </p> <p>where orphangae is empty and the other contains like 5 files that are ju= st something else. </p> <p>What am I doing wrong here ?? any help would be great.</p> <p>Thanks</p> <p><br> </p> <p><br> </p> </div> </body> </html> --_000_SN1PR05MB231785E5196A5D31D0D833EACC230SN1PR05MB2317namp_-- From sandeen@sandeen.net Wed Jun 29 14:29:10 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3EE2F7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 14:29:10 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9CADEAC006 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 12:29:09 -0700 (PDT) X-ASG-Debug-ID: 1467228546-04cbb02735379750001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id 1OSDj1yBAiFMSY4R for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 12:29:06 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 6F4A21F1C for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 14:29:06 -0500 (CDT) Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <7e2ec911-1079-2339-b72d-8f86b13d5501@sandeen.net> Date: Wed, 29 Jun 2016 14:29:05 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1467228546 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1984 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30874 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/29/16 1:48 PM, Anthony l wrote: > Hello Anthony here, > > I'm not sure if this is the correct place to send a question, If I am > wrong I would appreciate if you could send me in the right direction. > I have come across the oss.sgi forums a lot looking for a solution to > my problem but I could not find much. > Sure, it's a fine place. Question below. > > Here's my situation. > > I have a bunch a tapes that were created way back when using an IRIX > system. Some kind of version 6, perhaps even the latest version. > anyway I am able to peak at the headers to determind the the file > type on the drive is indeed: > > xFSdump0.... or when I make a sample using 'dd if=/dev/nst0 > of=./test.img' '+ 'file test.img' I get XFSDUMP archive (version 2) > > So, instinctively to get the data off the tapes I would think would > be as simple as: > > sudo xfsrestore -f /dev/nst0 ./path to where I want it stored > > Then I get: > > using dump format 3 > > xfsrestore: searching media for dump > > xfsrestore: preparing drive > > xfsrestore: examining media file 1 > > ... > > xfsrestore examining media file xx > > the following dump has been found on drive 0: > > hostname: isp---------(stuff) > > mount point: /isp-iga > > volume: /dev/rdsk/sks0d2s7 > > session time: Mon Jan 10 11:47:42 2005 > > media label: "backup" > > file system id: xxx.... > > session id: xxx... > > media id:... > > restore this dump? > > 1: skip > > 2: restore (default) > >> 2 (enter) > > ====== > > examining media file 0 > reading directories > examining media file 1 > reading directories > ... and so on > no files selected for restoral That doesn't seem to be an actual xfsdump error string, is it? Maybe you can capture and include the entire xfsdump output, or put it in a pastebin somewhere? By the time things get hand-transcribed it's easy to lose important bits. -Eric From darrick.wong@oracle.com Wed Jun 29 15:02:50 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 4861F7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 15:02:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 173438F8049 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 13:02:47 -0700 (PDT) X-ASG-Debug-ID: 1467230561-04cb6c063e296fd0001-NocioJ Received: from userp1040.oracle.com (userp1040.oracle.com [156.151.31.81]) by cuda.sgi.com with ESMTP id y9ClNiR1eJqe2Uii (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 13:02:42 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: userp1040.oracle.com[156.151.31.81] X-Barracuda-Apparent-Source-IP: 156.151.31.81 Received: from userv0022.oracle.com (userv0022.oracle.com [156.151.31.74]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5TK2bsA005337 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 29 Jun 2016 20:02:37 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0022.oracle.com (8.14.4/8.13.8) with ESMTP id u5TK2bI7003591 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 29 Jun 2016 20:02:37 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5TK2alE020458; Wed, 29 Jun 2016 20:02:36 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 29 Jun 2016 13:02:35 -0700 Date: Wed, 29 Jun 2016 13:02:34 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: Dave Chinner <david@fromorbit.com> Cc: xfs@oss.sgi.com Subject: [PATCH] xfs: lock the rt summary inode when unmapping realtime extents Message-ID: <20160629200234.GE4917@birch.djwong.org> X-ASG-Orig-Subj: [PATCH] xfs: lock the rt summary inode when unmapping realtime extents MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0022.oracle.com [156.151.31.74] X-Barracuda-Connect: userp1040.oracle.com[156.151.31.81] X-Barracuda-Start-Time: 1467230562 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 804 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30876 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines When we're deleting realtime extents, lock the summary inode in case we need to update the summary info. This prevents an assert on the rsumip inode lock on a debug kernel. (Same idea as "xfs: lock rt summary inode on allocation".) Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> --- fs/xfs/libxfs/xfs_bmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 97820c1..9c7227b 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5524,6 +5524,8 @@ __xfs_bunmapi( */ xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); + xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); } extno = 0; From sandeen@sandeen.net Wed Jun 29 15:20:58 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1FEBA7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 15:20:58 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8EF4BAC005 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 13:20:54 -0700 (PDT) X-ASG-Debug-ID: 1467231649-04cbb0273737c0b0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id 1uFHMrYznNCVpc9N for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 13:20:50 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id B97241F1C for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 15:20:49 -0500 (CDT) Subject: Re: [PATCH] xfs: lock the rt summary inode when unmapping realtime extents To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: [PATCH] xfs: lock the rt summary inode when unmapping realtime extents References: <20160629200234.GE4917@birch.djwong.org> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <873055fd-2642-a95e-102a-40dab76ab698@sandeen.net> Date: Wed, 29 Jun 2016 15:20:49 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160629200234.GE4917@birch.djwong.org> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1467231650 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1160 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30876 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/29/16 3:02 PM, Darrick J. Wong wrote: > When we're deleting realtime extents, lock the summary inode > in case we need to update the summary info. This prevents an > assert on the rsumip inode lock on a debug kernel. > > (Same idea as "xfs: lock rt summary inode on allocation".) > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Makes sense to me; I wonder how/when/why this is/got/was broken.... Reviewed-by: Eric Sandeen <sandeen@redhat.com> > --- > fs/xfs/libxfs/xfs_bmap.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c > index 97820c1..9c7227b 100644 > --- a/fs/xfs/libxfs/xfs_bmap.c > +++ b/fs/xfs/libxfs/xfs_bmap.c > @@ -5524,6 +5524,8 @@ __xfs_bunmapi( > */ > xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); > + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); > + xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); > } > > extno = 0; > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs > From david@fromorbit.com Wed Jun 29 17:17:57 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id F346E7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 17:17:56 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id B848B8F8040 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 15:17:53 -0700 (PDT) X-ASG-Debug-ID: 1467238670-04cbb0273637ff80001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id 4EFmTG1UOjYfPIcz for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 15:17:50 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CkLAD0R3RXIHvHLHlbgz6BU4ZvnXsGjEeKEIYSBAICgTM9EAEBAQEBAQEGAQEBAQEBQEBBAQQLAYN6AQEBAwE6HCMFCwgDGAklDwUlAwcaExuIDQfDKAELJR6FQoUVhAmGEgWZBY40jy+QAzWEISoygRGGOIF/AQEB Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail05.adl6.internode.on.net with ESMTP; 30 Jun 2016 07:47:49 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bINnp-0004ZX-2m; Thu, 30 Jun 2016 08:17:49 +1000 Date: Thu, 30 Jun 2016 08:17:49 +1000 From: Dave Chinner <david@fromorbit.com> To: Anthony l <Martinezant2141@live.com> Cc: "xfs@oss.sgi.com" <xfs@oss.sgi.com> Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Message-ID: <20160629221749.GP12670@dastard> X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1467238670 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1199 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30880 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 29, 2016 at 06:48:29PM +0000, Anthony l wrote: > Hello Anthony here, > > I'm not sure if this is the correct place to send a question, If I am wrong I would appreciate if you could send me in the right direction. I have come across the oss.sgi forums a lot looking for a solution to my problem but I could not find much. > > > Here's my situation. > > I have a bunch a tapes that were created way back when using an IRIX system. Some kind of version 6, perhaps even the latest version. anyway I am able to peak at the headers to determind the the file type on the drive is indeed: > > xFSdump0.... or when I make a sample using 'dd if=/dev/nst0 of=./test.img' '+ 'file test.img' I get XFSDUMP archive (version 2) dump version 2.... > So, instinctively to get the data off the tapes I would think would be as simple as: > > sudo xfsrestore -f /dev/nst0 ./path to where I want it stored > > Then I get: > > using dump format 3 Oops, wrong format version. > What am I doing wrong here ?? any help would be great. Try telling restore to use dump format version 2 by using the -K option. Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Wed Jun 29 17:21:49 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 8ABF07CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 17:21:49 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 4C60F304039 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 15:21:46 -0700 (PDT) X-ASG-Debug-ID: 1467238903-04bdf074b52094e0001-NocioJ Received: from ipmail05.adl6.internode.on.net (ipmail05.adl6.internode.on.net [150.101.137.143]) by cuda.sgi.com with ESMTP id jfVay85hxJBo2SNQ for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 15:21:44 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Apparent-Source-IP: 150.101.137.143 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2BpEgBJSXRXIHvHLHlbgz6BU4ZvnXsGjEeGBoIPgXuGEgICAQECgTM7EgEBAQEBAQEGAQEBAQEBQECETQEBBCcTHCMQCAMYCSUPBSUDBxoTiC/DIAEBAQcCASQehUKFFYobBZkFjjSBc408hlSJLyUMhCUqMolIAQEB Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail05.adl6.internode.on.net with ESMTP; 30 Jun 2016 07:51:42 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bINra-0004a6-I9; Thu, 30 Jun 2016 08:21:42 +1000 Date: Thu, 30 Jun 2016 08:21:42 +1000 From: Dave Chinner <david@fromorbit.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs: lock the rt summary inode when unmapping realtime extents Message-ID: <20160629222142.GQ12670@dastard> X-ASG-Orig-Subj: Re: [PATCH] xfs: lock the rt summary inode when unmapping realtime extents References: <20160629200234.GE4917@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160629200234.GE4917@birch.djwong.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail05.adl6.internode.on.net[150.101.137.143] X-Barracuda-Start-Time: 1467238903 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1172 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30880 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Wed, Jun 29, 2016 at 01:02:34PM -0700, Darrick J. Wong wrote: > When we're deleting realtime extents, lock the summary inode > in case we need to update the summary info. This prevents an > assert on the rsumip inode lock on a debug kernel. > > (Same idea as "xfs: lock rt summary inode on allocation".) > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > fs/xfs/libxfs/xfs_bmap.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c > index 97820c1..9c7227b 100644 > --- a/fs/xfs/libxfs/xfs_bmap.c > +++ b/fs/xfs/libxfs/xfs_bmap.c > @@ -5524,6 +5524,8 @@ __xfs_bunmapi( > */ > xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, mp->m_rbmip, XFS_ILOCK_EXCL); > + xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL); > + xfs_trans_ijoin(tp, mp->m_rsumip, XFS_ILOCK_EXCL); These need a lockdep annotations, right? i.e. xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP); xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL|XFS_ILOCK_RTSUM); Because they are nested inside the inode ilock? Cheers, Dave. -- Dave Chinner david@fromorbit.com From darrick.wong@oracle.com Wed Jun 29 19:11:50 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id C2CFF7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 19:11:50 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 956BD8F8059 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 17:11:47 -0700 (PDT) X-ASG-Debug-ID: 1467245497-04cb6c063d2a01a0001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id 4eYpaAw3CI02ftCY (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 17:11:37 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5U0BWYx003665 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 30 Jun 2016 00:11:33 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5U0BWcW021357 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 30 Jun 2016 00:11:32 GMT Received: from abhmp0001.oracle.com (abhmp0001.oracle.com [141.146.116.7]) by aserv0122.oracle.com (8.13.8/8.13.8) with ESMTP id u5U0BUTW024055; Thu, 30 Jun 2016 00:11:31 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 29 Jun 2016 17:11:29 -0700 Date: Wed, 29 Jun 2016 17:11:27 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: david@fromorbit.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 020/119] xfs: change xfs_bmap_{finish, cancel, init, free} -> xfs_defer_* Message-ID: <20160630001127.GF4917@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 020/119] xfs: change xfs_bmap_{finish, cancel, init, free} -> xfs_defer_* References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612639995.12839.12854314786533753722.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612639995.12839.12854314786533753722.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: aserv0021.oracle.com [141.146.126.233] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467245497 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 49725 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, MARKETING_SUBJECT, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30882 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.60 MARKETING_SUBJECT Subject contains popular marketing words 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Thu, Jun 16, 2016 at 06:20:00PM -0700, Darrick J. Wong wrote: > Drop the compatibility shims that we were using to integrate the new > deferred operation mechanism into the existing code. No new code. I've since renamed xfs_bmap_free_item to xfs_extent_free_item to better reflect the increased separation between bmap and extent free. --D > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > fs/xfs/libxfs/xfs_attr.c | 58 ++++++++++++++++++------------------ > fs/xfs/libxfs/xfs_attr_remote.c | 14 ++++----- > fs/xfs/libxfs/xfs_bmap.c | 38 ++++++++++++------------ > fs/xfs/libxfs/xfs_bmap.h | 10 +++--- > fs/xfs/libxfs/xfs_btree.h | 5 ++- > fs/xfs/libxfs/xfs_da_btree.h | 4 +-- > fs/xfs/libxfs/xfs_defer.h | 7 ---- > fs/xfs/libxfs/xfs_dir2.c | 6 ++-- > fs/xfs/libxfs/xfs_dir2.h | 8 +++-- > fs/xfs/libxfs/xfs_ialloc.c | 6 ++-- > fs/xfs/libxfs/xfs_ialloc.h | 2 + > fs/xfs/libxfs/xfs_trans_resv.c | 4 +-- > fs/xfs/xfs_bmap_util.c | 28 +++++++++--------- > fs/xfs/xfs_dquot.c | 10 +++--- > fs/xfs/xfs_inode.c | 62 ++++++++++++++++++++------------------- > fs/xfs/xfs_inode.h | 4 +-- > fs/xfs/xfs_iomap.c | 24 ++++++++------- > fs/xfs/xfs_rtalloc.c | 8 +++-- > fs/xfs/xfs_symlink.c | 16 +++++----- > 19 files changed, 154 insertions(+), 160 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c > index 79d3a30..66baf97 100644 > --- a/fs/xfs/libxfs/xfs_attr.c > +++ b/fs/xfs/libxfs/xfs_attr.c > @@ -204,7 +204,7 @@ xfs_attr_set( > { > struct xfs_mount *mp = dp->i_mount; > struct xfs_da_args args; > - struct xfs_bmap_free flist; > + struct xfs_defer_ops flist; > struct xfs_trans_res tres; > xfs_fsblock_t firstblock; > int rsvd = (flags & ATTR_ROOT) != 0; > @@ -317,13 +317,13 @@ xfs_attr_set( > * It won't fit in the shortform, transform to a leaf block. > * GROT: another possible req'mt for a double-split btree op. > */ > - xfs_bmap_init(args.flist, args.firstblock); > + xfs_defer_init(args.flist, args.firstblock); > error = xfs_attr_shortform_to_leaf(&args); > if (!error) > - error = xfs_bmap_finish(&args.trans, args.flist, dp); > + error = xfs_defer_finish(&args.trans, args.flist, dp); > if (error) { > args.trans = NULL; > - xfs_bmap_cancel(&flist); > + xfs_defer_cancel(&flist); > goto out; > } > > @@ -383,7 +383,7 @@ xfs_attr_remove( > { > struct xfs_mount *mp = dp->i_mount; > struct xfs_da_args args; > - struct xfs_bmap_free flist; > + struct xfs_defer_ops flist; > xfs_fsblock_t firstblock; > int error; > > @@ -585,13 +585,13 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) > * Commit that transaction so that the node_addname() call > * can manage its own transactions. > */ > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_attr3_leaf_to_node(args); > if (!error) > - error = xfs_bmap_finish(&args->trans, args->flist, dp); > + error = xfs_defer_finish(&args->trans, args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > return error; > } > > @@ -675,15 +675,15 @@ xfs_attr_leaf_addname(xfs_da_args_t *args) > * If the result is small enough, shrink it all into the inode. > */ > if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); > /* bp is gone due to xfs_da_shrink_inode */ > if (!error) > - error = xfs_bmap_finish(&args->trans, > + error = xfs_defer_finish(&args->trans, > args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > return error; > } > } > @@ -738,14 +738,14 @@ xfs_attr_leaf_removename(xfs_da_args_t *args) > * If the result is small enough, shrink it all into the inode. > */ > if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); > /* bp is gone due to xfs_da_shrink_inode */ > if (!error) > - error = xfs_bmap_finish(&args->trans, args->flist, dp); > + error = xfs_defer_finish(&args->trans, args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > return error; > } > } > @@ -864,14 +864,14 @@ restart: > */ > xfs_da_state_free(state); > state = NULL; > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_attr3_leaf_to_node(args); > if (!error) > - error = xfs_bmap_finish(&args->trans, > + error = xfs_defer_finish(&args->trans, > args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > goto out; > } > > @@ -892,13 +892,13 @@ restart: > * in the index/blkno/rmtblkno/rmtblkcnt fields and > * in the index2/blkno2/rmtblkno2/rmtblkcnt2 fields. > */ > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_da3_split(state); > if (!error) > - error = xfs_bmap_finish(&args->trans, args->flist, dp); > + error = xfs_defer_finish(&args->trans, args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > goto out; > } > } else { > @@ -991,14 +991,14 @@ restart: > * Check to see if the tree needs to be collapsed. > */ > if (retval && (state->path.active > 1)) { > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_da3_join(state); > if (!error) > - error = xfs_bmap_finish(&args->trans, > + error = xfs_defer_finish(&args->trans, > args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > goto out; > } > } > @@ -1114,13 +1114,13 @@ xfs_attr_node_removename(xfs_da_args_t *args) > * Check to see if the tree needs to be collapsed. > */ > if (retval && (state->path.active > 1)) { > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_da3_join(state); > if (!error) > - error = xfs_bmap_finish(&args->trans, args->flist, dp); > + error = xfs_defer_finish(&args->trans, args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > goto out; > } > /* > @@ -1147,15 +1147,15 @@ xfs_attr_node_removename(xfs_da_args_t *args) > goto out; > > if ((forkoff = xfs_attr_shortform_allfit(bp, dp))) { > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_attr3_leaf_to_shortform(bp, args, forkoff); > /* bp is gone due to xfs_da_shrink_inode */ > if (!error) > - error = xfs_bmap_finish(&args->trans, > + error = xfs_defer_finish(&args->trans, > args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > goto out; > } > } else > diff --git a/fs/xfs/libxfs/xfs_attr_remote.c b/fs/xfs/libxfs/xfs_attr_remote.c > index 93a9ce1..aabb516 100644 > --- a/fs/xfs/libxfs/xfs_attr_remote.c > +++ b/fs/xfs/libxfs/xfs_attr_remote.c > @@ -461,16 +461,16 @@ xfs_attr_rmtval_set( > * extent and then crash then the block may not contain the > * correct metadata after log recovery occurs. > */ > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > nmap = 1; > error = xfs_bmapi_write(args->trans, dp, (xfs_fileoff_t)lblkno, > blkcnt, XFS_BMAPI_ATTRFORK, args->firstblock, > args->total, &map, &nmap, args->flist); > if (!error) > - error = xfs_bmap_finish(&args->trans, args->flist, dp); > + error = xfs_defer_finish(&args->trans, args->flist, dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > return error; > } > > @@ -504,7 +504,7 @@ xfs_attr_rmtval_set( > > ASSERT(blkcnt > 0); > > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > nmap = 1; > error = xfs_bmapi_read(dp, (xfs_fileoff_t)lblkno, > blkcnt, &map, &nmap, > @@ -604,16 +604,16 @@ xfs_attr_rmtval_remove( > blkcnt = args->rmtblkcnt; > done = 0; > while (!done) { > - xfs_bmap_init(args->flist, args->firstblock); > + xfs_defer_init(args->flist, args->firstblock); > error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, > XFS_BMAPI_ATTRFORK, 1, args->firstblock, > args->flist, &done); > if (!error) > - error = xfs_bmap_finish(&args->trans, args->flist, > + error = xfs_defer_finish(&args->trans, args->flist, > args->dp); > if (error) { > args->trans = NULL; > - xfs_bmap_cancel(args->flist); > + xfs_defer_cancel(args->flist); > return error; > } > > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c > index 64ca97f..45ce7bd 100644 > --- a/fs/xfs/libxfs/xfs_bmap.c > +++ b/fs/xfs/libxfs/xfs_bmap.c > @@ -572,7 +572,7 @@ xfs_bmap_validate_ret( > void > xfs_bmap_add_free( > struct xfs_mount *mp, /* mount point structure */ > - struct xfs_bmap_free *flist, /* list of extents */ > + struct xfs_defer_ops *flist, /* list of extents */ > xfs_fsblock_t bno, /* fs block number of extent */ > xfs_filblks_t len) /* length of extent */ > { > @@ -672,7 +672,7 @@ xfs_bmap_extents_to_btree( > xfs_trans_t *tp, /* transaction pointer */ > xfs_inode_t *ip, /* incore inode pointer */ > xfs_fsblock_t *firstblock, /* first-block-allocated */ > - xfs_bmap_free_t *flist, /* blocks freed in xaction */ > + struct xfs_defer_ops *flist, /* blocks freed in xaction */ > xfs_btree_cur_t **curp, /* cursor returned to caller */ > int wasdel, /* converting a delayed alloc */ > int *logflagsp, /* inode logging flags */ > @@ -940,7 +940,7 @@ xfs_bmap_add_attrfork_btree( > xfs_trans_t *tp, /* transaction pointer */ > xfs_inode_t *ip, /* incore inode pointer */ > xfs_fsblock_t *firstblock, /* first block allocated */ > - xfs_bmap_free_t *flist, /* blocks to free at commit */ > + struct xfs_defer_ops *flist, /* blocks to free at commit */ > int *flags) /* inode logging flags */ > { > xfs_btree_cur_t *cur; /* btree cursor */ > @@ -983,7 +983,7 @@ xfs_bmap_add_attrfork_extents( > xfs_trans_t *tp, /* transaction pointer */ > xfs_inode_t *ip, /* incore inode pointer */ > xfs_fsblock_t *firstblock, /* first block allocated */ > - xfs_bmap_free_t *flist, /* blocks to free at commit */ > + struct xfs_defer_ops *flist, /* blocks to free at commit */ > int *flags) /* inode logging flags */ > { > xfs_btree_cur_t *cur; /* bmap btree cursor */ > @@ -1018,7 +1018,7 @@ xfs_bmap_add_attrfork_local( > xfs_trans_t *tp, /* transaction pointer */ > xfs_inode_t *ip, /* incore inode pointer */ > xfs_fsblock_t *firstblock, /* first block allocated */ > - xfs_bmap_free_t *flist, /* blocks to free at commit */ > + struct xfs_defer_ops *flist, /* blocks to free at commit */ > int *flags) /* inode logging flags */ > { > xfs_da_args_t dargs; /* args for dir/attr code */ > @@ -1059,7 +1059,7 @@ xfs_bmap_add_attrfork( > int rsvd) /* xact may use reserved blks */ > { > xfs_fsblock_t firstblock; /* 1st block/ag allocated */ > - xfs_bmap_free_t flist; /* freed extent records */ > + struct xfs_defer_ops flist; /* freed extent records */ > xfs_mount_t *mp; /* mount structure */ > xfs_trans_t *tp; /* transaction pointer */ > int blks; /* space reservation */ > @@ -1125,7 +1125,7 @@ xfs_bmap_add_attrfork( > ip->i_afp = kmem_zone_zalloc(xfs_ifork_zone, KM_SLEEP); > ip->i_afp->if_flags = XFS_IFEXTENTS; > logflags = 0; > - xfs_bmap_init(&flist, &firstblock); > + xfs_defer_init(&flist, &firstblock); > switch (ip->i_d.di_format) { > case XFS_DINODE_FMT_LOCAL: > error = xfs_bmap_add_attrfork_local(tp, ip, &firstblock, &flist, > @@ -1165,7 +1165,7 @@ xfs_bmap_add_attrfork( > xfs_log_sb(tp); > } > > - error = xfs_bmap_finish(&tp, &flist, NULL); > + error = xfs_defer_finish(&tp, &flist, NULL); > if (error) > goto bmap_cancel; > error = xfs_trans_commit(tp); > @@ -1173,7 +1173,7 @@ xfs_bmap_add_attrfork( > return error; > > bmap_cancel: > - xfs_bmap_cancel(&flist); > + xfs_defer_cancel(&flist); > trans_cancel: > xfs_trans_cancel(tp); > xfs_iunlock(ip, XFS_ILOCK_EXCL); > @@ -2214,7 +2214,7 @@ xfs_bmap_add_extent_unwritten_real( > xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ > xfs_bmbt_irec_t *new, /* new data to add to file extents */ > xfs_fsblock_t *first, /* pointer to firstblock variable */ > - xfs_bmap_free_t *flist, /* list of extents to be freed */ > + struct xfs_defer_ops *flist, /* list of extents to be freed */ > int *logflagsp) /* inode logging flags */ > { > xfs_btree_cur_t *cur; /* btree cursor */ > @@ -4447,7 +4447,7 @@ xfs_bmapi_write( > xfs_extlen_t total, /* total blocks needed */ > struct xfs_bmbt_irec *mval, /* output: map values */ > int *nmap, /* i/o: mval size/count */ > - struct xfs_bmap_free *flist) /* i/o: list extents to free */ > + struct xfs_defer_ops *flist) /* i/o: list extents to free */ > { > struct xfs_mount *mp = ip->i_mount; > struct xfs_ifork *ifp; > @@ -4735,7 +4735,7 @@ xfs_bmap_del_extent( > xfs_inode_t *ip, /* incore inode pointer */ > xfs_trans_t *tp, /* current transaction pointer */ > xfs_extnum_t *idx, /* extent number to update/delete */ > - xfs_bmap_free_t *flist, /* list of extents to be freed */ > + struct xfs_defer_ops *flist, /* list of extents to be freed */ > xfs_btree_cur_t *cur, /* if null, not a btree */ > xfs_bmbt_irec_t *del, /* data to remove from extents */ > int *logflagsp, /* inode logging flags */ > @@ -5064,7 +5064,7 @@ xfs_bunmapi( > xfs_extnum_t nexts, /* number of extents max */ > xfs_fsblock_t *firstblock, /* first allocated block > controls a.g. for allocs */ > - xfs_bmap_free_t *flist, /* i/o: list extents to free */ > + struct xfs_defer_ops *flist, /* i/o: list extents to free */ > int *done) /* set if not done yet */ > { > xfs_btree_cur_t *cur; /* bmap btree cursor */ > @@ -5678,7 +5678,7 @@ xfs_bmap_shift_extents( > int *done, > xfs_fileoff_t stop_fsb, > xfs_fsblock_t *firstblock, > - struct xfs_bmap_free *flist, > + struct xfs_defer_ops *flist, > enum shift_direction direction, > int num_exts) > { > @@ -5832,7 +5832,7 @@ xfs_bmap_split_extent_at( > struct xfs_inode *ip, > xfs_fileoff_t split_fsb, > xfs_fsblock_t *firstfsb, > - struct xfs_bmap_free *free_list) > + struct xfs_defer_ops *free_list) > { > int whichfork = XFS_DATA_FORK; > struct xfs_btree_cur *cur = NULL; > @@ -5971,7 +5971,7 @@ xfs_bmap_split_extent( > { > struct xfs_mount *mp = ip->i_mount; > struct xfs_trans *tp; > - struct xfs_bmap_free free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t firstfsb; > int error; > > @@ -5983,21 +5983,21 @@ xfs_bmap_split_extent( > xfs_ilock(ip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); > > - xfs_bmap_init(&free_list, &firstfsb); > + xfs_defer_init(&free_list, &firstfsb); > > error = xfs_bmap_split_extent_at(tp, ip, split_fsb, > &firstfsb, &free_list); > if (error) > goto out; > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto out; > > return xfs_trans_commit(tp); > > out: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > xfs_trans_cancel(tp); > return error; > } > diff --git a/fs/xfs/libxfs/xfs_bmap.h b/fs/xfs/libxfs/xfs_bmap.h > index 6681bd9..e2a0425 100644 > --- a/fs/xfs/libxfs/xfs_bmap.h > +++ b/fs/xfs/libxfs/xfs_bmap.h > @@ -32,7 +32,7 @@ extern kmem_zone_t *xfs_bmap_free_item_zone; > */ > struct xfs_bmalloca { > xfs_fsblock_t *firstblock; /* i/o first block allocated */ > - struct xfs_bmap_free *flist; /* bmap freelist */ > + struct xfs_defer_ops *flist; /* bmap freelist */ > struct xfs_trans *tp; /* transaction pointer */ > struct xfs_inode *ip; /* incore inode pointer */ > struct xfs_bmbt_irec prev; /* extent before the new one */ > @@ -164,7 +164,7 @@ void xfs_bmap_trace_exlist(struct xfs_inode *ip, xfs_extnum_t cnt, > > int xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd); > void xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork); > -void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_bmap_free *flist, > +void xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *flist, > xfs_fsblock_t bno, xfs_filblks_t len); > void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork); > int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip, > @@ -186,18 +186,18 @@ int xfs_bmapi_write(struct xfs_trans *tp, struct xfs_inode *ip, > xfs_fileoff_t bno, xfs_filblks_t len, int flags, > xfs_fsblock_t *firstblock, xfs_extlen_t total, > struct xfs_bmbt_irec *mval, int *nmap, > - struct xfs_bmap_free *flist); > + struct xfs_defer_ops *flist); > int xfs_bunmapi(struct xfs_trans *tp, struct xfs_inode *ip, > xfs_fileoff_t bno, xfs_filblks_t len, int flags, > xfs_extnum_t nexts, xfs_fsblock_t *firstblock, > - struct xfs_bmap_free *flist, int *done); > + struct xfs_defer_ops *flist, int *done); > int xfs_check_nostate_extents(struct xfs_ifork *ifp, xfs_extnum_t idx, > xfs_extnum_t num); > uint xfs_default_attroffset(struct xfs_inode *ip); > int xfs_bmap_shift_extents(struct xfs_trans *tp, struct xfs_inode *ip, > xfs_fileoff_t *next_fsb, xfs_fileoff_t offset_shift_fsb, > int *done, xfs_fileoff_t stop_fsb, xfs_fsblock_t *firstblock, > - struct xfs_bmap_free *flist, enum shift_direction direction, > + struct xfs_defer_ops *flist, enum shift_direction direction, > int num_exts); > int xfs_bmap_split_extent(struct xfs_inode *ip, xfs_fileoff_t split_offset); > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index 0ec3055..ae714a8 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -19,7 +19,7 @@ > #define __XFS_BTREE_H__ > > struct xfs_buf; > -struct xfs_bmap_free; > +struct xfs_defer_ops; > struct xfs_inode; > struct xfs_mount; > struct xfs_trans; > @@ -234,11 +234,12 @@ typedef struct xfs_btree_cur > union { > struct { /* needed for BNO, CNT, INO */ > struct xfs_buf *agbp; /* agf/agi buffer pointer */ > + struct xfs_defer_ops *flist; /* deferred updates */ > xfs_agnumber_t agno; /* ag number */ > } a; > struct { /* needed for BMAP */ > struct xfs_inode *ip; /* pointer to our inode */ > - struct xfs_bmap_free *flist; /* list to free after */ > + struct xfs_defer_ops *flist; /* deferred updates */ > xfs_fsblock_t firstblock; /* 1st blk allocated */ > int allocated; /* count of alloced */ > short forksize; /* fork's inode space */ > diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h > index 6e153e3..249813a 100644 > --- a/fs/xfs/libxfs/xfs_da_btree.h > +++ b/fs/xfs/libxfs/xfs_da_btree.h > @@ -19,7 +19,7 @@ > #ifndef __XFS_DA_BTREE_H__ > #define __XFS_DA_BTREE_H__ > > -struct xfs_bmap_free; > +struct xfs_defer_ops; > struct xfs_inode; > struct xfs_trans; > struct zone; > @@ -70,7 +70,7 @@ typedef struct xfs_da_args { > xfs_ino_t inumber; /* input/output inode number */ > struct xfs_inode *dp; /* directory inode to manipulate */ > xfs_fsblock_t *firstblock; /* ptr to firstblock for bmap calls */ > - struct xfs_bmap_free *flist; /* ptr to freelist for bmap_finish */ > + struct xfs_defer_ops *flist; /* ptr to freelist for bmap_finish */ > struct xfs_trans *trans; /* current trans (changes over time) */ > xfs_extlen_t total; /* total blocks needed, for 1st bmap */ > int whichfork; /* data or attribute fork */ > diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h > index 4c05ba6..743fc32 100644 > --- a/fs/xfs/libxfs/xfs_defer.h > +++ b/fs/xfs/libxfs/xfs_defer.h > @@ -94,11 +94,4 @@ struct xfs_defer_op_type { > void xfs_defer_init_op_type(const struct xfs_defer_op_type *type); > void xfs_defer_init_types(void); > > -/* XXX: compatibility shims, will go away in the next patch */ > -#define xfs_bmap_finish xfs_defer_finish > -#define xfs_bmap_cancel xfs_defer_cancel > -#define xfs_bmap_init xfs_defer_init > -#define xfs_bmap_free xfs_defer_ops > -typedef struct xfs_defer_ops xfs_bmap_free_t; > - > #endif /* __XFS_DEFER_H__ */ > diff --git a/fs/xfs/libxfs/xfs_dir2.c b/fs/xfs/libxfs/xfs_dir2.c > index 945c0345..0523100 100644 > --- a/fs/xfs/libxfs/xfs_dir2.c > +++ b/fs/xfs/libxfs/xfs_dir2.c > @@ -260,7 +260,7 @@ xfs_dir_createname( > struct xfs_name *name, > xfs_ino_t inum, /* new entry inode number */ > xfs_fsblock_t *first, /* bmap's firstblock */ > - xfs_bmap_free_t *flist, /* bmap's freeblock list */ > + struct xfs_defer_ops *flist, /* bmap's freeblock list */ > xfs_extlen_t total) /* bmap's total block count */ > { > struct xfs_da_args *args; > @@ -437,7 +437,7 @@ xfs_dir_removename( > struct xfs_name *name, > xfs_ino_t ino, > xfs_fsblock_t *first, /* bmap's firstblock */ > - xfs_bmap_free_t *flist, /* bmap's freeblock list */ > + struct xfs_defer_ops *flist, /* bmap's freeblock list */ > xfs_extlen_t total) /* bmap's total block count */ > { > struct xfs_da_args *args; > @@ -499,7 +499,7 @@ xfs_dir_replace( > struct xfs_name *name, /* name of entry to replace */ > xfs_ino_t inum, /* new inode number */ > xfs_fsblock_t *first, /* bmap's firstblock */ > - xfs_bmap_free_t *flist, /* bmap's freeblock list */ > + struct xfs_defer_ops *flist, /* bmap's freeblock list */ > xfs_extlen_t total) /* bmap's total block count */ > { > struct xfs_da_args *args; > diff --git a/fs/xfs/libxfs/xfs_dir2.h b/fs/xfs/libxfs/xfs_dir2.h > index 0a62e73..5737d85 100644 > --- a/fs/xfs/libxfs/xfs_dir2.h > +++ b/fs/xfs/libxfs/xfs_dir2.h > @@ -18,7 +18,7 @@ > #ifndef __XFS_DIR2_H__ > #define __XFS_DIR2_H__ > > -struct xfs_bmap_free; > +struct xfs_defer_ops; > struct xfs_da_args; > struct xfs_inode; > struct xfs_mount; > @@ -129,18 +129,18 @@ extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, > extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, > struct xfs_name *name, xfs_ino_t inum, > xfs_fsblock_t *first, > - struct xfs_bmap_free *flist, xfs_extlen_t tot); > + struct xfs_defer_ops *flist, xfs_extlen_t tot); > extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, > struct xfs_name *name, xfs_ino_t *inum, > struct xfs_name *ci_name); > extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, > struct xfs_name *name, xfs_ino_t ino, > xfs_fsblock_t *first, > - struct xfs_bmap_free *flist, xfs_extlen_t tot); > + struct xfs_defer_ops *flist, xfs_extlen_t tot); > extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, > struct xfs_name *name, xfs_ino_t inum, > xfs_fsblock_t *first, > - struct xfs_bmap_free *flist, xfs_extlen_t tot); > + struct xfs_defer_ops *flist, xfs_extlen_t tot); > extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, > struct xfs_name *name); > > diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c > index 9ae9a43..f2e29a1 100644 > --- a/fs/xfs/libxfs/xfs_ialloc.c > +++ b/fs/xfs/libxfs/xfs_ialloc.c > @@ -1818,7 +1818,7 @@ xfs_difree_inode_chunk( > struct xfs_mount *mp, > xfs_agnumber_t agno, > struct xfs_inobt_rec_incore *rec, > - struct xfs_bmap_free *flist) > + struct xfs_defer_ops *flist) > { > xfs_agblock_t sagbno = XFS_AGINO_TO_AGBNO(mp, rec->ir_startino); > int startidx, endidx; > @@ -1890,7 +1890,7 @@ xfs_difree_inobt( > struct xfs_trans *tp, > struct xfs_buf *agbp, > xfs_agino_t agino, > - struct xfs_bmap_free *flist, > + struct xfs_defer_ops *flist, > struct xfs_icluster *xic, > struct xfs_inobt_rec_incore *orec) > { > @@ -2122,7 +2122,7 @@ int > xfs_difree( > struct xfs_trans *tp, /* transaction pointer */ > xfs_ino_t inode, /* inode to be freed */ > - struct xfs_bmap_free *flist, /* extents to free */ > + struct xfs_defer_ops *flist, /* extents to free */ > struct xfs_icluster *xic) /* cluster info if deleted */ > { > /* REFERENCED */ > diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h > index 6e450df..2e06b67 100644 > --- a/fs/xfs/libxfs/xfs_ialloc.h > +++ b/fs/xfs/libxfs/xfs_ialloc.h > @@ -95,7 +95,7 @@ int /* error */ > xfs_difree( > struct xfs_trans *tp, /* transaction pointer */ > xfs_ino_t inode, /* inode to be freed */ > - struct xfs_bmap_free *flist, /* extents to free */ > + struct xfs_defer_ops *flist, /* extents to free */ > struct xfs_icluster *ifree); /* cluster info if deleted */ > > /* > diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c > index 68cb1e7..4c7eb9d 100644 > --- a/fs/xfs/libxfs/xfs_trans_resv.c > +++ b/fs/xfs/libxfs/xfs_trans_resv.c > @@ -153,9 +153,9 @@ xfs_calc_finobt_res( > * item logged to try to account for the overhead of the transaction mechanism. > * > * Note: Most of the reservations underestimate the number of allocation > - * groups into which they could free extents in the xfs_bmap_finish() call. > + * groups into which they could free extents in the xfs_defer_finish() call. > * This is because the number in the worst case is quite high and quite > - * unusual. In order to fix this we need to change xfs_bmap_finish() to free > + * unusual. In order to fix this we need to change xfs_defer_finish() to free > * extents in only a single AG at a time. This will require changes to the > * EFI code as well, however, so that the EFI for the extents not freed is > * logged again in each transaction. See SGI PV #261917. > diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c > index 972a27a..928dfa4 100644 > --- a/fs/xfs/xfs_bmap_util.c > +++ b/fs/xfs/xfs_bmap_util.c > @@ -685,7 +685,7 @@ xfs_bmap_punch_delalloc_range( > xfs_bmbt_irec_t imap; > int nimaps = 1; > xfs_fsblock_t firstblock; > - xfs_bmap_free_t flist; > + struct xfs_defer_ops flist; > > /* > * Map the range first and check that it is a delalloc extent > @@ -721,7 +721,7 @@ xfs_bmap_punch_delalloc_range( > * allocated or freed for a delalloc extent and hence we need > * don't cancel or finish them after the xfs_bunmapi() call. > */ > - xfs_bmap_init(&flist, &firstblock); > + xfs_defer_init(&flist, &firstblock); > error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock, > &flist, &done); > if (error) > @@ -884,7 +884,7 @@ xfs_alloc_file_space( > int rt; > xfs_trans_t *tp; > xfs_bmbt_irec_t imaps[1], *imapp; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > uint qblocks, resblks, resrtextents; > int error; > > @@ -975,7 +975,7 @@ xfs_alloc_file_space( > > xfs_trans_ijoin(tp, ip, 0); > > - xfs_bmap_init(&free_list, &firstfsb); > + xfs_defer_init(&free_list, &firstfsb); > error = xfs_bmapi_write(tp, ip, startoffset_fsb, > allocatesize_fsb, alloc_type, &firstfsb, > resblks, imapp, &nimaps, &free_list); > @@ -985,7 +985,7 @@ xfs_alloc_file_space( > /* > * Complete the transaction > */ > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto error0; > > @@ -1008,7 +1008,7 @@ xfs_alloc_file_space( > return error; > > error0: /* Cancel bmap, unlock inode, unreserve quota blocks, cancel trans */ > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag); > > error1: /* Just cancel transaction */ > @@ -1122,7 +1122,7 @@ xfs_free_file_space( > xfs_fileoff_t endoffset_fsb; > int error; > xfs_fsblock_t firstfsb; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_bmbt_irec_t imap; > xfs_off_t ioffset; > xfs_off_t iendoffset; > @@ -1245,7 +1245,7 @@ xfs_free_file_space( > /* > * issue the bunmapi() call to free the blocks > */ > - xfs_bmap_init(&free_list, &firstfsb); > + xfs_defer_init(&free_list, &firstfsb); > error = xfs_bunmapi(tp, ip, startoffset_fsb, > endoffset_fsb - startoffset_fsb, > 0, 2, &firstfsb, &free_list, &done); > @@ -1255,7 +1255,7 @@ xfs_free_file_space( > /* > * complete the transaction > */ > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, ip); > if (error) > goto error0; > > @@ -1267,7 +1267,7 @@ xfs_free_file_space( > return error; > > error0: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > error1: > xfs_trans_cancel(tp); > xfs_iunlock(ip, XFS_ILOCK_EXCL); > @@ -1333,7 +1333,7 @@ xfs_shift_file_space( > struct xfs_mount *mp = ip->i_mount; > struct xfs_trans *tp; > int error; > - struct xfs_bmap_free free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > xfs_fileoff_t stop_fsb; > xfs_fileoff_t next_fsb; > @@ -1411,7 +1411,7 @@ xfs_shift_file_space( > > xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); > > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > > /* > * We are using the write transaction in which max 2 bmbt > @@ -1423,7 +1423,7 @@ xfs_shift_file_space( > if (error) > goto out_bmap_cancel; > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto out_bmap_cancel; > > @@ -1433,7 +1433,7 @@ xfs_shift_file_space( > return error; > > out_bmap_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > out_trans_cancel: > xfs_trans_cancel(tp); > return error; > diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c > index be17f0a..764e1cc 100644 > --- a/fs/xfs/xfs_dquot.c > +++ b/fs/xfs/xfs_dquot.c > @@ -307,7 +307,7 @@ xfs_qm_dqalloc( > xfs_buf_t **O_bpp) > { > xfs_fsblock_t firstblock; > - xfs_bmap_free_t flist; > + struct xfs_defer_ops flist; > xfs_bmbt_irec_t map; > int nmaps, error; > xfs_buf_t *bp; > @@ -320,7 +320,7 @@ xfs_qm_dqalloc( > /* > * Initialize the bmap freelist prior to calling bmapi code. > */ > - xfs_bmap_init(&flist, &firstblock); > + xfs_defer_init(&flist, &firstblock); > xfs_ilock(quotip, XFS_ILOCK_EXCL); > /* > * Return if this type of quotas is turned off while we didn't > @@ -368,7 +368,7 @@ xfs_qm_dqalloc( > dqp->dq_flags & XFS_DQ_ALLTYPES, bp); > > /* > - * xfs_bmap_finish() may commit the current transaction and > + * xfs_defer_finish() may commit the current transaction and > * start a second transaction if the freelist is not empty. > * > * Since we still want to modify this buffer, we need to > @@ -382,7 +382,7 @@ xfs_qm_dqalloc( > > xfs_trans_bhold(tp, bp); > > - error = xfs_bmap_finish(tpp, &flist, NULL); > + error = xfs_defer_finish(tpp, &flist, NULL); > if (error) > goto error1; > > @@ -398,7 +398,7 @@ xfs_qm_dqalloc( > return 0; > > error1: > - xfs_bmap_cancel(&flist); > + xfs_defer_cancel(&flist); > error0: > xfs_iunlock(quotip, XFS_ILOCK_EXCL); > > diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c > index d2389bb..3ce50da 100644 > --- a/fs/xfs/xfs_inode.c > +++ b/fs/xfs/xfs_inode.c > @@ -1123,7 +1123,7 @@ xfs_create( > struct xfs_inode *ip = NULL; > struct xfs_trans *tp = NULL; > int error; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > bool unlock_dp_on_error = false; > prid_t prid; > @@ -1183,7 +1183,7 @@ xfs_create( > XFS_IOLOCK_PARENT | XFS_ILOCK_PARENT); > unlock_dp_on_error = true; > > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > > /* > * Reserve disk quota and the inode. > @@ -1254,7 +1254,7 @@ xfs_create( > */ > xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp); > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto out_bmap_cancel; > > @@ -1270,7 +1270,7 @@ xfs_create( > return 0; > > out_bmap_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > out_trans_cancel: > xfs_trans_cancel(tp); > out_release_inode: > @@ -1402,7 +1402,7 @@ xfs_link( > xfs_mount_t *mp = tdp->i_mount; > xfs_trans_t *tp; > int error; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > int resblks; > > @@ -1453,7 +1453,7 @@ xfs_link( > goto error_return; > } > > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > > /* > * Handle initial link state of O_TMPFILE inode > @@ -1483,9 +1483,9 @@ xfs_link( > if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) > xfs_trans_set_sync(tp); > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) { > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > goto error_return; > } > > @@ -1527,7 +1527,7 @@ xfs_itruncate_extents( > { > struct xfs_mount *mp = ip->i_mount; > struct xfs_trans *tp = *tpp; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > xfs_fileoff_t first_unmap_block; > xfs_fileoff_t last_block; > @@ -1563,7 +1563,7 @@ xfs_itruncate_extents( > ASSERT(first_unmap_block < last_block); > unmap_len = last_block - first_unmap_block + 1; > while (!done) { > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > error = xfs_bunmapi(tp, ip, > first_unmap_block, unmap_len, > xfs_bmapi_aflag(whichfork), > @@ -1577,7 +1577,7 @@ xfs_itruncate_extents( > * Duplicate the transaction that has the permanent > * reservation and commit the old transaction. > */ > - error = xfs_bmap_finish(&tp, &free_list, ip); > + error = xfs_defer_finish(&tp, &free_list, ip); > if (error) > goto out_bmap_cancel; > > @@ -1603,7 +1603,7 @@ out_bmap_cancel: > * the transaction can be properly aborted. We just need to make sure > * we're not holding any resources that we were not when we came in. > */ > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > goto out; > } > > @@ -1744,7 +1744,7 @@ STATIC int > xfs_inactive_ifree( > struct xfs_inode *ip) > { > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > struct xfs_mount *mp = ip->i_mount; > struct xfs_trans *tp; > @@ -1781,7 +1781,7 @@ xfs_inactive_ifree( > xfs_ilock(ip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, ip, 0); > > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > error = xfs_ifree(tp, ip, &free_list); > if (error) { > /* > @@ -1808,11 +1808,11 @@ xfs_inactive_ifree( > * Just ignore errors at this point. There is nothing we can do except > * to try to keep going. Make sure it's not a silent error. > */ > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) { > - xfs_notice(mp, "%s: xfs_bmap_finish returned error %d", > + xfs_notice(mp, "%s: xfs_defer_finish returned error %d", > __func__, error); > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > } > error = xfs_trans_commit(tp); > if (error) > @@ -2368,7 +2368,7 @@ int > xfs_ifree( > xfs_trans_t *tp, > xfs_inode_t *ip, > - xfs_bmap_free_t *flist) > + struct xfs_defer_ops *flist) > { > int error; > struct xfs_icluster xic = { 0 }; > @@ -2475,7 +2475,7 @@ xfs_iunpin_wait( > * directory entry. > * > * This is still safe from a transactional point of view - it is not until we > - * get to xfs_bmap_finish() that we have the possibility of multiple > + * get to xfs_defer_finish() that we have the possibility of multiple > * transactions in this operation. Hence as long as we remove the directory > * entry and drop the link count in the first transaction of the remove > * operation, there are no transactional constraints on the ordering here. > @@ -2490,7 +2490,7 @@ xfs_remove( > xfs_trans_t *tp = NULL; > int is_dir = S_ISDIR(VFS_I(ip)->i_mode); > int error = 0; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > uint resblks; > > @@ -2572,7 +2572,7 @@ xfs_remove( > if (error) > goto out_trans_cancel; > > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > error = xfs_dir_removename(tp, dp, name, ip->i_ino, > &first_block, &free_list, resblks); > if (error) { > @@ -2588,7 +2588,7 @@ xfs_remove( > if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) > xfs_trans_set_sync(tp); > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto out_bmap_cancel; > > @@ -2602,7 +2602,7 @@ xfs_remove( > return 0; > > out_bmap_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > out_trans_cancel: > xfs_trans_cancel(tp); > std_return: > @@ -2663,7 +2663,7 @@ xfs_sort_for_rename( > static int > xfs_finish_rename( > struct xfs_trans *tp, > - struct xfs_bmap_free *free_list) > + struct xfs_defer_ops *free_list) > { > int error; > > @@ -2674,9 +2674,9 @@ xfs_finish_rename( > if (tp->t_mountp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) > xfs_trans_set_sync(tp); > > - error = xfs_bmap_finish(&tp, free_list, NULL); > + error = xfs_defer_finish(&tp, free_list, NULL); > if (error) { > - xfs_bmap_cancel(free_list); > + xfs_defer_cancel(free_list); > xfs_trans_cancel(tp); > return error; > } > @@ -2698,7 +2698,7 @@ xfs_cross_rename( > struct xfs_inode *dp2, > struct xfs_name *name2, > struct xfs_inode *ip2, > - struct xfs_bmap_free *free_list, > + struct xfs_defer_ops *free_list, > xfs_fsblock_t *first_block, > int spaceres) > { > @@ -2801,7 +2801,7 @@ xfs_cross_rename( > return xfs_finish_rename(tp, free_list); > > out_trans_abort: > - xfs_bmap_cancel(free_list); > + xfs_defer_cancel(free_list); > xfs_trans_cancel(tp); > return error; > } > @@ -2856,7 +2856,7 @@ xfs_rename( > { > struct xfs_mount *mp = src_dp->i_mount; > struct xfs_trans *tp; > - struct xfs_bmap_free free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > struct xfs_inode *wip = NULL; /* whiteout inode */ > struct xfs_inode *inodes[__XFS_SORT_INODES]; > @@ -2945,7 +2945,7 @@ xfs_rename( > goto out_trans_cancel; > } > > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > > /* RENAME_EXCHANGE is unique from here on. */ > if (flags & RENAME_EXCHANGE) > @@ -3131,7 +3131,7 @@ xfs_rename( > return error; > > out_bmap_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > out_trans_cancel: > xfs_trans_cancel(tp); > out_release_wip: > diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h > index 99d7522..633f2af 100644 > --- a/fs/xfs/xfs_inode.h > +++ b/fs/xfs/xfs_inode.h > @@ -27,7 +27,7 @@ > struct xfs_dinode; > struct xfs_inode; > struct xfs_buf; > -struct xfs_bmap_free; > +struct xfs_defer_ops; > struct xfs_bmbt_irec; > struct xfs_inode_log_item; > struct xfs_mount; > @@ -398,7 +398,7 @@ uint xfs_ilock_attr_map_shared(struct xfs_inode *); > > uint xfs_ip2xflags(struct xfs_inode *); > int xfs_ifree(struct xfs_trans *, xfs_inode_t *, > - struct xfs_bmap_free *); > + struct xfs_defer_ops *); > int xfs_itruncate_extents(struct xfs_trans **, struct xfs_inode *, > int, xfs_fsize_t); > void xfs_iext_realloc(xfs_inode_t *, int, int); > diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c > index b090bc1..cb7abe84 100644 > --- a/fs/xfs/xfs_iomap.c > +++ b/fs/xfs/xfs_iomap.c > @@ -128,7 +128,7 @@ xfs_iomap_write_direct( > int quota_flag; > int rt; > xfs_trans_t *tp; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > uint qblocks, resblks, resrtextents; > int error; > int lockmode; > @@ -231,7 +231,7 @@ xfs_iomap_write_direct( > * From this point onwards we overwrite the imap pointer that the > * caller gave to us. > */ > - xfs_bmap_init(&free_list, &firstfsb); > + xfs_defer_init(&free_list, &firstfsb); > nimaps = 1; > error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, > bmapi_flags, &firstfsb, resblks, imap, > @@ -242,7 +242,7 @@ xfs_iomap_write_direct( > /* > * Complete the transaction > */ > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto out_bmap_cancel; > > @@ -266,7 +266,7 @@ out_unlock: > return error; > > out_bmap_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > xfs_trans_unreserve_quota_nblks(tp, ip, (long)qblocks, 0, quota_flag); > out_trans_cancel: > xfs_trans_cancel(tp); > @@ -685,7 +685,7 @@ xfs_iomap_write_allocate( > xfs_fileoff_t offset_fsb, last_block; > xfs_fileoff_t end_fsb, map_start_fsb; > xfs_fsblock_t first_block; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_filblks_t count_fsb; > xfs_trans_t *tp; > int nimaps; > @@ -727,7 +727,7 @@ xfs_iomap_write_allocate( > xfs_ilock(ip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, ip, 0); > > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > > /* > * it is possible that the extents have changed since > @@ -787,7 +787,7 @@ xfs_iomap_write_allocate( > if (error) > goto trans_cancel; > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto trans_cancel; > > @@ -821,7 +821,7 @@ xfs_iomap_write_allocate( > } > > trans_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > xfs_trans_cancel(tp); > error0: > xfs_iunlock(ip, XFS_ILOCK_EXCL); > @@ -842,7 +842,7 @@ xfs_iomap_write_unwritten( > int nimaps; > xfs_trans_t *tp; > xfs_bmbt_irec_t imap; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > xfs_fsize_t i_size; > uint resblks; > int error; > @@ -886,7 +886,7 @@ xfs_iomap_write_unwritten( > /* > * Modify the unwritten extent state of the buffer. > */ > - xfs_bmap_init(&free_list, &firstfsb); > + xfs_defer_init(&free_list, &firstfsb); > nimaps = 1; > error = xfs_bmapi_write(tp, ip, offset_fsb, count_fsb, > XFS_BMAPI_CONVERT, &firstfsb, resblks, > @@ -909,7 +909,7 @@ xfs_iomap_write_unwritten( > xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); > } > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto error_on_bmapi_transaction; > > @@ -936,7 +936,7 @@ xfs_iomap_write_unwritten( > return 0; > > error_on_bmapi_transaction: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > xfs_trans_cancel(tp); > xfs_iunlock(ip, XFS_ILOCK_EXCL); > return error; > diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c > index 627f7e6..c761a6a 100644 > --- a/fs/xfs/xfs_rtalloc.c > +++ b/fs/xfs/xfs_rtalloc.c > @@ -770,7 +770,7 @@ xfs_growfs_rt_alloc( > xfs_daddr_t d; /* disk block address */ > int error; /* error return value */ > xfs_fsblock_t firstblock;/* first block allocated in xaction */ > - struct xfs_bmap_free flist; /* list of freed blocks */ > + struct xfs_defer_ops flist; /* list of freed blocks */ > xfs_fsblock_t fsbno; /* filesystem block for bno */ > struct xfs_bmbt_irec map; /* block map output */ > int nmap; /* number of block maps */ > @@ -795,7 +795,7 @@ xfs_growfs_rt_alloc( > xfs_ilock(ip, XFS_ILOCK_EXCL); > xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); > > - xfs_bmap_init(&flist, &firstblock); > + xfs_defer_init(&flist, &firstblock); > /* > * Allocate blocks to the bitmap file. > */ > @@ -810,7 +810,7 @@ xfs_growfs_rt_alloc( > /* > * Free any blocks freed up in the transaction, then commit. > */ > - error = xfs_bmap_finish(&tp, &flist, NULL); > + error = xfs_defer_finish(&tp, &flist, NULL); > if (error) > goto out_bmap_cancel; > error = xfs_trans_commit(tp); > @@ -863,7 +863,7 @@ xfs_growfs_rt_alloc( > return 0; > > out_bmap_cancel: > - xfs_bmap_cancel(&flist); > + xfs_defer_cancel(&flist); > out_trans_cancel: > xfs_trans_cancel(tp); > return error; > diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c > index 20af47b..3b005ec 100644 > --- a/fs/xfs/xfs_symlink.c > +++ b/fs/xfs/xfs_symlink.c > @@ -173,7 +173,7 @@ xfs_symlink( > struct xfs_inode *ip = NULL; > int error = 0; > int pathlen; > - struct xfs_bmap_free free_list; > + struct xfs_defer_ops free_list; > xfs_fsblock_t first_block; > bool unlock_dp_on_error = false; > xfs_fileoff_t first_fsb; > @@ -270,7 +270,7 @@ xfs_symlink( > * Initialize the bmap freelist prior to calling either > * bmapi or the directory create code. > */ > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > > /* > * Allocate an inode for the symlink. > @@ -377,7 +377,7 @@ xfs_symlink( > xfs_trans_set_sync(tp); > } > > - error = xfs_bmap_finish(&tp, &free_list, NULL); > + error = xfs_defer_finish(&tp, &free_list, NULL); > if (error) > goto out_bmap_cancel; > > @@ -393,7 +393,7 @@ xfs_symlink( > return 0; > > out_bmap_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > out_trans_cancel: > xfs_trans_cancel(tp); > out_release_inode: > @@ -427,7 +427,7 @@ xfs_inactive_symlink_rmt( > int done; > int error; > xfs_fsblock_t first_block; > - xfs_bmap_free_t free_list; > + struct xfs_defer_ops free_list; > int i; > xfs_mount_t *mp; > xfs_bmbt_irec_t mval[XFS_SYMLINK_MAPS]; > @@ -466,7 +466,7 @@ xfs_inactive_symlink_rmt( > * Find the block(s) so we can inval and unmap them. > */ > done = 0; > - xfs_bmap_init(&free_list, &first_block); > + xfs_defer_init(&free_list, &first_block); > nmaps = ARRAY_SIZE(mval); > error = xfs_bmapi_read(ip, 0, xfs_symlink_blocks(mp, size), > mval, &nmaps, 0); > @@ -496,7 +496,7 @@ xfs_inactive_symlink_rmt( > /* > * Commit the first transaction. This logs the EFI and the inode. > */ > - error = xfs_bmap_finish(&tp, &free_list, ip); > + error = xfs_defer_finish(&tp, &free_list, ip); > if (error) > goto error_bmap_cancel; > /* > @@ -526,7 +526,7 @@ xfs_inactive_symlink_rmt( > return 0; > > error_bmap_cancel: > - xfs_bmap_cancel(&free_list); > + xfs_defer_cancel(&free_list); > error_trans_cancel: > xfs_trans_cancel(tp); > error_unlock: > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From darrick.wong@oracle.com Wed Jun 29 19:15:18 2016 Return-Path: <darrick.wong@oracle.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 88F1B7CA1 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 19:15:18 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 4B6DC8F8040 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 17:15:18 -0700 (PDT) X-ASG-Debug-ID: 1467245714-04cbb02735386a40001-NocioJ Received: from aserp1040.oracle.com (aserp1040.oracle.com [141.146.126.69]) by cuda.sgi.com with ESMTP id JEDfHPaRVkzFonho (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 17:15:14 -0700 (PDT) X-Barracuda-Envelope-From: darrick.wong@oracle.com X-Barracuda-Effective-Source-IP: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Apparent-Source-IP: 141.146.126.69 Received: from userv0021.oracle.com (userv0021.oracle.com [156.151.31.71]) by aserp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id u5U0FBmC006778 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 30 Jun 2016 00:15:12 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by userv0021.oracle.com (8.13.8/8.13.8) with ESMTP id u5U0FBRE015170 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Thu, 30 Jun 2016 00:15:11 GMT Received: from abhmp0011.oracle.com (abhmp0011.oracle.com [141.146.116.17]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id u5U0FAtp019549; Thu, 30 Jun 2016 00:15:10 GMT Received: from localhost (/10.145.178.207) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 29 Jun 2016 17:15:10 -0700 Date: Wed, 29 Jun 2016 17:15:08 -0700 From: "Darrick J. Wong" <darrick.wong@oracle.com> To: david@fromorbit.com Cc: linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, xfs@oss.sgi.com Subject: Re: [PATCH 038/119] xfs: convert unwritten status of reverse mappings Message-ID: <20160630001507.GG4917@birch.djwong.org> X-ASG-Orig-Subj: Re: [PATCH 038/119] xfs: convert unwritten status of reverse mappings References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612651582.12839.562287367335619574.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612651582.12839.562287367335619574.stgit@birch.djwong.org> User-Agent: Mutt/1.5.24 (2015-08-30) X-Source-IP: userv0021.oracle.com [156.151.31.71] X-Barracuda-Connect: aserp1040.oracle.com[141.146.126.69] X-Barracuda-Start-Time: 1467245714 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 16628 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, UNPARSEABLE_RELAY X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30882 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 UNPARSEABLE_RELAY Informational: message has unparseable relay lines On Thu, Jun 16, 2016 at 06:21:55PM -0700, Darrick J. Wong wrote: > Provide a function to convert an unwritten extent to a real one and > vice versa. > > v2: Move unwritten bit to rm_offset. > > Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> > --- > fs/xfs/libxfs/xfs_rmap.c | 442 ++++++++++++++++++++++++++++++++++++++++++++++ > fs/xfs/xfs_trace.h | 6 + > 2 files changed, 448 insertions(+) > > > diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c > index 1043c63..53ba14e 100644 > --- a/fs/xfs/libxfs/xfs_rmap.c > +++ b/fs/xfs/libxfs/xfs_rmap.c > @@ -610,6 +610,448 @@ out_error: > return error; > } > > +#define RMAP_LEFT_CONTIG (1 << 0) > +#define RMAP_RIGHT_CONTIG (1 << 1) > +#define RMAP_LEFT_FILLING (1 << 2) > +#define RMAP_RIGHT_FILLING (1 << 3) > +#define RMAP_LEFT_VALID (1 << 6) > +#define RMAP_RIGHT_VALID (1 << 7) > + > +#define LEFT r[0] > +#define RIGHT r[1] > +#define PREV r[2] > +#define NEW r[3] > + > +/* > + * Convert an unwritten extent to a real extent or vice versa. > + * Does not handle overlapping extents. > + */ > +STATIC int > +__xfs_rmap_convert( > + struct xfs_btree_cur *cur, > + xfs_agblock_t bno, > + xfs_extlen_t len, > + bool unwritten, > + struct xfs_owner_info *oinfo) > +{ > + struct xfs_mount *mp = cur->bc_mp; > + struct xfs_rmap_irec r[4]; /* neighbor extent entries */ > + /* left is 0, right is 1, prev is 2 */ > + /* new is 3 */ > + uint64_t owner; > + uint64_t offset; > + uint64_t new_endoff; > + unsigned int oldext; > + unsigned int newext; > + unsigned int flags = 0; > + int i; > + int state = 0; > + int error; > + > + xfs_owner_info_unpack(oinfo, &owner, &offset, &flags); > + ASSERT(!(XFS_RMAP_NON_INODE_OWNER(owner) || > + (flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))); > + oldext = unwritten ? XFS_RMAP_UNWRITTEN : 0; > + new_endoff = offset + len; > + trace_xfs_rmap_convert(mp, cur->bc_private.a.agno, bno, len, > + unwritten, oinfo); > + > + /* > + * For the initial lookup, look for and exact match or the left-adjacent > + * record for our insertion point. This will also give us the record for > + * start block contiguity tests. > + */ > + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + > + error = xfs_rmap_get_rec(cur, &PREV, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + trace_xfs_rmap_lookup_le_range_result(cur->bc_mp, > + cur->bc_private.a.agno, PREV.rm_startblock, > + PREV.rm_blockcount, PREV.rm_owner, > + PREV.rm_offset, PREV.rm_flags); > + > + ASSERT(PREV.rm_offset <= offset); > + ASSERT(PREV.rm_offset + PREV.rm_blockcount >= new_endoff); > + ASSERT((PREV.rm_flags & XFS_RMAP_UNWRITTEN) == oldext); > + newext = ~oldext & XFS_RMAP_UNWRITTEN; > + > + /* > + * Set flags determining what part of the previous oldext allocation > + * extent is being replaced by a newext allocation. > + */ > + if (PREV.rm_offset == offset) > + state |= RMAP_LEFT_FILLING; > + if (PREV.rm_offset + PREV.rm_blockcount == new_endoff) > + state |= RMAP_RIGHT_FILLING; > + > + /* > + * Decrement the cursor to see if we have a left-adjacent record to our > + * insertion point. This will give us the record for end block > + * contiguity tests. > + */ > + error = xfs_btree_decrement(cur, 0, &i); > + if (error) > + goto done; > + if (i) { > + state |= RMAP_LEFT_VALID; > + error = xfs_rmap_get_rec(cur, &LEFT, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + XFS_WANT_CORRUPTED_GOTO(mp, > + LEFT.rm_startblock + LEFT.rm_blockcount <= bno, > + done); > + trace_xfs_rmap_find_left_neighbor_result(cur->bc_mp, > + cur->bc_private.a.agno, LEFT.rm_startblock, > + LEFT.rm_blockcount, LEFT.rm_owner, > + LEFT.rm_offset, LEFT.rm_flags); > + if (LEFT.rm_startblock + LEFT.rm_blockcount == bno && > + LEFT.rm_offset + LEFT.rm_blockcount == offset && > + xfs_rmap_is_mergeable(&LEFT, owner, offset, len, newext)) > + state |= RMAP_LEFT_CONTIG; > + } > + > + /* > + * Increment the cursor to see if we have a right-adjacent record to our > + * insertion point. This will give us the record for end block > + * contiguity tests. > + */ > + error = xfs_btree_increment(cur, 0, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + error = xfs_btree_increment(cur, 0, &i); > + if (error) > + goto done; > + if (i) { > + state |= RMAP_RIGHT_VALID; > + error = xfs_rmap_get_rec(cur, &RIGHT, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + XFS_WANT_CORRUPTED_GOTO(mp, bno + len <= RIGHT.rm_startblock, > + done); > + trace_xfs_rmap_convert_gtrec(cur->bc_mp, > + cur->bc_private.a.agno, RIGHT.rm_startblock, > + RIGHT.rm_blockcount, RIGHT.rm_owner, > + RIGHT.rm_offset, RIGHT.rm_flags); > + if (bno + len == RIGHT.rm_startblock && > + offset + len == RIGHT.rm_offset && > + xfs_rmap_is_mergeable(&RIGHT, owner, offset, len, newext)) > + state |= RMAP_RIGHT_CONTIG; > + } > + > + /* check that left + prev + right is not too long */ > + if ((state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | > + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) == > + (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | > + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG) && > + (unsigned long)LEFT.rm_blockcount + len + > + RIGHT.rm_blockcount > XFS_RMAP_LEN_MAX) > + state &= ~RMAP_RIGHT_CONTIG; > + > + trace_xfs_rmap_convert_state(mp, cur->bc_private.a.agno, state, > + _RET_IP_); > + > + /* reset the cursor back to PREV */ > + error = xfs_rmap_lookup_le(cur, bno, len, owner, offset, oldext, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + > + /* > + * Switch out based on the FILLING and CONTIG state bits. > + */ > + switch (state & (RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | > + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG)) { > + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | > + RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: > + /* > + * Setting all of a previous oldext extent to newext. > + * The left and right neighbors are both contiguous with new. > + */ > + error = xfs_btree_increment(cur, 0, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, > + RIGHT.rm_startblock, RIGHT.rm_blockcount, > + RIGHT.rm_owner, RIGHT.rm_offset, > + RIGHT.rm_flags); > + error = xfs_btree_delete(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + error = xfs_btree_decrement(cur, 0, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, > + PREV.rm_startblock, PREV.rm_blockcount, > + PREV.rm_owner, PREV.rm_offset, > + PREV.rm_flags); > + error = xfs_btree_delete(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + error = xfs_btree_decrement(cur, 0, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + NEW = LEFT; > + NEW.rm_blockcount += PREV.rm_blockcount + RIGHT.rm_blockcount; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + break; > + > + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: > + /* > + * Setting all of a previous oldext extent to newext. > + * The left neighbor is contiguous, the right is not. > + */ > + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, > + PREV.rm_startblock, PREV.rm_blockcount, > + PREV.rm_owner, PREV.rm_offset, > + PREV.rm_flags); > + error = xfs_btree_delete(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + error = xfs_btree_decrement(cur, 0, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + NEW = LEFT; > + NEW.rm_blockcount += PREV.rm_blockcount; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + break; > + > + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: > + /* > + * Setting all of a previous oldext extent to newext. > + * The right neighbor is contiguous, the left is not. > + */ > + error = xfs_btree_increment(cur, 0, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + trace_xfs_rmapbt_delete(mp, cur->bc_private.a.agno, > + RIGHT.rm_startblock, RIGHT.rm_blockcount, > + RIGHT.rm_owner, RIGHT.rm_offset, > + RIGHT.rm_flags); > + error = xfs_btree_delete(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + error = xfs_btree_decrement(cur, 0, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + NEW.rm_startblock = bno; > + NEW.rm_owner = owner; > + NEW.rm_offset = offset; > + NEW.rm_blockcount = len + RIGHT.rm_blockcount; > + NEW.rm_flags = newext; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + break; > + > + case RMAP_LEFT_FILLING | RMAP_RIGHT_FILLING: > + /* > + * Setting all of a previous oldext extent to newext. > + * Neither the left nor right neighbors are contiguous with > + * the new one. > + */ > + NEW = PREV; > + NEW.rm_flags = newext; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + break; > + > + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG: > + /* > + * Setting the first part of a previous oldext extent to newext. > + * The left neighbor is contiguous. > + */ > + NEW = PREV; > + NEW.rm_offset += len; > + NEW.rm_startblock += len; > + NEW.rm_blockcount -= len; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + error = xfs_btree_decrement(cur, 0, &i); > + if (error) > + goto done; > + NEW = LEFT; > + NEW.rm_blockcount += len; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + break; > + > + case RMAP_LEFT_FILLING: > + /* > + * Setting the first part of a previous oldext extent to newext. > + * The left neighbor is not contiguous. > + */ > + NEW = PREV; > + NEW.rm_startblock += len; > + NEW.rm_offset += len; > + NEW.rm_blockcount -= len; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + NEW.rm_startblock = bno; > + NEW.rm_owner = owner; > + NEW.rm_offset = offset; > + NEW.rm_blockcount = len; > + NEW.rm_flags = newext; > + cur->bc_rec.r = NEW; > + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, > + len, owner, offset, newext); > + error = xfs_btree_insert(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + break; > + > + case RMAP_RIGHT_FILLING | RMAP_RIGHT_CONTIG: > + /* > + * Setting the last part of a previous oldext extent to newext. > + * The right neighbor is contiguous with the new allocation. > + */ > + NEW = PREV; > + NEW.rm_blockcount -= len; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + error = xfs_btree_increment(cur, 0, &i); > + if (error) > + goto done; > + NEW = RIGHT; > + NEW.rm_offset = offset; > + NEW.rm_startblock = bno; > + NEW.rm_blockcount += len; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + break; > + > + case RMAP_RIGHT_FILLING: > + /* > + * Setting the last part of a previous oldext extent to newext. > + * The right neighbor is not contiguous. > + */ > + NEW = PREV; > + NEW.rm_blockcount -= len; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, > + oldext, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); > + NEW.rm_startblock = bno; > + NEW.rm_owner = owner; > + NEW.rm_offset = offset; > + NEW.rm_blockcount = len; > + NEW.rm_flags = newext; > + cur->bc_rec.r = NEW; > + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, > + len, owner, offset, newext); > + error = xfs_btree_insert(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + break; > + > + case 0: > + /* > + * Setting the middle part of a previous oldext extent to > + * newext. Contiguity is impossible here. > + * One extent becomes three extents. > + */ > + /* new right extent - oldext */ > + NEW.rm_startblock = bno + len; > + NEW.rm_owner = owner; > + NEW.rm_offset = new_endoff; > + NEW.rm_blockcount = PREV.rm_offset + PREV.rm_blockcount - > + new_endoff; > + NEW.rm_flags = PREV.rm_flags; > + error = xfs_rmap_update(cur, &NEW); > + if (error) > + goto done; > + /* new left extent - oldext */ > + NEW = PREV; > + NEW.rm_blockcount = offset - PREV.rm_offset; > + cur->bc_rec.r = NEW; > + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, > + NEW.rm_startblock, NEW.rm_blockcount, > + NEW.rm_owner, NEW.rm_offset, > + NEW.rm_flags); > + error = xfs_btree_insert(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + /* > + * Reset the cursor to the position of the new extent > + * we are about to insert as we can't trust it after > + * the previous insert. > + */ > + error = xfs_rmap_lookup_eq(cur, bno, len, owner, offset, > + oldext, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 0, done); > + /* new middle extent - newext */ > + cur->bc_rec.b.br_state = newext; Wrong, should be: cur->bc_rec.r.rm_flags &= ~XFS_RMAP_UNWRITTEN; cur->bc_rec.r.rm_flags |= newext; We're modifying the rmapbt here, not the bmbt, so it makes no sense to touch the bmbt_irec in the cursor. Modify the rmap_irec instead. Incidentally this just happens not to fail because the fields line up.... --D > + trace_xfs_rmapbt_insert(mp, cur->bc_private.a.agno, bno, len, > + owner, offset, newext); > + error = xfs_btree_insert(cur, &i); > + if (error) > + goto done; > + XFS_WANT_CORRUPTED_GOTO(mp, i == 1, done); > + break; > + > + case RMAP_LEFT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: > + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: > + case RMAP_LEFT_FILLING | RMAP_RIGHT_CONTIG: > + case RMAP_RIGHT_FILLING | RMAP_LEFT_CONTIG: > + case RMAP_LEFT_CONTIG | RMAP_RIGHT_CONTIG: > + case RMAP_LEFT_CONTIG: > + case RMAP_RIGHT_CONTIG: > + /* > + * These cases are all impossible. > + */ > + ASSERT(0); > + } > + > + trace_xfs_rmap_convert_done(mp, cur->bc_private.a.agno, bno, len, > + unwritten, oinfo); > +done: > + if (error) > + trace_xfs_rmap_convert_error(cur->bc_mp, > + cur->bc_private.a.agno, error, _RET_IP_); > + return error; > +} > + > +#undef NEW > +#undef LEFT > +#undef RIGHT > +#undef PREV > + > struct xfs_rmapbt_query_range_info { > xfs_rmapbt_query_range_fn fn; > void *priv; > diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h > index 3ebceb0..6466adc 100644 > --- a/fs/xfs/xfs_trace.h > +++ b/fs/xfs/xfs_trace.h > @@ -2497,6 +2497,10 @@ DEFINE_RMAP_EVENT(xfs_rmap_free_extent_error); > DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent); > DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_done); > DEFINE_RMAP_EVENT(xfs_rmap_alloc_extent_error); > +DEFINE_RMAP_EVENT(xfs_rmap_convert); > +DEFINE_RMAP_EVENT(xfs_rmap_convert_done); > +DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_error); > +DEFINE_AG_ERROR_EVENT(xfs_rmap_convert_state); > > DECLARE_EVENT_CLASS(xfs_rmapbt_class, > TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, > @@ -2551,6 +2555,8 @@ DEFINE_AG_ERROR_EVENT(xfs_rmapbt_delete_error); > DEFINE_AG_ERROR_EVENT(xfs_rmapbt_update_error); > DEFINE_RMAPBT_EVENT(xfs_rmap_lookup_le_range_result); > DEFINE_RMAPBT_EVENT(xfs_rmap_map_gtrec); > +DEFINE_RMAPBT_EVENT(xfs_rmap_convert_gtrec); > +DEFINE_RMAPBT_EVENT(xfs_rmap_find_left_neighbor_result); > > #endif /* _TRACE_XFS_H */ > > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From wagi@monom.org Thu Jun 30 01:04:18 2016 Return-Path: <wagi@monom.org> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 658D87CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 01:04:18 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 261D4304032 for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 23:04:15 -0700 (PDT) X-ASG-Debug-ID: 1467266651-04bdf074b42244e0001-NocioJ Received: from hotel311.server4you.de (hotel311.server4you.de [85.25.146.15]) by cuda.sgi.com with ESMTP id TTufZYY2pKALjPgg (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Wed, 29 Jun 2016 23:04:12 -0700 (PDT) X-Barracuda-Envelope-From: wagi@monom.org X-Barracuda-Effective-Source-IP: hotel311.server4you.de[85.25.146.15] X-Barracuda-Apparent-Source-IP: 85.25.146.15 Received: from hotel311.server4you.de (localhost [127.0.0.1]) by filter.mynetwork.local (Postfix) with ESMTP id BBBD11940750; Thu, 30 Jun 2016 08:04:09 +0200 (CEST) Received: from [10.10.50.60] (unknown [212.118.206.70]) by hotel311.server4you.de (Postfix) with ESMTPSA id 7BCAC1940129; Thu, 30 Jun 2016 08:04:09 +0200 (CEST) Subject: Re: crash in xfs in current To: Dave Chinner <david@fromorbit.com>, Reinoud Koornstra <reinoudkoornstra@gmail.com> X-ASG-Orig-Subj: Re: crash in xfs in current References: <48817b4c-26f4-5eb6-8a97-d8fa34fe7f6a@monom.org> <20160607134442.GA1803@infradead.org> <CAAA5faFWyPDienm2NbHkafZh-RvbjJp6f_zDq62z6rC1d1Vzyw@mail.gmail.com> <CAAA5faGXHJZPWkkxDM-kvHqh--hPhnD1Y8RuaaSmuzgiz=_LDg@mail.gmail.com> <CAAA5faEDdR_L6y9ShhUcermgvjtmzNCzwoYeENjx+8RUEMdwaA@mail.gmail.com> <20160609022238.GY26977@dastard> <CAAA5faGL_Nyu=jW2Vrgr_m7crhnB9BriWWzMAPODbiQATFhS=Q@mail.gmail.com> <00bbe658-a891-3771-ca1d-5661a8b6ab61@sandeen.net> <CAAA5faH7RA=_WByj6uh4yVCLgwxkLh88CkrtTOa-qJqdyEDT-A@mail.gmail.com> <CAAA5faGTL4i3YS_oLxoeetpsEt+q59dmc2L7Kc-b5khzoV0GvA@mail.gmail.com> <20160622014253.GS12670@dastard> Cc: Eric Sandeen <sandeen@sandeen.net>, Christoph Hellwig <hch@infradead.org>, viro@zeniv.linux.org.uk, xfs@oss.sgi.com From: Daniel Wagner <wagi@monom.org> Message-ID: <c5c53ec1-cc9f-2b50-079a-4d0b4f405558@monom.org> Date: Thu, 30 Jun 2016 08:04:09 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <20160622014253.GS12670@dastard> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit X-Barracuda-Connect: hotel311.server4you.de[85.25.146.15] X-Barracuda-Start-Time: 1467266652 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 939 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30890 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header > Ok, that's good to hear. Now for some more testing: Al Viro just > pushed some fixes to the parallel lookup code that may fix this > problem. Al asked this question: > > | Can that be triggered on 4e82901 + cherry-pick of e7d6ef979? > | Same for 9f541801 + e7d6ef979? > > Those commits are all in the current Linus tree - would you be > able to test them? (i.e. check out tree to 4e82901, then just > cherry pick the single commit (e7d6ef979) on top of that). Finally I found some time to do some testing. In one shell, git did some checkouts: while true; do git checkout master && git checkout b4.0; done While in the other shell I just rebuild a kernel: while true; do make clean && make -j200; done 4e82901 crashed after 10 minutes 4e82901 + e7d6ef979 no crash after 4 hours 9f541801 no crash after 2 hours 9f541801 + e7d6ef979 no crash after 12 hours cheers, daniel From bfoster@redhat.com Thu Jun 30 07:53:56 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 1BBD87CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 07:53:56 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id E3DBE304039 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 05:53:52 -0700 (PDT) X-ASG-Debug-ID: 1467291230-04cb6c063d2c1b60001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id J5qwsiDSIHsfimk1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 05:53:51 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9BDE563171 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:53:50 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UCroSu017061 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:53:50 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 556BC1200E8; Thu, 30 Jun 2016 08:53:49 -0400 (EDT) From: Brian Foster <bfoster@redhat.com> To: xfs@oss.sgi.com Subject: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic Date: Thu, 30 Jun 2016 08:53:49 -0400 X-ASG-Orig-Subj: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic Message-Id: <1467291229-13548-1-git-send-email-bfoster@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 30 Jun 2016 12:53:50 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467291231 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2766 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Newly allocated XFS metadata buffers are added to the LRU once the hold count is released, which typically occurs after I/O completion. There is no other mechanism at current that tracks the existence or I/O state of a new buffer. Further, readahead I/O tends to be submitted asynchronously by nature, which means the I/O can remain in flight and actually complete long after the calling context is gone. This means that file descriptors or any other holds on the filesystem can be released, allowing the filesystem to be unmounted while I/O is still in flight. When I/O completion occurs, core data structures may have been freed, causing completion to run into invalid memory accesses and likely to panic. This problem is reproduced on XFS via directory readahead. A filesystem is mounted, a directory is opened/closed and the filesystem immediately unmounted. The open/close cycle triggers a directory readahead that if delayed long enough, runs buffer I/O completion after the unmount has completed. To work around this problem, add readahead buffers to the LRU earlier than other buffers (when the buffer is allocated, specifically). The buffer hold count will ultimately remain until I/O completion, which means any shrinker activity will skip the buffer until then. This makes the buffer visible to xfs_wait_buftarg(), however, which ensures that an unmount or quiesce waits for I/O completion appropriately. Signed-off-by: Brian Foster <bfoster@redhat.com> --- This addresses the problem reproduced by the recently posted xfstests test: http://thread.gmane.org/gmane.comp.file-systems.fstests/2740 This could probably be made more involved, i.e., to create another list of buffers in flight or some such. This seems more simple/sane to me, however, and survives my testing so far... Brian fs/xfs/xfs_buf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 4665ff6..3f03df9 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -590,8 +590,20 @@ xfs_buf_get_map( return NULL; } + /* + * If the buffer found doesn't match the one allocated above, somebody + * else beat us to insertion and we can toss the new one. + * + * If we did add the buffer and it happens to be readahead, add to the + * LRU now rather than waiting until the hold is released. Otherwise, + * the buffer is not visible to xfs_wait_buftarg() while in flight and + * nothing else prevents an unmount before I/O completion. + */ if (bp != new_bp) xfs_buf_free(new_bp); + else if (flags & XBF_READ_AHEAD && + list_lru_add(&bp->b_target->bt_lru, &bp->b_lru)) + atomic_inc(&bp->b_hold); found: if (!bp->b_addr) { -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:47:27 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 6BA6D7CA2 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:47:27 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1FA3130404E for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:24 -0700 (PDT) X-ASG-Debug-ID: 1467294442-04bdf074b7238640001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 3Ov1Ampyik5GtHDb (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:22 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A373881F03; Thu, 30 Jun 2016 13:47:21 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsb005273; Thu, 30 Jun 2016 09:47:14 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 00/22] Richacls (Core and Ext4) Date: Thu, 30 Jun 2016 15:46:51 +0200 X-ASG-Orig-Subj: [PATCH v23 00/22] Richacls (Core and Ext4) Message-Id: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 30 Jun 2016 13:47:22 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294442 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4776 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Here is another update of the richacl patches. Changes since the last posting (https://lwn.net/Articles/689151/): * Rebase on top of 4.7-rc5+ because of commit 999653786d "nfsd: check permissions when setting ACLs". * Introduce set_richacl() similar to set_posix_acl() and use it in nfsd to avoid going through the richacl xattr representation. The complete patch queue is available here: git://git.kernel.org/pub/scm/linux/kernel/git/agruen/linux-richacl.git \ richacl-2016-06-30 The richacl user-space utilitites, man pages, and test suite are available here: https://github.com/andreas-gruenbacher/richacl Changes to other user-space packages for richacl: https://github.com/andreas-gruenbacher/coreutils https://github.com/andreas-gruenbacher/e2fsprogs https://github.com/andreas-gruenbacher/samba https://github.com/andreas-gruenbacher/xfsprogs-dev https://github.com/andreas-gruenbacher/nfs-utils Please see the richacl homepage for more information: http://www.bestbits.at/richacl/ What more needs to be done to get this initial set of patches merged? Thanks, Andreas Andreas Gruenbacher (20): vfs: Add IS_ACL() and IS_RICHACL() tests vfs: Add MAY_CREATE_FILE and MAY_CREATE_DIR permission flags vfs: Add MAY_DELETE_SELF and MAY_DELETE_CHILD permission flags vfs: Make the inode passed to inode_change_ok non-const vfs: Add permission flags for setting file attributes richacl: In-memory representation and helper functions richacl: Permission mapping functions richacl: Compute maximum file masks from an acl richacl: Permission check algorithm posix_acl: Improve xattr fixup code vfs: Cache base_acl objects in inodes vfs: Add get_richacl and set_richacl inode operations vfs: Cache richacl in struct inode richacl: Update the file masks in chmod() richacl: Check if an acl is equivalent to a file mode richacl: Create-time inheritance richacl: Automatic Inheritance richacl: xattr mapping functions richacl: Add richacl xattr handler vfs: Add richacl permission checking Aneesh Kumar K.V (2): ext4: Add richacl support ext4: Add richacl feature flag drivers/staging/lustre/lustre/llite/llite_lib.c | 2 +- fs/9p/acl.c | 8 +- fs/Kconfig | 3 + fs/Makefile | 1 + fs/attr.c | 81 ++- fs/ext4/Kconfig | 11 + fs/ext4/Makefile | 1 + fs/ext4/ext4.h | 6 +- fs/ext4/file.c | 3 + fs/ext4/ialloc.c | 11 +- fs/ext4/inode.c | 5 +- fs/ext4/namei.c | 5 + fs/ext4/richacl.c | 134 ++++ fs/ext4/richacl.h | 40 ++ fs/ext4/super.c | 49 +- fs/ext4/xattr.c | 7 + fs/f2fs/acl.c | 4 +- fs/inode.c | 43 +- fs/jffs2/acl.c | 6 +- fs/namei.c | 152 +++- fs/nfs/nfs3acl.c | 14 +- fs/posix_acl.c | 69 +- fs/richacl.c | 915 ++++++++++++++++++++++++ fs/richacl_xattr.c | 222 ++++++ fs/xattr.c | 29 +- include/linux/acl.h | 15 + include/linux/fs.h | 67 +- include/linux/posix_acl.h | 21 +- include/linux/richacl.h | 211 ++++++ include/linux/richacl_xattr.h | 31 + include/uapi/linux/Kbuild | 2 + include/uapi/linux/fs.h | 3 +- include/uapi/linux/richacl.h | 152 ++++ include/uapi/linux/richacl_xattr.h | 44 ++ include/uapi/linux/xattr.h | 2 + 35 files changed, 2209 insertions(+), 160 deletions(-) create mode 100644 fs/ext4/richacl.c create mode 100644 fs/ext4/richacl.h create mode 100644 fs/richacl.c create mode 100644 fs/richacl_xattr.c create mode 100644 include/linux/acl.h create mode 100644 include/linux/richacl.h create mode 100644 include/linux/richacl_xattr.h create mode 100644 include/uapi/linux/richacl.h create mode 100644 include/uapi/linux/richacl_xattr.h -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:47:41 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4C76C7CA2 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:47:41 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id B9D5DAC007 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:37 -0700 (PDT) X-ASG-Debug-ID: 1467294455-04cbb027373b6260001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 2O6QFNIb86Rbj68F (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:36 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 650CEC05B1D0; Thu, 30 Jun 2016 13:47:35 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsd005273; Thu, 30 Jun 2016 09:47:29 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 02/22] vfs: Add MAY_CREATE_FILE and MAY_CREATE_DIR permission flags Date: Thu, 30 Jun 2016 15:46:53 +0200 X-ASG-Orig-Subj: [PATCH v23 02/22] vfs: Add MAY_CREATE_FILE and MAY_CREATE_DIR permission flags Message-Id: <1467294433-3222-3-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 30 Jun 2016 13:47:35 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294456 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7068 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Richacls distinguish between creating non-directories and directories. To support that, add an isdir parameter to may_create(). When checking inode_permission() for create permission, pass in an additional MAY_CREATE_FILE or MAY_CREATE_DIR mask flag. Add may_replace() to allow checking for delete and create access when replacing an existing file in vfs_rename(). Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> Reviewed-by: Andreas Dilger <adilger@dilger.ca> Reviewed-by: Steve French <steve.french@primarydata.com> --- fs/namei.c | 49 +++++++++++++++++++++++++++++++++---------------- include/linux/fs.h | 2 ++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 7cc5487..dc91858 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -454,7 +454,9 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask) * this, letting us set arbitrary permissions for filesystem access without * changing the "normal" UIDs which are used for other things. * - * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask. + * MAY_WRITE must be set in @mask whenever MAY_APPEND, MAY_CREATE_FILE, or + * MAY_CREATE_DIR are set. That way, file systems that don't support these + * permissions will check for MAY_WRITE instead. */ int inode_permission(struct inode *inode, int mask) { @@ -2763,7 +2765,8 @@ EXPORT_SYMBOL(__check_sticky); * 10. We don't allow removal of NFS sillyrenamed files; it's handled by * nfs_async_unlink(). */ -static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) +static int may_delete_or_replace(struct inode *dir, struct dentry *victim, + bool isdir, int mask) { struct inode *inode = d_backing_inode(victim); int error; @@ -2775,7 +2778,7 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) BUG_ON(victim->d_parent->d_inode != dir); audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); - error = inode_permission(dir, MAY_WRITE | MAY_EXEC); + error = inode_permission(dir, mask); if (error) return error; if (IS_APPEND(dir)) @@ -2798,6 +2801,18 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) return 0; } +static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) +{ + return may_delete_or_replace(dir, victim, isdir, MAY_WRITE | MAY_EXEC); +} + +static int may_replace(struct inode *dir, struct dentry *victim, bool isdir) +{ + int mask = isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE; + + return may_delete_or_replace(dir, victim, isdir, mask | MAY_WRITE | MAY_EXEC); +} + /* Check whether we can create an object with dentry child in directory * dir. * 1. We can't do it if child already exists (open has special treatment for @@ -2806,14 +2821,16 @@ static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) * 3. We should have write and exec permissions on dir * 4. We can't do it if dir is immutable (done in permission()) */ -static inline int may_create(struct inode *dir, struct dentry *child) +static inline int may_create(struct inode *dir, struct dentry *child, bool isdir) { + int mask = isdir ? MAY_CREATE_DIR : MAY_CREATE_FILE; + audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE); if (child->d_inode) return -EEXIST; if (IS_DEADDIR(dir)) return -ENOENT; - return inode_permission(dir, MAY_WRITE | MAY_EXEC); + return inode_permission(dir, MAY_WRITE | MAY_EXEC | mask); } /* @@ -2863,7 +2880,7 @@ EXPORT_SYMBOL(unlock_rename); int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool want_excl) { - int error = may_create(dir, dentry); + int error = may_create(dir, dentry, false); if (error) return error; @@ -3650,7 +3667,7 @@ EXPORT_SYMBOL(user_path_create); int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { - int error = may_create(dir, dentry); + int error = may_create(dir, dentry, false); if (error) return error; @@ -3744,7 +3761,7 @@ SYSCALL_DEFINE3(mknod, const char __user *, filename, umode_t, mode, unsigned, d int vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { - int error = may_create(dir, dentry); + int error = may_create(dir, dentry, true); unsigned max_links = dir->i_sb->s_max_links; if (error) @@ -3800,7 +3817,7 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode) int vfs_rmdir(struct inode *dir, struct dentry *dentry) { - int error = may_delete(dir, dentry, 1); + int error = may_delete(dir, dentry, true); if (error) return error; @@ -3922,7 +3939,7 @@ SYSCALL_DEFINE1(rmdir, const char __user *, pathname) int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegated_inode) { struct inode *target = dentry->d_inode; - int error = may_delete(dir, dentry, 0); + int error = may_delete(dir, dentry, false); if (error) return error; @@ -4056,7 +4073,7 @@ SYSCALL_DEFINE1(unlink, const char __user *, pathname) int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) { - int error = may_create(dir, dentry); + int error = may_create(dir, dentry, false); if (error) return error; @@ -4139,7 +4156,7 @@ int vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_de if (!inode) return -ENOENT; - error = may_create(dir, new_dentry); + error = may_create(dir, new_dentry, false); if (error) return error; @@ -4336,14 +4353,14 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry, return error; if (!target) { - error = may_create(new_dir, new_dentry); + error = may_create(new_dir, new_dentry, is_dir); } else { new_is_dir = d_is_dir(new_dentry); if (!(flags & RENAME_EXCHANGE)) - error = may_delete(new_dir, new_dentry, is_dir); + error = may_replace(new_dir, new_dentry, is_dir); else - error = may_delete(new_dir, new_dentry, new_is_dir); + error = may_replace(new_dir, new_dentry, new_is_dir); } if (error) return error; @@ -4606,7 +4623,7 @@ SYSCALL_DEFINE2(rename, const char __user *, oldname, const char __user *, newna int vfs_whiteout(struct inode *dir, struct dentry *dentry) { - int error = may_create(dir, dentry); + int error = may_create(dir, dentry, false); if (error) return error; diff --git a/include/linux/fs.h b/include/linux/fs.h index 4ad130c..dd614ad 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -84,6 +84,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define MAY_CHDIR 0x00000040 /* called from RCU mode, don't block */ #define MAY_NOT_BLOCK 0x00000080 +#define MAY_CREATE_FILE 0x00000100 +#define MAY_CREATE_DIR 0x00000200 /* * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:47:45 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id E7D067CB0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:47:44 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 638FDAC007 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:44 -0700 (PDT) X-ASG-Debug-ID: 1467294462-04cb6c063e2c42c0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id qYQ3saIH5t6ER9X9 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:43 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 65E76811DF; Thu, 30 Jun 2016 13:47:42 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDse005273; Thu, 30 Jun 2016 09:47:35 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 03/22] vfs: Add MAY_DELETE_SELF and MAY_DELETE_CHILD permission flags Date: Thu, 30 Jun 2016 15:46:54 +0200 X-ASG-Orig-Subj: [PATCH v23 03/22] vfs: Add MAY_DELETE_SELF and MAY_DELETE_CHILD permission flags Message-Id: <1467294433-3222-4-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 30 Jun 2016 13:47:42 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294463 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3400 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Normally, deleting a file requires MAY_WRITE access to the parent directory. With richacls, a file may be deleted with MAY_DELETE_CHILD access to the parent directory or with MAY_DELETE_SELF access to the file. To support that, pass the MAY_DELETE_CHILD mask flag to inode_permission() when checking for delete access inside a directory, and MAY_DELETE_SELF when checking for delete access to a file itelf. The MAY_DELETE_SELF permission overrides the sticky directory check. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> Reviewed-by: Steve French <steve.french@primarydata.com> --- fs/namei.c | 20 ++++++++++++-------- include/linux/fs.h | 2 ++ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index dc91858..663933e 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -454,9 +454,9 @@ static int sb_permission(struct super_block *sb, struct inode *inode, int mask) * this, letting us set arbitrary permissions for filesystem access without * changing the "normal" UIDs which are used for other things. * - * MAY_WRITE must be set in @mask whenever MAY_APPEND, MAY_CREATE_FILE, or - * MAY_CREATE_DIR are set. That way, file systems that don't support these - * permissions will check for MAY_WRITE instead. + * MAY_WRITE must be set in @mask whenever MAY_APPEND, MAY_CREATE_FILE, + * MAY_CREATE_DIR, or MAY_DELETE_CHILD are set. That way, file systems that + * don't support these permissions will check for MAY_WRITE instead. */ int inode_permission(struct inode *inode, int mask) { @@ -2778,14 +2778,18 @@ static int may_delete_or_replace(struct inode *dir, struct dentry *victim, BUG_ON(victim->d_parent->d_inode != dir); audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); - error = inode_permission(dir, mask); + error = inode_permission(dir, mask | MAY_WRITE | MAY_DELETE_CHILD); + if (!error && check_sticky(dir, inode)) + error = -EPERM; + if (error && IS_RICHACL(inode) && + inode_permission(inode, MAY_DELETE_SELF) == 0 && + inode_permission(dir, mask) == 0) + error = 0; if (error) return error; if (IS_APPEND(dir)) return -EPERM; - - if (check_sticky(dir, inode) || IS_APPEND(inode) || - IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) + if (IS_APPEND(inode) || IS_IMMUTABLE(inode) || IS_SWAPFILE(inode)) return -EPERM; if (isdir) { if (!d_is_dir(victim)) @@ -2803,7 +2807,7 @@ static int may_delete_or_replace(struct inode *dir, struct dentry *victim, static int may_delete(struct inode *dir, struct dentry *victim, bool isdir) { - return may_delete_or_replace(dir, victim, isdir, MAY_WRITE | MAY_EXEC); + return may_delete_or_replace(dir, victim, isdir, MAY_EXEC); } static int may_replace(struct inode *dir, struct dentry *victim, bool isdir) diff --git a/include/linux/fs.h b/include/linux/fs.h index dd614ad..86bfa10 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -86,6 +86,8 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define MAY_NOT_BLOCK 0x00000080 #define MAY_CREATE_FILE 0x00000100 #define MAY_CREATE_DIR 0x00000200 +#define MAY_DELETE_CHILD 0x00000400 +#define MAY_DELETE_SELF 0x00000800 /* * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:47:47 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 1E18B7CB4 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:47:47 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9AEDAAC007 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:46 -0700 (PDT) X-ASG-Debug-ID: 1467294449-04cb6c063c2c4240001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id HvaChjLNKfYppGcU (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:29 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 895803710EB; Thu, 30 Jun 2016 13:47:28 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsc005273; Thu, 30 Jun 2016 09:47:22 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 01/22] vfs: Add IS_ACL() and IS_RICHACL() tests Date: Thu, 30 Jun 2016 15:46:52 +0200 X-ASG-Orig-Subj: [PATCH v23 01/22] vfs: Add IS_ACL() and IS_RICHACL() tests Message-Id: <1467294433-3222-2-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 30 Jun 2016 13:47:28 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294449 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4048 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 The vfs does not apply the umask for file systems that support acls. The test used for this used to be called IS_POSIXACL(). Switch to a new IS_ACL() test to check for either posix acls or richacls instead. Add a new MS_RICHACL flag and IS_RICHACL() test for richacls alone. The IS_POSIXACL() test is still needed in some places like nfsd. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> Reviewed-by: Andreas Dilger <adilger@dilger.ca> Reviewed-by: Steve French <steve.french@primarydata.com> --- fs/Kconfig | 3 +++ fs/namei.c | 6 +++--- include/linux/fs.h | 12 ++++++++++++ include/uapi/linux/fs.h | 3 ++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/fs/Kconfig b/fs/Kconfig index b8fcb41..de6de55 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -64,6 +64,9 @@ endif # BLOCK config FS_POSIX_ACL def_bool n +config FS_RICHACL + def_bool n + config EXPORTFS tristate diff --git a/fs/namei.c b/fs/namei.c index 70580ab..7cc5487 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3115,7 +3115,7 @@ static int lookup_open(struct nameidata *nd, struct path *path, * O_EXCL open we want to return EEXIST not EROFS). */ if (open_flag & O_CREAT) { - if (!IS_POSIXACL(dir->d_inode)) + if (!IS_ACL(dir->d_inode)) mode &= ~current_umask(); if (unlikely(!got_write)) { create_error = -EROFS; @@ -3709,7 +3709,7 @@ retry: if (IS_ERR(dentry)) return PTR_ERR(dentry); - if (!IS_POSIXACL(path.dentry->d_inode)) + if (!IS_ACL(path.dentry->d_inode)) mode &= ~current_umask(); error = security_path_mknod(&path, dentry, mode, dev); if (error) @@ -3780,7 +3780,7 @@ retry: if (IS_ERR(dentry)) return PTR_ERR(dentry); - if (!IS_POSIXACL(path.dentry->d_inode)) + if (!IS_ACL(path.dentry->d_inode)) mode &= ~current_umask(); error = security_path_mkdir(&path, dentry, mode); if (!error) diff --git a/include/linux/fs.h b/include/linux/fs.h index dd28814..4ad130c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1850,6 +1850,12 @@ struct super_operations { #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL) +#ifdef CONFIG_FS_RICHACL +#define IS_RICHACL(inode) __IS_FLG(inode, MS_RICHACL) +#else +#define IS_RICHACL(inode) 0 +#endif + #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD) #define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME) #define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) @@ -1863,6 +1869,12 @@ struct super_operations { (inode)->i_rdev == WHITEOUT_DEV) /* + * IS_ACL() tells the VFS to not apply the umask + * and use check_acl for acl permission checks when defined. + */ +#define IS_ACL(inode) __IS_FLG(inode, MS_POSIXACL | MS_RICHACL) + +/* * Inode state bits. Protected by inode->i_lock * * Three bits determine the dirty state of the inode, I_DIRTY_SYNC, diff --git a/include/uapi/linux/fs.h b/include/uapi/linux/fs.h index 3b00f7c..f9c41ef 100644 --- a/include/uapi/linux/fs.h +++ b/include/uapi/linux/fs.h @@ -120,7 +120,7 @@ struct inodes_stat_t { #define MS_VERBOSE 32768 /* War is peace. Verbosity is silence. MS_VERBOSE is deprecated. */ #define MS_SILENT 32768 -#define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ +#define MS_POSIXACL (1<<16) /* Supports POSIX ACLs */ #define MS_UNBINDABLE (1<<17) /* change to unbindable */ #define MS_PRIVATE (1<<18) /* change to private */ #define MS_SLAVE (1<<19) /* change to slave */ @@ -130,6 +130,7 @@ struct inodes_stat_t { #define MS_I_VERSION (1<<23) /* Update inode I_version field */ #define MS_STRICTATIME (1<<24) /* Always perform atime updates */ #define MS_LAZYTIME (1<<25) /* Update the on-disk [acm]times lazily */ +#define MS_RICHACL (1<<26) /* Supports richacls */ /* These sb flags are internal to the kernel */ #define MS_NOSEC (1<<28) -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:47:52 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id F3DDA7CBC for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:47:51 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 610ADAC007 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:51 -0700 (PDT) X-ASG-Debug-ID: 1467294469-04cbb027353b6290001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id dErVISdRGgWUTp90 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:50 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 509233F725; Thu, 30 Jun 2016 13:47:49 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsf005273; Thu, 30 Jun 2016 09:47:42 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 04/22] vfs: Make the inode passed to inode_change_ok non-const Date: Thu, 30 Jun 2016 15:46:55 +0200 X-ASG-Orig-Subj: [PATCH v23 04/22] vfs: Make the inode passed to inode_change_ok non-const Message-Id: <1467294433-3222-5-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 30 Jun 2016 13:47:49 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294470 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1455 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 We will need to call iop->permission and iop->get_acl from inode_change_ok() for additional permission checks, and both take a non-const inode. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> Reviewed-by: Andreas Dilger <adilger@dilger.ca> Reviewed-by: Steve French <steve.french@primarydata.com> --- fs/attr.c | 2 +- include/linux/fs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index 25b24d0..7ca7fa0 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -28,7 +28,7 @@ * Should be called as the first thing in ->setattr implementations, * possibly after taking additional locks. */ -int inode_change_ok(const struct inode *inode, struct iattr *attr) +int inode_change_ok(struct inode *inode, struct iattr *attr) { unsigned int ia_valid = attr->ia_valid; diff --git a/include/linux/fs.h b/include/linux/fs.h index 86bfa10..208f73b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2993,7 +2993,7 @@ extern int buffer_migrate_page(struct address_space *, #define buffer_migrate_page NULL #endif -extern int inode_change_ok(const struct inode *, struct iattr *); +extern int inode_change_ok(struct inode *, struct iattr *); extern int inode_newsize_ok(const struct inode *, loff_t offset); extern void setattr_copy(struct inode *inode, const struct iattr *attr); -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:01 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 940C17CB9 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:01 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 668E48F8050 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:58 -0700 (PDT) X-ASG-Debug-ID: 1467294476-04cb6c063d2c4340001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id opriBZxGlNBXGzDb (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:47:57 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4372D65426; Thu, 30 Jun 2016 13:47:56 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsg005273; Thu, 30 Jun 2016 09:47:49 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 05/22] vfs: Add permission flags for setting file attributes Date: Thu, 30 Jun 2016 15:46:56 +0200 X-ASG-Orig-Subj: [PATCH v23 05/22] vfs: Add permission flags for setting file attributes Message-Id: <1467294433-3222-6-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 30 Jun 2016 13:47:56 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294477 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4621 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Richacls support permissions that allow to take ownership of a file, change the file permissions, and set the file timestamps. Support that by introducing new permission mask flags and by checking for those mask flags in inode_change_ok(). Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> Reviewed-by: Steve French <steve.french@primarydata.com> --- fs/attr.c | 79 +++++++++++++++++++++++++++++++++++++++++++++--------- include/linux/fs.h | 3 +++ 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index 7ca7fa0..2a8c49c 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -17,6 +17,65 @@ #include <linux/ima.h> /** + * inode_extended_permission - permissions beyond read/write/execute + * + * Check for permissions that only richacls can currently grant. + */ +static int inode_extended_permission(struct inode *inode, int mask) +{ + if (!IS_RICHACL(inode)) + return -EPERM; + return inode_permission(inode, mask); +} + +static bool inode_uid_change_ok(struct inode *inode, kuid_t ia_uid) +{ + if (uid_eq(current_fsuid(), inode->i_uid) && + uid_eq(ia_uid, inode->i_uid)) + return true; + if (uid_eq(current_fsuid(), ia_uid) && + inode_extended_permission(inode, MAY_TAKE_OWNERSHIP) == 0) + return true; + if (capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + return true; + return false; +} + +static bool inode_gid_change_ok(struct inode *inode, kgid_t ia_gid) +{ + int in_group = in_group_p(ia_gid); + if (uid_eq(current_fsuid(), inode->i_uid) && + (in_group || gid_eq(ia_gid, inode->i_gid))) + return true; + if (in_group && inode_extended_permission(inode, MAY_TAKE_OWNERSHIP) == 0) + return true; + if (capable_wrt_inode_uidgid(inode, CAP_CHOWN)) + return true; + return false; +} + +/** + * inode_owner_permitted_or_capable + * + * Check for permissions implicitly granted to the owner, like MAY_CHMOD or + * MAY_SET_TIMES. Equivalent to inode_owner_or_capable for file systems + * without support for those permissions. + */ +static bool inode_owner_permitted_or_capable(struct inode *inode, int mask) +{ + struct user_namespace *ns; + + if (uid_eq(current_fsuid(), inode->i_uid)) + return true; + if (inode_extended_permission(inode, mask) == 0) + return true; + ns = current_user_ns(); + if (ns_capable(ns, CAP_FOWNER) && kuid_has_mapping(ns, inode->i_uid)) + return true; + return false; +} + +/** * inode_change_ok - check if attribute changes to an inode are allowed * @inode: inode to check * @attr: attributes to change @@ -47,22 +106,18 @@ int inode_change_ok(struct inode *inode, struct iattr *attr) return 0; /* Make sure a caller can chown. */ - if ((ia_valid & ATTR_UID) && - (!uid_eq(current_fsuid(), inode->i_uid) || - !uid_eq(attr->ia_uid, inode->i_uid)) && - !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) - return -EPERM; + if (ia_valid & ATTR_UID) + if (!inode_uid_change_ok(inode, attr->ia_uid)) + return -EPERM; /* Make sure caller can chgrp. */ - if ((ia_valid & ATTR_GID) && - (!uid_eq(current_fsuid(), inode->i_uid) || - (!in_group_p(attr->ia_gid) && !gid_eq(attr->ia_gid, inode->i_gid))) && - !capable_wrt_inode_uidgid(inode, CAP_CHOWN)) - return -EPERM; + if (ia_valid & ATTR_GID) + if (!inode_gid_change_ok(inode, attr->ia_gid)) + return -EPERM; /* Make sure a caller can chmod. */ if (ia_valid & ATTR_MODE) { - if (!inode_owner_or_capable(inode)) + if (!inode_owner_permitted_or_capable(inode, MAY_CHMOD)) return -EPERM; /* Also check the setgid bit! */ if (!in_group_p((ia_valid & ATTR_GID) ? attr->ia_gid : @@ -73,7 +128,7 @@ int inode_change_ok(struct inode *inode, struct iattr *attr) /* Check for setting the inode time. */ if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) { - if (!inode_owner_or_capable(inode)) + if (!inode_owner_permitted_or_capable(inode, MAY_SET_TIMES)) return -EPERM; } diff --git a/include/linux/fs.h b/include/linux/fs.h index 208f73b..bb36561 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -88,6 +88,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define MAY_CREATE_DIR 0x00000200 #define MAY_DELETE_CHILD 0x00000400 #define MAY_DELETE_SELF 0x00000800 +#define MAY_TAKE_OWNERSHIP 0x00001000 +#define MAY_CHMOD 0x00002000 +#define MAY_SET_TIMES 0x00004000 /* * flags in file.f_mode. Note that FMODE_READ and FMODE_WRITE must correspond -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:06 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0F36C7CC7 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:06 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id D59E78F8064 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:05 -0700 (PDT) X-ASG-Debug-ID: 1467294483-04cbb027363b62c0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id WqLLZwFIUYMbVtGf (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:03 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 36530D64B1; Thu, 30 Jun 2016 13:48:03 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsh005273; Thu, 30 Jun 2016 09:47:56 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 06/22] richacl: In-memory representation and helper functions Date: Thu, 30 Jun 2016 15:46:57 +0200 X-ASG-Orig-Subj: [PATCH v23 06/22] richacl: In-memory representation and helper functions Message-Id: <1467294433-3222-7-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 30 Jun 2016 13:48:03 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294483 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 12573 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 A richacl consists of an NFSv4 acl and an owner, group, and other mask. These three masks correspond to the owner, group, and other file permission bits, but they contain NFSv4 permissions instead of POSIX permissions. Each entry in the NFSv4 acl applies to the file owner (OWNER@), the owning group (GROUP@), everyone (EVERYONE@), or to a specific uid or gid. As in the standard POSIX file permission model, each process is the owner, group, or other file class. A richacl grants a requested access only if the NFSv4 acl in the richacl grants the access (according to the NFSv4 permission check algorithm), and the file mask that applies to the process includes the requested permissions. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> --- fs/Makefile | 1 + fs/richacl.c | 65 ++++++++++++++++ include/linux/richacl.h | 179 +++++++++++++++++++++++++++++++++++++++++++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/richacl.h | 99 ++++++++++++++++++++++++ 5 files changed, 345 insertions(+) create mode 100644 fs/richacl.c create mode 100644 include/linux/richacl.h create mode 100644 include/uapi/linux/richacl.h diff --git a/fs/Makefile b/fs/Makefile index 85b6e13..2b3e6f1 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_COREDUMP) += coredump.o obj-$(CONFIG_SYSCTL) += drop_caches.o obj-$(CONFIG_FHANDLE) += fhandle.o +obj-$(CONFIG_FS_RICHACL) += richacl.o obj-y += quota/ diff --git a/fs/richacl.c b/fs/richacl.c new file mode 100644 index 0000000..bcc6591 --- /dev/null +++ b/fs/richacl.c @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher <agruenba@redhat.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/sched.h> +#include <linux/module.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/richacl.h> + +/** + * richacl_alloc - allocate a richacl + * @count: number of entries + */ +struct richacl * +richacl_alloc(int count, gfp_t gfp) +{ + size_t size = sizeof(struct richacl) + count * sizeof(struct richace); + struct richacl *acl = kzalloc(size, gfp); + + if (acl) { + atomic_set(&acl->a_refcount, 1); + acl->a_count = count; + } + return acl; +} +EXPORT_SYMBOL_GPL(richacl_alloc); + +/** + * richacl_clone - create a copy of a richacl + */ +struct richacl * +richacl_clone(const struct richacl *acl, gfp_t gfp) +{ + int count = acl->a_count; + size_t size = sizeof(struct richacl) + count * sizeof(struct richace); + struct richacl *dup = kmalloc(size, gfp); + + if (dup) { + memcpy(dup, acl, size); + atomic_set(&dup->a_refcount, 1); + } + return dup; +} + +/** + * richace_copy - copy an acl entry + */ +void +richace_copy(struct richace *to, const struct richace *from) +{ + memcpy(to, from, sizeof(struct richace)); +} diff --git a/include/linux/richacl.h b/include/linux/richacl.h new file mode 100644 index 0000000..edb8480 --- /dev/null +++ b/include/linux/richacl.h @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher <agruenba@redhat.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __RICHACL_H +#define __RICHACL_H + +#include <uapi/linux/richacl.h> + +struct richace { + unsigned short e_type; + unsigned short e_flags; + unsigned int e_mask; + union { + kuid_t uid; + kgid_t gid; + unsigned int special; + } e_id; +}; + +struct richacl { + atomic_t a_refcount; + unsigned int a_owner_mask; + unsigned int a_group_mask; + unsigned int a_other_mask; + unsigned short a_count; + unsigned short a_flags; + struct richace a_entries[0]; +}; + +#define richacl_for_each_entry(_ace, _acl) \ + for (_ace = (_acl)->a_entries; \ + _ace != (_acl)->a_entries + (_acl)->a_count; \ + _ace++) + +#define richacl_for_each_entry_reverse(_ace, _acl) \ + for (_ace = (_acl)->a_entries + (_acl)->a_count - 1; \ + _ace != (_acl)->a_entries - 1; \ + _ace--) + +/** + * richacl_get - grab another reference to a richacl handle + */ +static inline struct richacl * +richacl_get(struct richacl *acl) +{ + if (acl) + atomic_inc(&acl->a_refcount); + return acl; +} + +/** + * richacl_put - free a richacl handle + */ +static inline void +richacl_put(struct richacl *acl) +{ + if (acl && atomic_dec_and_test(&acl->a_refcount)) + kfree(acl); +} + +/** + * richace_is_owner - check if @ace is an OWNER@ entry + */ +static inline bool +richace_is_owner(const struct richace *ace) +{ + return (ace->e_flags & RICHACE_SPECIAL_WHO) && + ace->e_id.special == RICHACE_OWNER_SPECIAL_ID; +} + +/** + * richace_is_group - check if @ace is a GROUP@ entry + */ +static inline bool +richace_is_group(const struct richace *ace) +{ + return (ace->e_flags & RICHACE_SPECIAL_WHO) && + ace->e_id.special == RICHACE_GROUP_SPECIAL_ID; +} + +/** + * richace_is_everyone - check if @ace is an EVERYONE@ entry + */ +static inline bool +richace_is_everyone(const struct richace *ace) +{ + return (ace->e_flags & RICHACE_SPECIAL_WHO) && + ace->e_id.special == RICHACE_EVERYONE_SPECIAL_ID; +} + +/** + * richace_is_unix_user - check if @ace applies to a specific user + */ +static inline bool +richace_is_unix_user(const struct richace *ace) +{ + return !(ace->e_flags & RICHACE_SPECIAL_WHO) && + !(ace->e_flags & RICHACE_IDENTIFIER_GROUP); +} + +/** + * richace_is_unix_group - check if @ace applies to a specific group + */ +static inline bool +richace_is_unix_group(const struct richace *ace) +{ + return !(ace->e_flags & RICHACE_SPECIAL_WHO) && + (ace->e_flags & RICHACE_IDENTIFIER_GROUP); +} + +/** + * richace_is_inherit_only - check if @ace is for inheritance only + * + * ACEs with the %RICHACE_INHERIT_ONLY_ACE flag set have no effect during + * permission checking. + */ +static inline bool +richace_is_inherit_only(const struct richace *ace) +{ + return ace->e_flags & RICHACE_INHERIT_ONLY_ACE; +} + +/** + * richace_is_inheritable - check if @ace is inheritable + */ +static inline bool +richace_is_inheritable(const struct richace *ace) +{ + return ace->e_flags & (RICHACE_FILE_INHERIT_ACE | + RICHACE_DIRECTORY_INHERIT_ACE); +} + +/** + * richace_is_allow - check if @ace is an %ALLOW type entry + */ +static inline bool +richace_is_allow(const struct richace *ace) +{ + return ace->e_type == RICHACE_ACCESS_ALLOWED_ACE_TYPE; +} + +/** + * richace_is_deny - check if @ace is a %DENY type entry + */ +static inline bool +richace_is_deny(const struct richace *ace) +{ + return ace->e_type == RICHACE_ACCESS_DENIED_ACE_TYPE; +} + +/** + * richace_is_same_identifier - are both identifiers the same? + */ +static inline bool +richace_is_same_identifier(const struct richace *a, const struct richace *b) +{ + return !((a->e_flags ^ b->e_flags) & + (RICHACE_SPECIAL_WHO | RICHACE_IDENTIFIER_GROUP)) && + !memcmp(&a->e_id, &b->e_id, sizeof(a->e_id)); +} + +extern struct richacl *richacl_alloc(int, gfp_t); +extern struct richacl *richacl_clone(const struct richacl *, gfp_t); +extern void richace_copy(struct richace *, const struct richace *); + +#endif /* __RICHACL_H */ diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index 8bdae34..abeaa98 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -355,6 +355,7 @@ header-y += reboot.h header-y += reiserfs_fs.h header-y += reiserfs_xattr.h header-y += resource.h +header-y += richacl.h header-y += rfkill.h header-y += rio_mport_cdev.h header-y += romfs_fs.h diff --git a/include/uapi/linux/richacl.h b/include/uapi/linux/richacl.h new file mode 100644 index 0000000..08856f8 --- /dev/null +++ b/include/uapi/linux/richacl.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher <agruenba@redhat.com> + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#ifndef __UAPI_RICHACL_H +#define __UAPI_RICHACL_H + +/* a_flags values */ +#define RICHACL_WRITE_THROUGH 0x40 +#define RICHACL_MASKED 0x80 + +/* e_type values */ +#define RICHACE_ACCESS_ALLOWED_ACE_TYPE 0x0000 +#define RICHACE_ACCESS_DENIED_ACE_TYPE 0x0001 + +/* e_flags bitflags */ +#define RICHACE_FILE_INHERIT_ACE 0x0001 +#define RICHACE_DIRECTORY_INHERIT_ACE 0x0002 +#define RICHACE_NO_PROPAGATE_INHERIT_ACE 0x0004 +#define RICHACE_INHERIT_ONLY_ACE 0x0008 +#define RICHACE_IDENTIFIER_GROUP 0x0040 +#define RICHACE_SPECIAL_WHO 0x4000 + +/* e_mask bitflags */ +#define RICHACE_READ_DATA 0x00000001 +#define RICHACE_LIST_DIRECTORY 0x00000001 +#define RICHACE_WRITE_DATA 0x00000002 +#define RICHACE_ADD_FILE 0x00000002 +#define RICHACE_APPEND_DATA 0x00000004 +#define RICHACE_ADD_SUBDIRECTORY 0x00000004 +#define RICHACE_READ_NAMED_ATTRS 0x00000008 +#define RICHACE_WRITE_NAMED_ATTRS 0x00000010 +#define RICHACE_EXECUTE 0x00000020 +#define RICHACE_DELETE_CHILD 0x00000040 +#define RICHACE_READ_ATTRIBUTES 0x00000080 +#define RICHACE_WRITE_ATTRIBUTES 0x00000100 +#define RICHACE_WRITE_RETENTION 0x00000200 +#define RICHACE_WRITE_RETENTION_HOLD 0x00000400 +#define RICHACE_DELETE 0x00010000 +#define RICHACE_READ_ACL 0x00020000 +#define RICHACE_WRITE_ACL 0x00040000 +#define RICHACE_WRITE_OWNER 0x00080000 +#define RICHACE_SYNCHRONIZE 0x00100000 + +/* e_id values */ +#define RICHACE_OWNER_SPECIAL_ID 0 +#define RICHACE_GROUP_SPECIAL_ID 1 +#define RICHACE_EVERYONE_SPECIAL_ID 2 + +#define RICHACL_VALID_FLAGS ( \ + RICHACL_WRITE_THROUGH | \ + RICHACL_MASKED ) + +#define RICHACE_VALID_FLAGS ( \ + RICHACE_FILE_INHERIT_ACE | \ + RICHACE_DIRECTORY_INHERIT_ACE | \ + RICHACE_NO_PROPAGATE_INHERIT_ACE | \ + RICHACE_INHERIT_ONLY_ACE | \ + RICHACE_IDENTIFIER_GROUP | \ + RICHACE_SPECIAL_WHO ) + +#define RICHACE_INHERITANCE_FLAGS ( \ + RICHACE_FILE_INHERIT_ACE | \ + RICHACE_DIRECTORY_INHERIT_ACE | \ + RICHACE_NO_PROPAGATE_INHERIT_ACE | \ + RICHACE_INHERIT_ONLY_ACE ) + +/* Valid RICHACE_* flags for directories and non-directories */ +#define RICHACE_VALID_MASK ( \ + RICHACE_READ_DATA | RICHACE_LIST_DIRECTORY | \ + RICHACE_WRITE_DATA | RICHACE_ADD_FILE | \ + RICHACE_APPEND_DATA | RICHACE_ADD_SUBDIRECTORY | \ + RICHACE_READ_NAMED_ATTRS | \ + RICHACE_WRITE_NAMED_ATTRS | \ + RICHACE_EXECUTE | \ + RICHACE_DELETE_CHILD | \ + RICHACE_READ_ATTRIBUTES | \ + RICHACE_WRITE_ATTRIBUTES | \ + RICHACE_WRITE_RETENTION | \ + RICHACE_WRITE_RETENTION_HOLD | \ + RICHACE_DELETE | \ + RICHACE_READ_ACL | \ + RICHACE_WRITE_ACL | \ + RICHACE_WRITE_OWNER | \ + RICHACE_SYNCHRONIZE ) + +#endif /* __UAPI_RICHACL_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:12 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id DB0057CCC for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:12 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id AD76A30404E for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:12 -0700 (PDT) X-ASG-Debug-ID: 1467294490-04cb6c063d2c43d0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id msHJFkKfzWQT9ZDC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:11 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 3199F7F0B6; Thu, 30 Jun 2016 13:48:10 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsi005273; Thu, 30 Jun 2016 09:48:03 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 07/22] richacl: Permission mapping functions Date: Thu, 30 Jun 2016 15:46:58 +0200 X-ASG-Orig-Subj: [PATCH v23 07/22] richacl: Permission mapping functions Message-Id: <1467294433-3222-8-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Thu, 30 Jun 2016 13:48:10 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294491 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6962 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 We need to map from POSIX permissions to NFSv4 permissions when a chmod() is done, from NFSv4 permissions to POSIX permissions when an acl is set (which implicitly sets the file permission bits), and from the MAY_READ/MAY_WRITE/MAY_EXEC/MAY_APPEND flags to NFSv4 permissions when doing an access check in a richacl. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> --- fs/richacl.c | 118 +++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 3 ++ include/uapi/linux/richacl.h | 44 ++++++++++++++++ 3 files changed, 165 insertions(+) diff --git a/fs/richacl.c b/fs/richacl.c index bcc6591..d0a4135 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -63,3 +63,121 @@ richace_copy(struct richace *to, const struct richace *from) { memcpy(to, from, sizeof(struct richace)); } + +/* + * richacl_mask_to_mode - compute the file permission bits from mask + * @mask: %RICHACE_* permission mask + * + * Compute the file permission bits corresponding to a particular set of + * richacl permissions. + * + * See richacl_masks_to_mode(). + */ +static int +richacl_mask_to_mode(unsigned int mask) +{ + int mode = 0; + + if (mask & RICHACE_POSIX_MODE_READ) + mode |= S_IROTH; + if (mask & RICHACE_POSIX_MODE_WRITE) + mode |= S_IWOTH; + if (mask & RICHACE_POSIX_MODE_EXEC) + mode |= S_IXOTH; + + return mode; +} + +/** + * richacl_masks_to_mode - compute file permission bits from file masks + * + * When setting a richacl, we set the file permission bits to indicate maximum + * permissions: for example, we set the Write permission when a mask contains + * RICHACE_APPEND_DATA even if it does not also contain RICHACE_WRITE_DATA. + * + * Permissions which are not in RICHACE_POSIX_MODE_READ, + * RICHACE_POSIX_MODE_WRITE, or RICHACE_POSIX_MODE_EXEC cannot be represented + * in the file permission bits. Such permissions can still be effective, but + * not for new files or after a chmod(); they must be explicitly enabled in the + * richacl. + */ +int +richacl_masks_to_mode(const struct richacl *acl) +{ + return richacl_mask_to_mode(acl->a_owner_mask) << 6 | + richacl_mask_to_mode(acl->a_group_mask) << 3 | + richacl_mask_to_mode(acl->a_other_mask); +} +EXPORT_SYMBOL_GPL(richacl_masks_to_mode); + +/** + * richacl_mode_to_mask - compute a file mask from the lowest three mode bits + * @mode: mode to convert to richacl permissions + * + * When the file permission bits of a file are set with chmod(), this specifies + * the maximum permissions that processes will get. All permissions beyond + * that will be removed from the file masks, and become ineffective. + */ +unsigned int +richacl_mode_to_mask(umode_t mode) +{ + unsigned int mask = 0; + + if (mode & S_IROTH) + mask |= RICHACE_POSIX_MODE_READ; + if (mode & S_IWOTH) + mask |= RICHACE_POSIX_MODE_WRITE; + if (mode & S_IXOTH) + mask |= RICHACE_POSIX_MODE_EXEC; + + return mask; +} + +/** + * richacl_want_to_mask - convert the iop->permission want argument to a mask + * @want: @want argument of the permission inode operation + * + * When checking for append, @want is (MAY_WRITE | MAY_APPEND). + * + * Richacls use the iop->may_create and iop->may_delete hooks which are used + * for checking if creating and deleting files is allowed. These hooks do not + * use richacl_want_to_mask(), so we do not have to deal with mapping MAY_WRITE + * to RICHACE_ADD_FILE, RICHACE_ADD_SUBDIRECTORY, and RICHACE_DELETE_CHILD + * here. + */ +unsigned int +richacl_want_to_mask(unsigned int want) +{ + unsigned int mask = 0; + + if (want & MAY_READ) + mask |= RICHACE_READ_DATA; + if (want & MAY_DELETE_SELF) + mask |= RICHACE_DELETE; + if (want & MAY_TAKE_OWNERSHIP) + mask |= RICHACE_WRITE_OWNER; + if (want & MAY_CHMOD) + mask |= RICHACE_WRITE_ACL; + if (want & MAY_SET_TIMES) + mask |= RICHACE_WRITE_ATTRIBUTES; + if (want & MAY_EXEC) + mask |= RICHACE_EXECUTE; + /* + * differentiate MAY_WRITE from these request + */ + if (want & (MAY_APPEND | + MAY_CREATE_FILE | MAY_CREATE_DIR | + MAY_DELETE_CHILD)) { + if (want & MAY_APPEND) + mask |= RICHACE_APPEND_DATA; + if (want & MAY_CREATE_FILE) + mask |= RICHACE_ADD_FILE; + if (want & MAY_CREATE_DIR) + mask |= RICHACE_ADD_SUBDIRECTORY; + if (want & MAY_DELETE_CHILD) + mask |= RICHACE_DELETE_CHILD; + } else if (want & MAY_WRITE) + mask |= RICHACE_WRITE_DATA; + return mask; +} +EXPORT_SYMBOL_GPL(richacl_want_to_mask); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index edb8480..9102ef0 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -175,5 +175,8 @@ richace_is_same_identifier(const struct richace *a, const struct richace *b) extern struct richacl *richacl_alloc(int, gfp_t); extern struct richacl *richacl_clone(const struct richacl *, gfp_t); extern void richace_copy(struct richace *, const struct richace *); +extern int richacl_masks_to_mode(const struct richacl *); +extern unsigned int richacl_mode_to_mask(umode_t); +extern unsigned int richacl_want_to_mask(unsigned int); #endif /* __RICHACL_H */ diff --git a/include/uapi/linux/richacl.h b/include/uapi/linux/richacl.h index 08856f8..1ed48ac 100644 --- a/include/uapi/linux/richacl.h +++ b/include/uapi/linux/richacl.h @@ -96,4 +96,48 @@ RICHACE_WRITE_OWNER | \ RICHACE_SYNCHRONIZE ) +/* + * The POSIX permissions are supersets of the following richacl permissions: + * + * - MAY_READ maps to READ_DATA or LIST_DIRECTORY, depending on the type + * of the file system object. + * + * - MAY_WRITE maps to WRITE_DATA or RICHACE_APPEND_DATA for files, and to + * ADD_FILE, RICHACE_ADD_SUBDIRECTORY, or RICHACE_DELETE_CHILD for directories. + * + * - MAY_EXECUTE maps to RICHACE_EXECUTE. + * + * (Some of these richacl permissions have the same bit values.) + */ +#define RICHACE_POSIX_MODE_READ ( \ + RICHACE_READ_DATA | \ + RICHACE_LIST_DIRECTORY) +#define RICHACE_POSIX_MODE_WRITE ( \ + RICHACE_WRITE_DATA | \ + RICHACE_ADD_FILE | \ + RICHACE_APPEND_DATA | \ + RICHACE_ADD_SUBDIRECTORY | \ + RICHACE_DELETE_CHILD) +#define RICHACE_POSIX_MODE_EXEC RICHACE_EXECUTE +#define RICHACE_POSIX_MODE_ALL ( \ + RICHACE_POSIX_MODE_READ | \ + RICHACE_POSIX_MODE_WRITE | \ + RICHACE_POSIX_MODE_EXEC) + +/* + * These permissions are always allowed no matter what the acl says. + */ +#define RICHACE_POSIX_ALWAYS_ALLOWED ( \ + RICHACE_SYNCHRONIZE | \ + RICHACE_READ_ATTRIBUTES | \ + RICHACE_READ_ACL) + +/* + * The owner is implicitly granted these permissions under POSIX. + */ +#define RICHACE_POSIX_OWNER_ALLOWED ( \ + RICHACE_WRITE_ATTRIBUTES | \ + RICHACE_WRITE_OWNER | \ + RICHACE_WRITE_ACL) + #endif /* __UAPI_RICHACL_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:21 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 17EEC7CA3 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:21 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id DDD1530404E for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:20 -0700 (PDT) X-ASG-Debug-ID: 1467294497-04cbb027353b62f0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id oyUzyfMBq8FvepLL (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:17 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1853763144; Thu, 30 Jun 2016 13:48:17 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsj005273; Thu, 30 Jun 2016 09:48:10 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 08/22] richacl: Compute maximum file masks from an acl Date: Thu, 30 Jun 2016 15:46:59 +0200 X-ASG-Orig-Subj: [PATCH v23 08/22] richacl: Compute maximum file masks from an acl Message-Id: <1467294433-3222-9-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 30 Jun 2016 13:48:17 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294497 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6812 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Compute upper bound owner, group, and other file masks with as few permissions as possible without denying any permissions that the NFSv4 acl in a richacl grants. This algorithm is used when a file inherits an acl at create time and when an acl is set via a mechanism that does not provide file masks (such as setting an acl via nfsd). When user-space sets an acl via setxattr, the extended attribute already includes the file masks. Setting an acl also sets the file mode permission bits: they are determined by the file masks; see richacl_masks_to_mode(). Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> --- fs/richacl.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 1 + 2 files changed, 158 insertions(+) diff --git a/fs/richacl.c b/fs/richacl.c index d0a4135..056228f 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -181,3 +181,160 @@ richacl_want_to_mask(unsigned int want) return mask; } EXPORT_SYMBOL_GPL(richacl_want_to_mask); + +/* + * Note: functions like richacl_allowed_to_who(), richacl_group_class_allowed(), + * and richacl_compute_max_masks() iterate through the entire acl in reverse + * order as an optimization. + * + * In the standard algorithm, aces are considered in forward order. When a + * process matches an ace, the permissions in the ace are either allowed or + * denied depending on the ace type. Once a permission has been allowed or + * denied, it is no longer considered in further aces. + * + * By iterating through the acl in reverse order, we can compute the same + * result without having to keep track of which permissions have been allowed + * and denied already. + */ + +/** + * richacl_allowed_to_who - permissions allowed to a specific who value + * + * Compute the maximum mask values allowed to a specific who value, taking + * everyone@ aces into account. + */ +static unsigned int richacl_allowed_to_who(struct richacl *acl, + struct richace *who) +{ + struct richace *ace; + unsigned int allowed = 0; + + richacl_for_each_entry_reverse(ace, acl) { + if (richace_is_inherit_only(ace)) + continue; + if (richace_is_same_identifier(ace, who) || + richace_is_everyone(ace)) { + if (richace_is_allow(ace)) + allowed |= ace->e_mask; + else if (richace_is_deny(ace)) + allowed &= ~ace->e_mask; + } + } + return allowed; +} + +/** + * richacl_group_class_allowed - maximum permissions of the group class + * + * Compute the maximum mask values allowed to a process in the group class + * (i.e., a process which is not the owner but is in the owning group or + * matches a user or group acl entry). This includes permissions granted or + * denied by everyone@ aces. + * + * See richacl_compute_max_masks(). + */ +static unsigned int richacl_group_class_allowed(struct richacl *acl) +{ + struct richace *ace; + unsigned int everyone_allowed = 0, group_class_allowed = 0; + int had_group_ace = 0; + + richacl_for_each_entry_reverse(ace, acl) { + if (richace_is_inherit_only(ace) || + richace_is_owner(ace)) + continue; + + if (richace_is_everyone(ace)) { + if (richace_is_allow(ace)) + everyone_allowed |= ace->e_mask; + else if (richace_is_deny(ace)) + everyone_allowed &= ~ace->e_mask; + } else { + group_class_allowed |= + richacl_allowed_to_who(acl, ace); + + if (richace_is_group(ace)) + had_group_ace = 1; + } + } + /* + * If the acl doesn't contain any group@ aces, richacl_allowed_to_who() + * wasn't called for the owning group. We could make that call now, but + * we already know the result (everyone_allowed). + */ + if (!had_group_ace) + group_class_allowed |= everyone_allowed; + return group_class_allowed; +} + +/** + * richacl_compute_max_masks - compute upper bound masks + * + * Computes upper bound owner, group, and other masks so that none of the + * permissions allowed by the acl are disabled. + * + * We don't make assumptions about who the owner is so that the owner can + * change with no effect on the file masks or file mode permission bits; this + * means that we must assume that all entries can match the owner. + */ +void richacl_compute_max_masks(struct richacl *acl) +{ + unsigned int gmask = ~0; + struct richace *ace; + + /* + * @gmask contains all permissions which the group class is ever + * allowed. We use it to avoid adding permissions to the group mask + * from everyone@ allow aces which the group class is always denied + * through other aces. For example, the following acl would otherwise + * result in a group mask of rw: + * + * group@:w::deny + * everyone@:rw::allow + * + * Avoid computing @gmask for acls which do not include any group class + * deny aces: in such acls, the group class is never denied any + * permissions from everyone@ allow aces, and the group class cannot + * have fewer permissions than the other class. + */ + +restart: + acl->a_owner_mask = 0; + acl->a_group_mask = 0; + acl->a_other_mask = 0; + + richacl_for_each_entry_reverse(ace, acl) { + if (richace_is_inherit_only(ace)) + continue; + + if (richace_is_owner(ace)) { + if (richace_is_allow(ace)) + acl->a_owner_mask |= ace->e_mask; + else if (richace_is_deny(ace)) + acl->a_owner_mask &= ~ace->e_mask; + } else if (richace_is_everyone(ace)) { + if (richace_is_allow(ace)) { + acl->a_owner_mask |= ace->e_mask; + acl->a_group_mask |= ace->e_mask & gmask; + acl->a_other_mask |= ace->e_mask; + } else if (richace_is_deny(ace)) { + acl->a_owner_mask &= ~ace->e_mask; + acl->a_group_mask &= ~ace->e_mask; + acl->a_other_mask &= ~ace->e_mask; + } + } else { + if (richace_is_allow(ace)) { + acl->a_owner_mask |= ace->e_mask & gmask; + acl->a_group_mask |= ace->e_mask & gmask; + } else if (richace_is_deny(ace) && gmask == ~0) { + gmask = richacl_group_class_allowed(acl); + if (likely(gmask != ~0)) + /* should always be true */ + goto restart; + } + } + } + + acl->a_flags &= ~(RICHACL_WRITE_THROUGH | RICHACL_MASKED); +} +EXPORT_SYMBOL_GPL(richacl_compute_max_masks); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index 9102ef0..3559b2c 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -178,5 +178,6 @@ extern void richace_copy(struct richace *, const struct richace *); extern int richacl_masks_to_mode(const struct richacl *); extern unsigned int richacl_mode_to_mask(umode_t); extern unsigned int richacl_want_to_mask(unsigned int); +extern void richacl_compute_max_masks(struct richacl *); #endif /* __RICHACL_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:25 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id EDBD97CA6 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:25 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id AE59E8F8064 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:25 -0700 (PDT) X-ASG-Debug-ID: 1467294504-04bdf074b5238700001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id dIHEE759OoxmYtTw (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:24 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 046FCC049D5C; Thu, 30 Jun 2016 13:48:24 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsk005273; Thu, 30 Jun 2016 09:48:17 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 09/22] richacl: Permission check algorithm Date: Thu, 30 Jun 2016 15:47:00 +0200 X-ASG-Orig-Subj: [PATCH v23 09/22] richacl: Permission check algorithm Message-Id: <1467294433-3222-10-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 30 Jun 2016 13:48:24 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294504 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5277 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 A richacl roughly grants a requested access if the NFSv4 acl in the richacl grants the requested permissions according to the NFSv4 permission check algorithm and the file mask that applies to the process includes the requested permissions. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@fieldses.org> --- fs/richacl.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 1 + 2 files changed, 129 insertions(+) diff --git a/fs/richacl.c b/fs/richacl.c index 056228f..cb0ef3f 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -338,3 +338,131 @@ restart: acl->a_flags &= ~(RICHACL_WRITE_THROUGH | RICHACL_MASKED); } EXPORT_SYMBOL_GPL(richacl_compute_max_masks); + +/** + * richacl_permission - richacl permission check algorithm + * @inode: inode to check + * @acl: rich acl of the inode + * @want: requested access (MAY_* flags) + * + * Checks if the current process is granted @mask flags in @acl. + */ +int +richacl_permission(struct inode *inode, const struct richacl *acl, + int want) +{ + const struct richace *ace; + unsigned int mask = richacl_want_to_mask(want); + unsigned int requested = mask, denied = 0; + int in_owning_group = in_group_p(inode->i_gid); + int in_owner_or_group_class = in_owning_group; + + /* + * A process is + * - in the owner file class if it owns the file, + * - in the group file class if it is in the file's owning group or + * it matches any of the user or group entries, and + * - in the other file class otherwise. + * The file class is only relevant for determining which file mask to + * apply, which only happens for masked acls. + */ + if (acl->a_flags & RICHACL_MASKED) { + if ((acl->a_flags & RICHACL_WRITE_THROUGH) && + uid_eq(current_fsuid(), inode->i_uid)) { + denied = requested & ~acl->a_owner_mask; + goto out; + } + } else { + /* + * When the acl is not masked, there is no need to determine if + * the process is in the group class and we can break out + * earlier of the loop below. + */ + in_owner_or_group_class = 1; + } + + /* + * Check if the acl grants the requested access and determine which + * file class the process is in. + */ + richacl_for_each_entry(ace, acl) { + unsigned int ace_mask = ace->e_mask; + + if (richace_is_inherit_only(ace)) + continue; + if (richace_is_owner(ace)) { + if (!uid_eq(current_fsuid(), inode->i_uid)) + continue; + goto entry_matches_owner; + } else if (richace_is_group(ace)) { + if (!in_owning_group) + continue; + } else if (richace_is_unix_user(ace)) { + if (!uid_eq(current_fsuid(), ace->e_id.uid)) + continue; + if (uid_eq(current_fsuid(), inode->i_uid)) + goto entry_matches_owner; + } else if (richace_is_unix_group(ace)) { + if (!in_group_p(ace->e_id.gid)) + continue; + } else + goto entry_matches_everyone; + + /* + * Apply the group file mask to entries other than owner@ and + * everyone@ or user entries matching the owner. This ensures + * that we grant the same permissions as the acl computed by + * richacl_apply_masks(). + * + * Without this restriction, the following richacl would grant + * rw access to processes which are both the owner and in the + * owning group, but not to other users in the owning group, + * which could not be represented without masks: + * + * owner:rw::mask + * group@:rw::allow + */ + if ((acl->a_flags & RICHACL_MASKED) && richace_is_allow(ace)) + ace_mask &= acl->a_group_mask; + +entry_matches_owner: + /* The process is in the owner or group file class. */ + in_owner_or_group_class = 1; + +entry_matches_everyone: + /* Check which mask flags the ACE allows or denies. */ + if (richace_is_deny(ace)) + denied |= ace_mask & mask; + mask &= ~ace_mask; + + /* + * Keep going until we know which file class + * the process is in. + */ + if (!mask && in_owner_or_group_class) + break; + } + denied |= mask; + + if (acl->a_flags & RICHACL_MASKED) { + /* + * The file class a process is in determines which file mask + * applies. Check if that file mask also grants the requested + * access. + */ + if (uid_eq(current_fsuid(), inode->i_uid)) + denied |= requested & ~acl->a_owner_mask; + else if (in_owner_or_group_class) + denied |= requested & ~acl->a_group_mask; + else { + if (acl->a_flags & RICHACL_WRITE_THROUGH) + denied = requested & ~acl->a_other_mask; + else + denied |= requested & ~acl->a_other_mask; + } + } + +out: + return denied ? -EACCES : 0; +} +EXPORT_SYMBOL_GPL(richacl_permission); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index 3559b2c..be9fb65 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -179,5 +179,6 @@ extern int richacl_masks_to_mode(const struct richacl *); extern unsigned int richacl_mode_to_mask(umode_t); extern unsigned int richacl_want_to_mask(unsigned int); extern void richacl_compute_max_masks(struct richacl *); +extern int richacl_permission(struct inode *, const struct richacl *, int); #endif /* __RICHACL_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:45 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 124827CB1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:45 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 94D55AC00A for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:44 -0700 (PDT) X-ASG-Debug-ID: 1467294522-04bdf074b5238730001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id LbcEOCNgO5Pr7fzK (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:42 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AB23747D2; Thu, 30 Jun 2016 13:48:38 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsm005273; Thu, 30 Jun 2016 09:48:31 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org, Andreas Dilger <adilger@dilger.ca> Subject: [PATCH v23 11/22] vfs: Cache base_acl objects in inodes Date: Thu, 30 Jun 2016 15:47:02 +0200 X-ASG-Orig-Subj: [PATCH v23 11/22] vfs: Cache base_acl objects in inodes Message-Id: <1467294433-3222-12-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 30 Jun 2016 13:48:38 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294522 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 17875 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 POSIX ACLs and richacls are both objects allocated by kmalloc() with a reference count which are freed by kfree_rcu(). An inode can either cache an access and a default POSIX ACL, or a richacl (richacls do not have default acls). To allow an inode to cache either of the two kinds of acls, introduce a new base_acl type and convert i_acl and i_default_acl to that type. In most cases, the vfs then doesn't care which kind of acl an inode caches (if any). Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Cc: Andreas Dilger <adilger@dilger.ca> --- drivers/staging/lustre/lustre/llite/llite_lib.c | 2 +- fs/9p/acl.c | 8 +-- fs/f2fs/acl.c | 4 +- fs/inode.c | 32 +++++++++++- fs/jffs2/acl.c | 6 ++- fs/namei.c | 33 ++++++------ fs/nfs/nfs3acl.c | 14 ++--- fs/posix_acl.c | 69 +++++++------------------ fs/richacl.c | 4 +- include/linux/fs.h | 41 +++++++++++++-- include/linux/posix_acl.h | 21 ++++---- include/linux/richacl.h | 9 ++-- 12 files changed, 139 insertions(+), 104 deletions(-) diff --git a/drivers/staging/lustre/lustre/llite/llite_lib.c b/drivers/staging/lustre/lustre/llite/llite_lib.c index 96c7e9f..7819a7c 100644 --- a/drivers/staging/lustre/lustre/llite/llite_lib.c +++ b/drivers/staging/lustre/lustre/llite/llite_lib.c @@ -1087,7 +1087,7 @@ void ll_clear_inode(struct inode *inode) } #ifdef CONFIG_FS_POSIX_ACL else if (lli->lli_posix_acl) { - LASSERT(atomic_read(&lli->lli_posix_acl->a_refcount) == 1); + LASSERT(base_acl_refcount(&lli->lli_posix_acl->a_base) == 1); LASSERT(!lli->lli_remote_perms); posix_acl_release(lli->lli_posix_acl); lli->lli_posix_acl = NULL; diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 0576eae..1ce572f 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -87,14 +87,14 @@ int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) { - struct posix_acl *acl; + struct base_acl *base_acl; /* * 9p Always cache the acl value when * instantiating the inode (v9fs_inode_from_fid) */ - acl = get_cached_acl(inode, type); - BUG_ON(is_uncached_acl(acl)); - return acl; + base_acl = get_cached_acl(inode, type); + BUG_ON(is_uncached_acl(base_acl)); + return posix_acl(base_acl); } struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type) diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c index a31c7e8..6079017 100644 --- a/fs/f2fs/acl.c +++ b/fs/f2fs/acl.c @@ -267,7 +267,7 @@ static struct posix_acl *f2fs_acl_clone(const struct posix_acl *acl, sizeof(struct posix_acl_entry); clone = kmemdup(acl, size, flags); if (clone) - atomic_set(&clone->a_refcount, 1); + base_acl_init(&clone->a_base); } return clone; } @@ -279,7 +279,7 @@ static int f2fs_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) umode_t mode = *mode_p; int not_equiv = 0; - /* assert(atomic_read(acl->a_refcount) == 1); */ + /* assert(base_acl_refcount(&acl->a_base) == 1); */ FOREACH_ACL_ENTRY(pa, acl, pe) { switch(pa->e_tag) { diff --git a/fs/inode.c b/fs/inode.c index 4ccbc21..40c03a7 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -240,14 +240,42 @@ void __destroy_inode(struct inode *inode) #ifdef CONFIG_FS_POSIX_ACL if (inode->i_acl && !is_uncached_acl(inode->i_acl)) - posix_acl_release(inode->i_acl); + base_acl_put(inode->i_acl); if (inode->i_default_acl && !is_uncached_acl(inode->i_default_acl)) - posix_acl_release(inode->i_default_acl); + base_acl_put(inode->i_default_acl); #endif this_cpu_dec(nr_inodes); } EXPORT_SYMBOL(__destroy_inode); +#ifdef CONFIG_FS_POSIX_ACL +struct base_acl *__get_cached_acl(struct base_acl **p) +{ + struct base_acl *base_acl; + + for (;;) { + rcu_read_lock(); + base_acl = rcu_dereference(*p); + if (!base_acl || is_uncached_acl(base_acl) || + atomic_inc_not_zero(&base_acl->ba_refcount)) + break; + rcu_read_unlock(); + cpu_relax(); + } + rcu_read_unlock(); + return base_acl; +} + +void __forget_cached_acl(struct base_acl **p) +{ + struct base_acl *old; + + old = xchg(p, ACL_NOT_CACHED); + if (!is_uncached_acl(old)) + base_acl_put(old); +} +#endif + static void i_callback(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index bc2693d..6c11909 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -292,13 +292,15 @@ int jffs2_init_acl_post(struct inode *inode) int rc; if (inode->i_default_acl) { - rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, inode->i_default_acl); + rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_DEFAULT, + posix_acl(inode->i_default_acl)); if (rc) return rc; } if (inode->i_acl) { - rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, inode->i_acl); + rc = __jffs2_set_acl(inode, JFFS2_XPREFIX_ACL_ACCESS, + posix_acl(inode->i_acl)); if (rc) return rc; } diff --git a/fs/namei.c b/fs/namei.c index 663933e..7a822d0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -259,25 +259,28 @@ void putname(struct filename *name) static int check_acl(struct inode *inode, int mask) { #ifdef CONFIG_FS_POSIX_ACL - struct posix_acl *acl; - if (mask & MAY_NOT_BLOCK) { - acl = get_cached_acl_rcu(inode, ACL_TYPE_ACCESS); - if (!acl) + struct base_acl *base_acl; + + base_acl = rcu_dereference(inode->i_acl); + if (!base_acl) return -EAGAIN; /* no ->get_acl() calls in RCU mode... */ - if (is_uncached_acl(acl)) + if (is_uncached_acl(base_acl)) return -ECHILD; - return posix_acl_permission(inode, acl, mask & ~MAY_NOT_BLOCK); - } - - acl = get_acl(inode, ACL_TYPE_ACCESS); - if (IS_ERR(acl)) - return PTR_ERR(acl); - if (acl) { - int error = posix_acl_permission(inode, acl, mask); - posix_acl_release(acl); - return error; + return posix_acl_permission(inode, posix_acl(base_acl), + mask & ~MAY_NOT_BLOCK); + } else { + struct posix_acl *acl; + + acl = get_acl(inode, ACL_TYPE_ACCESS); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + int error = posix_acl_permission(inode, acl, mask); + posix_acl_release(acl); + return error; + } } #endif diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c index 720d92f5..2b70944 100644 --- a/fs/nfs/nfs3acl.c +++ b/fs/nfs/nfs3acl.c @@ -16,28 +16,28 @@ * caching get_acl results in a race-free way. See fs/posix_acl.c:get_acl() * for explanations. */ -static void nfs3_prepare_get_acl(struct posix_acl **p) +static void nfs3_prepare_get_acl(struct base_acl **p) { - struct posix_acl *sentinel = uncached_acl_sentinel(current); + struct base_acl *sentinel = uncached_acl_sentinel(current); if (cmpxchg(p, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) { /* Not the first reader or sentinel already in place. */ } } -static void nfs3_complete_get_acl(struct posix_acl **p, struct posix_acl *acl) +static void nfs3_complete_get_acl(struct base_acl **p, struct posix_acl *acl) { - struct posix_acl *sentinel = uncached_acl_sentinel(current); + struct base_acl *sentinel = uncached_acl_sentinel(current); /* Only cache the ACL if our sentinel is still in place. */ posix_acl_dup(acl); - if (cmpxchg(p, sentinel, acl) != sentinel) + if (cmpxchg(p, sentinel, &acl->a_base) != sentinel) posix_acl_release(acl); } -static void nfs3_abort_get_acl(struct posix_acl **p) +static void nfs3_abort_get_acl(struct base_acl **p) { - struct posix_acl *sentinel = uncached_acl_sentinel(current); + struct base_acl *sentinel = uncached_acl_sentinel(current); /* Remove our sentinel upon failure. */ cmpxchg(p, sentinel, ACL_NOT_CACHED); diff --git a/fs/posix_acl.c b/fs/posix_acl.c index edc452c..1b685a1 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -21,7 +21,7 @@ #include <linux/export.h> #include <linux/user_namespace.h> -static struct posix_acl **acl_by_type(struct inode *inode, int type) +static inline struct base_acl **acl_by_type(struct inode *inode, int type) { switch (type) { case ACL_TYPE_ACCESS: @@ -33,51 +33,23 @@ static struct posix_acl **acl_by_type(struct inode *inode, int type) } } -struct posix_acl *get_cached_acl(struct inode *inode, int type) +struct base_acl *get_cached_acl(struct inode *inode, int type) { - struct posix_acl **p = acl_by_type(inode, type); - struct posix_acl *acl; - - for (;;) { - rcu_read_lock(); - acl = rcu_dereference(*p); - if (!acl || is_uncached_acl(acl) || - atomic_inc_not_zero(&acl->a_refcount)) - break; - rcu_read_unlock(); - cpu_relax(); - } - rcu_read_unlock(); - return acl; + return __get_cached_acl(acl_by_type(inode, type)); } EXPORT_SYMBOL(get_cached_acl); -struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type) -{ - return rcu_dereference(*acl_by_type(inode, type)); -} -EXPORT_SYMBOL(get_cached_acl_rcu); - void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl) { - struct posix_acl **p = acl_by_type(inode, type); - struct posix_acl *old; + struct base_acl **p = acl_by_type(inode, type); + struct base_acl *old; - old = xchg(p, posix_acl_dup(acl)); + old = xchg(p, &posix_acl_dup(acl)->a_base); if (!is_uncached_acl(old)) - posix_acl_release(old); + base_acl_put(old); } EXPORT_SYMBOL(set_cached_acl); -static void __forget_cached_acl(struct posix_acl **p) -{ - struct posix_acl *old; - - old = xchg(p, ACL_NOT_CACHED); - if (!is_uncached_acl(old)) - posix_acl_release(old); -} - void forget_cached_acl(struct inode *inode, int type) { __forget_cached_acl(acl_by_type(inode, type)); @@ -93,25 +65,24 @@ EXPORT_SYMBOL(forget_all_cached_acls); struct posix_acl *get_acl(struct inode *inode, int type) { - void *sentinel; - struct posix_acl **p; + struct base_acl **p = acl_by_type(inode, type); + struct base_acl *sentinel, *base_acl; struct posix_acl *acl; + if (!IS_POSIXACL(inode)) + return NULL; + /* * The sentinel is used to detect when another operation like * set_cached_acl() or forget_cached_acl() races with get_acl(). * It is guaranteed that is_uncached_acl(sentinel) is true. */ - acl = get_cached_acl(inode, type); - if (!is_uncached_acl(acl)) - return acl; - - if (!IS_POSIXACL(inode)) - return NULL; + base_acl = __get_cached_acl(p); + if (!is_uncached_acl(base_acl)) + return posix_acl(base_acl); sentinel = uncached_acl_sentinel(current); - p = acl_by_type(inode, type); /* * If the ACL isn't being read yet, set our sentinel. Otherwise, the @@ -151,7 +122,7 @@ struct posix_acl *get_acl(struct inode *inode, int type) * Cache the result, but only if our sentinel is still in place. */ posix_acl_dup(acl); - if (unlikely(cmpxchg(p, sentinel, acl) != sentinel)) + if (unlikely(cmpxchg(p, sentinel, &acl->a_base) != sentinel)) posix_acl_release(acl); return acl; } @@ -163,7 +134,7 @@ EXPORT_SYMBOL(get_acl); void posix_acl_init(struct posix_acl *acl, int count) { - atomic_set(&acl->a_refcount, 1); + base_acl_init(&acl->a_base); acl->a_count = count; } EXPORT_SYMBOL(posix_acl_init); @@ -196,7 +167,7 @@ posix_acl_clone(const struct posix_acl *acl, gfp_t flags) sizeof(struct posix_acl_entry); clone = kmemdup(acl, size, flags); if (clone) - atomic_set(&clone->a_refcount, 1); + base_acl_init(&clone->a_base); } return clone; } @@ -418,7 +389,7 @@ static int posix_acl_create_masq(struct posix_acl *acl, umode_t *mode_p) umode_t mode = *mode_p; int not_equiv = 0; - /* assert(atomic_read(acl->a_refcount) == 1); */ + /* assert(base_acl_refcount(&acl->a_base) == 1); */ FOREACH_ACL_ENTRY(pa, acl, pe) { switch(pa->e_tag) { @@ -473,7 +444,7 @@ static int __posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode) struct posix_acl_entry *group_obj = NULL, *mask_obj = NULL; struct posix_acl_entry *pa, *pe; - /* assert(atomic_read(acl->a_refcount) == 1); */ + /* assert(base_acl_refcount(&acl->a_base) == 1); */ FOREACH_ACL_ENTRY(pa, acl, pe) { switch(pa->e_tag) { diff --git a/fs/richacl.c b/fs/richacl.c index cb0ef3f..8971ead 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -31,7 +31,7 @@ richacl_alloc(int count, gfp_t gfp) struct richacl *acl = kzalloc(size, gfp); if (acl) { - atomic_set(&acl->a_refcount, 1); + base_acl_init(&acl->a_base); acl->a_count = count; } return acl; @@ -50,7 +50,7 @@ richacl_clone(const struct richacl *acl, gfp_t gfp) if (dup) { memcpy(dup, acl, size); - atomic_set(&dup->a_refcount, 1); + base_acl_init(&dup->a_base); } return dup; } diff --git a/include/linux/fs.h b/include/linux/fs.h index bb36561..06a30b0 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -582,17 +582,23 @@ static inline void mapping_allow_writable(struct address_space *mapping) #define i_size_ordered_init(inode) do { } while (0) #endif +struct base_acl { + union { + atomic_t ba_refcount; + struct rcu_head ba_rcu; + }; +}; struct posix_acl; #define ACL_NOT_CACHED ((void *)(-1)) -static inline struct posix_acl * +static inline struct base_acl * uncached_acl_sentinel(struct task_struct *task) { return (void *)task + 1; } static inline bool -is_uncached_acl(struct posix_acl *acl) +is_uncached_acl(struct base_acl *acl) { return (long)acl & 1; } @@ -613,9 +619,9 @@ struct inode { kgid_t i_gid; unsigned int i_flags; -#ifdef CONFIG_FS_POSIX_ACL - struct posix_acl *i_acl; - struct posix_acl *i_default_acl; +#if defined(CONFIG_FS_POSIX_ACL) + struct base_acl *i_acl; + struct base_acl *i_default_acl; #endif const struct inode_operations *i_op; @@ -3193,4 +3199,29 @@ static inline bool dir_relax_shared(struct inode *inode) extern bool path_noexec(const struct path *path); extern void inode_nohighmem(struct inode *inode); +static inline void base_acl_get(struct base_acl *acl) +{ + if (acl) + atomic_inc(&acl->ba_refcount); +} + +static inline void base_acl_put(struct base_acl *acl) +{ + if (acl && atomic_dec_and_test(&acl->ba_refcount)) + kfree_rcu(acl, ba_rcu); +} + +static inline void base_acl_init(struct base_acl *acl) +{ + atomic_set(&acl->ba_refcount, 1); +} + +static inline int base_acl_refcount(struct base_acl *acl) +{ + return atomic_read(&acl->ba_refcount); +} + +extern struct base_acl *__get_cached_acl(struct base_acl **); +extern void __forget_cached_acl(struct base_acl **); + #endif /* _LINUX_FS_H */ diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 5b5a80c..daf84fa 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -43,10 +43,7 @@ struct posix_acl_entry { }; struct posix_acl { - union { - atomic_t a_refcount; - struct rcu_head a_rcu; - }; + struct base_acl a_base; /* must be first, see posix_acl_release() */ unsigned int a_count; struct posix_acl_entry a_entries[0]; }; @@ -61,8 +58,7 @@ struct posix_acl { static inline struct posix_acl * posix_acl_dup(struct posix_acl *acl) { - if (acl) - atomic_inc(&acl->a_refcount); + base_acl_get(&acl->a_base); return acl; } @@ -72,10 +68,16 @@ posix_acl_dup(struct posix_acl *acl) static inline void posix_acl_release(struct posix_acl *acl) { - if (acl && atomic_dec_and_test(&acl->a_refcount)) - kfree_rcu(acl, a_rcu); + BUILD_BUG_ON(offsetof(struct posix_acl, a_base) != 0); + base_acl_put(&acl->a_base); } +static inline struct posix_acl * +posix_acl(struct base_acl *base_acl) +{ + BUILD_BUG_ON(offsetof(struct posix_acl, a_base) != 0); + return container_of(base_acl, struct posix_acl, a_base); +} /* posix_acl.c */ @@ -99,8 +101,7 @@ extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, extern int simple_set_acl(struct inode *, struct posix_acl *, int); extern int simple_acl_create(struct inode *, struct inode *); -struct posix_acl *get_cached_acl(struct inode *inode, int type); -struct posix_acl *get_cached_acl_rcu(struct inode *inode, int type); +struct base_acl *get_cached_acl(struct inode *inode, int type); void set_cached_acl(struct inode *inode, int type, struct posix_acl *acl); void forget_cached_acl(struct inode *inode, int type); void forget_all_cached_acls(struct inode *inode); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index be9fb65..35a5bcb 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -31,7 +31,7 @@ struct richace { }; struct richacl { - atomic_t a_refcount; + struct base_acl a_base; /* must be first, see richacl_put() */ unsigned int a_owner_mask; unsigned int a_group_mask; unsigned int a_other_mask; @@ -56,8 +56,7 @@ struct richacl { static inline struct richacl * richacl_get(struct richacl *acl) { - if (acl) - atomic_inc(&acl->a_refcount); + base_acl_get(&acl->a_base); return acl; } @@ -67,8 +66,8 @@ richacl_get(struct richacl *acl) static inline void richacl_put(struct richacl *acl) { - if (acl && atomic_dec_and_test(&acl->a_refcount)) - kfree(acl); + BUILD_BUG_ON(offsetof(struct richacl, a_base) != 0); + base_acl_put(&acl->a_base); } /** -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:55 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 639377CDB for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id DEE10AC008 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:54 -0700 (PDT) X-ASG-Debug-ID: 1467294511-04cbb027353b6310001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id LN2Kc7nv0eUUzpnq (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:31 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1052363330; Thu, 30 Jun 2016 13:48:31 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsl005273; Thu, 30 Jun 2016 09:48:24 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 10/22] posix_acl: Improve xattr fixup code Date: Thu, 30 Jun 2016 15:47:01 +0200 X-ASG-Orig-Subj: [PATCH v23 10/22] posix_acl: Improve xattr fixup code Message-Id: <1467294433-3222-11-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Thu, 30 Jun 2016 13:48:31 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294511 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2418 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Both XATTR_NAME_POSIX_ACL_ACCESS and XATTR_NAME_POSIX_ACL_DEFAULT have the same XATTR_SYSTEM_PREFIX prefix; don't check for the same prefix repeatedly. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Steve French <steve.french@primarydata.com> --- fs/xattr.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/fs/xattr.c b/fs/xattr.c index 4beafc4..61ac218 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -295,6 +295,16 @@ out: } EXPORT_SYMBOL_GPL(vfs_removexattr); +static void +fix_xattr_from_user(const char *kname, void *kvalue, size_t size) +{ + if (strncmp(kname, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return; + kname += XATTR_SYSTEM_PREFIX_LEN; + if (!strcmp(kname, XATTR_POSIX_ACL_ACCESS) || + !strcmp(kname, XATTR_POSIX_ACL_DEFAULT)) + posix_acl_fix_xattr_from_user(kvalue, size); +} /* * Extended attribute SET operations @@ -329,9 +339,7 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value, error = -EFAULT; goto out; } - if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) || - (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) - posix_acl_fix_xattr_from_user(kvalue, size); + fix_xattr_from_user(kname, kvalue, size); } error = vfs_setxattr(d, kname, kvalue, size, flags); @@ -396,6 +404,17 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, return error; } +static void +fix_xattr_to_user(const char *kname, void *kvalue, size_t size) +{ + if (strncmp(kname, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) + return; + kname += XATTR_SYSTEM_PREFIX_LEN; + if (!strcmp(kname, XATTR_POSIX_ACL_ACCESS) || + !strcmp(kname, XATTR_POSIX_ACL_DEFAULT)) + posix_acl_fix_xattr_to_user(kvalue, size); +} + /* * Extended attribute GET operations */ @@ -426,9 +445,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, error = vfs_getxattr(d, kname, kvalue, size); if (error > 0) { - if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) || - (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) - posix_acl_fix_xattr_to_user(kvalue, size); + fix_xattr_to_user(kname, kvalue, size); if (size && copy_to_user(value, kvalue, error)) error = -EFAULT; } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:56 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 9BE217CDC for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:55 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 15DCCAC00A for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:54 -0700 (PDT) X-ASG-Debug-ID: 1467294525-04cbb027363b6350001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 2cGuTwyxlSqit4na (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:46 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9A2B73B70D; Thu, 30 Jun 2016 13:48:45 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsn005273; Thu, 30 Jun 2016 09:48:39 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 12/22] vfs: Add get_richacl and set_richacl inode operations Date: Thu, 30 Jun 2016 15:47:03 +0200 X-ASG-Orig-Subj: [PATCH v23 12/22] vfs: Add get_richacl and set_richacl inode operations Message-Id: <1467294433-3222-13-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 30 Jun 2016 13:48:45 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294526 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1230 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 These operations are similar to the get_acl and set_acl operations for POSIX ACLs. The distinction between access and default ACLs doesn't exist for richacls. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Steve French <steve.french@primarydata.com> --- include/linux/fs.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/fs.h b/include/linux/fs.h index 06a30b0..ac96bda 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1726,6 +1726,7 @@ struct inode_operations { const char * (*get_link) (struct dentry *, struct inode *, struct delayed_call *); int (*permission) (struct inode *, int); struct posix_acl * (*get_acl)(struct inode *, int); + struct richacl * (*get_richacl)(struct inode *); int (*readlink) (struct dentry *, char __user *,int); @@ -1756,6 +1757,7 @@ struct inode_operations { umode_t create_mode, int *opened); int (*tmpfile) (struct inode *, struct dentry *, umode_t); int (*set_acl)(struct inode *, struct posix_acl *, int); + int (*set_richacl)(struct inode *, struct richacl *); } ____cacheline_aligned; ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector, -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:48:55 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 544977CD9 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:48:55 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 18B48304039 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:55 -0700 (PDT) X-ASG-Debug-ID: 1467294533-04cb6c063e2c4560001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id aAyNyNDaAjnE3mTh (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:48:53 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 200F2C049D67; Thu, 30 Jun 2016 13:48:53 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDso005273; Thu, 30 Jun 2016 09:48:46 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 13/22] vfs: Cache richacl in struct inode Date: Thu, 30 Jun 2016 15:47:04 +0200 X-ASG-Orig-Subj: [PATCH v23 13/22] vfs: Cache richacl in struct inode Message-Id: <1467294433-3222-14-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 30 Jun 2016 13:48:53 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294533 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5815 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Cache richacls in struct inode so that this doesn't have to be done individually in each filesystem. This is similar to POSIX ACLs. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- fs/inode.c | 13 +++++--- fs/richacl.c | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 5 ++- include/linux/richacl.h | 11 +++++++ 4 files changed, 105 insertions(+), 5 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 40c03a7..7dbb09c 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -181,8 +181,11 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_private = NULL; inode->i_mapping = mapping; INIT_HLIST_HEAD(&inode->i_dentry); /* buggered by rcu freeing */ -#ifdef CONFIG_FS_POSIX_ACL - inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED; +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) + inode->i_acl = ACL_NOT_CACHED; +# if defined(CONFIG_FS_POSIX_ACL) + inode->i_default_acl = ACL_NOT_CACHED; +# endif #endif #ifdef CONFIG_FSNOTIFY @@ -238,17 +241,19 @@ void __destroy_inode(struct inode *inode) atomic_long_dec(&inode->i_sb->s_remove_count); } -#ifdef CONFIG_FS_POSIX_ACL +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) if (inode->i_acl && !is_uncached_acl(inode->i_acl)) base_acl_put(inode->i_acl); +# if defined(CONFIG_FS_POSIX_ACL) if (inode->i_default_acl && !is_uncached_acl(inode->i_default_acl)) base_acl_put(inode->i_default_acl); +# endif #endif this_cpu_dec(nr_inodes); } EXPORT_SYMBOL(__destroy_inode); -#ifdef CONFIG_FS_POSIX_ACL +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) struct base_acl *__get_cached_acl(struct base_acl **p) { struct base_acl *base_acl; diff --git a/fs/richacl.c b/fs/richacl.c index 8971ead..b2a03c1 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -20,6 +20,87 @@ #include <linux/slab.h> #include <linux/richacl.h> +void set_cached_richacl(struct inode *inode, struct richacl *acl) +{ + struct base_acl *old; + + old = xchg(&inode->i_acl, &richacl_get(acl)->a_base); + if (!is_uncached_acl(old)) + base_acl_put(old); +} +EXPORT_SYMBOL_GPL(set_cached_richacl); + +void forget_cached_richacl(struct inode *inode) +{ + __forget_cached_acl(&inode->i_acl); +} +EXPORT_SYMBOL_GPL(forget_cached_richacl); + +struct richacl *get_richacl(struct inode *inode) +{ + struct base_acl *sentinel, *base_acl; + struct richacl *acl; + + if (!IS_RICHACL(inode)) + return NULL; + + /* + * The sentinel is used to detect when another operation like + * set_cached_richacl() or forget_cached_richacl() races with + * get_richacl(). + * It is guaranteed that is_uncached_acl(sentinel) is true. + */ + + base_acl = __get_cached_acl(&inode->i_acl); + if (!is_uncached_acl(base_acl)) + return richacl(base_acl); + + sentinel = uncached_acl_sentinel(current); + + /* + * If the ACL isn't being read yet, set our sentinel. Otherwise, the + * current value of the ACL will not be ACL_NOT_CACHED and so our own + * sentinel will not be set; another task will update the cache. We + * could wait for that other task to complete its job, but it's easier + * to just call ->get_acl to fetch the ACL ourself. (This is going to + * be an unlikely race.) + */ + if (cmpxchg(&inode->i_acl, ACL_NOT_CACHED, sentinel) != ACL_NOT_CACHED) + /* fall through */ ; + + /* + * Normally, the ACL returned by ->get_richacl will be cached. + * A filesystem can prevent that by calling + * forget_cached_richacl(inode) in ->get_richacl. + * + * If the filesystem doesn't have a ->get_richacl function at all, + * we'll just create the negative cache entry. + */ + if (!inode->i_op->get_richacl) { + set_cached_richacl(inode, NULL); + return NULL; + } + + acl = inode->i_op->get_richacl(inode); + if (IS_ERR(acl)) { + /* + * Remove our sentinel so that we don't block future attempts + * to cache the ACL. + */ + cmpxchg(&inode->i_acl, sentinel, ACL_NOT_CACHED); + return acl; + } + + /* + * Cache the result, but only if our sentinel is still in place. + */ + richacl_get(acl); + if (unlikely(cmpxchg(&inode->i_acl, sentinel, &acl->a_base) != sentinel)) + richacl_put(acl); + return acl; +} +EXPORT_SYMBOL_GPL(get_richacl); + /** * richacl_alloc - allocate a richacl * @count: number of entries diff --git a/include/linux/fs.h b/include/linux/fs.h index ac96bda..4d72a6d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -589,6 +589,7 @@ struct base_acl { }; }; struct posix_acl; +struct richacl; #define ACL_NOT_CACHED ((void *)(-1)) static inline struct base_acl * @@ -619,9 +620,11 @@ struct inode { kgid_t i_gid; unsigned int i_flags; -#if defined(CONFIG_FS_POSIX_ACL) +#if defined(CONFIG_FS_POSIX_ACL) || defined(CONFIG_FS_RICHACL) struct base_acl *i_acl; +# if defined(CONFIG_FS_POSIX_ACL) struct base_acl *i_default_acl; +# endif #endif const struct inode_operations *i_op; diff --git a/include/linux/richacl.h b/include/linux/richacl.h index 35a5bcb..3e05c94 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -70,6 +70,17 @@ richacl_put(struct richacl *acl) base_acl_put(&acl->a_base); } +static inline struct richacl * +richacl(struct base_acl *base_acl) +{ + BUILD_BUG_ON(offsetof(struct richacl, a_base) != 0); + return container_of(base_acl, struct richacl, a_base); +} + +extern void set_cached_richacl(struct inode *, struct richacl *); +extern void forget_cached_richacl(struct inode *); +extern struct richacl *get_richacl(struct inode *); + /** * richace_is_owner - check if @ace is an OWNER@ entry */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:02 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 0DDE47CEB for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:02 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 9B7D0AC008 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:01 -0700 (PDT) X-ASG-Debug-ID: 1467294540-04bdf074b5238750001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 6Y4XAwpCtmGLtcri (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:00 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 4C75660BC; Thu, 30 Jun 2016 13:49:00 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsp005273; Thu, 30 Jun 2016 09:48:53 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 14/22] richacl: Update the file masks in chmod() Date: Thu, 30 Jun 2016 15:47:05 +0200 X-ASG-Orig-Subj: [PATCH v23 14/22] richacl: Update the file masks in chmod() Message-Id: <1467294433-3222-15-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 30 Jun 2016 13:49:00 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294540 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3909 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Doing a chmod() sets the file mode, which includes the file permission bits. When a file has a richacl, the permissions that the richacl grants need to be limited to what the new file permission bits allow. This is done by setting the file masks in the richacl to what the file permission bits map to. The richacl access check algorithm takes the file masks into account, which ensures that the richacl cannot grant too many permissions. It is possible to explicitly add permissions to the file masks which go beyond what the file permission bits can grant (like the RICHACE_WRITE_ACL permission). The POSIX.1 standard calls this an alternate file access control mechanism. A subsequent chmod() would ensure that those permissions are disabled again. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> --- fs/richacl.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 1 + 2 files changed, 72 insertions(+) diff --git a/fs/richacl.c b/fs/richacl.c index b2a03c1..ba110a6 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -547,3 +547,74 @@ out: return denied ? -EACCES : 0; } EXPORT_SYMBOL_GPL(richacl_permission); + +/** + * __richacl_chmod - update the file masks to reflect the new mode + * @acl: access control list + * @mode: new file permission bits including the file type + * + * Return a copy of @acl where the file masks have been replaced by the file + * masks corresponding to the file permission bits in @mode, or returns @acl + * itself if the file masks are already up to date. Takes over a reference + * to @acl. + */ +static struct richacl * +__richacl_chmod(struct richacl *acl, umode_t mode) +{ + unsigned int x = S_ISDIR(mode) ? 0 : RICHACE_DELETE_CHILD; + unsigned int owner_mask, group_mask, other_mask; + struct richacl *clone; + + owner_mask = richacl_mode_to_mask(mode >> 6) & ~x; + group_mask = richacl_mode_to_mask(mode >> 3) & ~x; + other_mask = richacl_mode_to_mask(mode) & ~x; + + if (acl->a_owner_mask == owner_mask && + acl->a_group_mask == group_mask && + acl->a_other_mask == other_mask && + (acl->a_flags & RICHACL_MASKED) && + (acl->a_flags & RICHACL_WRITE_THROUGH)) + return acl; + + clone = richacl_clone(acl, GFP_KERNEL); + richacl_put(acl); + if (!clone) + return ERR_PTR(-ENOMEM); + + clone->a_flags |= (RICHACL_WRITE_THROUGH | RICHACL_MASKED); + clone->a_owner_mask = owner_mask; + clone->a_group_mask = group_mask; + clone->a_other_mask = other_mask; + + return clone; +} + +/** + * richacl_chmod - filesystem chmod helper + * @inode: inode whose file permission bits to change + * @mode: new file permission bits including the file type + * + * Helper for filesystems to use to perform a chmod on the richacl of an inode. + */ +int +richacl_chmod(struct inode *inode, umode_t mode) +{ + struct richacl *acl; + int retval; + + if (S_ISLNK(mode)) + return -EOPNOTSUPP; + if (!inode->i_op->set_richacl) + return -EOPNOTSUPP; + acl = get_richacl(inode); + if (IS_ERR_OR_NULL(acl)) + return PTR_ERR(acl); + acl = __richacl_chmod(acl, mode); + if (IS_ERR(acl)) + return PTR_ERR(acl); + retval = inode->i_op->set_richacl(inode, acl); + richacl_put(acl); + + return retval; +} +EXPORT_SYMBOL(richacl_chmod); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index 3e05c94..db82fab 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -190,5 +190,6 @@ extern unsigned int richacl_mode_to_mask(umode_t); extern unsigned int richacl_want_to_mask(unsigned int); extern void richacl_compute_max_masks(struct richacl *); extern int richacl_permission(struct inode *, const struct richacl *, int); +extern int richacl_chmod(struct inode *, umode_t); #endif /* __RICHACL_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:09 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 0FC807CA4 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:09 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id C83298F8064 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:08 -0700 (PDT) X-ASG-Debug-ID: 1467294547-04cbb027373b63a0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id 6wPc5Mg4B9aCd1M5 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:07 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EB6E7C0467C8; Thu, 30 Jun 2016 13:49:06 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsq005273; Thu, 30 Jun 2016 09:49:00 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 15/22] richacl: Check if an acl is equivalent to a file mode Date: Thu, 30 Jun 2016 15:47:06 +0200 X-ASG-Orig-Subj: [PATCH v23 15/22] richacl: Check if an acl is equivalent to a file mode Message-Id: <1467294433-3222-16-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Thu, 30 Jun 2016 13:49:07 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294547 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4352 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 ACLs are considered equivalent to file modes if they only consist of owner@, group@, and everyone@ entries, the owner@ permissions do not depend on whether the owner is a member in the owning group, and no inheritance flags are set. This test is used to avoid storing richacls if the acl can be computed from the file permission bits. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: J. Bruce Fields <bfields@redhat.com> --- fs/richacl.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 1 + 2 files changed, 105 insertions(+) diff --git a/fs/richacl.c b/fs/richacl.c index ba110a6..e8a383b 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -618,3 +618,107 @@ richacl_chmod(struct inode *inode, umode_t mode) return retval; } EXPORT_SYMBOL(richacl_chmod); + +/** + * richacl_equiv_mode - compute the mode equivalent of @acl + * + * An acl is considered equivalent to a file mode if it only consists of + * owner@, group@, and everyone@ entries and the owner@ permissions do not + * depend on whether the owner is a member in the owning group. + */ +int +richacl_equiv_mode(const struct richacl *acl, umode_t *mode_p) +{ + umode_t mode = *mode_p; + + /* + * The RICHACE_DELETE_CHILD flag is meaningless for non-directories, so + * we ignore it. + */ + unsigned int x = S_ISDIR(mode) ? 0 : RICHACE_DELETE_CHILD; + struct { + unsigned int allowed; + unsigned int defined; /* allowed or denied */ + } owner = { + .defined = RICHACE_POSIX_ALWAYS_ALLOWED | + RICHACE_POSIX_OWNER_ALLOWED | x, + }, group = { + .defined = RICHACE_POSIX_ALWAYS_ALLOWED | x, + }, everyone = { + .defined = RICHACE_POSIX_ALWAYS_ALLOWED | x, + }; + const struct richace *ace; + + if (acl->a_flags & ~(RICHACL_WRITE_THROUGH | RICHACL_MASKED)) + return -1; + + richacl_for_each_entry(ace, acl) { + if (ace->e_flags & ~RICHACE_SPECIAL_WHO) + return -1; + + if (richace_is_owner(ace) || richace_is_everyone(ace)) { + x = ace->e_mask & ~owner.defined; + if (richace_is_allow(ace)) { + unsigned int group_denied = + group.defined & ~group.allowed; + + if (x & group_denied) + return -1; + owner.allowed |= x; + } else /* if (richace_is_deny(ace)) */ { + if (x & group.allowed) + return -1; + } + owner.defined |= x; + + if (richace_is_everyone(ace)) { + x = ace->e_mask; + if (richace_is_allow(ace)) { + group.allowed |= + x & ~group.defined; + everyone.allowed |= + x & ~everyone.defined; + } + group.defined |= x; + everyone.defined |= x; + } + } else if (richace_is_group(ace)) { + x = ace->e_mask & ~group.defined; + if (richace_is_allow(ace)) + group.allowed |= x; + group.defined |= x; + } else + return -1; + } + + if (group.allowed & ~owner.defined) + return -1; + + if (acl->a_flags & RICHACL_MASKED) { + if (acl->a_flags & RICHACL_WRITE_THROUGH) { + owner.allowed = acl->a_owner_mask; + everyone.allowed = acl->a_other_mask; + } else { + owner.allowed &= acl->a_owner_mask; + everyone.allowed &= acl->a_other_mask; + } + group.allowed &= acl->a_group_mask; + } + + mode = (mode & ~S_IRWXUGO) | + (richacl_mask_to_mode(owner.allowed) << 6) | + (richacl_mask_to_mode(group.allowed) << 3) | + richacl_mask_to_mode(everyone.allowed); + + /* Mask flags we can ignore */ + x = S_ISDIR(mode) ? 0 : RICHACE_DELETE_CHILD; + + if (((richacl_mode_to_mask(mode >> 6) ^ owner.allowed) & ~x) || + ((richacl_mode_to_mask(mode >> 3) ^ group.allowed) & ~x) || + ((richacl_mode_to_mask(mode) ^ everyone.allowed) & ~x)) + return -1; + + *mode_p = mode; + return 0; +} +EXPORT_SYMBOL_GPL(richacl_equiv_mode); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index db82fab..9212edb 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -191,5 +191,6 @@ extern unsigned int richacl_want_to_mask(unsigned int); extern void richacl_compute_max_masks(struct richacl *); extern int richacl_permission(struct inode *, const struct richacl *, int); extern int richacl_chmod(struct inode *, umode_t); +extern int richacl_equiv_mode(const struct richacl *, umode_t *); #endif /* __RICHACL_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:16 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 4B62C7CA4 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:16 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id D9633AC008 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:15 -0700 (PDT) X-ASG-Debug-ID: 1467294554-04bdf074b62387a0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id geSX7xTzVvzuMCpo (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:14 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id DDDA1C05B1E7; Thu, 30 Jun 2016 13:49:13 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsr005273; Thu, 30 Jun 2016 09:49:07 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 16/22] richacl: Create-time inheritance Date: Thu, 30 Jun 2016 15:47:07 +0200 X-ASG-Orig-Subj: [PATCH v23 16/22] richacl: Create-time inheritance Message-Id: <1467294433-3222-17-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 30 Jun 2016 13:49:14 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294554 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5758 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 When a new file is created, it can inherit an acl from its parent directory; this is similar to how default acls work in POSIX ACLs. As with POSIX ACLs, if a file inherits an acl from its parent directory, the intersection between the create mode and the permissions granted by the inherited acl determines the file masks and file permission bits, and the umask is ignored. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- fs/richacl.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 2 + 2 files changed, 153 insertions(+) diff --git a/fs/richacl.c b/fs/richacl.c index e8a383b..29eaf89 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -722,3 +722,154 @@ richacl_equiv_mode(const struct richacl *acl, umode_t *mode_p) return 0; } EXPORT_SYMBOL_GPL(richacl_equiv_mode); + +static inline bool +ace_inherits_to_directory(const struct richace *ace) +{ + if (ace->e_flags & RICHACE_DIRECTORY_INHERIT_ACE) + return true; + if ((ace->e_flags & RICHACE_FILE_INHERIT_ACE) && + !(ace->e_flags & RICHACE_NO_PROPAGATE_INHERIT_ACE)) + return true; + return false; +} + +/** + * richacl_inherit - compute the inherited acl of a new file + * @dir_acl: acl of the containing directory + * @isdir: inherit by a directory or non-directory? + * + * A directory can have acl entries which files and/or directories created + * inside the directory will inherit. This function computes the acl for such + * a new file. If there is no inheritable acl, it will return %NULL. + */ +struct richacl * +richacl_inherit(const struct richacl *dir_acl, int isdir) +{ + const struct richace *dir_ace; + struct richacl *acl = NULL; + struct richace *ace; + int count = 0; + + if (isdir) { + richacl_for_each_entry(dir_ace, dir_acl) { + if (!ace_inherits_to_directory(dir_ace)) + continue; + count++; + } + if (!count) + return NULL; + acl = richacl_alloc(count, GFP_KERNEL); + if (!acl) + return ERR_PTR(-ENOMEM); + ace = acl->a_entries; + richacl_for_each_entry(dir_ace, dir_acl) { + if (!ace_inherits_to_directory(dir_ace)) + continue; + richace_copy(ace, dir_ace); + if (dir_ace->e_flags & RICHACE_NO_PROPAGATE_INHERIT_ACE) + ace->e_flags &= ~RICHACE_INHERITANCE_FLAGS; + else if (dir_ace->e_flags & RICHACE_DIRECTORY_INHERIT_ACE) + ace->e_flags &= ~RICHACE_INHERIT_ONLY_ACE; + else + ace->e_flags |= RICHACE_INHERIT_ONLY_ACE; + ace++; + } + } else { + richacl_for_each_entry(dir_ace, dir_acl) { + if (!(dir_ace->e_flags & RICHACE_FILE_INHERIT_ACE)) + continue; + count++; + } + if (!count) + return NULL; + acl = richacl_alloc(count, GFP_KERNEL); + if (!acl) + return ERR_PTR(-ENOMEM); + ace = acl->a_entries; + richacl_for_each_entry(dir_ace, dir_acl) { + if (!(dir_ace->e_flags & RICHACE_FILE_INHERIT_ACE)) + continue; + richace_copy(ace, dir_ace); + ace->e_flags &= ~RICHACE_INHERITANCE_FLAGS; + /* + * RICHACE_DELETE_CHILD is meaningless for + * non-directories, so clear it. + */ + ace->e_mask &= ~RICHACE_DELETE_CHILD; + ace++; + } + } + + return acl; +} + +/* + * richacl_inherit_inode - compute inherited acl and file mode + * @dir_acl: acl of the containing directory + * @mode_p: mode of the new inode + * + * The file permission bits in @mode_p must be set to the create mode by the + * caller. + * + * If there is an inheritable acl, the maximum permissions that the acl grants + * are computed and the file masks of the new acl are set accordingly. + */ +static struct richacl * +richacl_inherit_inode(const struct richacl *dir_acl, umode_t *mode_p) +{ + struct richacl *acl; + umode_t mode = *mode_p; + + acl = richacl_inherit(dir_acl, S_ISDIR(mode)); + if (acl) { + if (richacl_equiv_mode(acl, &mode) == 0) { + *mode_p &= mode; + richacl_put(acl); + acl = NULL; + } else { + richacl_compute_max_masks(acl); + /* + * Ensure that the acl will not grant any permissions + * beyond the create mode. + */ + acl->a_flags |= RICHACL_MASKED; + acl->a_owner_mask &= + richacl_mode_to_mask(mode >> 6); + acl->a_group_mask &= + richacl_mode_to_mask(mode >> 3); + acl->a_other_mask &= + richacl_mode_to_mask(mode); + } + } else + *mode_p &= ~current_umask(); + + return acl; +} + +/** + * richacl_create - filesystem create helper + * @mode_p: mode of the new inode + * @dir: containing directory + * + * Compute the inherited acl for a new inode. If there is no acl to inherit, + * apply the umask. Use when creating a new inode on a richacl enabled file + * system. + */ +struct richacl *richacl_create(umode_t *mode_p, struct inode *dir) +{ + struct richacl *dir_acl, *acl = NULL; + + if (S_ISLNK(*mode_p)) + return NULL; + dir_acl = get_richacl(dir); + if (dir_acl) { + if (IS_ERR(dir_acl)) + return dir_acl; + acl = richacl_inherit_inode(dir_acl, mode_p); + richacl_put(dir_acl); + } else + *mode_p &= ~current_umask(); + return acl; +} +EXPORT_SYMBOL_GPL(richacl_create); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index 9212edb..7aca1a3 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -192,5 +192,7 @@ extern void richacl_compute_max_masks(struct richacl *); extern int richacl_permission(struct inode *, const struct richacl *, int); extern int richacl_chmod(struct inode *, umode_t); extern int richacl_equiv_mode(const struct richacl *, umode_t *); +extern struct richacl *richacl_inherit(const struct richacl *, int); +extern struct richacl *richacl_create(umode_t *, struct inode *); #endif /* __RICHACL_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:23 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 13AF07CF6 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:23 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id DA724304039 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:22 -0700 (PDT) X-ASG-Debug-ID: 1467294561-04cbb027353b63e0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id EgFcOdCQOceOI0AB (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:21 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D414E552FE; Thu, 30 Jun 2016 13:49:20 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDss005273; Thu, 30 Jun 2016 09:49:14 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 17/22] richacl: Automatic Inheritance Date: Thu, 30 Jun 2016 15:47:08 +0200 X-ASG-Orig-Subj: [PATCH v23 17/22] richacl: Automatic Inheritance Message-Id: <1467294433-3222-18-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 30 Jun 2016 13:49:21 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294561 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6227 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Automatic Inheritance (AI) allows changes to the acl of a directory to propagate down to children. This is mostly implemented in user space: when a process changes the permissions of a directory and Automatic Inheritance is enabled for that directory, the process must propagate those changes to all children, recursively. The kernel enables this by keeping track of which permissions have been inherited at create time. In addition, it makes sure that permission propagation is turned off when the permissions are set explicitly (for example, upon create or chmod). Automatic Inheritance works as follows: - When the RICHACL_AUTO_INHERIT flag in the acl of a file or directory is not set, the file or directory is not affected by AI. - When the RICHACL_AUTO_INHERIT flag in the acl of a directory is set and a file or subdirectory is created in that directory, the inherited acl will have the RICHACL_AUTO_INHERIT flag set, and all inherited aces will have the RICHACE_INHERITED_ACE flag set. This allows user space to distinguish between aces which have been inherited and aces which have been explicitly added. - When the RICHACL_PROTECTED acl flag in the acl of a file or directory is set, AI will not modify the acl. This does not affect propagation of permissions from the file to its children (if the file is a directory). Linux does not have a way of creating files or directories without setting the file permission bits, so all files created inside a directory with RICHACL_AUTO_INHERIT set will have the RICHACL_PROTECTED flag set. This effectively disables Automatic Inheritance. Protocols which support creating files without specifying permissions can explicitly clear the RICHACL_PROTECTED flag after creating a file and reset the file masks to "undo" applying the create mode; see richacl_compute_max_masks(). They should set the RICHACL_DEFAULTED flag. (A mechanism that would allow to indicate to the kernel to ignore the create mode in the first place when there are inherited permissions would be nice to have.) Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- fs/richacl.c | 20 +++++++++++++++++++- include/linux/richacl.h | 12 ++++++++++++ include/uapi/linux/richacl.h | 11 ++++++++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/fs/richacl.c b/fs/richacl.c index 29eaf89..40e4af9 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -573,7 +573,8 @@ __richacl_chmod(struct richacl *acl, umode_t mode) acl->a_group_mask == group_mask && acl->a_other_mask == other_mask && (acl->a_flags & RICHACL_MASKED) && - (acl->a_flags & RICHACL_WRITE_THROUGH)) + (acl->a_flags & RICHACL_WRITE_THROUGH) && + (!richacl_is_auto_inherit(acl) || richacl_is_protected(acl))) return acl; clone = richacl_clone(acl, GFP_KERNEL); @@ -585,6 +586,8 @@ __richacl_chmod(struct richacl *acl, umode_t mode) clone->a_owner_mask = owner_mask; clone->a_group_mask = group_mask; clone->a_other_mask = other_mask; + if (richacl_is_auto_inherit(clone)) + clone->a_flags |= RICHACL_PROTECTED; return clone; } @@ -800,6 +803,14 @@ richacl_inherit(const struct richacl *dir_acl, int isdir) ace++; } } + if (richacl_is_auto_inherit(dir_acl)) { + acl->a_flags = RICHACL_AUTO_INHERIT; + richacl_for_each_entry(ace, acl) + ace->e_flags |= RICHACE_INHERITED_ACE; + } else { + richacl_for_each_entry(ace, acl) + ace->e_flags &= ~RICHACE_INHERITED_ACE; + } return acl; } @@ -828,6 +839,13 @@ richacl_inherit_inode(const struct richacl *dir_acl, umode_t *mode_p) richacl_put(acl); acl = NULL; } else { + /* + * We need to set RICHACL_PROTECTED because we are + * doing an implicit chmod + */ + if (richacl_is_auto_inherit(acl)) + acl->a_flags |= RICHACL_PROTECTED; + richacl_compute_max_masks(acl); /* * Ensure that the acl will not grant any permissions diff --git a/include/linux/richacl.h b/include/linux/richacl.h index 7aca1a3..a442372 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -81,6 +81,18 @@ extern void set_cached_richacl(struct inode *, struct richacl *); extern void forget_cached_richacl(struct inode *); extern struct richacl *get_richacl(struct inode *); +static inline int +richacl_is_auto_inherit(const struct richacl *acl) +{ + return acl->a_flags & RICHACL_AUTO_INHERIT; +} + +static inline int +richacl_is_protected(const struct richacl *acl) +{ + return acl->a_flags & RICHACL_PROTECTED; +} + /** * richace_is_owner - check if @ace is an OWNER@ entry */ diff --git a/include/uapi/linux/richacl.h b/include/uapi/linux/richacl.h index 1ed48ac..8849a53 100644 --- a/include/uapi/linux/richacl.h +++ b/include/uapi/linux/richacl.h @@ -18,6 +18,9 @@ #define __UAPI_RICHACL_H /* a_flags values */ +#define RICHACL_AUTO_INHERIT 0x01 +#define RICHACL_PROTECTED 0x02 +#define RICHACL_DEFAULTED 0x04 #define RICHACL_WRITE_THROUGH 0x40 #define RICHACL_MASKED 0x80 @@ -31,6 +34,7 @@ #define RICHACE_NO_PROPAGATE_INHERIT_ACE 0x0004 #define RICHACE_INHERIT_ONLY_ACE 0x0008 #define RICHACE_IDENTIFIER_GROUP 0x0040 +#define RICHACE_INHERITED_ACE 0x0080 #define RICHACE_SPECIAL_WHO 0x4000 /* e_mask bitflags */ @@ -60,6 +64,9 @@ #define RICHACE_EVERYONE_SPECIAL_ID 2 #define RICHACL_VALID_FLAGS ( \ + RICHACL_AUTO_INHERIT | \ + RICHACL_PROTECTED | \ + RICHACL_DEFAULTED | \ RICHACL_WRITE_THROUGH | \ RICHACL_MASKED ) @@ -69,13 +76,15 @@ RICHACE_NO_PROPAGATE_INHERIT_ACE | \ RICHACE_INHERIT_ONLY_ACE | \ RICHACE_IDENTIFIER_GROUP | \ + RICHACE_INHERITED_ACE | \ RICHACE_SPECIAL_WHO ) #define RICHACE_INHERITANCE_FLAGS ( \ RICHACE_FILE_INHERIT_ACE | \ RICHACE_DIRECTORY_INHERIT_ACE | \ RICHACE_NO_PROPAGATE_INHERIT_ACE | \ - RICHACE_INHERIT_ONLY_ACE ) + RICHACE_INHERIT_ONLY_ACE | \ + RICHACE_INHERITED_ACE ) /* Valid RICHACE_* flags for directories and non-directories */ #define RICHACE_VALID_MASK ( \ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:30 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 679557CF6 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:30 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2AFE98F8054 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:30 -0700 (PDT) X-ASG-Debug-ID: 1467294568-04cb6c063f2c46b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id A9UFZwt1dWJJM8zC (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:28 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id C7256627C5; Thu, 30 Jun 2016 13:49:27 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDst005273; Thu, 30 Jun 2016 09:49:21 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 18/22] richacl: xattr mapping functions Date: Thu, 30 Jun 2016 15:47:09 +0200 X-ASG-Orig-Subj: [PATCH v23 18/22] richacl: xattr mapping functions Message-Id: <1467294433-3222-19-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Thu, 30 Jun 2016 13:49:27 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294568 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9922 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Map between "system.richacl" xattrs and the in-kernel representation. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- fs/Makefile | 2 +- fs/richacl_xattr.c | 161 +++++++++++++++++++++++++++++++++++++ include/linux/richacl_xattr.h | 29 +++++++ include/uapi/linux/Kbuild | 1 + include/uapi/linux/richacl_xattr.h | 44 ++++++++++ include/uapi/linux/xattr.h | 2 + 6 files changed, 238 insertions(+), 1 deletion(-) create mode 100644 fs/richacl_xattr.c create mode 100644 include/linux/richacl_xattr.h create mode 100644 include/uapi/linux/richacl_xattr.h diff --git a/fs/Makefile b/fs/Makefile index 2b3e6f1..262fd67 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_COREDUMP) += coredump.o obj-$(CONFIG_SYSCTL) += drop_caches.o obj-$(CONFIG_FHANDLE) += fhandle.o -obj-$(CONFIG_FS_RICHACL) += richacl.o +obj-$(CONFIG_FS_RICHACL) += richacl.o richacl_xattr.o obj-y += quota/ diff --git a/fs/richacl_xattr.c b/fs/richacl_xattr.c new file mode 100644 index 0000000..dc1ad36 --- /dev/null +++ b/fs/richacl_xattr.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher <agruenba@redhat.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/slab.h> +#include <linux/module.h> +#include <linux/richacl_xattr.h> + +/** + * richacl_from_xattr - convert a richacl xattr into the in-memory representation + */ +struct richacl * +richacl_from_xattr(struct user_namespace *user_ns, + const void *value, size_t size, int invalid_error) +{ + const struct richacl_xattr *xattr_acl = value; + const struct richace_xattr *xattr_ace = (void *)(xattr_acl + 1); + struct richacl *acl; + struct richace *ace; + int count; + + if (size < sizeof(*xattr_acl) || + xattr_acl->a_version != RICHACL_XATTR_VERSION || + (xattr_acl->a_flags & ~RICHACL_VALID_FLAGS)) + goto invalid; + size -= sizeof(*xattr_acl); + count = le16_to_cpu(xattr_acl->a_count); + if (count > RICHACL_XATTR_MAX_COUNT) + goto invalid; + if (size != count * sizeof(*xattr_ace)) + goto invalid; + + acl = richacl_alloc(count, GFP_NOFS); + if (!acl) + return ERR_PTR(-ENOMEM); + + acl->a_flags = xattr_acl->a_flags; + acl->a_owner_mask = le32_to_cpu(xattr_acl->a_owner_mask); + if (acl->a_owner_mask & ~RICHACE_VALID_MASK) + goto put_invalid; + acl->a_group_mask = le32_to_cpu(xattr_acl->a_group_mask); + if (acl->a_group_mask & ~RICHACE_VALID_MASK) + goto put_invalid; + acl->a_other_mask = le32_to_cpu(xattr_acl->a_other_mask); + if (acl->a_other_mask & ~RICHACE_VALID_MASK) + goto put_invalid; + + richacl_for_each_entry(ace, acl) { + ace->e_type = le16_to_cpu(xattr_ace->e_type); + ace->e_flags = le16_to_cpu(xattr_ace->e_flags); + ace->e_mask = le32_to_cpu(xattr_ace->e_mask); + + if (ace->e_flags & ~RICHACE_VALID_FLAGS) + goto put_invalid; + if (ace->e_flags & RICHACE_SPECIAL_WHO) { + ace->e_id.special = le32_to_cpu(xattr_ace->e_id); + if (ace->e_id.special > RICHACE_EVERYONE_SPECIAL_ID) + goto put_invalid; + } else if (ace->e_flags & RICHACE_IDENTIFIER_GROUP) { + u32 id = le32_to_cpu(xattr_ace->e_id); + + ace->e_id.gid = make_kgid(user_ns, id); + if (!gid_valid(ace->e_id.gid)) + goto put_invalid; + } else { + u32 id = le32_to_cpu(xattr_ace->e_id); + + ace->e_id.uid = make_kuid(user_ns, id); + if (!uid_valid(ace->e_id.uid)) + goto put_invalid; + } + if (ace->e_type > RICHACE_ACCESS_DENIED_ACE_TYPE || + (ace->e_mask & ~RICHACE_VALID_MASK)) + goto put_invalid; + + xattr_ace++; + } + + return acl; + +put_invalid: + richacl_put(acl); +invalid: + return ERR_PTR(invalid_error); +} +EXPORT_SYMBOL_GPL(richacl_from_xattr); + +/** + * richacl_xattr_size - compute the size of the xattr representation of @acl + */ +size_t +richacl_xattr_size(const struct richacl *acl) +{ + size_t size = sizeof(struct richacl_xattr); + + size += sizeof(struct richace_xattr) * acl->a_count; + return size; +} +EXPORT_SYMBOL_GPL(richacl_xattr_size); + +/** + * richacl_to_xattr - convert @acl into its xattr representation + * @acl: the richacl to convert + * @buffer: buffer for the result + * @size: size of @buffer + */ +int +richacl_to_xattr(struct user_namespace *user_ns, + const struct richacl *acl, void *buffer, size_t size) +{ + struct richacl_xattr *xattr_acl = buffer; + struct richace_xattr *xattr_ace; + const struct richace *ace; + size_t real_size; + + real_size = richacl_xattr_size(acl); + if (!buffer) + return real_size; + if (real_size > size) + return -ERANGE; + + xattr_acl->a_version = RICHACL_XATTR_VERSION; + xattr_acl->a_flags = acl->a_flags; + xattr_acl->a_count = cpu_to_le16(acl->a_count); + + xattr_acl->a_owner_mask = cpu_to_le32(acl->a_owner_mask); + xattr_acl->a_group_mask = cpu_to_le32(acl->a_group_mask); + xattr_acl->a_other_mask = cpu_to_le32(acl->a_other_mask); + + xattr_ace = (void *)(xattr_acl + 1); + richacl_for_each_entry(ace, acl) { + xattr_ace->e_type = cpu_to_le16(ace->e_type); + xattr_ace->e_flags = cpu_to_le16(ace->e_flags); + xattr_ace->e_mask = cpu_to_le32(ace->e_mask); + if (ace->e_flags & RICHACE_SPECIAL_WHO) + xattr_ace->e_id = cpu_to_le32(ace->e_id.special); + else if (ace->e_flags & RICHACE_IDENTIFIER_GROUP) + xattr_ace->e_id = + cpu_to_le32(from_kgid(user_ns, ace->e_id.gid)); + else + xattr_ace->e_id = + cpu_to_le32(from_kuid(user_ns, ace->e_id.uid)); + xattr_ace++; + } + return real_size; +} +EXPORT_SYMBOL_GPL(richacl_to_xattr); diff --git a/include/linux/richacl_xattr.h b/include/linux/richacl_xattr.h new file mode 100644 index 0000000..0efa14b --- /dev/null +++ b/include/linux/richacl_xattr.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher <agruenba@redhat.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#ifndef __RICHACL_XATTR_H +#define __RICHACL_XATTR_H + +#include <uapi/linux/richacl_xattr.h> +#include <linux/richacl.h> + +extern struct richacl *richacl_from_xattr(struct user_namespace *, const void *, + size_t, int); +extern size_t richacl_xattr_size(const struct richacl *); +extern int richacl_to_xattr(struct user_namespace *, const struct richacl *, + void *, size_t); + +#endif /* __RICHACL_XATTR_H */ diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild index abeaa98..c24e106 100644 --- a/include/uapi/linux/Kbuild +++ b/include/uapi/linux/Kbuild @@ -356,6 +356,7 @@ header-y += reiserfs_fs.h header-y += reiserfs_xattr.h header-y += resource.h header-y += richacl.h +header-y += richacl_xattr.h header-y += rfkill.h header-y += rio_mport_cdev.h header-y += romfs_fs.h diff --git a/include/uapi/linux/richacl_xattr.h b/include/uapi/linux/richacl_xattr.h new file mode 100644 index 0000000..20da204 --- /dev/null +++ b/include/uapi/linux/richacl_xattr.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2006, 2010 Novell, Inc. + * Copyright (C) 2015 Red Hat, Inc. + * Written by Andreas Gruenbacher <agruenba@redhat.com> + * + * This file is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + */ + +#ifndef __UAPI_RICHACL_XATTR_H +#define __UAPI_RICHACL_XATTR_H + +#include <linux/types.h> +#include <linux/limits.h> + +struct richace_xattr { + __le16 e_type; + __le16 e_flags; + __le32 e_mask; + __le32 e_id; +}; + +struct richacl_xattr { + __u8 a_version; + __u8 a_flags; + __le16 a_count; + __le32 a_owner_mask; + __le32 a_group_mask; + __le32 a_other_mask; +}; + +#define RICHACL_XATTR_VERSION 0 +#define RICHACL_XATTR_MAX_COUNT \ + ((XATTR_SIZE_MAX - sizeof(struct richacl_xattr)) / \ + sizeof(struct richace_xattr)) + +#endif /* __UAPI_RICHACL_XATTR_H */ diff --git a/include/uapi/linux/xattr.h b/include/uapi/linux/xattr.h index 1590c49..1996903 100644 --- a/include/uapi/linux/xattr.h +++ b/include/uapi/linux/xattr.h @@ -73,5 +73,7 @@ #define XATTR_POSIX_ACL_DEFAULT "posix_acl_default" #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT +#define XATTR_RICHACL "richacl" +#define XATTR_NAME_RICHACL XATTR_SYSTEM_PREFIX XATTR_RICHACL #endif /* _UAPI_LINUX_XATTR_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:37 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 6222E7D01 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:37 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2538A8F8054 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:37 -0700 (PDT) X-ASG-Debug-ID: 1467294574-04bdf074b62387f0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id ZxGXe2P54DRsvoBv (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:35 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id AB9FBBDEA; Thu, 30 Jun 2016 13:49:34 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsu005273; Thu, 30 Jun 2016 09:49:28 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 19/22] richacl: Add richacl xattr handler Date: Thu, 30 Jun 2016 15:47:10 +0200 X-ASG-Orig-Subj: [PATCH v23 19/22] richacl: Add richacl xattr handler Message-Id: <1467294433-3222-20-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 30 Jun 2016 13:49:34 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294575 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4284 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Add richacl xattr handler implementing the xattr operations based on the get_richacl and set_richacl inode operations. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- fs/richacl.c | 22 ++++++++++++++++ fs/richacl_xattr.c | 61 +++++++++++++++++++++++++++++++++++++++++++ include/linux/richacl.h | 1 + include/linux/richacl_xattr.h | 2 ++ 4 files changed, 86 insertions(+) diff --git a/fs/richacl.c b/fs/richacl.c index 40e4af9..b7d7104 100644 --- a/fs/richacl.c +++ b/fs/richacl.c @@ -549,6 +549,28 @@ out: EXPORT_SYMBOL_GPL(richacl_permission); /** + * set_richacl - set the richacl of an inode + * @inode: inode whose richacl to set + * @acl: access control list + */ +int +set_richacl(struct inode *inode, struct richacl *acl) +{ + if (!IS_RICHACL(inode)) + return -EOPNOTSUPP; + if (!inode->i_op->set_richacl) + return -EOPNOTSUPP; + + if (!uid_eq(current_fsuid(), inode->i_uid) && + inode_permission(inode, MAY_CHMOD) && + !capable(CAP_FOWNER)) + return -EPERM; + + return inode->i_op->set_richacl(inode, acl); +} +EXPORT_SYMBOL(set_richacl); + +/** * __richacl_chmod - update the file masks to reflect the new mode * @acl: access control list * @mode: new file permission bits including the file type diff --git a/fs/richacl_xattr.c b/fs/richacl_xattr.c index dc1ad36..5eb4aba 100644 --- a/fs/richacl_xattr.c +++ b/fs/richacl_xattr.c @@ -18,7 +18,9 @@ #include <linux/fs.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/xattr.h> #include <linux/richacl_xattr.h> +#include <uapi/linux/xattr.h> /** * richacl_from_xattr - convert a richacl xattr into the in-memory representation @@ -159,3 +161,62 @@ richacl_to_xattr(struct user_namespace *user_ns, return real_size; } EXPORT_SYMBOL_GPL(richacl_to_xattr); + +static bool +richacl_xattr_list(struct dentry *dentry) +{ + return IS_RICHACL(d_backing_inode(dentry)); +} + +static int +richacl_xattr_get(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *name, void *buffer, size_t buffer_size) +{ + struct richacl *acl; + int error; + + if (*name) + return -EINVAL; + if (!IS_RICHACL(inode)) + return -EOPNOTSUPP; + if (S_ISLNK(inode->i_mode)) + return -EOPNOTSUPP; + acl = get_richacl(inode); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl == NULL) + return -ENODATA; + error = richacl_to_xattr(current_user_ns(), acl, buffer, buffer_size); + richacl_put(acl); + return error; +} + +static int +richacl_xattr_set(const struct xattr_handler *handler, + struct dentry *unused, struct inode *inode, + const char *name, const void *value, size_t size, + int flags) +{ + struct richacl *acl = NULL; + int ret; + + if (value) { + acl = richacl_from_xattr(current_user_ns(), value, size, + -EINVAL); + if (IS_ERR(acl)) + return PTR_ERR(acl); + } + + ret = set_richacl(inode, acl); + richacl_put(acl); + return ret; +} + +struct xattr_handler richacl_xattr_handler = { + .name = XATTR_NAME_RICHACL, + .list = richacl_xattr_list, + .get = richacl_xattr_get, + .set = richacl_xattr_set, +}; +EXPORT_SYMBOL(richacl_xattr_handler); diff --git a/include/linux/richacl.h b/include/linux/richacl.h index a442372..e7db066 100644 --- a/include/linux/richacl.h +++ b/include/linux/richacl.h @@ -206,5 +206,6 @@ extern int richacl_chmod(struct inode *, umode_t); extern int richacl_equiv_mode(const struct richacl *, umode_t *); extern struct richacl *richacl_inherit(const struct richacl *, int); extern struct richacl *richacl_create(umode_t *, struct inode *); +extern int set_richacl(struct inode *, struct richacl *); #endif /* __RICHACL_H */ diff --git a/include/linux/richacl_xattr.h b/include/linux/richacl_xattr.h index 0efa14b..6c6adb1 100644 --- a/include/linux/richacl_xattr.h +++ b/include/linux/richacl_xattr.h @@ -26,4 +26,6 @@ extern size_t richacl_xattr_size(const struct richacl *); extern int richacl_to_xattr(struct user_namespace *, const struct richacl *, void *, size_t); +extern struct xattr_handler richacl_xattr_handler; + #endif /* __RICHACL_XATTR_H */ -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:45 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5563B7CA1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:45 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id 082E18F8054 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:44 -0700 (PDT) X-ASG-Debug-ID: 1467294581-04bdf074b5238800001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id HoCwTulPPaiJEZC2 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:42 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 9ED7ABBB4D; Thu, 30 Jun 2016 13:49:41 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsv005273; Thu, 30 Jun 2016 09:49:35 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Andreas Gruenbacher <agruenba@redhat.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: [PATCH v23 20/22] vfs: Add richacl permission checking Date: Thu, 30 Jun 2016 15:47:11 +0200 X-ASG-Orig-Subj: [PATCH v23 20/22] vfs: Add richacl permission checking Message-Id: <1467294433-3222-21-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Thu, 30 Jun 2016 13:49:41 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294582 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2617 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 Hook the richacl permission checking function into the vfs. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> --- fs/namei.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 7a822d0..48c9958 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -34,6 +34,7 @@ #include <linux/device_cgroup.h> #include <linux/fs_struct.h> #include <linux/posix_acl.h> +#include <linux/richacl.h> #include <linux/hash.h> #include <linux/bitops.h> #include <asm/uaccess.h> @@ -256,7 +257,43 @@ void putname(struct filename *name) __putname(name); } -static int check_acl(struct inode *inode, int mask) +static int check_richacl(struct inode *inode, int mask) +{ +#ifdef CONFIG_FS_RICHACL + if (mask & MAY_NOT_BLOCK) { + struct base_acl *base_acl; + + base_acl = rcu_dereference(inode->i_acl); + if (!base_acl) + goto no_acl; + /* no ->get_richacl() calls in RCU mode... */ + if (is_uncached_acl(base_acl)) + return -ECHILD; + return richacl_permission(inode, richacl(base_acl), + mask & ~MAY_NOT_BLOCK); + } else { + struct richacl *acl; + + acl = get_richacl(inode); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl) { + int error = richacl_permission(inode, acl, mask); + richacl_put(acl); + return error; + } + } +no_acl: +#endif + if (mask & (MAY_DELETE_SELF | MAY_TAKE_OWNERSHIP | + MAY_CHMOD | MAY_SET_TIMES)) { + /* File permission bits cannot grant this. */ + return -EACCES; + } + return -EAGAIN; +} + +static int check_posix_acl(struct inode *inode, int mask) { #ifdef CONFIG_FS_POSIX_ACL if (mask & MAY_NOT_BLOCK) { @@ -294,11 +331,24 @@ static int acl_permission_check(struct inode *inode, int mask) { unsigned int mode = inode->i_mode; + /* + * With POSIX ACLs, the (mode & S_IRWXU) bits exactly match the owner + * permissions, and we can skip checking posix acls for the owner. + * With richacls, the owner may be granted fewer permissions than the + * mode bits seem to suggest (for example, append but not write), and + * we always need to check the richacl. + */ + + if (IS_RICHACL(inode)) { + int error = check_richacl(inode, mask); + if (error != -EAGAIN) + return error; + } if (likely(uid_eq(current_fsuid(), inode->i_uid))) mode >>= 6; else { if (IS_POSIXACL(inode) && (mode & S_IRWXG)) { - int error = check_acl(inode, mask); + int error = check_posix_acl(inode, mask); if (error != -EAGAIN) return error; } -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:49:53 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 33B437CA1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:49:53 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 95D0AAC007 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:52 -0700 (PDT) X-ASG-Debug-ID: 1467294589-04cb6c063f2c4770001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id StWXhrXPWoa6KfXP (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:50 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A0C46141C; Thu, 30 Jun 2016 13:49:49 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsw005273; Thu, 30 Jun 2016 09:49:42 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org, Andreas Gruenbacher <agruenba@redhat.com> Subject: [PATCH v23 21/22] ext4: Add richacl support Date: Thu, 30 Jun 2016 15:47:12 +0200 X-ASG-Orig-Subj: [PATCH v23 21/22] ext4: Add richacl support Message-Id: <1467294433-3222-22-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.25]); Thu, 30 Jun 2016 13:49:49 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294590 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 11569 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> Support the richacl permission model in ext4. The richacls are stored in "system.richacl" xattrs. Richacls need to be enabled by tune2fs or at file system create time. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Andreas Dilger <adilger@dilger.ca> --- fs/ext4/Kconfig | 11 +++++ fs/ext4/Makefile | 1 + fs/ext4/file.c | 3 ++ fs/ext4/ialloc.c | 11 ++++- fs/ext4/inode.c | 5 +- fs/ext4/namei.c | 5 ++ fs/ext4/richacl.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++ fs/ext4/richacl.h | 40 ++++++++++++++++ fs/ext4/xattr.c | 7 +++ include/linux/acl.h | 15 ++++++ 10 files changed, 228 insertions(+), 4 deletions(-) create mode 100644 fs/ext4/richacl.c create mode 100644 fs/ext4/richacl.h create mode 100644 include/linux/acl.h diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index b46e9fc..4e21c18 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -22,6 +22,17 @@ config EXT3_FS_POSIX_ACL This config option is here only for backward compatibility. ext3 filesystem is now handled by the ext4 driver. +config EXT4_FS_RICHACL + bool "Ext4 Rich Access Control Lists" + depends on EXT4_FS + select FS_RICHACL + help + Richacls are an implementation of NFSv4 ACLs, extended by file masks + to cleanly integrate into the POSIX file permission model. To learn + more about them, see http://www.bestbits.at/richacl/. + + If you don't know what Richacls are, say N. + config EXT3_FS_SECURITY bool "Ext3 Security Labels" depends on EXT3_FS diff --git a/fs/ext4/Makefile b/fs/ext4/Makefile index f52cf54..1fb7f11 100644 --- a/fs/ext4/Makefile +++ b/fs/ext4/Makefile @@ -14,3 +14,4 @@ ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o ext4-$(CONFIG_EXT4_FS_ENCRYPTION) += crypto_policy.o crypto.o \ crypto_key.o crypto_fname.o +ext4-$(CONFIG_EXT4_FS_RICHACL) += richacl.o diff --git a/fs/ext4/file.c b/fs/ext4/file.c index df44c87..6e7b4b9 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -30,6 +30,7 @@ #include "ext4_jbd2.h" #include "xattr.h" #include "acl.h" +#include "richacl.h" /* * Called when an inode is released. Note that this is different @@ -717,6 +718,8 @@ const struct inode_operations ext4_file_inode_operations = { .removexattr = generic_removexattr, .get_acl = ext4_get_acl, .set_acl = ext4_set_acl, + .get_richacl = ext4_get_richacl, + .set_richacl = ext4_set_richacl, .fiemap = ext4_fiemap, }; diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 3da4cf8..5bd382a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -27,6 +27,7 @@ #include "ext4_jbd2.h" #include "xattr.h" #include "acl.h" +#include "richacl.h" #include <trace/events/ext4.h> @@ -729,6 +730,14 @@ out: return ret; } +static inline int +ext4_new_acl(handle_t *handle, struct inode *inode, struct inode *dir) +{ + if (IS_RICHACL(dir)) + return ext4_init_richacl(handle, inode, dir); + return ext4_init_acl(handle, inode, dir); +} + /* * There are two policies for allocating an inode. If the new inode is * a directory, then a forward search is made for a block group with both @@ -1093,7 +1102,7 @@ got: if (err) goto fail_drop; - err = ext4_init_acl(handle, inode, dir); + err = ext4_new_acl(handle, inode, dir); if (err) goto fail_free_drop; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index f7140ca..7b8d96f 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -37,10 +37,10 @@ #include <linux/printk.h> #include <linux/slab.h> #include <linux/bitops.h> +#include <linux/acl.h> #include "ext4_jbd2.h" #include "xattr.h" -#include "acl.h" #include "truncate.h" #include <trace/events/ext4.h> @@ -5183,8 +5183,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) ext4_orphan_del(NULL, inode); if (!rc && (ia_valid & ATTR_MODE)) - rc = posix_acl_chmod(inode, inode->i_mode); - + rc = acl_chmod(inode); err_out: ext4_std_error(inode->i_sb, error); if (!error) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index ec4c399..09e36b7 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -38,6 +38,7 @@ #include "xattr.h" #include "acl.h" +#include "richacl.h" #include <trace/events/ext4.h> /* @@ -3893,6 +3894,8 @@ const struct inode_operations ext4_dir_inode_operations = { .removexattr = generic_removexattr, .get_acl = ext4_get_acl, .set_acl = ext4_set_acl, + .get_richacl = ext4_get_richacl, + .set_richacl = ext4_set_richacl, .fiemap = ext4_fiemap, }; @@ -3904,4 +3907,6 @@ const struct inode_operations ext4_special_inode_operations = { .removexattr = generic_removexattr, .get_acl = ext4_get_acl, .set_acl = ext4_set_acl, + .get_richacl = ext4_get_richacl, + .set_richacl = ext4_set_richacl, }; diff --git a/fs/ext4/richacl.c b/fs/ext4/richacl.c new file mode 100644 index 0000000..0c316ff --- /dev/null +++ b/fs/ext4/richacl.c @@ -0,0 +1,134 @@ +/* + * Copyright IBM Corporation, 2010 + * Copyright (C) 2015 Red Hat, Inc. + * Author: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>, + * Andreas Gruenbacher <agruenba@redhat.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include <linux/kernel.h> +#include <linux/fs.h> +#include <linux/richacl_xattr.h> + +#include "ext4.h" +#include "ext4_jbd2.h" +#include "xattr.h" +#include "acl.h" +#include "richacl.h" + +struct richacl * +ext4_get_richacl(struct inode *inode) +{ + const int name_index = EXT4_XATTR_INDEX_RICHACL; + void *value = NULL; + struct richacl *acl = NULL; + int retval; + + retval = ext4_xattr_get(inode, name_index, "", NULL, 0); + if (retval > 0) { + value = kmalloc(retval, GFP_NOFS); + if (!value) + return ERR_PTR(-ENOMEM); + retval = ext4_xattr_get(inode, name_index, "", value, retval); + } + if (retval > 0) + acl = richacl_from_xattr(&init_user_ns, value, retval, -EIO); + else if (retval != -ENODATA && retval != -ENOSYS) + acl = ERR_PTR(retval); + kfree(value); + + return acl; +} + +static int +__ext4_remove_richacl(handle_t *handle, struct inode *inode) +{ + const int name_index = EXT4_XATTR_INDEX_RICHACL; + int retval; + + retval = ext4_xattr_set_handle(handle, inode, name_index, "", + NULL, 0, 0); + if (!retval) + set_cached_richacl(inode, NULL); + return retval; +} + +static int +__ext4_set_richacl(handle_t *handle, struct inode *inode, struct richacl *acl) +{ + const int name_index = EXT4_XATTR_INDEX_RICHACL; + umode_t mode = inode->i_mode; + int retval, size; + void *value; + + if (richacl_equiv_mode(acl, &mode) == 0) { + inode->i_ctime = ext4_current_time(inode); + inode->i_mode = mode; + ext4_mark_inode_dirty(handle, inode); + return __ext4_remove_richacl(handle, inode); + } + + mode &= ~S_IRWXUGO; + mode |= richacl_masks_to_mode(acl); + + size = richacl_xattr_size(acl); + value = kmalloc(size, GFP_NOFS); + if (!value) + return -ENOMEM; + richacl_to_xattr(&init_user_ns, acl, value, size); + inode->i_mode = mode; + retval = ext4_xattr_set_handle(handle, inode, name_index, "", + value, size, 0); + kfree(value); + if (retval) + return retval; + + set_cached_richacl(inode, acl); + + return 0; +} + +int +ext4_set_richacl(struct inode *inode, struct richacl *acl) +{ + handle_t *handle; + int retval, retries = 0; + +retry: + handle = ext4_journal_start(inode, EXT4_HT_XATTR, + ext4_jbd2_credits_xattr(inode)); + if (IS_ERR(handle)) + return PTR_ERR(handle); + + if (acl) + retval = __ext4_set_richacl(handle, inode, acl); + else + retval = __ext4_remove_richacl(handle, inode); + + ext4_journal_stop(handle); + if (retval == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) + goto retry; + return retval; +} + +int +ext4_init_richacl(handle_t *handle, struct inode *inode, struct inode *dir) +{ + struct richacl *acl = richacl_create(&inode->i_mode, dir); + int error; + + error = PTR_ERR(acl); + if (!IS_ERR_OR_NULL(acl)) { + error = __ext4_set_richacl(handle, inode, acl); + richacl_put(acl); + } + return error; +} diff --git a/fs/ext4/richacl.h b/fs/ext4/richacl.h new file mode 100644 index 0000000..6fe9a92 --- /dev/null +++ b/fs/ext4/richacl.h @@ -0,0 +1,40 @@ +/* + * Copyright IBM Corporation, 2010 + * Copyright (C) 2015 Red Hat, Inc. + * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifndef __FS_EXT4_RICHACL_H +#define __FS_EXT4_RICHACL_H + +#include <linux/richacl.h> + +#ifdef CONFIG_EXT4_FS_RICHACL + +extern struct richacl *ext4_get_richacl(struct inode *); +extern int ext4_set_richacl(struct inode *, struct richacl *); + +extern int ext4_init_richacl(handle_t *, struct inode *, struct inode *); + +#else /* CONFIG_EXT4_FS_RICHACL */ + +#define ext4_get_richacl NULL +#define ext4_set_richacl NULL + +static inline int +ext4_init_richacl(handle_t *handle, struct inode *inode, struct inode *dir) +{ + return 0; +} + +#endif /* CONFIG_EXT4_FS_RICHACL */ +#endif /* __FS_EXT4_RICHACL_H */ diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e79bd32..e5ca483 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -55,6 +55,7 @@ #include <linux/slab.h> #include <linux/mbcache.h> #include <linux/quotaops.h> +#include <linux/richacl_xattr.h> #include "ext4_jbd2.h" #include "ext4.h" #include "xattr.h" @@ -97,6 +98,9 @@ static const struct xattr_handler *ext4_xattr_handler_map[] = { #ifdef CONFIG_EXT4_FS_SECURITY [EXT4_XATTR_INDEX_SECURITY] = &ext4_xattr_security_handler, #endif +#ifdef CONFIG_EXT4_FS_RICHACL + [EXT4_XATTR_INDEX_RICHACL] = &richacl_xattr_handler, +#endif }; const struct xattr_handler *ext4_xattr_handlers[] = { @@ -109,6 +113,9 @@ const struct xattr_handler *ext4_xattr_handlers[] = { #ifdef CONFIG_EXT4_FS_SECURITY &ext4_xattr_security_handler, #endif +#ifdef CONFIG_EXT4_FS_RICHACL + &richacl_xattr_handler, +#endif NULL }; diff --git a/include/linux/acl.h b/include/linux/acl.h new file mode 100644 index 0000000..3c3b5ce --- /dev/null +++ b/include/linux/acl.h @@ -0,0 +1,15 @@ +#ifndef __LINUX_ACL_H +#define __LINUX_ACL_H + +#include <linux/posix_acl.h> +#include <linux/richacl.h> + +static inline int +acl_chmod(struct inode *inode) +{ + if (IS_RICHACL(inode)) + return richacl_chmod(inode, inode->i_mode); + return posix_acl_chmod(inode, inode->i_mode); +} + +#endif -- 2.5.5 From agruenba@redhat.com Thu Jun 30 08:50:00 2016 Return-Path: <agruenba@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 05CF17D12 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:50:00 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 72124AC007 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:59 -0700 (PDT) X-ASG-Debug-ID: 1467294597-04cb6c063c2c47b0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id R9iPz8EH9ttyoDRX (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 06:49:58 -0700 (PDT) X-Barracuda-Envelope-From: agruenba@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5A94115554; Thu, 30 Jun 2016 13:49:57 +0000 (UTC) Received: from nux.redhat.com (vpn1-5-124.ams2.redhat.com [10.36.5.124]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UDlDsx005273; Thu, 30 Jun 2016 09:49:50 -0400 From: Andreas Gruenbacher <agruenba@redhat.com> To: Alexander Viro <viro@zeniv.linux.org.uk> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>, Christoph Hellwig <hch@infradead.org>, "Theodore Ts'o" <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org, Andreas Gruenbacher <agruenba@redhat.com> Subject: [PATCH v23 22/22] ext4: Add richacl feature flag Date: Thu, 30 Jun 2016 15:47:13 +0200 X-ASG-Orig-Subj: [PATCH v23 22/22] ext4: Add richacl feature flag Message-Id: <1467294433-3222-23-git-send-email-agruenba@redhat.com> In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.29]); Thu, 30 Jun 2016 13:49:57 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467294597 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5592 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> This feature flag selects richacl instead of POSIX ACL support on the filesystem. When this feature is off, the "acl" and "noacl" mount options control whether POSIX ACLs are enabled. When it is on, richacls are automatically enabled and using the "noacl" mount option leads to an error. Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Andreas Dilger <adilger@dilger.ca> --- fs/ext4/ext4.h | 6 ++++-- fs/ext4/super.c | 49 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 44 insertions(+), 11 deletions(-) diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index b84aa1c..ff48f07 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1126,7 +1126,7 @@ struct ext4_inode_info { #define EXT4_MOUNT_UPDATE_JOURNAL 0x01000 /* Update the journal format */ #define EXT4_MOUNT_NO_UID32 0x02000 /* Disable 32-bit UIDs */ #define EXT4_MOUNT_XATTR_USER 0x04000 /* Extended user attributes */ -#define EXT4_MOUNT_POSIX_ACL 0x08000 /* POSIX Access Control Lists */ +#define EXT4_MOUNT_ACL 0x08000 /* Access Control Lists */ #define EXT4_MOUNT_NO_AUTO_DA_ALLOC 0x10000 /* No auto delalloc mapping */ #define EXT4_MOUNT_BARRIER 0x20000 /* Use block barriers */ #define EXT4_MOUNT_QUOTA 0x80000 /* Some quota option set */ @@ -1707,6 +1707,7 @@ static inline int ext4_encrypted_inode(struct inode *inode) #define EXT4_FEATURE_INCOMPAT_LARGEDIR 0x4000 /* >2GB or 3-lvl htree */ #define EXT4_FEATURE_INCOMPAT_INLINE_DATA 0x8000 /* data in inode */ #define EXT4_FEATURE_INCOMPAT_ENCRYPT 0x10000 +#define EXT4_FEATURE_INCOMPAT_RICHACL 0x20000 #define EXT4_FEATURE_COMPAT_FUNCS(name, flagname) \ static inline bool ext4_has_feature_##name(struct super_block *sb) \ @@ -1821,7 +1822,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT) EXT4_FEATURE_INCOMPAT_MMP | \ EXT4_FEATURE_INCOMPAT_INLINE_DATA | \ EXT4_FEATURE_INCOMPAT_ENCRYPT | \ - EXT4_FEATURE_INCOMPAT_CSUM_SEED) + EXT4_FEATURE_INCOMPAT_CSUM_SEED | \ + EXT4_FEATURE_INCOMPAT_RICHACL) #define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 3822a5a..122410f 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1306,6 +1306,28 @@ static ext4_fsblk_t get_sb_block(void **data) return sb_block; } +static int enable_acl(struct super_block *sb) +{ + sb->s_flags &= ~(MS_POSIXACL | MS_RICHACL); + if (test_opt(sb, ACL)) { + if (EXT4_HAS_INCOMPAT_FEATURE(sb, + EXT4_FEATURE_INCOMPAT_RICHACL)) { +#ifdef CONFIG_EXT4_FS_RICHACL + sb->s_flags |= MS_RICHACL; +#else + return -EOPNOTSUPP; +#endif + } else { +#ifdef CONFIG_EXT4_FS_POSIX_ACL + sb->s_flags |= MS_POSIXACL; +#else + return -EOPNOTSUPP; +#endif + } + } + return 0; +} + #define DEFAULT_JOURNAL_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3)) static char deprecated_msg[] = "Mount option \"%s\" will be removed by %s\n" "Contact linux-ext4@vger.kernel.org if you think we should keep it.\n"; @@ -1452,9 +1474,9 @@ static const struct mount_opts { MOPT_NO_EXT2 | MOPT_DATAJ}, {Opt_user_xattr, EXT4_MOUNT_XATTR_USER, MOPT_SET}, {Opt_nouser_xattr, EXT4_MOUNT_XATTR_USER, MOPT_CLEAR}, -#ifdef CONFIG_EXT4_FS_POSIX_ACL - {Opt_acl, EXT4_MOUNT_POSIX_ACL, MOPT_SET}, - {Opt_noacl, EXT4_MOUNT_POSIX_ACL, MOPT_CLEAR}, +#if defined(CONFIG_EXT4_FS_POSIX_ACL) || defined(CONFIG_EXT4_FS_RICHACL) + {Opt_acl, EXT4_MOUNT_ACL, MOPT_SET}, + {Opt_noacl, EXT4_MOUNT_ACL, MOPT_CLEAR}, #else {Opt_acl, 0, MOPT_NOSUPPORT}, {Opt_noacl, 0, MOPT_NOSUPPORT}, @@ -1502,6 +1524,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token, #endif switch (token) { case Opt_noacl: +#ifdef CONFIG_EXT4_FS_RICHACL + if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RICHACL)) { + ext4_msg(sb, KERN_ERR, "Mount option \"%s\" incompatible " + "with richacl feature", opt); + return -1; + } +#endif case Opt_nouser_xattr: ext4_msg(sb, KERN_WARNING, deprecated_msg, opt, "3.5"); break; @@ -3274,8 +3303,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) set_opt(sb, NO_UID32); /* xattr user namespace & acls are now defaulted on */ set_opt(sb, XATTR_USER); -#ifdef CONFIG_EXT4_FS_POSIX_ACL - set_opt(sb, POSIX_ACL); +#if defined(CONFIG_EXT4_FS_POSIX_ACL) || defined(CONFIG_EXT4_FS_RICHACL) + set_opt(sb, ACL); #endif /* don't forget to enable journal_csum when metadata_csum is enabled. */ if (ext4_has_metadata_csum(sb)) @@ -3358,8 +3387,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) sb->s_iflags |= SB_I_CGROUPWB; } - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | - (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); + err = enable_acl(sb); + if (err) + goto failed_mount; if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV && (ext4_has_compat_features(sb) || @@ -4673,8 +4703,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) ext4_abort(sb, "Abort forced by user"); - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | - (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); + err = enable_acl(sb); + if (err) + goto restore_opts; es = sbi->s_es; -- 2.5.5 From Volker.Lendecke@SerNet.DE Thu Jun 30 09:11:47 2016 Return-Path: <Volker.Lendecke@SerNet.DE> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 3213B7CD2 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 09:11:47 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay1.corp.sgi.com (Postfix) with ESMTP id E7DEF8F8065 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 07:11:43 -0700 (PDT) X-ASG-Debug-ID: 1467295898-04bdf074b42396b0001-NocioJ Received: from mail.SerNet.de (mail.SerNet.de [193.175.80.2]) by cuda.sgi.com with ESMTP id qDsNvomEkCOQyrz5 (version=TLSv1.2 cipher=DHE-RSA-AES128-SHA bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 07:11:39 -0700 (PDT) X-Barracuda-Envelope-From: Volker.Lendecke@SerNet.DE X-Barracuda-Effective-Source-IP: mail.SerNet.de[193.175.80.2] X-Barracuda-Apparent-Source-IP: 193.175.80.2 Received: from intern.SerNet.DE by mail.SerNet.DE with esmtps (Exim 4.80 #2) id 1bIcgn-0004Pp-6r; Thu, 30 Jun 2016 16:11:33 +0200 Received: by intern.sernet.de id 1bIcgn-0005mW-2s; Thu, 30 Jun 2016 16:11:33 +0200 Date: Thu, 30 Jun 2016 16:11:28 +0200 From: Volker Lendecke <Volker.Lendecke@SerNet.DE> To: Andreas Gruenbacher <agruenba@redhat.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk>, Christoph Hellwig <hch@infradead.org>, Theodore Ts'o <tytso@mit.edu>, Andreas Dilger <adilger.kernel@dilger.ca>, "J. Bruce Fields" <bfields@fieldses.org>, Jeff Layton <jlayton@poochiereds.net>, Trond Myklebust <trond.myklebust@primarydata.com>, Anna Schumaker <anna.schumaker@netapp.com>, Dave Chinner <david@fromorbit.com>, linux-ext4@vger.kernel.org, xfs@oss.sgi.com, linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-cifs@vger.kernel.org, linux-api@vger.kernel.org Subject: Re: [PATCH v23 00/22] Richacls (Core and Ext4) Message-ID: <20160630141128.GB17201@sernet.de> X-ASG-Orig-Subj: Re: [PATCH v23 00/22] Richacls (Core and Ext4) Reply-To: Volker.Lendecke@SerNet.DE References: <1467294433-3222-1-git-send-email-agruenba@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1467294433-3222-1-git-send-email-agruenba@redhat.com> User-Agent: Mutt/1.5.23 (2014-03-12) X-Barracuda-Connect: mail.SerNet.de[193.175.80.2] X-Barracuda-Start-Time: 1467295899 X-Barracuda-Encrypted: DHE-RSA-AES128-SHA X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 325 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30896 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 30, 2016 at 03:46:51PM +0200, Andreas Gruenbacher wrote: > What more needs to be done to get this initial set of patches merged? Bind Christoph to some tree in the Harz hills, so that he can't reject them? :-) Christoph, is there anything realistic that can be done to get over your concerns? Volker From Martinezant2141@live.com Thu Jun 30 10:35:20 2016 Return-Path: <Martinezant2141@live.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_MESSAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 5A3827CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:35:20 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 2B6648F80B5 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:35:20 -0700 (PDT) X-ASG-Debug-ID: 1467300915-04cbb027383bdc50001-NocioJ Received: from COL004-OMC4S6.hotmail.com (col004-omc4s6.hotmail.com [65.55.34.208]) by cuda.sgi.com with ESMTP id 5ljze55H3kTwoClM (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 08:35:16 -0700 (PDT) X-Barracuda-Envelope-From: Martinezant2141@live.com X-Barracuda-Effective-Source-IP: col004-omc4s6.hotmail.com[65.55.34.208] X-Barracuda-Apparent-Source-IP: 65.55.34.208 Received: from NAM03-CO1-obe.outbound.protection.outlook.com ([65.55.34.199]) by COL004-OMC4S6.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Thu, 30 Jun 2016 08:35:15 -0700 Received: from BY2NAM03FT042.eop-NAM03.prod.protection.outlook.com (10.152.84.54) by BY2NAM03HT199.eop-NAM03.prod.protection.outlook.com (10.152.85.217) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.534.7; Thu, 30 Jun 2016 15:35:14 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com (10.152.84.54) by BY2NAM03FT042.mail.protection.outlook.com (10.152.85.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.534.7 via Frontend Transport; Thu, 30 Jun 2016 15:35:14 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) by SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) with mapi id 15.01.0523.024; Thu, 30 Jun 2016 15:35:14 +0000 From: Anthony l <Martinezant2141@live.com> To: "xfs@oss.sgi.com" <xfs@oss.sgi.com> Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Topic: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Index: AQHR0jAXIVEyd//VeEGYMdUD0l4C3qACJFOX Date: Thu, 30 Jun 2016 15:35:14 +0000 Message-ID: <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com> References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> In-Reply-To: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=softfail (sender IP is 10.152.84.54) smtp.mailfrom=live.com; oss.sgi.com; dkim=none (message not signed) header.d=none;oss.sgi.com; dmarc=none action=none header.from=live.com; received-spf: SoftFail (protection.outlook.com: domain of transitioning live.com discourages use of 10.152.84.54 as permitted sender) x-tmn: [mr7G/lao3OBuOSPiZY6+Do/v0n/1nmz2] x-eopattributedmessage: 0 x-forefront-antispam-report: CIP:10.152.84.54;IPV:NLI;CTRY:;EFV:NLI;SFV:NSPM;SFS:(10019020)(98900003);DIR:OUT;SFP:1102;SCL:1;SRVR:BY2NAM03HT199;H:SN1PR05MB2317.namprd05.prod.outlook.com;FPR:;SPF:None;LANG:en; x-ms-office365-filtering-correlation-id: 529b41d4-d4b0-47c0-4233-08d3a0fc2181 x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:(1601124038)(5061506196)(5061507196)(1603103041)(1601125047);SRVR:BY2NAM03HT199; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(432015012)(82015046);SRVR:BY2NAM03HT199;BCL:0;PCL:0;RULEID:;SRVR:BY2NAM03HT199; x-forefront-prvs: 0989A7979C Content-Type: multipart/alternative; boundary="_000_SN1PR05MB23175D5BF190CCC3F22E2EB0CC240SN1PR05MB2317namp_" MIME-Version: 1.0 X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-originalarrivaltime: 30 Jun 2016 15:35:14.3223 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: BY2NAM03HT199 X-OriginalArrivalTime: 30 Jun 2016 15:35:15.0740 (UTC) FILETIME=[FFDB65C0:01D1D2E4] X-Barracuda-Connect: col004-omc4s6.hotmail.com[65.55.34.208] X-Barracuda-Start-Time: 1467300916 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1557 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30898 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 HTML_MESSAGE BODY: HTML included in message --_000_SN1PR05MB23175D5BF190CCC3F22E2EB0CC240SN1PR05MB2317namp_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Thanks for replying. I made a Paste bin of the output I'm getting. This tim= e I used the -K option which is to force use compatibility with older versi= ons of xfs I think. http://pastebin.com/vrL6iiW2 There is my full output to what I am getting. Not actually getting an error= code I just don't understand why this wouldn't work. Also If I chose skip = instead of restore ill get to some different dumps. But same thing happens = if I choose restore on those too. Thanks for the reply Dave and Eric --_000_SN1PR05MB23175D5BF190CCC3F22E2EB0CC240SN1PR05MB2317namp_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-8859-= 1"> <style type=3D"text/css" style=3D"display:none;"><!-- P {margin-top:0;margi= n-bottom:0;} --></style> </head> <body dir=3D"ltr"> <div id=3D"divtagdefaultwrapper" style=3D"font-size:12pt;color:#000000;back= ground-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;"> <p>Thanks for replying. I made a Paste bin of the output I'm getting. This = time I used the -K option which is to force use compatibility with older ve= rsions of xfs I think. <br> </p> <p><a id=3D"LPlnk675788" href=3D"http://pastebin.com/vrL6iiW2" class=3D"OWA= AutoLink">http://pastebin.com/vrL6iiW2</a></p> <p><br> </p> <p><br> </p> <p>There is my full output to what I am getting. Not actually getting an er= ror code I just don't understand why this wouldn't work. Also If I chose sk= ip instead of restore ill get to some different dumps. But same thing happe= ns if I choose restore on those too. <br> </p> <p>Thanks for the reply Dave and Eric <br> <br> </p> </div> </body> </html> --_000_SN1PR05MB23175D5BF190CCC3F22E2EB0CC240SN1PR05MB2317namp_-- From sandeen@sandeen.net Thu Jun 30 11:11:22 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 3C10A7CA4 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 11:11:22 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id C543BAC00A for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 09:11:18 -0700 (PDT) X-ASG-Debug-ID: 1467303075-04bdf074b423f8f0001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id 14oTVH6FuhgLaDq9 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 09:11:15 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id 16491142F for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 11:11:15 -0500 (CDT) Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <4d9d00ef-82d5-a658-e88c-ba75fb7a6023@sandeen.net> Date: Thu, 30 Jun 2016 11:11:14 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1467303075 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 729 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30899 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/30/16 10:35 AM, Anthony l wrote: > Thanks for replying. I made a Paste bin of the output I'm getting. > This time I used the -K option which is to force use compatibility > with older versions of xfs I think. > > http://pastebin.com/vrL6iiW2 > > > > There is my full output to what I am getting. Not actually getting an > error code I just don't understand why this wouldn't work. Also If I > chose skip instead of restore ill get to some different dumps. But > same thing happens if I choose restore on those too. You might also look at http://oss.sgi.com/archives/xfs/2005-01/msg00418.html and try another run with maximum verbosity as that user did. Is this a multi-tape dump? -Eric From Martinezant2141@live.com Thu Jun 30 11:59:11 2016 Return-Path: <Martinezant2141@live.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_MESSAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 34E207CA1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 11:59:11 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 07E738F8084 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 09:59:07 -0700 (PDT) X-ASG-Debug-ID: 1467305944-04cbb027353c2790001-NocioJ Received: from SNT004-OMC4S14.hotmail.com (snt004-omc4s14.hotmail.com [65.55.90.217]) by cuda.sgi.com with ESMTP id IdKtTBfAELXEX06v (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 09:59:04 -0700 (PDT) X-Barracuda-Envelope-From: Martinezant2141@live.com X-Barracuda-Effective-Source-IP: snt004-omc4s14.hotmail.com[65.55.90.217] X-Barracuda-Apparent-Source-IP: 65.55.90.217 Received: from NAM01-BY2-obe.outbound.protection.outlook.com ([65.55.90.201]) by SNT004-OMC4S14.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Thu, 30 Jun 2016 09:59:04 -0700 Received: from BN3NAM01FT035.eop-nam01.prod.protection.outlook.com (10.152.66.54) by BN3NAM01HT035.eop-nam01.prod.protection.outlook.com (10.152.66.235) with Microsoft SMTP Server (TLS) id 15.1.523.9; Thu, 30 Jun 2016 16:59:02 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com (10.152.66.52) by BN3NAM01FT035.mail.protection.outlook.com (10.152.67.159) with Microsoft SMTP Server (TLS) id 15.1.523.9 via Frontend Transport; Thu, 30 Jun 2016 16:59:02 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) by SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) with mapi id 15.01.0523.024; Thu, 30 Jun 2016 16:59:01 +0000 From: Anthony l <Martinezant2141@live.com> To: Eric Sandeen <sandeen@sandeen.net> CC: "xfs@oss.sgi.com" <xfs@oss.sgi.com> Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Topic: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Index: AQHR0uoTpTlXrUi8902XIsNl1Vl39qACM7x6 Date: Thu, 30 Jun 2016 16:59:01 +0000 Message-ID: <SN1PR05MB2317E464B2CFB5A06CC4B66BCC240@SN1PR05MB2317.namprd05.prod.outlook.com> References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com>,<4d9d00ef-82d5-a658-e88c-ba75fb7a6023@sandeen.net> In-Reply-To: <4d9d00ef-82d5-a658-e88c-ba75fb7a6023@sandeen.net> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=softfail (sender IP is 25.152.66.52) smtp.mailfrom=live.com; oss.sgi.com; dkim=none (message not signed) header.d=none;oss.sgi.com; dmarc=none action=none header.from=live.com; received-spf: SoftFail (protection.outlook.com: domain of transitioning live.com discourages use of 25.152.66.52 as permitted sender) x-tmn: [o8bwz3vlvTTz8wGa9VPiGcegH/5jkt3y] x-eopattributedmessage: 0 x-forefront-antispam-report: EFV:NLI;SFV:NSPM;SFS:(10019020)(98900003);DIR:OUT;SFP:1102;SCL:1;SRVR:BN3NAM01HT035;H:SN1PR05MB2317.namprd05.prod.outlook.com;FPR:;SPF:None;CAT:NONE;LANG:en;CAT:NONE; x-ms-office365-filtering-correlation-id: 389eeec5-da80-4581-d0f1-08d3a107d62f x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:(1601124038)(5061506196)(5061507196)(1603103041)(1601125047);SRVR:BN3NAM01HT035; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(432015012)(82015046);SRVR:BN3NAM01HT035;BCL:0;PCL:0;RULEID:;SRVR:BN3NAM01HT035; x-forefront-prvs: 0989A7979C Content-Type: multipart/alternative; boundary="_000_SN1PR05MB2317E464B2CFB5A06CC4B66BCC240SN1PR05MB2317namp_" MIME-Version: 1.0 X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-originalarrivaltime: 30 Jun 2016 16:59:01.8211 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN3NAM01HT035 X-OriginalArrivalTime: 30 Jun 2016 16:59:04.0583 (UTC) FILETIME=[B547F170:01D1D2F0] X-Barracuda-Connect: snt004-omc4s14.hotmail.com[65.55.90.217] X-Barracuda-Start-Time: 1467305944 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3154 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30900 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message --_000_SN1PR05MB2317E464B2CFB5A06CC4B66BCC240SN1PR05MB2317namp_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable I don't think this is a multi tape dump. But then again i don't know for su= re. I recently got a job and this is my first 'project'. I have about 10 ta= pes each are labeled a month and a year, so I don't think they are multi ta= pe because they span like 3 years 2004-2007 . Although for the current tape= I am working on right now if I select 1 skip, I'll get to another back up = labeled "incremental backup 1" or something similar. Using the verbosity ou= tput here is what I got. (also using interactive restore). I went ahead and= specified byte size 4096. Through earlier test using the dd command I dete= rmined that was the correct size. Ill post one without byte size specified = too. I just saw it in that post and thought it might help. Here is the output with verbosity. http://pastebin.com/Nd6BqNc5 The out is the same with or without -b 4096. http://pastebin.com/0dxbCvyc (no -b) -Anthony <http://oss.sgi.com/mailman/listinfo/xfs> --_000_SN1PR05MB2317E464B2CFB5A06CC4B66BCC240SN1PR05MB2317namp_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-8859-= 1"> <style type=3D"text/css" style=3D"display:none;"><!-- P {margin-top:0;margi= n-bottom:0;} --></style> </head> <body dir=3D"ltr"> <div id=3D"divtagdefaultwrapper" style=3D"font-size:12pt;color:#000000;back= ground-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;"> <p><span style=3D"font-size: 8pt;"><span style=3D"font-size: 10pt;"></span>= <span style=3D"font-size: 10pt;">I don't think this is a multi tape dump. B= ut then again i don't know for sure. I recently got a job and this is my fi= rst 'project'. I have about 10 tapes each are labeled a month and a year, so I don't think they are multi tape becau= se they span like 3 years 2004-2007 . Although for the current tape I am wo= rking on right now if I select 1 skip, I'll get to another back up labeled = "incremental backup 1" or something similar. Using the verbosity output here is what I got. (also using intera= ctive restore). I went ahead and specified byte size 4096. Through earlier = test using the dd command I determined that was the correct size. Ill post = one without byte size specified too. I just saw it in that post and thought it might help.<br> </span></span></p> <p><span style=3D"font-size: 8pt;"><span style=3D"font-size: 10pt;"></span>= </span><font size=3D"2"><span style=3D"font-size:10pt;"></span></font>Here = is the output with verbosity. <br> </p> <p><a id=3D"LPlnk552761" href=3D"http://pastebin.com/Nd6BqNc5" class=3D"OWA= AutoLink">http://pastebin.com/Nd6BqNc5</a></p> <p><span style=3D"font-size: 10pt;">The out is the same with or without -b = 4096. <br> </span></p> <p><span style=3D"font-size: 10pt;"></span><a id=3D"LPlnk828460" href=3D"ht= tp://pastebin.com/0dxbCvyc" class=3D"OWAAutoLink">http://pastebin.com/0dxbC= vyc</a> (no -b)</p> <p><br> </p> <p>-Anthony<br> </p> <font size=3D"2"><span style=3D"font-size:10pt;"> <div class=3D"PlainText"><a href=3D"http://oss.sgi.com/mailman/listinfo/xfs= "></a></div> </span></font><font size=3D"2"><span style=3D"font-size:10pt;"> <div class=3D"PlainText"></div> </span></font> <div style=3D"color: rgb(0, 0, 0);"><font size=3D"2"><span style=3D"font-si= ze:10pt;"></span></font></div> </div> </body> </html> --_000_SN1PR05MB2317E464B2CFB5A06CC4B66BCC240SN1PR05MB2317namp_-- From sandeen@sandeen.net Thu Jun 30 12:04:13 2016 Return-Path: <sandeen@sandeen.net> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id D2ABC7CA2 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:04:13 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 96B653040AA for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:04:10 -0700 (PDT) X-ASG-Debug-ID: 1467306247-04cbb027363c3220001-NocioJ Received: from sandeen.net (sandeen.net [63.231.237.45]) by cuda.sgi.com with ESMTP id OBX6Pb2O11HJlUD7 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:04:07 -0700 (PDT) X-Barracuda-Envelope-From: sandeen@sandeen.net X-Barracuda-Effective-Source-IP: sandeen.net[63.231.237.45] X-Barracuda-Apparent-Source-IP: 63.231.237.45 Received: from [10.0.0.4] (liberator [10.0.0.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by sandeen.net (Postfix) with ESMTPSA id B8EF5142F for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:04:07 -0500 (CDT) Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) To: xfs@oss.sgi.com X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com> <4d9d00ef-82d5-a658-e88c-ba75fb7a6023@sandeen.net> <SN1PR05MB2317E464B2CFB5A06CC4B66BCC240@SN1PR05MB2317.namprd05.prod.outlook.com> From: Eric Sandeen <sandeen@sandeen.net> Message-ID: <dc20d8ae-d57f-53f1-72b8-d623529c695b@sandeen.net> Date: Thu, 30 Jun 2016 12:04:07 -0500 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:45.0) Gecko/20100101 Thunderbird/45.1.1 MIME-Version: 1.0 In-Reply-To: <SN1PR05MB2317E464B2CFB5A06CC4B66BCC240@SN1PR05MB2317.namprd05.prod.outlook.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 8bit X-Barracuda-Connect: sandeen.net[63.231.237.45] X-Barracuda-Start-Time: 1467306247 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 1599 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests= X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30900 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- On 6/30/16 11:59 AM, Anthony l wrote: > I don't think this is a multi tape dump. But then again i don't know for sure. I recently got a job and this is my first 'project'. I have about 10 tapes each are labeled a month and a year, so I don't think they are multi tape because they span like 3 years 2004-2007 . Although for the current tape I am working on right now if I select 1 skip, I'll get to another back up labeled "incremental backup 1" or something similar. Using the verbosity output here is what I got. (also using interactive restore). I went ahead and specified byte size 4096. Through earlier test using the dd command I determined that was the correct size. Ill post one without byte size specified too. I just saw it in that post and thought it might help. > > Here is the output with verbosity. > > http://pastebin.com/Nd6BqNc5 > > The out is the same with or without -b 4096. > > http://pastebin.com/0dxbCvyc (no -b) interactively restore from this dump? 1: skip 2: interactively restore (default) ->2 ++++================++++ missing some stuff------ ^^^ is that your comment, or actual output? Looks like it eventually encountered a short read: xfsrestore: drive op: read: wanted 131072 (0x20000) xfsrestore: tape op: reading 245760 bytes xfsrestore: tape op read of 245760 bytes short: nread == 4096 xfsrestore: tape op: get status xfsrestore: tape status = wprot onl xfsrestore: short read record 1 (nread == 4096) xfsrestore: drive op read returning error rval=1 in dmesg, is there any sort of IO error from the tape? -Eric From hch@lst.de Thu Jun 30 12:22:43 2016 Return-Path: <hch@lst.de> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 741897CA6 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:22:43 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 3540730408A for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:22:43 -0700 (PDT) X-ASG-Debug-ID: 1467307359-04cbb027383c50f0001-NocioJ Received: from newverein.lst.de (verein.lst.de [213.95.11.211]) by cuda.sgi.com with ESMTP id bA63Pp87D1sGI7P8 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:22:41 -0700 (PDT) X-Barracuda-Envelope-From: hch@lst.de X-Barracuda-Effective-Source-IP: verein.lst.de[213.95.11.211] X-Barracuda-Apparent-Source-IP: 213.95.11.211 Received: by newverein.lst.de (Postfix, from userid 2407) id 2A4C268D8C; Thu, 30 Jun 2016 19:22:39 +0200 (CEST) Date: Thu, 30 Jun 2016 19:22:39 +0200 From: Christoph Hellwig <hch@lst.de> To: Dave Chinner <david@fromorbit.com> Cc: xfs@oss.sgi.com, rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V5 Message-ID: <20160630172239.GA23082@lst.de> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V5 References: <1464792297-13185-1-git-send-email-hch@lst.de> <20160628002649.GI12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160628002649.GI12670@dastard> User-Agent: Mutt/1.5.17 (2007-11-01) X-Barracuda-Connect: verein.lst.de[213.95.11.211] X-Barracuda-Start-Time: 1467307360 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2598 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30901 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Tue, Jun 28, 2016 at 10:26:49AM +1000, Dave Chinner wrote: > Christoph, it look slike there's an ENOSPC+ENOMEM behavioural regression here. > generic/224 on my 1p/1GB RAM VM using a 1k lock size filesystem has > significantly different behaviour once ENOSPC is hit withi this patchset. > > It ends up with an endless stream of errors like this: I've spent some time trying to reproduce this. I'm actually getting the OOM killer almost reproducible for for-next without the iomap patches as well when just using 1GB of mem. 1400 MB is the minimum I can reproducibly finish the test with either code base. But with the 1400 MB setup I see a few interesting things. Even with the baseline, no-iomap case I see a few errors in the log: [ 70.407465] Filesystem "vdc": reserve blocks depleted! Consider increasing reserve pool size. [ 70.195645] XFS (vdc): page discard on page ffff88005682a988, inode 0xd3, offset 761856. [ 70.408079] Buffer I/O error on dev vdc, logical block 1048513, lost async page write [ 70.408598] Buffer I/O error on dev vdc, logical block 1048514, lost async page write 27s With iomap I also see the spew of page discard errors your see, but while I see a lot of them, the rest still finishes after a reasonable time, just a few seconds more than the pre-iomap baseline. I also see the reserve block depleted message in this case. Digging into the reserve block depleted message - it seems we have too many parallel iomap_allocate transactions going on. I suspect this might be because the writeback code will not finish a writeback context if we have multiple blocks inside a page, which can happen easily for this 1k ENOSPC setup. I've not had time to fully check if this is what really happens, but I did a quick hack (see below) to only allocate 1k at a time in iomap_begin, and with that generic/224 finishes without the warning spew. Of course this isn't a real fix, and I need to fully understand what's going on in writeback due to different allocation / dirtying patterns from the iomap change. diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index 620fc91..d9afba2 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -1018,7 +1018,7 @@ xfs_file_iomap_begin( * Note that the values needs to be less than 32-bits wide until * the lower level functions are updated. */ - length = min_t(loff_t, length, 1024 * PAGE_SIZE); + length = min_t(loff_t, length, 1024); if (xfs_get_extsz_hint(ip)) { /* * xfs_iomap_write_direct() expects the shared lock. It From bfoster@redhat.com Thu Jun 30 12:32:46 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id AE8DB7CA1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:32:46 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id 7188D8F8065 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:32:43 -0700 (PDT) X-ASG-Debug-ID: 1467307961-04cbb027373c59f0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id B26BIHGSqiOzYuBO (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:32:42 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 505A03F73C; Thu, 30 Jun 2016 17:32:41 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UHWeNE024038; Thu, 30 Jun 2016 13:32:40 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 70F831200E8; Thu, 30 Jun 2016 13:32:39 -0400 (EDT) Date: Thu, 30 Jun 2016 13:32:39 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Dave Chinner <dchinner@redhat.com>, xfs@oss.sgi.com Subject: Re: [PATCH 023/119] xfs: introduce rmap btree definitions Message-ID: <20160630173238.GA27303@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 023/119] xfs: introduce rmap btree definitions References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612641935.12839.2545862100454514832.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612641935.12839.2545862100454514832.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 30 Jun 2016 17:32:41 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467307961 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 7078 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:20:19PM -0700, Darrick J. Wong wrote: > From: Dave Chinner <dchinner@redhat.com> > > Add new per-ag rmap btree definitions to the per-ag structures. The > rmap btree will sit in the empty slots on disk after the free space > btrees, and hence form a part of the array of space management > btrees. This requires the definition of the btree to be contiguous > with the free space btrees. > > Signed-off-by: Dave Chinner <dchinner@redhat.com> > Signed-off-by: Dave Chinner <david@fromorbit.com> > --- Reviewed-by: Brian Foster <bfoster@redhat.com> > fs/xfs/libxfs/xfs_alloc.c | 6 ++++++ > fs/xfs/libxfs/xfs_btree.c | 4 ++-- > fs/xfs/libxfs/xfs_btree.h | 3 +++ > fs/xfs/libxfs/xfs_format.h | 22 +++++++++++++++++----- > fs/xfs/libxfs/xfs_types.h | 4 ++-- > 5 files changed, 30 insertions(+), 9 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c > index 56c8690..b61e9c6 100644 > --- a/fs/xfs/libxfs/xfs_alloc.c > +++ b/fs/xfs/libxfs/xfs_alloc.c > @@ -2272,6 +2272,10 @@ xfs_agf_verify( > be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]) > XFS_BTREE_MAXLEVELS) > return false; > > + if (xfs_sb_version_hasrmapbt(&mp->m_sb) && > + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]) > XFS_BTREE_MAXLEVELS) > + return false; > + > /* > * during growfs operations, the perag is not fully initialised, > * so we can't use it for any useful checking. growfs ensures we can't > @@ -2403,6 +2407,8 @@ xfs_alloc_read_agf( > be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNOi]); > pag->pagf_levels[XFS_BTNUM_CNTi] = > be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]); > + pag->pagf_levels[XFS_BTNUM_RMAPi] = > + be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAPi]); > spin_lock_init(&pag->pagb_lock); > pag->pagb_count = 0; > #ifdef __KERNEL__ > diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c > index 5b3743a..624b572 100644 > --- a/fs/xfs/libxfs/xfs_btree.c > +++ b/fs/xfs/libxfs/xfs_btree.c > @@ -44,9 +44,9 @@ kmem_zone_t *xfs_btree_cur_zone; > * Btree magic numbers. > */ > static const __uint32_t xfs_magics[2][XFS_BTNUM_MAX] = { > - { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, > + { XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, 0, XFS_BMAP_MAGIC, XFS_IBT_MAGIC, > XFS_FIBT_MAGIC }, > - { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, > + { XFS_ABTB_CRC_MAGIC, XFS_ABTC_CRC_MAGIC, XFS_RMAP_CRC_MAGIC, > XFS_BMAP_CRC_MAGIC, XFS_IBT_CRC_MAGIC, XFS_FIBT_CRC_MAGIC } > }; > #define xfs_btree_magic(cur) \ > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index 7483cac..202fdd3 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -63,6 +63,7 @@ union xfs_btree_rec { > #define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi) > #define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi) > #define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi) > +#define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi) > > /* > * For logging record fields. > @@ -95,6 +96,7 @@ do { \ > case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ > case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ > case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ > + case XFS_BTNUM_RMAP: break; \ > case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ > } \ > } while (0) > @@ -115,6 +117,7 @@ do { \ > __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ > case XFS_BTNUM_FINO: \ > __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ > + case XFS_BTNUM_RMAP: break; \ > case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ > } \ > } while (0) > diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h > index ba528b3..8ca4a3d 100644 > --- a/fs/xfs/libxfs/xfs_format.h > +++ b/fs/xfs/libxfs/xfs_format.h > @@ -455,6 +455,7 @@ xfs_sb_has_compat_feature( > } > > #define XFS_SB_FEAT_RO_COMPAT_FINOBT (1 << 0) /* free inode btree */ > +#define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ > #define XFS_SB_FEAT_RO_COMPAT_ALL \ > (XFS_SB_FEAT_RO_COMPAT_FINOBT) > #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL > @@ -538,6 +539,12 @@ static inline bool xfs_sb_version_hasmetauuid(struct xfs_sb *sbp) > (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_META_UUID); > } > > +static inline bool xfs_sb_version_hasrmapbt(struct xfs_sb *sbp) > +{ > + return (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5) && > + (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_RMAPBT); > +} > + > /* > * end of superblock version macros > */ > @@ -598,10 +605,10 @@ xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino) > #define XFS_AGI_GOOD_VERSION(v) ((v) == XFS_AGI_VERSION) > > /* > - * Btree number 0 is bno, 1 is cnt. This value gives the size of the > + * Btree number 0 is bno, 1 is cnt, 2 is rmap. This value gives the size of the > * arrays below. > */ > -#define XFS_BTNUM_AGF ((int)XFS_BTNUM_CNTi + 1) > +#define XFS_BTNUM_AGF ((int)XFS_BTNUM_RMAPi + 1) > > /* > * The second word of agf_levels in the first a.g. overlaps the EFS > @@ -618,12 +625,10 @@ typedef struct xfs_agf { > __be32 agf_seqno; /* sequence # starting from 0 */ > __be32 agf_length; /* size in blocks of a.g. */ > /* > - * Freespace information > + * Freespace and rmap information > */ > __be32 agf_roots[XFS_BTNUM_AGF]; /* root blocks */ > - __be32 agf_spare0; /* spare field */ > __be32 agf_levels[XFS_BTNUM_AGF]; /* btree levels */ > - __be32 agf_spare1; /* spare field */ > > __be32 agf_flfirst; /* first freelist block's index */ > __be32 agf_fllast; /* last freelist block's index */ > @@ -1307,6 +1312,13 @@ typedef __be32 xfs_inobt_ptr_t; > #define XFS_FIBT_BLOCK(mp) ((xfs_agblock_t)(XFS_IBT_BLOCK(mp) + 1)) > > /* > + * Reverse mapping btree format definitions > + * > + * There is a btree for the reverse map per allocation group > + */ > +#define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ > + > +/* > * The first data block of an AG depends on whether the filesystem was formatted > * with the finobt feature. If so, account for the finobt reserved root btree > * block. > diff --git a/fs/xfs/libxfs/xfs_types.h b/fs/xfs/libxfs/xfs_types.h > index f0d145a..da87796 100644 > --- a/fs/xfs/libxfs/xfs_types.h > +++ b/fs/xfs/libxfs/xfs_types.h > @@ -111,8 +111,8 @@ typedef enum { > } xfs_lookup_t; > > typedef enum { > - XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_BMAPi, XFS_BTNUM_INOi, > - XFS_BTNUM_FINOi, XFS_BTNUM_MAX > + XFS_BTNUM_BNOi, XFS_BTNUM_CNTi, XFS_BTNUM_RMAPi, XFS_BTNUM_BMAPi, > + XFS_BTNUM_INOi, XFS_BTNUM_FINOi, XFS_BTNUM_MAX > } xfs_btnum_t; > > struct xfs_name { > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Thu Jun 30 12:32:49 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 81E187CAF for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:32:49 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay2.corp.sgi.com (Postfix) with ESMTP id 1F12D304048 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:32:49 -0700 (PDT) X-ASG-Debug-ID: 1467307967-04cbb027373c5a00001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id NJejylpbFfEmpZAA (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:32:48 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id A40D2C05FBB0; Thu, 30 Jun 2016 17:32:47 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UHWlac013492; Thu, 30 Jun 2016 13:32:47 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id E153C1200E8; Thu, 30 Jun 2016 13:32:45 -0400 (EDT) Date: Thu, 30 Jun 2016 13:32:45 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Dave Chinner <dchinner@redhat.com>, xfs@oss.sgi.com Subject: Re: [PATCH 024/119] xfs: add rmap btree stats infrastructure Message-ID: <20160630173245.GB27303@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 024/119] xfs: add rmap btree stats infrastructure References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612642642.12839.4422813555398236765.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612642642.12839.4422813555398236765.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 30 Jun 2016 17:32:47 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467307968 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3414 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:20:26PM -0700, Darrick J. Wong wrote: > From: Dave Chinner <dchinner@redhat.com> > > The rmap btree will require the same stats as all the other generic > btrees, so add al the code for that now. all > > Signed-off-by: Dave Chinner <dchinner@redhat.com> > Signed-off-by: Dave Chinner <david@fromorbit.com> > --- Reviewed-by: Brian Foster <bfoster@redhat.com> > fs/xfs/libxfs/xfs_btree.h | 5 +++-- > fs/xfs/xfs_stats.c | 1 + > fs/xfs/xfs_stats.h | 18 +++++++++++++++++- > 3 files changed, 21 insertions(+), 3 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h > index 202fdd3..a29067c 100644 > --- a/fs/xfs/libxfs/xfs_btree.h > +++ b/fs/xfs/libxfs/xfs_btree.h > @@ -96,7 +96,7 @@ do { \ > case XFS_BTNUM_BMAP: __XFS_BTREE_STATS_INC(__mp, bmbt, stat); break; \ > case XFS_BTNUM_INO: __XFS_BTREE_STATS_INC(__mp, ibt, stat); break; \ > case XFS_BTNUM_FINO: __XFS_BTREE_STATS_INC(__mp, fibt, stat); break; \ > - case XFS_BTNUM_RMAP: break; \ > + case XFS_BTNUM_RMAP: __XFS_BTREE_STATS_INC(__mp, rmap, stat); break; \ > case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ > } \ > } while (0) > @@ -117,7 +117,8 @@ do { \ > __XFS_BTREE_STATS_ADD(__mp, ibt, stat, val); break; \ > case XFS_BTNUM_FINO: \ > __XFS_BTREE_STATS_ADD(__mp, fibt, stat, val); break; \ > - case XFS_BTNUM_RMAP: break; \ > + case XFS_BTNUM_RMAP: \ > + __XFS_BTREE_STATS_ADD(__mp, rmap, stat, val); break; \ > case XFS_BTNUM_MAX: ASSERT(0); __mp = __mp /* fucking gcc */ ; break; \ > } \ > } while (0) > diff --git a/fs/xfs/xfs_stats.c b/fs/xfs/xfs_stats.c > index 8686df6..f04f547 100644 > --- a/fs/xfs/xfs_stats.c > +++ b/fs/xfs/xfs_stats.c > @@ -61,6 +61,7 @@ int xfs_stats_format(struct xfsstats __percpu *stats, char *buf) > { "bmbt2", XFSSTAT_END_BMBT_V2 }, > { "ibt2", XFSSTAT_END_IBT_V2 }, > { "fibt2", XFSSTAT_END_FIBT_V2 }, > + { "rmapbt", XFSSTAT_END_RMAP_V2 }, > /* we print both series of quota information together */ > { "qm", XFSSTAT_END_QM }, > }; > diff --git a/fs/xfs/xfs_stats.h b/fs/xfs/xfs_stats.h > index 483b0ef..657865f 100644 > --- a/fs/xfs/xfs_stats.h > +++ b/fs/xfs/xfs_stats.h > @@ -197,7 +197,23 @@ struct xfsstats { > __uint32_t xs_fibt_2_alloc; > __uint32_t xs_fibt_2_free; > __uint32_t xs_fibt_2_moves; > -#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_FIBT_V2+6) > +#define XFSSTAT_END_RMAP_V2 (XFSSTAT_END_FIBT_V2+15) > + __uint32_t xs_rmap_2_lookup; > + __uint32_t xs_rmap_2_compare; > + __uint32_t xs_rmap_2_insrec; > + __uint32_t xs_rmap_2_delrec; > + __uint32_t xs_rmap_2_newroot; > + __uint32_t xs_rmap_2_killroot; > + __uint32_t xs_rmap_2_increment; > + __uint32_t xs_rmap_2_decrement; > + __uint32_t xs_rmap_2_lshift; > + __uint32_t xs_rmap_2_rshift; > + __uint32_t xs_rmap_2_split; > + __uint32_t xs_rmap_2_join; > + __uint32_t xs_rmap_2_alloc; > + __uint32_t xs_rmap_2_free; > + __uint32_t xs_rmap_2_moves; > +#define XFSSTAT_END_XQMSTAT (XFSSTAT_END_RMAP_V2+6) > __uint32_t xs_qm_dqreclaims; > __uint32_t xs_qm_dqreclaim_misses; > __uint32_t xs_qm_dquot_dups; > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From bfoster@redhat.com Thu Jun 30 12:32:54 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay2.corp.sgi.com [137.38.102.29]) by oss.sgi.com (Postfix) with ESMTP id 318D57CA1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:32:54 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay2.corp.sgi.com (Postfix) with ESMTP id 02206304067 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:32:53 -0700 (PDT) X-ASG-Debug-ID: 1467307972-04cb6c063c2cc770001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id NlyfFkQdpJCAEh5g (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:32:53 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 544DB3B721; Thu, 30 Jun 2016 17:32:52 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UHWpVO017800; Thu, 30 Jun 2016 13:32:52 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id A28401200E8; Thu, 30 Jun 2016 13:32:50 -0400 (EDT) Date: Thu, 30 Jun 2016 13:32:50 -0400 From: Brian Foster <bfoster@redhat.com> To: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: david@fromorbit.com, linux-fsdevel@vger.kernel.org, vishal.l.verma@intel.com, Dave Chinner <dchinner@redhat.com>, xfs@oss.sgi.com Subject: Re: [PATCH 025/119] xfs: rmap btree add more reserved blocks Message-ID: <20160630173250.GC27303@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH 025/119] xfs: rmap btree add more reserved blocks References: <146612627129.12839.3827886950949809165.stgit@birch.djwong.org> <146612643276.12839.2224272649304333643.stgit@birch.djwong.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <146612643276.12839.2224272649304333643.stgit@birch.djwong.org> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 30 Jun 2016 17:32:52 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467307972 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 5526 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Thu, Jun 16, 2016 at 06:20:32PM -0700, Darrick J. Wong wrote: > From: Dave Chinner <dchinner@redhat.com> > > XFS reserves a small amount of space in each AG for the minimum > number of free blocks needed for operation. Adding the rmap btree > increases the number of reserved blocks, but it also increases the > complexity of the calculation as the free inode btree is optional > (like the rmbt). > > Rather than calculate the prealloc blocks every time we need to > check it, add a function to calculate it at mount time and store it > in the struct xfs_mount, and convert the XFS_PREALLOC_BLOCKS macro > just to use the xfs-mount variable directly. > > Signed-off-by: Dave Chinner <dchinner@redhat.com> > Signed-off-by: Dave Chinner <david@fromorbit.com> > --- Reviewed-by: Brian Foster <bfoster@redhat.com> > fs/xfs/libxfs/xfs_alloc.c | 11 +++++++++++ > fs/xfs/libxfs/xfs_alloc.h | 2 ++ > fs/xfs/libxfs/xfs_format.h | 9 +-------- > fs/xfs/xfs_fsops.c | 6 +++--- > fs/xfs/xfs_mount.c | 2 ++ > fs/xfs/xfs_mount.h | 1 + > 6 files changed, 20 insertions(+), 11 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c > index b61e9c6..fb00042 100644 > --- a/fs/xfs/libxfs/xfs_alloc.c > +++ b/fs/xfs/libxfs/xfs_alloc.c > @@ -50,6 +50,17 @@ STATIC int xfs_alloc_ag_vextent_size(xfs_alloc_arg_t *); > STATIC int xfs_alloc_ag_vextent_small(xfs_alloc_arg_t *, > xfs_btree_cur_t *, xfs_agblock_t *, xfs_extlen_t *, int *); > > +xfs_extlen_t > +xfs_prealloc_blocks( > + struct xfs_mount *mp) > +{ > + if (xfs_sb_version_hasrmapbt(&mp->m_sb)) > + return XFS_RMAP_BLOCK(mp) + 1; > + if (xfs_sb_version_hasfinobt(&mp->m_sb)) > + return XFS_FIBT_BLOCK(mp) + 1; > + return XFS_IBT_BLOCK(mp) + 1; > +} > + > /* > * Lookup the record equal to [bno, len] in the btree given by cur. > */ > diff --git a/fs/xfs/libxfs/xfs_alloc.h b/fs/xfs/libxfs/xfs_alloc.h > index cf268b2..20b54aa 100644 > --- a/fs/xfs/libxfs/xfs_alloc.h > +++ b/fs/xfs/libxfs/xfs_alloc.h > @@ -232,4 +232,6 @@ int xfs_alloc_fix_freelist(struct xfs_alloc_arg *args, int flags); > int xfs_free_extent_fix_freelist(struct xfs_trans *tp, xfs_agnumber_t agno, > struct xfs_buf **agbp); > > +xfs_extlen_t xfs_prealloc_blocks(struct xfs_mount *mp); > + > #endif /* __XFS_ALLOC_H__ */ > diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h > index 8ca4a3d..b5b0901 100644 > --- a/fs/xfs/libxfs/xfs_format.h > +++ b/fs/xfs/libxfs/xfs_format.h > @@ -1318,18 +1318,11 @@ typedef __be32 xfs_inobt_ptr_t; > */ > #define XFS_RMAP_CRC_MAGIC 0x524d4233 /* 'RMB3' */ > > -/* > - * The first data block of an AG depends on whether the filesystem was formatted > - * with the finobt feature. If so, account for the finobt reserved root btree > - * block. > - */ > -#define XFS_PREALLOC_BLOCKS(mp) \ > +#define XFS_RMAP_BLOCK(mp) \ > (xfs_sb_version_hasfinobt(&((mp)->m_sb)) ? \ > XFS_FIBT_BLOCK(mp) + 1 : \ > XFS_IBT_BLOCK(mp) + 1) > > - > - > /* > * BMAP Btree format definitions > * > diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c > index 064fce1..62162d4 100644 > --- a/fs/xfs/xfs_fsops.c > +++ b/fs/xfs/xfs_fsops.c > @@ -243,7 +243,7 @@ xfs_growfs_data_private( > agf->agf_flfirst = cpu_to_be32(1); > agf->agf_fllast = 0; > agf->agf_flcount = 0; > - tmpsize = agsize - XFS_PREALLOC_BLOCKS(mp); > + tmpsize = agsize - mp->m_ag_prealloc_blocks; > agf->agf_freeblks = cpu_to_be32(tmpsize); > agf->agf_longest = cpu_to_be32(tmpsize); > if (xfs_sb_version_hascrc(&mp->m_sb)) > @@ -340,7 +340,7 @@ xfs_growfs_data_private( > agno, 0); > > arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); > - arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); > + arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks); > arec->ar_blockcount = cpu_to_be32( > agsize - be32_to_cpu(arec->ar_startblock)); > > @@ -369,7 +369,7 @@ xfs_growfs_data_private( > agno, 0); > > arec = XFS_ALLOC_REC_ADDR(mp, XFS_BUF_TO_BLOCK(bp), 1); > - arec->ar_startblock = cpu_to_be32(XFS_PREALLOC_BLOCKS(mp)); > + arec->ar_startblock = cpu_to_be32(mp->m_ag_prealloc_blocks); > arec->ar_blockcount = cpu_to_be32( > agsize - be32_to_cpu(arec->ar_startblock)); > nfree += be32_to_cpu(arec->ar_blockcount); > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c > index bf63682..b4153f0 100644 > --- a/fs/xfs/xfs_mount.c > +++ b/fs/xfs/xfs_mount.c > @@ -231,6 +231,8 @@ xfs_initialize_perag( > > if (maxagi) > *maxagi = index; > + > + mp->m_ag_prealloc_blocks = xfs_prealloc_blocks(mp); > return 0; > > out_unwind: > diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h > index c1b798c..0537b1f 100644 > --- a/fs/xfs/xfs_mount.h > +++ b/fs/xfs/xfs_mount.h > @@ -119,6 +119,7 @@ typedef struct xfs_mount { > uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ > uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ > uint m_in_maxlevels; /* max inobt btree levels. */ > + xfs_extlen_t m_ag_prealloc_blocks; /* reserved ag blocks */ > struct radix_tree_root m_perag_tree; /* per-ag accounting info */ > spinlock_t m_perag_lock; /* lock for m_perag_tree */ > struct mutex m_growlock; /* growfs mutex */ > > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs From Martinezant2141@live.com Thu Jun 30 12:39:53 2016 Return-Path: <Martinezant2141@live.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.3 required=5.0 tests=FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,HTML_MESSAGE autolearn=no version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id EB62F7CA1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 12:39:52 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 62737AC002 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:39:49 -0700 (PDT) X-ASG-Debug-ID: 1467308384-04cbb027363c5d50001-NocioJ Received: from COL004-OMC2S1.hotmail.com (col004-omc2s1.hotmail.com [65.55.34.75]) by cuda.sgi.com with ESMTP id guRWqcpXTvLghVDf (version=TLSv1.2 cipher=ECDHE-RSA-AES256-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 10:39:44 -0700 (PDT) X-Barracuda-Envelope-From: Martinezant2141@live.com X-Barracuda-Effective-Source-IP: col004-omc2s1.hotmail.com[65.55.34.75] X-Barracuda-Apparent-Source-IP: 65.55.34.75 Received: from NAM03-DM3-obe.outbound.protection.outlook.com ([65.55.34.71]) by COL004-OMC2S1.hotmail.com over TLS secured channel with Microsoft SMTPSVC(7.5.7601.23008); Thu, 30 Jun 2016 10:39:44 -0700 Received: from CO1NAM03FT063.eop-NAM03.prod.protection.outlook.com (10.152.80.60) by CO1NAM03HT059.eop-NAM03.prod.protection.outlook.com (10.152.81.196) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.534.7; Thu, 30 Jun 2016 17:39:42 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com (10.152.80.51) by CO1NAM03FT063.mail.protection.outlook.com (10.152.81.61) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.534.7 via Frontend Transport; Thu, 30 Jun 2016 17:39:42 +0000 Received: from SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) by SN1PR05MB2317.namprd05.prod.outlook.com ([10.169.125.19]) with mapi id 15.01.0523.024; Thu, 30 Jun 2016 17:39:41 +0000 From: Anthony l <Martinezant2141@live.com> To: Eric Sandeen <sandeen@sandeen.net> CC: "xfs@oss.sgi.com" <xfs@oss.sgi.com> Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Topic: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Thread-Index: AQHR0uoTpTlXrUi8902XIsNl1Vl39qACM7x6gAAJQoCAAAKw3Q== Date: Thu, 30 Jun 2016 17:39:41 +0000 Message-ID: <SN1PR05MB231770F5231AF4B51CD9DCF3CC240@SN1PR05MB2317.namprd05.prod.outlook.com> References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com> <4d9d00ef-82d5-a658-e88c-ba75fb7a6023@sandeen.net> <SN1PR05MB2317E464B2CFB5A06CC4B66BCC240@SN1PR05MB2317.namprd05.prod.outlook.com>,<dc20d8ae-d57f-53f1-72b8-d623529c695b@sandeen.net> In-Reply-To: <dc20d8ae-d57f-53f1-72b8-d623529c695b@sandeen.net> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=softfail (sender IP is 10.152.80.51) smtp.mailfrom=live.com; oss.sgi.com; dkim=none (message not signed) header.d=none;oss.sgi.com; dmarc=none action=none header.from=live.com; received-spf: SoftFail (protection.outlook.com: domain of transitioning live.com discourages use of 10.152.80.51 as permitted sender) x-tmn: [B56eHt/xG6c2zqEkwXejss0tyR5e1GnK] x-eopattributedmessage: 0 x-forefront-antispam-report: CIP:10.152.80.51;IPV:NLI;CTRY:;EFV:NLI;SFV:NSPM;SFS:(10019020)(98900003);DIR:OUT;SFP:1102;SCL:1;SRVR:CO1NAM03HT059;H:SN1PR05MB2317.namprd05.prod.outlook.com;FPR:;SPF:None;LANG:en; x-ms-office365-filtering-correlation-id: 1da2be22-7c0c-4b11-f480-08d3a10d848c x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:(1601124038)(5061506196)(5061507196)(1603103041)(1601125047);SRVR:CO1NAM03HT059; x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(432015012)(82015046);SRVR:CO1NAM03HT059;BCL:0;PCL:0;RULEID:;SRVR:CO1NAM03HT059; x-forefront-prvs: 0989A7979C Content-Type: multipart/alternative; boundary="_000_SN1PR05MB231770F5231AF4B51CD9DCF3CC240SN1PR05MB2317namp_" MIME-Version: 1.0 X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-originalarrivaltime: 30 Jun 2016 17:39:41.8627 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Internet X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-Transport-CrossTenantHeadersStamped: CO1NAM03HT059 X-OriginalArrivalTime: 30 Jun 2016 17:39:44.0095 (UTC) FILETIME=[6357EEF0:01D1D2F6] X-Barracuda-Connect: col004-omc2s1.hotmail.com[65.55.34.75] X-Barracuda-Start-Time: 1467308384 X-Barracuda-Encrypted: ECDHE-RSA-AES256-SHA384 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 23592 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.02 X-Barracuda-Spam-Status: No, SCORE=0.02 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, HTML_MESSAGE, THREAD_INDEX, THREAD_TOPIC X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30901 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.01 THREAD_INDEX thread-index: AcO7Y8iR61tzADqsRmmc5wNiFHEOig== 0.01 THREAD_TOPIC Thread-Topic: ...(Japanese Subject)... 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header 0.00 HTML_MESSAGE BODY: HTML included in message --_000_SN1PR05MB231770F5231AF4B51CD9DCF3CC240SN1PR05MB2317namp_ Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable I put that, but I suppose if I am trouble shooting thats not the best idea.= That was all I was able to see. I just ran the command and moved all the o= ut put to a file here is a complete paste of the entire verbosity out. http://pastebin.com/UW9zRAZ0 (full verbosity out) Nothing looks like its producing an error which is why I am so confused. and cat/var/log/dmesg | grep -i st0 (tape connector) $ cat /var/log/dmesg | grep -i st0 [ 1.036623] scsi host0: ata_piix [ 16.613496] st 6:0:0:0: Attached scsi tape st0 [ 16.613500] st 6:0:0:0: st0: try direct i/o: yes (alignment 4 B) $ cat /var/log/dmesg | grep -i scsi [ 0.429954] SCSI subsystem initialized [ 0.827902] Block layer SCSI generic (bsg) driver version 0.4 loaded (ma= jor 249) [ 1.036623] scsi host0: ata_piix [ 1.036699] scsi host1: ata_piix [ 1.192299] scsi host2: ata_piix [ 1.192390] scsi host3: ata_piix [ 1.193129] scsi host4: ata_generic [ 1.193216] scsi host5: ata_generic [ 1.864429] scsi 0:0:0:0: Direct-Access ATA SAMSUNG HE160HJ 0-= 24 PQ: 0 ANSI: 5 [ 1.864648] sd 0:0:0:0: Attached scsi generic sg0 type 0 [ 1.867113] scsi 1:0:1:0: CD-ROM PLDS DVD+-RW DH-16A6S YD= 12 PQ: 0 ANSI: 5 [ 1.882378] sr 1:0:1:0: [sr0] scsi3-mmc drive: 48x/12x writer dvd-ram cd= /rw xa/form2 cdda tray [ 1.882516] sr 1:0:1:0: Attached scsi CD-ROM sr0 [ 1.882574] sr 1:0:1:0: Attached scsi generic sg1 type 5 [ 1.898525] sd 0:0:0:0: [sda] Attached SCSI disk [ 7.328020] scsi host6: Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev 3.0 [ 7.328020] <Adaptec 29320LP Ultra320 SCSI adapter> [ 7.328020] aic7901A: Ultra320 Wide Channel A, SCSI Id=3D5, PCI = 33 or 66MHz, 512 SCBs [ 7.329000] scsi target6:0:0: asynchronous [ 7.330396] scsi 6:0:0:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.330404] scsi target6:0:0: Beginning Domain Validation [ 7.334243] scsi target6:0:0: wide asynchronous [ 7.337044] scsi target6:0:0: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.349735] scsi target6:0:0: Ending Domain Validation [ 7.352917] scsi target6:0:1: asynchronous [ 7.354313] scsi 6:0:1:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.354319] scsi target6:0:1: Beginning Domain Validation [ 7.358061] scsi target6:0:1: wide asynchronous [ 7.361002] scsi target6:0:1: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.373736] scsi target6:0:1: Ending Domain Validation [ 7.376870] scsi target6:0:2: asynchronous [ 7.378273] scsi 6:0:2:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.378279] scsi target6:0:2: Beginning Domain Validation [ 7.381828] scsi target6:0:2: wide asynchronous [ 7.384690] scsi target6:0:2: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.397361] scsi target6:0:2: Ending Domain Validation [ 7.400499] scsi target6:0:3: asynchronous [ 7.401901] scsi 6:0:3:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.401907] scsi target6:0:3: Beginning Domain Validation [ 7.405763] scsi target6:0:3: wide asynchronous [ 7.408555] scsi target6:0:3: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.421233] scsi target6:0:3: Ending Domain Validation [ 7.424407] scsi target6:0:4: asynchronous [ 7.425819] scsi 6:0:4:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.425825] scsi target6:0:4: Beginning Domain Validation [ 7.429636] scsi target6:0:4: wide asynchronous [ 7.432427] scsi target6:0:4: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.445294] scsi target6:0:4: Ending Domain Validation [ 7.448422] scsi target6:0:6: asynchronous [ 7.449838] scsi 6:0:6:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.449845] scsi target6:0:6: Beginning Domain Validation [ 7.453663] scsi target6:0:6: wide asynchronous [ 7.456487] scsi target6:0:6: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.469217] scsi target6:0:6: Ending Domain Validation [ 7.472339] scsi target6:0:7: asynchronous [ 7.473800] scsi 6:0:7:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.473807] scsi target6:0:7: Beginning Domain Validation [ 7.477631] scsi target6:0:7: wide asynchronous [ 7.480481] scsi target6:0:7: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.493222] scsi target6:0:7: Ending Domain Validation [ 7.496351] scsi target6:0:8: asynchronous [ 7.497771] scsi 6:0:8:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.497778] scsi target6:0:8: Beginning Domain Validation [ 7.501488] scsi target6:0:8: wide asynchronous [ 7.504429] scsi target6:0:8: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.517155] scsi target6:0:8: Ending Domain Validation [ 7.520280] scsi target6:0:9: asynchronous [ 7.521668] scsi 6:0:9:0: Sequential-Access QUANTUM SDLT600 2B= 2B PQ: 0 ANSI: 4 [ 7.521675] scsi target6:0:9: Beginning Domain Validation [ 7.525473] scsi target6:0:9: wide asynchronous [ 7.528407] scsi target6:0:9: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, = offset 120) [ 7.541143] scsi target6:0:9: Ending Domain Validation [ 7.544314] scsi target6:0:10: asynchronous [ 7.545727] scsi 6:0:10:0: Sequential-Access QUANTUM SDLT600 2= B2B PQ: 0 ANSI: 4 [ 7.545735] scsi target6:0:10: Beginning Domain Validation [ 7.549442] scsi target6:0:10: wide asynchronous [ 7.552280] scsi target6:0:10: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns,= offset 120) [ 7.564984] scsi target6:0:10: Ending Domain Validation [ 7.568067] scsi target6:0:11: asynchronous [ 7.569451] scsi 6:0:11:0: Sequential-Access QUANTUM SDLT600 2= B2B PQ: 0 ANSI: 4 [ 7.569459] scsi target6:0:11: Beginning Domain Validation [ 7.573197] scsi target6:0:11: wide asynchronous [ 7.576047] scsi target6:0:11: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns,= offset 120) [ 7.588771] scsi target6:0:11: Ending Domain Validation [ 7.591894] scsi target6:0:12: asynchronous [ 7.593326] scsi 6:0:12:0: Sequential-Access QUANTUM SDLT600 2= B2B PQ: 0 ANSI: 4 [ 7.593334] scsi target6:0:12: Beginning Domain Validation [ 7.597156] scsi target6:0:12: wide asynchronous [ 7.599974] scsi target6:0:12: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns,= offset 120) [ 7.612720] scsi target6:0:12: Ending Domain Validation [ 7.615848] scsi target6:0:13: asynchronous [ 7.617212] scsi 6:0:13:0: Sequential-Access QUANTUM SDLT600 2= B2B PQ: 0 ANSI: 4 [ 7.617220] scsi target6:0:13: Beginning Domain Validation [ 7.620943] scsi target6:0:13: wide asynchronous [ 7.623937] scsi target6:0:13: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns,= offset 120) [ 7.636720] scsi target6:0:13: Ending Domain Validation [ 7.639849] scsi target6:0:14: asynchronous [ 7.641217] scsi 6:0:14:0: Sequential-Access QUANTUM SDLT600 2= B2B PQ: 0 ANSI: 4 [ 7.641225] scsi target6:0:14: Beginning Domain Validation [ 7.644860] scsi target6:0:14: wide asynchronous [ 7.647710] scsi target6:0:14: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns,= offset 120) [ 7.660427] scsi target6:0:14: Ending Domain Validation [ 7.663613] scsi target6:0:15: asynchronous [ 7.665008] scsi 6:0:15:0: Sequential-Access QUANTUM SDLT600 2= B2B PQ: 0 ANSI: 4 [ 7.665016] scsi target6:0:15: Beginning Domain Validation [ 7.668828] scsi target6:0:15: wide asynchronous [ 7.671621] scsi target6:0:15: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns,= offset 120) [ 7.684311] scsi target6:0:15: Ending Domain Validation [ 7.686630] scsi 6:0:0:0: Attached scsi generic sg2 type 1 [ 7.686795] scsi 6:0:1:0: Attached scsi generic sg3 type 1 [ 7.686956] scsi 6:0:2:0: Attached scsi generic sg4 type 1 [ 7.687115] scsi 6:0:3:0: Attached scsi generic sg5 type 1 [ 7.687276] scsi 6:0:4:0: Attached scsi generic sg6 type 1 [ 7.687437] scsi 6:0:6:0: Attached scsi generic sg7 type 1 [ 7.687598] scsi 6:0:7:0: Attached scsi generic sg8 type 1 [ 7.687761] scsi 6:0:8:0: Attached scsi generic sg9 type 1 [ 7.687924] scsi 6:0:9:0: Attached scsi generic sg10 type 1 [ 7.688089] scsi 6:0:10:0: Attached scsi generic sg11 type 1 [ 7.688249] scsi 6:0:11:0: Attached scsi generic sg12 type 1 [ 7.688409] scsi 6:0:12:0: Attached scsi generic sg13 type 1 [ 7.688569] scsi 6:0:13:0: Attached scsi generic sg14 type 1 [ 7.688731] scsi 6:0:14:0: Attached scsi generic sg15 type 1 [ 7.688893] scsi 6:0:15:0: Attached scsi generic sg16 type 1 [ 16.613496] st 6:0:0:0: Attached scsi tape st0 [ 16.617070] st 6:0:1:0: Attached scsi tape st1 [ 16.638012] st 6:0:2:0: Attached scsi tape st2 [ 16.638789] st 6:0:3:0: Attached scsi tape st3 [ 16.639266] st 6:0:4:0: Attached scsi tape st4 [ 16.639837] st 6:0:6:0: Attached scsi tape st5 [ 16.640425] st 6:0:7:0: Attached scsi tape st6 [ 16.640905] st 6:0:8:0: Attached scsi tape st7 [ 16.641381] st 6:0:9:0: Attached scsi tape st8 [ 16.641998] st 6:0:10:0: Attached scsi tape st9 [ 16.642563] st 6:0:11:0: Attached scsi tape st10 [ 16.643069] st 6:0:12:0: Attached scsi tape st11 [ 16.643545] st 6:0:13:0: Attached scsi tape st12 [ 16.644117] st 6:0:14:0: Attached scsi tape st13 [ 16.644597] st 6:0:15:0: Attached scsi tape st14 <http://oss.sgi.com/mailman/listinfo/xfs> --_000_SN1PR05MB231770F5231AF4B51CD9DCF3CC240SN1PR05MB2317namp_ Content-Type: text/html; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable <html> <head> <meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Diso-8859-= 1"> <style type=3D"text/css" style=3D"display:none;"><!-- P {margin-top:0;margi= n-bottom:0;} --></style> </head> <body dir=3D"ltr"> <div id=3D"divtagdefaultwrapper" style=3D"font-size:12pt;color:#000000;back= ground-color:#FFFFFF;font-family:Calibri,Arial,Helvetica,sans-serif;"> <font size=3D"2"><span style=3D"font-size:10pt;">I put that, but I suppose = if I am trouble shooting thats not the best idea. That was all I was able t= o see. I just ran the command and moved all the out put to a file here is a= complete paste of the entire verbosity out. <br> <a disabled=3D"true" tabindex=3D"-1" title=3D"Ctrl+Click or tap to foll= ow the link" id=3D"LPlnk580685" href=3D"http://pastebin.com/UW9zRAZ0" class= =3D"OWAAutoLink">http://pastebin.com/UW9zRAZ0</a>    (full v= erbosity out)<br> Nothing looks like its producing an error which is why I am so confused. <b= r> <br> and cat/var/log/dmesg | grep -i st0  (tape connector) <br> <div>$ cat /var/log/dmesg | grep -i st0<br> [    1.036623] scsi host0: ata_piix<br> [   16.613496] st 6:0:0:0: Attached scsi tape st0<br> [   16.613500] st 6:0:0:0: st0: try direct i/o: yes (alignment 4 = B)<br> </div> <br> <br> <br> <div>$ cat /var/log/dmesg | grep -i scsi<br> [    0.429954] SCSI subsystem initialized<br> [    0.827902] Block layer SCSI generic (bsg) driver version= 0.4 loaded (major 249)<br> [    1.036623] scsi host0: ata_piix<br> [    1.036699] scsi host1: ata_piix<br> [    1.192299] scsi host2: ata_piix<br> [    1.192390] scsi host3: ata_piix<br> [    1.193129] scsi host4: ata_generic<br> [    1.193216] scsi host5: ata_generic<br> [    1.864429] scsi 0:0:0:0: Direct-Access   =   ATA      SAMSUNG HE160HJ  0-24 PQ: 0 A= NSI: 5<br> [    1.864648] sd 0:0:0:0: Attached scsi generic sg0 type 0<= br> [    1.867113] scsi 1:0:1:0: CD-ROM    &= nbsp;       PLDS     DVD&= #43;-RW DH-16A6S YD12 PQ: 0 ANSI: 5<br> [    1.882378] sr 1:0:1:0: [sr0] scsi3-mmc drive: 48x/12x wr= iter dvd-ram cd/rw xa/form2 cdda tray<br> [    1.882516] sr 1:0:1:0: Attached scsi CD-ROM sr0<br> [    1.882574] sr 1:0:1:0: Attached scsi generic sg1 type 5<= br> [    1.898525] sd 0:0:0:0: [sda] Attached SCSI disk<br> [    7.328020] scsi host6: Adaptec AIC79XX PCI-X SCSI HBA DR= IVER, Rev 3.0<br> [    7.328020]       &nbs= p; <Adaptec 29320LP Ultra320 SCSI adapter><br> [    7.328020]       &nbs= p; aic7901A: Ultra320 Wide Channel A, SCSI Id=3D5, PCI 33 or 66MHz, 512 SCB= s<br> [    7.329000] scsi target6:0:0: asynchronous<br> [    7.330396] scsi 6:0:0:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.330404] scsi target6:0:0: Beginning Domain Validation= <br> [    7.334243] scsi target6:0:0: wide asynchronous<br> [    7.337044] scsi target6:0:0: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.349735] scsi target6:0:0: Ending Domain Validation<br= > [    7.352917] scsi target6:0:1: asynchronous<br> [    7.354313] scsi 6:0:1:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.354319] scsi target6:0:1: Beginning Domain Validation= <br> [    7.358061] scsi target6:0:1: wide asynchronous<br> [    7.361002] scsi target6:0:1: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.373736] scsi target6:0:1: Ending Domain Validation<br= > [    7.376870] scsi target6:0:2: asynchronous<br> [    7.378273] scsi 6:0:2:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.378279] scsi target6:0:2: Beginning Domain Validation= <br> [    7.381828] scsi target6:0:2: wide asynchronous<br> [    7.384690] scsi target6:0:2: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.397361] scsi target6:0:2: Ending Domain Validation<br= > [    7.400499] scsi target6:0:3: asynchronous<br> [    7.401901] scsi 6:0:3:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.401907] scsi target6:0:3: Beginning Domain Validation= <br> [    7.405763] scsi target6:0:3: wide asynchronous<br> [    7.408555] scsi target6:0:3: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.421233] scsi target6:0:3: Ending Domain Validation<br= > [    7.424407] scsi target6:0:4: asynchronous<br> [    7.425819] scsi 6:0:4:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.425825] scsi target6:0:4: Beginning Domain Validation= <br> [    7.429636] scsi target6:0:4: wide asynchronous<br> [    7.432427] scsi target6:0:4: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.445294] scsi target6:0:4: Ending Domain Validation<br= > [    7.448422] scsi target6:0:6: asynchronous<br> [    7.449838] scsi 6:0:6:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.449845] scsi target6:0:6: Beginning Domain Validation= <br> [    7.453663] scsi target6:0:6: wide asynchronous<br> [    7.456487] scsi target6:0:6: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.469217] scsi target6:0:6: Ending Domain Validation<br= > [    7.472339] scsi target6:0:7: asynchronous<br> [    7.473800] scsi 6:0:7:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.473807] scsi target6:0:7: Beginning Domain Validation= <br> [    7.477631] scsi target6:0:7: wide asynchronous<br> [    7.480481] scsi target6:0:7: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.493222] scsi target6:0:7: Ending Domain Validation<br= > [    7.496351] scsi target6:0:8: asynchronous<br> [    7.497771] scsi 6:0:8:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.497778] scsi target6:0:8: Beginning Domain Validation= <br> [    7.501488] scsi target6:0:8: wide asynchronous<br> [    7.504429] scsi target6:0:8: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.517155] scsi target6:0:8: Ending Domain Validation<br= > [    7.520280] scsi target6:0:9: asynchronous<br> [    7.521668] scsi 6:0:9:0: Sequential-Access QUANTUM = SDLT600          2B2B PQ: 0 A= NSI: 4<br> [    7.521675] scsi target6:0:9: Beginning Domain Validation= <br> [    7.525473] scsi target6:0:9: wide asynchronous<br> [    7.528407] scsi target6:0:9: FAST-80 WIDE SCSI 160.0 MB/= s DT (12.5 ns, offset 120)<br> [    7.541143] scsi target6:0:9: Ending Domain Validation<br= > [    7.544314] scsi target6:0:10: asynchronous<br> [    7.545727] scsi 6:0:10:0: Sequential-Access QUANTUM = ; SDLT600          2B2B PQ: 0 = ANSI: 4<br> [    7.545735] scsi target6:0:10: Beginning Domain Validatio= n<br> [    7.549442] scsi target6:0:10: wide asynchronous<br> [    7.552280] scsi target6:0:10: FAST-80 WIDE SCSI 160.0 MB= /s DT (12.5 ns, offset 120)<br> [    7.564984] scsi target6:0:10: Ending Domain Validation<b= r> [    7.568067] scsi target6:0:11: asynchronous<br> [    7.569451] scsi 6:0:11:0: Sequential-Access QUANTUM = ; SDLT600          2B2B PQ: 0 = ANSI: 4<br> [    7.569459] scsi target6:0:11: Beginning Domain Validatio= n<br> [    7.573197] scsi target6:0:11: wide asynchronous<br> [    7.576047] scsi target6:0:11: FAST-80 WIDE SCSI 160.0 MB= /s DT (12.5 ns, offset 120)<br> [    7.588771] scsi target6:0:11: Ending Domain Validation<b= r> [    7.591894] scsi target6:0:12: asynchronous<br> [    7.593326] scsi 6:0:12:0: Sequential-Access QUANTUM = ; SDLT600          2B2B PQ: 0 = ANSI: 4<br> [    7.593334] scsi target6:0:12: Beginning Domain Validatio= n<br> [    7.597156] scsi target6:0:12: wide asynchronous<br> [    7.599974] scsi target6:0:12: FAST-80 WIDE SCSI 160.0 MB= /s DT (12.5 ns, offset 120)<br> [    7.612720] scsi target6:0:12: Ending Domain Validation<b= r> [    7.615848] scsi target6:0:13: asynchronous<br> [    7.617212] scsi 6:0:13:0: Sequential-Access QUANTUM = ; SDLT600          2B2B PQ: 0 = ANSI: 4<br> [    7.617220] scsi target6:0:13: Beginning Domain Validatio= n<br> [    7.620943] scsi target6:0:13: wide asynchronous<br> [    7.623937] scsi target6:0:13: FAST-80 WIDE SCSI 160.0 MB= /s DT (12.5 ns, offset 120)<br> [    7.636720] scsi target6:0:13: Ending Domain Validation<b= r> [    7.639849] scsi target6:0:14: asynchronous<br> [    7.641217] scsi 6:0:14:0: Sequential-Access QUANTUM = ; SDLT600          2B2B PQ: 0 = ANSI: 4<br> [    7.641225] scsi target6:0:14: Beginning Domain Validatio= n<br> [    7.644860] scsi target6:0:14: wide asynchronous<br> [    7.647710] scsi target6:0:14: FAST-80 WIDE SCSI 160.0 MB= /s DT (12.5 ns, offset 120)<br> [    7.660427] scsi target6:0:14: Ending Domain Validation<b= r> [    7.663613] scsi target6:0:15: asynchronous<br> [    7.665008] scsi 6:0:15:0: Sequential-Access QUANTUM = ; SDLT600          2B2B PQ: 0 = ANSI: 4<br> [    7.665016] scsi target6:0:15: Beginning Domain Validatio= n<br> [    7.668828] scsi target6:0:15: wide asynchronous<br> [    7.671621] scsi target6:0:15: FAST-80 WIDE SCSI 160.0 MB= /s DT (12.5 ns, offset 120)<br> [    7.684311] scsi target6:0:15: Ending Domain Validation<b= r> [    7.686630] scsi 6:0:0:0: Attached scsi generic sg2 type = 1<br> [    7.686795] scsi 6:0:1:0: Attached scsi generic sg3 type = 1<br> [    7.686956] scsi 6:0:2:0: Attached scsi generic sg4 type = 1<br> [    7.687115] scsi 6:0:3:0: Attached scsi generic sg5 type = 1<br> [    7.687276] scsi 6:0:4:0: Attached scsi generic sg6 type = 1<br> [    7.687437] scsi 6:0:6:0: Attached scsi generic sg7 type = 1<br> [    7.687598] scsi 6:0:7:0: Attached scsi generic sg8 type = 1<br> [    7.687761] scsi 6:0:8:0: Attached scsi generic sg9 type = 1<br> [    7.687924] scsi 6:0:9:0: Attached scsi generic sg10 type= 1<br> [    7.688089] scsi 6:0:10:0: Attached scsi generic sg11 typ= e 1<br> [    7.688249] scsi 6:0:11:0: Attached scsi generic sg12 typ= e 1<br> [    7.688409] scsi 6:0:12:0: Attached scsi generic sg13 typ= e 1<br> [    7.688569] scsi 6:0:13:0: Attached scsi generic sg14 typ= e 1<br> [    7.688731] scsi 6:0:14:0: Attached scsi generic sg15 typ= e 1<br> [    7.688893] scsi 6:0:15:0: Attached scsi generic sg16 typ= e 1<br> [   16.613496] st 6:0:0:0: Attached scsi tape st0<br> [   16.617070] st 6:0:1:0: Attached scsi tape st1<br> [   16.638012] st 6:0:2:0: Attached scsi tape st2<br> [   16.638789] st 6:0:3:0: Attached scsi tape st3<br> [   16.639266] st 6:0:4:0: Attached scsi tape st4<br> [   16.639837] st 6:0:6:0: Attached scsi tape st5<br> [   16.640425] st 6:0:7:0: Attached scsi tape st6<br> [   16.640905] st 6:0:8:0: Attached scsi tape st7<br> [   16.641381] st 6:0:9:0: Attached scsi tape st8<br> [   16.641998] st 6:0:10:0: Attached scsi tape st9<br> [   16.642563] st 6:0:11:0: Attached scsi tape st10<br> [   16.643069] st 6:0:12:0: Attached scsi tape st11<br> [   16.643545] st 6:0:13:0: Attached scsi tape st12<br> [   16.644117] st 6:0:14:0: Attached scsi tape st13<br> [   16.644597] st 6:0:15:0: Attached scsi tape st14<br> </div> <br> </span></font> <div style=3D"color: rgb(0, 0, 0);"><font size=3D"2"><span style=3D"font-si= ze:10pt;"> <div class=3D"PlainText"><a disabled=3D"true" tabindex=3D"-1" href=3D"http:= //oss.sgi.com/mailman/listinfo/xfs"></a><br> </div> </span></font></div> </div> </body> </html> --_000_SN1PR05MB231770F5231AF4B51CD9DCF3CC240SN1PR05MB2317namp_-- From david@fromorbit.com Thu Jun 30 17:08:12 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 2A97B7CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 17:08:12 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id 8613AAC002 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 15:08:08 -0700 (PDT) X-ASG-Debug-ID: 1467324485-04cbb027373dacd0001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id FCXAYWUCh0lWZwwA for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 15:08:05 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2AtHgDDl3VXIHvHLHlbgz5WdwaCdqFwAQEBAQEBBoppgWCKER6FcwQCAoE7TQEBAQEBAQcBAQEBAQFAQEEOAYN9AQEEJxMcIxAIAxgJJQ8FJQMHGhOILwrEHwELJR6FQoUVhAmGEgWZC4YIiC+BdE6HNoU8h3obFIdcglkfgV4qMnmISAEBAQ Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail06.adl6.internode.on.net with ESMTP; 01 Jul 2016 07:37:38 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bIk7V-00078T-L7; Fri, 01 Jul 2016 08:07:37 +1000 Date: Fri, 1 Jul 2016 08:07:37 +1000 From: Dave Chinner <david@fromorbit.com> To: Eric Sandeen <sandeen@sandeen.net> Cc: xfs@oss.sgi.com Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Message-ID: <20160630220737.GS12670@dastard> X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com> <4d9d00ef-82d5-a658-e88c-ba75fb7a6023@sandeen.net> <SN1PR05MB2317E464B2CFB5A06CC4B66BCC240@SN1PR05MB2317.namprd05.prod.outlook.com> <dc20d8ae-d57f-53f1-72b8-d623529c695b@sandeen.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <dc20d8ae-d57f-53f1-72b8-d623529c695b@sandeen.net> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1467324485 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2396 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30908 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 30, 2016 at 12:04:07PM -0500, Eric Sandeen wrote: > > > On 6/30/16 11:59 AM, Anthony l wrote: > > I don't think this is a multi tape dump. But then again i don't know for sure. I recently got a job and this is my first 'project'. I have about 10 tapes each are labeled a month and a year, so I don't think they are multi tape because they span like 3 years 2004-2007 . Although for the current tape I am working on right now if I select 1 skip, I'll get to another back up labeled "incremental backup 1" or something similar. Using the verbosity output here is what I got. (also using interactive restore). I went ahead and specified byte size 4096. Through earlier test using the dd command I determined that was the correct size. Ill post one without byte size specified too. I just saw it in that post and thought it might help. > > > > Here is the output with verbosity. > > > > http://pastebin.com/Nd6BqNc5 > > > > The out is the same with or without -b 4096. > > > > http://pastebin.com/0dxbCvyc (no -b) > > > interactively restore from this dump? > 1: skip > 2: interactively restore > (default) > ->2 > ++++================++++ > missing some stuff------ > > ^^^ is that your comment, or actual output? > > Looks like it eventually encountered a short read: > > xfsrestore: drive op: read: wanted 131072 (0x20000) > xfsrestore: tape op: reading 245760 bytes > xfsrestore: tape op read of 245760 bytes short: nread == 4096 > xfsrestore: tape op: get status > xfsrestore: tape status = wprot onl > xfsrestore: short read record 1 (nread == 4096) > xfsrestore: drive op read returning error rval=1 > > in dmesg, is there any sort of IO error from the tape? So xfs_reatore is wanting to find the session inventory in that last media file, and it would appear that it isn't there or shorter than expected. A tape problem, perhaps? Have you tried running xfs_restore using the minimal tape protocol (-m)? Another option is to try to restore the dump files from tape to a local file on disk and see if that can be parsed instead. The other thing you might want to do is upgrade xfsdump to the latest version - you're running 3.1.1 and the current version is 3.1.6. I doubt it will change the behaviour, but at least it will give us something to work from... Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 30 17:45:05 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 88A067CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 17:45:05 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay3.corp.sgi.com (Postfix) with ESMTP id F2918AC002 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 15:45:04 -0700 (PDT) X-ASG-Debug-ID: 1467326698-04cbb027353dc520001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id NDMIhxAJd1a6GMIh for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 15:44:59 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2BdEwDgn3VXIHvHLHlbgz5WfYJ2oWQMAQEBAQEBBoxKhgaECiKFbwICAQECgTNNAQEBAQEBBwEBAQEBAT8BQIRNAQEEJxMcIxAIAw4KCSUPBSUDBxoTiC8PxA4BAQgCASQehUKFFoobBZkLhgiIL4F0Toc2hTyQBYJcHIFeKjIBAQGJPgEBAQ Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail06.adl6.internode.on.net with ESMTP; 01 Jul 2016 08:14:58 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bIkhd-0007CH-BY; Fri, 01 Jul 2016 08:44:57 +1000 Date: Fri, 1 Jul 2016 08:44:57 +1000 From: Dave Chinner <david@fromorbit.com> To: Brian Foster <bfoster@redhat.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic Message-ID: <20160630224457.GT12670@dastard> X-ASG-Orig-Subj: Re: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic References: <1467291229-13548-1-git-send-email-bfoster@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1467291229-13548-1-git-send-email-bfoster@redhat.com> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1467326699 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 4436 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30909 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 30, 2016 at 08:53:49AM -0400, Brian Foster wrote: > Newly allocated XFS metadata buffers are added to the LRU once the hold > count is released, which typically occurs after I/O completion. There is > no other mechanism at current that tracks the existence or I/O state of > a new buffer. Further, readahead I/O tends to be submitted > asynchronously by nature, which means the I/O can remain in flight and > actually complete long after the calling context is gone. This means > that file descriptors or any other holds on the filesystem can be > released, allowing the filesystem to be unmounted while I/O is still in > flight. When I/O completion occurs, core data structures may have been > freed, causing completion to run into invalid memory accesses and likely > to panic. > > This problem is reproduced on XFS via directory readahead. A filesystem > is mounted, a directory is opened/closed and the filesystem immediately > unmounted. The open/close cycle triggers a directory readahead that if > delayed long enough, runs buffer I/O completion after the unmount has > completed. > > To work around this problem, add readahead buffers to the LRU earlier > than other buffers (when the buffer is allocated, specifically). The > buffer hold count will ultimately remain until I/O completion, which > means any shrinker activity will skip the buffer until then. This makes > the buffer visible to xfs_wait_buftarg(), however, which ensures that an > unmount or quiesce waits for I/O completion appropriately. > > Signed-off-by: Brian Foster <bfoster@redhat.com> > --- > > This addresses the problem reproduced by the recently posted xfstests > test: > > http://thread.gmane.org/gmane.comp.file-systems.fstests/2740 > > This could probably be made more involved, i.e., to create another list > of buffers in flight or some such. This seems more simple/sane to me, > however, and survives my testing so far... > > Brian > > fs/xfs/xfs_buf.c | 12 ++++++++++++ > 1 file changed, 12 insertions(+) > > diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c > index 4665ff6..3f03df9 100644 > --- a/fs/xfs/xfs_buf.c > +++ b/fs/xfs/xfs_buf.c > @@ -590,8 +590,20 @@ xfs_buf_get_map( > return NULL; > } > > + /* > + * If the buffer found doesn't match the one allocated above, somebody > + * else beat us to insertion and we can toss the new one. > + * > + * If we did add the buffer and it happens to be readahead, add to the > + * LRU now rather than waiting until the hold is released. Otherwise, > + * the buffer is not visible to xfs_wait_buftarg() while in flight and > + * nothing else prevents an unmount before I/O completion. > + */ > if (bp != new_bp) > xfs_buf_free(new_bp); > + else if (flags & XBF_READ_AHEAD && > + list_lru_add(&bp->b_target->bt_lru, &bp->b_lru)) > + atomic_inc(&bp->b_hold); This doesn't sit right with me. The LRU is for "unused" objects, and readahead objects are not unused until IO completes and nobody is waiting on them. As it is, this points out another problem with readahead buffers - they aren't actually being cached properly because b_lru_ref == 0, which means they are immediately reclaimed on IO completion rather than being added to the LRU.... I also think that it's not sufficient to cover the generic case of async IO that has no waiter. i.e. we could do get_buf, submit async write, drop submitter reference, and now we have the same problem but on a write. i.e. this problem is and async IO issue, not a readahead issue. I think that it might be better to fix it by doing this: 1. ensure async IO submission always has b_lru_ref set, and if it isn't, set it to 1. This ensures the buffer will be added to the LRU on completion if it isn't already there. 2. keep a count of async buffer IO in progress. A per-cpu counter in the buftarg will be fine for this. Increment in xfs_buf_submit(), decrement in the xfs_buf_rele() call from xfs_buf_iodone() once we've determined if the buffer needs adding to the LRU or not. 3. make xfs_wait_buftarg() wait until the async IO count goes to zero before it gives up trying to release buffers on the LRU. That will ensure readahead buffers are cached, and we capture both async read and async write buffers in xfs_wait_buftarg(). Cheers, Dave. -- Dave Chinner david@fromorbit.com From david@fromorbit.com Thu Jun 30 18:18:23 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id 00D197CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 18:18:23 -0500 (CDT) Received: from cuda.sgi.com (cuda1.sgi.com [192.48.157.11]) by relay3.corp.sgi.com (Postfix) with ESMTP id 7DE40AC005 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 16:18:19 -0700 (PDT) X-ASG-Debug-ID: 1467328563-04bdf074b425af40001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id IFsgH34EYwOADzNf for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 16:16:03 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2CcEgDHpnVXIHvHLHlbgz6BU4J2g3mddwEBAQEBAQaMSooQhhEEAgKBM00BAQEBAQEHAQEBAQEBPwFAhEwBAQEDATocIwULCAMOCgklDwUlAwcaE4goB8QfAQslHoVChRaKGwWZC443jzSQBYJcHIFeKjKJQQEBAQ Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail06.adl6.internode.on.net with ESMTP; 01 Jul 2016 08:46:02 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bIlBh-0007Fa-TG; Fri, 01 Jul 2016 09:16:01 +1000 Date: Fri, 1 Jul 2016 09:16:01 +1000 From: Dave Chinner <david@fromorbit.com> To: Christoph Hellwig <hch@lst.de> Cc: xfs@oss.sgi.com, rpeterso@redhat.com, linux-fsdevel@vger.kernel.org Subject: Re: iomap infrastructure and multipage writes V5 Message-ID: <20160630231601.GU12670@dastard> X-ASG-Orig-Subj: Re: iomap infrastructure and multipage writes V5 References: <1464792297-13185-1-git-send-email-hch@lst.de> <20160628002649.GI12670@dastard> <20160630172239.GA23082@lst.de> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160630172239.GA23082@lst.de> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1467328563 X-Barracuda-URL: https://192.48.157.11:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 3332 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30911 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 30, 2016 at 07:22:39PM +0200, Christoph Hellwig wrote: > On Tue, Jun 28, 2016 at 10:26:49AM +1000, Dave Chinner wrote: > > Christoph, it look slike there's an ENOSPC+ENOMEM behavioural regression here. > > generic/224 on my 1p/1GB RAM VM using a 1k lock size filesystem has > > significantly different behaviour once ENOSPC is hit withi this patchset. > > > > It ends up with an endless stream of errors like this: > > I've spent some time trying to reproduce this. I'm actually getting > the OOM killer almost reproducible for for-next without the iomap > patches as well when just using 1GB of mem. 1400 MB is the minimum > I can reproducibly finish the test with either code base. > > But with the 1400 MB setup I see a few interesting things. Even > with the baseline, no-iomap case I see a few errors in the log: > > [ 70.407465] Filesystem "vdc": reserve blocks depleted! Consider increasing > reserve pool > size. > [ 70.195645] XFS (vdc): page discard on page ffff88005682a988, inode 0xd3, offset 761856. > [ 70.408079] Buffer I/O error on dev vdc, logical block 1048513, lost async > page write > [ 70.408598] Buffer I/O error on dev vdc, logical block 1048514, lost async > page write > 27s > > With iomap I also see the spew of page discard errors your see, but while > I see a lot of them, the rest still finishes after a reasonable time, > just a few seconds more than the pre-iomap baseline. I also see the > reserve block depleted message in this case. The reserve block pool depleted message is normal for me in this test. We're throwing a thousand concurrent processes at the filesystem at ENOSPC, and so the metadata reservation for the delayed allocation totals quite a lot. We only reserve 8192 blocks for the reserve pool, so a delalloc reservation for one page on each file (4 blocks per page, which means a couple of blocks for the metadata reservation via the indlen calculation) is going to consume the reserve pool quite quickly if the up front reservation overshoots the XFS_ALLOC_SET_ASIDE() ENOSPC threshold. > Digging into the reserve block depleted message - it seems we have > too many parallel iomap_allocate transactions going on. I suspect > this might be because the writeback code will not finish a writeback > context if we have multiple blocks inside a page, which can > happen easily for this 1k ENOSPC setup. Right - this test has regularly triggered that warning on this particular test setup for me - it's not something new to the iomap patchset. > I've not had time to fully > check if this is what really happens, but I did a quick hack (see below) > to only allocate 1k at a time in iomap_begin, and with that generic/224 > finishes without the warning spew. Of course this isn't a real fix, > and I need to fully understand what's going on in writeback due to > different allocation / dirtying patterns from the iomap change. Which tends to indicate that the multi-block allocation has a larger indlen reservation, and that's what is causing the code to hit whatever edge-case that is leading to it not recovering. However, I'm still wondering how we are not throwing ENOSPC back to userspace at XFS_ALLOC_SET_ASIDE limits. Cheers, Dave. -- Dave Chinner david@fromorbit.com From bfoster@redhat.com Thu Jun 30 18:56:29 2016 Return-Path: <bfoster@redhat.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay3.corp.sgi.com [198.149.34.15]) by oss.sgi.com (Postfix) with ESMTP id B0BB57CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 18:56:29 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay3.corp.sgi.com (Postfix) with ESMTP id 2940CAC005 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 16:56:28 -0700 (PDT) X-ASG-Debug-ID: 1467330984-04cb6c063f2e08e0001-NocioJ Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by cuda.sgi.com with ESMTP id jimjGyMW3C38B29x (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 16:56:24 -0700 (PDT) X-Barracuda-Envelope-From: bfoster@redhat.com X-Barracuda-Effective-Source-IP: mx1.redhat.com[209.132.183.28] X-Barracuda-Apparent-Source-IP: 209.132.183.28 X-ASG-Whitelist: Client Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E1E6CC003556; Thu, 30 Jun 2016 23:56:23 +0000 (UTC) Received: from bfoster.bfoster (dhcp-41-180.bos.redhat.com [10.18.41.180]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u5UNuNvI018588; Thu, 30 Jun 2016 19:56:23 -0400 Received: by bfoster.bfoster (Postfix, from userid 1000) id 9C3FF1200E8; Thu, 30 Jun 2016 19:56:21 -0400 (EDT) Date: Thu, 30 Jun 2016 19:56:21 -0400 From: Brian Foster <bfoster@redhat.com> To: Dave Chinner <david@fromorbit.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic Message-ID: <20160630235621.GA44823@bfoster.bfoster> X-ASG-Orig-Subj: Re: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic References: <1467291229-13548-1-git-send-email-bfoster@redhat.com> <20160630224457.GT12670@dastard> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160630224457.GT12670@dastard> User-Agent: Mutt/1.6.1 (2016-04-27) X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.32]); Thu, 30 Jun 2016 23:56:23 +0000 (UTC) X-Barracuda-Connect: mx1.redhat.com[209.132.183.28] X-Barracuda-Start-Time: 1467330984 X-Barracuda-Encrypted: ECDHE-RSA-AES256-GCM-SHA384 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 6446 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 On Fri, Jul 01, 2016 at 08:44:57AM +1000, Dave Chinner wrote: > On Thu, Jun 30, 2016 at 08:53:49AM -0400, Brian Foster wrote: > > Newly allocated XFS metadata buffers are added to the LRU once the hold > > count is released, which typically occurs after I/O completion. There is > > no other mechanism at current that tracks the existence or I/O state of > > a new buffer. Further, readahead I/O tends to be submitted > > asynchronously by nature, which means the I/O can remain in flight and > > actually complete long after the calling context is gone. This means > > that file descriptors or any other holds on the filesystem can be > > released, allowing the filesystem to be unmounted while I/O is still in > > flight. When I/O completion occurs, core data structures may have been > > freed, causing completion to run into invalid memory accesses and likely > > to panic. > > > > This problem is reproduced on XFS via directory readahead. A filesystem > > is mounted, a directory is opened/closed and the filesystem immediately > > unmounted. The open/close cycle triggers a directory readahead that if > > delayed long enough, runs buffer I/O completion after the unmount has > > completed. > > > > To work around this problem, add readahead buffers to the LRU earlier > > than other buffers (when the buffer is allocated, specifically). The > > buffer hold count will ultimately remain until I/O completion, which > > means any shrinker activity will skip the buffer until then. This makes > > the buffer visible to xfs_wait_buftarg(), however, which ensures that an > > unmount or quiesce waits for I/O completion appropriately. > > > > Signed-off-by: Brian Foster <bfoster@redhat.com> > > --- > > > > This addresses the problem reproduced by the recently posted xfstests > > test: > > > > http://thread.gmane.org/gmane.comp.file-systems.fstests/2740 > > > > This could probably be made more involved, i.e., to create another list > > of buffers in flight or some such. This seems more simple/sane to me, > > however, and survives my testing so far... > > > > Brian > > > > fs/xfs/xfs_buf.c | 12 ++++++++++++ > > 1 file changed, 12 insertions(+) > > > > diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c > > index 4665ff6..3f03df9 100644 > > --- a/fs/xfs/xfs_buf.c > > +++ b/fs/xfs/xfs_buf.c > > @@ -590,8 +590,20 @@ xfs_buf_get_map( > > return NULL; > > } > > > > + /* > > + * If the buffer found doesn't match the one allocated above, somebody > > + * else beat us to insertion and we can toss the new one. > > + * > > + * If we did add the buffer and it happens to be readahead, add to the > > + * LRU now rather than waiting until the hold is released. Otherwise, > > + * the buffer is not visible to xfs_wait_buftarg() while in flight and > > + * nothing else prevents an unmount before I/O completion. > > + */ > > if (bp != new_bp) > > xfs_buf_free(new_bp); > > + else if (flags & XBF_READ_AHEAD && > > + list_lru_add(&bp->b_target->bt_lru, &bp->b_lru)) > > + atomic_inc(&bp->b_hold); > > This doesn't sit right with me. The LRU is for "unused" objects, and > readahead objects are not unused until IO completes and nobody is > waiting on them. > Sure, but don't buffers remain on the LRU once they are reused? My impression is that this patch really doesn't change behavior in that regard. IOWs, the buffer is going to end up on the LRU either way and either end up disposed if it is never actually accessed or "used" otherwise and the hold count is bumped. Further, isn't the hold count mechanism precisely to handle "used" buffers on the LRU? > As it is, this points out another problem with readahead buffers - > they aren't actually being cached properly because b_lru_ref == 0, > which means they are immediately reclaimed on IO completion rather > than being added to the LRU.... > Not following... _xfs_buf_alloc() sets b_lru_ref to 1 and I don't see it set/decremented unless we stale or dispose it. What am I missing? > I also think that it's not sufficient to cover the generic case of > async IO that has no waiter. i.e. we could do get_buf, submit async > write, drop submitter reference, and now we have the same problem > but on a write. i.e. this problem is and async IO issue, not a > readahead issue. > Indeed. I thought about making the current patch check for ASYNC, but opted to try and make it more isolated (I suppose ASYNC|READAHEAD would have been moreso). The other thought I had was to change where buffers are added to the LRU altogether, but didn't want to jump right to that. Is there any issue with populating the LRU with initially held buffers as such, or any particular reason LRU addition was deferred to I/O completion in the first place? > I think that it might be better to fix it by doing this: > > 1. ensure async IO submission always has b_lru_ref set, and > if it isn't, set it to 1. This ensures the buffer will be > added to the LRU on completion if it isn't already there. > See above. I'm not following why this is necessary (if it is, it seems indicative of a bug). > 2. keep a count of async buffer IO in progress. A per-cpu > counter in the buftarg will be fine for this. Increment in > xfs_buf_submit(), decrement in the xfs_buf_rele() call from > xfs_buf_iodone() once we've determined if the buffer needs > adding to the LRU or not. > > 3. make xfs_wait_buftarg() wait until the async IO count > goes to zero before it gives up trying to release buffers on > the LRU. > This is along the lines of what I was thinking wrt to a list (explicit I/O tracking one way or another). The count is more simple and does cover the arbitrary read/write case, but is still more code and seems slightly duplicative to me because in most cases the LRU wait already handles this. I'm also not totally sure we need to handle the write case. Are we susceptible to this issue anywhere that isn't already protected by the sb write protection mechanism, for example? OTOH, explicit tracking might provide a more generic way to deal with uncached buffers as opposed to lock cycling. Brian > That will ensure readahead buffers are cached, and we capture both > async read and async write buffers in xfs_wait_buftarg(). > > Cheers, > > Dave. > -- > Dave Chinner > david@fromorbit.com From david@fromorbit.com Thu Jun 30 23:34:04 2016 Return-Path: <david@fromorbit.com> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 37DD37CA0 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 23:34:04 -0500 (CDT) Received: from cuda.sgi.com (cuda2.sgi.com [192.48.176.25]) by relay1.corp.sgi.com (Postfix) with ESMTP id EF2E08F8040 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 21:34:00 -0700 (PDT) X-ASG-Debug-ID: 1467347633-04cbb027383e95e0001-NocioJ Received: from ipmail06.adl6.internode.on.net (ipmail06.adl6.internode.on.net [150.101.137.145]) by cuda.sgi.com with ESMTP id wPECkIYQ2NQhWhhM for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 21:33:54 -0700 (PDT) X-Barracuda-Envelope-From: david@fromorbit.com X-Barracuda-Effective-Source-IP: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Apparent-Source-IP: 150.101.137.145 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A2BeDwBS8nVXEHvHLHlbgz5WLU+CdqFmDAEBAQEBAQaMS4YGhAoihXACAgEBAoEyTQEBAQEBAQcBAQEBAQEBAT5AhEwBAQQBJxMcIwULCAMOCgklDwUlAwcaE4goBw/EEQwlHoVChBKBA4obBYgQhyOJWoYIiC+BdE6HNoU8kAiCXByBXioyAQEBiHEBAQE Received: from ppp121-44-199-123.lns20.syd7.internode.on.net (HELO dastard) ([121.44.199.123]) by ipmail06.adl6.internode.on.net with ESMTP; 01 Jul 2016 14:03:33 +0930 Received: from dave by dastard with local (Exim 4.80) (envelope-from <david@fromorbit.com>) id 1bIq8y-0007ir-10; Fri, 01 Jul 2016 14:33:32 +1000 Date: Fri, 1 Jul 2016 14:33:31 +1000 From: Dave Chinner <david@fromorbit.com> To: Brian Foster <bfoster@redhat.com> Cc: xfs@oss.sgi.com Subject: Re: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic Message-ID: <20160701043331.GV12670@dastard> X-ASG-Orig-Subj: Re: [PATCH] xfs: add readahead bufs to lru early to prevent post-unmount panic References: <1467291229-13548-1-git-send-email-bfoster@redhat.com> <20160630224457.GT12670@dastard> <20160630235621.GA44823@bfoster.bfoster> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20160630235621.GA44823@bfoster.bfoster> User-Agent: Mutt/1.5.21 (2010-09-15) X-Barracuda-Connect: ipmail06.adl6.internode.on.net[150.101.137.145] X-Barracuda-Start-Time: 1467347633 X-Barracuda-URL: https://192.48.176.25:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 9324 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30915 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header On Thu, Jun 30, 2016 at 07:56:21PM -0400, Brian Foster wrote: > On Fri, Jul 01, 2016 at 08:44:57AM +1000, Dave Chinner wrote: > > On Thu, Jun 30, 2016 at 08:53:49AM -0400, Brian Foster wrote: > > > Newly allocated XFS metadata buffers are added to the LRU once the hold > > > count is released, which typically occurs after I/O completion. There is > > > no other mechanism at current that tracks the existence or I/O state of > > > a new buffer. Further, readahead I/O tends to be submitted > > > asynchronously by nature, which means the I/O can remain in flight and > > > actually complete long after the calling context is gone. This means > > > that file descriptors or any other holds on the filesystem can be > > > released, allowing the filesystem to be unmounted while I/O is still in > > > flight. When I/O completion occurs, core data structures may have been > > > freed, causing completion to run into invalid memory accesses and likely > > > to panic. > > > > > > This problem is reproduced on XFS via directory readahead. A filesystem > > > is mounted, a directory is opened/closed and the filesystem immediately > > > unmounted. The open/close cycle triggers a directory readahead that if > > > delayed long enough, runs buffer I/O completion after the unmount has > > > completed. > > > > > > To work around this problem, add readahead buffers to the LRU earlier > > > than other buffers (when the buffer is allocated, specifically). The > > > buffer hold count will ultimately remain until I/O completion, which > > > means any shrinker activity will skip the buffer until then. This makes > > > the buffer visible to xfs_wait_buftarg(), however, which ensures that an > > > unmount or quiesce waits for I/O completion appropriately. > > > > > > Signed-off-by: Brian Foster <bfoster@redhat.com> > > > --- > > > > > > This addresses the problem reproduced by the recently posted xfstests > > > test: > > > > > > http://thread.gmane.org/gmane.comp.file-systems.fstests/2740 > > > > > > This could probably be made more involved, i.e., to create another list > > > of buffers in flight or some such. This seems more simple/sane to me, > > > however, and survives my testing so far... > > > > > > Brian > > > > > > fs/xfs/xfs_buf.c | 12 ++++++++++++ > > > 1 file changed, 12 insertions(+) > > > > > > diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c > > > index 4665ff6..3f03df9 100644 > > > --- a/fs/xfs/xfs_buf.c > > > +++ b/fs/xfs/xfs_buf.c > > > @@ -590,8 +590,20 @@ xfs_buf_get_map( > > > return NULL; > > > } > > > > > > + /* > > > + * If the buffer found doesn't match the one allocated above, somebody > > > + * else beat us to insertion and we can toss the new one. > > > + * > > > + * If we did add the buffer and it happens to be readahead, add to the > > > + * LRU now rather than waiting until the hold is released. Otherwise, > > > + * the buffer is not visible to xfs_wait_buftarg() while in flight and > > > + * nothing else prevents an unmount before I/O completion. > > > + */ > > > if (bp != new_bp) > > > xfs_buf_free(new_bp); > > > + else if (flags & XBF_READ_AHEAD && > > > + list_lru_add(&bp->b_target->bt_lru, &bp->b_lru)) > > > + atomic_inc(&bp->b_hold); > > > > This doesn't sit right with me. The LRU is for "unused" objects, and > > readahead objects are not unused until IO completes and nobody is > > waiting on them. > > > > Sure, but don't buffers remain on the LRU once they are reused? Yes, but that's once the contents have been used. > My > impression is that this patch really doesn't change behavior in that > regard. Not really - but it makes the readahead buffers completely different to the rest of the buffers on the LRU in that they don't contain valid data. For the same reason we also don't add buffers at creation time because they don't hold valid data until after the code that has created/read in the data has released it..... > IOWs, the buffer is going to end up on the LRU either way and > either end up disposed if it is never actually accessed or "used" > otherwise and the hold count is bumped. Further, isn't the hold count > mechanism precisely to handle "used" buffers on the LRU? ... hence we only add the buffer to the LRU once the initial hold count reaches zero and the owner has indicated that the buffer should be moved to the LRU by setting b_lru_ref. Once we've added the buffer to the LRU, we add a reference count that persists untile b_lru_ref is decremented to zero. At that point, we remove the euffer from the LRU and release it. That (b_lru_ref == 0) then triggers the buffer to be freed.... Note also that buffers that contain stale data (i.e. XBF_STALE) are not added to the LRU and xfs_buf_stale() removes buffers from the LRU, so shortcutting the above reclaim lifecycle in the case where a user invalidates the contents of the buffer. The end result is the same - there are no buffers with stale contents on the LRU. readahead is a special case - there is no accessor to say "cache this buffer for N references", but we have to keep it around for some time so that readahead is effective. We don't want to add it before we've done IO on it, and realistically we should only add it to the LRU if there was no IO error. We've had to work around bugs introduced by caching failed readahead buffers on the LRU in the past.... > > As it is, this points out another problem with readahead buffers - > > they aren't actually being cached properly because b_lru_ref == 0, > > which means they are immediately reclaimed on IO completion rather > > than being added to the LRU.... > > > > Not following... _xfs_buf_alloc() sets b_lru_ref to 1 and I don't see it > set/decremented unless we stale or dispose it. What am I missing? Sorry, I misread the cscope output I was looking at to quickly remind me of how it all worked - xfs_buf_stale() sets it to zero, not _xfs_buf_alloc(). > > I also think that it's not sufficient to cover the generic case of > > async IO that has no waiter. i.e. we could do get_buf, submit async > > write, drop submitter reference, and now we have the same problem > > but on a write. i.e. this problem is and async IO issue, not a > > readahead issue. > > > > Indeed. I thought about making the current patch check for ASYNC, but > opted to try and make it more isolated (I suppose ASYNC|READAHEAD would > have been moreso). > > The other thought I had was to change where buffers are added to the LRU > altogether, but didn't want to jump right to that. Is there any issue > with populating the LRU with initially held buffers as such, or any > particular reason LRU addition was deferred to I/O completion in the > first place? Yes, because then we have to deal with buffers that fail memory allocation, read IO or are allocated just to invalidate a range of disk blocks during a transaction (e.g. removing a remote attribute). There are probably other cases where we don't want to put buffers we allocate onto the LRU, but I can't think of any more right now. > > I think that it might be better to fix it by doing this: > > > > 1. ensure async IO submission always has b_lru_ref set, and > > if it isn't, set it to 1. This ensures the buffer will be > > added to the LRU on completion if it isn't already there. > > > > See above. I'm not following why this is necessary (if it is, it seems > indicative of a bug). > > > 2. keep a count of async buffer IO in progress. A per-cpu > > counter in the buftarg will be fine for this. Increment in > > xfs_buf_submit(), decrement in the xfs_buf_rele() call from > > xfs_buf_iodone() once we've determined if the buffer needs > > adding to the LRU or not. > > > > 3. make xfs_wait_buftarg() wait until the async IO count > > goes to zero before it gives up trying to release buffers on > > the LRU. > > > > This is along the lines of what I was thinking wrt to a list (explicit > I/O tracking one way or another). The count is more simple and does > cover the arbitrary read/write case, but is still more code and seems > slightly duplicative to me because in most cases the LRU wait already > handles this. Sure, but adding a list means you need global locks and when you have lots of concurrent readahead going on that will be a problem. readahead is supposed to have minimal overhead, so anything that adds submission serialisation is not the best idea... The counter has almost no overhead for the async IO case, read or write, and that's all we need to allow the IO to complete safely during unmount. > I'm also not totally sure we need to handle the write > case. Are we susceptible to this issue anywhere that isn't already > protected by the sb write protection mechanism, for example? We can do metadata buffer writes outside the superblock write protection context. A good example of that is log recovery on read-only filesystems.... > OTOH, explicit tracking might provide a more generic way to deal with > uncached buffers as opposed to lock cycling. Well, only if those uncached buffers are using async IO.... Cheers, Dave. -- Dave Chinner david@fromorbit.com From andrewho@animezone.org Thu Jun 30 23:44:32 2016 Return-Path: <andrewho@animezone.org> X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on oss.sgi.com X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=MIME_QP_LONG_LINE, T_DKIM_INVALID autolearn=ham version=3.3.1 X-Original-To: xfs@oss.sgi.com Delivered-To: xfs@oss.sgi.com Received: from relay.sgi.com (relay1.corp.sgi.com [137.38.102.111]) by oss.sgi.com (Postfix) with ESMTP id 640617CA1 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 23:44:32 -0500 (CDT) Received: from cuda.sgi.com (cuda3.sgi.com [192.48.176.15]) by relay1.corp.sgi.com (Postfix) with ESMTP id 244508F8040 for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 21:44:32 -0700 (PDT) X-ASG-Debug-ID: 1467348268-04cb6c063f2e8410001-NocioJ Received: from nm17-vm5.access.bullet.mail.gq1.yahoo.com (nm17-vm5.access.bullet.mail.gq1.yahoo.com [216.39.63.135]) by cuda.sgi.com with ESMTP id eVhqNHrquKNn5GJu (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NO) for <xfs@oss.sgi.com>; Thu, 30 Jun 2016 21:44:29 -0700 (PDT) X-Barracuda-Envelope-From: andrewho@animezone.org X-Barracuda-Effective-Source-IP: nm17-vm5.access.bullet.mail.gq1.yahoo.com[216.39.63.135] X-Barracuda-Apparent-Source-IP: 216.39.63.135 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1467348268; bh=5D3YzdLeCkeLZPKcXT+zTebTlfHDehbU9Af8M7IxSrc=; h=References:In-Reply-To:Cc:From:Subject:Date:To:From:Subject; b=FT2EFV4kqJ134MfQlYgso6hSukhaegFqsqyT6v1mz1fcOZw5NE00JBXqNkBECXvcFku0NbhCvxp2T+PbczIcegZz73DF/P1N9r2ezOrW3VjyDLYVhgQAwQvwk+sp8w3O1y+PXECUmxr53/Rw4HUEnVQzoSX2G597QtgStpiwIYjDkRiiTnfxl/jK3wVjH0MOvkxGKXX4K0vVXvWjHPQdHx4faWvyS/EvLXW7QidzcRaTsKbfRxOB0VtBmeW82abaVCzjzUmB4q42t3SZqR8w6LOt+RKQvb5Y9vUIRCC+0rN6XcdY1N6HlWH4oi6RuoyWDvWxVmzV7pM+PI60tfg/JQ== Received: from [216.39.60.171] by nm17.access.bullet.mail.gq1.yahoo.com with NNFMP; 01 Jul 2016 04:44:28 -0000 Received: from [98.138.104.96] by tm7.access.bullet.mail.gq1.yahoo.com with NNFMP; 01 Jul 2016 04:44:28 -0000 Received: from [127.0.0.1] by smtp116.sbc.mail.ne1.yahoo.com with NNFMP; 01 Jul 2016 04:44:27 -0000 X-Yahoo-Newman-Id: 937809.22653.bm@smtp116.sbc.mail.ne1.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: D0zSRVAVM1mRpk2gmNgRFl31Ep_oxVY179HDAqpv.0Jtkc5 784RSP_Kq9bGhOQqiB4srn9dDjiIxC_NfKPFaXDJwkSz77F6zryoAZ29pv0S qC67kG2JlO.JGyWg3IATh0wWt6icVUrqBXrTnhIHQVIes95oMVOVnsfE9GnD hm1SwbiprYNIynTqOKP_uRKK9qEepPSw3_ML.Dl52gLTxL7tehWdsjVGm3eo sVBrI5tGAvgQYunLe3XhVgIs7MviIJw_AFG_zuVc65bCX31zaufPfc79n.A9 o3P5VeNWZiMVr0tk71vHHPz1D0q5SD8r3wSmEtGVsUPGBuewsu1vYAevyuOY 44gCXbGqwHBPMoAeE8m5RAQGQ6azgGezFrF_h1uitcIEFJNZF_W59GISKxWB GIAAxUENsUg2AXkzIaKo8BQMDIBdOXAKoTFeGUhSBmIdZ4vZOl9Kk0b0qAHu pJBr94pIah_xx8fnOHVMM9S3kh2tz_YbTNVZbWRKL8kbBVQoB_cVrkH8abRp GiXbtMsZjwp90EtuFzSlGOIHipZ6zwgtdllawbhf76GYfCt83KWZl6I9FCA- - X-Yahoo-SMTP: P1NUfv.swBA7SNJnRSdqBmzyjrss6o3q3TdA3Q-- References: <SN1PR05MB231785E5196A5D31D0D833EACC230@SN1PR05MB2317.namprd05.prod.outlook.com> <SN1PR05MB23175D5BF190CCC3F22E2EB0CC240@SN1PR05MB2317.namprd05.prod.outlook.com> <4d9d00ef-82d5-a658-e88c-ba75fb7a6023@sandeen.net> <SN1PR05MB2317E464B2CFB5A06CC4B66BCC240@SN1PR05MB2317.namprd05.prod.outlook.com> <dc20d8ae-d57f-53f1-72b8-d623529c695b@sandeen.net> <20160630220737.GS12670@dastard> Mime-Version: 1.0 (1.0) In-Reply-To: <20160630220737.GS12670@dastard> Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable Message-Id: <BFF5CB1A-BA65-4212-9607-2F25F427433B@animezone.org> Cc: Eric Sandeen <sandeen@sandeen.net>, xfs@oss.sgi.com X-Mailer: iPad Mail (13F69) From: Andrew Ho <andrewho@animezone.org> Subject: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) Date: Fri, 1 Jul 2016 00:44:26 -0400 X-ASG-Orig-Subj: Re: Question: Old Irix tape backup. Recovery on Linux (xfsdump/xfsrestore) To: Dave Chinner <david@fromorbit.com> X-Barracuda-Connect: nm17-vm5.access.bullet.mail.gq1.yahoo.com[216.39.63.135] X-Barracuda-Start-Time: 1467348269 X-Barracuda-Encrypted: ECDHE-RSA-AES128-GCM-SHA256 X-Barracuda-URL: https://192.48.176.15:443/cgi-mod/mark.cgi X-Barracuda-Scan-Msg-Size: 2928 X-Virus-Scanned: by bsmtpd at sgi.com X-Barracuda-BRTS-Status: 1 X-Barracuda-Spam-Score: 0.00 X-Barracuda-Spam-Status: No, SCORE=0.00 using per-user scores of TAG_LEVEL=1000.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=2.7 tests=BSF_SC0_MISMATCH_TO, DKIM_SIGNED, DKIM_VERIFIED, MIME_QP_LONG_LINE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.30915 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 BSF_SC0_MISMATCH_TO Envelope rcpt doesn't match header -0.00 DKIM_VERIFIED Domain Keys Identified Mail: signature passes verification 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.00 MIME_QP_LONG_LINE RAW: Quoted-printable line longer than 76 chars I did restore the irix tape on Linux by using the command "tar". tar xv is f= or restore. If the tape was backup by a propriety backup software on SGI Irix, it is dif= ficult to restore on Linux. Andrew Pressure creates diamond. > On Jun 30, 2016, at 6:07 PM, Dave Chinner <david@fromorbit.com> wrote: >=20 >> On Thu, Jun 30, 2016 at 12:04:07PM -0500, Eric Sandeen wrote: >>=20 >>=20 >>> On 6/30/16 11:59 AM, Anthony l wrote: >>> I don't think this is a multi tape dump. But then again i don't know for= sure. I recently got a job and this is my first 'project'. I have about 10 t= apes each are labeled a month and a year, so I don't think they are multi ta= pe because they span like 3 years 2004-2007 . Although for the current tape I= am working on right now if I select 1 skip, I'll get to another back up lab= eled "incremental backup 1" or something similar. Using the verbosity output= here is what I got. (also using interactive restore). I went ahead and spec= ified byte size 4096. Through earlier test using the dd command I determined= that was the correct size. Ill post one without byte size specified too. I j= ust saw it in that post and thought it might help. >>>=20 >>> Here is the output with verbosity. >>>=20 >>> http://pastebin.com/Nd6BqNc5 >>>=20 >>> The out is the same with or without -b 4096. >>>=20 >>> http://pastebin.com/0dxbCvyc (no -b) >>=20 >>=20 >> interactively restore from this dump? >> 1: skip >> 2: interactively restore >> (default) >> ->2 >> ++++=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D++++ >> missing some stuff------ >>=20 >> ^^^ is that your comment, or actual output? >>=20 >> Looks like it eventually encountered a short read: >>=20 >> xfsrestore: drive op: read: wanted 131072 (0x20000) >> xfsrestore: tape op: reading 245760 bytes >> xfsrestore: tape op read of 245760 bytes short: nread =3D=3D 4096 >> xfsrestore: tape op: get status >> xfsrestore: tape status =3D wprot onl >> xfsrestore: short read record 1 (nread =3D=3D 4096) >> xfsrestore: drive op read returning error rval=3D1 >>=20 >> in dmesg, is there any sort of IO error from the tape? >=20 > So xfs_reatore is wanting to find the session inventory in that > last media file, and it would appear that it isn't there or shorter > than expected. A tape problem, perhaps? Have you tried running > xfs_restore using the minimal tape protocol (-m)? >=20 > Another option is to try to restore the dump files from tape to a > local file on disk and see if that can be parsed instead. >=20 > The other thing you might want to do is upgrade xfsdump to the > latest version - you're running 3.1.1 and the current version is > 3.1.6. I doubt it will change the behaviour, but at least it will > give us something to work from... >=20 > Cheers, >=20 > Dave. > --=20 > Dave Chinner > david@fromorbit.com >=20 > _______________________________________________ > xfs mailing list > xfs@oss.sgi.com > http://oss.sgi.com/mailman/listinfo/xfs
       


30 =D0=B8=D1=8E=D0=BD=D1=8F = =E2=80=93 1 =D0=B8=D1=8E=D0=BB=D1=8F  |  =D0=B3. = =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D0=B0=20 | = =D0=90=D1=80=D1=82=D0=B8=D0=BA=D1=83=D0=BB:=20 433

=D0=90=D0=BA=D0=BA=D1=80=D0=B5=D0=B4=D0=B8=D1=82=D0=BE=D0=B2= =D0=B0=D0=BD=D0=BD=D1=8B=D0=B9 = =D0=A3=D1=87=D0=B5=D0=B1=D0=BD=D1=8B=D0=B9 = =D1=86=D0=B5=D0=BD=D1=82=D1=80 = =D0=BF=D1=80=D0=B8=D0=B3=D0=BB=D0=B0=D1=88=D0=B0=D0=B5=D1=82 = =D0=BD=D0=B0 =D0=BE=D0=B1=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B5 =D0=BF=D0=BE = =D1=82=D0=B5=D0=BC=D0=B5:

=D0=9A=D0=B0=D0=B4=D1=80=D0=BE=D0=B2=D0=BE=D0=B5=20 = =D0=B4=D0=B5=D0=BB=D0=BE=D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D1= =81=D1=82=D0=B2=D0=BE:
=D0=B1=D0=B5=D0=B7 = =D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA =D0=B8 = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D1=80=D0=BE=D0=BA
 

=D0=A7=D0=B0=D1=81=D1=8B=20 =D0=B7=D0=B0=D0=BD=D1=8F=D1=82=D0=B8=D0=B9: c 10:00 =D0=B4=D0=BE=20 17:30

=D0=9C=D0=B5=D1=81=D1=82=D0=BE = =D0=BF=D1=80=D0=BE=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F: = =D1=83=D0=BB. = =D0=91=D0=B0=D1=83=D0=BC=D0=B0=D0=BD=D1=81=D0=BA=D0=B0=D1=8F, =D0=B4.6, = =D0=B1=D0=B8=D0=B7=D0=BD=D0=B5=D1=81 =D1=86=D0=B5=D0=BD=D1=82=D1=80=20 "=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80=D0=B8=D1=8F = =D0=9F=D0=BB=D0=B0=D0=B7=D0=B0".


=D0=9F=D0=BE=D0=BB=D0=BD=D0=B0=D1=8F = =D0=BF=D1=80=D0=BE=D0=B3=D1=80=D0=B0=D0=BC=D0=BC=D0=B0 =D0=B8=20 = =D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D0= =B0=D1=8F =D0=B8=D0=BD=D1=84=D0=BE=D1=80=D0=BC=D0=B0=D1=86=D0=B8=D1=8F = =D0=BF=D0=BE =D1=82=D0=B5=D0=BB.:

8 =D0=BA=D0=BE=D0=B4 = =D0=B3=D0=BE=D1=80=D0=BE=D0=B4=D0=B0=20 =D0=9C=D0=BE=D1=81=D0=BA=D0=B2=D1=8B  (495) =D1=82=D0=B5=D0=BB.:=20 961 = -=20 00=20 -=20 38=20 = (=D0=BC=D0=BD=D0=BE=D0=B3=D0=BE=D0=BA=D0=B0=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD= =D1=8B=D0=B9)

* *=20 *

         

 

=D0=A1=D0=BE=D0=B4=D0=B5=D1=80=D0=B6=D0=B0=D0=BD=D0=B8=D0=B5= =20 =D0=BF=D1=80=D0=BE=D0=B3=D1=80=D0=B0=D0=BC=D0=BC=D1=8B:

=D0=9B=D0=BE=D0=BA=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5= =D0=BD=D0=BE=D1=80=D0=BC=D0=B0=D1=82=D0=B8=D0=B2=D0=BD=D1=8B=D0=B5 = =D0=B0=D0=BA=D1=82=D1=8B=20 (=D0=9B=D0=9D=D0=90): =D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA = =D1=80=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8 =D0=B8 = =D0=B2=D0=BD=D0=B5=D0=B4=D1=80=D0=B5=D0=BD=D0=B8=D1=8F. =
    =20 = =D0=9E=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5 = =D0=9B=D0=9D=D0=90, =D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA = =D1=80=D0=B0=D0=B7=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8 =D0=B8 = =D0=B2=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B8=D1=8F = =D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9: = =D1=88=D1=82=D0=B0=D1=82=D0=BD=D0=BE=D0=B5=20 =D1=80=D0=B0=D1=81=D0=BF=D0=B8=D1=81=D0=B0=D0=BD=D0=B8=D0=B5, =
     =D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D0=BB=D0=B0 = =D0=B2=D0=BD=D1=83=D1=82=D1=80=D0=B5=D0=BD=D0=BD=D0=B5=D0=B3=D0=BE = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE=20 =D1=80=D0=B0=D1=81=D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BA=D0=B0, = =D0=BF=D0=BE=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5 =D0=BE = =D0=B7=D0=B0=D1=89=D0=B8=D1=82=D0=B5 = =D0=BF=D0=B5=D1=80=D1=81=D0=BE=D0=BD=D0=B0=D0=BB=D1=8C=D0=BD=D1=8B=D1=85 = =D0=B4=D0=B0=D0=BD=D0=BD=D1=8B=D1=85,=20
     =D0=B3=D1=80=D0=B0=D1=84=D0=B8=D0=BA = =D0=BE=D1=82=D0=BF=D1=83=D1=81=D0=BA=D0=BE=D0=B2.
   &n= bsp;=20 = =D0=9D=D0=B5=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1= =8B=D0=B5 =D0=9B=D0=9D=D0=90: = =D0=B8=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=86=D0=B8=D1=8F = =D0=BF=D0=BE =D0=BA=D0=B0=D0=B4=D1=80=D0=BE=D0=B2=D0=BE=D0=BC=D1=83 = =D0=B4=D0=B5=D0=BB=D0=BE=D0=BF=D1=80=D0=BE=D0=B8=D0=B7=D0=B2=D0=BE=D0=B4=D1= =81=D1=82=D0=B2=D1=83, = =D0=BF=D0=BE=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D0=B5 =D0=BE=20
     = =D0=BF=D1=80=D0=B5=D0=BC=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B8,= =D0=B4=D0=BE=D0=BB=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D0=BD=D1=8B=D0=B5=20 = =D0=B8=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=86=D0=B8=D0=B8.
=D0=94= =D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80=D1=8B =D0=B2 = =D0=BA=D0=B0=D0=B4=D1=80=D0=BE=D0=B2=D0=BE=D0=B9 = =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B5.=20
     = =D0=A2=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D0=BE=D0=B9 = =D0=B4=D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80. = =D0=A1=D1=80=D0=BE=D1=87=D0=BD=D1=8B=D0=B9 =D0=B8 = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D0=BE=D0=B9=20 =D0=B4=D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80, = =D0=B7=D0=B0=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=BD=D1=8B=D0=B9 = =D0=BD=D0=B0 = =D0=BD=D0=B5=D0=BE=D0=BF=D1=80=D0=B5=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D0=BD=D1= =8B=D0=B9 =D1=81=D1=80=D0=BE=D0=BA.
    =20 =D0=A3=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1=8F = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D0=BE=D0=B3=D0=BE = =D0=B4=D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80=D0=B0: = =D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5 = =D0=B8=20 = =D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1= =8B=D0=B5.
     = =D0=93=D1=80=D0=B0=D0=B6=D0=B4=D0=B0=D0=BD=D1=81=D0=BA=D0=BE-=D0=BF=D1=80= =D0=B0=D0=B2=D0=BE=D0=B2=D1=8B=D0=B5 = =D0=B4=D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80=D1=8B=20 (=D0=93=D0=9F=D0=94). =D0=9E=D1=82=D0=BB=D0=B8=D1=87=D0=B8=D1=8F = =D0=93=D0=9F=D0=94 =D0=BE=D1=82 = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D1=8B=D1=85 = =D0=B4=D0=BE=D0=B3=D0=BE=D0=B2=D0=BE=D1=80=D0=BE=D0=B2.
=D0=A2=D1=80= =D1=83=D0=B4=D0=BE=D0=B2=D0=B0=D1=8F = =D0=BA=D0=BD=D0=B8=D0=B6=D0=BA=D0=B0.=20
     = =D0=A2=D1=80=D0=B5=D0=B1=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F =D0=BA = =D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8E = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D1=8B=D1=85 = =D0=BA=D0=BD=D0=B8=D0=B6=D0=B5=D0=BA.=20 =D0=98=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=86=D0=B8=D1=8F = =D0=BF=D0=BE = =D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8E = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D0=BE=D0=B9 = =D0=BA=D0=BD=D0=B8=D0=B6=D0=BA=D0=B8.
    =20 =D0=9E=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5 = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D0=BE=D0=B9 = =D0=BA=D0=BD=D0=B8=D0=B6=D0=BA=D0=B8 = =D0=B2=D0=BF=D0=B5=D1=80=D0=B2=D1=8B=D0=B5, = =D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D0=B5 = =D1=82=D0=B8=D1=82=D1=83=D0=BB=D1=8C=D0=BD=D0=BE=D0=B3=D0=BE=20 =D0=BB=D0=B8=D1=81=D1=82=D0=B0.
     = =D0=92=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=B7=D0=B0=D0=BF=D0=B8=D1=81=D0=B8 =D0=BE = =D0=BF=D1=80=D0=B8=D0=B5=D0=BC=D0=B5, = =D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=D0=B5,=20 =D1=83=D0=B2=D0=BE=D0=BB=D1=8C=D0=BD=D0=B5=D0=BD=D0=B8=D0=B8, = =D0=BF=D0=BE=D0=BE=D1=89=D1=80=D0=B5=D0=BD=D0=B8=D0=B8.
  &n= bsp;  = =D0=9E=D1=81=D0=BE=D0=B1=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D0=B7=D0=B0=D0=BF=D0=BE=D0=BB=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20 =D0=B2=D0=BA=D0=BB=D0=B0=D0=B4=D1=8B=D1=88=D0=B0 =D0=B2 = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D1=83=D1=8E = =D0=BA=D0=BD=D0=B8=D0=B6=D0=BA=D1=83.
     = =D0=A3=D1=87=D0=B5=D1=82 =D0=B8 = =D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F=20 =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D1=8B=D1=85 = =D0=BA=D0=BD=D0=B8=D0=B6=D0=B5=D0=BA.
     = =D0=92=D0=BD=D0=B5=D1=81=D0=B5=D0=BD=D0=B8=D0=B5 = =D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD=D0=B8=D0=B9 =D0=B2 = =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D1=83=D1=8E=20 =D0=BA=D0=BD=D0=B8=D0=B6=D0=BA=D1=83.
     = =D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=B2 =D1=82=D1=80=D1=83=D0=B4=D0=BE=D0=B2=D0=BE=D0=B9=20 = =D0=BA=D0=BD=D0=B8=D0=B6=D0=BA=D0=B5.
=D0=96=D1=83=D1=80=D0=BD=D0=B0= =D0=BB=D1=8B = =D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=86=D0=B8=D0=B8. =
    =20 = =D0=9E=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5 = =D0=B8 = =D0=BD=D0=B5=D0=BE=D0=B1=D1=8F=D0=B7=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1= =8B=D0=B5 =D0=B6=D1=83=D1=80=D0=BD=D0=B0=D0=BB=D1=8B = =D1=80=D0=B5=D0=B3=D0=B8=D1=81=D1=82=D1=80=D0=B0=D1=86=D0=B8=D0=B8, = =D0=BF=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA=20 =D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F.
=D0=9F=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA = =D1=85=D1=80=D0=B0=D0=BD=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BA=D0=B0=D0=B4=D1=80=D0=BE=D0=B2=D0=BE=D0=B9=20 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8.=
=D0=9F=D0=BE=D1=88=D0=B0=D0=B3=D0=BE=D0=B2=D1=8B=D0=B5 = =D0=BF=D1=80=D0=BE=D1=86=D0=B5=D0=B4=D1=83=D1=80=D1=8B = =D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BA=D0=B0=D0=B4=D1=80=D0=BE=D0=B2=D0=BE=D0=B9 = =D0=B4=D0=BE=D0=BA=D1=83=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=86=D0=B8=D0=B8.= =20

     =D0=9F=D1=80=D0=B8=D0=B5=D0=BC = =D0=BD=D0=B0 =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D1=83: = =D0=BF=D0=BE=D1=88=D0=B0=D0=B3=D0=BE=D0=B2=D0=B0=D1=8F = =D0=BF=D1=80=D0=BE=D1=86=D0=B5=D0=B4=D1=83=D1=80=D0=B0=20 = =D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F.
 &n= bsp;   =D0=9F=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4 = =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BD=D0=B8=D0=BA=D0=B0: = =D0=BF=D0=BE=D1=88=D0=B0=D0=B3=D0=BE=D0=B2=D0=B0=D1=8F=20 =D0=BF=D1=80=D0=BE=D1=86=D0=B5=D0=B4=D1=83=D1=80=D0=B0 = =D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F. = =D0=92=D0=B8=D0=B4=D1=8B = =D0=BF=D0=B5=D1=80=D0=B5=D0=B2=D0=BE=D0=B4=D0=BE=D0=B2. = =D0=9F=D0=B5=D1=80=D0=B5=D0=BC=D0=B5=D1=89=D0=B5=D0=BD=D0=B8=D0=B5.
=D0=9E=D1=82=D0=BF=D1=83=D1=81=D0=BA.=20
     = =D0=9E=D0=BF=D0=BB=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=B5=D0=BC=D1=8B=D0=B5 = =D0=B8 = =D0=BD=D0=B5=D0=BE=D0=BF=D0=BB=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=B5=D0=BC=D1= =8B=D0=B5 =D0=BE=D1=82=D0=BF=D1=83=D1=81=D0=BA=D0=B0,=20 = =D0=B4=D0=BE=D0=BF=D0=BE=D0=BB=D0=BD=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0=BD=D1= =8B=D0=B5 =D0=BE=D1=82=D0=BF=D1=83=D1=81=D0=BA=D0=B0: = =D0=BF=D1=80=D0=BE=D0=B4=D0=BE=D0=BB=D0=B6=D0=B8=D1=82=D0=B5=D0=BB=D1=8C=D0= =BD=D0=BE=D1=81=D1=82=D1=8C,
    =20 =D1=83=D1=81=D0=BB=D0=BE=D0=B2=D0=B8=D1=8F = =D0=BF=D1=80=D0=B5=D0=B4=D0=BE=D1=81=D1=82=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0= =B8=D1=8F = =D0=BE=D1=82=D0=BF=D1=83=D1=81=D0=BA=D0=BE=D0=B2.
   &n= bsp; =D0=9F=D0=BE=D1=80=D1=8F=D0=B4=D0=BE=D0=BA=20 =D0=BF=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D0=BA=D0=B8 = =D0=B3=D1=80=D0=B0=D1=84=D0=B8=D0=BA=D0=B0 = =D0=BE=D1=82=D0=BF=D1=83=D1=81=D0=BA=D0=BE=D0=B2: =D1=87=D1=82=D0=BE = =D0=BD=D0=B5=D0=BE=D0=B1=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=D0=BE = =D1=83=D1=87=D0=B5=D1=81=D1=82=D1=8C. = =D0=9F=D0=B5=D1=80=D0=B8=D0=BE=D0=B4=D1=8B, = =D0=B2=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D0=B5=D0=BC=D1=8B=D0=B5 =D0=B8=20 =D0=BD=D0=B5
     = =D0=B2=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=D0=B5=D0=BC=D1=8B=D0=B5 = =D0=B4=D0=BB=D1=8F =D0=BF=D0=BE=D0=B4=D1=81=D1=87=D0=B5=D1=82=D0=B0 = =D1=81=D1=82=D0=B0=D0=B6=D0=B0, = =D0=B4=D0=B0=D1=8E=D1=89=D0=B5=D0=B3=D0=BE=20 =D0=BF=D1=80=D0=B0=D0=B2=D0=BE =D0=BD=D0=B0 = =D0=BE=D1=82=D0=BF=D1=83=D1=81=D0=BA.
     = =D0=9F=D0=BE=D1=88=D0=B0=D0=B3=D0=BE=D0=B2=D0=B0=D1=8F = =D0=BF=D1=80=D0=BE=D1=86=D0=B5=D0=B4=D1=83=D1=80=D0=B0=20 =D0=BE=D1=84=D0=BE=D1=80=D0=BC=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F = =D0=BE=D1=82=D0=BF=D1=83=D1=81=D0=BA=D0=B0.
=D0=9F=D0=BE=D0=BE=D1=89=D1=80=D0=B5=D0=BD=D0=B8=D0=B5= =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BD=D0=B8=D0=BA=D0=BE=D0=B2.=20 =D0=92=D0=B8=D0=B4=D1=8B = =D0=BF=D0=BE=D0=BE=D1=89=D1=80=D0=B5=D0=BD=D0=B8=D0=B9.
=D0=94=D0=B8=D1= =81=D1=86=D0=B8=D0=BF=D0=BB=D0=B8=D0=BD=D0=B0=D1=80=D0=BD=D1=8B=D0=B5 = =D0=B2=D0=B7=D1=8B=D1=81=D0=BA=D0=B0=D0=BD=D0=B8=D1=8F.=20

     =D0=92=D0=B8=D0=B4=D1=8B = =D0=B2=D0=B7=D1=8B=D1=81=D0=BA=D0=B0=D0=BD=D0=B8=D0=B9. = =D0=9F=D1=80=D0=BE=D1=86=D0=B5=D0=B4=D1=83=D1=80=D0=B0 = =D0=BD=D0=B0=D0=BB=D0=BE=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F=20 = =D0=B4=D0=B8=D1=81=D1=86=D0=B8=D0=BF=D0=BB=D0=B8=D0=BD=D0=B0=D1=80=D0=BD=D0= =BE=D0=B3=D0=BE =D0=B2=D0=B7=D1=8B=D1=81=D0=BA=D0=B0=D0=BD=D0=B8=D1=8F. = =D0=A1=D0=BD=D1=8F=D1=82=D0=B8=D0=B5
    =20 = =D0=B4=D0=B8=D1=81=D1=86=D0=B8=D0=BF=D0=BB=D0=B8=D0=BD=D0=B0=D1=80=D0=BD=D0= =BE=D0=B3=D0=BE = =D0=B2=D0=B7=D1=8B=D1=81=D0=BA=D0=B0=D0=BD=D0=B8=D1=8F.
=D0=9A=D0=BE=D0=BC=D0=B0=D0=BD=D0=B4=D0=B8=D1=80=D0=BE= =D0=B2=D0=BA=D0=B0.=20 =D0=9D=D0=BE=D0=B2=D0=BE=D0=B5 =D0=B2 = =D0=B7=D0=B0=D0=BA=D0=BE=D0=BD=D0=BE=D0=B4=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=D1= =81=D1=82=D0=B2=D0=B5.
=D0=A3=D0=B2=D0=BE=D0=BB=D1=8C=D0=BD=D0=B5=D0=BD= =D0=B8=D0=B5.

    =20 =D0=9E=D1=81=D0=BE=D0=B1=D0=B5=D0=BD=D0=BD=D0=BE=D1=81=D1=82=D0=B8 = =D1=80=D0=B0=D1=81=D1=82=D0=BE=D1=80=D0=B6=D0=B5=D0=BD=D0=B8=D1=8F = =D0=A2=D0=94 =D0=BF=D0=BE = =D0=B8=D0=BD=D0=B8=D1=86=D0=B8=D0=B0=D1=82=D0=B8=D0=B2=D0=B5 = =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BD=D0=B8=D0=BA=D0=B0 =D0=B8 = =D0=BF=D0=BE = =D0=B8=D0=BD=D0=B8=D1=86=D0=B8=D0=B0=D1=82=D0=B8=D0=B2=D0=B5=20 = =D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BE=D0=B4=D0=B0=D1=82=D0=B5=D0=BB=D1=8F.=
 


=D0=A3=D1=87=D0=B0=D1=81=D1=82=D0=B8=D0=B5
: = 22 800 =D1=80=D1=83=D0=B1.
=D0=92 = =D1=81=D1=82=D0=BE=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C = =D0=B2=D1=85=D0=BE=D0=B4=D0=B8=D1=82 = =D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=B9 = =D0=BC=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=B0=D0=BB, = =D0=BE=D0=B1=D0=B5=D0=B4=D1=8B, = =D0=BA=D0=BE=D1=84=D0=B5-=D0=BF=D0=B0=D1=83=D0=B7=D1=8B,=20 = =D1=81=D0=B5=D1=80=D1=82=D0=B8=D1=84=D0=B8=D0=BA=D0=B0=D1=82.
 

 =20